chatlab-cli 0.21.1 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +5 -5
  2. package/dist/{chunk-2AIOU3PW.mjs → chunk-6NB475AA.mjs} +12 -3
  3. package/dist/chunk-6NB475AA.mjs.map +1 -0
  4. package/dist/{chunk-OZWXLRJL.mjs → chunk-LZ3W6NS5.mjs} +24 -15
  5. package/dist/chunk-LZ3W6NS5.mjs.map +1 -0
  6. package/dist/{chunk-OQVKZTVD.mjs → chunk-OC2W5Q5T.mjs} +2 -2
  7. package/dist/{chunk-AIR7EAF4.mjs → chunk-QRC3RSER.mjs} +2 -2
  8. package/dist/{chunk-7HQWGLX6.mjs → chunk-SQKT45MM.mjs} +174 -120
  9. package/dist/chunk-SQKT45MM.mjs.map +1 -0
  10. package/dist/chunk-VSOWNKPA.mjs +49 -0
  11. package/dist/{chunk-LI4X52E7.mjs → chunk-XPBPKH6B.mjs} +350 -100
  12. package/dist/chunk-XPBPKH6B.mjs.map +1 -0
  13. package/dist/{chunk-4GI2UPCS.mjs → chunk-Z2LYMKCC.mjs} +2 -2
  14. package/dist/cli.mjs +4 -3
  15. package/dist/{http-DHQI4G5J.mjs → http-O5P4BYXU.mjs} +8 -7
  16. package/dist/{import-CQWGIMZQ.mjs → import-BDLL3DG7.mjs} +5 -4
  17. package/dist/index.mjs +8 -7
  18. package/dist/{mcp-7Q3FEI3Z.mjs → mcp-L2TPZFE7.mjs} +8 -7
  19. package/dist/mcp-L2TPZFE7.mjs.map +1 -0
  20. package/dist/{src-QBT5SYW5.mjs → src-FVJL5ENA.mjs} +3 -2
  21. package/dist/{stream-import-VG7RP6KJ.mjs → stream-import-ZTEW3YVL.mjs} +4 -3
  22. package/dist/stream-import-ZTEW3YVL.mjs.map +1 -0
  23. package/dist/update-checker-MQMQ6A4B.mjs +191 -0
  24. package/dist/update-checker-MQMQ6A4B.mjs.map +1 -0
  25. package/dist-web/assets/{DebugToolsPanel-CoBtqb--.css → DebugToolsPanel-DkbsB6lr.css} +1 -1
  26. package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-CpFGhsl5.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-CqacsKDU.js} +5 -5
  27. package/dist-web/assets/{EChartWordcloud-BYLFxPAX.js → EChartWordcloud-Ubal_aYg.js} +1 -1
  28. package/dist-web/assets/{MessageExportModal-DTgxz1eQ.js → MessageExportModal-D1GY6WSV.js} +1 -1
  29. package/dist-web/assets/{electron-CTK4NJag.js → electron-CRSL7qPM.js} +1 -1
  30. package/dist-web/assets/{electron-H65bUnhW.js → electron-CsUM2O_Y.js} +1 -1
  31. package/dist-web/assets/{fetch-CTZXLLcn.js → fetch-BOogCPfg.js} +1 -1
  32. package/dist-web/assets/{fetch-C2vUkdnA.js → fetch-CxwnEEqk.js} +1 -1
  33. package/dist-web/assets/index-CM29Kc4p.js +173 -0
  34. package/dist-web/assets/index-D183wYuz.js +7 -0
  35. package/dist-web/assets/{index-DeG0EHOT.js → index-DOwQB7In.js} +1 -1
  36. package/dist-web/assets/index-DSpvXged.css +1 -0
  37. package/dist-web/assets/{index-C4B0hv6C.js → index-DTxRy2FH.js} +4 -4
  38. package/dist-web/assets/{index-DuhN8jAf.js → index-grds3iG-.js} +2 -2
  39. package/dist-web/assets/logo-DXIuG_WE.svg +17 -0
  40. package/dist-web/assets/{vendor-echarts-C13vDgZW.js → vendor-echarts-C5u62NnM.js} +1 -1
  41. package/dist-web/assets/{vendor-echarts-wordcloud-uVdwYsYa.js → vendor-echarts-wordcloud-CZ9gsX8l.js} +1 -1
  42. package/dist-web/assets/{vendor-nuxt-ui-CYMNNdeD.js → vendor-nuxt-ui-7OAuiz_i.js} +1 -1
  43. package/dist-web/assets/{vendor-zrender-5DcYjSZk.js → vendor-zrender-DFl4U2Oe.js} +1 -1
  44. package/dist-web/assets/{web-DImo6Kjz.js → web-Cx5APyCN.js} +1 -1
  45. package/dist-web/index.html +3 -3
  46. package/package.json +4 -3
  47. package/dist/chunk-2AIOU3PW.mjs.map +0 -1
  48. package/dist/chunk-7HQWGLX6.mjs.map +0 -1
  49. package/dist/chunk-LI4X52E7.mjs.map +0 -1
  50. package/dist/chunk-OZWXLRJL.mjs.map +0 -1
  51. package/dist/mcp-7Q3FEI3Z.mjs.map +0 -1
  52. package/dist-web/assets/index-B8867dX7.css +0 -1
  53. package/dist-web/assets/index-DUXf21MT.js +0 -173
  54. package/dist-web/assets/index-DZiH2cC1.js +0 -7
  55. /package/dist/{chunk-OQVKZTVD.mjs.map → chunk-OC2W5Q5T.mjs.map} +0 -0
  56. /package/dist/{chunk-AIR7EAF4.mjs.map → chunk-QRC3RSER.mjs.map} +0 -0
  57. /package/dist/{http-DHQI4G5J.mjs.map → chunk-VSOWNKPA.mjs.map} +0 -0
  58. /package/dist/{chunk-4GI2UPCS.mjs.map → chunk-Z2LYMKCC.mjs.map} +0 -0
  59. /package/dist/{import-CQWGIMZQ.mjs.map → http-O5P4BYXU.mjs.map} +0 -0
  60. /package/dist/{src-QBT5SYW5.mjs.map → import-BDLL3DG7.mjs.map} +0 -0
  61. /package/dist/{stream-import-VG7RP6KJ.mjs.map → src-FVJL5ENA.mjs.map} +0 -0
