chatlab-cli 0.28.1 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/{chat-command-ISJ2DC7R.mjs → chat-command-JKG3FY5B.mjs} +8 -5
  2. package/dist/{chat-command-ISJ2DC7R.mjs.map → chat-command-JKG3FY5B.mjs.map} +1 -1
  3. package/dist/chunk-2MZ6G4AC.mjs +1339 -0
  4. package/dist/chunk-2MZ6G4AC.mjs.map +1 -0
  5. package/dist/{chunk-NJB2NNB2.mjs → chunk-6FPEP2ZX.mjs} +2 -2
  6. package/dist/{chunk-YBS3YQB6.mjs → chunk-7RW4CQAO.mjs} +31 -57
  7. package/dist/chunk-7RW4CQAO.mjs.map +1 -0
  8. package/dist/{chunk-GHTGFM6O.mjs → chunk-ARZM6HBX.mjs} +14 -12
  9. package/dist/{chunk-GHTGFM6O.mjs.map → chunk-ARZM6HBX.mjs.map} +1 -1
  10. package/dist/{chunk-3QBVO4J7.mjs → chunk-CIB23U32.mjs} +2 -2
  11. package/dist/chunk-D4WTE7LV.mjs +526 -0
  12. package/dist/chunk-D4WTE7LV.mjs.map +1 -0
  13. package/dist/{chunk-T7IETWHN.mjs → chunk-I35WHWA6.mjs} +5 -3
  14. package/dist/{chunk-T7IETWHN.mjs.map → chunk-I35WHWA6.mjs.map} +1 -1
  15. package/dist/{chunk-AB6TAXTQ.mjs → chunk-KL2NGIMQ.mjs} +171 -47
  16. package/dist/chunk-KL2NGIMQ.mjs.map +1 -0
  17. package/dist/{chunk-ZVDOFWL7.mjs → chunk-QQK7MLCR.mjs} +3926 -10867
  18. package/dist/chunk-QQK7MLCR.mjs.map +1 -0
  19. package/dist/{chunk-ERAAWLEF.mjs → chunk-SKUG5XVD.mjs} +10 -8
  20. package/dist/{chunk-ERAAWLEF.mjs.map → chunk-SKUG5XVD.mjs.map} +1 -1
  21. package/dist/chunk-WPI6YSAR.mjs +8813 -0
  22. package/dist/chunk-WPI6YSAR.mjs.map +1 -0
  23. package/dist/cli.mjs +7 -4
  24. package/dist/contacts-worker.mjs +48 -0
  25. package/dist/contacts-worker.mjs.map +1 -0
  26. package/dist/{http-MBILV37U.mjs → http-5E7ARYFW.mjs} +11 -8
  27. package/dist/{import-EYV3GXHE.mjs → import-3KG6VK6O.mjs} +7 -4
  28. package/dist/index.mjs +11 -8
  29. package/dist/{mcp-H55AEXU5.mjs → mcp-JBI4CUQT.mjs} +8 -5
  30. package/dist/{mcp-H55AEXU5.mjs.map → mcp-JBI4CUQT.mjs.map} +1 -1
  31. package/dist/people-relationships-worker.mjs +48 -0
  32. package/dist/people-relationships-worker.mjs.map +1 -0
  33. package/dist/semantic-index-worker.mjs +1 -1
  34. package/dist/{src-36ZIR65K.mjs → src-UTBQAOJ3.mjs} +62 -44
  35. package/dist/{stream-import-YZMZ56B5.mjs → stream-import-7HZ4IRYJ.mjs} +7 -4
  36. package/dist/{worker-runtime-YDYS2C6T.mjs → worker-runtime-ALS4MR2A.mjs} +7 -3
  37. package/dist/{worker-runtime-YDYS2C6T.mjs.map → worker-runtime-ALS4MR2A.mjs.map} +1 -1
  38. package/dist-web/assets/BufferResource-MsqP5sq3.js +185 -0
  39. package/dist-web/assets/CanvasRenderer-BKCvcc2p.js +1 -0
  40. package/dist-web/assets/DebugToolsPanel-D_lFIW6j.css +1 -0
  41. package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-HGJb0Et1.js +110 -0
  42. package/dist-web/assets/{EChartWordcloud-B_YisOW5.js → EChartWordcloud-Clg60FMo.js} +1 -1
  43. package/dist-web/assets/Filter-wRJtdXx9.js +1 -0
  44. package/dist-web/assets/MessageExportModal-BCrMf5Kw.js +1 -0
  45. package/dist-web/assets/PageHeader-Bbn87QZS.css +1 -0
  46. package/dist-web/assets/PageHeader-C_yw54le.js +1 -0
  47. package/dist-web/assets/RelationshipGalaxyCanvas-DTzJq7q7.js +244 -0
  48. package/dist-web/assets/RelationshipGalaxyThreeCanvas-BluPHjCR.css +1 -0
  49. package/dist-web/assets/RelationshipGalaxyThreeCanvas-DIE-0_iM.js +4108 -0
  50. package/dist-web/assets/RenderTargetSystem-BSAQFamI.js +184 -0
  51. package/dist-web/assets/WebGLRenderer-lfzmCZNT.js +156 -0
  52. package/dist-web/assets/WebGPURenderer-BnEdfdr_.js +41 -0
  53. package/dist-web/assets/browserAll-gRNfDyPu.js +14 -0
  54. package/dist-web/assets/{electron-DWDCqx_d.js → electron-BHaEaaZP.js} +1 -1
  55. package/dist-web/assets/{fetch-29ZBtGV0.js → fetch-BW3aO7PS.js} +1 -1
  56. package/dist-web/assets/fetch-BwF5hNuF.js +1 -0
  57. package/dist-web/assets/{fetch-Bh1fo3Df.js → fetch-C1fI_KOX.js} +1 -1
  58. package/dist-web/assets/{fetch-DyD8wDhb.js → fetch-CBZbgZqk.js} +1 -1
  59. package/dist-web/assets/{fetch-C3yhWO2S.js → fetch-CFRoSIAn.js} +1 -1
  60. package/dist-web/assets/fetch-CN91TIwV.js +1 -0
  61. package/dist-web/assets/{fetch-BcxrU2mr.js → fetch-CQt-gb-f.js} +1 -1
  62. package/dist-web/assets/{fetch-TCeykOkO.js → fetch-DPCJ-1l-.js} +1 -1
  63. package/dist-web/assets/{fetch-tIIVdXSv.js → fetch-gMB4wuBd.js} +1 -1
  64. package/dist-web/assets/{fetch-BYczbT4C.js → fetch-mFlEBZyB.js} +1 -1
  65. package/dist-web/assets/index---rXG1hZ.css +1 -0
  66. package/dist-web/assets/index--6C0sK6a.css +1 -0
  67. package/dist-web/assets/index-B6wEGata.js +173 -0
  68. package/dist-web/assets/index-Bg4GGPXv.js +1 -0
  69. package/dist-web/assets/index-BgVbj5qX.js +12 -0
  70. package/dist-web/assets/index-BkoXaBV_.js +64 -0
  71. package/dist-web/assets/index-C56IuV5U.css +1 -0
  72. package/dist-web/assets/index-CLRaKwpT.js +2 -0
  73. package/dist-web/assets/index-Dj1BSD7O.js +1 -0
  74. package/dist-web/assets/index-DosG7LmJ.css +1 -0
  75. package/dist-web/assets/index-DveHdPfK.js +1 -0
  76. package/dist-web/assets/{index-BX3tqfLz.css → index-MBRD3wPd.css} +1 -1
  77. package/dist-web/assets/index-RoDgJcHU.js +2 -0
  78. package/dist-web/assets/{index-fbWrQpgH.js → index-ZdCB7xcf.js} +4 -4
  79. package/dist-web/assets/index-aljYO5ms.js +1 -0
  80. package/dist-web/assets/people-page-header-Mupn-U_b.js +1 -0
  81. package/dist-web/assets/relationship-galaxy-viewport-Cwfa51ER.js +1 -0
  82. package/dist-web/assets/{vendor-echarts-CITQeskI.js → vendor-echarts-hJVnODyU.js} +2 -2
  83. package/dist-web/assets/{vendor-echarts-wordcloud-B1kQMklB.js → vendor-echarts-wordcloud-k5ih2Jl4.js} +1 -1
  84. package/dist-web/assets/{vendor-nuxt-ui-Zy8txNdC.js → vendor-nuxt-ui-Dr2T8_OZ.js} +2 -2
  85. package/dist-web/assets/{vendor-reka-ui-mMvma1EP.js → vendor-reka-ui-CzM4kDQ7.js} +1 -1
  86. package/dist-web/assets/{vendor-zrender-DFl4U2Oe.js → vendor-zrender-5DcYjSZk.js} +1 -1
  87. package/dist-web/assets/{web-H3XLx159.js → web-BakeV58u.js} +1 -1
  88. package/dist-web/assets/webworkerAll-D_6PgURS.js +83 -0
  89. package/dist-web/index.html +4 -4
  90. package/package.json +1 -1
  91. package/dist/chunk-AB6TAXTQ.mjs.map +0 -1
  92. package/dist/chunk-YBS3YQB6.mjs.map +0 -1
  93. package/dist/chunk-ZVDOFWL7.mjs.map +0 -1
  94. package/dist-web/assets/DebugToolsPanel-DFw6_G5V.css +0 -1
  95. package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-Do3x4aL3.js +0 -110
  96. package/dist-web/assets/MessageExportModal-rijqUusq.js +0 -1
  97. package/dist-web/assets/fetch-BAxKmbKF.js +0 -1
  98. package/dist-web/assets/fetch-Da_TBxrX.js +0 -1
  99. package/dist-web/assets/index-BzjLqlW_.js +0 -173
  100. package/dist-web/assets/index-C74qEDFh.js +0 -64
  101. package/dist-web/assets/index-CM6xNPFp.css +0 -1
  102. package/dist-web/assets/index-CgK2LLIF.js +0 -12
  103. package/dist-web/assets/index-CjkOvM3N.js +0 -2
  104. package/dist-web/assets/index-Dno7CADA.js +0 -1
  105. package/dist-web/assets/index-I3SWZjnW.css +0 -1
  106. /package/dist/{chunk-NJB2NNB2.mjs.map → chunk-6FPEP2ZX.mjs.map} +0 -0
  107. /package/dist/{chunk-3QBVO4J7.mjs.map → chunk-CIB23U32.mjs.map} +0 -0
  108. /package/dist/{http-MBILV37U.mjs.map → http-5E7ARYFW.mjs.map} +0 -0
  109. /package/dist/{import-EYV3GXHE.mjs.map → import-3KG6VK6O.mjs.map} +0 -0
  110. /package/dist/{src-36ZIR65K.mjs.map → src-UTBQAOJ3.mjs.map} +0 -0
  111. /package/dist/{stream-import-YZMZ56B5.mjs.map → stream-import-7HZ4IRYJ.mjs.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../packages/node-runtime/src/node-path-provider.ts","../../../packages/node-runtime/src/data-dir-switch.ts","../../../packages/node-runtime/src/jieba-nlp-provider.ts","../../../packages/node-runtime/src/preferences.ts","../../../packages/node-runtime/src/merger/index.ts","../../../packages/node-runtime/src/services/analytics.ts","../../../packages/node-runtime/src/semantic-index/index.ts","../../../packages/node-runtime/src/semantic-index/worker-client.ts","../../../packages/node-runtime/src/semantic-index/worker-thread-transport.ts","../../../packages/node-runtime/src/semantic-index/embedding/index.ts"],"sourcesContent":["/**\n * PathProvider 的 Node.js 独立实现\n *\n * 为 CLI / npm 服务版提供路径管理,不依赖 Electron。\n *\n * 目录分为两类:\n * - 系统数据:固定在 ~/.chatlab/,存放配置、日志、缓存、AI 数据等\n * - 用户数据:可配置位置,存放聊天记录数据库等核心资产\n *\n * 用户数据目录(userDataDir)解析优先级:\n * 1. 构造函数传入的 userDataDir 参数\n * 2. CHATLAB_DATA_DIR 环境变量\n * 3. ~/.chatlab/config.toml → [data] user_data_dir\n * 4. 平台默认路径\n */\n\nimport * as fs from 'fs'\nimport * as os from 'os'\nimport * as path from 'path'\nimport type { PathProvider } from '@openchatlab/core'\nimport { writeConfigField, loadConfig } from '@openchatlab/config'\nimport { migrateFromElectronIfNeeded } from './migrations/electron-data-migration'\nimport { applyPendingNodeDataDirMigration } from './data-dir-switch'\n\nconst SYSTEM_DIR = path.join(os.homedir(), '.chatlab')\n\n/**\n * Set after resolveUserDataDir() detects Electron installation but cannot find databases.\n * CLI should check this and block execution with instructions.\n */\nlet _pendingElectronDataWarning = false\n\nexport function hasPendingElectronDataWarning(): boolean {\n return _pendingElectronDataWarning\n}\n\nexport function applyPendingNodeDataDirMigrationIfNeeded(): { success: boolean; skipped?: boolean; error?: string } {\n if (process.env.CHATLAB_DATA_DIR) return { success: true, skipped: true }\n return applyPendingNodeDataDirMigration(SYSTEM_DIR)\n}\n\nexport class NodePathProvider implements PathProvider {\n private systemDir: string\n private userDataDir: string\n\n constructor(userDataDir?: string) {\n this.systemDir = SYSTEM_DIR\n this.userDataDir = userDataDir || resolveUserDataDir()\n }\n\n getSystemDir(): string {\n return this.systemDir\n }\n\n getUserDataDir(): string {\n return this.userDataDir\n }\n\n getDatabaseDir(): string {\n return path.join(this.userDataDir, 'databases')\n }\n\n getVectorDir(): string {\n return path.join(this.userDataDir, 'vector')\n }\n\n getAiDataDir(): string {\n return path.join(this.systemDir, 'ai')\n }\n\n getSettingsDir(): string {\n return path.join(this.systemDir, 'settings')\n }\n\n getCacheDir(): string {\n return path.join(this.systemDir, 'cache')\n }\n\n getTempDir(): string {\n return path.join(this.systemDir, 'temp')\n }\n\n getLogsDir(): string {\n return path.join(this.systemDir, 'logs')\n }\n\n getDownloadsDir(): string {\n return path.join(os.homedir(), 'Downloads')\n }\n\n /**\n * 确保系统目录和用户数据目录都存在\n */\n ensureAllDirs(): void {\n const dirs = [\n this.systemDir,\n this.userDataDir,\n this.getDatabaseDir(),\n this.getVectorDir(),\n this.getAiDataDir(),\n this.getSettingsDir(),\n this.getCacheDir(),\n this.getTempDir(),\n this.getLogsDir(),\n ]\n for (const dir of dirs) {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n }\n\n const markerPath = path.join(this.userDataDir, '.chatlab')\n if (!fs.existsSync(markerPath)) {\n fs.writeFileSync(markerPath, 'ChatLab Data Directory', 'utf-8')\n }\n }\n}\n\nfunction resolveUserDataDir(): string {\n const envDir = process.env.CHATLAB_DATA_DIR\n if (envDir) {\n return expandHome(envDir)\n }\n\n const config = loadConfig()\n if (config.data.user_data_dir) {\n return expandHome(config.data.user_data_dir)\n }\n\n // First run: check for existing Electron desktop data before using default\n const result = migrateFromElectronIfNeeded(SYSTEM_DIR)\n if (result.migrated && result.userDataDir) {\n return result.userDataDir\n }\n\n const defaultDir = getDefaultNodeUserDataDir()\n\n if (result.electronDetected) {\n // Electron was used but we couldn't find databases — likely a custom data directory.\n // Don't persist default to config.toml so migration retries on next startup.\n _pendingElectronDataWarning = true\n return defaultDir\n }\n\n writeConfigField('data', 'user_data_dir', defaultDir)\n return defaultDir\n}\n\nexport function getDefaultNodeUserDataDir(): string {\n return path.join(os.homedir(), '.chatlab', 'data')\n}\n\nexport function getSystemLogsDir(): string {\n return path.join(SYSTEM_DIR, 'logs')\n}\n\nfunction expandHome(filePath: string): string {\n if (filePath.startsWith('~/') || filePath === '~') {\n return path.join(os.homedir(), filePath.slice(1))\n }\n return filePath\n}\n","import * as fs from 'fs'\nimport * as path from 'path'\nimport { writeConfigField } from '@openchatlab/config'\n\nconst CHATLAB_MARKER_FILE = '.chatlab'\nconst USER_DATA_REQUIRED_DIRS = ['databases']\nconst PENDING_MIGRATION_FILE = 'data-dir-migration.json'\n\nconst DANGEROUS_PATHS = [\n 'C:\\\\Windows',\n 'C:\\\\Program Files',\n 'C:\\\\Program Files (x86)',\n 'C:\\\\ProgramData',\n '/usr',\n '/etc',\n '/bin',\n '/sbin',\n '/lib',\n '/var',\n '/boot',\n '/root',\n '/System',\n '/Library',\n]\n\nexport interface CopyStats {\n copied: number\n skipped: number\n errors: string[]\n}\n\nexport interface PendingDataDirMigration {\n from: string\n to: string\n migrate: boolean\n deleteSourceOnSuccess: boolean\n createdAt: string\n}\n\nexport interface RunPendingDataDirMigrationDeps {\n copyDirMerge?: typeof copyDirMerge\n ensureDir?: (dirPath: string) => void\n writeUserDataDir: (dir: string) => void\n clearPendingMigration: () => void\n markPendingDeleteDir?: (dir: string) => void\n log?: (message: string) => void\n}\n\nexport interface RunPendingDataDirMigrationResult {\n success: boolean\n from: string\n to: string\n copied: number\n skipped: number\n errors: string[]\n}\n\nexport interface DataDirSwitchResult {\n success: boolean\n error?: string\n from?: string\n to?: string\n requiresRelaunch?: boolean\n}\n\nexport interface ApplyPendingNodeDataDirMigrationDeps {\n writeConfigField?: typeof writeConfigField\n removeDir?: (dir: string) => void\n}\n\nfunction normalizePathForCompare(input: string): string {\n const resolved = path.resolve(input)\n const normalized = path.normalize(resolved)\n return process.platform === 'win32' ? normalized.toLowerCase() : normalized\n}\n\nfunction isSubPath(parent: string, child: string): boolean {\n const parentPath = normalizePathForCompare(parent)\n const childPath = normalizePathForCompare(child)\n\n if (parentPath === childPath) return false\n return childPath.startsWith(`${parentPath}${path.sep}`)\n}\n\nfunction isPathSafe(targetPath: string): boolean {\n const normalizedTarget = targetPath.toLowerCase().replace(/\\//g, '\\\\')\n\n for (const dangerous of DANGEROUS_PATHS) {\n const normalizedDangerous = dangerous.toLowerCase().replace(/\\//g, '\\\\')\n if (normalizedTarget.startsWith(normalizedDangerous)) {\n return false\n }\n }\n\n return true\n}\n\nfunction ensureDir(dirPath: string): void {\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true })\n }\n}\n\nfunction hasChatLabUserDataStructure(entries: string[]): boolean {\n return entries.includes(CHATLAB_MARKER_FILE) && USER_DATA_REQUIRED_DIRS.every((dir) => entries.includes(dir))\n}\n\nfunction hasChatLabDatabaseFiles(dirPath: string, entries?: string[]): boolean {\n const dirEntries = entries ?? fs.readdirSync(dirPath)\n if (!dirEntries.includes('databases')) return false\n\n const dbDir = path.join(dirPath, 'databases')\n try {\n return fs.existsSync(dbDir) && fs.readdirSync(dbDir).some((file) => file.endsWith('.db'))\n } catch {\n return false\n }\n}\n\nexport function isExistingUserDataDir(dirPath: string): boolean {\n if (!fs.existsSync(dirPath)) return false\n\n try {\n const entries = fs.readdirSync(dirPath)\n return hasChatLabUserDataStructure(entries) || hasChatLabDatabaseFiles(dirPath, entries)\n } catch {\n return false\n }\n}\n\nexport function isUserDataDirSafeToUse(dirPath: string): boolean {\n if (!fs.existsSync(dirPath)) return true\n\n try {\n const entries = fs.readdirSync(dirPath)\n if (entries.length === 0) return true\n return hasChatLabUserDataStructure(entries) || hasChatLabDatabaseFiles(dirPath, entries)\n } catch {\n return false\n }\n}\n\nexport function isDirectoryEmptyOrMissing(dirPath: string): boolean {\n if (!fs.existsSync(dirPath)) return true\n\n try {\n return fs.readdirSync(dirPath).length === 0\n } catch {\n return false\n }\n}\n\nexport function copyDirMerge(\n src: string,\n dest: string,\n mkdir: (dirPath: string) => void = ensureDir,\n stats: CopyStats = { copied: 0, skipped: 0, errors: [] }\n): CopyStats {\n if (!fs.existsSync(src)) return stats\n\n try {\n mkdir(dest)\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n try {\n if (entry.isDirectory()) {\n copyDirMerge(srcPath, destPath, mkdir, stats)\n } else if (!fs.existsSync(destPath)) {\n fs.copyFileSync(srcPath, destPath)\n stats.copied++\n } else {\n stats.skipped++\n }\n } catch (error) {\n stats.errors.push(`复制失败: ${srcPath} -> ${error instanceof Error ? error.message : String(error)}`)\n }\n }\n } catch (error) {\n stats.errors.push(`读取目录失败: ${src} -> ${error instanceof Error ? error.message : String(error)}`)\n }\n\n return stats\n}\n\nexport function createPendingDataDirMigration(input: {\n from: string\n to: string\n migrate: boolean\n targetWasEmpty: boolean\n}): PendingDataDirMigration {\n return {\n from: input.from,\n to: input.to,\n migrate: input.migrate,\n deleteSourceOnSuccess: input.migrate && input.targetWasEmpty,\n createdAt: new Date().toISOString(),\n }\n}\n\nexport function runPendingDataDirMigration(\n pending: PendingDataDirMigration,\n deps: RunPendingDataDirMigrationDeps\n): RunPendingDataDirMigrationResult {\n const copy = deps.copyDirMerge ?? copyDirMerge\n const mkdir = deps.ensureDir ?? ensureDir\n\n let stats: CopyStats = { copied: 0, skipped: 0, errors: [] }\n if (pending.migrate && path.resolve(pending.from) !== path.resolve(pending.to)) {\n if (!fs.existsSync(pending.from)) {\n return {\n success: false,\n from: pending.from,\n to: pending.to,\n copied: 0,\n skipped: 0,\n errors: [`源数据目录不存在: ${pending.from}`],\n }\n }\n\n stats = copy(pending.from, pending.to, mkdir)\n deps.log?.(\n `数据目录迁移完成: 从 ${pending.from} 到 ${pending.to},复制 ${stats.copied} 项,跳过 ${stats.skipped} 项,错误 ${stats.errors.length} 项`\n )\n if (stats.errors.length > 0) {\n return {\n success: false,\n from: pending.from,\n to: pending.to,\n copied: stats.copied,\n skipped: stats.skipped,\n errors: stats.errors,\n }\n }\n } else {\n mkdir(pending.to)\n }\n\n deps.writeUserDataDir(pending.to)\n deps.clearPendingMigration()\n\n if (pending.deleteSourceOnSuccess && path.resolve(pending.from) !== path.resolve(pending.to)) {\n deps.markPendingDeleteDir?.(pending.from)\n }\n\n return {\n success: true,\n from: pending.from,\n to: pending.to,\n copied: stats.copied,\n skipped: stats.skipped,\n errors: [],\n }\n}\n\nfunction getPendingMigrationPath(systemDir: string): string {\n return path.join(systemDir, 'settings', PENDING_MIGRATION_FILE)\n}\n\nexport function getPendingNodeDataDirMigration(systemDir: string): PendingDataDirMigration | null {\n const filePath = getPendingMigrationPath(systemDir)\n if (!fs.existsSync(filePath)) return null\n\n try {\n const parsed = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as PendingDataDirMigration\n if (!parsed.from || !parsed.to || typeof parsed.migrate !== 'boolean') return null\n return parsed\n } catch {\n return null\n }\n}\n\nexport function clearPendingNodeDataDirMigration(systemDir: string): void {\n const filePath = getPendingMigrationPath(systemDir)\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath)\n }\n}\n\n// 只删除确认仍是 ChatLab 用户数据目录的旧路径,避免误删用户选择的普通目录。\nexport function deleteOldUserDataDirIfSafe(\n dirPath: string,\n currentDir: string,\n removeDir?: (dir: string) => void\n): boolean {\n if (path.resolve(dirPath) === path.resolve(currentDir)) return false\n if (!isPathSafe(dirPath)) return false\n if (!fs.existsSync(dirPath)) return false\n if (!isExistingUserDataDir(dirPath)) return false\n\n const remove = removeDir ?? ((dir: string) => fs.rmSync(dir, { recursive: true, force: true }))\n remove(dirPath)\n return true\n}\n\nfunction writePendingNodeDataDirMigration(systemDir: string, pending: PendingDataDirMigration): void {\n const filePath = getPendingMigrationPath(systemDir)\n ensureDir(path.dirname(filePath))\n fs.writeFileSync(filePath, JSON.stringify(pending, null, 2), 'utf-8')\n}\n\nexport function createNodeDataDirSwitch(input: {\n systemDir: string\n currentDir: string\n targetDir: string | null\n defaultDir?: string\n migrate?: boolean\n envDataDir?: string\n}): DataDirSwitchResult {\n if (input.envDataDir) {\n return { success: false, error: 'CHATLAB_DATA_DIR is set, data directory cannot be changed from Web UI' }\n }\n\n const newDir = (input.targetDir?.trim() || input.defaultDir || '').trim()\n if (!newDir) return { success: false, error: 'Data directory is required' }\n if (!path.isAbsolute(newDir)) return { success: false, error: 'Data directory must be an absolute path' }\n if (!isPathSafe(newDir)) return { success: false, error: 'System directories cannot be used as data directory' }\n\n const migrate = input.migrate !== false\n if (migrate && path.resolve(input.currentDir) !== path.resolve(newDir) && isSubPath(input.currentDir, newDir)) {\n return { success: false, error: 'Target directory cannot be inside current data directory' }\n }\n\n if (!isUserDataDirSafeToUse(newDir)) {\n return { success: false, error: 'Target directory is not empty and is not a ChatLab data directory' }\n }\n\n if (path.resolve(input.currentDir) === path.resolve(newDir)) {\n clearPendingNodeDataDirMigration(input.systemDir)\n return { success: true, from: input.currentDir, to: newDir, requiresRelaunch: false }\n }\n\n const pending = createPendingDataDirMigration({\n from: input.currentDir,\n to: newDir,\n migrate,\n targetWasEmpty: isDirectoryEmptyOrMissing(newDir),\n })\n writePendingNodeDataDirMigration(input.systemDir, pending)\n\n return { success: true, from: input.currentDir, to: newDir, requiresRelaunch: true }\n}\n\nexport function applyPendingNodeDataDirMigration(\n systemDir: string,\n deps: ApplyPendingNodeDataDirMigrationDeps = {}\n): {\n success: boolean\n skipped?: boolean\n error?: string\n} {\n const pending = getPendingNodeDataDirMigration(systemDir)\n if (!pending) return { success: true, skipped: true }\n const writeConfig = deps.writeConfigField ?? writeConfigField\n\n const result = runPendingDataDirMigration(pending, {\n writeUserDataDir(dir) {\n writeConfig('data', 'user_data_dir', dir)\n writeConfig('data', 'electron_migration_done', true)\n },\n clearPendingMigration() {\n clearPendingNodeDataDirMigration(systemDir)\n },\n markPendingDeleteDir(dir) {\n deleteOldUserDataDirIfSafe(dir, pending.to, deps.removeDir)\n },\n })\n\n if (!result.success) {\n return { success: false, error: result.errors.join('; ') || 'Data directory migration failed' }\n }\n\n return { success: true }\n}\n","/**\n * JiebaNlpProvider — NlpProvider 实现(基于 @node-rs/jieba)\n *\n * 提供给 @openchatlab/core 的 getLanguagePreferenceAnalysis 使用。\n * 仅在 Node.js 环境中可用(Electron worker / CLI server)。\n *\n * 使用 nlp/segmenter 的共享 getJieba() 实例,自动加载磁盘词库。\n */\n\nimport type { NlpProvider, PosTagResult } from '@openchatlab/core'\nimport { MEANINGFUL_POS_TAGS, isStopword } from '@openchatlab/core'\nimport { getJieba } from './nlp/segmenter'\nimport type { DictType } from '@openchatlab/core'\n\nexport function createJiebaNlpProvider(dictType: DictType = 'default'): NlpProvider {\n return {\n tag(text: string): PosTagResult[] {\n return getJieba(dictType).tag(text)\n },\n isStopword,\n meaningfulPosTags: MEANINGFUL_POS_TAGS,\n }\n}\n","/**\n * PreferencesManager — manages ~/.chatlab/preferences.json\n *\n * Stores complex user preferences that cannot fit into config.toml\n * (arrays, nested objects) and need cross-client consistency.\n */\n\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { DESENSITIZE_RULES_SCHEMA_VERSION } from './ai/preprocessor'\nimport type {\n Preferences,\n AIGlobalSettings,\n AIPreprocessConfig,\n WordFilterScheme,\n KeywordTemplate,\n ContextCompressionSettings,\n DesensitizeRule,\n FilterHistoryItem,\n} from '@openchatlab/shared-types'\n\nexport type {\n Preferences,\n AIGlobalSettings,\n AIPreprocessConfig,\n WordFilterScheme,\n KeywordTemplate,\n ContextCompressionSettings,\n DesensitizeRule,\n FilterHistoryItem,\n}\n\nconst DEFAULTS: Preferences = {\n pinnedSessionIds: [],\n aiPreprocessConfig: {\n dataCleaning: true,\n mergeConsecutive: true,\n mergeWindowSeconds: 180,\n blacklistKeywords: [],\n denoise: true,\n desensitize: true,\n desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,\n desensitizeBuiltinRuleOverrides: {},\n desensitizeRules: [],\n anonymizeNames: false,\n },\n aiGlobalSettings: {\n maxMessagesPerRequest: 1000,\n exportFormat: 'markdown',\n sqlExportFormat: 'csv',\n enableAutoSkill: true,\n chartAutoMode: 'suggest',\n searchContextBefore: 2,\n searchContextAfter: 2,\n contextCompression: {\n enabled: true,\n tokenThresholdPercent: 75,\n bufferSizePercent: 20,\n maxToolResultPercent: 50,\n },\n },\n customKeywordTemplates: [],\n deletedPresetTemplateIds: [],\n wordFilter: {\n schemes: [],\n defaultSchemeId: null,\n sessionSchemeOverrides: {},\n },\n filterHistory: [],\n thinkingLevels: {},\n ownerProfilesByPlatform: {},\n ownerPromptDismissedSessionIds: [],\n}\n\nexport class PreferencesManager {\n private filePath: string\n private cache: Preferences | null = null\n\n constructor(systemDir: string) {\n this.filePath = path.join(systemDir, 'preferences.json')\n }\n\n load(): Preferences {\n if (this.cache) return this.cache\n\n try {\n if (fs.existsSync(this.filePath)) {\n const raw = fs.readFileSync(this.filePath, 'utf-8')\n const parsed = JSON.parse(raw) as Partial<Preferences>\n const migrated = this.migrateLegacyDesensitizeRules(parsed, raw)\n this.cache = this.mergeDefaults(migrated.preferences)\n if (migrated.changed) {\n this.writePreferences(this.cache)\n }\n return this.cache\n }\n } catch (err) {\n console.warn('[Preferences] Failed to load preferences.json:', err)\n }\n\n this.cache = { ...DEFAULTS }\n return this.cache\n }\n\n save(partial: Partial<Preferences>): { success: boolean; error?: string } {\n try {\n const current = this.load()\n const merged = this.deepMerge(\n current as unknown as Record<string, unknown>,\n partial as unknown as Record<string, unknown>\n )\n if (Object.prototype.hasOwnProperty.call(partial.aiPreprocessConfig ?? {}, 'desensitizeBuiltinRuleOverrides')) {\n const mergedAiPreprocessConfig = merged.aiPreprocessConfig as Record<string, unknown>\n mergedAiPreprocessConfig.desensitizeBuiltinRuleOverrides =\n partial.aiPreprocessConfig?.desensitizeBuiltinRuleOverrides\n }\n this.cache = this.mergeDefaults(merged as unknown as Partial<Preferences>)\n\n this.writePreferences(this.cache)\n return { success: true }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error('[Preferences] Failed to save:', msg)\n return { success: false, error: msg }\n }\n }\n\n getFilePath(): string {\n return this.filePath\n }\n\n invalidateCache(): void {\n this.cache = null\n }\n\n private mergeDefaults(partial: Partial<Preferences>): Preferences {\n return {\n pinnedSessionIds: partial.pinnedSessionIds ?? DEFAULTS.pinnedSessionIds,\n aiPreprocessConfig: partial.aiPreprocessConfig\n ? this.normalizeAiPreprocessConfig(partial.aiPreprocessConfig)\n : { ...DEFAULTS.aiPreprocessConfig },\n aiGlobalSettings: partial.aiGlobalSettings\n ? {\n ...DEFAULTS.aiGlobalSettings,\n ...partial.aiGlobalSettings,\n contextCompression: {\n ...DEFAULTS.aiGlobalSettings.contextCompression,\n ...(partial.aiGlobalSettings.contextCompression ?? {}),\n },\n }\n : { ...DEFAULTS.aiGlobalSettings },\n customKeywordTemplates: partial.customKeywordTemplates ?? DEFAULTS.customKeywordTemplates,\n deletedPresetTemplateIds: partial.deletedPresetTemplateIds ?? DEFAULTS.deletedPresetTemplateIds,\n wordFilter: partial.wordFilter ? { ...DEFAULTS.wordFilter, ...partial.wordFilter } : { ...DEFAULTS.wordFilter },\n filterHistory: partial.filterHistory ?? DEFAULTS.filterHistory,\n thinkingLevels: partial.thinkingLevels ?? DEFAULTS.thinkingLevels,\n ownerProfilesByPlatform: partial.ownerProfilesByPlatform ?? DEFAULTS.ownerProfilesByPlatform,\n ownerPromptDismissedSessionIds: partial.ownerPromptDismissedSessionIds ?? DEFAULTS.ownerPromptDismissedSessionIds,\n }\n }\n\n private normalizeAiPreprocessConfig(partial: Partial<AIPreprocessConfig> | undefined): AIPreprocessConfig {\n const defaults = DEFAULTS.aiPreprocessConfig\n const rules = Array.isArray(partial?.desensitizeRules) ? partial.desensitizeRules : []\n const customRules = rules.filter((rule) => !rule.builtin)\n return {\n dataCleaning: partial?.dataCleaning ?? defaults.dataCleaning,\n mergeConsecutive: partial?.mergeConsecutive ?? defaults.mergeConsecutive,\n mergeWindowSeconds: partial?.mergeWindowSeconds ?? defaults.mergeWindowSeconds,\n blacklistKeywords: partial?.blacklistKeywords ?? defaults.blacklistKeywords,\n denoise: partial?.denoise ?? defaults.denoise,\n desensitize: partial?.desensitize ?? defaults.desensitize,\n desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,\n desensitizeBuiltinRuleOverrides: this.normalizeBooleanMap(partial?.desensitizeBuiltinRuleOverrides),\n desensitizeRules: customRules,\n anonymizeNames: partial?.anonymizeNames ?? defaults.anonymizeNames,\n }\n }\n\n private normalizeBooleanMap(value: unknown): Record<string, boolean> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {}\n const result: Record<string, boolean> = {}\n for (const [key, flag] of Object.entries(value as Record<string, unknown>)) {\n if (typeof flag === 'boolean') result[key] = flag\n }\n return result\n }\n\n private migrateLegacyDesensitizeRules(\n partial: Partial<Preferences>,\n rawContent: string\n ): { preferences: Partial<Preferences>; changed: boolean } {\n const rules = partial.aiPreprocessConfig?.desensitizeRules\n if (!Array.isArray(rules) || !rules.some((rule) => rule.builtin)) {\n return { preferences: partial, changed: false }\n }\n\n this.backupLegacyPreferences(rawContent)\n\n const legacyBuiltinRuleOverrides = rules\n .filter((rule) => rule.builtin && typeof rule.enabled === 'boolean')\n .reduce<Record<string, boolean>>((overrides, rule) => {\n overrides[rule.id] = rule.enabled\n return overrides\n }, {})\n const existingOverrides = this.normalizeBooleanMap(partial.aiPreprocessConfig?.desensitizeBuiltinRuleOverrides)\n\n return {\n preferences: {\n ...partial,\n aiPreprocessConfig: {\n ...partial.aiPreprocessConfig,\n desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,\n desensitizeBuiltinRuleOverrides: {\n ...legacyBuiltinRuleOverrides,\n ...existingOverrides,\n },\n desensitizeRules: rules.filter((rule) => !rule.builtin),\n },\n } as Partial<Preferences>,\n changed: true,\n }\n }\n\n private backupLegacyPreferences(rawContent: string): void {\n const backupDir = path.join(path.dirname(this.filePath), 'backups')\n if (!fs.existsSync(backupDir)) {\n fs.mkdirSync(backupDir, { recursive: true })\n }\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-')\n const backupPath = path.join(backupDir, `preferences-pre-desensitize-groups-${timestamp}.json`)\n fs.writeFileSync(backupPath, rawContent, 'utf-8')\n console.info(`[Preferences] Backed up legacy desensitize rules to ${backupPath}`)\n }\n\n private writePreferences(preferences: Preferences): void {\n const dir = path.dirname(this.filePath)\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n fs.writeFileSync(this.filePath, JSON.stringify(preferences, null, 2), 'utf-8')\n }\n\n /**\n * Deep merge: arrays are replaced (not concatenated), objects are merged.\n */\n private deepMerge(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {\n const result = { ...base }\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof base[key] === 'object' &&\n base[key] !== null &&\n !Array.isArray(base[key])\n ) {\n result[key] = this.deepMerge(base[key] as Record<string, unknown>, value as Record<string, unknown>)\n } else {\n result[key] = value\n }\n }\n return result\n }\n}\n","/**\n * Merger orchestration — abstract data-source reading, conflict checking,\n * merge assembly, and ChatLab output formatting.\n *\n * Decoupled from Electron-specific TempDbReader via MergerDataSource interface.\n */\n\nimport {\n getCollidingPlatformIds,\n normalizePlatformId,\n detectConflictsInMessages,\n mergeMergerMembers,\n generateMessageKey,\n type MergerMember,\n type MergerMessage,\n type ConflictCheckResult,\n type MergedMember,\n type MergedMessage,\n} from '@openchatlab/core'\n\n// ==================== Data source abstraction ====================\n\nexport interface MergerSourceMeta {\n name: string\n platform: string\n type: string\n groupId?: string\n groupAvatar?: string\n}\n\n/**\n * Abstract data source for merger input.\n * In Electron, this wraps TempDbReader. Other platforms can implement\n * their own (e.g. reading from IndexedDB, REST API, etc.).\n */\nexport interface MergerDataSource {\n getMeta(): MergerSourceMeta | null\n getMembers(): MergerMember[]\n getMessageCount(): number\n streamMessages(batchSize: number, callback: (messages: MergerMessage[]) => void): void\n}\n\n// ==================== Output types ====================\n\nexport interface MergeSourceInfo {\n filename: string\n platform: string\n messageCount: number\n}\n\nexport interface ChatLabHeader {\n version: string\n exportedAt: number\n generator: string\n description: string\n}\n\nexport interface ChatLabMeta {\n name: string\n platform: string\n type: string\n sources: MergeSourceInfo[]\n groupId?: string\n groupAvatar?: string\n}\n\nexport interface ChatLabOutput {\n chatlab: ChatLabHeader\n meta: ChatLabMeta\n members: MergedMember[]\n messages: MergedMessage[]\n}\n\n// ==================== Conflict checking ====================\n\nexport function checkConflictsFromSources(\n dataSources: Array<{ source: MergerDataSource; filename: string }>\n): ConflictCheckResult {\n const allMessages: Array<{ msg: MergerMessage; source: string; platform: string }> = []\n\n for (const { source, filename } of dataSources) {\n const meta = source.getMeta()\n const platform = meta?.platform || 'unknown'\n source.streamMessages(10000, (messages) => {\n for (const msg of messages) {\n allMessages.push({ msg, source: filename, platform })\n }\n })\n }\n\n return detectConflictsInMessages(allMessages)\n}\n\n// ==================== Merge orchestration ====================\n\nexport interface MergeOrchestrationResult {\n success: true\n chatLabData: ChatLabOutput\n}\n\n/**\n * Build a merged ChatLabOutput from multiple data sources.\n * Pure orchestration: reads data sources, calls core algorithms,\n * assembles the output. Does NOT write to disk or import to DB.\n */\nexport function buildMergedOutput(\n dataSources: Array<{ source: MergerDataSource; filename: string }>,\n outputName: string\n): MergeOrchestrationResult {\n const metas = dataSources.map(({ source, filename }) => ({\n meta: source.getMeta(),\n members: source.getMembers(),\n filename,\n source,\n }))\n\n const collidingIds = getCollidingPlatformIds(\n metas.map(({ meta, members }) => ({\n platform: meta?.platform || 'unknown',\n members: members.map((m) => ({ platformId: m.platformId })),\n }))\n )\n\n const memberMap = mergeMergerMembers(\n metas.map(({ meta, members }) => ({\n platform: meta?.platform || 'unknown',\n members,\n })),\n collidingIds\n )\n\n // Streaming dedup: process batches to avoid loading all into memory\n const seenKeys = new Set<string>()\n const mergedMessages: MergedMessage[] = []\n\n for (const { source, meta } of metas) {\n const platform = meta?.platform || 'unknown'\n source.streamMessages(10000, (messages) => {\n for (const msg of messages) {\n const nid = normalizePlatformId(msg.senderPlatformId, platform, collidingIds)\n const key = generateMessageKey(msg.timestamp, nid, msg.content ?? null)\n if (seenKeys.has(key)) continue\n seenKeys.add(key)\n mergedMessages.push({\n sender: nid,\n accountName: msg.senderAccountName,\n groupNickname: msg.senderGroupNickname,\n timestamp: msg.timestamp,\n type: msg.type,\n content: msg.content,\n })\n }\n })\n }\n\n mergedMessages.sort((a, b) => a.timestamp - b.timestamp)\n\n const sources: MergeSourceInfo[] = dataSources.map(({ source, filename }) => ({\n filename,\n platform: source.getMeta()?.platform || 'unknown',\n messageCount: source.getMessageCount(),\n }))\n\n const uniquePlatforms = [...new Set(metas.map(({ meta }) => meta?.platform || 'unknown'))]\n const platform = uniquePlatforms.length === 1 ? uniquePlatforms[0] : 'mixed'\n\n const groupIds = new Set(metas.map(({ meta }) => meta?.groupId).filter(Boolean))\n const groupId = groupIds.size === 1 ? metas.find(({ meta }) => meta?.groupId)?.meta?.groupId : undefined\n const groupAvatar = groupId\n ? metas.filter(({ meta }) => meta?.groupId === groupId).pop()?.meta?.groupAvatar\n : undefined\n\n const chatLabData: ChatLabOutput = {\n chatlab: {\n version: '0.0.1',\n exportedAt: Math.floor(Date.now() / 1000),\n generator: 'ChatLab Merge Tool',\n description: `Merged from ${dataSources.length} files`,\n },\n meta: {\n name: outputName,\n platform,\n type: metas[0]?.meta?.type || 'group',\n sources,\n groupId,\n groupAvatar,\n },\n members: Array.from(memberMap.values()),\n messages: mergedMessages,\n }\n\n return { success: true, chatLabData }\n}\n\n// ==================== JSONL serialization ====================\n\n/**\n * Serialize ChatLabOutput to JSONL lines (generator for streaming writes).\n */\nexport function* serializeChatLabToJsonl(data: ChatLabOutput): Generator<string> {\n yield JSON.stringify({\n _type: 'header',\n chatlab: data.chatlab,\n meta: data.meta,\n })\n\n for (const member of data.members) {\n yield JSON.stringify({ _type: 'member', ...member })\n }\n\n for (const msg of data.messages) {\n yield JSON.stringify({ _type: 'message', ...msg })\n }\n}\n","import * as fs from 'fs'\nimport * as path from 'path'\n\nconst REGIONS: Record<string, string> = {\n US: 'https://us.aptabase.com',\n EU: 'https://eu.aptabase.com',\n}\n\ninterface AnalyticsData {\n lastReportDate: string | null\n firstReportDate: string | null\n enabled: boolean\n}\n\nconst DEFAULT_DATA: AnalyticsData = { lastReportDate: null, firstReportDate: null, enabled: true }\n\nexport class AnalyticsService {\n private readonly dataPath: string\n private readonly endpoint: string | null\n private readonly appKey: string\n private readonly appVersion: string\n private readonly sessionId: string\n\n constructor(systemDir: string, appKey: string, appVersion: string) {\n this.dataPath = path.join(systemDir, 'analytics.json')\n this.appKey = appKey\n this.appVersion = appVersion\n this.sessionId = `${Math.floor(Date.now() / 1000)}${Math.floor(Math.random() * 1e8)\n .toString()\n .padStart(8, '0')}`\n const parts = appKey.split('-')\n const base = parts.length === 3 ? REGIONS[parts[1]] : undefined\n this.endpoint = base ? `${base}/api/v0/event` : null\n }\n\n private load(): AnalyticsData {\n try {\n if (fs.existsSync(this.dataPath)) {\n return { ...DEFAULT_DATA, ...JSON.parse(fs.readFileSync(this.dataPath, 'utf-8')) }\n }\n } catch (_e) {\n // Corrupted or unreadable file — fall back to defaults\n }\n return { ...DEFAULT_DATA }\n }\n\n private save(data: AnalyticsData): void {\n try {\n fs.writeFileSync(this.dataPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (e) {\n console.error('[Analytics] Failed to save:', e)\n }\n }\n\n getEnabled(): boolean {\n return this.load().enabled\n }\n\n setEnabled(enabled: boolean): void {\n const data = this.load()\n data.enabled = enabled\n this.save(data)\n }\n\n async track(eventName: string, props?: Record<string, string | number>): Promise<boolean> {\n if (!this.endpoint) return false\n if (!this.getEnabled()) return false\n try {\n const resp = await fetch(this.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'App-Key': this.appKey },\n body: JSON.stringify({\n timestamp: new Date().toISOString(),\n sessionId: this.sessionId,\n eventName,\n systemProps: {\n isDebug: false,\n locale: '',\n osName: process.platform,\n osVersion: '',\n engineName: 'Node.js',\n engineVersion: process.versions.node,\n appVersion: this.appVersion,\n sdkVersion: 'chatlab@1',\n },\n props,\n }),\n })\n return resp.ok\n } catch (e) {\n console.error(`[Analytics] Failed to track ${eventName}:`, e)\n return false\n }\n }\n\n async trackDailyActive(props?: Record<string, string | number>): Promise<void> {\n if (!this.endpoint) return\n const data = this.load()\n if (!data.enabled) return\n const today = new Date().toISOString().slice(0, 10)\n const isNew = data.firstReportDate === null\n if (isNew) data.firstReportDate = today\n if (data.lastReportDate === today) {\n if (isNew) this.save(data)\n return\n }\n const tracked = await this.track(isNew ? 'app_active_new' : 'app_active', props)\n if (!tracked) return\n data.lastReportDate = today\n this.save(data)\n }\n}\n","/**\n * 语义索引模块(Phase 1)\n *\n * 独立于 dormant 的旧 `ai/rag` 模块,按 chunking-decision-final.md 重新实现:\n * 向量存储、parent/child chunker、embedding provider、混合召回与后台预热。\n */\n\nexport { EmbeddingIndexStore } from './store'\nexport type { LoadSqliteVec } from './store'\nexport {\n EMBEDDING_INDEX_SCHEMA,\n CHUNK_VECTOR_INDEX_TABLE,\n CHUNK_VECTOR_INDEX_INDEXES,\n SEMANTIC_INDEX_SESSION_TABLE,\n vecTableName,\n vecTableSchema,\n} from './schema'\nexport { SemanticIndexStateStore } from './session-state-store'\nexport type {\n SemanticIndexSessionState,\n SemanticIndexStatus,\n SemanticIndexCleanupStatus,\n EnableParams,\n ProgressPatch,\n} from './session-state-store'\nexport type {\n ChunkRecord,\n ChunkInsert,\n ChunkStatus,\n DenseQueryParams,\n DenseQueryResult,\n MessageToChunkParams,\n} from './types'\nexport {\n CHUNKER_VERSION,\n STRATEGY_ID,\n DEFAULT_CHUNKER_CONFIG,\n computeChunkerConfigHash,\n computeDbPathHash,\n composeChunkId,\n deriveParentId,\n parseParentBounds,\n} from './chunker-config'\nexport type { ChunkerConfig } from './chunker-config'\nexport { estimateTokens } from './tokens'\nexport {\n SemanticIndexConfigStore,\n defaultSemanticIndexConfig,\n isSemanticIndexConfigured,\n resolveModelId,\n clampSearchMaxResults,\n SEMANTIC_INDEX_CONFIG_VERSION,\n SEARCH_MAX_RESULTS_DEFAULT,\n SEARCH_MAX_RESULTS_MIN,\n SEARCH_MAX_RESULTS_MAX,\n} from './config'\nexport type {\n SemanticIndexConfig,\n SemanticIndexConfigInput,\n SemanticIndexMode,\n SemanticIndexLocalConfig,\n SemanticIndexApiConfig,\n} from './config'\nexport { createEmbedder } from './embedder-factory'\nexport type { EmbedderFactoryDeps } from './embedder-factory'\nexport {\n SemanticIndexService,\n createSemanticIndexService,\n persistSemanticIndexConfig,\n resolveSemanticIndexApiKeySet,\n SEMANTIC_INDEX_AUTH_PROFILE,\n SEMANTIC_INDEX_DB_FILE,\n SEMANTIC_INDEX_CONFIG_FILE,\n} from './service'\nexport type { SemanticIndexRuntime, MaybePromise } from './runtime'\nexport {\n SemanticIndexWorkerClient,\n createSemanticIndexWorkerClient,\n createSemanticIndexWorkerRuntimeClient,\n} from './worker-client'\nexport type {\n SemanticIndexWorkerClientOptions,\n SemanticIndexWorkerRuntimeClientOptions,\n SemanticIndexWorkerTransport,\n SemanticIndexWorkerTransportFactory,\n} from './worker-client'\nexport { createSemanticIndexWorkerThreadTransport } from './worker-thread-transport'\nexport type { SemanticIndexWorkerThreadTransportOptions, SemanticIndexWorkerLike } from './worker-thread-transport'\nexport { StaticPathProvider, snapshotPathProvider } from './static-path-provider'\nexport type { StaticPathProviderSnapshot } from './static-path-provider'\nexport type {\n SemanticIndexServiceOptions,\n SemanticIndexSessionStatus,\n SemanticSearchResult,\n SemanticSearchReason,\n SemanticSearchToolResult,\n SemanticSearchToolSource,\n SemanticSearchToolOptions,\n} from './service'\nexport { runWarmup } from './warmup/runner'\nexport type {\n SemanticMessageSource,\n StopSignal,\n WarmupRunnerOptions,\n WarmupResult,\n WarmupStatus,\n} from './warmup/runner'\nexport { SemanticIndexJobQueue } from './warmup/job-queue'\nexport type { SemanticIndexJob, SemanticIndexJobType, JobContext, JobExecutor } from './warmup/job-queue'\nexport { reciprocalRankFusion } from './retrieval/rrf'\nexport type { RrfResult } from './retrieval/rrf'\nexport { hybridSearch } from './retrieval/hybrid-search'\nexport type { FtsSearcher, HybridSearchDeps, HybridSearchParams, HybridSearchResult } from './retrieval/hybrid-search'\nexport { createChatDbMessageSource } from './chat-db/message-source'\nexport { createChatDbMessageRangeReader } from './chat-db/message-range-reader'\nexport { createChatDbFtsSearcher, extractFtsKeywords } from './chat-db/fts-searcher'\nexport { assembleEvidence, formatEvidenceMessages } from './retrieval/evidence'\nexport type {\n EvidenceMessage,\n MessageRangeReader,\n EvidenceHit,\n EvidenceBudget,\n EvidenceBlock,\n EvidenceResult,\n} from './retrieval/evidence'\nexport { chunkMessages, isSemanticVoid } from './chunker'\nexport type { ChunkMessageInput, ChunkSource, ChunkMessagesInput, ChildChunk, ChunkResult } from './chunker'\nexport * as embedding from './embedding'\n","import path from 'node:path'\nimport type { PathProvider } from '@openchatlab/core'\nimport type { AuthProfile } from '@openchatlab/config'\nimport { resolveApiKey as defaultResolveApiKey } from '@openchatlab/config'\nimport type { SemanticIndexConfig, SemanticIndexConfigInput } from './config'\nimport { isKeylessSemanticIndexApiBaseUrl, SemanticIndexConfigStore } from './config'\nimport {\n SEMANTIC_INDEX_CONFIG_FILE,\n persistSemanticIndexConfig,\n resolveSemanticIndexApiKeySet,\n type SemanticIndexSessionStatus,\n type SemanticSearchResult,\n type SemanticSearchToolOptions,\n type SemanticSearchToolResult,\n} from './service'\nimport type { SemanticIndexRuntime } from './runtime'\nimport type { RuntimeIdentity } from '../data-dir-compat'\nimport { snapshotPathProvider } from './static-path-provider'\nimport { createSemanticIndexWorkerThreadTransport } from './worker-thread-transport'\n\nexport interface SemanticIndexWorkerTransport {\n request<T>(method: string, args: unknown[]): Promise<T>\n close(): void | Promise<void>\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport type SemanticIndexWorkerTransportFactory = (modelDownloadProxyUrl?: string) => SemanticIndexWorkerTransport\n\ninterface WorkerClientTimers {\n setTimeout(callback: () => void, ms: number): unknown\n clearTimeout(timer: unknown): void\n}\n\nexport interface SemanticIndexWorkerClientOptions {\n configStore: SemanticIndexConfigStore\n transportFactory: SemanticIndexWorkerTransportFactory\n idleTimeoutMs?: number\n timers?: WorkerClientTimers\n getModelDownloadProxyUrl?: () => MaybePromise<string | undefined>\n resolveApiKey?: (provider: string, authProfile?: string) => string\n writeAuthProfile?: (name: string, profile: AuthProfile) => void\n}\n\nexport interface SemanticIndexWorkerRuntimeClientOptions {\n pathProvider: PathProvider\n runtime: RuntimeIdentity\n nativeBinding?: string\n sqliteVecLoadablePath?: string\n workerEntryUrl?: string | URL\n idleTimeoutMs?: number\n getModelDownloadProxyUrl?: () => MaybePromise<string | undefined>\n resolveApiKey?: (provider: string, authProfile?: string) => string\n writeAuthProfile?: (name: string, profile: AuthProfile) => void\n}\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000\n\nconst defaultTimers: WorkerClientTimers = {\n setTimeout: (callback, ms) => setTimeout(callback, ms),\n clearTimeout: (timer) => clearTimeout(timer as ReturnType<typeof setTimeout>),\n}\n\nexport class SemanticIndexWorkerClient implements SemanticIndexRuntime {\n private transport: SemanticIndexWorkerTransport | null = null\n private pendingRequests = 0\n private idleTimer: unknown = null\n private activeBuildSessionIds = new Set<string>()\n private hasUnknownActiveBuild = false\n private activeModelDownloadProxyUrl: string | undefined\n private readonly configStore: SemanticIndexConfigStore\n private readonly transportFactory: SemanticIndexWorkerTransportFactory\n private readonly idleTimeoutMs: number\n private readonly timers: WorkerClientTimers\n private readonly getModelDownloadProxyUrl: () => MaybePromise<string | undefined>\n private readonly resolveApiKey: (provider: string, authProfile?: string) => string\n private readonly writeAuthProfile?: (name: string, profile: AuthProfile) => void\n\n constructor(options: SemanticIndexWorkerClientOptions) {\n this.configStore = options.configStore\n this.transportFactory = options.transportFactory\n this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS\n this.timers = options.timers ?? defaultTimers\n this.getModelDownloadProxyUrl = options.getModelDownloadProxyUrl ?? (() => undefined)\n this.resolveApiKey = options.resolveApiKey ?? defaultResolveApiKey\n this.writeAuthProfile = options.writeAuthProfile\n }\n\n getConfig(): SemanticIndexConfig {\n return this.configStore.get()\n }\n\n async setConfig(config: SemanticIndexConfigInput, options?: { apiKey?: string }): Promise<SemanticIndexConfig> {\n const saved = persistSemanticIndexConfig(this.configStore, config, {\n apiKey: options?.apiKey,\n writeAuthProfile: this.writeAuthProfile,\n })\n if (!saved.enabled) this.clearActiveBuildTracking()\n // 本地模式且功能开启时,即使 worker 未运行也需启动它以触发 preload;\n // 其余情况(disabled / api 模式)无需唤醒 worker,直接返回本地保存结果。\n const needsWorker = saved.enabled && saved.mode === 'local' && this.configStore.isConfigured()\n if (!this.transport && !needsWorker) return saved\n if (needsWorker) await this.closeTransportForLocalModelProxyChangeIfNeeded()\n return await this.call<SemanticIndexConfig>('setConfig', [saved])\n }\n\n isConfigured(): boolean {\n return this.configStore.isConfigured()\n }\n\n hasApiKey(): boolean {\n return resolveSemanticIndexApiKeySet(this.configStore.get(), this.resolveApiKey)\n }\n\n async getModelStatus(): Promise<'idle' | 'downloading' | 'ready' | 'error'> {\n if (!this.transport) return 'idle'\n return this.call<'idle' | 'downloading' | 'ready' | 'error'>('getModelStatus', [])\n }\n\n enable(sessionId: string): Promise<void> {\n return this.call('enable', [sessionId])\n }\n\n remove(sessionId: string): Promise<void> {\n return this.call('remove', [sessionId])\n }\n\n async build(sessionId: string): Promise<void> {\n await this.closeTransportForLocalModelProxyChangeIfNeeded()\n this.activeBuildSessionIds.add(sessionId)\n try {\n await this.call('build', [sessionId])\n } catch (error) {\n this.activeBuildSessionIds.delete(sessionId)\n throw error\n }\n }\n\n pause(sessionId: string): Promise<void> {\n return this.call('pause', [sessionId])\n }\n\n cancel(sessionId: string): Promise<void> {\n return this.call('cancel', [sessionId])\n }\n\n async rebuild(sessionId: string): Promise<void> {\n await this.closeTransportForLocalModelProxyChangeIfNeeded()\n this.activeBuildSessionIds.add(sessionId)\n try {\n await this.call('rebuild', [sessionId])\n } catch (error) {\n this.activeBuildSessionIds.delete(sessionId)\n throw error\n }\n }\n\n async buildAllPending(): Promise<void> {\n await this.closeTransportForLocalModelProxyChangeIfNeeded()\n this.hasUnknownActiveBuild = true\n try {\n await this.call('buildAllPending', [])\n } catch (error) {\n this.hasUnknownActiveBuild = false\n throw error\n }\n }\n\n async listEnabledStatuses(): Promise<SemanticIndexSessionStatus[]> {\n const statuses = await this.callProbe<SemanticIndexSessionStatus[]>('listEnabledStatuses', [], [], {\n scheduleIdle: false,\n })\n this.updateActiveBuildFromCompleteSnapshot(statuses)\n this.scheduleIdleCloseIfNeeded()\n return statuses\n }\n\n async status(sessionId: string): Promise<SemanticIndexSessionStatus | null> {\n const status = await this.callProbe<SemanticIndexSessionStatus | null>('status', [sessionId], null, {\n scheduleIdle: false,\n })\n this.updateActiveBuildFromPartialSnapshot([sessionId], status ? [status] : [])\n this.scheduleIdleCloseIfNeeded()\n return status\n }\n\n async statusForSessions(sessionIds: string[]): Promise<SemanticIndexSessionStatus[]> {\n const statuses = await this.callProbe<SemanticIndexSessionStatus[]>('statusForSessions', [sessionIds], [], {\n scheduleIdle: false,\n })\n this.updateActiveBuildFromPartialSnapshot(sessionIds, statuses)\n this.scheduleIdleCloseIfNeeded()\n return statuses\n }\n\n async canSearch(sessionId: string): Promise<boolean> {\n if (!this.canRunFromLocalConfig()) return false\n return await this.callProbe<boolean>('canSearch', [sessionId], false)\n }\n\n async search(\n sessionId: string,\n query: string,\n options?: { finalTopK?: number; timeRangeMs?: { startTs?: number; endTs?: number } }\n ): Promise<SemanticSearchResult> {\n await this.closeTransportForLocalModelProxyChangeIfNeeded()\n return await this.call('search', [sessionId, query, options])\n }\n\n async searchForTool(\n sessionId: string,\n query: string,\n options?: SemanticSearchToolOptions\n ): Promise<SemanticSearchToolResult> {\n await this.closeTransportForLocalModelProxyChangeIfNeeded()\n return await this.call('searchForTool', [sessionId, query, options])\n }\n\n cleanupUnused(): Promise<{ cleaned: number }> {\n return this.call('cleanupUnused', [])\n }\n\n recover(): Promise<void> {\n return this.call('recover', [])\n }\n\n async close(): Promise<void> {\n this.clearIdleTimer()\n await this.closeTransport()\n }\n\n private async call<T>(method: string, args: unknown[], options?: { scheduleIdle?: boolean }): Promise<T> {\n const transport = await this.ensureTransport()\n this.pendingRequests++\n this.clearIdleTimer()\n try {\n return await transport.request<T>(method, args)\n } finally {\n this.pendingRequests--\n if (options?.scheduleIdle !== false) this.scheduleIdleCloseIfNeeded()\n }\n }\n\n private async callProbe<T>(\n method: string,\n args: unknown[],\n fallback: T,\n options?: { scheduleIdle?: boolean }\n ): Promise<T> {\n try {\n return await this.call<T>(method, args, options)\n } catch {\n await this.closeFailedProbeTransport()\n return fallback\n }\n }\n\n private async ensureTransport(): Promise<SemanticIndexWorkerTransport> {\n if (!this.transport) {\n const proxyUrl = await this.currentModelDownloadProxyUrl()\n if (!this.transport) {\n this.activeModelDownloadProxyUrl = proxyUrl\n this.transport = this.transportFactory(proxyUrl)\n }\n }\n return this.transport\n }\n\n private async currentModelDownloadProxyUrl(): Promise<string | undefined> {\n const proxyUrl = (await this.getModelDownloadProxyUrl())?.trim()\n return proxyUrl || undefined\n }\n\n private async closeTransportForLocalModelProxyChangeIfNeeded(): Promise<void> {\n if (!this.transport) return\n const config = this.configStore.get()\n if (!this.configStore.canRun() || config.mode !== 'local') return\n if (this.hasUnknownActiveBuild || this.activeBuildSessionIds.size > 0) return\n if ((await this.currentModelDownloadProxyUrl()) === this.activeModelDownloadProxyUrl) return\n await this.closeTransport()\n }\n\n private canRunFromLocalConfig(): boolean {\n const config = this.configStore.get()\n if (!this.configStore.canRun()) return false\n if (config.mode !== 'api') return true\n if (isKeylessSemanticIndexApiBaseUrl(config.api?.baseUrl)) return true\n return resolveSemanticIndexApiKeySet(config, this.resolveApiKey)\n }\n\n private updateActiveBuildFromCompleteSnapshot(statuses: SemanticIndexSessionStatus[]): void {\n this.hasUnknownActiveBuild = false\n this.activeBuildSessionIds = new Set(\n statuses.filter((status) => this.isActiveBuildStatus(status)).map((status) => status.sessionId)\n )\n }\n\n private updateActiveBuildFromPartialSnapshot(\n requestedSessionIds: string[],\n statuses: SemanticIndexSessionStatus[]\n ): void {\n const bySessionId = new Map(statuses.map((status) => [status.sessionId, status]))\n for (const sessionId of requestedSessionIds) {\n const status = bySessionId.get(sessionId)\n if (status && this.isActiveBuildStatus(status)) this.activeBuildSessionIds.add(sessionId)\n else this.activeBuildSessionIds.delete(sessionId)\n }\n }\n\n private isActiveBuildStatus(status: SemanticIndexSessionStatus): boolean {\n return status.running || status.queued || status.indexStatus === 'running'\n }\n\n private clearActiveBuildTracking(): void {\n this.hasUnknownActiveBuild = false\n this.activeBuildSessionIds.clear()\n }\n\n private scheduleIdleCloseIfNeeded(): void {\n if (\n !this.transport ||\n this.pendingRequests > 0 ||\n this.hasUnknownActiveBuild ||\n this.activeBuildSessionIds.size > 0\n )\n return\n this.clearIdleTimer()\n this.idleTimer = this.timers.setTimeout(() => {\n void this.closeTransport().catch((err) => {\n console.warn('[semantic-index] idle worker close failed:', err instanceof Error ? err.message : String(err))\n })\n }, this.idleTimeoutMs)\n }\n\n private clearIdleTimer(): void {\n if (this.idleTimer) {\n this.timers.clearTimeout(this.idleTimer)\n this.idleTimer = null\n }\n }\n\n private async closeTransport(): Promise<void> {\n const transport = this.transport\n this.transport = null\n this.activeModelDownloadProxyUrl = undefined\n this.clearActiveBuildTracking()\n if (transport) await transport.close()\n }\n\n private async closeFailedProbeTransport(): Promise<void> {\n this.clearIdleTimer()\n try {\n await this.closeTransport()\n } catch {\n // 语义索引探针失败只降级为不可用,不能打断普通 AI 对话流程。\n }\n }\n}\n\nexport function createSemanticIndexWorkerClient(options: SemanticIndexWorkerClientOptions): SemanticIndexWorkerClient {\n return new SemanticIndexWorkerClient(options)\n}\n\nexport function createSemanticIndexWorkerRuntimeClient(\n options: SemanticIndexWorkerRuntimeClientOptions\n): SemanticIndexWorkerClient {\n const configStore = new SemanticIndexConfigStore(\n path.join(options.pathProvider.getAiDataDir(), SEMANTIC_INDEX_CONFIG_FILE)\n )\n return createSemanticIndexWorkerClient({\n configStore,\n idleTimeoutMs: options.idleTimeoutMs,\n resolveApiKey: options.resolveApiKey,\n writeAuthProfile: options.writeAuthProfile,\n getModelDownloadProxyUrl: options.getModelDownloadProxyUrl,\n transportFactory: (modelDownloadProxyUrl) =>\n createSemanticIndexWorkerThreadTransport({\n workerEntryUrl: options.workerEntryUrl,\n startup: {\n paths: snapshotPathProvider(options.pathProvider),\n runtime: options.runtime,\n nativeBinding: options.nativeBinding,\n sqliteVecLoadablePath: options.sqliteVecLoadablePath,\n modelDownloadProxyUrl,\n },\n }),\n })\n}\n","import { Worker } from 'node:worker_threads'\nimport type { WorkerOptions } from 'node:worker_threads'\nimport type { SemanticIndexWorkerTransport } from './worker-client'\nimport type { SemanticIndexWorkerStartupOptions } from './worker-runtime'\n\nexport interface SemanticIndexWorkerLike {\n postMessage(message: unknown): void\n terminate(): Promise<number>\n on(event: 'message', listener: (message: unknown) => void): this\n on(event: 'error', listener: (error: Error) => void): this\n on(event: 'exit', listener: (code: number) => void): this\n}\n\nexport interface SemanticIndexWorkerThreadTransportOptions {\n startup: SemanticIndexWorkerStartupOptions\n workerFactory?: () => SemanticIndexWorkerLike\n workerEntryUrl?: string | URL\n closeTimeoutMs?: number\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n}\n\nconst DEFAULT_CLOSE_TIMEOUT_MS = 3_000\n\ntype ModuleWorkerOptions = WorkerOptions & { type: 'module' }\n\nfunction defaultWorkerEntryUrl(): URL {\n return import.meta.url.endsWith('.ts')\n ? new URL('./worker-thread-entry.ts', import.meta.url)\n : new URL('./worker-thread-entry.js', import.meta.url)\n}\n\nfunction normalizeWorkerEntryUrl(entryUrl?: string | URL): URL {\n if (!entryUrl) return defaultWorkerEntryUrl()\n return typeof entryUrl === 'string' ? new URL(entryUrl) : entryUrl\n}\n\nfunction createDefaultWorker(\n startup: SemanticIndexWorkerStartupOptions,\n entryUrlInput?: string | URL\n): SemanticIndexWorkerLike {\n const entryUrl = normalizeWorkerEntryUrl(entryUrlInput)\n if (!entryUrl.href.endsWith('.ts')) {\n return new Worker(entryUrl, { workerData: startup }) as SemanticIndexWorkerLike\n }\n\n const bootstrap = `\n import { register } from 'tsx/esm/api';\n register();\n await import(${JSON.stringify(entryUrl.href)});\n `\n const options: ModuleWorkerOptions = {\n eval: true,\n type: 'module',\n workerData: startup,\n execArgv: [],\n }\n return new Worker(bootstrap, options) as SemanticIndexWorkerLike\n}\n\nexport class SemanticIndexWorkerThreadTransport implements SemanticIndexWorkerTransport {\n private worker: SemanticIndexWorkerLike\n private pending = new Map<string, PendingRequest>()\n private requestId = 0\n private readonly closeTimeoutMs: number\n\n constructor(options: SemanticIndexWorkerThreadTransportOptions) {\n this.closeTimeoutMs = options.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS\n this.worker = options.workerFactory?.() ?? createDefaultWorker(options.startup, options.workerEntryUrl)\n\n this.worker.on('message', (message) => this.handleMessage(message))\n this.worker.on('error', (error) => this.rejectAll(error))\n this.worker.on('exit', (code) => {\n if (code !== 0) this.rejectAll(new Error(`Semantic index worker exited with code ${code}`))\n })\n }\n\n request<T>(method: string, args: unknown[]): Promise<T> {\n const id = `si_${++this.requestId}`\n return new Promise<T>((resolve, reject) => {\n this.pending.set(id, { resolve: resolve as (value: unknown) => void, reject })\n this.worker.postMessage({ id, method, args })\n })\n }\n\n async close(): Promise<void> {\n await this.requestRuntimeClose()\n await this.worker.terminate()\n this.rejectAll(new Error('Semantic index worker closed'))\n }\n\n private async requestRuntimeClose(): Promise<void> {\n let timeout: ReturnType<typeof setTimeout> | null = null\n const timeoutPromise = new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, this.closeTimeoutMs)\n })\n\n try {\n // 先让 worker 内的 service 正常 close,避免 SQLite/vector 资源被直接中断;超时后仍会 terminate。\n await Promise.race([this.request('__close', []).then(() => undefined), timeoutPromise])\n } catch {\n // Worker may already be gone; terminate below still clears local state.\n } finally {\n if (timeout) clearTimeout(timeout)\n }\n }\n\n private handleMessage(message: unknown): void {\n const payload = message as { id?: string; success?: boolean; result?: unknown; error?: string }\n if (!payload.id) return\n const pending = this.pending.get(payload.id)\n if (!pending) return\n this.pending.delete(payload.id)\n if (payload.success) pending.resolve(payload.result)\n else pending.reject(new Error(payload.error ?? 'Semantic index worker request failed'))\n }\n\n private rejectAll(error: Error): void {\n for (const [id, pending] of this.pending.entries()) {\n this.pending.delete(id)\n pending.reject(error)\n }\n }\n}\n\nexport function createSemanticIndexWorkerThreadTransport(\n options: SemanticIndexWorkerThreadTransportOptions\n): SemanticIndexWorkerThreadTransport {\n return new SemanticIndexWorkerThreadTransport(options)\n}\n","/**\n * Embedding provider 模块\n */\n\nexport type { EmbeddingProvider, EmbeddingPooling } from './types'\nexport {\n QWEN3_PROFILE,\n BGE_BASE_PROFILE,\n getLocalProfilesForLocale,\n getLocalProfileByModelId,\n type LocalEmbeddingProfile,\n} from './profiles'\nexport { applyQueryInstruction, clampTextChars } from './text'\nexport { LocalEmbeddingProvider } from './local'\nexport type { LocalPipelineFactory, FeatureExtractFn, LocalEmbeddingProviderOptions } from './local'\nexport { OpenAICompatibleEmbeddingProvider } from './api'\nexport type { OpenAICompatibleConfig, FetchFn } from './api'\n"],"mappings":"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","names":["fs","path","fs","path","platform","fs","path","path","resolve","path"]}
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  assertCliDataDirCompatible
9
- } from "./chunk-NJB2NNB2.mjs";
9
+ } from "./chunk-6FPEP2ZX.mjs";
10
10
  import {
11
11
  getVersion
12
12
  } from "./chunk-5ADKYYNA.mjs";
