chatlab-cli 0.34.2 → 0.34.3
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/dist/{chat-command-6IOH2QRF.mjs → chat-command-QH7DXCAJ.mjs} +8 -8
- package/dist/{chunk-JX6MFS6F.mjs → chunk-2Q3HHVTS.mjs} +15 -15
- package/dist/{chunk-INBJ7SND.mjs → chunk-2WYXD5ZP.mjs} +117 -416
- package/dist/chunk-2WYXD5ZP.mjs.map +1 -0
- package/dist/{chunk-U6MVJSXX.mjs → chunk-3X26JJIP.mjs} +15 -9
- package/dist/chunk-3X26JJIP.mjs.map +1 -0
- package/dist/{chunk-UMBEHBIZ.mjs → chunk-6U2QZO3N.mjs} +2 -2
- package/dist/{chunk-52P5ZRBD.mjs → chunk-AWGXYFIC.mjs} +2 -2
- package/dist/{chunk-4LW6443F.mjs → chunk-AWXHYTD5.mjs} +795 -876
- package/dist/chunk-AWXHYTD5.mjs.map +1 -0
- package/dist/{chunk-4RLZFGO5.mjs → chunk-C2PD3BS7.mjs} +2 -2
- package/dist/{chunk-H6D4DZOC.mjs → chunk-JYBPJWE2.mjs} +7 -5
- package/dist/{chunk-H6D4DZOC.mjs.map → chunk-JYBPJWE2.mjs.map} +1 -1
- package/dist/{chunk-652KEAX3.mjs → chunk-SWUTRDGZ.mjs} +2 -2
- package/dist/{chunk-72RWABYJ.mjs → chunk-WJVE5Q4Y.mjs} +3 -3
- package/dist/chunk-WJVE5Q4Y.mjs.map +1 -0
- package/dist/{chunk-2XCNTG4O.mjs → chunk-XIWVJAXH.mjs} +670 -54
- package/dist/chunk-XIWVJAXH.mjs.map +1 -0
- package/dist/{chunk-MENKFEPC.mjs → chunk-ZVGDOSGG.mjs} +29 -41
- package/dist/chunk-ZVGDOSGG.mjs.map +1 -0
- package/dist/cli.mjs +9 -9
- package/dist/contacts-worker.mjs +2 -2
- package/dist/global-insight-worker.mjs +1 -1
- package/dist/{http-HSK46XEU.mjs → http-D2F4QTQW.mjs} +12 -12
- package/dist/{import-DF2WD2HE.mjs → import-H7X2JU2O.mjs} +7 -7
- package/dist/index.mjs +12 -12
- package/dist/{mcp-A2RND7KN.mjs → mcp-UURXRGDF.mjs} +8 -8
- package/dist/people-relationships-worker.mjs +2 -2
- package/dist/semantic-index-worker.mjs +1 -1
- package/dist/{src-SHFHW2QB.mjs → src-MHCO4HYY.mjs} +22 -38
- package/dist/{stream-import-GZ2QDE3Z.mjs → stream-import-BHXACUCA.mjs} +7 -7
- package/dist/{worker-runtime-OWN56GG5.mjs → worker-runtime-JOUCP2L4.mjs} +5 -5
- package/dist-cli-web/assets/ActionToolsPanel.vue_vue_type_script_setup_true_lang-kN3uxTW8.js +110 -0
- package/dist-cli-web/assets/{BufferResource-BdKXeRZS.js → BufferResource-Dak23r3B.js} +1 -1
- package/dist-cli-web/assets/{CanvasRenderer-DDRdIyZ8.js → CanvasRenderer-Cmjtvski.js} +1 -1
- package/dist-cli-web/assets/DataDirCleanupNotice-B5tyDzK-.js +1 -0
- package/dist-cli-web/assets/{EChartWordcloud-CqknPGui.js → EChartWordcloud-Bd3L3G8I.js} +1 -1
- package/dist-cli-web/assets/{Filter-B2eEAPxI.js → Filter-CHKZVYB3.js} +1 -1
- package/dist-cli-web/assets/LoadingState.vue_vue_type_script_setup_true_lang-CKf_gC1k.js +1 -0
- package/dist-cli-web/assets/{MessageExportModal-CZge6qub.js → MessageExportModal-ODYCcSnk.js} +1 -1
- package/dist-cli-web/assets/{PageHeader-CxKbcLDc.js → PageHeader-Bn7Jn8JW.js} +1 -1
- package/dist-cli-web/assets/{RelationshipGalaxyCanvas-CwQ63TPi.js → RelationshipGalaxyCanvas-mJhEPzsY.js} +3 -3
- package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-BLqISQe5.js → RelationshipGalaxyThreeCanvas-Bf76yzmQ.js} +1 -1
- package/dist-cli-web/assets/{RenderTargetSystem-eC_VrDAr.js → RenderTargetSystem-1rM7OF-M.js} +1 -1
- package/dist-cli-web/assets/{ThemeCard.vue_vue_type_script_setup_true_lang-DVmpDz05.js → ThemeCard.vue_vue_type_script_setup_true_lang-CADZpPia.js} +1 -1
- package/dist-cli-web/assets/TimeSelect.vue_vue_type_script_setup_true_lang-I3FYjhfs.js +1 -0
- package/dist-cli-web/assets/{WebGLRenderer-CRp_HC84.js → WebGLRenderer-Y0jQtBvK.js} +1 -1
- package/dist-cli-web/assets/{WebGPURenderer-WIUnEhpi.js → WebGPURenderer-BcUvCPhd.js} +1 -1
- package/dist-cli-web/assets/{annual-summary-time-range-R3pLPEuN.js → annual-summary-time-range-BIADd8qE.js} +1 -1
- package/dist-cli-web/assets/{base-CLwWn3Rs.js → base-BpxxC5Z5.js} +1 -1
- package/dist-cli-web/assets/{browserAll-B29Ox2in.js → browserAll-BsR1UaCC.js} +1 -1
- package/dist-cli-web/assets/{cli-web-CVLb5Pkq.js → cli-web-BiWUOncc.js} +1 -1
- package/dist-cli-web/assets/{dateFormat-T7kMS5IP.js → dateFormat-B6JnNCxp.js} +1 -1
- package/dist-cli-web/assets/{fetch-DvrVGAzR.js → fetch-BAJ_VjWE.js} +1 -1
- package/dist-cli-web/assets/{fetch-BLi6Jsjg.js → fetch-BNcHe2-O.js} +1 -1
- package/dist-cli-web/assets/{fetch-D8hJZa8o.js → fetch-CPloHijF.js} +1 -1
- package/dist-cli-web/assets/{fetch-D9sn99zX.js → fetch-Clj_RVUD.js} +1 -1
- package/dist-cli-web/assets/{fetch-CYaGyohV.js → fetch-D7vgaLpy.js} +1 -1
- package/dist-cli-web/assets/{fetch-DsHf-61a.js → fetch-DGvqctIb.js} +1 -1
- package/dist-cli-web/assets/fetch-DSxgaVBO.js +1 -0
- package/dist-cli-web/assets/{fetch-BKBlpBl4.js → fetch-DtnhbqTN.js} +1 -1
- package/dist-cli-web/assets/{fetch-BBgZQob_.js → fetch-bdY0RMM3.js} +1 -1
- package/dist-cli-web/assets/{fetch-L6PKD8-N.js → fetch-bhHY8rO7.js} +1 -1
- package/dist-cli-web/assets/index-B6Gq11lw.css +1 -0
- package/dist-cli-web/assets/index-BJ2lywiG.js +1 -0
- package/dist-cli-web/assets/{index-C4TuoOLM.js → index-BT3_fSP6.js} +2 -2
- package/dist-cli-web/assets/{index-CkgUsaeX.js → index-BVZhP1J5.js} +1 -1
- package/dist-cli-web/assets/index-Br8r4pu8.js +1 -0
- package/dist-cli-web/assets/index-Byok4VaA.css +1 -0
- package/dist-cli-web/assets/index-CKnnxOci.js +1 -0
- package/dist-cli-web/assets/index-CXnYfvTv.js +137 -0
- package/dist-cli-web/assets/index-CsFLLk3T.css +1 -0
- package/dist-cli-web/assets/index-CzoOQ7zg.js +1 -0
- package/dist-cli-web/assets/{index-C6Mk-Xqt.js → index-D-dTTUGj.js} +1 -1
- package/dist-cli-web/assets/index-DEbvEKzi.js +2 -0
- package/dist-cli-web/assets/{index-0qcENyvH.js → index-DMYFpctK.js} +1 -1
- package/dist-cli-web/assets/index-KO7uPd8W.js +64 -0
- package/dist-cli-web/assets/index-lkmJ6dI7.js +1 -0
- package/dist-cli-web/assets/{index-D_0qeKKc.js → index-y7xPDpsW.js} +5 -5
- package/dist-cli-web/assets/{people-page-header-CCNJOrmK.js → people-page-header-gjTyODWs.js} +1 -1
- package/dist-cli-web/assets/{webworkerAll-B2qvP2qR.js → webworkerAll-CfZWlukP.js} +1 -1
- package/dist-cli-web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-2XCNTG4O.mjs.map +0 -1
- package/dist/chunk-4LW6443F.mjs.map +0 -1
- package/dist/chunk-72RWABYJ.mjs.map +0 -1
- package/dist/chunk-INBJ7SND.mjs.map +0 -1
- package/dist/chunk-MENKFEPC.mjs.map +0 -1
- package/dist/chunk-U6MVJSXX.mjs.map +0 -1
- package/dist-cli-web/assets/ActionToolsPanel.vue_vue_type_script_setup_true_lang-B06LYYS9.js +0 -110
- package/dist-cli-web/assets/DataDirCleanupNotice-CP8P1lsL.js +0 -1
- package/dist-cli-web/assets/LoadingState.vue_vue_type_script_setup_true_lang-BFaXTz1c.js +0 -1
- package/dist-cli-web/assets/TimeSelect.vue_vue_type_script_setup_true_lang-CCH1UQGc.js +0 -1
- package/dist-cli-web/assets/fetch-Cm2WR2Cv.js +0 -1
- package/dist-cli-web/assets/index-AkF_KqVI.js +0 -1
- package/dist-cli-web/assets/index-BVOFyB9E.js +0 -137
- package/dist-cli-web/assets/index-BkdOH41D.js +0 -1
- package/dist-cli-web/assets/index-CuAy1Xmt.js +0 -64
- package/dist-cli-web/assets/index-DeR0Vukh.js +0 -1
- package/dist-cli-web/assets/index-DrjoMv9s.css +0 -1
- package/dist-cli-web/assets/index-Dx-XvfIK.js +0 -2
- package/dist-cli-web/assets/index-Jhwca9kg.css +0 -1
- package/dist-cli-web/assets/index-_DrviTnP.js +0 -1
- package/dist-cli-web/assets/index-vtF05fh7.css +0 -1
- package/dist-cli-web/assets/index-xN0sjOLK.js +0 -1
- /package/dist/{chat-command-6IOH2QRF.mjs.map → chat-command-QH7DXCAJ.mjs.map} +0 -0
- /package/dist/{chunk-JX6MFS6F.mjs.map → chunk-2Q3HHVTS.mjs.map} +0 -0
- /package/dist/{chunk-UMBEHBIZ.mjs.map → chunk-6U2QZO3N.mjs.map} +0 -0
- /package/dist/{chunk-52P5ZRBD.mjs.map → chunk-AWGXYFIC.mjs.map} +0 -0
- /package/dist/{chunk-4RLZFGO5.mjs.map → chunk-C2PD3BS7.mjs.map} +0 -0
- /package/dist/{chunk-652KEAX3.mjs.map → chunk-SWUTRDGZ.mjs.map} +0 -0
- /package/dist/{http-HSK46XEU.mjs.map → http-D2F4QTQW.mjs.map} +0 -0
- /package/dist/{import-DF2WD2HE.mjs.map → import-H7X2JU2O.mjs.map} +0 -0
- /package/dist/{mcp-A2RND7KN.mjs.map → mcp-UURXRGDF.mjs.map} +0 -0
- /package/dist/{src-SHFHW2QB.mjs.map → src-MHCO4HYY.mjs.map} +0 -0
- /package/dist/{stream-import-GZ2QDE3Z.mjs.map → stream-import-BHXACUCA.mjs.map} +0 -0
- /package/dist/{worker-runtime-OWN56GG5.mjs.map → worker-runtime-JOUCP2L4.mjs.map} +0 -0
|
@@ -4273,7 +4273,8 @@ function getLaughAnalysis(db, filter, keywords) {
|
|
|
4273
4273
|
totalMessages: 0,
|
|
4274
4274
|
groupLaughRate: 0
|
|
4275
4275
|
};
|
|
4276
|
-
const laughKeywords = keywords
|
|
4276
|
+
const laughKeywords = keywords?.map((keyword) => keyword.trim()).filter(Boolean) ?? [];
|
|
4277
|
+
if (laughKeywords.length === 0) return emptyResult;
|
|
4277
4278
|
const patterns = laughKeywords.map(keywordToPattern);
|
|
4278
4279
|
const laughRegex = new RegExp(`(${patterns.join("|")})`, "gi");
|
|
4279
4280
|
const { clause, params } = buildTimeFilter(filter);
|
|
@@ -6223,8 +6224,8 @@ function getJourneyStats(db, filter) {
|
|
|
6223
6224
|
const indexAvailable = hasSessionIndex(db) && hasTable(db, "message_context");
|
|
6224
6225
|
const segmentRows = indexAvailable ? querySegmentRows(db, effectiveFilter) : [];
|
|
6225
6226
|
const segmentCountByMonth = /* @__PURE__ */ new Map();
|
|
6226
|
-
for (const
|
|
6227
|
-
segmentCountByMonth.set(
|
|
6227
|
+
for (const segment of segmentRows) {
|
|
6228
|
+
segmentCountByMonth.set(segment.startMonth, (segmentCountByMonth.get(segment.startMonth) ?? 0) + 1);
|
|
6228
6229
|
}
|
|
6229
6230
|
const firstRow = monthlyRows[0];
|
|
6230
6231
|
const lastRow = monthlyRows[monthlyRows.length - 1];
|
|
@@ -7702,7 +7703,7 @@ function mergeMembers2(sources, collidingIds) {
|
|
|
7702
7703
|
}
|
|
7703
7704
|
|
|
7704
7705
|
// ../../packages/core/src/schema/tables.ts
|
|
7705
|
-
var CURRENT_SCHEMA_VERSION =
|
|
7706
|
+
var CURRENT_SCHEMA_VERSION = 9;
|
|
7706
7707
|
var CHAT_DB_TABLES = `
|
|
7707
7708
|
CREATE TABLE IF NOT EXISTS meta (
|
|
7708
7709
|
name TEXT NOT NULL,
|
|
@@ -7776,13 +7777,6 @@ var CHAT_DB_INDEXES = `
|
|
|
7776
7777
|
CREATE INDEX IF NOT EXISTS idx_context_segment ON message_context(segment_id);
|
|
7777
7778
|
`;
|
|
7778
7779
|
var CHAT_DB_SCHEMA = CHAT_DB_TABLES + CHAT_DB_INDEXES;
|
|
7779
|
-
var FTS_TABLE_SCHEMA = `
|
|
7780
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS message_fts USING fts5(
|
|
7781
|
-
content,
|
|
7782
|
-
content='',
|
|
7783
|
-
content_rowid=id
|
|
7784
|
-
);
|
|
7785
|
-
`;
|
|
7786
7780
|
|
|
7787
7781
|
// ../../packages/core/src/schema/migrations.ts
|
|
7788
7782
|
function getSchemaVersion(db) {
|
|
@@ -8040,282 +8034,30 @@ var appLogger = {
|
|
|
8040
8034
|
getLogPath: () => instance?.getLogPath() ?? null
|
|
8041
8035
|
};
|
|
8042
8036
|
|
|
8043
|
-
// ../../packages/node-runtime/src/nlp/segmenter.ts
|
|
8044
|
-
import * as fs8 from "fs";
|
|
8045
|
-
import * as path13 from "path";
|
|
8046
|
-
import { createRequire } from "module";
|
|
8047
|
-
var _nlpDir = null;
|
|
8048
|
-
var jiebaInstances = /* @__PURE__ */ new Map();
|
|
8049
|
-
var require2 = createRequire(import.meta.url);
|
|
8050
|
-
function initNlpDir(nlpDir) {
|
|
8051
|
-
_nlpDir = nlpDir;
|
|
8052
|
-
}
|
|
8053
|
-
function getNlpDir() {
|
|
8054
|
-
return _nlpDir;
|
|
8055
|
-
}
|
|
8056
|
-
function existsDictOnDisk(dictId) {
|
|
8057
|
-
if (!_nlpDir) return false;
|
|
8058
|
-
return fs8.existsSync(path13.join(_nlpDir, `${dictId}.dict`));
|
|
8059
|
-
}
|
|
8060
|
-
function tryLoadDictFromDisk(dictId) {
|
|
8061
|
-
if (!_nlpDir) return null;
|
|
8062
|
-
const dictPath = path13.join(_nlpDir, `${dictId}.dict`);
|
|
8063
|
-
if (!fs8.existsSync(dictPath)) return null;
|
|
8064
|
-
try {
|
|
8065
|
-
return fs8.readFileSync(dictPath);
|
|
8066
|
-
} catch {
|
|
8067
|
-
return null;
|
|
8068
|
-
}
|
|
8069
|
-
}
|
|
8070
|
-
function getJieba(dictType = "default") {
|
|
8071
|
-
const effectiveType = dictType === "default" ? "zh-CN" : dictType;
|
|
8072
|
-
const cached = jiebaInstances.get(effectiveType);
|
|
8073
|
-
if (cached) {
|
|
8074
|
-
if (cached.fromDiskDict === existsDictOnDisk(effectiveType)) return cached.instance;
|
|
8075
|
-
jiebaInstances.delete(effectiveType);
|
|
8076
|
-
console.error(`[NLP] jieba cache invalidated (dict ${cached.fromDiskDict ? "removed" : "added"}): ${effectiveType}`);
|
|
8077
|
-
}
|
|
8078
|
-
try {
|
|
8079
|
-
const { Jieba } = require2("@node-rs/jieba");
|
|
8080
|
-
let instance2;
|
|
8081
|
-
const diskDict = tryLoadDictFromDisk(effectiveType);
|
|
8082
|
-
if (diskDict) {
|
|
8083
|
-
instance2 = Jieba.withDict(diskDict);
|
|
8084
|
-
console.error(`[NLP] jieba dict loaded: ${effectiveType} (${diskDict.length} bytes)`);
|
|
8085
|
-
} else {
|
|
8086
|
-
instance2 = new Jieba();
|
|
8087
|
-
console.warn(`[NLP] jieba dict missing: ${effectiveType}, fallback to built-in tokenizer`);
|
|
8088
|
-
}
|
|
8089
|
-
jiebaInstances.set(effectiveType, { instance: instance2, fromDiskDict: !!diskDict });
|
|
8090
|
-
return instance2;
|
|
8091
|
-
} catch (error) {
|
|
8092
|
-
console.error(`[NLP] Failed to load jieba module (dict=${effectiveType}):`, error);
|
|
8093
|
-
throw new Error(`jieba \u6A21\u5757\u52A0\u8F7D\u5931\u8D25 (${effectiveType})`);
|
|
8094
|
-
}
|
|
8095
|
-
}
|
|
8096
|
-
function clearJiebaInstance(dictType) {
|
|
8097
|
-
jiebaInstances.delete(dictType);
|
|
8098
|
-
console.error(`[NLP] jieba instance cleared: ${dictType}`);
|
|
8099
|
-
}
|
|
8100
|
-
function segmentChinese(text, options = {}) {
|
|
8101
|
-
const { posFilterMode = "meaningful", customPosTags, dictType = "default" } = options;
|
|
8102
|
-
const cleaned = cleanText(text);
|
|
8103
|
-
if (!cleaned) return [];
|
|
8104
|
-
try {
|
|
8105
|
-
const jieba = getJieba(dictType);
|
|
8106
|
-
if (posFilterMode === "all") return jieba.cut(cleaned, false);
|
|
8107
|
-
const tagged = jieba.tag(cleaned);
|
|
8108
|
-
const allowedTags = posFilterMode === "custom" && customPosTags ? new Set(customPosTags) : MEANINGFUL_POS_TAGS;
|
|
8109
|
-
return tagged.filter((item) => allowedTags.has(item.tag)).map((item) => item.word);
|
|
8110
|
-
} catch (error) {
|
|
8111
|
-
console.error("[NLP] Chinese segmentation failed:", error);
|
|
8112
|
-
try {
|
|
8113
|
-
return getJieba("default").cut(cleanText(text), false);
|
|
8114
|
-
} catch {
|
|
8115
|
-
return cleaned.split("");
|
|
8116
|
-
}
|
|
8117
|
-
}
|
|
8118
|
-
}
|
|
8119
|
-
function segmentEnglish(text) {
|
|
8120
|
-
const cleaned = cleanText(text);
|
|
8121
|
-
if (!cleaned) return [];
|
|
8122
|
-
try {
|
|
8123
|
-
const segmenter = new Intl.Segmenter("en", { granularity: "word" });
|
|
8124
|
-
return [...segmenter.segment(cleaned)].filter((s) => s.isWordLike).map((s) => s.segment.toLowerCase());
|
|
8125
|
-
} catch {
|
|
8126
|
-
return cleaned.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
|
|
8127
|
-
}
|
|
8128
|
-
}
|
|
8129
|
-
function segmentJapanese(text) {
|
|
8130
|
-
const cleaned = cleanText(text);
|
|
8131
|
-
if (!cleaned) return [];
|
|
8132
|
-
try {
|
|
8133
|
-
const segmenter = new Intl.Segmenter("ja", { granularity: "word" });
|
|
8134
|
-
return [...segmenter.segment(cleaned)].filter((s) => s.isWordLike).map((s) => s.segment);
|
|
8135
|
-
} catch {
|
|
8136
|
-
return cleaned.split("").filter((ch) => ch.trim().length > 0);
|
|
8137
|
-
}
|
|
8138
|
-
}
|
|
8139
|
-
function segment(text, locale, options = {}) {
|
|
8140
|
-
const {
|
|
8141
|
-
minLength,
|
|
8142
|
-
posFilterMode = "meaningful",
|
|
8143
|
-
customPosTags,
|
|
8144
|
-
enableStopwords = true,
|
|
8145
|
-
dictType = "default"
|
|
8146
|
-
} = options;
|
|
8147
|
-
const isChinese = locale.startsWith("zh");
|
|
8148
|
-
const isJapanese = locale === "ja-JP";
|
|
8149
|
-
const defaultMinLength = isChinese || isJapanese ? 2 : 3;
|
|
8150
|
-
const effectiveMinLength = minLength ?? defaultMinLength;
|
|
8151
|
-
let words;
|
|
8152
|
-
if (isChinese) {
|
|
8153
|
-
words = segmentChinese(text, { posFilterMode, customPosTags, dictType });
|
|
8154
|
-
} else if (isJapanese) {
|
|
8155
|
-
words = segmentJapanese(text);
|
|
8156
|
-
} else {
|
|
8157
|
-
words = segmentEnglish(text);
|
|
8158
|
-
}
|
|
8159
|
-
return words.filter((word) => isValidWord(word, locale, effectiveMinLength, enableStopwords, isStopword));
|
|
8160
|
-
}
|
|
8161
|
-
function batchSegmentWithFrequency(texts, locale, options = {}) {
|
|
8162
|
-
const {
|
|
8163
|
-
minLength,
|
|
8164
|
-
minCount = 2,
|
|
8165
|
-
topN = 100,
|
|
8166
|
-
posFilterMode,
|
|
8167
|
-
customPosTags,
|
|
8168
|
-
enableStopwords,
|
|
8169
|
-
dictType,
|
|
8170
|
-
excludeWords
|
|
8171
|
-
} = options;
|
|
8172
|
-
const wordFrequency = /* @__PURE__ */ new Map();
|
|
8173
|
-
const excludeSet = excludeWords?.length ? new Set(excludeWords.map((w) => w.toLowerCase())) : null;
|
|
8174
|
-
for (const text of texts) {
|
|
8175
|
-
const words = segment(text, locale, { minLength, posFilterMode, customPosTags, enableStopwords, dictType });
|
|
8176
|
-
for (const word of words) {
|
|
8177
|
-
if (excludeSet && excludeSet.has(word.toLowerCase())) continue;
|
|
8178
|
-
wordFrequency.set(word, (wordFrequency.get(word) || 0) + 1);
|
|
8179
|
-
}
|
|
8180
|
-
}
|
|
8181
|
-
const filtered = /* @__PURE__ */ new Map();
|
|
8182
|
-
let totalWords = 0;
|
|
8183
|
-
for (const [word, count] of wordFrequency) {
|
|
8184
|
-
if (count >= minCount) {
|
|
8185
|
-
filtered.set(word, count);
|
|
8186
|
-
totalWords += count;
|
|
8187
|
-
}
|
|
8188
|
-
}
|
|
8189
|
-
const sorted = [...filtered.entries()].sort((a, b) => b[1] - a[1]).slice(0, topN);
|
|
8190
|
-
return { words: new Map(sorted), uniqueWords: filtered.size, totalWords };
|
|
8191
|
-
}
|
|
8192
|
-
function batchSegmentChineseWithStats(texts, locale, options = {}) {
|
|
8193
|
-
const {
|
|
8194
|
-
minLength,
|
|
8195
|
-
minCount = 2,
|
|
8196
|
-
topN = 100,
|
|
8197
|
-
posFilterMode = "meaningful",
|
|
8198
|
-
customPosTags,
|
|
8199
|
-
enableStopwords = true,
|
|
8200
|
-
dictType = "default",
|
|
8201
|
-
excludeWords
|
|
8202
|
-
} = options;
|
|
8203
|
-
const effectiveMinLength = minLength ?? 2;
|
|
8204
|
-
const allowedTags = posFilterMode === "custom" && customPosTags ? new Set(customPosTags) : MEANINGFUL_POS_TAGS;
|
|
8205
|
-
const excludeSet = excludeWords?.length ? new Set(excludeWords.map((w) => w.toLowerCase())) : null;
|
|
8206
|
-
const wordFrequency = /* @__PURE__ */ new Map();
|
|
8207
|
-
const posTagStats = /* @__PURE__ */ new Map();
|
|
8208
|
-
try {
|
|
8209
|
-
const jieba = getJieba(dictType);
|
|
8210
|
-
for (const text of texts) {
|
|
8211
|
-
const cleaned = cleanText(text);
|
|
8212
|
-
if (!cleaned) continue;
|
|
8213
|
-
for (const { tag, word } of jieba.tag(cleaned)) {
|
|
8214
|
-
if (!isValidWord(word, locale, effectiveMinLength, enableStopwords, isStopword)) continue;
|
|
8215
|
-
posTagStats.set(tag, (posTagStats.get(tag) || 0) + 1);
|
|
8216
|
-
if (!allowedTags.has(tag)) continue;
|
|
8217
|
-
if (excludeSet && excludeSet.has(word.toLowerCase())) continue;
|
|
8218
|
-
wordFrequency.set(word, (wordFrequency.get(word) || 0) + 1);
|
|
8219
|
-
}
|
|
8220
|
-
}
|
|
8221
|
-
} catch (error) {
|
|
8222
|
-
console.error("[NLP] Chinese single-pass segmentation failed:", error);
|
|
8223
|
-
}
|
|
8224
|
-
const filtered = /* @__PURE__ */ new Map();
|
|
8225
|
-
let totalWords = 0;
|
|
8226
|
-
for (const [word, count] of wordFrequency) {
|
|
8227
|
-
if (count >= minCount) {
|
|
8228
|
-
filtered.set(word, count);
|
|
8229
|
-
totalWords += count;
|
|
8230
|
-
}
|
|
8231
|
-
}
|
|
8232
|
-
const sorted = [...filtered.entries()].sort((a, b) => b[1] - a[1]).slice(0, topN);
|
|
8233
|
-
return { words: new Map(sorted), uniqueWords: filtered.size, totalWords, posTagStats };
|
|
8234
|
-
}
|
|
8235
|
-
function collectPosTagStats(texts, minWordLength = 2, enableStopwords = true, dictType = "default") {
|
|
8236
|
-
const posStats = /* @__PURE__ */ new Map();
|
|
8237
|
-
try {
|
|
8238
|
-
const jieba = getJieba(dictType);
|
|
8239
|
-
for (const text of texts) {
|
|
8240
|
-
const cleaned = cleanText(text);
|
|
8241
|
-
if (!cleaned) continue;
|
|
8242
|
-
const tagged = jieba.tag(cleaned);
|
|
8243
|
-
for (const item of tagged) {
|
|
8244
|
-
if (!isValidWord(item.word, "zh-CN", minWordLength, enableStopwords, isStopword)) continue;
|
|
8245
|
-
posStats.set(item.tag, (posStats.get(item.tag) || 0) + 1);
|
|
8246
|
-
}
|
|
8247
|
-
}
|
|
8248
|
-
} catch (error) {
|
|
8249
|
-
console.error("[NLP] Failed to collect POS stats:", error);
|
|
8250
|
-
}
|
|
8251
|
-
return posStats;
|
|
8252
|
-
}
|
|
8253
|
-
function getPosTagDefinitions() {
|
|
8254
|
-
return POS_TAG_DEFINITIONS;
|
|
8255
|
-
}
|
|
8256
|
-
|
|
8257
|
-
// ../../packages/node-runtime/src/nlp/fts-tokenizer.ts
|
|
8258
|
-
function tokenizeForFts(text) {
|
|
8259
|
-
if (!text || text.trim().length === 0) return "";
|
|
8260
|
-
try {
|
|
8261
|
-
const jieba = getJieba();
|
|
8262
|
-
const tokens = jieba.cut(text, false);
|
|
8263
|
-
return tokens.map((t) => t.trim().toLowerCase()).filter((t) => t.length > 0).join(" ");
|
|
8264
|
-
} catch {
|
|
8265
|
-
return fallbackTokenize(text);
|
|
8266
|
-
}
|
|
8267
|
-
}
|
|
8268
|
-
function fallbackTokenize(text) {
|
|
8269
|
-
return text.toLowerCase().split(/\s+/).filter((t) => t.length > 0).join(" ");
|
|
8270
|
-
}
|
|
8271
|
-
function escapeToken(token) {
|
|
8272
|
-
return `"${token.replace(/"/g, '""')}"`;
|
|
8273
|
-
}
|
|
8274
|
-
function tokenizeQueryForFts(keywords) {
|
|
8275
|
-
if (keywords.length === 0) return "";
|
|
8276
|
-
const groups = keywords.map((kw) => {
|
|
8277
|
-
const trimmed = kw.trim();
|
|
8278
|
-
if (!trimmed) return "";
|
|
8279
|
-
try {
|
|
8280
|
-
const jieba = getJieba();
|
|
8281
|
-
const tokens = jieba.cut(trimmed, false).map((t) => t.trim().toLowerCase()).filter((t) => t.length > 0);
|
|
8282
|
-
if (tokens.length === 0) return "";
|
|
8283
|
-
if (tokens.length === 1) return escapeToken(tokens[0]);
|
|
8284
|
-
return tokens.map(escapeToken).join(" ");
|
|
8285
|
-
} catch {
|
|
8286
|
-
const simple = trimmed.toLowerCase().trim();
|
|
8287
|
-
return simple ? escapeToken(simple) : "";
|
|
8288
|
-
}
|
|
8289
|
-
}).filter((g) => g.length > 0);
|
|
8290
|
-
if (groups.length === 0) return "";
|
|
8291
|
-
if (groups.length === 1) return groups[0];
|
|
8292
|
-
return groups.map((g) => g.includes(" ") ? `(${g})` : g).join(" OR ");
|
|
8293
|
-
}
|
|
8294
|
-
|
|
8295
8037
|
// ../../packages/node-runtime/src/migrations/electron-data-migration.ts
|
|
8296
|
-
import * as
|
|
8038
|
+
import * as fs8 from "fs";
|
|
8297
8039
|
import * as os3 from "os";
|
|
8298
|
-
import * as
|
|
8040
|
+
import * as path13 from "path";
|
|
8299
8041
|
var SYSTEM_SUBDIRS = ["ai", "settings", "cache", "logs", "nlp"];
|
|
8300
8042
|
var STORAGE_CONFIG_FILE = "storage.json";
|
|
8301
8043
|
function getElectronUserDataDir(options = {}) {
|
|
8302
8044
|
const home = options.homeDir ?? os3.homedir();
|
|
8303
8045
|
switch (options.platform ?? process.platform) {
|
|
8304
8046
|
case "darwin":
|
|
8305
|
-
return
|
|
8047
|
+
return path13.join(home, "Library", "Application Support", "ChatLab");
|
|
8306
8048
|
case "win32": {
|
|
8307
|
-
const appData = options.appDataDir ?? process.env.APPDATA ??
|
|
8308
|
-
return
|
|
8049
|
+
const appData = options.appDataDir ?? process.env.APPDATA ?? path13.join(home, "AppData", "Roaming");
|
|
8050
|
+
return path13.join(appData, "ChatLab");
|
|
8309
8051
|
}
|
|
8310
8052
|
default:
|
|
8311
|
-
return
|
|
8053
|
+
return path13.join(home, ".config", "ChatLab");
|
|
8312
8054
|
}
|
|
8313
8055
|
}
|
|
8314
8056
|
function readElectronStorageConfig(electronUserData) {
|
|
8315
|
-
const configPath =
|
|
8316
|
-
if (!
|
|
8057
|
+
const configPath = path13.join(electronUserData, STORAGE_CONFIG_FILE);
|
|
8058
|
+
if (!fs8.existsSync(configPath)) return {};
|
|
8317
8059
|
try {
|
|
8318
|
-
return JSON.parse(
|
|
8060
|
+
return JSON.parse(fs8.readFileSync(configPath, "utf-8"));
|
|
8319
8061
|
} catch {
|
|
8320
8062
|
return {};
|
|
8321
8063
|
}
|
|
@@ -8323,45 +8065,45 @@ function readElectronStorageConfig(electronUserData) {
|
|
|
8323
8065
|
function resolveElectronDataDir() {
|
|
8324
8066
|
const electronUserData = getElectronUserDataDir();
|
|
8325
8067
|
const storageConfig = readElectronStorageConfig(electronUserData);
|
|
8326
|
-
if (storageConfig.dataDir &&
|
|
8068
|
+
if (storageConfig.dataDir && path13.isAbsolute(storageConfig.dataDir)) {
|
|
8327
8069
|
return storageConfig.dataDir;
|
|
8328
8070
|
}
|
|
8329
|
-
return
|
|
8071
|
+
return path13.join(electronUserData, "data");
|
|
8330
8072
|
}
|
|
8331
8073
|
function hasDatabases(dir) {
|
|
8332
|
-
const dbDir =
|
|
8333
|
-
if (!
|
|
8074
|
+
const dbDir = path13.join(dir, "databases");
|
|
8075
|
+
if (!fs8.existsSync(dbDir)) return false;
|
|
8334
8076
|
try {
|
|
8335
|
-
return
|
|
8077
|
+
return fs8.readdirSync(dbDir).some((f) => f.endsWith(".db"));
|
|
8336
8078
|
} catch {
|
|
8337
8079
|
return false;
|
|
8338
8080
|
}
|
|
8339
8081
|
}
|
|
8340
8082
|
function ensureDir2(dirPath) {
|
|
8341
|
-
if (!
|
|
8342
|
-
|
|
8083
|
+
if (!fs8.existsSync(dirPath)) {
|
|
8084
|
+
fs8.mkdirSync(dirPath, { recursive: true });
|
|
8343
8085
|
}
|
|
8344
8086
|
}
|
|
8345
8087
|
function copyDirMerge(src, dest) {
|
|
8346
8088
|
const stats = { copied: 0, skipped: 0 };
|
|
8347
|
-
if (!
|
|
8089
|
+
if (!fs8.existsSync(src)) return stats;
|
|
8348
8090
|
ensureDir2(dest);
|
|
8349
8091
|
let entries;
|
|
8350
8092
|
try {
|
|
8351
|
-
entries =
|
|
8093
|
+
entries = fs8.readdirSync(src, { withFileTypes: true });
|
|
8352
8094
|
} catch {
|
|
8353
8095
|
return stats;
|
|
8354
8096
|
}
|
|
8355
8097
|
for (const entry of entries) {
|
|
8356
|
-
const srcPath =
|
|
8357
|
-
const destPath =
|
|
8098
|
+
const srcPath = path13.join(src, entry.name);
|
|
8099
|
+
const destPath = path13.join(dest, entry.name);
|
|
8358
8100
|
try {
|
|
8359
8101
|
if (entry.isDirectory()) {
|
|
8360
8102
|
const sub = copyDirMerge(srcPath, destPath);
|
|
8361
8103
|
stats.copied += sub.copied;
|
|
8362
8104
|
stats.skipped += sub.skipped;
|
|
8363
|
-
} else if (!
|
|
8364
|
-
|
|
8105
|
+
} else if (!fs8.existsSync(destPath)) {
|
|
8106
|
+
fs8.copyFileSync(srcPath, destPath);
|
|
8365
8107
|
stats.copied++;
|
|
8366
8108
|
} else {
|
|
8367
8109
|
stats.skipped++;
|
|
@@ -8374,22 +8116,22 @@ function copyDirMerge(src, dest) {
|
|
|
8374
8116
|
function writeMigrationLog(logDir, message) {
|
|
8375
8117
|
try {
|
|
8376
8118
|
ensureDir2(logDir);
|
|
8377
|
-
const logPath =
|
|
8119
|
+
const logPath = path13.join(logDir, "app.log");
|
|
8378
8120
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
8379
|
-
|
|
8121
|
+
fs8.appendFileSync(logPath, `[${ts}] [MIGRATION] ${message}
|
|
8380
8122
|
`, "utf-8");
|
|
8381
8123
|
} catch {
|
|
8382
8124
|
}
|
|
8383
8125
|
}
|
|
8384
8126
|
function wasElectronUsed() {
|
|
8385
8127
|
const electronUserData = getElectronUserDataDir();
|
|
8386
|
-
if (!
|
|
8387
|
-
return
|
|
8128
|
+
if (!fs8.existsSync(electronUserData)) return false;
|
|
8129
|
+
return fs8.existsSync(path13.join(electronUserData, "Preferences")) || fs8.existsSync(path13.join(electronUserData, "Local Storage")) || fs8.existsSync(path13.join(electronUserData, "Session Storage")) || fs8.existsSync(path13.join(electronUserData, "data"));
|
|
8388
8130
|
}
|
|
8389
8131
|
function verifyCliDataPath(databaseDir) {
|
|
8390
|
-
if (
|
|
8132
|
+
if (fs8.existsSync(databaseDir)) {
|
|
8391
8133
|
try {
|
|
8392
|
-
if (
|
|
8134
|
+
if (fs8.readdirSync(databaseDir).some((f) => f.endsWith(".db"))) return true;
|
|
8393
8135
|
} catch {
|
|
8394
8136
|
}
|
|
8395
8137
|
}
|
|
@@ -8407,9 +8149,9 @@ function migrateFromElectronIfNeeded(systemDir) {
|
|
|
8407
8149
|
let totalSkipped = 0;
|
|
8408
8150
|
const movedDirs = [];
|
|
8409
8151
|
for (const subDir of SYSTEM_SUBDIRS) {
|
|
8410
|
-
const srcDir =
|
|
8411
|
-
const destDir =
|
|
8412
|
-
if (!
|
|
8152
|
+
const srcDir = path13.join(electronDataDir, subDir);
|
|
8153
|
+
const destDir = path13.join(systemDir, subDir);
|
|
8154
|
+
if (!fs8.existsSync(srcDir)) continue;
|
|
8413
8155
|
const { copied, skipped } = copyDirMerge(srcDir, destDir);
|
|
8414
8156
|
if (copied > 0 || skipped > 0) {
|
|
8415
8157
|
movedDirs.push(subDir);
|
|
@@ -8419,13 +8161,13 @@ function migrateFromElectronIfNeeded(systemDir) {
|
|
|
8419
8161
|
}
|
|
8420
8162
|
}
|
|
8421
8163
|
for (const subDir of movedDirs) {
|
|
8422
|
-
const srcDir =
|
|
8164
|
+
const srcDir = path13.join(electronDataDir, subDir);
|
|
8423
8165
|
try {
|
|
8424
|
-
|
|
8166
|
+
fs8.rmSync(srcDir, { recursive: true, force: true });
|
|
8425
8167
|
} catch {
|
|
8426
8168
|
}
|
|
8427
8169
|
}
|
|
8428
|
-
const logsDir =
|
|
8170
|
+
const logsDir = path13.join(systemDir, "logs");
|
|
8429
8171
|
const summary = `CLI first-run: detected Electron data at ${electronDataDir}, pointed user_data_dir there, copied ${totalCopied} system files (${movedDirs.join(", ") || "none"})`;
|
|
8430
8172
|
writeMigrationLog(logsDir, summary);
|
|
8431
8173
|
console.log(`[Migration] ${summary}`);
|
|
@@ -8439,7 +8181,7 @@ function migrateFromElectronIfNeeded(systemDir) {
|
|
|
8439
8181
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
8440
8182
|
console.error("[Migration] Electron data migration failed:", errorMsg);
|
|
8441
8183
|
try {
|
|
8442
|
-
writeMigrationLog(
|
|
8184
|
+
writeMigrationLog(path13.join(systemDir, "logs"), `Electron migration failed: ${errorMsg}`);
|
|
8443
8185
|
} catch {
|
|
8444
8186
|
}
|
|
8445
8187
|
return { migrated: false, electronDetected: true, error: errorMsg };
|
|
@@ -8447,26 +8189,26 @@ function migrateFromElectronIfNeeded(systemDir) {
|
|
|
8447
8189
|
}
|
|
8448
8190
|
|
|
8449
8191
|
// ../../packages/node-runtime/src/cache/session-cache.ts
|
|
8450
|
-
import * as
|
|
8451
|
-
import * as
|
|
8192
|
+
import * as fs9 from "fs";
|
|
8193
|
+
import * as path14 from "path";
|
|
8452
8194
|
function getCachePath(sessionId, cacheDir) {
|
|
8453
|
-
return
|
|
8195
|
+
return path14.join(cacheDir, `${sessionId}.cache.json`);
|
|
8454
8196
|
}
|
|
8455
8197
|
function readCacheFile(cachePath) {
|
|
8456
8198
|
try {
|
|
8457
|
-
if (!
|
|
8458
|
-
return JSON.parse(
|
|
8199
|
+
if (!fs9.existsSync(cachePath)) return null;
|
|
8200
|
+
return JSON.parse(fs9.readFileSync(cachePath, "utf-8"));
|
|
8459
8201
|
} catch {
|
|
8460
8202
|
return null;
|
|
8461
8203
|
}
|
|
8462
8204
|
}
|
|
8463
8205
|
function writeCacheFile(cachePath, content) {
|
|
8464
8206
|
try {
|
|
8465
|
-
const dir =
|
|
8466
|
-
if (!
|
|
8467
|
-
|
|
8207
|
+
const dir = path14.dirname(cachePath);
|
|
8208
|
+
if (!fs9.existsSync(dir)) {
|
|
8209
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
8468
8210
|
}
|
|
8469
|
-
|
|
8211
|
+
fs9.writeFileSync(cachePath, JSON.stringify(content), "utf-8");
|
|
8470
8212
|
} catch {
|
|
8471
8213
|
}
|
|
8472
8214
|
}
|
|
@@ -8486,7 +8228,7 @@ function invalidateCache(sessionId, cacheDir, key) {
|
|
|
8486
8228
|
const cachePath = getCachePath(sessionId, cacheDir);
|
|
8487
8229
|
try {
|
|
8488
8230
|
if (!key) {
|
|
8489
|
-
if (
|
|
8231
|
+
if (fs9.existsSync(cachePath)) fs9.unlinkSync(cachePath);
|
|
8490
8232
|
} else {
|
|
8491
8233
|
const file = readCacheFile(cachePath);
|
|
8492
8234
|
if (file && file[key]) {
|
|
@@ -8500,7 +8242,7 @@ function invalidateCache(sessionId, cacheDir, key) {
|
|
|
8500
8242
|
function deleteSessionCache(sessionId, cacheDir) {
|
|
8501
8243
|
const cachePath = getCachePath(sessionId, cacheDir);
|
|
8502
8244
|
try {
|
|
8503
|
-
if (
|
|
8245
|
+
if (fs9.existsSync(cachePath)) fs9.unlinkSync(cachePath);
|
|
8504
8246
|
} catch {
|
|
8505
8247
|
}
|
|
8506
8248
|
}
|
|
@@ -8554,8 +8296,8 @@ function computeAndSetMembersCache(db, sessionId, cacheDir) {
|
|
|
8554
8296
|
}
|
|
8555
8297
|
|
|
8556
8298
|
// ../../packages/node-runtime/src/data-dir-compat.ts
|
|
8557
|
-
import
|
|
8558
|
-
import
|
|
8299
|
+
import fs10 from "fs";
|
|
8300
|
+
import path15 from "path";
|
|
8559
8301
|
var DataDirCompatibilityError = class extends Error {
|
|
8560
8302
|
code;
|
|
8561
8303
|
userDataDir;
|
|
@@ -8575,10 +8317,10 @@ var DataDirCompatibilityError = class extends Error {
|
|
|
8575
8317
|
};
|
|
8576
8318
|
function readDataDirCompatibilityMeta(userDataDir) {
|
|
8577
8319
|
const metaPath = getMetaPath(userDataDir);
|
|
8578
|
-
if (!
|
|
8320
|
+
if (!fs10.existsSync(metaPath)) return null;
|
|
8579
8321
|
let parsed;
|
|
8580
8322
|
try {
|
|
8581
|
-
parsed = JSON.parse(
|
|
8323
|
+
parsed = JSON.parse(fs10.readFileSync(metaPath, "utf-8"));
|
|
8582
8324
|
} catch (error) {
|
|
8583
8325
|
throw createInvalidMetaError(userDataDir, metaPath, "Invalid data directory compatibility meta JSON.", error);
|
|
8584
8326
|
}
|
|
@@ -8661,7 +8403,7 @@ function raiseDataDirMinRuntimeVersion(pathProvider, input) {
|
|
|
8661
8403
|
return nextMeta;
|
|
8662
8404
|
}
|
|
8663
8405
|
function getMetaPath(userDataDir) {
|
|
8664
|
-
return
|
|
8406
|
+
return path15.join(userDataDir, ".chatlab-meta.json");
|
|
8665
8407
|
}
|
|
8666
8408
|
function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
|
|
8667
8409
|
if (!isRecord2(value)) {
|
|
@@ -8732,15 +8474,15 @@ function mergeReasons(existing, next) {
|
|
|
8732
8474
|
return [.../* @__PURE__ */ new Set([...existing, next])];
|
|
8733
8475
|
}
|
|
8734
8476
|
function writeMetaAtomic(userDataDir, metaPath, meta) {
|
|
8735
|
-
|
|
8736
|
-
const tempPath =
|
|
8477
|
+
fs10.mkdirSync(userDataDir, { recursive: true });
|
|
8478
|
+
const tempPath = path15.join(userDataDir, `.chatlab-meta.json.${process.pid}.${Date.now()}.tmp`);
|
|
8737
8479
|
try {
|
|
8738
|
-
|
|
8480
|
+
fs10.writeFileSync(tempPath, `${JSON.stringify(meta, null, 2)}
|
|
8739
8481
|
`, "utf-8");
|
|
8740
|
-
|
|
8482
|
+
fs10.renameSync(tempPath, metaPath);
|
|
8741
8483
|
} catch (error) {
|
|
8742
8484
|
try {
|
|
8743
|
-
if (
|
|
8485
|
+
if (fs10.existsSync(tempPath)) fs10.unlinkSync(tempPath);
|
|
8744
8486
|
} catch {
|
|
8745
8487
|
}
|
|
8746
8488
|
throw error;
|
|
@@ -8777,7 +8519,7 @@ function raiseChatDbCompatibilityGate(pathProvider, runtime) {
|
|
|
8777
8519
|
});
|
|
8778
8520
|
}
|
|
8779
8521
|
}
|
|
8780
|
-
function getChatDbMigrations(
|
|
8522
|
+
function getChatDbMigrations() {
|
|
8781
8523
|
const hasColumn2 = (db, tableName, columnName) => {
|
|
8782
8524
|
const tableInfo = db.pragma(`table_info(${tableName})`);
|
|
8783
8525
|
return tableInfo.some((col) => col.name === columnName);
|
|
@@ -8856,39 +8598,8 @@ function getChatDbMigrations(deps) {
|
|
|
8856
8598
|
},
|
|
8857
8599
|
{
|
|
8858
8600
|
version: 4,
|
|
8859
|
-
description: "
|
|
8860
|
-
up: (
|
|
8861
|
-
const hasTable2 = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='message_fts'").get();
|
|
8862
|
-
if (hasTable2) return;
|
|
8863
|
-
db.exec(`
|
|
8864
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS message_fts USING fts5(
|
|
8865
|
-
content,
|
|
8866
|
-
content='',
|
|
8867
|
-
content_rowid=id
|
|
8868
|
-
)
|
|
8869
|
-
`);
|
|
8870
|
-
const tokenize = deps?.tokenizeForFts;
|
|
8871
|
-
if (!tokenize) return;
|
|
8872
|
-
const BATCH_SIZE = 5e3;
|
|
8873
|
-
const insertFts = db.prepare("INSERT INTO message_fts(rowid, content) VALUES (?, ?)");
|
|
8874
|
-
const countRow = db.prepare("SELECT COUNT(*) as total FROM message WHERE type = 0 AND content IS NOT NULL AND content != ''").get();
|
|
8875
|
-
const total = countRow?.total ?? 0;
|
|
8876
|
-
let offset = 0;
|
|
8877
|
-
while (offset < total) {
|
|
8878
|
-
const rows = db.prepare(
|
|
8879
|
-
`SELECT id, content FROM message
|
|
8880
|
-
WHERE type = 0 AND content IS NOT NULL AND content != ''
|
|
8881
|
-
ORDER BY id ASC LIMIT ? OFFSET ?`
|
|
8882
|
-
).all(BATCH_SIZE, offset);
|
|
8883
|
-
if (rows.length === 0) break;
|
|
8884
|
-
for (const row of rows) {
|
|
8885
|
-
const tokens = tokenize(row.content);
|
|
8886
|
-
if (tokens) {
|
|
8887
|
-
insertFts.run(row.id, tokens);
|
|
8888
|
-
}
|
|
8889
|
-
}
|
|
8890
|
-
offset += BATCH_SIZE;
|
|
8891
|
-
}
|
|
8601
|
+
description: "Preserve the legacy schema migration sequence",
|
|
8602
|
+
up: () => {
|
|
8892
8603
|
}
|
|
8893
8604
|
},
|
|
8894
8605
|
{
|
|
@@ -9076,49 +8787,56 @@ function getChatDbMigrations(deps) {
|
|
|
9076
8787
|
CREATE INDEX IF NOT EXISTS idx_message_reply_to ON message(reply_to_message_id);
|
|
9077
8788
|
`);
|
|
9078
8789
|
}
|
|
8790
|
+
},
|
|
8791
|
+
{
|
|
8792
|
+
version: 9,
|
|
8793
|
+
description: "Remove the obsolete per-session full-text index",
|
|
8794
|
+
up: (db) => {
|
|
8795
|
+
db.exec("DROP TABLE IF EXISTS message_fts");
|
|
8796
|
+
}
|
|
9079
8797
|
}
|
|
9080
8798
|
];
|
|
9081
8799
|
}
|
|
9082
8800
|
|
|
9083
8801
|
// ../../packages/node-runtime/src/services/contacts/paths.ts
|
|
9084
|
-
import
|
|
8802
|
+
import path16 from "path";
|
|
9085
8803
|
var CONTACTS_DIR_NAME = "contacts";
|
|
9086
8804
|
var CONTACTS_FACTS_DIR_NAME = "facts";
|
|
9087
8805
|
function getContactsDir(userDataDir) {
|
|
9088
|
-
return
|
|
8806
|
+
return path16.join(userDataDir, CONTACTS_DIR_NAME);
|
|
9089
8807
|
}
|
|
9090
8808
|
function getContactsFactsCacheDir(userDataDir) {
|
|
9091
|
-
return
|
|
8809
|
+
return path16.join(getContactsDir(userDataDir), CONTACTS_FACTS_DIR_NAME);
|
|
9092
8810
|
}
|
|
9093
8811
|
|
|
9094
8812
|
// ../../packages/node-runtime/src/services/global-insight/paths.ts
|
|
9095
|
-
import
|
|
8813
|
+
import path17 from "path";
|
|
9096
8814
|
function getGlobalInsightDir(userDataDir) {
|
|
9097
|
-
return
|
|
8815
|
+
return path17.join(userDataDir, "insight", "annual-summary");
|
|
9098
8816
|
}
|
|
9099
8817
|
function getGlobalInsightFactsCacheDir(userDataDir) {
|
|
9100
|
-
return
|
|
8818
|
+
return path17.join(getGlobalInsightDir(userDataDir), "facts");
|
|
9101
8819
|
}
|
|
9102
8820
|
|
|
9103
8821
|
// ../../packages/node-runtime/src/services/people/relationships/paths.ts
|
|
9104
|
-
import
|
|
8822
|
+
import path18 from "path";
|
|
9105
8823
|
var PEOPLE_DIR_NAME = "people";
|
|
9106
8824
|
var RELATIONSHIPS_DIR_NAME = "relationships";
|
|
9107
8825
|
var RELATIONSHIPS_FACTS_DIR_NAME = "facts";
|
|
9108
8826
|
function getPeopleRelationshipsDir(userDataDir) {
|
|
9109
|
-
return
|
|
8827
|
+
return path18.join(userDataDir, PEOPLE_DIR_NAME, RELATIONSHIPS_DIR_NAME);
|
|
9110
8828
|
}
|
|
9111
8829
|
function getPeopleRelationshipsFactsCacheDir(userDataDir) {
|
|
9112
|
-
return
|
|
8830
|
+
return path18.join(getPeopleRelationshipsDir(userDataDir), RELATIONSHIPS_FACTS_DIR_NAME);
|
|
9113
8831
|
}
|
|
9114
8832
|
|
|
9115
8833
|
// ../../packages/node-runtime/src/database-manager.ts
|
|
9116
|
-
import * as
|
|
9117
|
-
import * as
|
|
8834
|
+
import * as fs12 from "fs";
|
|
8835
|
+
import * as path20 from "path";
|
|
9118
8836
|
|
|
9119
8837
|
// ../../packages/node-runtime/src/services/global-insight/snapshot.ts
|
|
9120
|
-
import
|
|
9121
|
-
import
|
|
8838
|
+
import fs11 from "fs";
|
|
8839
|
+
import path19 from "path";
|
|
9122
8840
|
|
|
9123
8841
|
// ../../packages/node-runtime/src/services/global-insight/time-range.ts
|
|
9124
8842
|
function normalizeAnnualSummaryRange(input, nowInput = /* @__PURE__ */ new Date()) {
|
|
@@ -9169,17 +8887,17 @@ function toAnnualSummaryLocalDate(range) {
|
|
|
9169
8887
|
// ../../packages/node-runtime/src/services/global-insight/snapshot.ts
|
|
9170
8888
|
var SNAPSHOT_TMP_PREFIX = "annual-summary.tmp-";
|
|
9171
8889
|
function getAnnualSummarySnapshotPath(snapshotDir, range) {
|
|
9172
|
-
return
|
|
8890
|
+
return path19.join(snapshotDir, `annual-summary-${toAnnualSummaryRangeKey(range)}.json`);
|
|
9173
8891
|
}
|
|
9174
8892
|
function readAnnualSummarySnapshot(snapshotDir, range, options = {}) {
|
|
9175
8893
|
const snapshotPath = getAnnualSummarySnapshotPath(snapshotDir, range);
|
|
9176
|
-
if (!
|
|
8894
|
+
if (!fs11.existsSync(snapshotPath)) return null;
|
|
9177
8895
|
try {
|
|
9178
|
-
return JSON.parse(
|
|
8896
|
+
return JSON.parse(fs11.readFileSync(snapshotPath, "utf-8"));
|
|
9179
8897
|
} catch (error) {
|
|
9180
|
-
const backupPath =
|
|
8898
|
+
const backupPath = path19.join(snapshotDir, `annual-summary.corrupt-${options.now?.() ?? Date.now()}.json`);
|
|
9181
8899
|
try {
|
|
9182
|
-
|
|
8900
|
+
fs11.renameSync(snapshotPath, backupPath);
|
|
9183
8901
|
} catch (renameError) {
|
|
9184
8902
|
appLogger.warn("global-insight", "failed to backup corrupt annual summary snapshot", renameError);
|
|
9185
8903
|
}
|
|
@@ -9188,28 +8906,28 @@ function readAnnualSummarySnapshot(snapshotDir, range, options = {}) {
|
|
|
9188
8906
|
}
|
|
9189
8907
|
}
|
|
9190
8908
|
function writeAnnualSummarySnapshot(snapshotDir, snapshot) {
|
|
9191
|
-
|
|
9192
|
-
const tmpPath =
|
|
9193
|
-
|
|
9194
|
-
|
|
8909
|
+
fs11.mkdirSync(snapshotDir, { recursive: true });
|
|
8910
|
+
const tmpPath = path19.join(snapshotDir, `${SNAPSHOT_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
8911
|
+
fs11.writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
8912
|
+
fs11.renameSync(tmpPath, getAnnualSummarySnapshotPath(snapshotDir, snapshot.range));
|
|
9195
8913
|
}
|
|
9196
8914
|
function cleanupAnnualSummarySnapshotTempFiles(snapshotDir) {
|
|
9197
|
-
if (!
|
|
9198
|
-
for (const name of
|
|
8915
|
+
if (!fs11.existsSync(snapshotDir)) return;
|
|
8916
|
+
for (const name of fs11.readdirSync(snapshotDir)) {
|
|
9199
8917
|
if (!name.startsWith(SNAPSHOT_TMP_PREFIX)) continue;
|
|
9200
8918
|
try {
|
|
9201
|
-
|
|
8919
|
+
fs11.rmSync(path19.join(snapshotDir, name), { force: true });
|
|
9202
8920
|
} catch (error) {
|
|
9203
8921
|
appLogger.warn("global-insight", "failed to remove annual summary snapshot temp file", error);
|
|
9204
8922
|
}
|
|
9205
8923
|
}
|
|
9206
8924
|
}
|
|
9207
8925
|
function deleteAnnualSummarySnapshots(snapshotDir) {
|
|
9208
|
-
if (!
|
|
9209
|
-
for (const name of
|
|
8926
|
+
if (!fs11.existsSync(snapshotDir)) return;
|
|
8927
|
+
for (const name of fs11.readdirSync(snapshotDir)) {
|
|
9210
8928
|
if (!name.startsWith("annual-summary-") && !name.startsWith("annual-summary.")) continue;
|
|
9211
8929
|
try {
|
|
9212
|
-
|
|
8930
|
+
fs11.rmSync(path19.join(snapshotDir, name), { force: true });
|
|
9213
8931
|
} catch (error) {
|
|
9214
8932
|
appLogger.warn("global-insight", "failed to remove annual summary snapshot", error);
|
|
9215
8933
|
}
|
|
@@ -9217,15 +8935,9 @@ function deleteAnnualSummarySnapshots(snapshotDir) {
|
|
|
9217
8935
|
}
|
|
9218
8936
|
|
|
9219
8937
|
// ../../packages/node-runtime/src/database-manager.ts
|
|
9220
|
-
function createMigrationDeps(overrides) {
|
|
9221
|
-
return {
|
|
9222
|
-
tokenizeForFts,
|
|
9223
|
-
...overrides
|
|
9224
|
-
};
|
|
9225
|
-
}
|
|
9226
8938
|
function listDatabaseCandidateIds(databaseDir) {
|
|
9227
|
-
if (!
|
|
9228
|
-
return
|
|
8939
|
+
if (!fs12.existsSync(databaseDir)) return [];
|
|
8940
|
+
return fs12.readdirSync(databaseDir).filter((fileName) => fileName.endsWith(".db") && !fileName.startsWith("._")).map((fileName) => fileName.slice(0, -3));
|
|
9229
8941
|
}
|
|
9230
8942
|
var DatabaseManager = class {
|
|
9231
8943
|
constructor(pathProvider, options = {}) {
|
|
@@ -9234,13 +8946,11 @@ var DatabaseManager = class {
|
|
|
9234
8946
|
throw new Error("DatabaseManager runtime identity is required for data directory compatibility checks.");
|
|
9235
8947
|
}
|
|
9236
8948
|
this.nativeBinding = options?.nativeBinding;
|
|
9237
|
-
this.migrationDeps = createMigrationDeps(options?.migrationDeps);
|
|
9238
8949
|
this.runtime = options?.runtime ?? null;
|
|
9239
8950
|
}
|
|
9240
8951
|
pathProvider;
|
|
9241
8952
|
cache = /* @__PURE__ */ new Map();
|
|
9242
8953
|
nativeBinding;
|
|
9243
|
-
migrationDeps;
|
|
9244
8954
|
runtime;
|
|
9245
8955
|
/**
|
|
9246
8956
|
* Open a session DB (read-only by default, cached).
|
|
@@ -9251,7 +8961,7 @@ var DatabaseManager = class {
|
|
|
9251
8961
|
return this.cache.get(sessionId);
|
|
9252
8962
|
}
|
|
9253
8963
|
const dbPath = this.getDbPath(sessionId);
|
|
9254
|
-
if (!
|
|
8964
|
+
if (!fs12.existsSync(dbPath)) return null;
|
|
9255
8965
|
this.migrateIfNeeded(dbPath);
|
|
9256
8966
|
this.assertCompatible();
|
|
9257
8967
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
@@ -9278,7 +8988,7 @@ var DatabaseManager = class {
|
|
|
9278
8988
|
nativeBinding: this.nativeBinding
|
|
9279
8989
|
});
|
|
9280
8990
|
try {
|
|
9281
|
-
const migrations = getChatDbMigrations(
|
|
8991
|
+
const migrations = getChatDbMigrations();
|
|
9282
8992
|
this.runMigrations(adapter, migrations);
|
|
9283
8993
|
} finally {
|
|
9284
8994
|
adapter.close();
|
|
@@ -9297,13 +9007,13 @@ var DatabaseManager = class {
|
|
|
9297
9007
|
this.cache.delete(sessionId);
|
|
9298
9008
|
}
|
|
9299
9009
|
const dbPath = this.getDbPath(sessionId);
|
|
9300
|
-
if (!
|
|
9010
|
+
if (!fs12.existsSync(dbPath)) return null;
|
|
9301
9011
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
9302
9012
|
readonly: false,
|
|
9303
9013
|
nativeBinding: this.nativeBinding
|
|
9304
9014
|
});
|
|
9305
9015
|
if (needsMigration(adapter, CURRENT_SCHEMA_VERSION)) {
|
|
9306
|
-
const migrations = getChatDbMigrations(
|
|
9016
|
+
const migrations = getChatDbMigrations();
|
|
9307
9017
|
this.runMigrations(adapter, migrations);
|
|
9308
9018
|
this.assertCompatible();
|
|
9309
9019
|
} else {
|
|
@@ -9365,17 +9075,17 @@ var DatabaseManager = class {
|
|
|
9365
9075
|
* 获取数据库文件路径
|
|
9366
9076
|
*/
|
|
9367
9077
|
getDbPath(sessionId) {
|
|
9368
|
-
return
|
|
9078
|
+
return path20.join(this.pathProvider.getDatabaseDir(), `${sessionId}.db`);
|
|
9369
9079
|
}
|
|
9370
9080
|
openRawSessionDatabase(sessionId, options = {}) {
|
|
9371
9081
|
this.assertCompatible();
|
|
9372
9082
|
const dbPath = this.getDbPath(sessionId);
|
|
9373
|
-
if (!options.create && !
|
|
9083
|
+
if (!options.create && !fs12.existsSync(dbPath)) {
|
|
9374
9084
|
throw new Error(`Session database not found: ${sessionId}`);
|
|
9375
9085
|
}
|
|
9376
9086
|
if (!options.readonly) {
|
|
9377
9087
|
this.close(sessionId);
|
|
9378
|
-
|
|
9088
|
+
fs12.mkdirSync(path20.dirname(dbPath), { recursive: true });
|
|
9379
9089
|
}
|
|
9380
9090
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
9381
9091
|
readonly: options.readonly ?? false,
|
|
@@ -9393,17 +9103,17 @@ var DatabaseManager = class {
|
|
|
9393
9103
|
deleteSessionDatabaseFiles(sessionId) {
|
|
9394
9104
|
this.close(sessionId);
|
|
9395
9105
|
const dbPath = this.getDbPath(sessionId);
|
|
9396
|
-
const existed = ["", "-wal", "-shm"].some((suffix) =>
|
|
9106
|
+
const existed = ["", "-wal", "-shm"].some((suffix) => fs12.existsSync(dbPath + suffix));
|
|
9397
9107
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
9398
9108
|
try {
|
|
9399
9109
|
const filePath = dbPath + suffix;
|
|
9400
|
-
if (
|
|
9110
|
+
if (fs12.existsSync(filePath)) fs12.unlinkSync(filePath);
|
|
9401
9111
|
} catch {
|
|
9402
9112
|
}
|
|
9403
9113
|
}
|
|
9404
9114
|
const cacheDir = this.pathProvider.getCacheDir();
|
|
9405
9115
|
deleteSessionCache(sessionId, cacheDir);
|
|
9406
|
-
deleteSessionCache(sessionId,
|
|
9116
|
+
deleteSessionCache(sessionId, path20.join(cacheDir, "query"));
|
|
9407
9117
|
deleteSessionCache(sessionId, getContactsFactsCacheDir(this.pathProvider.getUserDataDir()));
|
|
9408
9118
|
deleteSessionCache(sessionId, getGlobalInsightFactsCacheDir(this.pathProvider.getUserDataDir()));
|
|
9409
9119
|
deleteAnnualSummarySnapshots(getGlobalInsightDir(this.pathProvider.getUserDataDir()));
|
|
@@ -9444,12 +9154,12 @@ function shouldRepairCompatibilityGate(schemaVersion) {
|
|
|
9444
9154
|
}
|
|
9445
9155
|
|
|
9446
9156
|
// ../../packages/node-runtime/src/cache/analytics-cache.ts
|
|
9447
|
-
import * as
|
|
9157
|
+
import * as fs13 from "fs";
|
|
9448
9158
|
function getDbFileVersion(dbPath) {
|
|
9449
9159
|
const parts = [];
|
|
9450
9160
|
for (const p of [dbPath, `${dbPath}-wal`]) {
|
|
9451
9161
|
try {
|
|
9452
|
-
const st =
|
|
9162
|
+
const st = fs13.statSync(p);
|
|
9453
9163
|
parts.push(`${Math.floor(st.mtimeMs)}:${st.size}`);
|
|
9454
9164
|
} catch {
|
|
9455
9165
|
parts.push("-");
|
|
@@ -9605,6 +9315,8 @@ export {
|
|
|
9605
9315
|
POS_TAG_DEFINITIONS,
|
|
9606
9316
|
MEANINGFUL_POS_TAGS,
|
|
9607
9317
|
isStopword,
|
|
9318
|
+
cleanText,
|
|
9319
|
+
isValidWord,
|
|
9608
9320
|
buildExcludeKeywordsConditions,
|
|
9609
9321
|
getMentionAnalysis,
|
|
9610
9322
|
getMentionGraph,
|
|
@@ -9683,28 +9395,17 @@ export {
|
|
|
9683
9395
|
generateMessageKey,
|
|
9684
9396
|
writeParseResultToDb,
|
|
9685
9397
|
getCollidingPlatformIds,
|
|
9398
|
+
getCollidingPlatformIdsFromMessages,
|
|
9686
9399
|
normalizePlatformId,
|
|
9687
9400
|
detectConflictsInMessages,
|
|
9688
9401
|
mergeMembers2,
|
|
9689
9402
|
CHAT_DB_INDEXES,
|
|
9690
9403
|
CHAT_DB_SCHEMA,
|
|
9691
|
-
FTS_TABLE_SCHEMA,
|
|
9692
9404
|
AiLogger,
|
|
9693
9405
|
extractErrorInfo,
|
|
9694
9406
|
extractErrorStack,
|
|
9695
9407
|
initAppLogger,
|
|
9696
9408
|
appLogger,
|
|
9697
|
-
initNlpDir,
|
|
9698
|
-
getNlpDir,
|
|
9699
|
-
getJieba,
|
|
9700
|
-
clearJiebaInstance,
|
|
9701
|
-
segment,
|
|
9702
|
-
batchSegmentWithFrequency,
|
|
9703
|
-
batchSegmentChineseWithStats,
|
|
9704
|
-
collectPosTagStats,
|
|
9705
|
-
getPosTagDefinitions,
|
|
9706
|
-
tokenizeForFts,
|
|
9707
|
-
tokenizeQueryForFts,
|
|
9708
9409
|
wasElectronUsed,
|
|
9709
9410
|
verifyCliDataPath,
|
|
9710
9411
|
migrateFromElectronIfNeeded,
|
|
@@ -9747,4 +9448,4 @@ export {
|
|
|
9747
9448
|
StaticPathProvider,
|
|
9748
9449
|
createDatabaseManagerAdapter
|
|
9749
9450
|
};
|
|
9750
|
-
//# sourceMappingURL=chunk-
|
|
9451
|
+
//# sourceMappingURL=chunk-2WYXD5ZP.mjs.map
|