package/README.md CHANGED
@@ -6,9 +6,9 @@
6
6
 
7
7
  Your chat history, finally yours.
8
8
 
9
- English | [简体中文](./docs/README.zh-CN.md)
9
+ English | [简体中文](./README.zh-CN.md)
10
10
 
11
- [Official Website](https://chatlab.fun/) · [Documentation](https://chatlab.fun/usage/) · [Roadmap](https://chatlab.fun/cn/roadmap/tasks)
11
+ [Official Website](https://chatlab.fun/) · [Documentation](https://docs.chatlab.fun/en/usage/) · [Roadmap](https://chatlab.fun/cn/roadmap/tasks)
12
12
 
13
13
  </div>
14
14
 
@@ -27,9 +27,9 @@ Currently supported: **WhatsApp, LINE, WeChat, QQ, Discord, Instagram, and Teleg
27
27
  ## Usage Guides
28
28
 
29
29
  - [Download Guide](https://chatlab.fun/?type=download)
30
- - [Chat Record Export Guide](https://chatlab.fun/usage/how-to-export)
31
- - [Standardized Format Specification](https://chatlab.fun/standard/chatlab-format)
32
- - [Troubleshooting Guide](https://chatlab.fun/usage/troubleshooting)
30
+ - [Chat Record Export Guide](https://docs.chatlab.fun/en/usage/how-to-export)
31
+ - [Standardized Format Specification](https://docs.chatlab.fun/en/standard/chatlab-format)
32
+ - [Troubleshooting Guide](https://docs.chatlab.fun/en/usage/troubleshooting)
33
33
 
34
34
  ## Preview
35
35
 
@@ -5,14 +5,22 @@ const require = __createRequire(import.meta.url);
5
5
  const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __pathDirname(__filename);
7
7
 
8
+ // src/paths.ts
9
+ import path from "path";
10
+ import { fileURLToPath } from "url";
11
+ function resolveCliPath(...segments) {
12
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
13
+ const packageRoot = path.basename(moduleDir) === "dist" ? path.dirname(moduleDir) : path.resolve(moduleDir, "..");
14
+ return path.resolve(packageRoot, ...segments);
15
+ }
16
+
8
17
  // src/version.ts
9
18
  import { readFileSync } from "fs";
10
- import { resolve } from "path";
11
19
  var cached;
12
20
  function getVersion() {
13
21
  if (cached) return cached;
14
22
  try {
15
- const pkgPath = resolve(__dirname, "../package.json");
23
+ const pkgPath = resolveCliPath("package.json");
16
24
  cached = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
17
25
  } catch {
18
26
  cached = "0.0.0-dev";
@@ -21,6 +29,7 @@ function getVersion() {
21
29
  }
22
30
 
23
31
  export {
32
+ resolveCliPath,
24
33
  getVersion
25
34
  };
26
- //# sourceMappingURL=chunk-2AIOU3PW.mjs.map
35
+ //# sourceMappingURL=chunk-6NB475AA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/paths.ts","../src/version.ts"],"sourcesContent":["import path from 'path'\nimport { fileURLToPath } from 'url'\n\nexport function resolveCliPath(...segments: string[]): string {\n const moduleDir = path.dirname(fileURLToPath(import.meta.url))\n const packageRoot = path.basename(moduleDir) === 'dist' ? path.dirname(moduleDir) : path.resolve(moduleDir, '..')\n return path.resolve(packageRoot, ...segments)\n}\n","import { readFileSync } from 'fs'\nimport { resolveCliPath } from './paths'\n\nlet cached: string | undefined\n\n/**\n * Read version from apps/cli/package.json at runtime.\n * Works for both tsx dev (src/) and bundled (dist/).\n */\nexport function getVersion(): string {\n if (cached) return cached\n try {\n const pkgPath = resolveCliPath('package.json')\n cached = JSON.parse(readFileSync(pkgPath, 'utf-8')).version\n } catch {\n cached = '0.0.0-dev'\n }\n return cached!\n}\n"],"mappings":";;;;;;;;AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAEvB,SAAS,kBAAkB,UAA4B;AAC5D,QAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAC7D,QAAM,cAAc,KAAK,SAAS,SAAS,MAAM,SAAS,KAAK,QAAQ,SAAS,IAAI,KAAK,QAAQ,WAAW,IAAI;AAChH,SAAO,KAAK,QAAQ,aAAa,GAAG,QAAQ;AAC9C;;;ACPA,SAAS,oBAAoB;AAG7B,IAAI;AAMG,SAAS,aAAqB;AACnC,MAAI,OAAQ,QAAO;AACnB,MAAI;AACF,UAAM,UAAU,eAAe,cAAc;AAC7C,aAAS,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC,EAAE;AAAA,EACtD,QAAQ;AACN,aAAS;AAAA,EACX;AACA,SAAO;AACT;","names":[]}
@@ -5,8 +5,9 @@ const require = __createRequire(import.meta.url);
5
5
  const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __pathDirname(__filename);
7
7
  import {
8
- getVersion
9
- } from "./chunk-2AIOU3PW.mjs";
8
+ getVersion,
9
+ resolveCliPath
10
+ } from "./chunk-6NB475AA.mjs";
10
11
  import {
11
12
  DEFAULT_API_PORT,
12
13
  DatabaseManager,
@@ -21,7 +22,7 @@ import {
21
22
  loadConfig,
22
23
  searchMessagesLike,
23
24
  verifyCliDataPath
24
- } from "./chunk-7HQWGLX6.mjs";
25
+ } from "./chunk-SQKT45MM.mjs";
25
26
 
26
27
  // src/cli.ts
27
28
  import * as fs from "fs";
@@ -29,7 +30,11 @@ import * as path from "path";
29
30
  import { execSync } from "child_process";
30
31
  import { Command } from "commander";
31
32
  var program = new Command();
32
- program.name("chatlab").description("ChatLab - Chat history analysis tool").version(getVersion());
33
+ program.name("chatlab").description("ChatLab - Chat history analysis tool").version(getVersion(), "-v, --version");
34
+ program.hook("preAction", async () => {
35
+ const { checkForUpdatesInteractive } = await import("./update-checker-MQMQ6A4B.mjs");
36
+ await checkForUpdatesInteractive();
37
+ });
33
38
  program.command("sessions").description("List all imported chat sessions").option("--format <format>", "Output format (table|json)", "table").action((options) => {
34
39
  const { dbManager } = initRuntime();
35
40
  const sessionIds = dbManager.listSessionIds();
@@ -168,7 +173,7 @@ program.command("import <file>").description("Import a chat history file (14+ fo
168
173
  console.error(`File not found: ${file}`);
169
174
  process.exit(1);
170
175
  }
171
- const { streamImport, detectFormat } = await import("./import-CQWGIMZQ.mjs");
176
+ const { streamImport, detectFormat } = await import("./import-BDLL3DG7.mjs");
172
177
  const { dbManager } = initRuntime();
173
178
  const nativeBinding = resolveNativeBinding();
174
179
  const format = detectFormat(file);
@@ -210,7 +215,7 @@ Import error: ${err instanceof Error ? err.message : err}`);
210
215
  }
211
216
  });
212
217
  program.command("formats").description("List all supported chat history formats").action(async () => {
213
- const { getSupportedFormats } = await import("./import-CQWGIMZQ.mjs");
218
+ const { getSupportedFormats } = await import("./import-BDLL3DG7.mjs");
214
219
  const formats = getSupportedFormats();
215
220
  console.log(`${formats.length} supported format(s):
216
221
  `);
@@ -219,15 +224,15 @@ program.command("formats").description("List all supported chat history formats"
219
224
  }
220
225
  });
221
226
  program.command("mcp").description("Start MCP Server (stdio transport, for ClaudeCode / Cursor / AI agents)").action(async () => {
222
- const { startCliMcpServer } = await import("./mcp-7Q3FEI3Z.mjs");
227
+ const { startCliMcpServer } = await import("./mcp-L2TPZFE7.mjs");
223
228
  await startCliMcpServer();
224
229
  });
225
230
  program.command("serve").description("Start the HTTP API server").option("--port <port>", "Server port", String(DEFAULT_API_PORT)).option("--host <host>", "Listen address", "127.0.0.1").option("--token <token>", "Custom Bearer Token (reads from config or auto-generates if omitted)").option("--web [dir]", "Serve Web frontend static assets (defaults to dist-web/)").action(async (options) => {
226
- const { startHttpServer } = await import("./http-DHQI4G5J.mjs");
231
+ const { startHttpServer } = await import("./http-O5P4BYXU.mjs");
227
232
  const port = parseInt(options.port, 10);
228
233
  let webRoot;
229
234
  if (options.web !== void 0) {
230
- const webDir = typeof options.web === "string" ? options.web : path.resolve(__dirname, "../dist-web");
235
+ const webDir = typeof options.web === "string" ? options.web : resolveCliPath("dist-web");
231
236
  if (fs.existsSync(webDir)) {
232
237
  webRoot = path.resolve(webDir);
233
238
  } else {
@@ -241,6 +246,8 @@ program.command("serve").description("Start the HTTP API server").option("--port
241
246
  token: options.token || void 0,
242
247
  webRoot
243
248
  });
249
+ const { startPeriodicUpdateCheck } = await import("./update-checker-MQMQ6A4B.mjs");
250
+ startPeriodicUpdateCheck();
244
251
  console.log(`
245
252
  ChatLab HTTP API started`);
246
253
  console.log(` Address: http://${info.host}:${info.port}`);
@@ -256,7 +263,7 @@ Press Ctrl+C to stop.
256
263
  `);
257
264
  const shutdown = async () => {
258
265
  console.log("\nShutting down...");
259
- const { stopHttpServer } = await import("./http-DHQI4G5J.mjs");
266
+ const { stopHttpServer } = await import("./http-O5P4BYXU.mjs");
260
267
  await stopHttpServer();
261
268
  process.exit(0);
262
269
  };
@@ -273,9 +280,9 @@ Press Ctrl+C to stop.
273
280
  }
274
281
  });
275
282
  program.command("web").description("Launch Web UI with one click (HTTP API + browser auto-open)").option("--port <port>", "Server port", String(DEFAULT_API_PORT)).option("--host <host>", "Listen address", "127.0.0.1").option("--no-open", "Do not auto-open browser").action(async (options) => {
276
- const { startHttpServer } = await import("./http-DHQI4G5J.mjs");
283
+ const { startHttpServer } = await import("./http-O5P4BYXU.mjs");
277
284
  const port = parseInt(options.port, 10);
278
- const webDir = path.resolve(__dirname, "../dist-web");
285
+ const webDir = resolveCliPath("dist-web");
279
286
  let webRoot;
280
287
  if (fs.existsSync(webDir)) {
281
288
  webRoot = webDir;
@@ -284,6 +291,8 @@ program.command("web").description("Launch Web UI with one click (HTTP API + bro
284
291
  }
285
292
  try {
286
293
  const info = await startHttpServer({ port, host: options.host, webRoot });
294
+ const { startPeriodicUpdateCheck } = await import("./update-checker-MQMQ6A4B.mjs");
295
+ startPeriodicUpdateCheck();
287
296
  const url = `http://${info.host === "0.0.0.0" ? "127.0.0.1" : info.host}:${info.port}`;
288
297
  console.log(`
289
298
  ChatLab v${getVersion()}`);
@@ -299,7 +308,7 @@ Press Ctrl+C to stop.`);
299
308
  }
300
309
  const shutdown = async () => {
301
310
  console.log("\nShutting down...");
302
- const { stopHttpServer } = await import("./http-DHQI4G5J.mjs");
311
+ const { stopHttpServer } = await import("./http-O5P4BYXU.mjs");
303
312
  await stopHttpServer();
304
313
  process.exit(0);
305
314
  };
@@ -333,7 +342,7 @@ function openBrowser(url) {
333
342
  }
334
343
  function resolveNativeBinding() {
335
344
  if (process.versions.electron) return void 0;
336
- const nativePath = path.resolve(__dirname, "../native/better_sqlite3.node");
345
+ const nativePath = resolveCliPath("native/better_sqlite3.node");
337
346
  if (fs.existsSync(nativePath)) return nativePath;
338
347
  return void 0;
339
348
  }
@@ -408,4 +417,4 @@ if (isDirectRun) {
408
417
  export {
409
418
  run
410
419
  };
411
- //# sourceMappingURL=chunk-OZWXLRJL.mjs.map
420
+ //# sourceMappingURL=chunk-LZ3W6NS5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.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 * as path from 'path'\nimport { execSync } from 'child_process'\nimport { Command } from 'commander'\nimport { DEFAULT_API_PORT, loadConfig, getConfigPath } from '@openchatlab/config'\nimport {\n NodePathProvider,\n DatabaseManager,\n hasPendingElectronDataWarning,\n verifyCliDataPath,\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'\n\nconst program = new Command()\n\nprogram.name('chatlab').description('ChatLab - Chat history analysis tool').version(getVersion(), '-v, --version')\n\nprogram.hook('preAction', async () => {\n const { checkForUpdatesInteractive } = await import('./update-checker')\n await checkForUpdatesInteractive()\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 } = 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 } 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('serve')\n .description('Start the HTTP API server')\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('--web [dir]', 'Serve Web frontend static assets (defaults to dist-web/)')\n .action(async (options) => {\n const { startHttpServer } = await import('./http')\n const port = parseInt(options.port, 10)\n\n let webRoot: string | undefined\n if (options.web !== undefined) {\n const webDir = typeof options.web === 'string' ? options.web : resolveCliPath('dist-web')\n if (fs.existsSync(webDir)) {\n webRoot = path.resolve(webDir)\n } else {\n console.warn(`Warning: Web directory not found: ${webDir}, starting in API-only mode`)\n }\n }\n\n try {\n const info = await startHttpServer({\n port,\n host: options.host,\n token: options.token || undefined,\n webRoot,\n })\n\n const { startPeriodicUpdateCheck } = await import('./update-checker')\n startPeriodicUpdateCheck()\n\n console.log(`\\nChatLab HTTP API started`)\n console.log(` Address: http://${info.host}:${info.port}`)\n console.log(` Token: ${info.token}`)\n if (webRoot) {\n console.log(` Web UI: http://${info.host}:${info.port}/`)\n }\n console.log(`\\nExample:`)\n console.log(` curl -H \"Authorization: Bearer ${info.token}\" http://${info.host}:${info.port}/api/v1/status`)\n console.log(`\\nPress Ctrl+C to stop.\\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 console.error(`Error: port ${port} is already in use`)\n } else {\n console.error(`Startup failed: ${message}`)\n }\n process.exit(1)\n }\n })\n\nprogram\n .command('web')\n .description('Launch Web UI with one click (HTTP API + browser auto-open)')\n .option('--port <port>', 'Server port', String(DEFAULT_API_PORT))\n .option('--host <host>', 'Listen address', '127.0.0.1')\n .option('--no-open', 'Do not auto-open browser')\n .action(async (options) => {\n const { startHttpServer } = await import('./http')\n const port = parseInt(options.port, 10)\n const webDir = resolveCliPath('dist-web')\n let webRoot: string | undefined\n\n if (fs.existsSync(webDir)) {\n webRoot = webDir\n } else {\n console.warn('Warning: dist-web/ not found, Web UI will not be available (API-only mode)')\n }\n\n try {\n const info = await startHttpServer({ port, host: options.host, webRoot })\n const { startPeriodicUpdateCheck } = await import('./update-checker')\n startPeriodicUpdateCheck()\n\n const url = `http://${info.host === '0.0.0.0' ? '127.0.0.1' : info.host}:${info.port}`\n\n console.log(`\\nChatLab v${getVersion()}`)\n console.log(` Web UI: ${url}`)\n console.log(` Token: ${info.token}`)\n\n if (options.open && webRoot) {\n openBrowser(url)\n console.log(`\\nBrowser opened. Press Ctrl+C to stop.`)\n } else {\n console.log(`\\nPress Ctrl+C to stop.`)\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 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 console.error(`Error: port ${port} is already in use`)\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\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 const config = loadConfig()\n const userDataDir = config.data.user_data_dir || undefined\n const pathProvider = new NodePathProvider(userDataDir)\n pathProvider.ensureAllDirs()\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 })\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 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"],"mappings":"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","names":[]}
@@ -11,7 +11,7 @@ import {
11
11
  generateMessageKey,
12
12
  openBetterSqliteDatabase,
13
13
  writeParseResultToDb
14
- } from "./chunk-7HQWGLX6.mjs";
14
+ } from "./chunk-SQKT45MM.mjs";
15
15
 
16
16
  // src/import/chatlab-reader.ts
17
17
  import * as fs from "fs";
@@ -392,4 +392,4 @@ export {
392
392
  parseFile,
393
393
  importData
394
394
  };
395
- //# sourceMappingURL=chunk-OQVKZTVD.mjs.map
395
+ //# sourceMappingURL=chunk-OC2W5Q5T.mjs.map
@@ -13,7 +13,7 @@ import {
13
13
  incrementalImport,
14
14
  openBetterSqliteDatabase,
15
15
  streamingImport
16
- } from "./chunk-7HQWGLX6.mjs";
16
+ } from "./chunk-SQKT45MM.mjs";
17
17
 
18
18
  // src/import/stream-import.ts
19
19
  import * as fs from "fs";
@@ -141,4 +141,4 @@ export {
141
141
  analyzeIncrementalImport2 as analyzeIncrementalImport,
142
142
  analyzeNewImport2 as analyzeNewImport
143
143
  };
144
- //# sourceMappingURL=chunk-AIR7EAF4.mjs.map
144
+ //# sourceMappingURL=chunk-QRC3RSER.mjs.map