@@ -18,9 +18,11 @@ import {
18
18
  applyPendingNodeDataDirMigrationIfNeeded,
19
19
  getSystemLogsDir,
20
20
  hasPendingElectronDataWarning
21
- } from "./chunk-YBS3YQB6.mjs";
21
+ } from "./chunk-7RW4CQAO.mjs";
22
+ import {
23
+ AIChatManager
24
+ } from "./chunk-QQK7MLCR.mjs";
22
25
  import {
23
- AIChatManager,
24
26
  DEFAULT_API_PORT,
25
27
  DatabaseManager,
26
28
  appLogger,
@@ -34,7 +36,7 @@ import {
34
36
  loadConfig,
35
37
  searchMessagesLike,
36
38
  verifyCliDataPath
37
- } from "./chunk-ZVDOFWL7.mjs";
39
+ } from "./chunk-WPI6YSAR.mjs";
38
40
 
39
41
  // src/cli.ts
40
42
  import * as fs from "fs";
@@ -228,7 +230,7 @@ program.command("import <file>").description("Import a chat history file (14+ fo
228
230
  console.error(`File not found: ${file}`);
229
231
  process.exit(1);
230
232
  }
231
- const { streamImport, detectFormat } = await import("./import-EYV3GXHE.mjs");
233
+ const { streamImport, detectFormat } = await import("./import-3KG6VK6O.mjs");
232
234
  const { dbManager, pathProvider } = initRuntime();
