chatlab-cli 0.30.2 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chat-command-VBDMWOKL.mjs → chat-command-CHV7RLBH.mjs} +9 -8
- package/dist/{chat-command-VBDMWOKL.mjs.map → chat-command-CHV7RLBH.mjs.map} +1 -1
- package/dist/{chunk-326OCJOT.mjs → chunk-DA5T64RY.mjs} +2 -2
- package/dist/{chunk-M2PXDX4G.mjs → chunk-DBBL74RK.mjs} +31 -22
- package/dist/chunk-DBBL74RK.mjs.map +1 -0
- package/dist/{chunk-KBSAVUFV.mjs → chunk-EXD2SXWL.mjs} +89 -15
- package/dist/chunk-EXD2SXWL.mjs.map +1 -0
- package/dist/{chunk-D3DPCDII.mjs → chunk-JH5RAJT2.mjs} +83 -34
- package/dist/chunk-JH5RAJT2.mjs.map +1 -0
- package/dist/{chunk-5EE2EFPE.mjs → chunk-RD335EMA.mjs} +4 -4
- package/dist/{chunk-WV5GSRQM.mjs → chunk-RDCUGC24.mjs} +5 -15
- package/dist/chunk-RDCUGC24.mjs.map +1 -0
- package/dist/{chunk-TEX44HNL.mjs → chunk-SNCXU2QL.mjs} +5 -15
- package/dist/chunk-SNCXU2QL.mjs.map +1 -0
- package/dist/{chunk-36JGKW6K.mjs → chunk-T64GA5HP.mjs} +1134 -364
- package/dist/chunk-T64GA5HP.mjs.map +1 -0
- package/dist/{chunk-LVEJHB3X.mjs → chunk-UWWFOEGF.mjs} +494 -97
- package/dist/chunk-UWWFOEGF.mjs.map +1 -0
- package/dist/{chunk-ULNRUS55.mjs → chunk-WQCY45U2.mjs} +3 -3
- package/dist/chunk-YAQLYL52.mjs +14 -0
- package/dist/chunk-YAQLYL52.mjs.map +1 -0
- package/dist/{chunk-TCZHG3G7.mjs → chunk-YPQ72HMX.mjs} +2 -2
- package/dist/cli.mjs +8 -7
- package/dist/contacts-worker.mjs +2 -2
- package/dist/global-insight-worker.mjs +179 -0
- package/dist/global-insight-worker.mjs.map +1 -0
- package/dist/{http-L4AMELPZ.mjs → http-3B5ARN7A.mjs} +12 -11
- package/dist/{import-WWCSXGVS.mjs → import-2DZGNSEX.mjs} +10 -7
- package/dist/index.mjs +12 -11
- package/dist/{mcp-A4M3LT5O.mjs → mcp-44I6FUUQ.mjs} +12 -11
- package/dist/{mcp-A4M3LT5O.mjs.map → mcp-44I6FUUQ.mjs.map} +1 -1
- package/dist/people-relationships-worker.mjs +2 -2
- package/dist/semantic-index-worker.mjs +1 -1
- package/dist/{src-MPNBTFOE.mjs → src-R3QX6L3L.mjs} +26 -6
- package/dist/{stream-import-HIE7PNL4.mjs → stream-import-VUEL2TTU.mjs} +10 -7
- package/dist/{worker-runtime-BJXO24XX.mjs → worker-runtime-GJAOIIZW.mjs} +6 -5
- package/dist/{worker-runtime-BJXO24XX.mjs.map → worker-runtime-GJAOIIZW.mjs.map} +1 -1
- package/dist-web/assets/ActionToolsPanel-fAio70bI.css +1 -0
- package/dist-web/assets/ActionToolsPanel.vue_vue_type_script_setup_true_lang-CdJT0t2f.js +110 -0
- package/dist-web/assets/{BufferResource-q3rzaWWd.js → BufferResource-BPGkshPa.js} +1 -1
- package/dist-web/assets/{CanvasRenderer-BRk1y8tp.js → CanvasRenderer-DTKkZhq4.js} +1 -1
- package/dist-web/assets/{EChartWordcloud-Clg60FMo.js → EChartWordcloud-DU3ZYdgz.js} +1 -1
- package/dist-web/assets/{Filter-BJwode73.js → Filter-CHXKzS2l.js} +1 -1
- package/dist-web/assets/{LoadingState.vue_vue_type_script_setup_true_lang-D_dJuLWJ.js → LoadingState.vue_vue_type_script_setup_true_lang-DACMroOe.js} +1 -1
- package/dist-web/assets/MessageExportModal-h-zl0dx1.js +1 -0
- package/dist-web/assets/PageHeader-CK0hTsdx.js +1 -0
- package/dist-web/assets/PageHeader-XIXMTomn.css +1 -0
- package/dist-web/assets/{RelationshipGalaxyCanvas-CORMD7vL.js → RelationshipGalaxyCanvas-Dwdy5flh.js} +3 -3
- package/dist-web/assets/{RelationshipGalaxyThreeCanvas-B_w_P4ob.js → RelationshipGalaxyThreeCanvas-CtY4TGen.js} +1 -1
- package/dist-web/assets/{RenderTargetSystem-CGhV9R9E.js → RenderTargetSystem-BE56mKRG.js} +1 -1
- package/dist-web/assets/ThemeCard.vue_vue_type_script_setup_true_lang-BoZyssJF.js +1 -0
- package/dist-web/assets/TimeSelect.vue_vue_type_script_setup_true_lang-27hMyAUE.js +1 -0
- package/dist-web/assets/{WebGLRenderer-CAokTE5X.js → WebGLRenderer-Dm18dxOf.js} +1 -1
- package/dist-web/assets/{WebGPURenderer-DzP4ggSy.js → WebGPURenderer-BF6TF-is.js} +1 -1
- package/dist-web/assets/annual-summary-time-range-DVLXK1r4.js +1 -0
- package/dist-web/assets/base-CFPyD9Gy.js +1 -0
- package/dist-web/assets/{browserAll-CAZCK6dd.js → browserAll-Cn_CfkXl.js} +1 -1
- package/dist-web/assets/dateFormat-BcqNKTQ1.js +1 -0
- package/dist-web/assets/{electron-CkPDbAaS.js → electron-B6xOabTq.js} +1 -1
- package/dist-web/assets/electron-hcWiB7Gg.js +1 -0
- package/dist-web/assets/fetch-BPkgnY0R.js +1 -0
- package/dist-web/assets/{fetch-LX9jrJCC.js → fetch-BRXmDI_2.js} +1 -1
- package/dist-web/assets/{fetch-Apd5OLJw.js → fetch-BUm1isWe.js} +1 -1
- package/dist-web/assets/{fetch-B8rik0TM.js → fetch-CBOJwwJp.js} +3 -3
- package/dist-web/assets/{fetch-wqMSiaK3.js → fetch-CEhUu1Yu.js} +1 -1
- package/dist-web/assets/fetch-C_EfVFJi.js +3 -0
- package/dist-web/assets/{fetch-DQ9UNNAy.js → fetch-DL_u25Ui.js} +1 -1
- package/dist-web/assets/{fetch-BIEXkvDq.js → fetch-DMLq3xPG.js} +1 -1
- package/dist-web/assets/{fetch--UbRoBT7.js → fetch-DylpNKCR.js} +1 -1
- package/dist-web/assets/fetch-etgwVKIw.js +1 -0
- package/dist-web/assets/index-0x1QPzKZ.js +1 -0
- package/dist-web/assets/index-B5S9FnfP.js +1 -0
- package/dist-web/assets/index-BS6loLHW.js +1 -0
- package/dist-web/assets/index-BfO_LpDv.css +1 -0
- package/dist-web/assets/index-BrTlAl8b.js +1 -0
- package/dist-web/assets/index-ByUaiVQK.css +1 -0
- package/dist-web/assets/{index-S-YQRH1E.js → index-C3TnydSt.js} +1 -1
- package/dist-web/assets/index-CAWO10k1.js +2 -0
- package/dist-web/assets/index-C_0GHEcb.css +1 -0
- package/dist-web/assets/index-Chm17wNe.js +2 -0
- package/dist-web/assets/index-DAr_2DlV.js +173 -0
- package/dist-web/assets/index-Em6upenM.js +64 -0
- package/dist-web/assets/index-FoTy2Cce.js +1 -0
- package/dist-web/assets/index-YADL4XIp.js +22 -0
- package/dist-web/assets/index-ZsZwPLWy.css +1 -0
- package/dist-web/assets/index-_6lck7Bv.css +1 -0
- package/dist-web/assets/index-aMIgqj43.js +1 -0
- package/dist-web/assets/index-y7cxH1Et.css +1 -0
- package/dist-web/assets/index-zZVsV5HB.js +1 -0
- package/dist-web/assets/{people-page-header-Mupn-U_b.js → people-page-header-BdKM1qhX.js} +1 -1
- package/dist-web/assets/types-CZnACqaB.js +1 -0
- package/dist-web/assets/{vendor-echarts-hJVnODyU.js → vendor-echarts-B-i_56Av.js} +1 -1
- package/dist-web/assets/{vendor-echarts-wordcloud-k5ih2Jl4.js → vendor-echarts-wordcloud-Ca8n6qS6.js} +1 -1
- package/dist-web/assets/{vendor-nuxt-ui-DaLxYaC4.js → vendor-nuxt-ui-CS1uxE9C.js} +2 -2
- package/dist-web/assets/{vendor-reka-ui-CzM4kDQ7.js → vendor-reka-ui-Cta6JPvN.js} +1 -1
- package/dist-web/assets/{web-DbKs6-1b.js → web-BUZ-dZy0.js} +1 -1
- package/dist-web/assets/{webworkerAll-Bhv-hBqR.js → webworkerAll-BKGP--A4.js} +1 -1
- package/dist-web/index.html +4 -4
- package/package.json +1 -1
- package/dist/chunk-36JGKW6K.mjs.map +0 -1
- package/dist/chunk-D3DPCDII.mjs.map +0 -1
- package/dist/chunk-KBSAVUFV.mjs.map +0 -1
- package/dist/chunk-LVEJHB3X.mjs.map +0 -1
- package/dist/chunk-M2PXDX4G.mjs.map +0 -1
- package/dist/chunk-TEX44HNL.mjs.map +0 -1
- package/dist/chunk-WV5GSRQM.mjs.map +0 -1
- package/dist-web/assets/DebugToolsPanel-D_lFIW6j.css +0 -1
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-F4n0zNX2.js +0 -110
- package/dist-web/assets/MessageExportModal-CGcdMOyw.js +0 -1
- package/dist-web/assets/PageHeader-Bbn87QZS.css +0 -1
- package/dist-web/assets/PageHeader-CZaqOdBQ.js +0 -1
- package/dist-web/assets/electron-D9vE5t3H.js +0 -1
- package/dist-web/assets/fetch-1pB-HbYw.js +0 -3
- package/dist-web/assets/fetch-CF_3ZqRa.js +0 -1
- package/dist-web/assets/fetch-FSNxSnAp.js +0 -1
- package/dist-web/assets/index---rXG1hZ.css +0 -1
- package/dist-web/assets/index-B01uUoHE.js +0 -1
- package/dist-web/assets/index-B4l3rHie.css +0 -1
- package/dist-web/assets/index-BSIyyt0z.js +0 -1
- package/dist-web/assets/index-Bh8z441f.js +0 -2
- package/dist-web/assets/index-C0rya8v4.js +0 -1
- package/dist-web/assets/index-C1p9CbmN.css +0 -1
- package/dist-web/assets/index-COpza1A4.css +0 -1
- package/dist-web/assets/index-CZbZv2fh.js +0 -64
- package/dist-web/assets/index-CqUuHQBQ.js +0 -22
- package/dist-web/assets/index-CzeTP5MJ.js +0 -173
- package/dist-web/assets/index-DgNxTM_8.js +0 -2
- package/dist-web/assets/index-DosG7LmJ.css +0 -1
- /package/dist/{chunk-326OCJOT.mjs.map → chunk-DA5T64RY.mjs.map} +0 -0
- /package/dist/{chunk-5EE2EFPE.mjs.map → chunk-RD335EMA.mjs.map} +0 -0
- /package/dist/{chunk-ULNRUS55.mjs.map → chunk-WQCY45U2.mjs.map} +0 -0
- /package/dist/{chunk-TCZHG3G7.mjs.map → chunk-YPQ72HMX.mjs.map} +0 -0
- /package/dist/{http-L4AMELPZ.mjs.map → http-3B5ARN7A.mjs.map} +0 -0
- /package/dist/{import-WWCSXGVS.mjs.map → import-2DZGNSEX.mjs.map} +0 -0
- /package/dist/{src-MPNBTFOE.mjs.map → src-R3QX6L3L.mjs.map} +0 -0
- /package/dist/{stream-import-HIE7PNL4.mjs.map → stream-import-VUEL2TTU.mjs.map} +0 -0
|
@@ -3899,6 +3899,348 @@ function notGroupSelfMemberCondition(db, memberAlias) {
|
|
|
3899
3899
|
)`;
|
|
3900
3900
|
}
|
|
3901
3901
|
|
|
3902
|
+
// ../../packages/core/src/owner/owner-matching.ts
|
|
3903
|
+
var NAME_MATCH_PLATFORMS = /* @__PURE__ */ new Set(["whatsapp", "line", "instagram"]);
|
|
3904
|
+
function isNameMatchPlatform(platform) {
|
|
3905
|
+
return NAME_MATCH_PLATFORMS.has(platform);
|
|
3906
|
+
}
|
|
3907
|
+
var INVISIBLE_CHARS_RE = /[\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/g;
|
|
3908
|
+
function normalizeOwnerName(name) {
|
|
3909
|
+
return name.replace(INVISIBLE_CHARS_RE, "").normalize("NFKC").replace(/\s+/g, " ").trim().toLowerCase();
|
|
3910
|
+
}
|
|
3911
|
+
function collectCandidateNames(member) {
|
|
3912
|
+
const names = [
|
|
3913
|
+
member.platformId,
|
|
3914
|
+
member.accountName ?? "",
|
|
3915
|
+
member.groupNickname ?? "",
|
|
3916
|
+
...member.aliases ?? [],
|
|
3917
|
+
member.displayName ?? ""
|
|
3918
|
+
];
|
|
3919
|
+
const result = [];
|
|
3920
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3921
|
+
for (const name of names) {
|
|
3922
|
+
if (!name || !name.trim()) continue;
|
|
3923
|
+
if (seen.has(name)) continue;
|
|
3924
|
+
seen.add(name);
|
|
3925
|
+
result.push(name);
|
|
3926
|
+
}
|
|
3927
|
+
return result;
|
|
3928
|
+
}
|
|
3929
|
+
function mergeConfirmedNames(existing, member) {
|
|
3930
|
+
const result = [];
|
|
3931
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3932
|
+
for (const name of [...existing, ...collectCandidateNames(member)]) {
|
|
3933
|
+
if (!name || !name.trim()) continue;
|
|
3934
|
+
if (seen.has(name)) continue;
|
|
3935
|
+
seen.add(name);
|
|
3936
|
+
result.push(name);
|
|
3937
|
+
}
|
|
3938
|
+
return result;
|
|
3939
|
+
}
|
|
3940
|
+
function matchOwnerProfile(platform, profile, members) {
|
|
3941
|
+
const exact = members.find((m) => m.platformId === profile.platformId);
|
|
3942
|
+
if (exact) {
|
|
3943
|
+
return { type: "exact", platformId: exact.platformId };
|
|
3944
|
+
}
|
|
3945
|
+
if (!isNameMatchPlatform(platform)) {
|
|
3946
|
+
return { type: "none" };
|
|
3947
|
+
}
|
|
3948
|
+
const confirmed = new Set(profile.confirmedNames.map(normalizeOwnerName).filter((n) => n.length > 0));
|
|
3949
|
+
if (confirmed.size === 0) {
|
|
3950
|
+
return { type: "none" };
|
|
3951
|
+
}
|
|
3952
|
+
const matched = members.filter(
|
|
3953
|
+
(m) => collectCandidateNames(m).some((name) => confirmed.has(normalizeOwnerName(name)))
|
|
3954
|
+
);
|
|
3955
|
+
if (matched.length === 1) {
|
|
3956
|
+
return { type: "name", platformId: matched[0].platformId };
|
|
3957
|
+
}
|
|
3958
|
+
if (matched.length > 1) {
|
|
3959
|
+
return { type: "ambiguous", platformIds: matched.map((m) => m.platformId) };
|
|
3960
|
+
}
|
|
3961
|
+
return { type: "none" };
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
// ../../packages/core/src/query/contact-identity.ts
|
|
3965
|
+
function shouldScopeContactToSession(platform, contact) {
|
|
3966
|
+
if (isNameMatchPlatform(platform)) return true;
|
|
3967
|
+
return platform.trim().toLowerCase() === "qq" && contact.platformId.trim() === contact.name.trim();
|
|
3968
|
+
}
|
|
3969
|
+
function buildContactKey(platform, platformId, sessionId) {
|
|
3970
|
+
const normalizedPlatform = platform.trim();
|
|
3971
|
+
const normalizedPlatformId = platformId.trim();
|
|
3972
|
+
if (!normalizedPlatform) throw new Error("platform is required");
|
|
3973
|
+
if (!normalizedPlatformId) throw new Error("platformId is required");
|
|
3974
|
+
return sessionId?.trim() ? `${normalizedPlatform}:${sessionId.trim()}:${normalizedPlatformId}` : `${normalizedPlatform}:${normalizedPlatformId}`;
|
|
3975
|
+
}
|
|
3976
|
+
|
|
3977
|
+
// ../../packages/shared-types/index.ts
|
|
3978
|
+
var KNOWN_PLATFORMS = {
|
|
3979
|
+
QQ: "qq",
|
|
3980
|
+
WECHAT: "weixin",
|
|
3981
|
+
DISCORD: "discord",
|
|
3982
|
+
WHATSAPP: "whatsapp",
|
|
3983
|
+
TELEGRAM: "telegram",
|
|
3984
|
+
INSTAGRAM: "instagram",
|
|
3985
|
+
GOOGLE_CHAT: "google-chat",
|
|
3986
|
+
LINE: "line",
|
|
3987
|
+
UNKNOWN: "unknown"
|
|
3988
|
+
};
|
|
3989
|
+
var CONTACTS_TIME_RANGE_PRESETS = ["1y", "2y", "3y", "5y", "all"];
|
|
3990
|
+
|
|
3991
|
+
// ../../packages/core/src/query/global-insight.ts
|
|
3992
|
+
var SYSTEM_MESSAGE_TYPES2 = [80 /* SYSTEM */, 81 /* RECALL */];
|
|
3993
|
+
function getAnnualSummarySessionFacts(db, sessionId, range) {
|
|
3994
|
+
if (!isChatSessionDb(db)) return emptyFacts("not_chat_db");
|
|
3995
|
+
const meta = getSessionMeta(db);
|
|
3996
|
+
if (!meta) return emptyFacts("missing_meta");
|
|
3997
|
+
if (meta.type !== "private" /* PRIVATE */ && meta.type !== "group" /* GROUP */) return emptyFacts("unsupported_type");
|
|
3998
|
+
if (!meta.ownerId?.trim()) return emptyFacts("missing_owner");
|
|
3999
|
+
const owner = resolveOwnerMember(db);
|
|
4000
|
+
if (!owner) return emptyFacts("unresolved_owner");
|
|
4001
|
+
const contacts = getNonSystemMembersForContacts(db).filter((member) => member.id !== owner.id);
|
|
4002
|
+
let privateContact = null;
|
|
4003
|
+
if (meta.type === "private" /* PRIVATE */) {
|
|
4004
|
+
const activeContacts = getActivePrivateContacts(db, contacts, owner.id, range);
|
|
4005
|
+
const candidates = activeContacts.length > 0 ? activeContacts : contacts;
|
|
4006
|
+
if (candidates.length === 0) return emptyFacts("private_missing");
|
|
4007
|
+
if (candidates.length > 1) return emptyFacts("private_ambiguous");
|
|
4008
|
+
privateContact = candidates[0];
|
|
4009
|
+
}
|
|
4010
|
+
const ownerMessagesByDay = rowsToNumberRecord(
|
|
4011
|
+
db.prepare(
|
|
4012
|
+
`SELECT strftime('%Y-%m-%d', msg.ts, 'unixepoch', 'localtime') as key, COUNT(*) as count
|
|
4013
|
+
FROM message msg
|
|
4014
|
+
WHERE msg.sender_id = ? AND msg.ts >= ? AND msg.ts <= ?
|
|
4015
|
+
AND msg.type NOT IN (${SYSTEM_MESSAGE_TYPES2.join(", ")})
|
|
4016
|
+
GROUP BY key ORDER BY key`
|
|
4017
|
+
).all(owner.id, range.startTs, range.endTs)
|
|
4018
|
+
);
|
|
4019
|
+
const messageTypeCounts = rowsToNumberRecord(
|
|
4020
|
+
db.prepare(
|
|
4021
|
+
`SELECT CAST(msg.type AS TEXT) as key, COUNT(*) as count
|
|
4022
|
+
FROM message msg
|
|
4023
|
+
WHERE msg.sender_id = ? AND msg.ts >= ? AND msg.ts <= ?
|
|
4024
|
+
AND msg.type NOT IN (${SYSTEM_MESSAGE_TYPES2.join(", ")})
|
|
4025
|
+
GROUP BY msg.type ORDER BY msg.type`
|
|
4026
|
+
).all(owner.id, range.startTs, range.endTs)
|
|
4027
|
+
);
|
|
4028
|
+
const textLengthCounts = rowsToNumberRecord(
|
|
4029
|
+
db.prepare(
|
|
4030
|
+
`SELECT CAST(LENGTH(msg.content) AS TEXT) as key, COUNT(*) as count
|
|
4031
|
+
FROM message msg
|
|
4032
|
+
WHERE msg.sender_id = ? AND msg.ts >= ? AND msg.ts <= ?
|
|
4033
|
+
AND msg.type = ${0 /* TEXT */} AND msg.content IS NOT NULL AND LENGTH(msg.content) > 0
|
|
4034
|
+
GROUP BY LENGTH(msg.content) ORDER BY LENGTH(msg.content)`
|
|
4035
|
+
).all(owner.id, range.startTs, range.endTs)
|
|
4036
|
+
);
|
|
4037
|
+
const availableDataYears = db.prepare(
|
|
4038
|
+
`SELECT DISTINCT CAST(strftime('%Y', msg.ts, 'unixepoch', 'localtime') AS INTEGER) as year
|
|
4039
|
+
FROM message msg
|
|
4040
|
+
WHERE msg.sender_id = ? AND msg.type NOT IN (${SYSTEM_MESSAGE_TYPES2.join(", ")})
|
|
4041
|
+
ORDER BY year DESC`
|
|
4042
|
+
).all(owner.id).map((row) => row.year);
|
|
4043
|
+
return {
|
|
4044
|
+
kind: "analyzed",
|
|
4045
|
+
availableDataYears,
|
|
4046
|
+
ownerMessagesByDay,
|
|
4047
|
+
directContactKeysByDay: meta.type === "private" /* PRIVATE */ && privateContact ? getPrivateDirectContactsByDay(db, sessionId, meta.platform, owner.id, privateContact, range) : getGroupDirectContactsByDay(db, sessionId, meta.platform, owner.id, contacts, range),
|
|
4048
|
+
messageTypeCounts,
|
|
4049
|
+
textLengthCounts
|
|
4050
|
+
};
|
|
4051
|
+
}
|
|
4052
|
+
function aggregateAnnualSummaryFacts(facts, range, elapsedDayCount) {
|
|
4053
|
+
const ownerMessagesByDay = /* @__PURE__ */ new Map();
|
|
4054
|
+
const directContactsByDay = /* @__PURE__ */ new Map();
|
|
4055
|
+
const directContacts = /* @__PURE__ */ new Set();
|
|
4056
|
+
const messageTypes = /* @__PURE__ */ new Map();
|
|
4057
|
+
const textLengths = /* @__PURE__ */ new Map();
|
|
4058
|
+
const availableDataYears = /* @__PURE__ */ new Set();
|
|
4059
|
+
const coverage = {
|
|
4060
|
+
totalSessions: 0,
|
|
4061
|
+
analyzedSessions: 0,
|
|
4062
|
+
missingOwnerSessions: 0,
|
|
4063
|
+
unresolvedOwnerSessions: 0,
|
|
4064
|
+
failedSessions: 0
|
|
4065
|
+
};
|
|
4066
|
+
for (const item of facts) {
|
|
4067
|
+
if (item.kind === "not_chat_db" || item.kind === "missing_meta" || item.kind === "unsupported_type") continue;
|
|
4068
|
+
coverage.totalSessions++;
|
|
4069
|
+
if (item.kind === "missing_owner") {
|
|
4070
|
+
coverage.missingOwnerSessions++;
|
|
4071
|
+
continue;
|
|
4072
|
+
}
|
|
4073
|
+
if (item.kind === "unresolved_owner") {
|
|
4074
|
+
coverage.unresolvedOwnerSessions++;
|
|
4075
|
+
continue;
|
|
4076
|
+
}
|
|
4077
|
+
if (item.kind !== "analyzed") {
|
|
4078
|
+
coverage.failedSessions++;
|
|
4079
|
+
continue;
|
|
4080
|
+
}
|
|
4081
|
+
coverage.analyzedSessions++;
|
|
4082
|
+
item.availableDataYears.forEach((year) => availableDataYears.add(year));
|
|
4083
|
+
mergeNumberRecord(ownerMessagesByDay, item.ownerMessagesByDay);
|
|
4084
|
+
mergeNumberRecord(messageTypes, item.messageTypeCounts, Number);
|
|
4085
|
+
mergeNumberRecord(textLengths, item.textLengthCounts, Number);
|
|
4086
|
+
for (const [date, keys] of Object.entries(item.directContactKeysByDay)) {
|
|
4087
|
+
const daily = directContactsByDay.get(date) ?? /* @__PURE__ */ new Set();
|
|
4088
|
+
keys.forEach((key) => {
|
|
4089
|
+
daily.add(key);
|
|
4090
|
+
directContacts.add(key);
|
|
4091
|
+
});
|
|
4092
|
+
directContactsByDay.set(date, daily);
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
const dailyActivity = [...ownerMessagesByDay.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([date, messageCount]) => ({ date, messageCount }));
|
|
4096
|
+
const sentMessageCount = dailyActivity.reduce((sum, item) => sum + item.messageCount, 0);
|
|
4097
|
+
const dailyDirectContactTotal = [...directContactsByDay.values()].reduce((sum, keys) => sum + keys.size, 0);
|
|
4098
|
+
const years = [...availableDataYears].sort((a, b) => b - a);
|
|
4099
|
+
return {
|
|
4100
|
+
availableDataYears: years,
|
|
4101
|
+
latestDataYear: years[0] ?? null,
|
|
4102
|
+
metrics: {
|
|
4103
|
+
sentMessageCount,
|
|
4104
|
+
activeDayCount: dailyActivity.length,
|
|
4105
|
+
directContactCount: directContacts.size,
|
|
4106
|
+
averageMessagesPerDay: roundAverage(sentMessageCount, elapsedDayCount),
|
|
4107
|
+
averageDirectContactsPerDay: roundAverage(dailyDirectContactTotal, elapsedDayCount)
|
|
4108
|
+
},
|
|
4109
|
+
monthlyActivity: buildMonthlyActivity(range, ownerMessagesByDay),
|
|
4110
|
+
dailyActivity,
|
|
4111
|
+
messageTypes: [...messageTypes.entries()].sort(([a], [b]) => a - b).map(([type, count]) => ({ type, count })),
|
|
4112
|
+
textLength: buildTextLengthSummary(textLengths),
|
|
4113
|
+
coverage
|
|
4114
|
+
};
|
|
4115
|
+
}
|
|
4116
|
+
function getActivePrivateContacts(db, contacts, ownerId, range) {
|
|
4117
|
+
if (contacts.length <= 1) return contacts;
|
|
4118
|
+
const byId = new Map(contacts.map((contact) => [contact.id, contact]));
|
|
4119
|
+
const rows = db.prepare(
|
|
4120
|
+
`SELECT DISTINCT msg.sender_id as senderId FROM message msg
|
|
4121
|
+
WHERE msg.sender_id <> ? AND msg.ts >= ? AND msg.ts <= ?
|
|
4122
|
+
AND msg.type NOT IN (${SYSTEM_MESSAGE_TYPES2.join(", ")})`
|
|
4123
|
+
).all(ownerId, range.startTs, range.endTs);
|
|
4124
|
+
return rows.map((row) => byId.get(row.senderId)).filter((contact) => Boolean(contact));
|
|
4125
|
+
}
|
|
4126
|
+
function getPrivateDirectContactsByDay(db, sessionId, platform, ownerId, contact, range) {
|
|
4127
|
+
const rows = db.prepare(
|
|
4128
|
+
`SELECT DISTINCT strftime('%Y-%m-%d', msg.ts, 'unixepoch', 'localtime') as date
|
|
4129
|
+
FROM message msg
|
|
4130
|
+
WHERE msg.sender_id IN (?, ?) AND msg.ts >= ? AND msg.ts <= ?
|
|
4131
|
+
AND msg.type NOT IN (${SYSTEM_MESSAGE_TYPES2.join(", ")})
|
|
4132
|
+
ORDER BY date`
|
|
4133
|
+
).all(ownerId, contact.id, range.startTs, range.endTs);
|
|
4134
|
+
const key = buildContactKey(
|
|
4135
|
+
platform,
|
|
4136
|
+
contact.platformId,
|
|
4137
|
+
shouldScopeContactToSession(platform, contact) ? sessionId : void 0
|
|
4138
|
+
);
|
|
4139
|
+
return Object.fromEntries(rows.map((row) => [row.date, [key]]));
|
|
4140
|
+
}
|
|
4141
|
+
function getGroupDirectContactsByDay(db, sessionId, platform, ownerId, contacts, range) {
|
|
4142
|
+
const byId = new Map(contacts.map((contact) => [contact.id, contact]));
|
|
4143
|
+
const rows = db.prepare(
|
|
4144
|
+
`SELECT
|
|
4145
|
+
strftime('%Y-%m-%d', msg.ts, 'unixepoch', 'localtime') as date,
|
|
4146
|
+
msg.sender_id as replySenderId,
|
|
4147
|
+
target.sender_id as targetSenderId
|
|
4148
|
+
FROM message msg
|
|
4149
|
+
JOIN message target ON msg.reply_to_message_id = target.platform_message_id
|
|
4150
|
+
WHERE msg.ts >= ? AND msg.ts <= ? AND msg.reply_to_message_id IS NOT NULL
|
|
4151
|
+
AND msg.type NOT IN (${SYSTEM_MESSAGE_TYPES2.join(", ")})`
|
|
4152
|
+
).all(range.startTs, range.endTs);
|
|
4153
|
+
const byDay = /* @__PURE__ */ new Map();
|
|
4154
|
+
for (const row of rows) {
|
|
4155
|
+
const contactId = row.replySenderId === ownerId ? row.targetSenderId : row.targetSenderId === ownerId ? row.replySenderId : null;
|
|
4156
|
+
if (contactId === null) continue;
|
|
4157
|
+
const contact = byId.get(contactId);
|
|
4158
|
+
if (!contact) continue;
|
|
4159
|
+
const key = buildContactKey(
|
|
4160
|
+
platform,
|
|
4161
|
+
contact.platformId,
|
|
4162
|
+
shouldScopeContactToSession(platform, contact) ? sessionId : void 0
|
|
4163
|
+
);
|
|
4164
|
+
const keys = byDay.get(row.date) ?? /* @__PURE__ */ new Set();
|
|
4165
|
+
keys.add(key);
|
|
4166
|
+
byDay.set(row.date, keys);
|
|
4167
|
+
}
|
|
4168
|
+
return Object.fromEntries([...byDay.entries()].map(([date, keys]) => [date, [...keys].sort()]));
|
|
4169
|
+
}
|
|
4170
|
+
function buildMonthlyActivity(range, ownerMessagesByDay) {
|
|
4171
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4172
|
+
for (const [date, count] of ownerMessagesByDay) {
|
|
4173
|
+
const month = date.slice(0, 7);
|
|
4174
|
+
counts.set(month, (counts.get(month) ?? 0) + count);
|
|
4175
|
+
}
|
|
4176
|
+
return listMonths(range).map((month) => ({ month, messageCount: counts.get(month) ?? 0 }));
|
|
4177
|
+
}
|
|
4178
|
+
function listMonths(range) {
|
|
4179
|
+
if (range.mode === "year" && range.year) {
|
|
4180
|
+
return Array.from({ length: 12 }, (_, index) => `${range.year}-${String(index + 1).padStart(2, "0")}`);
|
|
4181
|
+
}
|
|
4182
|
+
const current = new Date(range.startTs * 1e3);
|
|
4183
|
+
current.setDate(1);
|
|
4184
|
+
current.setHours(0, 0, 0, 0);
|
|
4185
|
+
const end = new Date(range.endTs * 1e3);
|
|
4186
|
+
const result = [];
|
|
4187
|
+
while (current <= end) {
|
|
4188
|
+
result.push(`${current.getFullYear()}-${String(current.getMonth() + 1).padStart(2, "0")}`);
|
|
4189
|
+
current.setMonth(current.getMonth() + 1);
|
|
4190
|
+
}
|
|
4191
|
+
return result;
|
|
4192
|
+
}
|
|
4193
|
+
function buildTextLengthSummary(lengths) {
|
|
4194
|
+
const textMessageCount = [...lengths.values()].reduce((sum, count) => sum + count, 0);
|
|
4195
|
+
return {
|
|
4196
|
+
textMessageCount,
|
|
4197
|
+
median: weightedPercentile(lengths, 0.5),
|
|
4198
|
+
p90: weightedPercentile(lengths, 0.9),
|
|
4199
|
+
buckets: [
|
|
4200
|
+
{ key: "1-10", count: countLengthRange(lengths, 1, 10) },
|
|
4201
|
+
{ key: "11-30", count: countLengthRange(lengths, 11, 30) },
|
|
4202
|
+
{ key: "31-100", count: countLengthRange(lengths, 31, 100) },
|
|
4203
|
+
{ key: "101-300", count: countLengthRange(lengths, 101, 300) },
|
|
4204
|
+
{ key: "300+", count: countLengthRange(lengths, 301, Number.POSITIVE_INFINITY) }
|
|
4205
|
+
]
|
|
4206
|
+
};
|
|
4207
|
+
}
|
|
4208
|
+
function weightedPercentile(lengths, percentile) {
|
|
4209
|
+
const entries = [...lengths.entries()].sort(([a], [b]) => a - b);
|
|
4210
|
+
const total = entries.reduce((sum, [, count]) => sum + count, 0);
|
|
4211
|
+
if (total === 0) return null;
|
|
4212
|
+
const target = Math.floor((total - 1) * percentile);
|
|
4213
|
+
let seen = 0;
|
|
4214
|
+
for (const [length, count] of entries) {
|
|
4215
|
+
seen += count;
|
|
4216
|
+
if (seen > target) return length;
|
|
4217
|
+
}
|
|
4218
|
+
return entries.at(-1)?.[0] ?? null;
|
|
4219
|
+
}
|
|
4220
|
+
function countLengthRange(lengths, min, max) {
|
|
4221
|
+
let count = 0;
|
|
4222
|
+
for (const [length, value] of lengths) {
|
|
4223
|
+
if (length >= min && length <= max) count += value;
|
|
4224
|
+
}
|
|
4225
|
+
return count;
|
|
4226
|
+
}
|
|
4227
|
+
function rowsToNumberRecord(rows) {
|
|
4228
|
+
return Object.fromEntries(rows.filter((row) => row.key).map((row) => [row.key, row.count]));
|
|
4229
|
+
}
|
|
4230
|
+
function mergeNumberRecord(target, source, mapKey = (key) => key) {
|
|
4231
|
+
for (const [key, value] of Object.entries(source)) {
|
|
4232
|
+
const mapped = mapKey(key);
|
|
4233
|
+
target.set(mapped, (target.get(mapped) ?? 0) + value);
|
|
4234
|
+
}
|
|
4235
|
+
}
|
|
4236
|
+
function roundAverage(total, days) {
|
|
4237
|
+
if (days <= 0) return 0;
|
|
4238
|
+
return Math.round(total / days * 100) / 100;
|
|
4239
|
+
}
|
|
4240
|
+
function emptyFacts(kind) {
|
|
4241
|
+
return { kind, availableDataYears: [] };
|
|
4242
|
+
}
|
|
4243
|
+
|
|
3902
4244
|
// ../../packages/core/src/query/contact-enablement.ts
|
|
3903
4245
|
var MIN_PRIVATE_SESSIONS_FOR_CONTACTS = 5;
|
|
3904
4246
|
var MIN_GROUP_SESSIONS_FOR_CONTACTS = 1;
|
|
@@ -5890,20 +6232,6 @@ function getRepeatAnalysis(db, filter) {
|
|
|
5890
6232
|
return computeRepeat(messages);
|
|
5891
6233
|
}
|
|
5892
6234
|
|
|
5893
|
-
// ../../packages/shared-types/index.ts
|
|
5894
|
-
var KNOWN_PLATFORMS = {
|
|
5895
|
-
QQ: "qq",
|
|
5896
|
-
WECHAT: "weixin",
|
|
5897
|
-
DISCORD: "discord",
|
|
5898
|
-
WHATSAPP: "whatsapp",
|
|
5899
|
-
TELEGRAM: "telegram",
|
|
5900
|
-
INSTAGRAM: "instagram",
|
|
5901
|
-
GOOGLE_CHAT: "google-chat",
|
|
5902
|
-
LINE: "line",
|
|
5903
|
-
UNKNOWN: "unknown"
|
|
5904
|
-
};
|
|
5905
|
-
var CONTACTS_TIME_RANGE_PRESETS = ["1y", "2y", "3y", "5y", "all"];
|
|
5906
|
-
|
|
5907
6235
|
// ../../packages/core/src/message-type.ts
|
|
5908
6236
|
var TYPE_STRING_MAP = {
|
|
5909
6237
|
[0 /* TEXT */]: "text",
|
|
@@ -7093,68 +7421,6 @@ function isValidWord(word, locale, minLength, enableStopwords, isStopwordFn) {
|
|
|
7093
7421
|
return true;
|
|
7094
7422
|
}
|
|
7095
7423
|
|
|
7096
|
-
// ../../packages/core/src/owner/owner-matching.ts
|
|
7097
|
-
var NAME_MATCH_PLATFORMS = /* @__PURE__ */ new Set(["whatsapp", "line", "instagram"]);
|
|
7098
|
-
function isNameMatchPlatform(platform) {
|
|
7099
|
-
return NAME_MATCH_PLATFORMS.has(platform);
|
|
7100
|
-
}
|
|
7101
|
-
var INVISIBLE_CHARS_RE = /[\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/g;
|
|
7102
|
-
function normalizeOwnerName(name) {
|
|
7103
|
-
return name.replace(INVISIBLE_CHARS_RE, "").normalize("NFKC").replace(/\s+/g, " ").trim().toLowerCase();
|
|
7104
|
-
}
|
|
7105
|
-
function collectCandidateNames(member) {
|
|
7106
|
-
const names = [
|
|
7107
|
-
member.platformId,
|
|
7108
|
-
member.accountName ?? "",
|
|
7109
|
-
member.groupNickname ?? "",
|
|
7110
|
-
...member.aliases ?? [],
|
|
7111
|
-
member.displayName ?? ""
|
|
7112
|
-
];
|
|
7113
|
-
const result = [];
|
|
7114
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7115
|
-
for (const name of names) {
|
|
7116
|
-
if (!name || !name.trim()) continue;
|
|
7117
|
-
if (seen.has(name)) continue;
|
|
7118
|
-
seen.add(name);
|
|
7119
|
-
result.push(name);
|
|
7120
|
-
}
|
|
7121
|
-
return result;
|
|
7122
|
-
}
|
|
7123
|
-
function mergeConfirmedNames(existing, member) {
|
|
7124
|
-
const result = [];
|
|
7125
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7126
|
-
for (const name of [...existing, ...collectCandidateNames(member)]) {
|
|
7127
|
-
if (!name || !name.trim()) continue;
|
|
7128
|
-
if (seen.has(name)) continue;
|
|
7129
|
-
seen.add(name);
|
|
7130
|
-
result.push(name);
|
|
7131
|
-
}
|
|
7132
|
-
return result;
|
|
7133
|
-
}
|
|
7134
|
-
function matchOwnerProfile(platform, profile, members) {
|
|
7135
|
-
const exact = members.find((m) => m.platformId === profile.platformId);
|
|
7136
|
-
if (exact) {
|
|
7137
|
-
return { type: "exact", platformId: exact.platformId };
|
|
7138
|
-
}
|
|
7139
|
-
if (!isNameMatchPlatform(platform)) {
|
|
7140
|
-
return { type: "none" };
|
|
7141
|
-
}
|
|
7142
|
-
const confirmed = new Set(profile.confirmedNames.map(normalizeOwnerName).filter((n) => n.length > 0));
|
|
7143
|
-
if (confirmed.size === 0) {
|
|
7144
|
-
return { type: "none" };
|
|
7145
|
-
}
|
|
7146
|
-
const matched = members.filter(
|
|
7147
|
-
(m) => collectCandidateNames(m).some((name) => confirmed.has(normalizeOwnerName(name)))
|
|
7148
|
-
);
|
|
7149
|
-
if (matched.length === 1) {
|
|
7150
|
-
return { type: "name", platformId: matched[0].platformId };
|
|
7151
|
-
}
|
|
7152
|
-
if (matched.length > 1) {
|
|
7153
|
-
return { type: "ambiguous", platformIds: matched.map((m) => m.platformId) };
|
|
7154
|
-
}
|
|
7155
|
-
return { type: "none" };
|
|
7156
|
-
}
|
|
7157
|
-
|
|
7158
7424
|
// ../../packages/core/src/import/dedup.ts
|
|
7159
7425
|
function fnv1a64(input) {
|
|
7160
7426
|
let h0 = 2166136261;
|
|
@@ -8479,21 +8745,132 @@ function getContactsFactsCacheDir(userDataDir) {
|
|
|
8479
8745
|
return path16.join(getContactsDir(userDataDir), CONTACTS_FACTS_DIR_NAME);
|
|
8480
8746
|
}
|
|
8481
8747
|
|
|
8482
|
-
// ../../packages/node-runtime/src/services/
|
|
8748
|
+
// ../../packages/node-runtime/src/services/global-insight/paths.ts
|
|
8483
8749
|
import path17 from "path";
|
|
8750
|
+
function getGlobalInsightDir(userDataDir) {
|
|
8751
|
+
return path17.join(userDataDir, "insight", "annual-summary");
|
|
8752
|
+
}
|
|
8753
|
+
function getGlobalInsightFactsCacheDir(userDataDir) {
|
|
8754
|
+
return path17.join(getGlobalInsightDir(userDataDir), "facts");
|
|
8755
|
+
}
|
|
8756
|
+
|
|
8757
|
+
// ../../packages/node-runtime/src/services/people/relationships/paths.ts
|
|
8758
|
+
import path18 from "path";
|
|
8484
8759
|
var PEOPLE_DIR_NAME = "people";
|
|
8485
8760
|
var RELATIONSHIPS_DIR_NAME = "relationships";
|
|
8486
8761
|
var RELATIONSHIPS_FACTS_DIR_NAME = "facts";
|
|
8487
8762
|
function getPeopleRelationshipsDir(userDataDir) {
|
|
8488
|
-
return
|
|
8763
|
+
return path18.join(userDataDir, PEOPLE_DIR_NAME, RELATIONSHIPS_DIR_NAME);
|
|
8489
8764
|
}
|
|
8490
8765
|
function getPeopleRelationshipsFactsCacheDir(userDataDir) {
|
|
8491
|
-
return
|
|
8766
|
+
return path18.join(getPeopleRelationshipsDir(userDataDir), RELATIONSHIPS_FACTS_DIR_NAME);
|
|
8767
|
+
}
|
|
8768
|
+
|
|
8769
|
+
// ../../packages/node-runtime/src/database-manager.ts
|
|
8770
|
+
import * as fs17 from "fs";
|
|
8771
|
+
import * as path20 from "path";
|
|
8772
|
+
|
|
8773
|
+
// ../../packages/node-runtime/src/services/global-insight/snapshot.ts
|
|
8774
|
+
import fs16 from "fs";
|
|
8775
|
+
import path19 from "path";
|
|
8776
|
+
|
|
8777
|
+
// ../../packages/node-runtime/src/services/global-insight/time-range.ts
|
|
8778
|
+
function normalizeAnnualSummaryRange(input, nowInput = /* @__PURE__ */ new Date()) {
|
|
8779
|
+
const now = new Date(nowInput);
|
|
8780
|
+
const nowTs = Math.floor(now.getTime() / 1e3);
|
|
8781
|
+
if (input.mode === "recent") {
|
|
8782
|
+
const start2 = new Date(now);
|
|
8783
|
+
start2.setHours(0, 0, 0, 0);
|
|
8784
|
+
start2.setDate(start2.getDate() - 364);
|
|
8785
|
+
return {
|
|
8786
|
+
mode: "recent",
|
|
8787
|
+
days: 365,
|
|
8788
|
+
startTs: Math.floor(start2.getTime() / 1e3),
|
|
8789
|
+
endTs: nowTs
|
|
8790
|
+
};
|
|
8791
|
+
}
|
|
8792
|
+
const currentYear = now.getFullYear();
|
|
8793
|
+
const parsedYear = Number(input.year);
|
|
8794
|
+
const year = Number.isInteger(parsedYear) && parsedYear >= 1970 && parsedYear <= currentYear ? parsedYear : currentYear;
|
|
8795
|
+
const start = new Date(year, 0, 1, 0, 0, 0);
|
|
8796
|
+
const end = year === currentYear ? now : new Date(year, 11, 31, 23, 59, 59);
|
|
8797
|
+
return {
|
|
8798
|
+
mode: "year",
|
|
8799
|
+
year,
|
|
8800
|
+
startTs: Math.floor(start.getTime() / 1e3),
|
|
8801
|
+
endTs: Math.floor(end.getTime() / 1e3)
|
|
8802
|
+
};
|
|
8803
|
+
}
|
|
8804
|
+
function getAnnualSummaryElapsedDayCount(range) {
|
|
8805
|
+
const start = new Date(range.startTs * 1e3);
|
|
8806
|
+
const end = new Date(range.endTs * 1e3);
|
|
8807
|
+
const startDay = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
|
|
8808
|
+
const endDay = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());
|
|
8809
|
+
return Math.max(Math.floor((endDay - startDay) / 864e5) + 1, 0);
|
|
8810
|
+
}
|
|
8811
|
+
function toAnnualSummaryRangeKey(range) {
|
|
8812
|
+
return range.mode === "year" ? `year-${range.year}` : "recent-365";
|
|
8813
|
+
}
|
|
8814
|
+
function toAnnualSummaryLocalDate(range) {
|
|
8815
|
+
const date = new Date(range.endTs * 1e3);
|
|
8816
|
+
return [
|
|
8817
|
+
date.getFullYear(),
|
|
8818
|
+
String(date.getMonth() + 1).padStart(2, "0"),
|
|
8819
|
+
String(date.getDate()).padStart(2, "0")
|
|
8820
|
+
].join("-");
|
|
8821
|
+
}
|
|
8822
|
+
|
|
8823
|
+
// ../../packages/node-runtime/src/services/global-insight/snapshot.ts
|
|
8824
|
+
var SNAPSHOT_TMP_PREFIX = "annual-summary.tmp-";
|
|
8825
|
+
function getAnnualSummarySnapshotPath(snapshotDir, range) {
|
|
8826
|
+
return path19.join(snapshotDir, `annual-summary-${toAnnualSummaryRangeKey(range)}.json`);
|
|
8827
|
+
}
|
|
8828
|
+
function readAnnualSummarySnapshot(snapshotDir, range, options = {}) {
|
|
8829
|
+
const snapshotPath = getAnnualSummarySnapshotPath(snapshotDir, range);
|
|
8830
|
+
if (!fs16.existsSync(snapshotPath)) return null;
|
|
8831
|
+
try {
|
|
8832
|
+
return JSON.parse(fs16.readFileSync(snapshotPath, "utf-8"));
|
|
8833
|
+
} catch (error) {
|
|
8834
|
+
const backupPath = path19.join(snapshotDir, `annual-summary.corrupt-${options.now?.() ?? Date.now()}.json`);
|
|
8835
|
+
try {
|
|
8836
|
+
fs16.renameSync(snapshotPath, backupPath);
|
|
8837
|
+
} catch (renameError) {
|
|
8838
|
+
appLogger.warn("global-insight", "failed to backup corrupt annual summary snapshot", renameError);
|
|
8839
|
+
}
|
|
8840
|
+
appLogger.warn("global-insight", "annual summary snapshot is corrupt", error);
|
|
8841
|
+
return null;
|
|
8842
|
+
}
|
|
8843
|
+
}
|
|
8844
|
+
function writeAnnualSummarySnapshot(snapshotDir, snapshot) {
|
|
8845
|
+
fs16.mkdirSync(snapshotDir, { recursive: true });
|
|
8846
|
+
const tmpPath = path19.join(snapshotDir, `${SNAPSHOT_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
8847
|
+
fs16.writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
8848
|
+
fs16.renameSync(tmpPath, getAnnualSummarySnapshotPath(snapshotDir, snapshot.range));
|
|
8849
|
+
}
|
|
8850
|
+
function cleanupAnnualSummarySnapshotTempFiles(snapshotDir) {
|
|
8851
|
+
if (!fs16.existsSync(snapshotDir)) return;
|
|
8852
|
+
for (const name of fs16.readdirSync(snapshotDir)) {
|
|
8853
|
+
if (!name.startsWith(SNAPSHOT_TMP_PREFIX)) continue;
|
|
8854
|
+
try {
|
|
8855
|
+
fs16.rmSync(path19.join(snapshotDir, name), { force: true });
|
|
8856
|
+
} catch (error) {
|
|
8857
|
+
appLogger.warn("global-insight", "failed to remove annual summary snapshot temp file", error);
|
|
8858
|
+
}
|
|
8859
|
+
}
|
|
8860
|
+
}
|
|
8861
|
+
function deleteAnnualSummarySnapshots(snapshotDir) {
|
|
8862
|
+
if (!fs16.existsSync(snapshotDir)) return;
|
|
8863
|
+
for (const name of fs16.readdirSync(snapshotDir)) {
|
|
8864
|
+
if (!name.startsWith("annual-summary-") && !name.startsWith("annual-summary.")) continue;
|
|
8865
|
+
try {
|
|
8866
|
+
fs16.rmSync(path19.join(snapshotDir, name), { force: true });
|
|
8867
|
+
} catch (error) {
|
|
8868
|
+
appLogger.warn("global-insight", "failed to remove annual summary snapshot", error);
|
|
8869
|
+
}
|
|
8870
|
+
}
|
|
8492
8871
|
}
|
|
8493
8872
|
|
|
8494
8873
|
// ../../packages/node-runtime/src/database-manager.ts
|
|
8495
|
-
import * as fs16 from "fs";
|
|
8496
|
-
import * as path18 from "path";
|
|
8497
8874
|
function createMigrationDeps(overrides) {
|
|
8498
8875
|
return {
|
|
8499
8876
|
tokenizeForFts,
|
|
@@ -8524,7 +8901,7 @@ var DatabaseManager = class {
|
|
|
8524
8901
|
return this.cache.get(sessionId);
|
|
8525
8902
|
}
|
|
8526
8903
|
const dbPath = this.getDbPath(sessionId);
|
|
8527
|
-
if (!
|
|
8904
|
+
if (!fs17.existsSync(dbPath)) return null;
|
|
8528
8905
|
this.migrateIfNeeded(dbPath);
|
|
8529
8906
|
this.assertCompatible();
|
|
8530
8907
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
@@ -8570,7 +8947,7 @@ var DatabaseManager = class {
|
|
|
8570
8947
|
this.cache.delete(sessionId);
|
|
8571
8948
|
}
|
|
8572
8949
|
const dbPath = this.getDbPath(sessionId);
|
|
8573
|
-
if (!
|
|
8950
|
+
if (!fs17.existsSync(dbPath)) return null;
|
|
8574
8951
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
8575
8952
|
readonly: false,
|
|
8576
8953
|
nativeBinding: this.nativeBinding
|
|
@@ -8610,28 +8987,31 @@ var DatabaseManager = class {
|
|
|
8610
8987
|
listSessionIds() {
|
|
8611
8988
|
this.assertCompatible();
|
|
8612
8989
|
const dbDir = this.pathProvider.getDatabaseDir();
|
|
8613
|
-
if (!
|
|
8614
|
-
return
|
|
8990
|
+
if (!fs17.existsSync(dbDir)) return [];
|
|
8991
|
+
return fs17.readdirSync(dbDir).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", "")).filter((id) => {
|
|
8615
8992
|
const db = this.open(id);
|
|
8616
8993
|
if (!db) return false;
|
|
8617
8994
|
return isChatSessionDb(db);
|
|
8618
8995
|
});
|
|
8619
8996
|
}
|
|
8997
|
+
getUserDataDir() {
|
|
8998
|
+
return this.pathProvider.getUserDataDir();
|
|
8999
|
+
}
|
|
8620
9000
|
/**
|
|
8621
9001
|
* 获取数据库文件路径
|
|
8622
9002
|
*/
|
|
8623
9003
|
getDbPath(sessionId) {
|
|
8624
|
-
return
|
|
9004
|
+
return path20.join(this.pathProvider.getDatabaseDir(), `${sessionId}.db`);
|
|
8625
9005
|
}
|
|
8626
9006
|
openRawSessionDatabase(sessionId, options = {}) {
|
|
8627
9007
|
this.assertCompatible();
|
|
8628
9008
|
const dbPath = this.getDbPath(sessionId);
|
|
8629
|
-
if (!options.create && !
|
|
9009
|
+
if (!options.create && !fs17.existsSync(dbPath)) {
|
|
8630
9010
|
throw new Error(`Session database not found: ${sessionId}`);
|
|
8631
9011
|
}
|
|
8632
9012
|
if (!options.readonly) {
|
|
8633
9013
|
this.close(sessionId);
|
|
8634
|
-
|
|
9014
|
+
fs17.mkdirSync(path20.dirname(dbPath), { recursive: true });
|
|
8635
9015
|
}
|
|
8636
9016
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
8637
9017
|
readonly: options.readonly ?? false,
|
|
@@ -8649,18 +9029,20 @@ var DatabaseManager = class {
|
|
|
8649
9029
|
deleteSessionDatabaseFiles(sessionId) {
|
|
8650
9030
|
this.close(sessionId);
|
|
8651
9031
|
const dbPath = this.getDbPath(sessionId);
|
|
8652
|
-
const existed = ["", "-wal", "-shm"].some((suffix) =>
|
|
9032
|
+
const existed = ["", "-wal", "-shm"].some((suffix) => fs17.existsSync(dbPath + suffix));
|
|
8653
9033
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
8654
9034
|
try {
|
|
8655
9035
|
const filePath = dbPath + suffix;
|
|
8656
|
-
if (
|
|
9036
|
+
if (fs17.existsSync(filePath)) fs17.unlinkSync(filePath);
|
|
8657
9037
|
} catch {
|
|
8658
9038
|
}
|
|
8659
9039
|
}
|
|
8660
9040
|
const cacheDir = this.pathProvider.getCacheDir();
|
|
8661
9041
|
deleteSessionCache(sessionId, cacheDir);
|
|
8662
|
-
deleteSessionCache(sessionId,
|
|
9042
|
+
deleteSessionCache(sessionId, path20.join(cacheDir, "query"));
|
|
8663
9043
|
deleteSessionCache(sessionId, getContactsFactsCacheDir(this.pathProvider.getUserDataDir()));
|
|
9044
|
+
deleteSessionCache(sessionId, getGlobalInsightFactsCacheDir(this.pathProvider.getUserDataDir()));
|
|
9045
|
+
deleteAnnualSummarySnapshots(getGlobalInsightDir(this.pathProvider.getUserDataDir()));
|
|
8664
9046
|
deleteSessionCache(sessionId, getPeopleRelationshipsFactsCacheDir(this.pathProvider.getUserDataDir()));
|
|
8665
9047
|
return existed;
|
|
8666
9048
|
}
|
|
@@ -8698,12 +9080,12 @@ function shouldRepairCompatibilityGate(schemaVersion) {
|
|
|
8698
9080
|
}
|
|
8699
9081
|
|
|
8700
9082
|
// ../../packages/node-runtime/src/cache/analytics-cache.ts
|
|
8701
|
-
import * as
|
|
9083
|
+
import * as fs18 from "fs";
|
|
8702
9084
|
function getDbFileVersion(dbPath) {
|
|
8703
9085
|
const parts = [];
|
|
8704
9086
|
for (const p of [dbPath, `${dbPath}-wal`]) {
|
|
8705
9087
|
try {
|
|
8706
|
-
const st =
|
|
9088
|
+
const st = fs18.statSync(p);
|
|
8707
9089
|
parts.push(`${Math.floor(st.mtimeMs)}:${st.size}`);
|
|
8708
9090
|
} catch {
|
|
8709
9091
|
parts.push("-");
|
|
@@ -8866,6 +9248,13 @@ export {
|
|
|
8866
9248
|
getPrivateContactFacts,
|
|
8867
9249
|
getGroupContactFacts,
|
|
8868
9250
|
getGroupRelationshipGraphFacts,
|
|
9251
|
+
isNameMatchPlatform,
|
|
9252
|
+
mergeConfirmedNames,
|
|
9253
|
+
matchOwnerProfile,
|
|
9254
|
+
shouldScopeContactToSession,
|
|
9255
|
+
buildContactKey,
|
|
9256
|
+
getAnnualSummarySessionFacts,
|
|
9257
|
+
aggregateAnnualSummaryFacts,
|
|
8869
9258
|
shouldEnableContactsEntry,
|
|
8870
9259
|
computeFriendScores,
|
|
8871
9260
|
computeNonFriendScores,
|
|
@@ -8916,9 +9305,6 @@ export {
|
|
|
8916
9305
|
isReasoningModel,
|
|
8917
9306
|
getThinkingCompat,
|
|
8918
9307
|
truncateToolResultText,
|
|
8919
|
-
isNameMatchPlatform,
|
|
8920
|
-
mergeConfirmedNames,
|
|
8921
|
-
matchOwnerProfile,
|
|
8922
9308
|
generateMessageKey,
|
|
8923
9309
|
getCollidingPlatformIds,
|
|
8924
9310
|
normalizePlatformId,
|
|
@@ -8959,6 +9345,17 @@ export {
|
|
|
8959
9345
|
getChatDbMigrations,
|
|
8960
9346
|
getContactsDir,
|
|
8961
9347
|
getContactsFactsCacheDir,
|
|
9348
|
+
getGlobalInsightDir,
|
|
9349
|
+
getGlobalInsightFactsCacheDir,
|
|
9350
|
+
normalizeAnnualSummaryRange,
|
|
9351
|
+
getAnnualSummaryElapsedDayCount,
|
|
9352
|
+
toAnnualSummaryRangeKey,
|
|
9353
|
+
toAnnualSummaryLocalDate,
|
|
9354
|
+
getAnnualSummarySnapshotPath,
|
|
9355
|
+
readAnnualSummarySnapshot,
|
|
9356
|
+
writeAnnualSummarySnapshot,
|
|
9357
|
+
cleanupAnnualSummarySnapshotTempFiles,
|
|
9358
|
+
deleteAnnualSummarySnapshots,
|
|
8962
9359
|
getPeopleRelationshipsDir,
|
|
8963
9360
|
getPeopleRelationshipsFactsCacheDir,
|
|
8964
9361
|
DatabaseManager,
|
|
@@ -8968,4 +9365,4 @@ export {
|
|
|
8968
9365
|
StaticPathProvider,
|
|
8969
9366
|
createDatabaseManagerAdapter
|
|
8970
9367
|
};
|
|
8971
|
-
//# sourceMappingURL=chunk-
|
|
9368
|
+
//# sourceMappingURL=chunk-UWWFOEGF.mjs.map
|