chatlab-cli 0.24.0 → 0.24.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.
- package/README.md +5 -2
- package/dist/{chunk-KCBIBRHL.mjs → chunk-43XWYC3M.mjs} +2 -2
- package/dist/{chunk-A6JCL4PT.mjs → chunk-CIIQ3S2X.mjs} +24 -10
- package/dist/chunk-CIIQ3S2X.mjs.map +1 -0
- package/dist/{chunk-XJJXSOLO.mjs → chunk-N5DGZQB4.mjs} +172 -41
- package/dist/chunk-N5DGZQB4.mjs.map +1 -0
- package/dist/{chunk-RLCFXTTS.mjs → chunk-QJI6AOAT.mjs} +2 -2
- package/dist/{chunk-36W2HWQN.mjs → chunk-QY6P2YS7.mjs} +2 -2
- package/dist/{chunk-NE4A6PND.mjs → chunk-ZL322NVL.mjs} +23 -26
- package/dist/chunk-ZL322NVL.mjs.map +1 -0
- package/dist/cli.mjs +2 -2
- package/dist/{http-OPQ352FZ.mjs → http-TPX74BLK.mjs} +6 -6
- package/dist/{import-GZMDLK2E.mjs → import-B745DRHD.mjs} +4 -4
- package/dist/index.mjs +6 -6
- package/dist/{mcp-SHZ2CVXY.mjs → mcp-YWAVG5XW.mjs} +3 -3
- package/dist/{stream-import-RDDB3N7B.mjs → stream-import-OPALPVWF.mjs} +3 -3
- package/dist/{update-checker-JG5K67O2.mjs → update-checker-JIBA7T4U.mjs} +24 -21
- package/dist/update-checker-JIBA7T4U.mjs.map +1 -0
- package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-_gbTn1ha.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-BBDrsJfe.js} +9 -9
- package/dist-web/assets/MessageExportModal-CSfaY25B.js +1 -0
- package/dist-web/assets/{electron-BIWBW8k_.js → electron-BUeXfvxT.js} +1 -1
- package/dist-web/assets/electron-BynNUuEA.js +1 -0
- package/dist-web/assets/{fetch-BhsrPRzn.js → fetch-B2q6973s.js} +1 -1
- package/dist-web/assets/{fetch-CnyupWWc.js → fetch-BGMRmQx0.js} +2 -2
- package/dist-web/assets/{fetch-ClDGP9DK.js → fetch-BneHn5qk.js} +1 -1
- package/dist-web/assets/{fetch-DwPB8NOH.js → fetch-BohUj3CQ.js} +1 -1
- package/dist-web/assets/{fetch-BOevuRK_.js → fetch-BtHwWs8A.js} +1 -1
- package/dist-web/assets/{fetch-DFWZ48Xw.js → fetch-CARsBVl0.js} +1 -1
- package/dist-web/assets/{fetch-CvaXKzA-.js → fetch-Ck3tjoLa.js} +1 -1
- package/dist-web/assets/{fetch-DKD1bKt2.js → fetch-DypPduyQ.js} +1 -1
- package/dist-web/assets/{fetch-ChECfwh7.js → fetch-DzNuFdFM.js} +1 -1
- package/dist-web/assets/{fetch-D1_jL6PO.js → fetch-RDFt3hmp.js} +1 -1
- package/dist-web/assets/index-BRwEubUe.js +173 -0
- package/dist-web/assets/{index-Bzg8BftZ.js → index-BvaWRM6_.js} +1 -1
- package/dist-web/assets/{index-BVQsKKwg.js → index-Bvlj3dMn.js} +1 -1
- package/dist-web/assets/{index-D6ga3hbF.js → index-C5LrQG3N.js} +3 -3
- package/dist-web/assets/index-DB-iqXzV.css +1 -0
- package/dist-web/assets/index-DCWvD-4L.js +2 -0
- package/dist-web/assets/index-DS1rzk1I.js +8 -0
- package/dist-web/assets/{vendor-nuxt-ui-BLMzqeB8.js → vendor-nuxt-ui-BYU7dz8t.js} +1 -1
- package/dist-web/assets/{web-DtlveK3q.js → web-CXPkmhis.js} +1 -1
- package/dist-web/index.html +3 -3
- package/package.json +1 -1
- package/dist/chunk-A6JCL4PT.mjs.map +0 -1
- package/dist/chunk-NE4A6PND.mjs.map +0 -1
- package/dist/chunk-XJJXSOLO.mjs.map +0 -1
- package/dist/update-checker-JG5K67O2.mjs.map +0 -1
- package/dist-web/assets/MessageExportModal-n4JgNg_F.js +0 -1
- package/dist-web/assets/electron-Bt9dK4Sr.js +0 -1
- package/dist-web/assets/index-BN79SJSr.js +0 -173
- package/dist-web/assets/index-C-5bP7_E.js +0 -2
- package/dist-web/assets/index-ESCx9pRR.js +0 -8
- package/dist-web/assets/index-JbR9Q-bb.css +0 -1
- package/dist-web/assets/model-catalog-DUuKjIVU.js +0 -1
- /package/dist/{chunk-KCBIBRHL.mjs.map → chunk-43XWYC3M.mjs.map} +0 -0
- /package/dist/{chunk-RLCFXTTS.mjs.map → chunk-QJI6AOAT.mjs.map} +0 -0
- /package/dist/{chunk-36W2HWQN.mjs.map → chunk-QY6P2YS7.mjs.map} +0 -0
- /package/dist/{http-OPQ352FZ.mjs.map → http-TPX74BLK.mjs.map} +0 -0
- /package/dist/{import-GZMDLK2E.mjs.map → import-B745DRHD.mjs.map} +0 -0
- /package/dist/{mcp-SHZ2CVXY.mjs.map → mcp-YWAVG5XW.mjs.map} +0 -0
- /package/dist/{stream-import-RDDB3N7B.mjs.map → stream-import-OPALPVWF.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -92,10 +92,12 @@ For a deep dive, see the [architecture documentation](https://docs.chatlab.fun/i
|
|
|
92
92
|
|
|
93
93
|
## Local Development
|
|
94
94
|
|
|
95
|
+
For complete contributor instructions, see the [Development Guide](https://docs.chatlab.fun/contributing/development).
|
|
96
|
+
|
|
95
97
|
### Requirements
|
|
96
98
|
|
|
97
|
-
- Node.js >=
|
|
98
|
-
- pnpm
|
|
99
|
+
- Node.js >= 24 < 25
|
|
100
|
+
- pnpm >= 9 < 10
|
|
99
101
|
|
|
100
102
|
### Setup
|
|
101
103
|
|
|
@@ -128,6 +130,7 @@ Please follow these principles before submitting a Pull Request:
|
|
|
128
130
|
- Obvious bug fixes can be submitted directly.
|
|
129
131
|
- For new features, please submit an Issue for discussion first; **PRs submitted without prior discussion will be closed**.
|
|
130
132
|
- Keep one PR focused on one task; if changes are extensive, consider splitting them into multiple independent PRs.
|
|
133
|
+
- For local setup, repository structure, checks, and AI collaboration notes, see the [Development Guide](https://docs.chatlab.fun/contributing/development).
|
|
131
134
|
|
|
132
135
|
Thanks to all contributors:
|
|
133
136
|
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
getWeekdayActivity,
|
|
27
27
|
searchMessagesLike,
|
|
28
28
|
searchSessions
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-N5DGZQB4.mjs";
|
|
30
30
|
|
|
31
31
|
// ../../packages/tools/src/definitions/sql-query.ts
|
|
32
32
|
var inputSchema = {
|
|
@@ -1341,4 +1341,4 @@ export {
|
|
|
1341
1341
|
MCP_TOOL_REGISTRY,
|
|
1342
1342
|
CoreDataProvider
|
|
1343
1343
|
};
|
|
1344
|
-
//# sourceMappingURL=chunk-
|
|
1344
|
+
//# sourceMappingURL=chunk-43XWYC3M.mjs.map
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
loadConfig,
|
|
23
23
|
searchMessagesLike,
|
|
24
24
|
verifyCliDataPath
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-N5DGZQB4.mjs";
|
|
26
26
|
import {
|
|
27
27
|
resolveCliPath
|
|
28
28
|
} from "./chunk-FJ35V3TE.mjs";
|
|
@@ -63,10 +63,24 @@ function formatPortInUseError(port) {
|
|
|
63
63
|
// src/cli.ts
|
|
64
64
|
var program = new Command();
|
|
65
65
|
program.name("chatlab").description("ChatLab - Chat history analysis tool").version(getVersion(), "-v, --version");
|
|
66
|
-
program.hook("preAction", async () => {
|
|
67
|
-
|
|
66
|
+
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
67
|
+
if (actionCommand.name() === "update") return;
|
|
68
|
+
const { checkForUpdatesInteractive } = await import("./update-checker-JIBA7T4U.mjs");
|
|
68
69
|
await checkForUpdatesInteractive();
|
|
69
70
|
});
|
|
71
|
+
program.command("update").description("Update ChatLab CLI to the latest version").action(async () => {
|
|
72
|
+
const { performCliSelfUpdate } = await import("./update-checker-JIBA7T4U.mjs");
|
|
73
|
+
const result = await performCliSelfUpdate({
|
|
74
|
+
write: (text) => process.stderr.write(text)
|
|
75
|
+
});
|
|
76
|
+
if (result.success) {
|
|
77
|
+
console.error(" Updated successfully. Please restart chatlab to use the new version.\n");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
console.error(` Update failed: ${result.error || "unknown error"}
|
|
81
|
+
`);
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
});
|
|
70
84
|
program.command("sessions").description("List all imported chat sessions").option("--format <format>", "Output format (table|json)", "table").action((options) => {
|
|
71
85
|
const { dbManager } = initRuntime();
|
|
72
86
|
const sessionIds = dbManager.listSessionIds();
|
|
@@ -205,7 +219,7 @@ program.command("import <file>").description("Import a chat history file (14+ fo
|
|
|
205
219
|
console.error(`File not found: ${file}`);
|
|
206
220
|
process.exit(1);
|
|
207
221
|
}
|
|
208
|
-
const { streamImport, detectFormat } = await import("./import-
|
|
222
|
+
const { streamImport, detectFormat } = await import("./import-B745DRHD.mjs");
|
|
209
223
|
const { dbManager } = initRuntime();
|
|
210
224
|
const nativeBinding = resolveNativeBinding();
|
|
211
225
|
const format = detectFormat(file);
|
|
@@ -247,7 +261,7 @@ Import error: ${err instanceof Error ? err.message : err}`);
|
|
|
247
261
|
}
|
|
248
262
|
});
|
|
249
263
|
program.command("formats").description("List all supported chat history formats").action(async () => {
|
|
250
|
-
const { getSupportedFormats } = await import("./import-
|
|
264
|
+
const { getSupportedFormats } = await import("./import-B745DRHD.mjs");
|
|
251
265
|
const formats = getSupportedFormats();
|
|
252
266
|
console.log(`${formats.length} supported format(s):
|
|
253
267
|
`);
|
|
@@ -256,7 +270,7 @@ program.command("formats").description("List all supported chat history formats"
|
|
|
256
270
|
}
|
|
257
271
|
});
|
|
258
272
|
program.command("mcp").description("Start MCP Server (stdio transport, for ClaudeCode / Cursor / AI agents)").action(async () => {
|
|
259
|
-
const { startCliMcpServer } = await import("./mcp-
|
|
273
|
+
const { startCliMcpServer } = await import("./mcp-YWAVG5XW.mjs");
|
|
260
274
|
await startCliMcpServer();
|
|
261
275
|
});
|
|
262
276
|
program.command("start").description("Start ChatLab (HTTP API + Web UI)").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("--headless", "API-only mode, do not serve the Web UI").option("--require-auth", "Require Bearer token for all routes including /_web/*").option("--no-open", "Do not auto-open the browser").option("--daemon", "Run as a resident system service (auto-start on login, macOS/Linux)").action(async (options) => {
|
|
@@ -271,7 +285,7 @@ program.command("start").description("Start ChatLab (HTTP API + Web UI)").option
|
|
|
271
285
|
});
|
|
272
286
|
return;
|
|
273
287
|
}
|
|
274
|
-
const { startHttpServer } = await import("./http-
|
|
288
|
+
const { startHttpServer } = await import("./http-TPX74BLK.mjs");
|
|
275
289
|
const port = parseInt(options.port, 10);
|
|
276
290
|
let webRoot;
|
|
277
291
|
if (!options.headless) {
|
|
@@ -294,7 +308,7 @@ program.command("start").description("Start ChatLab (HTTP API + Web UI)").option
|
|
|
294
308
|
webRoot,
|
|
295
309
|
requireAuth: options.requireAuth || void 0
|
|
296
310
|
});
|
|
297
|
-
const { startPeriodicUpdateCheck } = await import("./update-checker-
|
|
311
|
+
const { startPeriodicUpdateCheck } = await import("./update-checker-JIBA7T4U.mjs");
|
|
298
312
|
startPeriodicUpdateCheck();
|
|
299
313
|
const displayHost = info.host === "0.0.0.0" ? "127.0.0.1" : info.host;
|
|
300
314
|
const url = `http://${displayHost}:${info.port}`;
|
|
@@ -318,7 +332,7 @@ Press Ctrl+C to stop.
|
|
|
318
332
|
}
|
|
319
333
|
const shutdown = async () => {
|
|
320
334
|
console.log("\nShutting down...");
|
|
321
|
-
const { stopHttpServer } = await import("./http-
|
|
335
|
+
const { stopHttpServer } = await import("./http-TPX74BLK.mjs");
|
|
322
336
|
await stopHttpServer();
|
|
323
337
|
process.exit(0);
|
|
324
338
|
};
|
|
@@ -461,4 +475,4 @@ if (isDirectRun) {
|
|
|
461
475
|
export {
|
|
462
476
|
run
|
|
463
477
|
};
|
|
464
|
-
//# sourceMappingURL=chunk-
|
|
478
|
+
//# sourceMappingURL=chunk-CIIQ3S2X.mjs.map
|
|
@@ -0,0 +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 applyPendingNodeDataDirMigrationIfNeeded,\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'\nimport { isPortAvailable, formatPortInUseError } from './http/port'\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 } = 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('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\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\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","/**\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":[]}
|
|
@@ -4377,6 +4377,39 @@ function runMigrations(db, migrationsList, forceRepair = false) {
|
|
|
4377
4377
|
return true;
|
|
4378
4378
|
}
|
|
4379
4379
|
|
|
4380
|
+
// ../../packages/core/src/version.ts
|
|
4381
|
+
function parseStableVersion(version) {
|
|
4382
|
+
const normalized = version.trim().replace(/^v/i, "");
|
|
4383
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(normalized);
|
|
4384
|
+
if (!match) return null;
|
|
4385
|
+
return buildParsedVersion(match);
|
|
4386
|
+
}
|
|
4387
|
+
function parseComparableCurrentVersion(version) {
|
|
4388
|
+
const normalized = version.trim().replace(/^v/i, "");
|
|
4389
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?$/.exec(normalized);
|
|
4390
|
+
if (!match) return null;
|
|
4391
|
+
return {
|
|
4392
|
+
...buildParsedVersion(match),
|
|
4393
|
+
prerelease: Boolean(match[4])
|
|
4394
|
+
};
|
|
4395
|
+
}
|
|
4396
|
+
function buildParsedVersion(match) {
|
|
4397
|
+
return {
|
|
4398
|
+
major: Number(match[1]),
|
|
4399
|
+
minor: Number(match[2]),
|
|
4400
|
+
patch: Number(match[3])
|
|
4401
|
+
};
|
|
4402
|
+
}
|
|
4403
|
+
function isNewerStableVersion(latest, current) {
|
|
4404
|
+
const latestVersion = parseStableVersion(latest);
|
|
4405
|
+
const currentVersion = parseComparableCurrentVersion(current);
|
|
4406
|
+
if (!latestVersion || !currentVersion) return false;
|
|
4407
|
+
if (latestVersion.major !== currentVersion.major) return latestVersion.major > currentVersion.major;
|
|
4408
|
+
if (latestVersion.minor !== currentVersion.minor) return latestVersion.minor > currentVersion.minor;
|
|
4409
|
+
if (latestVersion.patch !== currentVersion.patch) return latestVersion.patch > currentVersion.patch;
|
|
4410
|
+
return currentVersion.prerelease;
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4380
4413
|
// ../../packages/core/src/nlp/pos-tags.ts
|
|
4381
4414
|
var POS_TAG_DEFINITIONS = [
|
|
4382
4415
|
{ tag: "n", name: "\u540D\u8BCD", description: "\u666E\u901A\u540D\u8BCD", meaningful: true },
|
|
@@ -14132,6 +14165,7 @@ function compileRules(rules, logger) {
|
|
|
14132
14165
|
}
|
|
14133
14166
|
|
|
14134
14167
|
// ../../packages/node-runtime/src/ai/preprocessor/builtin-rules.ts
|
|
14168
|
+
var DESENSITIZE_RULES_SCHEMA_VERSION = 2;
|
|
14135
14169
|
var BUILTIN_DESENSITIZE_RULES = [
|
|
14136
14170
|
// ==================== 中国 (zh-CN) ====================
|
|
14137
14171
|
{
|
|
@@ -14141,7 +14175,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14141
14175
|
replacement: "[\u624B\u673A\u53F7]",
|
|
14142
14176
|
enabled: true,
|
|
14143
14177
|
builtin: true,
|
|
14144
|
-
locales: ["zh-CN"]
|
|
14178
|
+
locales: ["zh-CN"],
|
|
14179
|
+
group: "region_cn"
|
|
14145
14180
|
},
|
|
14146
14181
|
{
|
|
14147
14182
|
id: "cn_id_card",
|
|
@@ -14150,25 +14185,28 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14150
14185
|
replacement: "[\u8EAB\u4EFD\u8BC1]",
|
|
14151
14186
|
enabled: true,
|
|
14152
14187
|
builtin: true,
|
|
14153
|
-
locales: ["zh-CN"]
|
|
14188
|
+
locales: ["zh-CN"],
|
|
14189
|
+
group: "region_cn"
|
|
14154
14190
|
},
|
|
14155
14191
|
{
|
|
14156
14192
|
id: "cn_bank_card",
|
|
14157
14193
|
label: "desensitize.rules.cn_bank_card",
|
|
14158
14194
|
pattern: "(?<!\\d)\\d{16,19}(?!\\d)",
|
|
14159
14195
|
replacement: "[\u94F6\u884C\u5361]",
|
|
14160
|
-
enabled:
|
|
14196
|
+
enabled: true,
|
|
14161
14197
|
builtin: true,
|
|
14162
|
-
locales: ["zh-CN"]
|
|
14198
|
+
locales: ["zh-CN"],
|
|
14199
|
+
group: "region_cn"
|
|
14163
14200
|
},
|
|
14164
14201
|
{
|
|
14165
14202
|
id: "cn_landline",
|
|
14166
14203
|
label: "desensitize.rules.cn_landline",
|
|
14167
14204
|
pattern: "(?<!\\d)0\\d{2,3}-?\\d{7,8}(?!\\d)",
|
|
14168
14205
|
replacement: "[\u5EA7\u673A\u53F7]",
|
|
14169
|
-
enabled:
|
|
14206
|
+
enabled: true,
|
|
14170
14207
|
builtin: true,
|
|
14171
|
-
locales: ["zh-CN"]
|
|
14208
|
+
locales: ["zh-CN"],
|
|
14209
|
+
group: "region_cn"
|
|
14172
14210
|
},
|
|
14173
14211
|
// ==================== 美国 (en-US) ====================
|
|
14174
14212
|
{
|
|
@@ -14178,7 +14216,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14178
14216
|
replacement: "[SSN]",
|
|
14179
14217
|
enabled: true,
|
|
14180
14218
|
builtin: true,
|
|
14181
|
-
locales: ["en-US"]
|
|
14219
|
+
locales: ["en-US"],
|
|
14220
|
+
group: "region_us"
|
|
14182
14221
|
},
|
|
14183
14222
|
{
|
|
14184
14223
|
id: "us_phone",
|
|
@@ -14187,16 +14226,18 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14187
14226
|
replacement: "[Phone]",
|
|
14188
14227
|
enabled: true,
|
|
14189
14228
|
builtin: true,
|
|
14190
|
-
locales: ["en-US"]
|
|
14229
|
+
locales: ["en-US"],
|
|
14230
|
+
group: "region_us"
|
|
14191
14231
|
},
|
|
14192
14232
|
{
|
|
14193
14233
|
id: "us_drivers_license",
|
|
14194
14234
|
label: "desensitize.rules.us_drivers_license",
|
|
14195
14235
|
pattern: "(?<![A-Z])\\b[A-Z]\\d{7,8}\\b",
|
|
14196
14236
|
replacement: "[Driver's License]",
|
|
14197
|
-
enabled:
|
|
14237
|
+
enabled: true,
|
|
14198
14238
|
builtin: true,
|
|
14199
|
-
locales: ["en-US"]
|
|
14239
|
+
locales: ["en-US"],
|
|
14240
|
+
group: "region_us"
|
|
14200
14241
|
},
|
|
14201
14242
|
// ==================== 日本 (ja-JP) ====================
|
|
14202
14243
|
{
|
|
@@ -14206,16 +14247,18 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14206
14247
|
replacement: "[\u96FB\u8A71\u756A\u53F7]",
|
|
14207
14248
|
enabled: true,
|
|
14208
14249
|
builtin: true,
|
|
14209
|
-
locales: ["ja-JP"]
|
|
14250
|
+
locales: ["ja-JP"],
|
|
14251
|
+
group: "region_jp"
|
|
14210
14252
|
},
|
|
14211
14253
|
{
|
|
14212
14254
|
id: "jp_my_number",
|
|
14213
14255
|
label: "desensitize.rules.jp_my_number",
|
|
14214
14256
|
pattern: "(?<!\\d)\\d{4}\\s?\\d{4}\\s?\\d{4}(?!\\d)",
|
|
14215
14257
|
replacement: "[\u30DE\u30A4\u30CA\u30F3\u30D0\u30FC]",
|
|
14216
|
-
enabled:
|
|
14258
|
+
enabled: true,
|
|
14217
14259
|
builtin: true,
|
|
14218
|
-
locales: ["ja-JP"]
|
|
14260
|
+
locales: ["ja-JP"],
|
|
14261
|
+
group: "region_jp"
|
|
14219
14262
|
},
|
|
14220
14263
|
// ==================== 韩国 (ko-KR) ====================
|
|
14221
14264
|
{
|
|
@@ -14225,7 +14268,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14225
14268
|
replacement: "[\uC804\uD654\uBC88\uD638]",
|
|
14226
14269
|
enabled: true,
|
|
14227
14270
|
builtin: true,
|
|
14228
|
-
locales: ["ko-KR"]
|
|
14271
|
+
locales: ["ko-KR"],
|
|
14272
|
+
group: "region_kr"
|
|
14229
14273
|
},
|
|
14230
14274
|
{
|
|
14231
14275
|
id: "kr_rrn",
|
|
@@ -14234,7 +14278,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14234
14278
|
replacement: "[\uC8FC\uBBFC\uBC88\uD638]",
|
|
14235
14279
|
enabled: true,
|
|
14236
14280
|
builtin: true,
|
|
14237
|
-
locales: ["ko-KR"]
|
|
14281
|
+
locales: ["ko-KR"],
|
|
14282
|
+
group: "region_kr"
|
|
14238
14283
|
},
|
|
14239
14284
|
// ==================== 凭据 / Token (所有语言) ====================
|
|
14240
14285
|
{
|
|
@@ -14244,7 +14289,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14244
14289
|
replacement: "[API Key]",
|
|
14245
14290
|
enabled: true,
|
|
14246
14291
|
builtin: true,
|
|
14247
|
-
locales: []
|
|
14292
|
+
locales: [],
|
|
14293
|
+
group: "credentials"
|
|
14248
14294
|
},
|
|
14249
14295
|
{
|
|
14250
14296
|
id: "bearer_token",
|
|
@@ -14253,7 +14299,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14253
14299
|
replacement: "Bearer [Token]",
|
|
14254
14300
|
enabled: true,
|
|
14255
14301
|
builtin: true,
|
|
14256
|
-
locales: []
|
|
14302
|
+
locales: [],
|
|
14303
|
+
group: "credentials"
|
|
14257
14304
|
},
|
|
14258
14305
|
// ==================== 通用 (所有语言) ====================
|
|
14259
14306
|
{
|
|
@@ -14263,34 +14310,38 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14263
14310
|
replacement: "[Email]",
|
|
14264
14311
|
enabled: true,
|
|
14265
14312
|
builtin: true,
|
|
14266
|
-
locales: []
|
|
14313
|
+
locales: [],
|
|
14314
|
+
group: "global_contact"
|
|
14267
14315
|
},
|
|
14268
14316
|
{
|
|
14269
14317
|
id: "credit_card",
|
|
14270
14318
|
label: "desensitize.rules.credit_card",
|
|
14271
14319
|
pattern: "(?<!\\d)(?:4\\d{3}|5[1-5]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}))[-\\s.]?\\d{4}[-\\s.]?\\d{4}[-\\s.]?\\d{4}(?!\\d)",
|
|
14272
14320
|
replacement: "[Credit Card]",
|
|
14273
|
-
enabled:
|
|
14321
|
+
enabled: true,
|
|
14274
14322
|
builtin: true,
|
|
14275
|
-
locales: []
|
|
14323
|
+
locales: [],
|
|
14324
|
+
group: "global_financial"
|
|
14276
14325
|
},
|
|
14277
14326
|
{
|
|
14278
14327
|
id: "ipv4",
|
|
14279
14328
|
label: "desensitize.rules.ipv4",
|
|
14280
14329
|
pattern: "(?<!\\d)(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)(?!\\d)",
|
|
14281
14330
|
replacement: "[IP]",
|
|
14282
|
-
enabled:
|
|
14331
|
+
enabled: true,
|
|
14283
14332
|
builtin: true,
|
|
14284
|
-
locales: []
|
|
14333
|
+
locales: [],
|
|
14334
|
+
group: "global_network"
|
|
14285
14335
|
},
|
|
14286
14336
|
{
|
|
14287
14337
|
id: "url",
|
|
14288
14338
|
label: "desensitize.rules.url",
|
|
14289
14339
|
pattern: 'https?://[^\\s<>"]+',
|
|
14290
14340
|
replacement: "[URL]",
|
|
14291
|
-
enabled:
|
|
14341
|
+
enabled: true,
|
|
14292
14342
|
builtin: true,
|
|
14293
|
-
locales: []
|
|
14343
|
+
locales: [],
|
|
14344
|
+
group: "global_network"
|
|
14294
14345
|
}
|
|
14295
14346
|
];
|
|
14296
14347
|
function getDefaultRulesForLocale(locale) {
|
|
@@ -14298,12 +14349,16 @@ function getDefaultRulesForLocale(locale) {
|
|
|
14298
14349
|
(rule) => ({ ...rule })
|
|
14299
14350
|
);
|
|
14300
14351
|
}
|
|
14301
|
-
function
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14352
|
+
function applyDesensitizeRuleOverrides(rules, overrides = {}) {
|
|
14353
|
+
return rules.map((rule) => ({
|
|
14354
|
+
...rule,
|
|
14355
|
+
enabled: overrides[rule.id] ?? rule.enabled
|
|
14356
|
+
}));
|
|
14357
|
+
}
|
|
14358
|
+
function mergeRulesForLocale(existing, locale, overrides = {}) {
|
|
14359
|
+
const customRules = existing.filter((rule) => !rule.builtin);
|
|
14360
|
+
const builtinRules = applyDesensitizeRuleOverrides(getDefaultRulesForLocale(locale), overrides);
|
|
14361
|
+
return [...builtinRules, ...customRules];
|
|
14307
14362
|
}
|
|
14308
14363
|
|
|
14309
14364
|
// ../../packages/node-runtime/src/ai/preprocessor/format.ts
|
|
@@ -17904,11 +17959,13 @@ var DEFAULTS = {
|
|
|
17904
17959
|
pinnedSessionIds: [],
|
|
17905
17960
|
aiPreprocessConfig: {
|
|
17906
17961
|
dataCleaning: true,
|
|
17907
|
-
mergeConsecutive:
|
|
17962
|
+
mergeConsecutive: true,
|
|
17908
17963
|
mergeWindowSeconds: 180,
|
|
17909
17964
|
blacklistKeywords: [],
|
|
17910
|
-
denoise:
|
|
17911
|
-
desensitize:
|
|
17965
|
+
denoise: true,
|
|
17966
|
+
desensitize: true,
|
|
17967
|
+
desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,
|
|
17968
|
+
desensitizeBuiltinRuleOverrides: {},
|
|
17912
17969
|
desensitizeRules: [],
|
|
17913
17970
|
anonymizeNames: false
|
|
17914
17971
|
},
|
|
@@ -17947,7 +18004,11 @@ var PreferencesManager = class {
|
|
|
17947
18004
|
if (fs35.existsSync(this.filePath)) {
|
|
17948
18005
|
const raw = fs35.readFileSync(this.filePath, "utf-8");
|
|
17949
18006
|
const parsed = JSON.parse(raw);
|
|
17950
|
-
|
|
18007
|
+
const migrated = this.migrateLegacyDesensitizeRules(parsed, raw);
|
|
18008
|
+
this.cache = this.mergeDefaults(migrated.preferences);
|
|
18009
|
+
if (migrated.changed) {
|
|
18010
|
+
this.writePreferences(this.cache);
|
|
18011
|
+
}
|
|
17951
18012
|
return this.cache;
|
|
17952
18013
|
}
|
|
17953
18014
|
} catch (err) {
|
|
@@ -17963,12 +18024,12 @@ var PreferencesManager = class {
|
|
|
17963
18024
|
current,
|
|
17964
18025
|
partial
|
|
17965
18026
|
);
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
fs35.mkdirSync(dir, { recursive: true });
|
|
18027
|
+
if (Object.prototype.hasOwnProperty.call(partial.aiPreprocessConfig ?? {}, "desensitizeBuiltinRuleOverrides")) {
|
|
18028
|
+
const mergedAiPreprocessConfig = merged.aiPreprocessConfig;
|
|
18029
|
+
mergedAiPreprocessConfig.desensitizeBuiltinRuleOverrides = partial.aiPreprocessConfig?.desensitizeBuiltinRuleOverrides;
|
|
17970
18030
|
}
|
|
17971
|
-
|
|
18031
|
+
this.cache = this.mergeDefaults(merged);
|
|
18032
|
+
this.writePreferences(this.cache);
|
|
17972
18033
|
return { success: true };
|
|
17973
18034
|
} catch (err) {
|
|
17974
18035
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -17985,7 +18046,7 @@ var PreferencesManager = class {
|
|
|
17985
18046
|
mergeDefaults(partial) {
|
|
17986
18047
|
return {
|
|
17987
18048
|
pinnedSessionIds: partial.pinnedSessionIds ?? DEFAULTS.pinnedSessionIds,
|
|
17988
|
-
aiPreprocessConfig: partial.aiPreprocessConfig ?
|
|
18049
|
+
aiPreprocessConfig: partial.aiPreprocessConfig ? this.normalizeAiPreprocessConfig(partial.aiPreprocessConfig) : { ...DEFAULTS.aiPreprocessConfig },
|
|
17989
18050
|
aiGlobalSettings: partial.aiGlobalSettings ? {
|
|
17990
18051
|
...DEFAULTS.aiGlobalSettings,
|
|
17991
18052
|
...partial.aiGlobalSettings,
|
|
@@ -18000,6 +18061,75 @@ var PreferencesManager = class {
|
|
|
18000
18061
|
filterHistory: partial.filterHistory ?? DEFAULTS.filterHistory
|
|
18001
18062
|
};
|
|
18002
18063
|
}
|
|
18064
|
+
normalizeAiPreprocessConfig(partial) {
|
|
18065
|
+
const defaults = DEFAULTS.aiPreprocessConfig;
|
|
18066
|
+
const rules = Array.isArray(partial?.desensitizeRules) ? partial.desensitizeRules : [];
|
|
18067
|
+
const customRules = rules.filter((rule) => !rule.builtin);
|
|
18068
|
+
return {
|
|
18069
|
+
dataCleaning: partial?.dataCleaning ?? defaults.dataCleaning,
|
|
18070
|
+
mergeConsecutive: partial?.mergeConsecutive ?? defaults.mergeConsecutive,
|
|
18071
|
+
mergeWindowSeconds: partial?.mergeWindowSeconds ?? defaults.mergeWindowSeconds,
|
|
18072
|
+
blacklistKeywords: partial?.blacklistKeywords ?? defaults.blacklistKeywords,
|
|
18073
|
+
denoise: partial?.denoise ?? defaults.denoise,
|
|
18074
|
+
desensitize: partial?.desensitize ?? defaults.desensitize,
|
|
18075
|
+
desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,
|
|
18076
|
+
desensitizeBuiltinRuleOverrides: this.normalizeBooleanMap(partial?.desensitizeBuiltinRuleOverrides),
|
|
18077
|
+
desensitizeRules: customRules,
|
|
18078
|
+
anonymizeNames: partial?.anonymizeNames ?? defaults.anonymizeNames
|
|
18079
|
+
};
|
|
18080
|
+
}
|
|
18081
|
+
normalizeBooleanMap(value) {
|
|
18082
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
18083
|
+
const result = {};
|
|
18084
|
+
for (const [key, flag] of Object.entries(value)) {
|
|
18085
|
+
if (typeof flag === "boolean") result[key] = flag;
|
|
18086
|
+
}
|
|
18087
|
+
return result;
|
|
18088
|
+
}
|
|
18089
|
+
migrateLegacyDesensitizeRules(partial, rawContent) {
|
|
18090
|
+
const rules = partial.aiPreprocessConfig?.desensitizeRules;
|
|
18091
|
+
if (!Array.isArray(rules) || !rules.some((rule) => rule.builtin)) {
|
|
18092
|
+
return { preferences: partial, changed: false };
|
|
18093
|
+
}
|
|
18094
|
+
this.backupLegacyPreferences(rawContent);
|
|
18095
|
+
const legacyBuiltinRuleOverrides = rules.filter((rule) => rule.builtin && typeof rule.enabled === "boolean").reduce((overrides, rule) => {
|
|
18096
|
+
overrides[rule.id] = rule.enabled;
|
|
18097
|
+
return overrides;
|
|
18098
|
+
}, {});
|
|
18099
|
+
const existingOverrides = this.normalizeBooleanMap(partial.aiPreprocessConfig?.desensitizeBuiltinRuleOverrides);
|
|
18100
|
+
return {
|
|
18101
|
+
preferences: {
|
|
18102
|
+
...partial,
|
|
18103
|
+
aiPreprocessConfig: {
|
|
18104
|
+
...partial.aiPreprocessConfig,
|
|
18105
|
+
desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,
|
|
18106
|
+
desensitizeBuiltinRuleOverrides: {
|
|
18107
|
+
...legacyBuiltinRuleOverrides,
|
|
18108
|
+
...existingOverrides
|
|
18109
|
+
},
|
|
18110
|
+
desensitizeRules: rules.filter((rule) => !rule.builtin)
|
|
18111
|
+
}
|
|
18112
|
+
},
|
|
18113
|
+
changed: true
|
|
18114
|
+
};
|
|
18115
|
+
}
|
|
18116
|
+
backupLegacyPreferences(rawContent) {
|
|
18117
|
+
const backupDir = path32.join(path32.dirname(this.filePath), "backups");
|
|
18118
|
+
if (!fs35.existsSync(backupDir)) {
|
|
18119
|
+
fs35.mkdirSync(backupDir, { recursive: true });
|
|
18120
|
+
}
|
|
18121
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18122
|
+
const backupPath = path32.join(backupDir, `preferences-pre-desensitize-groups-${timestamp}.json`);
|
|
18123
|
+
fs35.writeFileSync(backupPath, rawContent, "utf-8");
|
|
18124
|
+
console.info(`[Preferences] Backed up legacy desensitize rules to ${backupPath}`);
|
|
18125
|
+
}
|
|
18126
|
+
writePreferences(preferences) {
|
|
18127
|
+
const dir = path32.dirname(this.filePath);
|
|
18128
|
+
if (!fs35.existsSync(dir)) {
|
|
18129
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
18130
|
+
}
|
|
18131
|
+
fs35.writeFileSync(this.filePath, JSON.stringify(preferences, null, 2), "utf-8");
|
|
18132
|
+
}
|
|
18003
18133
|
/**
|
|
18004
18134
|
* Deep merge: arrays are replaced (not concatenated), objects are merged.
|
|
18005
18135
|
*/
|
|
@@ -18794,6 +18924,7 @@ export {
|
|
|
18794
18924
|
getClusterGraph,
|
|
18795
18925
|
getRelationshipStats,
|
|
18796
18926
|
getLanguagePreferenceAnalysis,
|
|
18927
|
+
isNewerStableVersion,
|
|
18797
18928
|
POS_TAG_DEFINITIONS,
|
|
18798
18929
|
BUILTIN_TOOL_CATALOG,
|
|
18799
18930
|
BUILTIN_PROVIDERS,
|
|
@@ -18874,4 +19005,4 @@ export {
|
|
|
18874
19005
|
createDatabaseManagerAdapter,
|
|
18875
19006
|
MergeSessionCache
|
|
18876
19007
|
};
|
|
18877
|
-
//# sourceMappingURL=chunk-
|
|
19008
|
+
//# sourceMappingURL=chunk-N5DGZQB4.mjs.map
|