233
235
  const nativeBinding = resolveNativeBinding();
234
236
  const format = detectFormat(file);
@@ -256,7 +258,7 @@ Import succeeded!`);
256
258
  console.log(` Messages skipped: ${result.diagnostics?.messagesSkipped ?? 0}`);
257
259
  if (result.sessionId) {
258
260
  try {
259
- const { PreferencesManager, createDatabaseManagerAdapter, ownerProfileService } = await import("./src-36ZIR65K.mjs");
261
+ const { PreferencesManager, createDatabaseManagerAdapter, ownerProfileService } = await import("./src-UTBQAOJ3.mjs");
260
262
  const applied = ownerProfileService.tryApplyOwnerProfile(
261
263
  createDatabaseManagerAdapter(dbManager),
262
264
  new PreferencesManager(pathProvider.getSystemDir()),
@@ -285,7 +287,7 @@ Import error: ${err instanceof Error ? err.message : err}`);
285
287
  }
286
288
  });
287
289
  program.command("formats").description("List all supported chat history formats").action(async () => {
288
- const { getSupportedFormats } = await import("./import-EYV3GXHE.mjs");
290
+ const { getSupportedFormats } = await import("./import-3KG6VK6O.mjs");
289
291
  const formats = getSupportedFormats();
290
292
  console.log(`${formats.length} supported format(s):
291
293
  `);
@@ -294,11 +296,11 @@ program.command("formats").description("List all supported chat history formats"
294
296
  }
295
297
  });
296
298
  program.command("mcp").description("Start MCP Server (stdio transport, for ClaudeCode / Cursor / AI agents)").action(async () => {
297
- const { startCliMcpServer } = await import("./mcp-H55AEXU5.mjs");
299
+ const { startCliMcpServer } = await import("./mcp-JBI4CUQT.mjs");
298
300
  await startCliMcpServer();
299
301
  });
300
302
  program.command("chat").description("Ask ChatLab AI about an imported chat session").option("--session-id <id>", "Source chat session ID").option("--ai-chat-id <id>", "Existing AI chat ID to continue").option("-q, --question <text>", "Question to ask").option("--json", "Output structured JSON").option("--include-events", "Include all agent stream chunks in JSON output").option("--no-stream", "Disable streaming output").option("--locale <locale>", "AI response locale", "zh-CN").action(async (options) => {
301
- const { runChatCommand } = await import("./chat-command-ISJ2DC7R.mjs");
303
+ const { runChatCommand } = await import("./chat-command-JKG3FY5B.mjs");
302
304
  const { dbManager, pathProvider } = initRuntime();
303
305
  const aiChatManager = new AIChatManager(pathProvider.getAiDataDir(), { nativeBinding: resolveNativeBinding() });
304
306
  try {
@@ -334,7 +336,7 @@ program.command("start").description("Start ChatLab (HTTP API + Web UI)").option
334
336
  });
335
337
  return;
336
338
  }
337
- const { startHttpServer } = await import("./http-MBILV37U.mjs");
339
+ const { startHttpServer } = await import("./http-5E7ARYFW.mjs");
338
340
  const port = parseInt(options.port, 10);
339
341
  let webRoot;
340
342
  if (!options.headless) {
@@ -381,7 +383,7 @@ Press Ctrl+C to stop.
381
383
  }
382
384
  const shutdown = async () => {
383
385
  console.log("\nShutting down...");
384
- const { stopHttpServer } = await import("./http-MBILV37U.mjs");
386
+ const { stopHttpServer } = await import("./http-5E7ARYFW.mjs");
385
387
  await stopHttpServer();
386
388
  process.exit(0);
387
389
  };
@@ -537,4 +539,4 @@ if (isDirectRun) {
537
539
  export {
538
540
  run
539
541
  };
540
- //# sourceMappingURL=chunk-GHTGFM6O.mjs.map
542
+ //# sourceMappingURL=chunk-ARZM6HBX.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/http/port.ts"],"sourcesContent":["/**\n * ChatLab CLI entry point\n *\n * Dev: pnpm --filter chatlab-cli run cli -- sessions\n */\n\nimport * as fs from 'fs'\nimport { execSync } from 'child_process'\nimport { Command } from 'commander'\nimport { DEFAULT_API_PORT, loadConfig, getConfigPath } from '@openchatlab/config'\nimport {\n NodePathProvider,\n DatabaseManager,\n AIChatManager,\n applyPendingNodeDataDirMigrationIfNeeded,\n hasPendingElectronDataWarning,\n verifyCliDataPath,\n initAppLogger,\n appLogger,\n getSystemLogsDir,\n} from '@openchatlab/node-runtime'\nimport {\n getSessionMeta,\n getSessionOverview,\n getMemberActivity,\n searchMessagesLike,\n getMembers,\n executeReadonlySql,\n} from '@openchatlab/core'\nimport { getVersion } from './version'\nimport { resolveCliPath } from './paths'\nimport { isPortAvailable, formatPortInUseError } from './http/port'\nimport { assertCliDataDirCompatible } from './runtime-compat'\n\nconst program = new Command()\n\nprogram.name('chatlab').description('ChatLab - Chat history analysis tool').version(getVersion(), '-v, --version')\n\nprogram.hook('preAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.name() === 'update') return\n const { checkForUpdatesInteractive } = await import('./update-checker')\n await checkForUpdatesInteractive()\n})\n\nprogram\n .command('update')\n .description('Update ChatLab CLI to the latest version')\n .action(async () => {\n const { performCliSelfUpdate } = await import('./update-checker')\n const result = await performCliSelfUpdate({\n write: (text) => process.stderr.write(text),\n })\n\n if (result.success) {\n console.error(' Updated successfully. Please restart chatlab to use the new version.\\n')\n return\n }\n\n console.error(` Update failed: ${result.error || 'unknown error'}\\n`)\n process.exitCode = 1\n })\n\nprogram\n .command('sessions')\n .description('List all imported chat sessions')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((options) => {\n const { dbManager } = initRuntime()\n const sessionIds = dbManager.listSessionIds()\n\n if (sessionIds.length === 0) {\n console.log('No chat sessions found.')\n console.log(`Data directory: ${dbManager['pathProvider'].getUserDataDir()}`)\n dbManager.closeAll()\n return\n }\n\n const sessions = sessionIds\n .map((id) => {\n const db = dbManager.open(id)\n if (!db) return null\n const meta = getSessionMeta(db)\n if (!meta) return null\n const overview = getSessionOverview(db)\n return { id, ...meta, ...overview }\n })\n .filter(Boolean)\n\n if (options.format === 'json') {\n console.log(JSON.stringify(sessions, null, 2))\n } else {\n console.log(`${sessions.length} session(s) found:\\n`)\n for (const s of sessions) {\n if (!s) continue\n const timeRange = formatTimeRange(s.firstMessageTs, s.lastMessageTs)\n console.log(` ${s.name}`)\n console.log(` ID: ${s.id}`)\n console.log(\n ` Platform: ${s.platform} | Type: ${s.type} | Members: ${s.totalMembers} | Messages: ${s.totalMessages}`\n )\n if (timeRange) console.log(` Range: ${timeRange}`)\n console.log()\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('stats <session-id>')\n .description('Show session statistics overview')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .option('--top <n>', 'Show top N active members', '10')\n .action((sessionId, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n const meta = getSessionMeta(db)\n const overview = getSessionOverview(db)\n const topMembers = getMemberActivity(db).slice(0, parseInt(options.top))\n\n if (options.format === 'json') {\n console.log(JSON.stringify({ meta, overview, topMembers }, null, 2))\n } else {\n console.log(`\\nSession: ${meta?.name}`)\n console.log(`Platform: ${meta?.platform} | Type: ${meta?.type}`)\n console.log(`Total messages: ${overview.totalMessages}`)\n console.log(`Total members: ${overview.totalMembers}`)\n console.log(`Time range: ${formatTimeRange(overview.firstMessageTs, overview.lastMessageTs)}`)\n\n if (topMembers.length > 0) {\n console.log(`\\nActivity ranking (Top ${options.top}):`)\n for (const [i, m] of topMembers.entries()) {\n console.log(` ${i + 1}. ${m.name} - ${m.messageCount} messages (${m.percentage}%)`)\n }\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('search <session-id> <keyword>')\n .description('Search messages by keyword')\n .option('--limit <n>', 'Max results to return', '20')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((sessionId, keyword, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n const limit = parseInt(options.limit)\n const result = searchMessagesLike(db, keyword, { limit })\n\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2))\n } else {\n console.log(\n `Search \"${keyword}\" - ${result.total} result(s)${result.hasMore ? ' (showing first ' + limit + ')' : ''}:\\n`\n )\n for (const msg of result.messages) {\n const time = new Date(msg.timestamp * 1000).toLocaleString()\n console.log(` [${time}] ${msg.senderName}: ${msg.content}`)\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('members <session-id>')\n .description('List session members')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((sessionId, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n const members = getMembers(db)\n\n if (options.format === 'json') {\n console.log(JSON.stringify(members, null, 2))\n } else {\n console.log(`${members.length} member(s):\\n`)\n for (const [i, m] of members.entries()) {\n console.log(` ${i + 1}. ${m.name} (${m.platformId}) - ${m.messageCount} messages`)\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('query <session-id>')\n .description('Execute a read-only SQL query on a session database')\n .requiredOption('--sql <sql>', 'SQL query statement')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((sessionId, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n try {\n const result = executeReadonlySql(db, options.sql)\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2))\n } else {\n if (result.rows.length === 0) {\n console.log('No results.')\n } else {\n printTable(result.columns, result.rows)\n console.log(`\\n${result.rowCount} row(s)${result.truncated ? ' (truncated)' : ''}`)\n }\n }\n } catch (err) {\n console.error(`SQL error: ${err instanceof Error ? err.message : err}`)\n process.exit(1)\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('import <file>')\n .description('Import a chat history file (14+ formats: QQ/WeChat/Telegram/WhatsApp/LINE/Discord/Instagram, etc.)')\n .option('--session-id <id>', 'Specify session ID (auto-generated if omitted)')\n .option('--format <id>', 'Specify format ID (skip auto-detection)')\n .action(async (file, options) => {\n if (!fs.existsSync(file)) {\n console.error(`File not found: ${file}`)\n process.exit(1)\n }\n\n const { streamImport, detectFormat } = await import('./import')\n const { dbManager, pathProvider } = initRuntime()\n const nativeBinding = resolveNativeBinding()\n\n const format = detectFormat(file)\n if (!format && !options.format) {\n console.error(`Unrecognized file format: ${file}`)\n console.error('Use --format <id> to specify manually, or run \"chatlab formats\" to see supported formats')\n process.exit(1)\n }\n\n console.log(`Importing: ${file}`)\n if (format) console.log(` Format: ${format.name} (${format.platform})`)\n\n try {\n const result = await streamImport(dbManager, file, {\n formatId: options.format,\n nativeBinding,\n onProgress: (p) => {\n process.stdout.write(`\\r ${p.stage}: ${p.progress}%`)\n },\n })\n\n if (result.success) {\n console.log(`\\n\\nImport succeeded!`)\n console.log(` Session ID: ${result.sessionId}`)\n console.log(` Messages written: ${result.diagnostics?.messagesWritten ?? 0}`)\n console.log(` Messages skipped: ${result.diagnostics?.messagesSkipped ?? 0}`)\n\n if (result.sessionId) {\n try {\n const { PreferencesManager, createDatabaseManagerAdapter, ownerProfileService } =\n await import('@openchatlab/node-runtime')\n const applied = ownerProfileService.tryApplyOwnerProfile(\n createDatabaseManagerAdapter(dbManager),\n new PreferencesManager(pathProvider.getSystemDir()),\n result.sessionId\n )\n if (applied.applied) {\n console.log(` Owner auto-detected: ${applied.ownerId}`)\n }\n } catch (ownerErr) {\n console.warn(` Owner profile apply skipped: ${ownerErr instanceof Error ? ownerErr.message : ownerErr}`)\n }\n }\n } else {\n console.error(`\\n\\nImport failed: ${result.error}`)\n process.exit(1)\n }\n } catch (err) {\n console.error(`\\n\\nImport error: ${err instanceof Error ? err.message : err}`)\n process.exit(1)\n } finally {\n dbManager.closeAll()\n }\n })\n\nprogram\n .command('formats')\n .description('List all supported chat history formats')\n .action(async () => {\n const { getSupportedFormats } = await import('./import')\n const formats = getSupportedFormats()\n console.log(`${formats.length} supported format(s):\\n`)\n for (const f of formats) {\n console.log(` ${f.id.padEnd(30)} ${f.name} (${f.platform}) [${f.extensions.join(', ')}]`)\n }\n })\n\nprogram\n .command('mcp')\n .description('Start MCP Server (stdio transport, for ClaudeCode / Cursor / AI agents)')\n .action(async () => {\n const { startCliMcpServer } = await import('./mcp')\n await startCliMcpServer()\n })\n\nprogram\n .command('chat')\n .description('Ask ChatLab AI about an imported chat session')\n .option('--session-id <id>', 'Source chat session ID')\n .option('--ai-chat-id <id>', 'Existing AI chat ID to continue')\n .option('-q, --question <text>', 'Question to ask')\n .option('--json', 'Output structured JSON')\n .option('--include-events', 'Include all agent stream chunks in JSON output')\n .option('--no-stream', 'Disable streaming output')\n .option('--locale <locale>', 'AI response locale', 'zh-CN')\n .action(async (options) => {\n const { runChatCommand } = await import('./ai/chat-command')\n const { dbManager, pathProvider } = initRuntime()\n const aiChatManager = new AIChatManager(pathProvider.getAiDataDir(), { nativeBinding: resolveNativeBinding() })\n\n try {\n await runChatCommand(\n {\n sessionId: options.sessionId,\n aiChatId: options.aiChatId,\n question: options.question,\n json: !!options.json,\n stream: options.stream,\n locale: options.locale,\n includeEvents: !!options.includeEvents,\n },\n { dbManager, pathProvider, aiChatManager }\n )\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exitCode = 1\n } finally {\n aiChatManager.close()\n dbManager.closeAll()\n }\n })\n\nprogram\n .command('start')\n .description('Start ChatLab (HTTP API + Web UI)')\n .option('--port <port>', 'Server port', String(DEFAULT_API_PORT))\n .option('--host <host>', 'Listen address', '127.0.0.1')\n .option('--token <token>', 'Custom Bearer Token (reads from config or auto-generates if omitted)')\n .option('--headless', 'API-only mode, do not serve the Web UI')\n .option('--require-auth', 'Require Bearer token for all routes including /_web/*')\n .option('--no-open', 'Do not auto-open the browser')\n .option('--daemon', 'Run as a resident system service (auto-start on login, macOS/Linux)')\n .action(async (options) => {\n // --daemon: install as system service and exit\n if (options.daemon) {\n const { serviceInstall } = await import('./daemon/service')\n serviceInstall({\n port: parseInt(options.port, 10),\n host: options.host,\n token: options.token || undefined,\n headless: options.headless,\n requireAuth: options.requireAuth || undefined,\n })\n return\n }\n\n const { startHttpServer } = await import('./http')\n const port = parseInt(options.port, 10)\n\n let webRoot: string | undefined\n if (!options.headless) {\n const webDir = resolveCliPath('dist-web')\n if (fs.existsSync(webDir)) {\n webRoot = webDir\n } else {\n console.warn('Warning: dist-web/ not found, starting in API-only mode')\n }\n }\n\n try {\n // 启动前预检端口,快速失败,避免无谓的初始化后再报 EADDRINUSE;\n // 置于 try 内确保非 EADDRINUSE 错误(EACCES/EADDRNOTAVAIL 等)\n // 也能走到统一的 Startup failed 错误处理路径。\n if (!(await isPortAvailable(port, options.host))) {\n console.error(formatPortInUseError(port))\n process.exit(1)\n }\n\n const info = await startHttpServer({\n port,\n host: options.host,\n token: options.token || undefined,\n webRoot,\n requireAuth: options.requireAuth || undefined,\n })\n\n const { startPeriodicUpdateCheck } = await import('./update-checker')\n startPeriodicUpdateCheck()\n\n const displayHost = info.host === '0.0.0.0' ? '127.0.0.1' : info.host\n const url = `http://${displayHost}:${info.port}`\n\n console.log(`\\nChatLab v${getVersion()}`)\n if (webRoot) console.log(` Web UI: ${url}/`)\n console.log(` API: ${url}`)\n console.log(` Token: ${info.token}`)\n console.log(`\\nExample:`)\n console.log(` curl -H \"Authorization: Bearer ${info.token}\" ${url}/api/v1/status`)\n\n if (webRoot && options.open) {\n openBrowser(url)\n console.log(`\\nBrowser opened. Press Ctrl+C to stop.\\n`)\n } else {\n console.log(`\\nPress Ctrl+C to stop.\\n`)\n }\n\n const shutdown = async () => {\n console.log('\\nShutting down...')\n const { stopHttpServer } = await import('./http')\n await stopHttpServer()\n process.exit(0)\n }\n\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n if (message.includes('EADDRINUSE')) {\n // 极低概率的 TOCTOU 竞态(预检通过后端口被占),复用统一文案\n console.error(formatPortInUseError(port))\n } else {\n console.error(`Startup failed: ${message}`)\n }\n process.exit(1)\n }\n })\n\nconst configCmd = program.command('config').description('Configuration management')\n\nconfigCmd\n .command('path')\n .description('Show config file path')\n .action(() => {\n console.log(getConfigPath())\n })\n\nconfigCmd\n .command('show')\n .description('Show current configuration')\n .action(() => {\n const config = loadConfig()\n console.log(JSON.stringify(config, null, 2))\n })\n\nprogram\n .command('stop')\n .description('Stop the resident service and remove auto-start (reverse of start --daemon)')\n .action(async () => {\n const { serviceUninstall } = await import('./daemon/service')\n serviceUninstall()\n })\n\nprogram\n .command('status')\n .description('Show resident service status')\n .action(async () => {\n const { getServiceStatus } = await import('./daemon/service')\n const svc = getServiceStatus()\n\n console.log('\\nChatLab Status')\n console.log('─'.repeat(36))\n console.log(` Logs: ${getSystemLogsDir()}`)\n\n if (svc.installed) {\n const portStr = svc.port ? `http://${svc.host ?? '127.0.0.1'}:${svc.port}` : ''\n console.log(` Service: ${svc.running ? 'running' : 'installed (not running)'}`)\n if (portStr) console.log(` Address: ${portStr}`)\n console.log(` Auto-start: enabled`)\n console.log(`\\n Use \\`chatlab stop\\` to remove the service.\\n`)\n } else {\n console.log(` Service: not installed`)\n console.log(` Auto-start: disabled`)\n console.log(`\\n Use \\`chatlab start --daemon\\` to install as a system service.\\n`)\n }\n })\n\n// --- 工具函数 ---\n\nfunction openBrowser(url: string): void {\n try {\n const cmd =\n process.platform === 'darwin'\n ? `open \"${url}\"`\n : process.platform === 'win32'\n ? `start \"\" \"${url}\"`\n : `xdg-open \"${url}\"`\n execSync(cmd, { stdio: 'ignore' })\n } catch {\n console.log(` Open manually: ${url}`)\n }\n}\n\n/**\n * Resolve standalone better-sqlite3 native module path.\n * Used in non-Electron environments to avoid electron-rebuild conflicts.\n */\nfunction resolveNativeBinding(): string | undefined {\n if (process.versions.electron) return undefined\n const nativePath = resolveCliPath('native/better_sqlite3.node')\n if (fs.existsSync(nativePath)) return nativePath\n return undefined\n}\n\nfunction initRuntime() {\n let config = loadConfig()\n const pendingMigration = applyPendingNodeDataDirMigrationIfNeeded()\n if (!pendingMigration.skipped) {\n if (pendingMigration.success) {\n console.log('[Migration] Pending data directory migration completed')\n config = loadConfig()\n } else {\n console.error('[Migration] Pending data directory migration failed:', pendingMigration.error)\n }\n }\n const userDataDir = config.data.user_data_dir || undefined\n const pathProvider = new NodePathProvider(userDataDir)\n pathProvider.ensureAllDirs()\n const runtime = assertCliDataDirCompatible(pathProvider, 'cli')\n\n if (hasPendingElectronDataWarning() || !verifyCliDataPath(pathProvider.getDatabaseDir())) {\n printElectronDataError()\n process.exit(1)\n }\n\n const nativeBinding = resolveNativeBinding()\n const dbManager = new DatabaseManager(pathProvider, { nativeBinding, runtime })\n return { config, pathProvider, dbManager }\n}\n\nfunction printElectronDataError(): void {\n console.error('\\n' + '='.repeat(68))\n console.error(' ChatLab: Electron desktop data not found')\n console.error('='.repeat(68))\n console.error('')\n console.error(' Detected that ChatLab desktop app was installed on this machine,')\n console.error(' but could not locate your chat databases.')\n console.error('')\n console.error(' This usually means you changed the data directory in desktop settings.')\n console.error('')\n console.error(' To fix this, choose one of:')\n console.error('')\n console.error(' 1. Open ChatLab desktop app — it will auto-migrate your data')\n console.error(' 2. Set the data directory manually:')\n console.error(' export CHATLAB_DATA_DIR=\"/path/to/your/data\"')\n console.error(' 3. Edit ~/.chatlab/config.toml:')\n console.error(' [data]')\n console.error(' user_data_dir = \"/path/to/your/data\"')\n console.error('')\n console.error('='.repeat(68) + '\\n')\n}\n\nfunction formatTimeRange(first: number | null, last: number | null): string {\n if (!first || !last) return 'Unknown'\n const from = new Date(first * 1000).toLocaleDateString()\n const to = new Date(last * 1000).toLocaleDateString()\n return `${from} ~ ${to}`\n}\n\nfunction printTable(columns: string[], rows: Record<string, unknown>[]): void {\n const widths = columns.map((col) => {\n const maxData = rows.reduce((max, row) => {\n const val = String(row[col] ?? '')\n return Math.max(max, val.length)\n }, 0)\n return Math.max(col.length, Math.min(maxData, 40))\n })\n\n const header = columns.map((col, i) => col.padEnd(widths[i])).join(' | ')\n const separator = widths.map((w) => '-'.repeat(w)).join('-+-')\n console.log(header)\n console.log(separator)\n\n for (const row of rows) {\n const line = columns\n .map((col, i) => {\n const val = String(row[col] ?? '')\n return val.length > 40 ? val.slice(0, 37) + '...' : val.padEnd(widths[i])\n })\n .join(' | ')\n console.log(line)\n }\n}\n\n/** CLI entry function */\nexport function run(argv?: string[]): void {\n // Logs go to ~/.chatlab/logs/app.log regardless of configured user data dir.\n initAppLogger(getSystemLogsDir())\n process.on('uncaughtException', (error) => {\n console.error('Uncaught Exception:', error)\n appLogger.error('crash', 'uncaughtException', error)\n process.exit(1)\n })\n process.on('unhandledRejection', (reason) => {\n console.error('Unhandled Rejection:', reason)\n appLogger.error('crash', 'unhandledRejection', reason)\n process.exit(1)\n })\n program.parse(argv)\n}\n\n// Auto-execute when run directly as a script\nconst isDirectRun = process.argv[1]?.endsWith('cli.ts') || process.argv[1]?.endsWith('cli.js')\nif (isDirectRun) {\n run()\n}\n","/**\n * 端口可用性检测与错误文案\n */\n\nimport * as net from 'net'\n\n/**\n * 检测指定端口在给定 host 上是否可用。\n * 使用 net.createServer() 试探性绑定,无副作用(成功后立即释放)。\n */\nexport function isPortAvailable(port: number, host: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n resolve(false)\n } else {\n reject(err)\n }\n })\n server.once('listening', () => server.close(() => resolve(true)))\n server.listen(port, host)\n })\n}\n\n/**\n * 返回端口被占用时统一的友好报错文案。\n */\nexport function formatPortInUseError(port: number): string {\n return [\n ``,\n ` ✖ Error: port ${port} is already in use.`,\n ``,\n ` Another process (possibly a ChatLab instance) is using this port. You can:`,\n ` • Use another port: chatlab start --port <port>`,\n ` • Find the process: lsof -iTCP:${port} -sTCP:LISTEN`,\n ``,\n ].join('\\n')\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/http/port.ts"],"sourcesContent":["/**\n * ChatLab CLI entry point\n *\n * Dev: pnpm --filter chatlab-cli run cli -- sessions\n */\n\nimport * as fs from 'fs'\nimport { execSync } from 'child_process'\nimport { Command } from 'commander'\nimport { DEFAULT_API_PORT, loadConfig, getConfigPath } from '@openchatlab/config'\nimport {\n NodePathProvider,\n DatabaseManager,\n AIChatManager,\n applyPendingNodeDataDirMigrationIfNeeded,\n hasPendingElectronDataWarning,\n verifyCliDataPath,\n initAppLogger,\n appLogger,\n getSystemLogsDir,\n} from '@openchatlab/node-runtime'\nimport {\n getSessionMeta,\n getSessionOverview,\n getMemberActivity,\n searchMessagesLike,\n getMembers,\n executeReadonlySql,\n} from '@openchatlab/core'\nimport { getVersion } from './version'\nimport { resolveCliPath } from './paths'\nimport { isPortAvailable, formatPortInUseError } from './http/port'\nimport { assertCliDataDirCompatible } from './runtime-compat'\n\nconst program = new Command()\n\nprogram.name('chatlab').description('ChatLab - Chat history analysis tool').version(getVersion(), '-v, --version')\n\nprogram.hook('preAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.name() === 'update') return\n const { checkForUpdatesInteractive } = await import('./update-checker')\n await checkForUpdatesInteractive()\n})\n\nprogram\n .command('update')\n .description('Update ChatLab CLI to the latest version')\n .action(async () => {\n const { performCliSelfUpdate } = await import('./update-checker')\n const result = await performCliSelfUpdate({\n write: (text) => process.stderr.write(text),\n })\n\n if (result.success) {\n console.error(' Updated successfully. Please restart chatlab to use the new version.\\n')\n return\n }\n\n console.error(` Update failed: ${result.error || 'unknown error'}\\n`)\n process.exitCode = 1\n })\n\nprogram\n .command('sessions')\n .description('List all imported chat sessions')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((options) => {\n const { dbManager } = initRuntime()\n const sessionIds = dbManager.listSessionIds()\n\n if (sessionIds.length === 0) {\n console.log('No chat sessions found.')\n console.log(`Data directory: ${dbManager['pathProvider'].getUserDataDir()}`)\n dbManager.closeAll()\n return\n }\n\n const sessions = sessionIds\n .map((id) => {\n const db = dbManager.open(id)\n if (!db) return null\n const meta = getSessionMeta(db)\n if (!meta) return null\n const overview = getSessionOverview(db)\n return { id, ...meta, ...overview }\n })\n .filter(Boolean)\n\n if (options.format === 'json') {\n console.log(JSON.stringify(sessions, null, 2))\n } else {\n console.log(`${sessions.length} session(s) found:\\n`)\n for (const s of sessions) {\n if (!s) continue\n const timeRange = formatTimeRange(s.firstMessageTs, s.lastMessageTs)\n console.log(` ${s.name}`)\n console.log(` ID: ${s.id}`)\n console.log(\n ` Platform: ${s.platform} | Type: ${s.type} | Members: ${s.totalMembers} | Messages: ${s.totalMessages}`\n )\n if (timeRange) console.log(` Range: ${timeRange}`)\n console.log()\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('stats <session-id>')\n .description('Show session statistics overview')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .option('--top <n>', 'Show top N active members', '10')\n .action((sessionId, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n const meta = getSessionMeta(db)\n const overview = getSessionOverview(db)\n const topMembers = getMemberActivity(db).slice(0, parseInt(options.top))\n\n if (options.format === 'json') {\n console.log(JSON.stringify({ meta, overview, topMembers }, null, 2))\n } else {\n console.log(`\\nSession: ${meta?.name}`)\n console.log(`Platform: ${meta?.platform} | Type: ${meta?.type}`)\n console.log(`Total messages: ${overview.totalMessages}`)\n console.log(`Total members: ${overview.totalMembers}`)\n console.log(`Time range: ${formatTimeRange(overview.firstMessageTs, overview.lastMessageTs)}`)\n\n if (topMembers.length > 0) {\n console.log(`\\nActivity ranking (Top ${options.top}):`)\n for (const [i, m] of topMembers.entries()) {\n console.log(` ${i + 1}. ${m.name} - ${m.messageCount} messages (${m.percentage}%)`)\n }\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('search <session-id> <keyword>')\n .description('Search messages by keyword')\n .option('--limit <n>', 'Max results to return', '20')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((sessionId, keyword, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n const limit = parseInt(options.limit)\n const result = searchMessagesLike(db, keyword, { limit })\n\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2))\n } else {\n console.log(\n `Search \"${keyword}\" - ${result.total} result(s)${result.hasMore ? ' (showing first ' + limit + ')' : ''}:\\n`\n )\n for (const msg of result.messages) {\n const time = new Date(msg.timestamp * 1000).toLocaleString()\n console.log(` [${time}] ${msg.senderName}: ${msg.content}`)\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('members <session-id>')\n .description('List session members')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((sessionId, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n const members = getMembers(db)\n\n if (options.format === 'json') {\n console.log(JSON.stringify(members, null, 2))\n } else {\n console.log(`${members.length} member(s):\\n`)\n for (const [i, m] of members.entries()) {\n console.log(` ${i + 1}. ${m.name} (${m.platformId}) - ${m.messageCount} messages`)\n }\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('query <session-id>')\n .description('Execute a read-only SQL query on a session database')\n .requiredOption('--sql <sql>', 'SQL query statement')\n .option('--format <format>', 'Output format (table|json)', 'table')\n .action((sessionId, options) => {\n const { dbManager } = initRuntime()\n const db = dbManager.open(sessionId)\n if (!db) {\n console.error(`Session ${sessionId} not found`)\n process.exit(1)\n }\n\n try {\n const result = executeReadonlySql(db, options.sql)\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2))\n } else {\n if (result.rows.length === 0) {\n console.log('No results.')\n } else {\n printTable(result.columns, result.rows)\n console.log(`\\n${result.rowCount} row(s)${result.truncated ? ' (truncated)' : ''}`)\n }\n }\n } catch (err) {\n console.error(`SQL error: ${err instanceof Error ? err.message : err}`)\n process.exit(1)\n }\n\n dbManager.closeAll()\n })\n\nprogram\n .command('import <file>')\n .description('Import a chat history file (14+ formats: QQ/WeChat/Telegram/WhatsApp/LINE/Discord/Instagram, etc.)')\n .option('--session-id <id>', 'Specify session ID (auto-generated if omitted)')\n .option('--format <id>', 'Specify format ID (skip auto-detection)')\n .action(async (file, options) => {\n if (!fs.existsSync(file)) {\n console.error(`File not found: ${file}`)\n process.exit(1)\n }\n\n const { streamImport, detectFormat } = await import('./import')\n const { dbManager, pathProvider } = initRuntime()\n const nativeBinding = resolveNativeBinding()\n\n const format = detectFormat(file)\n if (!format && !options.format) {\n console.error(`Unrecognized file format: ${file}`)\n console.error('Use --format <id> to specify manually, or run \"chatlab formats\" to see supported formats')\n process.exit(1)\n }\n\n console.log(`Importing: ${file}`)\n if (format) console.log(` Format: ${format.name} (${format.platform})`)\n\n try {\n const result = await streamImport(dbManager, file, {\n formatId: options.format,\n nativeBinding,\n onProgress: (p) => {\n process.stdout.write(`\\r ${p.stage}: ${p.progress}%`)\n },\n })\n\n if (result.success) {\n console.log(`\\n\\nImport succeeded!`)\n console.log(` Session ID: ${result.sessionId}`)\n console.log(` Messages written: ${result.diagnostics?.messagesWritten ?? 0}`)\n console.log(` Messages skipped: ${result.diagnostics?.messagesSkipped ?? 0}`)\n\n if (result.sessionId) {\n try {\n const { PreferencesManager, createDatabaseManagerAdapter, ownerProfileService } =\n await import('@openchatlab/node-runtime')\n const applied = ownerProfileService.tryApplyOwnerProfile(\n createDatabaseManagerAdapter(dbManager),\n new PreferencesManager(pathProvider.getSystemDir()),\n result.sessionId\n )\n if (applied.applied) {\n console.log(` Owner auto-detected: ${applied.ownerId}`)\n }\n } catch (ownerErr) {\n console.warn(` Owner profile apply skipped: ${ownerErr instanceof Error ? ownerErr.message : ownerErr}`)\n }\n }\n } else {\n console.error(`\\n\\nImport failed: ${result.error}`)\n process.exit(1)\n }\n } catch (err) {\n console.error(`\\n\\nImport error: ${err instanceof Error ? err.message : err}`)\n process.exit(1)\n } finally {\n dbManager.closeAll()\n }\n })\n\nprogram\n .command('formats')\n .description('List all supported chat history formats')\n .action(async () => {\n const { getSupportedFormats } = await import('./import')\n const formats = getSupportedFormats()\n console.log(`${formats.length} supported format(s):\\n`)\n for (const f of formats) {\n console.log(` ${f.id.padEnd(30)} ${f.name} (${f.platform}) [${f.extensions.join(', ')}]`)\n }\n })\n\nprogram\n .command('mcp')\n .description('Start MCP Server (stdio transport, for ClaudeCode / Cursor / AI agents)')\n .action(async () => {\n const { startCliMcpServer } = await import('./mcp')\n await startCliMcpServer()\n })\n\nprogram\n .command('chat')\n .description('Ask ChatLab AI about an imported chat session')\n .option('--session-id <id>', 'Source chat session ID')\n .option('--ai-chat-id <id>', 'Existing AI chat ID to continue')\n .option('-q, --question <text>', 'Question to ask')\n .option('--json', 'Output structured JSON')\n .option('--include-events', 'Include all agent stream chunks in JSON output')\n .option('--no-stream', 'Disable streaming output')\n .option('--locale <locale>', 'AI response locale', 'zh-CN')\n .action(async (options) => {\n const { runChatCommand } = await import('./ai/chat-command')\n const { dbManager, pathProvider } = initRuntime()\n const aiChatManager = new AIChatManager(pathProvider.getAiDataDir(), { nativeBinding: resolveNativeBinding() })\n\n try {\n await runChatCommand(\n {\n sessionId: options.sessionId,\n aiChatId: options.aiChatId,\n question: options.question,\n json: !!options.json,\n stream: options.stream,\n locale: options.locale,\n includeEvents: !!options.includeEvents,\n },\n { dbManager, pathProvider, aiChatManager }\n )\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exitCode = 1\n } finally {\n aiChatManager.close()\n dbManager.closeAll()\n }\n })\n\nprogram\n .command('start')\n .description('Start ChatLab (HTTP API + Web UI)')\n .option('--port <port>', 'Server port', String(DEFAULT_API_PORT))\n .option('--host <host>', 'Listen address', '127.0.0.1')\n .option('--token <token>', 'Custom Bearer Token (reads from config or auto-generates if omitted)')\n .option('--headless', 'API-only mode, do not serve the Web UI')\n .option('--require-auth', 'Require Bearer token for all routes including /_web/*')\n .option('--no-open', 'Do not auto-open the browser')\n .option('--daemon', 'Run as a resident system service (auto-start on login, macOS/Linux)')\n .action(async (options) => {\n // --daemon: install as system service and exit\n if (options.daemon) {\n const { serviceInstall } = await import('./daemon/service')\n serviceInstall({\n port: parseInt(options.port, 10),\n host: options.host,\n token: options.token || undefined,\n headless: options.headless,\n requireAuth: options.requireAuth || undefined,\n })\n return\n }\n\n const { startHttpServer } = await import('./http')\n const port = parseInt(options.port, 10)\n\n let webRoot: string | undefined\n if (!options.headless) {\n const webDir = resolveCliPath('dist-web')\n if (fs.existsSync(webDir)) {\n webRoot = webDir\n } else {\n console.warn('Warning: dist-web/ not found, starting in API-only mode')\n }\n }\n\n try {\n // 启动前预检端口,快速失败,避免无谓的初始化后再报 EADDRINUSE;\n // 置于 try 内确保非 EADDRINUSE 错误(EACCES/EADDRNOTAVAIL 等)\n // 也能走到统一的 Startup failed 错误处理路径。\n if (!(await isPortAvailable(port, options.host))) {\n console.error(formatPortInUseError(port))\n process.exit(1)\n }\n\n const info = await startHttpServer({\n port,\n host: options.host,\n token: options.token || undefined,\n webRoot,\n requireAuth: options.requireAuth || undefined,\n })\n\n const { startPeriodicUpdateCheck } = await import('./update-checker')\n startPeriodicUpdateCheck()\n\n const displayHost = info.host === '0.0.0.0' ? '127.0.0.1' : info.host\n const url = `http://${displayHost}:${info.port}`\n\n console.log(`\\nChatLab v${getVersion()}`)\n if (webRoot) console.log(` Web UI: ${url}/`)\n console.log(` API: ${url}`)\n console.log(` Token: ${info.token}`)\n console.log(`\\nExample:`)\n console.log(` curl -H \"Authorization: Bearer ${info.token}\" ${url}/api/v1/status`)\n\n if (webRoot && options.open) {\n openBrowser(url)\n console.log(`\\nBrowser opened. Press Ctrl+C to stop.\\n`)\n } else {\n console.log(`\\nPress Ctrl+C to stop.\\n`)\n }\n\n const shutdown = async () => {\n console.log('\\nShutting down...')\n const { stopHttpServer } = await import('./http')\n await stopHttpServer()\n process.exit(0)\n }\n\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n if (message.includes('EADDRINUSE')) {\n // 极低概率的 TOCTOU 竞态(预检通过后端口被占),复用统一文案\n console.error(formatPortInUseError(port))\n } else {\n console.error(`Startup failed: ${message}`)\n }\n process.exit(1)\n }\n })\n\nconst configCmd = program.command('config').description('Configuration management')\n\nconfigCmd\n .command('path')\n .description('Show config file path')\n .action(() => {\n console.log(getConfigPath())\n })\n\nconfigCmd\n .command('show')\n .description('Show current configuration')\n .action(() => {\n const config = loadConfig()\n console.log(JSON.stringify(config, null, 2))\n })\n\nprogram\n .command('stop')\n .description('Stop the resident service and remove auto-start (reverse of start --daemon)')\n .action(async () => {\n const { serviceUninstall } = await import('./daemon/service')\n serviceUninstall()\n })\n\nprogram\n .command('status')\n .description('Show resident service status')\n .action(async () => {\n const { getServiceStatus } = await import('./daemon/service')\n const svc = getServiceStatus()\n\n console.log('\\nChatLab Status')\n console.log('─'.repeat(36))\n console.log(` Logs: ${getSystemLogsDir()}`)\n\n if (svc.installed) {\n const portStr = svc.port ? `http://${svc.host ?? '127.0.0.1'}:${svc.port}` : ''\n console.log(` Service: ${svc.running ? 'running' : 'installed (not running)'}`)\n if (portStr) console.log(` Address: ${portStr}`)\n console.log(` Auto-start: enabled`)\n console.log(`\\n Use \\`chatlab stop\\` to remove the service.\\n`)\n } else {\n console.log(` Service: not installed`)\n console.log(` Auto-start: disabled`)\n console.log(`\\n Use \\`chatlab start --daemon\\` to install as a system service.\\n`)\n }\n })\n\n// --- 工具函数 ---\n\nfunction openBrowser(url: string): void {\n try {\n const cmd =\n process.platform === 'darwin'\n ? `open \"${url}\"`\n : process.platform === 'win32'\n ? `start \"\" \"${url}\"`\n : `xdg-open \"${url}\"`\n execSync(cmd, { stdio: 'ignore' })\n } catch {\n console.log(` Open manually: ${url}`)\n }\n}\n\n/**\n * Resolve standalone better-sqlite3 native module path.\n * Used in non-Electron environments to avoid electron-rebuild conflicts.\n */\nfunction resolveNativeBinding(): string | undefined {\n if (process.versions.electron) return undefined\n const nativePath = resolveCliPath('native/better_sqlite3.node')\n if (fs.existsSync(nativePath)) return nativePath\n return undefined\n}\n\nfunction initRuntime() {\n let config = loadConfig()\n const pendingMigration = applyPendingNodeDataDirMigrationIfNeeded()\n if (!pendingMigration.skipped) {\n if (pendingMigration.success) {\n console.log('[Migration] Pending data directory migration completed')\n config = loadConfig()\n } else {\n console.error('[Migration] Pending data directory migration failed:', pendingMigration.error)\n }\n }\n const userDataDir = config.data.user_data_dir || undefined\n const pathProvider = new NodePathProvider(userDataDir)\n pathProvider.ensureAllDirs()\n const runtime = assertCliDataDirCompatible(pathProvider, 'cli')\n\n if (hasPendingElectronDataWarning() || !verifyCliDataPath(pathProvider.getDatabaseDir())) {\n printElectronDataError()\n process.exit(1)\n }\n\n const nativeBinding = resolveNativeBinding()\n const dbManager = new DatabaseManager(pathProvider, { nativeBinding, runtime })\n return { config, pathProvider, dbManager }\n}\n\nfunction printElectronDataError(): void {\n console.error('\\n' + '='.repeat(68))\n console.error(' ChatLab: Electron desktop data not found')\n console.error('='.repeat(68))\n console.error('')\n console.error(' Detected that ChatLab desktop app was installed on this machine,')\n console.error(' but could not locate your chat databases.')\n console.error('')\n console.error(' This usually means you changed the data directory in desktop settings.')\n console.error('')\n console.error(' To fix this, choose one of:')\n console.error('')\n console.error(' 1. Open ChatLab desktop app — it will auto-migrate your data')\n console.error(' 2. Set the data directory manually:')\n console.error(' export CHATLAB_DATA_DIR=\"/path/to/your/data\"')\n console.error(' 3. Edit ~/.chatlab/config.toml:')\n console.error(' [data]')\n console.error(' user_data_dir = \"/path/to/your/data\"')\n console.error('')\n console.error('='.repeat(68) + '\\n')\n}\n\nfunction formatTimeRange(first: number | null, last: number | null): string {\n if (!first || !last) return 'Unknown'\n const from = new Date(first * 1000).toLocaleDateString()\n const to = new Date(last * 1000).toLocaleDateString()\n return `${from} ~ ${to}`\n}\n\nfunction printTable(columns: string[], rows: Record<string, unknown>[]): void {\n const widths = columns.map((col) => {\n const maxData = rows.reduce((max, row) => {\n const val = String(row[col] ?? '')\n return Math.max(max, val.length)\n }, 0)\n return Math.max(col.length, Math.min(maxData, 40))\n })\n\n const header = columns.map((col, i) => col.padEnd(widths[i])).join(' | ')\n const separator = widths.map((w) => '-'.repeat(w)).join('-+-')\n console.log(header)\n console.log(separator)\n\n for (const row of rows) {\n const line = columns\n .map((col, i) => {\n const val = String(row[col] ?? '')\n return val.length > 40 ? val.slice(0, 37) + '...' : val.padEnd(widths[i])\n })\n .join(' | ')\n console.log(line)\n }\n}\n\n/** CLI entry function */\nexport function run(argv?: string[]): void {\n // Logs go to ~/.chatlab/logs/app.log regardless of configured user data dir.\n initAppLogger(getSystemLogsDir())\n process.on('uncaughtException', (error) => {\n console.error('Uncaught Exception:', error)\n appLogger.error('crash', 'uncaughtException', error)\n process.exit(1)\n })\n process.on('unhandledRejection', (reason) => {\n console.error('Unhandled Rejection:', reason)\n appLogger.error('crash', 'unhandledRejection', reason)\n process.exit(1)\n })\n program.parse(argv)\n}\n\n// Auto-execute when run directly as a script\nconst isDirectRun = process.argv[1]?.endsWith('cli.ts') || process.argv[1]?.endsWith('cli.js')\nif (isDirectRun) {\n run()\n}\n","/**\n * 端口可用性检测与错误文案\n */\n\nimport * as net from 'net'\n\n/**\n * 检测指定端口在给定 host 上是否可用。\n * 使用 net.createServer() 试探性绑定,无副作用(成功后立即释放)。\n */\nexport function isPortAvailable(port: number, host: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n resolve(false)\n } else {\n reject(err)\n }\n })\n server.once('listening', () => server.close(() => resolve(true)))\n server.listen(port, host)\n })\n}\n\n/**\n * 返回端口被占用时统一的友好报错文案。\n */\nexport function formatPortInUseError(port: number): string {\n return [\n ``,\n ` ✖ Error: port ${port} is already in use.`,\n ``,\n ` Another process (possibly a ChatLab instance) is using this port. You can:`,\n ` • Use another port: chatlab start --port <port>`,\n ` • Find the process: lsof -iTCP:${port} -sTCP:LISTEN`,\n ``,\n ].join('\\n')\n}\n"],"mappings":"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","names":[]}
@@ -26,7 +26,7 @@ import {
26
26
  getSessionOverview,
27
27
  getWeekdayActivity,
28
28
  searchMessagesByKeywords
29
- } from "./chunk-ZVDOFWL7.mjs";
29
+ } from "./chunk-WPI6YSAR.mjs";
30
30
 
31
31
  // ../../packages/tools/src/definitions/sql-query.ts
32
32
  var inputSchema = {
@@ -1828,4 +1828,4 @@ export {
1828
1828
  MCP_TOOL_REGISTRY,
1829
1829
  CoreDataProvider
1830
1830
  };
1831
- //# sourceMappingURL=chunk-3QBVO4J7.mjs.map
1831
+ //# sourceMappingURL=chunk-CIB23U32.mjs.map