chatlab-cli 0.30.2-beta.1 → 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-CYSOCeE0.js → BufferResource-BPGkshPa.js} +1 -1
- package/dist-web/assets/{CanvasRenderer-j7Z_ij_m.js → CanvasRenderer-DTKkZhq4.js} +1 -1
- package/dist-web/assets/{EChartWordcloud-Clg60FMo.js → EChartWordcloud-DU3ZYdgz.js} +1 -1
- package/dist-web/assets/{Filter-BgGyBeXz.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-D2owKyDp.js → RelationshipGalaxyCanvas-Dwdy5flh.js} +3 -3
- package/dist-web/assets/{RelationshipGalaxyThreeCanvas-DfJ2x8y9.js → RelationshipGalaxyThreeCanvas-CtY4TGen.js} +1 -1
- package/dist-web/assets/{RenderTargetSystem-BQ__RbzR.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-DuThUm1R.js → WebGLRenderer-Dm18dxOf.js} +1 -1
- package/dist-web/assets/{WebGPURenderer-d8BwTpxP.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-t_tpJM2L.js → browserAll-Cn_CfkXl.js} +1 -1
- package/dist-web/assets/dateFormat-BcqNKTQ1.js +1 -0
- package/dist-web/assets/{electron-6T3FvCfK.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-DFifsv8L.js → fetch-BRXmDI_2.js} +1 -1
- package/dist-web/assets/{fetch-BgeRLaoA.js → fetch-BUm1isWe.js} +1 -1
- package/dist-web/assets/{fetch-Y-LYZmiT.js → fetch-CBOJwwJp.js} +3 -3
- package/dist-web/assets/{fetch-C7rlHKE7.js → fetch-CEhUu1Yu.js} +1 -1
- package/dist-web/assets/fetch-C_EfVFJi.js +3 -0
- package/dist-web/assets/{fetch-BVM5kQ6-.js → fetch-DL_u25Ui.js} +1 -1
- package/dist-web/assets/{fetch-BLTlXcRA.js → fetch-DMLq3xPG.js} +1 -1
- package/dist-web/assets/{fetch-BgIWhYDV.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-BA87rT8F.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-BUZ-dZy0.js +1 -0
- package/dist-web/assets/{webworkerAll-CoXPTsvw.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-Bk9RvIsW.js +0 -110
- package/dist-web/assets/MessageExportModal-BkEhC8s3.js +0 -1
- package/dist-web/assets/PageHeader-Bbn87QZS.css +0 -1
- package/dist-web/assets/PageHeader-CUwv2AFR.js +0 -1
- package/dist-web/assets/electron-D9vE5t3H.js +0 -1
- package/dist-web/assets/fetch-D0ccqGk_.js +0 -1
- package/dist-web/assets/fetch-DdoIAbX4.js +0 -1
- package/dist-web/assets/fetch-HpiZrx8C.js +0 -3
- package/dist-web/assets/index---rXG1hZ.css +0 -1
- package/dist-web/assets/index-B4l3rHie.css +0 -1
- package/dist-web/assets/index-B5YKZflT.js +0 -2
- package/dist-web/assets/index-C1p9CbmN.css +0 -1
- package/dist-web/assets/index-COpza1A4.css +0 -1
- package/dist-web/assets/index-CQsrsY5d.js +0 -64
- package/dist-web/assets/index-CdsKtFEJ.js +0 -22
- package/dist-web/assets/index-DosG7LmJ.css +0 -1
- package/dist-web/assets/index-DraLHiEK.js +0 -173
- package/dist-web/assets/index-IL5tkxhM.js +0 -2
- package/dist-web/assets/index-Tgk7RCvc.js +0 -1
- package/dist-web/assets/index-cyh3gOBe.js +0 -1
- package/dist-web/assets/index-g8yqhgfj.js +0 -1
- package/dist-web/assets/web-DAgXT8gQ.js +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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../packages/node-runtime/src/services/people/relationships/facts-cache.ts","../../../packages/node-runtime/src/services/people/relationships/time-range.ts","../../../packages/node-runtime/src/services/people/relationships/compute.ts"],"sourcesContent":["import { ChatType, type ChatPlatform, type ContactsTimeRangeState } from '@openchatlab/shared-types'\nimport type {\n ContactMemberRef,\n GroupContactFacts,\n RelationshipGraphEdgeFact,\n RelationshipGraphMemberFact,\n} from '@openchatlab/core'\nimport { deleteSessionCache, getCache, setCache } from '../../../cache/session-cache'\n\nexport const PEOPLE_RELATIONSHIPS_FACTS_FORMAT_VERSION = 3\n\nexport interface PeopleRelationshipsFactsCacheStats {\n latestHits: number\n latestMisses: number\n factsHits: number\n factsMisses: number\n writes: number\n}\n\nexport interface PeopleRelationshipsSessionMetaFacts {\n name: string\n platform: ChatPlatform\n type: ChatType.PRIVATE | ChatType.GROUP\n ownerId: string | null\n owner?: ContactMemberRef\n}\n\nexport interface PeopleRelationshipsCachedPrivateFacts {\n contact: ContactMemberRef\n privateMessageCount: number\n activeMonths: string[]\n lastMessageTs: number | null\n}\n\nexport interface PeopleRelationshipsCachedGroupFacts {\n members: RelationshipGraphMemberFact[]\n edges: RelationshipGraphEdgeFact[]\n ownerEdges: GroupContactFacts[]\n ownerMessageCount: number\n}\n\nexport type PeopleRelationshipsSessionFacts =\n | { kind: 'not_chat_db'; latestMessageTs: null }\n | { kind: 'missing_meta'; latestMessageTs: number | null }\n | { kind: 'unsupported_type'; latestMessageTs: number | null }\n | { kind: 'missing_owner'; meta: PeopleRelationshipsSessionMetaFacts; latestMessageTs: number | null }\n | { kind: 'unresolved_owner'; meta: PeopleRelationshipsSessionMetaFacts; latestMessageTs: number | null }\n | { kind: 'private_missing'; meta: PeopleRelationshipsSessionMetaFacts; latestMessageTs: number | null }\n | { kind: 'private_ambiguous'; meta: PeopleRelationshipsSessionMetaFacts; latestMessageTs: number | null }\n | {\n kind: 'private'\n meta: PeopleRelationshipsSessionMetaFacts\n latestMessageTs: number | null\n facts: PeopleRelationshipsCachedPrivateFacts\n }\n | {\n kind: 'group'\n meta: PeopleRelationshipsSessionMetaFacts\n latestMessageTs: number | null\n facts: PeopleRelationshipsCachedGroupFacts\n }\n\nexport interface PeopleRelationshipsSessionLatestFacts {\n latestMessageTs: number | null\n}\n\nexport type PeopleRelationshipsCacheReadResult<T> = { hit: true; data: T } | { hit: false }\n\ninterface VersionedPeopleRelationshipsCacheEntry<T> {\n v: string\n data: T\n}\n\nexport function createEmptyPeopleRelationshipsFactsCacheStats(): PeopleRelationshipsFactsCacheStats {\n return {\n latestHits: 0,\n latestMisses: 0,\n factsHits: 0,\n factsMisses: 0,\n writes: 0,\n }\n}\n\nexport function buildPeopleRelationshipsSessionLatestCacheKey(algorithmVersion: string): string {\n return `people-relationships:latest:v${PEOPLE_RELATIONSHIPS_FACTS_FORMAT_VERSION}:${algorithmVersion}`\n}\n\nexport function buildPeopleRelationshipsSessionFactsCacheKey(\n algorithmVersion: string,\n timeRange: ContactsTimeRangeState\n): string {\n return [\n 'people-relationships:facts',\n `v${PEOPLE_RELATIONSHIPS_FACTS_FORMAT_VERSION}`,\n algorithmVersion,\n `preset:${timeRange.preset}`,\n `start:${timeRange.startTs ?? 'all'}`,\n ].join(':')\n}\n\nexport function readCachedPeopleRelationshipsSessionLatest(\n sessionId: string,\n cacheDir: string,\n key: string,\n dbVersion: string\n): PeopleRelationshipsCacheReadResult<PeopleRelationshipsSessionLatestFacts> {\n const cached = getCache<VersionedPeopleRelationshipsCacheEntry<PeopleRelationshipsSessionLatestFacts>>(\n sessionId,\n key,\n cacheDir\n )\n if (!cached || cached.v !== dbVersion || !isPeopleRelationshipsSessionLatestFacts(cached.data)) return { hit: false }\n return { hit: true, data: cached.data }\n}\n\nexport function writeCachedPeopleRelationshipsSessionLatest(\n sessionId: string,\n cacheDir: string,\n key: string,\n dbVersion: string,\n data: PeopleRelationshipsSessionLatestFacts\n): void {\n setCache<VersionedPeopleRelationshipsCacheEntry<PeopleRelationshipsSessionLatestFacts>>(\n sessionId,\n key,\n { v: dbVersion, data },\n cacheDir\n )\n}\n\nexport function readCachedPeopleRelationshipsSessionFacts(\n sessionId: string,\n cacheDir: string,\n key: string,\n dbVersion: string\n): PeopleRelationshipsCacheReadResult<PeopleRelationshipsSessionFacts> {\n const cached = getCache<VersionedPeopleRelationshipsCacheEntry<PeopleRelationshipsSessionFacts>>(\n sessionId,\n key,\n cacheDir\n )\n if (!cached || cached.v !== dbVersion || !isPeopleRelationshipsSessionFacts(cached.data)) return { hit: false }\n return { hit: true, data: cached.data }\n}\n\nexport function writeCachedPeopleRelationshipsSessionFacts(\n sessionId: string,\n cacheDir: string,\n key: string,\n dbVersion: string,\n data: PeopleRelationshipsSessionFacts\n): void {\n setCache<VersionedPeopleRelationshipsCacheEntry<PeopleRelationshipsSessionFacts>>(\n sessionId,\n key,\n { v: dbVersion, data },\n cacheDir\n )\n}\n\nexport function deletePeopleRelationshipsSessionFactsCache(sessionId: string, cacheDir: string): void {\n deleteSessionCache(sessionId, cacheDir)\n}\n\nfunction isPeopleRelationshipsSessionLatestFacts(value: unknown): value is PeopleRelationshipsSessionLatestFacts {\n return isObject(value) && isNullableNumber(value.latestMessageTs)\n}\n\nfunction isPeopleRelationshipsSessionFacts(value: unknown): value is PeopleRelationshipsSessionFacts {\n if (!isObject(value) || typeof value.kind !== 'string' || !isNullableNumber(value.latestMessageTs)) return false\n switch (value.kind) {\n case 'not_chat_db':\n case 'missing_meta':\n case 'unsupported_type':\n return true\n case 'missing_owner':\n case 'unresolved_owner':\n case 'private_missing':\n case 'private_ambiguous':\n return isPeopleRelationshipsSessionMetaFacts(value.meta)\n case 'private':\n return isPeopleRelationshipsSessionMetaFacts(value.meta) && isPeopleRelationshipsCachedPrivateFacts(value.facts)\n case 'group':\n return isPeopleRelationshipsSessionMetaFacts(value.meta) && isPeopleRelationshipsCachedGroupFacts(value.facts)\n default:\n return false\n }\n}\n\nfunction isPeopleRelationshipsSessionMetaFacts(value: unknown): value is PeopleRelationshipsSessionMetaFacts {\n return (\n isObject(value) &&\n typeof value.name === 'string' &&\n typeof value.platform === 'string' &&\n (value.type === ChatType.PRIVATE || value.type === ChatType.GROUP) &&\n (typeof value.ownerId === 'string' || value.ownerId === null) &&\n (value.owner === undefined || isContactMemberRef(value.owner))\n )\n}\n\nfunction isPeopleRelationshipsCachedPrivateFacts(value: unknown): value is PeopleRelationshipsCachedPrivateFacts {\n return (\n isObject(value) &&\n isContactMemberRef(value.contact) &&\n isFiniteNumber(value.privateMessageCount) &&\n Array.isArray(value.activeMonths) &&\n value.activeMonths.every((month) => typeof month === 'string') &&\n isNullableNumber(value.lastMessageTs)\n )\n}\n\nfunction isPeopleRelationshipsCachedGroupFacts(value: unknown): value is PeopleRelationshipsCachedGroupFacts {\n return (\n isObject(value) &&\n Array.isArray(value.members) &&\n value.members.every(isRelationshipGraphMemberFact) &&\n Array.isArray(value.edges) &&\n value.edges.every(isRelationshipGraphEdgeFact) &&\n Array.isArray(value.ownerEdges) &&\n value.ownerEdges.every(isGroupContactFacts) &&\n isFiniteNumber(value.ownerMessageCount)\n )\n}\n\nfunction isGroupContactFacts(value: unknown): value is GroupContactFacts {\n return (\n isObject(value) &&\n isContactMemberRef(value.contact) &&\n isFiniteNumber(value.messageCount) &&\n isFiniteNumber(value.coOccurrenceCount) &&\n isFiniteNumber(value.coOccurrenceRawScore) &&\n isFiniteNumber(value.replyInteractionCount) &&\n isFiniteNumber(value.repliesFromOwnerToContact) &&\n isFiniteNumber(value.repliesFromContactToOwner) &&\n isNullableNumber(value.lastInteractionTs)\n )\n}\n\nfunction isRelationshipGraphMemberFact(value: unknown): value is RelationshipGraphMemberFact {\n return (\n isObject(value) &&\n isContactMemberRef(value.contact) &&\n isFiniteNumber(value.messageCount) &&\n isNullableNumber(value.lastMessageTs)\n )\n}\n\nfunction isRelationshipGraphEdgeFact(value: unknown): value is RelationshipGraphEdgeFact {\n return (\n isObject(value) &&\n isContactMemberRef(value.source) &&\n isContactMemberRef(value.target) &&\n isFiniteNumber(value.coOccurrenceCount) &&\n isFiniteNumber(value.coOccurrenceRawScore) &&\n isFiniteNumber(value.replyInteractionCount) &&\n isFiniteNumber(value.repliesFromSourceToTarget) &&\n isFiniteNumber(value.repliesFromTargetToSource) &&\n isNullableNumber(value.lastInteractionTs)\n )\n}\n\nfunction isContactMemberRef(value: unknown): value is ContactMemberRef {\n return (\n isObject(value) &&\n isFiniteNumber(value.id) &&\n typeof value.platformId === 'string' &&\n typeof value.name === 'string' &&\n Array.isArray(value.aliases) &&\n value.aliases.every((alias) => typeof alias === 'string') &&\n (typeof value.avatar === 'string' || value.avatar === null)\n )\n}\n\nfunction isNullableNumber(value: unknown): value is number | null {\n return value === null || isFiniteNumber(value)\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n","import {\n CONTACTS_TIME_RANGE_PRESETS,\n type ContactsTimeRangePreset,\n type ContactsTimeRangeState,\n} from '@openchatlab/shared-types'\n\nconst SECONDS_PER_YEAR = 365 * 24 * 60 * 60\nconst DEFAULT_PEOPLE_RELATIONSHIPS_TIME_RANGE_PRESET: ContactsTimeRangePreset = '1y'\n\nconst YEARS_BY_PRESET: Partial<Record<ContactsTimeRangePreset, number>> = {\n '1y': 1,\n '2y': 2,\n '3y': 3,\n '5y': 5,\n}\n\nexport function normalizePeopleRelationshipsTimeRangePreset(value: unknown): ContactsTimeRangePreset {\n return CONTACTS_TIME_RANGE_PRESETS.includes(value as ContactsTimeRangePreset)\n ? (value as ContactsTimeRangePreset)\n : DEFAULT_PEOPLE_RELATIONSHIPS_TIME_RANGE_PRESET\n}\n\nexport function resolvePeopleRelationshipsTimeRange(\n presetInput: unknown,\n anchorTs: number | null | undefined\n): ContactsTimeRangeState {\n const preset = normalizePeopleRelationshipsTimeRangePreset(presetInput)\n const normalizedAnchor = typeof anchorTs === 'number' ? anchorTs : null\n const years = YEARS_BY_PRESET[preset]\n\n return {\n preset,\n anchorTs: normalizedAnchor,\n startTs: normalizedAnchor !== null && years ? normalizedAnchor - years * SECONDS_PER_YEAR : null,\n }\n}\n","import {\n ChatType,\n type ChatPlatform,\n type ContactsTimeRangePreset,\n type ContactsTimeRangeState,\n type PeopleRelationshipCommunity,\n type PeopleRelationshipsGraphData,\n type PeopleRelationshipGraphEdge,\n type PeopleRelationshipGraphNode,\n type PeopleRelationshipsDiagnostics,\n} from '@openchatlab/shared-types'\nimport {\n computeFriendScores,\n computeNonFriendScores,\n getGroupContactFacts,\n getGroupRelationshipGraphFacts,\n getLatestContactMessageTs,\n getPrivateContactFacts,\n getSessionMeta,\n isChatSessionDb,\n isNameMatchPlatform,\n resolveOwnerMember,\n} from '@openchatlab/core'\nimport type { ContactMemberRef, SessionMeta } from '@openchatlab/core'\nimport { getDbFileVersion } from '../../../cache/analytics-cache'\nimport { appLogger } from '../../../logging/app-logger'\nimport type { SessionRuntimeAdapter } from '../../adapters'\nimport {\n buildPeopleRelationshipsSessionFactsCacheKey,\n buildPeopleRelationshipsSessionLatestCacheKey,\n createEmptyPeopleRelationshipsFactsCacheStats,\n readCachedPeopleRelationshipsSessionFacts,\n readCachedPeopleRelationshipsSessionLatest,\n writeCachedPeopleRelationshipsSessionFacts,\n writeCachedPeopleRelationshipsSessionLatest,\n type PeopleRelationshipsCachedGroupFacts,\n type PeopleRelationshipsCachedPrivateFacts,\n type PeopleRelationshipsFactsCacheStats,\n type PeopleRelationshipsSessionFacts,\n type PeopleRelationshipsSessionLatestFacts,\n type PeopleRelationshipsSessionMetaFacts,\n} from './facts-cache'\nimport { resolvePeopleRelationshipsTimeRange } from './time-range'\n\nexport const PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION = 'people-relationships-v2'\n\nconst PRIVATE_COMMUNITY_ID = 'private'\nconst OWNER_KEY_PREFIX = 'owner'\nconst REPLY_WEIGHT = 3\nconst CO_OCCURRENCE_COUNT_WEIGHT = 0.05\nconst EDGE_RECENCY_HALF_LIFE_SECONDS = 120 * 24 * 60 * 60\nconst EDGE_RECENCY_FLOOR = 0.1\nconst MIN_GROUP_FRIENDS_FOR_PANORAMA = 3\nconst MIN_GROUP_FRIEND_RATIO_FOR_PANORAMA = 0.2\nconst MIN_OWNER_CONNECTED_MEMBERS_FOR_PANORAMA = 3\nconst MIN_OWNER_GROUP_MESSAGES_FOR_PANORAMA = 20\nconst MIN_OWNER_GROUP_MESSAGE_RATIO_FOR_PANORAMA = 0.05\nconst MIN_OWNER_GROUP_MESSAGES_FOR_RATIO = 8\nconst SMALL_GROUP_MEMBER_LIMIT_FOR_FRIEND_EDGE = 12\nconst MAX_OWNER_CONNECTED_NON_FRIENDS_PER_GROUP = 30\nconst MAX_FRIEND_CONNECTED_NON_FRIENDS_PER_GROUP = 30\nconst MAX_HIGH_SIGNAL_NON_FRIENDS_PER_GROUP = 10\nconst MAX_MEMBERS_PER_GROUP_FOR_PANORAMA = 80\n\nconst COMMUNITY_COLORS = [\n '#7dd3fc',\n '#f0abfc',\n '#facc15',\n '#34d399',\n '#fb7185',\n '#a78bfa',\n '#2dd4bf',\n '#f97316',\n '#60a5fa',\n '#e879f9',\n]\n\nexport interface PeopleRelationshipsWorkerStats {\n durationMs: number\n totalSessions: number\n processedSessions: number\n skippedFailedSessions: number\n}\n\nexport interface PeopleRelationshipsComputeLimits {\n coreNodeLimit?: number\n coreEdgeLimit?: number\n perNodeEdgeLimit?: number\n neighborhoodNodeLimit?: number\n neighborhoodEdgeLimit?: number\n searchResultLimit?: number\n}\n\nexport interface PeopleRelationshipsSnapshot {\n nodes: PeopleRelationshipGraphNode[]\n edges: PeopleRelationshipGraphEdge[]\n communities: PeopleRelationshipCommunity[]\n graph: PeopleRelationshipsGraphData\n diagnostics: PeopleRelationshipsDiagnostics\n algorithmVersion: string\n signature: string\n timeRange: ContactsTimeRangeState\n computedAt: number\n workerStats: PeopleRelationshipsWorkerStats\n limits: Required<PeopleRelationshipsComputeLimits>\n}\n\nexport interface PeopleRelationshipsComputeProgress {\n processedSessions: number\n totalSessions: number\n currentSessionId?: string\n}\n\nexport interface ComputePeopleRelationshipsSnapshotOptions {\n adapter: SessionRuntimeAdapter\n signature: string\n timeRangePreset?: ContactsTimeRangePreset\n factsCacheDir?: string\n limits?: PeopleRelationshipsComputeLimits\n now?: () => number\n onProgress?: (progress: PeopleRelationshipsComputeProgress) => void\n}\n\ninterface NodeAccumulator {\n key: string\n kind: 'contact' | 'owner'\n platform: ChatPlatform\n platformId: string\n sessionScoped: boolean\n sessionId?: string\n displayName: string\n aliases: Set<string>\n avatar: string | null\n isFriend: boolean\n friendSource?: 'private'\n privateMessageCount: number\n activePrivateMonths: Set<string>\n groupMessageCount: number\n commonGroupSessionIds: Set<string>\n ownerCoOccurrenceCount: number\n ownerCoOccurrenceRawScore: number\n ownerReplyInteractionCount: number\n ownerRepliesFromOwnerToContact: number\n ownerRepliesFromContactToOwner: number\n communityWeights: Map<string, number>\n edgeWeight: number\n panoramaCandidate: boolean\n lastInteractionTs: number | null\n}\n\ninterface EdgeAccumulator {\n sourceKey: string\n targetKey: string\n coOccurrenceCount: number\n coOccurrenceRawScore: number\n replyInteractionCount: number\n repliesFromSourceToTarget: number\n repliesFromTargetToSource: number\n sourceSessionIds: Set<string>\n panoramaEligible: boolean\n lastInteractionTs: number | null\n}\n\ninterface GroupPanoramaContribution {\n sessionId: string\n memberKeys: Set<string>\n memberMessageCounts: Map<string, number>\n ownerConnectedKeys: Set<string>\n ownerEdgeScores: Map<string, number>\n relationshipEdgeIds: Set<string>\n relationshipEdgeEndpoints: Map<string, [string, string]>\n relationshipEdgeScores: Map<string, number>\n friendConnectedScores: Map<string, number>\n ownerMessageCount: number\n}\n\ninterface BuildGraphResult {\n nodes: PeopleRelationshipGraphNode[]\n edges: PeopleRelationshipGraphEdge[]\n communities: PeopleRelationshipCommunity[]\n graph: PeopleRelationshipsGraphData\n diagnostics: PeopleRelationshipsDiagnostics\n}\n\ninterface PeopleRelationshipsFactsCacheContext {\n dir: string\n latestKey: string\n stats: PeopleRelationshipsFactsCacheStats\n}\n\nexport function computePeopleRelationshipsSnapshot(\n options: ComputePeopleRelationshipsSnapshotOptions\n): PeopleRelationshipsSnapshot {\n const startedAt = options.now?.() ?? Date.now()\n const sessionIds = options.adapter.listSessionIds()\n const limits = normalizeLimits(options.limits)\n const factsCache = options.factsCacheDir ? createFactsCacheContext(options.factsCacheDir) : null\n const timeRange = resolvePeopleRelationshipsTimeRange(\n options.timeRangePreset,\n findGlobalLatestMessageTs(options.adapter, sessionIds, factsCache)\n )\n const result = computePeopleRelationships({\n adapter: options.adapter,\n sessionIds,\n timeRange,\n factsCache,\n limits,\n onProgress: options.onProgress,\n })\n const finishedAt = options.now?.() ?? Date.now()\n if (factsCache) {\n appLogger.info('people-relationships', 'people relationships session facts cache summary', factsCache.stats)\n }\n appLogger.info('people-relationships', 'people relationships panorama filter summary', {\n includedGroupSessions: result.diagnostics.panoramaIncludedGroupSessions,\n excludedLowValueGroupSessions: result.diagnostics.panoramaExcludedLowValueGroupSessions,\n includedGroupMembers: result.diagnostics.panoramaIncludedGroupMembers,\n excludedGroupMembers: result.diagnostics.panoramaExcludedGroupMembers,\n candidateNodes: result.diagnostics.panoramaCandidateNodes,\n reasons: result.diagnostics.panoramaGroupInclusionReasons,\n })\n return {\n ...result,\n algorithmVersion: PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION,\n signature: options.signature,\n timeRange,\n computedAt: finishedAt,\n limits,\n workerStats: {\n durationMs: Math.max(0, finishedAt - startedAt),\n totalSessions: sessionIds.length,\n processedSessions: sessionIds.length,\n skippedFailedSessions: result.diagnostics.skippedFailedSessions,\n },\n }\n}\n\nexport function buildPeopleRelationshipsNeighborhoodGraph(\n snapshot: PeopleRelationshipsSnapshot,\n contactKey: string,\n limits: PeopleRelationshipsComputeLimits = {}\n): PeopleRelationshipsGraphData {\n const normalizedLimits = normalizeLimits({ ...snapshot.limits, ...limits })\n const center = snapshot.nodes.find((node) => node.key === contactKey)\n if (!center) return { nodes: [], edges: [], communities: [] }\n\n const relatedEdges = sortEdgesForDisplay(\n snapshot.edges.filter((edge) => edge.sourceKey === contactKey || edge.targetKey === contactKey)\n )\n const { directEdges, nodeKeys } = selectNeighborhoodDirectEdges(relatedEdges, contactKey, normalizedLimits)\n\n const directEdgeIds = new Set(relatedEdges.map((edge) => edge.id))\n const secondaryEdgeLimit = Math.max(0, normalizedLimits.neighborhoodEdgeLimit - directEdges.length)\n const secondaryEdges = sortEdgesForDisplay(\n snapshot.edges.filter(\n (edge) => !directEdgeIds.has(edge.id) && nodeKeys.has(edge.sourceKey) && nodeKeys.has(edge.targetKey)\n )\n ).slice(0, secondaryEdgeLimit)\n const edges = sortEdgesForDisplay([...directEdges, ...secondaryEdges])\n const nodes = layoutNeighborhoodNodes(\n snapshot.nodes.filter((node) => nodeKeys.has(node.key)),\n directEdges,\n contactKey\n ).sort(compareNodes)\n return {\n nodes,\n edges,\n communities: filterNeighborhoodCommunities(snapshot.communities, directEdges),\n }\n}\n\nfunction selectNeighborhoodDirectEdges(\n relatedEdges: PeopleRelationshipGraphEdge[],\n contactKey: string,\n limits: Required<PeopleRelationshipsComputeLimits>\n): { directEdges: PeopleRelationshipGraphEdge[]; nodeKeys: Set<string> } {\n // 邻域图先按直接关系排序选择节点,避免高连接节点绕过节点/边上限。\n const nodeKeys = new Set<string>([contactKey])\n const directEdges: PeopleRelationshipGraphEdge[] = []\n\n for (const edge of relatedEdges) {\n if (directEdges.length >= limits.neighborhoodEdgeLimit) break\n const neighborKey = getNeighborhoodNeighborKey(edge, contactKey)\n if (!neighborKey) continue\n if (!nodeKeys.has(neighborKey)) {\n if (nodeKeys.size >= limits.neighborhoodNodeLimit) continue\n nodeKeys.add(neighborKey)\n }\n directEdges.push(edge)\n }\n\n return { directEdges, nodeKeys }\n}\n\nfunction getNeighborhoodNeighborKey(edge: PeopleRelationshipGraphEdge, contactKey: string): string | null {\n if (edge.sourceKey === contactKey) return edge.targetKey\n if (edge.targetKey === contactKey) return edge.sourceKey\n return null\n}\n\nfunction layoutNeighborhoodNodes(\n nodes: PeopleRelationshipGraphNode[],\n relatedEdges: PeopleRelationshipGraphEdge[],\n contactKey: string\n): PeopleRelationshipGraphNode[] {\n const center = nodes.find((node) => node.key === contactKey)\n if (!center) return nodes.map((node) => ({ ...node }))\n\n const directEdgeByNodeKey = new Map<string, PeopleRelationshipGraphEdge>()\n for (const edge of relatedEdges) {\n const neighborKey =\n edge.sourceKey === contactKey ? edge.targetKey : edge.targetKey === contactKey ? edge.sourceKey : null\n if (neighborKey) directEdgeByNodeKey.set(neighborKey, edge)\n }\n const maxDirectWeight = Math.max(...[...directEdgeByNodeKey.values()].map((edge) => edge.weight), 1)\n const communityGroups = new Map<string, PeopleRelationshipGraphNode[]>()\n for (const node of nodes) {\n if (node.key === contactKey) continue\n const group = communityGroups.get(node.communityId) ?? []\n group.push(node)\n communityGroups.set(node.communityId, group)\n }\n\n const sortedCommunityGroups = [...communityGroups.entries()].sort((a, b) => {\n if (a[0] === center.communityId) return -1\n if (b[0] === center.communityId) return 1\n const weightA = sumNeighborhoodCommunityWeight(a[1], directEdgeByNodeKey)\n const weightB = sumNeighborhoodCommunityWeight(b[1], directEdgeByNodeKey)\n return weightB - weightA || a[0].localeCompare(b[0])\n })\n\n const localNodes: PeopleRelationshipGraphNode[] = [{ ...center, x: 0, y: 0 }]\n for (const [communityIndex, [communityId, communityNodes]] of sortedCommunityGroups.entries()) {\n const baseAngle = neighborhoodCommunityAngle(communityIndex, communityId, center.communityId)\n communityNodes.sort((a, b) => {\n const edgeA = directEdgeByNodeKey.get(a.key)?.weight ?? 0\n const edgeB = directEdgeByNodeKey.get(b.key)?.weight ?? 0\n return edgeB - edgeA || compareNodes(a, b)\n })\n\n for (const [index, node] of communityNodes.entries()) {\n const angle = neighborhoodNodeAngle(baseAngle, communityId, node.key, index, communityNodes.length)\n const radius = neighborhoodNodeRadius(\n node,\n center,\n directEdgeByNodeKey.get(node.key),\n maxDirectWeight,\n communityNodes.length\n )\n localNodes.push({\n ...node,\n x: roundNum(Math.cos(angle) * radius, 2),\n y: roundNum(Math.sin(angle) * radius, 2),\n })\n }\n }\n return localNodes\n}\n\nfunction sumNeighborhoodCommunityWeight(\n nodes: PeopleRelationshipGraphNode[],\n directEdgeByNodeKey: Map<string, PeopleRelationshipGraphEdge>\n): number {\n return nodes.reduce((sum, node) => sum + (directEdgeByNodeKey.get(node.key)?.weight ?? 0), 0)\n}\n\nfunction neighborhoodCommunityAngle(index: number, communityId: string, centerCommunityId: string): number {\n if (communityId === centerCommunityId) return -Math.PI / 2\n return index * 2.399963229728653\n}\n\nfunction neighborhoodNodeAngle(\n baseAngle: number,\n communityId: string,\n nodeKey: string,\n index: number,\n communitySize: number\n): number {\n const seedOffset = ((stableHash(`${communityId}:${nodeKey}:neighborhood-angle`) % 1000) / 1000 - 0.5) * 0.12\n const centeredIndex = index - (communitySize - 1) / 2\n const spacing = communitySize <= 4 ? 0.42 : communitySize <= 10 ? 0.24 : 0.14\n const maxSpread = communitySize <= 4 ? 0.72 : communitySize <= 20 ? 1.08 : 1.32\n return baseAngle + clamp(centeredIndex * spacing + seedOffset, -maxSpread, maxSpread)\n}\n\nfunction neighborhoodNodeRadius(\n node: PeopleRelationshipGraphNode,\n center: PeopleRelationshipGraphNode,\n directEdge: PeopleRelationshipGraphEdge | undefined,\n maxDirectWeight: number,\n communitySize: number\n): number {\n const directStrength = directEdge ? Math.min(1, directEdge.weight / maxDirectWeight) : 0\n const sameCommunityBonus = node.communityId === center.communityId ? 110 : 0\n const smallCommunityBonus = node.communityId === center.communityId && communitySize <= 6 ? 80 : 0\n const friendBonus = node.pool === 'friend' ? 70 : 0\n const scoreBonus = Math.min(90, Math.sqrt(Math.max(0, Math.min(1, node.score))) * 90)\n const rankPenalty = Math.sqrt(Math.max(0, node.rank - center.rank)) * 8\n return roundNum(\n clamp(\n 260 +\n (1 - directStrength) * 560 +\n rankPenalty -\n sameCommunityBonus -\n smallCommunityBonus -\n friendBonus -\n scoreBonus,\n 120,\n 1100\n ),\n 2\n )\n}\n\nfunction computePeopleRelationships(options: {\n adapter: SessionRuntimeAdapter\n sessionIds: string[]\n timeRange: ContactsTimeRangeState\n factsCache: PeopleRelationshipsFactsCacheContext | null\n limits: Required<PeopleRelationshipsComputeLimits>\n onProgress?: (progress: PeopleRelationshipsComputeProgress) => void\n}): BuildGraphResult {\n const diagnostics = createEmptyDiagnostics()\n const nodes = new Map<string, NodeAccumulator>()\n const edges = new Map<string, EdgeAccumulator>()\n const groupContributions: GroupPanoramaContribution[] = []\n const communityLabels = new Map<string, string>([[PRIVATE_COMMUNITY_ID, 'Private contacts']])\n let processedSessions = 0\n\n for (const sessionId of options.sessionIds) {\n options.onProgress?.({ processedSessions, totalSessions: options.sessionIds.length, currentSessionId: sessionId })\n try {\n const facts = getSessionFacts(options.adapter, sessionId, options.timeRange, options.factsCache)\n applySessionFacts(nodes, edges, groupContributions, communityLabels, diagnostics, sessionId, facts)\n } catch (error) {\n diagnostics.skippedFailedSessions++\n appLogger.error('people-relationships', `failed to process people relationship session: ${sessionId}`, error)\n } finally {\n processedSessions++\n options.onProgress?.({ processedSessions, totalSessions: options.sessionIds.length, currentSessionId: sessionId })\n }\n }\n\n applyPanoramaContributions([...nodes.values()], edges, groupContributions, diagnostics)\n return buildGraph(\n [...nodes.values()],\n [...edges.values()],\n communityLabels,\n groupContributions,\n options.limits,\n diagnostics\n )\n}\n\nfunction findGlobalLatestMessageTs(\n adapter: SessionRuntimeAdapter,\n sessionIds: string[],\n factsCache: PeopleRelationshipsFactsCacheContext | null\n): number | null {\n let latest: number | null = null\n for (const sessionId of sessionIds) {\n const dbVersion = getSessionDbVersion(adapter, sessionId)\n const cached = readLatestFacts(sessionId, factsCache, dbVersion)\n if (cached) {\n if (cached.latestMessageTs !== null) latest = Math.max(latest ?? 0, cached.latestMessageTs)\n continue\n }\n try {\n const db = adapter.openReadonly(sessionId)\n const ts = db && isChatSessionDb(db) ? getLatestContactMessageTs(db) : null\n writeLatestFacts(adapter, sessionId, factsCache, { latestMessageTs: ts }, dbVersion)\n if (ts !== null) latest = Math.max(latest ?? 0, ts)\n } catch (error) {\n appLogger.error(\n 'people-relationships',\n `failed to inspect people relationship session range: ${sessionId}`,\n error\n )\n }\n }\n return latest\n}\n\nfunction getSessionFacts(\n adapter: SessionRuntimeAdapter,\n sessionId: string,\n timeRange: ContactsTimeRangeState,\n factsCache: PeopleRelationshipsFactsCacheContext | null\n): PeopleRelationshipsSessionFacts {\n const dbVersion = getSessionDbVersion(adapter, sessionId)\n const cached = readSessionFacts(sessionId, timeRange, factsCache, dbVersion)\n if (cached) return cached\n\n const facts = computeSessionFacts(adapter, sessionId, timeRange)\n writeSessionFacts(adapter, sessionId, timeRange, factsCache, facts, dbVersion)\n return facts\n}\n\nfunction computeSessionFacts(\n adapter: SessionRuntimeAdapter,\n sessionId: string,\n timeRange: ContactsTimeRangeState\n): PeopleRelationshipsSessionFacts {\n const db = adapter.openReadonly(sessionId)\n if (!db || !isChatSessionDb(db)) return { kind: 'not_chat_db', latestMessageTs: null }\n\n const latestMessageTs = getLatestContactMessageTs(db)\n const meta = getSessionMeta(db)\n if (!meta) return { kind: 'missing_meta', latestMessageTs }\n if (meta.type !== ChatType.PRIVATE && meta.type !== ChatType.GROUP)\n return { kind: 'unsupported_type', latestMessageTs }\n\n const cachedMeta = toPeopleRelationshipsSessionMetaFacts(meta)\n if (!meta.ownerId?.trim()) return { kind: 'missing_owner', meta: cachedMeta, latestMessageTs }\n\n const owner = resolveOwnerMember(db)\n if (!owner) return { kind: 'unresolved_owner', meta: cachedMeta, latestMessageTs }\n const cachedMetaWithOwner = toPeopleRelationshipsSessionMetaFacts(meta, owner)\n\n if (meta.type === ChatType.PRIVATE) {\n const facts = getPrivateContactFacts(db, owner.id, { startTs: timeRange.startTs })\n if (facts.type === 'missing') return { kind: 'private_missing', meta: cachedMetaWithOwner, latestMessageTs }\n if (facts.type === 'ambiguous') return { kind: 'private_ambiguous', meta: cachedMetaWithOwner, latestMessageTs }\n return { kind: 'private', meta: cachedMetaWithOwner, latestMessageTs, facts }\n }\n\n return {\n kind: 'group',\n meta: cachedMetaWithOwner,\n latestMessageTs,\n facts: {\n ...getGroupRelationshipGraphFacts(db, owner.id, { startTs: timeRange.startTs }),\n ownerEdges: getGroupContactFacts(db, owner.id, { startTs: timeRange.startTs }),\n },\n }\n}\n\nfunction applySessionFacts(\n nodes: Map<string, NodeAccumulator>,\n edges: Map<string, EdgeAccumulator>,\n groupContributions: GroupPanoramaContribution[],\n communityLabels: Map<string, string>,\n diagnostics: PeopleRelationshipsDiagnostics,\n sessionId: string,\n sessionFacts: PeopleRelationshipsSessionFacts\n): void {\n switch (sessionFacts.kind) {\n case 'missing_owner':\n diagnostics.skippedMissingOwnerSessions++\n return\n case 'unresolved_owner':\n diagnostics.skippedUnresolvedOwnerSessions++\n return\n case 'private_ambiguous':\n diagnostics.skippedAmbiguousPrivateSessions++\n return\n case 'private':\n diagnostics.processedPrivateSessions++\n applyPrivateFacts(nodes, edges, sessionId, sessionFacts.meta, sessionFacts.facts)\n return\n case 'group':\n diagnostics.processedGroupSessions++\n applyGroupFacts(\n nodes,\n edges,\n groupContributions,\n communityLabels,\n sessionId,\n sessionFacts.meta,\n sessionFacts.facts\n )\n return\n default:\n return\n }\n}\n\nfunction applyPrivateFacts(\n nodes: Map<string, NodeAccumulator>,\n edges: Map<string, EdgeAccumulator>,\n sessionId: string,\n meta: PeopleRelationshipsSessionMetaFacts,\n facts: PeopleRelationshipsCachedPrivateFacts\n): void {\n if (facts.privateMessageCount <= 0) return\n const ownerNode = getOrCreateOwnerNode(nodes, meta)\n const node = getOrCreateNode(nodes, sessionId, meta, facts.contact)\n node.isFriend = true\n node.friendSource = 'private'\n node.panoramaCandidate = true\n node.privateMessageCount += facts.privateMessageCount\n for (const month of facts.activeMonths) node.activePrivateMonths.add(month)\n node.communityWeights.set(PRIVATE_COMMUNITY_ID, (node.communityWeights.get(PRIVATE_COMMUNITY_ID) ?? 0) + 1)\n updateLastInteraction(node, facts.lastMessageTs)\n\n if (!ownerNode) return\n ownerNode.isFriend = true\n ownerNode.panoramaCandidate = true\n ownerNode.privateMessageCount += facts.privateMessageCount\n for (const month of facts.activeMonths) ownerNode.activePrivateMonths.add(month)\n ownerNode.communityWeights.set(PRIVATE_COMMUNITY_ID, (ownerNode.communityWeights.get(PRIVATE_COMMUNITY_ID) ?? 0) + 1)\n updateLastInteraction(ownerNode, facts.lastMessageTs)\n applyOwnerContactEdge(edges, ownerNode, node, {\n coOccurrenceCount: facts.privateMessageCount,\n coOccurrenceRawScore: facts.privateMessageCount * 1.8,\n replyInteractionCount: 0,\n repliesFromOwnerToContact: 0,\n repliesFromContactToOwner: 0,\n lastInteractionTs: facts.lastMessageTs,\n sessionId,\n panoramaEligible: true,\n })\n}\n\nfunction applyGroupFacts(\n nodes: Map<string, NodeAccumulator>,\n edges: Map<string, EdgeAccumulator>,\n groupContributions: GroupPanoramaContribution[],\n communityLabels: Map<string, string>,\n sessionId: string,\n meta: PeopleRelationshipsSessionMetaFacts,\n facts: PeopleRelationshipsCachedGroupFacts\n): void {\n const communityId = `group:${sessionId}`\n communityLabels.set(communityId, meta.name)\n const ownerNode = getOrCreateOwnerNode(nodes, meta)\n const contribution: GroupPanoramaContribution = {\n sessionId,\n memberKeys: new Set(),\n memberMessageCounts: new Map(),\n ownerConnectedKeys: new Set(),\n ownerEdgeScores: new Map(),\n relationshipEdgeIds: new Set(),\n relationshipEdgeEndpoints: new Map(),\n relationshipEdgeScores: new Map(),\n friendConnectedScores: new Map(),\n ownerMessageCount: facts.ownerMessageCount,\n }\n for (const member of facts.members) {\n const node = getOrCreateNode(nodes, sessionId, meta, member.contact)\n contribution.memberKeys.add(node.key)\n contribution.memberMessageCounts.set(node.key, member.messageCount)\n node.groupMessageCount += member.messageCount\n node.commonGroupSessionIds.add(sessionId)\n node.communityWeights.set(\n communityId,\n (node.communityWeights.get(communityId) ?? 0) + Math.max(1, member.messageCount)\n )\n updateLastInteraction(node, member.lastMessageTs)\n }\n\n if (ownerNode) {\n ownerNode.groupMessageCount += facts.ownerMessageCount\n for (const fact of facts.ownerEdges) {\n if (fact.coOccurrenceCount <= 0 && fact.replyInteractionCount <= 0) continue\n const contactNode = getOrCreateNode(nodes, sessionId, meta, fact.contact)\n const ownerEdgeScore = computeRawEdgeWeight({\n coOccurrenceCount: fact.coOccurrenceCount,\n coOccurrenceRawScore: fact.coOccurrenceRawScore,\n replyInteractionCount: fact.replyInteractionCount,\n })\n contribution.memberKeys.add(contactNode.key)\n contribution.ownerConnectedKeys.add(contactNode.key)\n contribution.ownerEdgeScores.set(\n contactNode.key,\n (contribution.ownerEdgeScores.get(contactNode.key) ?? 0) + ownerEdgeScore\n )\n ownerNode.commonGroupSessionIds.add(sessionId)\n ownerNode.communityWeights.set(communityId, (ownerNode.communityWeights.get(communityId) ?? 0) + 1)\n updateLastInteraction(ownerNode, fact.lastInteractionTs)\n applyOwnerContactEdge(edges, ownerNode, contactNode, {\n coOccurrenceCount: fact.coOccurrenceCount,\n coOccurrenceRawScore: fact.coOccurrenceRawScore,\n replyInteractionCount: fact.replyInteractionCount,\n repliesFromOwnerToContact: fact.repliesFromOwnerToContact,\n repliesFromContactToOwner: fact.repliesFromContactToOwner,\n lastInteractionTs: fact.lastInteractionTs,\n sessionId,\n })\n }\n }\n\n for (const fact of facts.edges) {\n const sourceNode = getOrCreateNode(nodes, sessionId, meta, fact.source)\n const targetNode = getOrCreateNode(nodes, sessionId, meta, fact.target)\n const sourceKey = sourceNode.key < targetNode.key ? sourceNode.key : targetNode.key\n const targetKey = sourceNode.key < targetNode.key ? targetNode.key : sourceNode.key\n const edge = getOrCreateEdge(edges, sourceKey, targetKey)\n const currentEdgeId = edgeId(sourceKey, targetKey)\n const relationshipEdgeScore = computeRawEdgeWeight(fact)\n contribution.memberKeys.add(sourceNode.key)\n contribution.memberKeys.add(targetNode.key)\n contribution.relationshipEdgeIds.add(currentEdgeId)\n contribution.relationshipEdgeEndpoints.set(currentEdgeId, [sourceKey, targetKey])\n contribution.relationshipEdgeScores.set(\n currentEdgeId,\n (contribution.relationshipEdgeScores.get(currentEdgeId) ?? 0) + relationshipEdgeScore\n )\n edge.coOccurrenceCount += fact.coOccurrenceCount\n edge.coOccurrenceRawScore += fact.coOccurrenceRawScore\n edge.replyInteractionCount += fact.replyInteractionCount\n if (sourceNode.key === sourceKey) {\n edge.repliesFromSourceToTarget += fact.repliesFromSourceToTarget\n edge.repliesFromTargetToSource += fact.repliesFromTargetToSource\n } else {\n edge.repliesFromSourceToTarget += fact.repliesFromTargetToSource\n edge.repliesFromTargetToSource += fact.repliesFromSourceToTarget\n }\n edge.sourceSessionIds.add(sessionId)\n edge.lastInteractionTs = maxNullableTs(edge.lastInteractionTs, fact.lastInteractionTs)\n sourceNode.commonGroupSessionIds.add(sessionId)\n targetNode.commonGroupSessionIds.add(sessionId)\n sourceNode.communityWeights.set(communityId, (sourceNode.communityWeights.get(communityId) ?? 0) + 1)\n targetNode.communityWeights.set(communityId, (targetNode.communityWeights.get(communityId) ?? 0) + 1)\n updateLastInteraction(sourceNode, fact.lastInteractionTs)\n updateLastInteraction(targetNode, fact.lastInteractionTs)\n }\n groupContributions.push(contribution)\n}\n\nfunction buildGraph(\n nodeAccumulators: NodeAccumulator[],\n edgeAccumulators: EdgeAccumulator[],\n communityLabels: Map<string, string>,\n groupContributions: GroupPanoramaContribution[],\n limits: Required<PeopleRelationshipsComputeLimits>,\n baseDiagnostics: PeopleRelationshipsDiagnostics\n): BuildGraphResult {\n const edgeWeights = new Map<string, number>()\n for (const edge of edgeAccumulators) {\n const weight = computeEdgeWeight(edge)\n edgeWeights.set(edgeId(edge.sourceKey, edge.targetKey), weight)\n }\n\n for (const edge of edgeAccumulators) {\n const weight = edgeWeights.get(edgeId(edge.sourceKey, edge.targetKey)) ?? 0\n const source = nodeAccumulators.find((node) => node.key === edge.sourceKey)\n const target = nodeAccumulators.find((node) => node.key === edge.targetKey)\n if (source) source.edgeWeight += weight\n if (target) target.edgeWeight += weight\n }\n\n const nodeScores = computeContactPriorityScores(nodeAccumulators)\n const rankedNodes = nodeAccumulators\n .map((node) => ({\n node,\n score: nodeScores.get(node) ?? 0,\n relationshipActivityScore: computeRelationshipActivityScore(node),\n }))\n .sort(compareRankedNodes)\n const panoramaCandidateKeys = new Set(\n rankedNodes.filter((item) => item.node.panoramaCandidate).map((item) => item.node.key)\n )\n const panoramaEligibleEdgeIds = new Set(\n edgeAccumulators.filter((edge) => edge.panoramaEligible).map((edge) => edgeId(edge.sourceKey, edge.targetKey))\n )\n const maxScore = Math.max(...rankedNodes.map((item) => item.score), 1)\n const nodeByKey = new Map<string, PeopleRelationshipGraphNode>()\n\n rankedNodes.forEach((item, index) => {\n const communityId = pickCommunityId(item.node)\n const color = colorForCommunity(communityId)\n nodeByKey.set(item.node.key, {\n key: item.node.key,\n kind: item.node.kind,\n platform: item.node.platform,\n platformId: item.node.platformId,\n sessionScoped: item.node.sessionScoped,\n sessionId: item.node.sessionId,\n displayName: item.node.displayName,\n aliases: [...item.node.aliases].filter((alias) => alias !== item.node.displayName),\n avatar: item.node.avatar,\n pool: item.node.isFriend ? 'friend' : 'non_friend',\n friendSource: item.node.friendSource,\n score: roundNum(item.score),\n rank: index + 1,\n communityId,\n x: 0,\n y: 0,\n size: roundNum(4 + Math.sqrt(item.score / maxScore) * 18, 2),\n color,\n labelVisibility: item.node.kind === 'owner' || index < 30 ? 2 : index < 160 ? 1 : 0,\n lastInteractionTs: item.node.lastInteractionTs,\n privateMessageCount: item.node.privateMessageCount,\n groupMessageCount: item.node.groupMessageCount,\n commonGroupCount: item.node.commonGroupSessionIds.size,\n searchText: [\n item.node.displayName,\n item.node.platformId,\n ...item.node.aliases,\n ...(item.node.kind === 'owner' ? ['我', 'me', 'myself', 'owner'] : []),\n ]\n .join(' ')\n .toLowerCase(),\n })\n })\n\n const allNodes = layoutNodes([...nodeByKey.values()], communityLabels)\n const allEdges = edgeAccumulators\n .map((edge) => toGraphEdge(edge, edgeWeights.get(edgeId(edge.sourceKey, edge.targetKey)) ?? 0))\n .filter((edge) => nodeByKey.has(edge.sourceKey) && nodeByKey.has(edge.targetKey))\n .sort(compareEdges)\n const communities = buildCommunities(allNodes, communityLabels, groupContributions)\n const coreNodeKeys = new Set(\n allNodes\n .filter((node) => panoramaCandidateKeys.has(node.key))\n .slice(0, limits.coreNodeLimit)\n .map((node) => node.key)\n )\n const coreEdges = cropEdges(\n allEdges.filter(\n (edge) =>\n coreNodeKeys.has(edge.sourceKey) && coreNodeKeys.has(edge.targetKey) && panoramaEligibleEdgeIds.has(edge.id)\n ),\n limits\n )\n const graphNodes = allNodes.filter((node) => coreNodeKeys.has(node.key))\n const graph: PeopleRelationshipsGraphData = {\n nodes: graphNodes,\n edges: coreEdges,\n communities: filterCommunities(communities, graphNodes),\n }\n const diagnostics: PeopleRelationshipsDiagnostics = {\n ...baseDiagnostics,\n totalNodes: allNodes.length,\n totalEdges: allEdges.length,\n panoramaCandidateNodes: panoramaCandidateKeys.size,\n coreNodeCount: graph.nodes.length,\n coreEdgeCount: graph.edges.length,\n }\n return { nodes: allNodes, edges: allEdges, communities, graph, diagnostics }\n}\n\nfunction cropEdges(\n edges: PeopleRelationshipGraphEdge[],\n limits: Required<PeopleRelationshipsComputeLimits>\n): PeopleRelationshipGraphEdge[] {\n const counts = new Map<string, number>()\n const kept: PeopleRelationshipGraphEdge[] = []\n for (const edge of sortEdgesForDisplay(edges)) {\n if (kept.length >= limits.coreEdgeLimit) break\n const sourceCount = counts.get(edge.sourceKey) ?? 0\n const targetCount = counts.get(edge.targetKey) ?? 0\n if (sourceCount >= limits.perNodeEdgeLimit || targetCount >= limits.perNodeEdgeLimit) continue\n kept.push(edge)\n counts.set(edge.sourceKey, sourceCount + 1)\n counts.set(edge.targetKey, targetCount + 1)\n }\n return kept\n}\n\nfunction layoutNodes(\n nodes: PeopleRelationshipGraphNode[],\n communityLabels: Map<string, string>\n): PeopleRelationshipGraphNode[] {\n const byCommunity = new Map<string, PeopleRelationshipGraphNode[]>()\n for (const node of nodes) {\n const group = byCommunity.get(node.communityId) ?? []\n group.push(node)\n byCommunity.set(node.communityId, group)\n }\n\n const sortedCommunities = [...byCommunity.entries()].sort((a, b) => {\n if (a[0] === PRIVATE_COMMUNITY_ID) return -1\n if (b[0] === PRIVATE_COMMUNITY_ID) return 1\n const scoreA = a[1].reduce((sum, node) => sum + node.score, 0)\n const scoreB = b[1].reduce((sum, node) => sum + node.score, 0)\n return scoreB - scoreA || (communityLabels.get(a[0]) ?? a[0]).localeCompare(communityLabels.get(b[0]) ?? b[0])\n })\n\n for (const [communityIndex, [communityId, communityNodes]] of sortedCommunities.entries()) {\n const baseAngle = communityAngle(communityIndex, communityId)\n communityNodes.sort(compareNodes)\n for (const [index, node] of communityNodes.entries()) {\n if (node.kind === 'owner') {\n node.x = 0\n node.y = 0\n continue\n }\n\n const angle = egoNodeAngle(baseAngle, communityId, node.key, index, communityNodes.length)\n const radius = egoNodeRadius(node, communityId, communityNodes.length)\n node.x = roundNum(Math.cos(angle) * radius, 2)\n node.y = roundNum(Math.sin(angle) * radius, 2)\n }\n }\n return nodes.sort(compareNodes)\n}\n\nfunction communityAngle(index: number, communityId: string): number {\n if (communityId === PRIVATE_COMMUNITY_ID) return -Math.PI / 2\n return index * 2.399963229728653\n}\n\nfunction egoNodeAngle(\n baseAngle: number,\n communityId: string,\n nodeKey: string,\n index: number,\n communitySize: number\n): number {\n const seedOffset = ((stableHash(`${communityId}:${nodeKey}:angle`) % 1000) / 1000 - 0.5) * 0.16\n const centeredIndex = index - (communitySize - 1) / 2\n const spacing = communitySize <= 4 ? 0.38 : communitySize <= 12 ? 0.24 : 0.12\n const maxSpread = communitySize <= 4 ? 0.75 : communitySize <= 20 ? 1.1 : 1.35\n return baseAngle + clamp(centeredIndex * spacing + seedOffset, -maxSpread, maxSpread)\n}\n\nfunction egoNodeRadius(node: PeopleRelationshipGraphNode, communityId: string, communitySize: number): number {\n const rankPenalty = Math.sqrt(Math.max(0, node.rank - 1)) * 26\n const scoreBonus = Math.min(260, Math.sqrt(Math.max(0, node.score)) * 22)\n const privateBonus = node.privateMessageCount > 0 ? Math.min(220, Math.log1p(node.privateMessageCount) * 48) : 0\n const friendBonus = node.pool === 'friend' ? 280 : 0\n const commonGroupBonus = Math.min(180, node.commonGroupCount * 18)\n // 大群更可能是同事群、兴趣群或通知群;这里只把它作为布局噪声惩罚,不改变关系评分。\n const groupSizePenalty = communityId.startsWith('group:')\n ? Math.min(1400, Math.max(0, communitySize - 6) * 22 + Math.sqrt(communitySize) * 24)\n : 0\n const baseRadius = node.pool === 'friend' ? 430 : 760\n const minRadius = node.pool === 'friend' ? 160 : 340\n return roundNum(\n clamp(\n baseRadius + rankPenalty + groupSizePenalty - scoreBonus - privateBonus - friendBonus - commonGroupBonus,\n minRadius,\n 2600\n ),\n 2\n )\n}\n\nfunction buildCommunities(\n nodes: PeopleRelationshipGraphNode[],\n communityLabels: Map<string, string>,\n groupContributions: GroupPanoramaContribution[]\n): PeopleRelationshipCommunity[] {\n const groups = new Map<string, PeopleRelationshipGraphNode[]>()\n for (const node of nodes) {\n const group = groups.get(node.communityId) ?? []\n group.push(node)\n groups.set(node.communityId, group)\n }\n const groupMemberCounts = new Map(groupContributions.map((item) => [`group:${item.sessionId}`, item.memberKeys.size]))\n const communitiesById = new Map<string, PeopleRelationshipCommunity>()\n\n for (const [id, group] of groups) {\n const x = group.reduce((sum, node) => sum + node.x, 0) / group.length\n const y = group.reduce((sum, node) => sum + node.y, 0) / group.length\n communitiesById.set(id, {\n id,\n label: communityLabels.get(id) ?? id,\n size: groupMemberCounts.get(id) ?? group.length,\n x: roundNum(x, 2),\n y: roundNum(y, 2),\n color: colorForCommunity(id),\n })\n }\n\n for (const [id, label] of communityLabels) {\n if (communitiesById.has(id) || !id.startsWith('group:')) continue\n communitiesById.set(id, {\n id,\n label,\n size: groupMemberCounts.get(id) ?? 0,\n x: 0,\n y: 0,\n color: colorForCommunity(id),\n })\n }\n\n return [...communitiesById.values()].sort((a, b) => b.size - a.size || a.label.localeCompare(b.label))\n}\n\nfunction filterNeighborhoodCommunities(\n communities: PeopleRelationshipCommunity[],\n relatedEdges: PeopleRelationshipGraphEdge[]\n): PeopleRelationshipCommunity[] {\n const communityById = new Map(communities.map((community) => [community.id, community]))\n const sourceCommunityIds = new Set<string>()\n for (const edge of relatedEdges) {\n for (const sessionId of edge.sourceSessionIds) sourceCommunityIds.add(`group:${sessionId}`)\n }\n return [...sourceCommunityIds]\n .map((id) => communityById.get(id))\n .filter((community): community is PeopleRelationshipCommunity => Boolean(community))\n .sort((a, b) => b.size - a.size || a.label.localeCompare(b.label))\n}\n\nfunction filterCommunities(\n communities: PeopleRelationshipCommunity[],\n nodes: PeopleRelationshipGraphNode[]\n): PeopleRelationshipCommunity[] {\n const ids = new Set(nodes.map((node) => node.communityId))\n return communities.filter((community) => ids.has(community.id))\n}\n\nfunction applyPanoramaContributions(\n nodes: NodeAccumulator[],\n edges: Map<string, EdgeAccumulator>,\n groupContributions: GroupPanoramaContribution[],\n diagnostics: PeopleRelationshipsDiagnostics\n): void {\n const nodeByKey = new Map(nodes.map((node) => [node.key, node]))\n for (const contribution of groupContributions) {\n const decision = evaluateGroupPanoramaContribution(contribution, nodeByKey)\n if (!decision.included) {\n diagnostics.panoramaExcludedLowValueGroupSessions++\n diagnostics.panoramaExcludedGroupMembers += contribution.memberKeys.size\n continue\n }\n\n diagnostics.panoramaIncludedGroupSessions++\n incrementPanoramaReason(diagnostics, decision.reason)\n\n for (const key of decision.selectedMemberKeys) {\n const node = nodeByKey.get(key)\n if (node) node.panoramaCandidate = true\n }\n for (const edgeId of contribution.relationshipEdgeIds) {\n const endpoints = contribution.relationshipEdgeEndpoints.get(edgeId)\n if (!endpoints) continue\n if (!decision.selectedMemberKeys.has(endpoints[0]) || !decision.selectedMemberKeys.has(endpoints[1])) continue\n const edge = edges.get(edgeId)\n if (edge) edge.panoramaEligible = true\n }\n for (const key of contribution.ownerConnectedKeys) {\n if (!decision.selectedMemberKeys.has(key)) continue\n const ownerKey = buildOwnerKeyForContribution(nodeByKey, key)\n if (!ownerKey) continue\n const ownerEdgeId = sortedEdgeId(ownerKey, key)\n const edge = edges.get(ownerEdgeId)\n if (edge) edge.panoramaEligible = true\n }\n\n diagnostics.panoramaIncludedGroupMembers += decision.selectedMemberKeys.size\n diagnostics.panoramaExcludedGroupMembers += Math.max(\n 0,\n contribution.memberKeys.size - decision.selectedMemberKeys.size\n )\n }\n}\n\nfunction evaluateGroupPanoramaContribution(\n contribution: GroupPanoramaContribution,\n nodeByKey: Map<string, NodeAccumulator>\n): { included: boolean; reason: string; selectedMemberKeys: Set<string> } {\n const friendKeys = [...contribution.memberKeys].filter((key) => nodeByKey.get(key)?.isFriend === true)\n const memberCount = contribution.memberKeys.size\n const friendCount = friendKeys.length\n const friendRatio = memberCount > 0 ? friendCount / memberCount : 0\n const ownerConnectedCount = contribution.ownerConnectedKeys.size\n const totalGroupMessages =\n contribution.ownerMessageCount +\n [...contribution.memberMessageCounts.values()].reduce((sum, count) => sum + count, 0)\n const ownerMessageRatio = totalGroupMessages > 0 ? contribution.ownerMessageCount / totalGroupMessages : 0\n const friendConnectedScores = computeFriendConnectedScores(contribution, new Set(friendKeys))\n contribution.friendConnectedScores.clear()\n for (const [key, score] of friendConnectedScores) contribution.friendConnectedScores.set(key, score)\n\n let reason: string | null = null\n if (friendCount === 0) {\n reason = null\n } else if (friendCount >= MIN_GROUP_FRIENDS_FOR_PANORAMA) {\n reason = 'friend_count'\n } else if (friendCount >= 2 && friendRatio >= MIN_GROUP_FRIEND_RATIO_FOR_PANORAMA) {\n reason = 'friend_ratio'\n } else if (ownerConnectedCount >= MIN_OWNER_CONNECTED_MEMBERS_FOR_PANORAMA) {\n reason = 'owner_connected'\n } else if (\n contribution.ownerMessageCount >= MIN_OWNER_GROUP_MESSAGES_FOR_PANORAMA ||\n (contribution.ownerMessageCount >= MIN_OWNER_GROUP_MESSAGES_FOR_RATIO &&\n ownerMessageRatio >= MIN_OWNER_GROUP_MESSAGE_RATIO_FOR_PANORAMA)\n ) {\n reason = 'owner_activity'\n } else if (memberCount <= SMALL_GROUP_MEMBER_LIMIT_FOR_FRIEND_EDGE && friendConnectedScores.size > 0) {\n reason = 'friend_connected'\n }\n\n if (!reason) return { included: false, reason: 'low_value', selectedMemberKeys: new Set() }\n return {\n included: true,\n reason,\n selectedMemberKeys: selectPanoramaMembers(contribution, nodeByKey, new Set(friendKeys)),\n }\n}\n\nfunction computeFriendConnectedScores(\n contribution: GroupPanoramaContribution,\n friendKeys: Set<string>\n): Map<string, number> {\n const scores = new Map<string, number>()\n for (const [edgeId, endpoints] of contribution.relationshipEdgeEndpoints) {\n const score = contribution.relationshipEdgeScores.get(edgeId) ?? 0\n const [sourceKey, targetKey] = endpoints\n if (friendKeys.has(sourceKey) && !friendKeys.has(targetKey)) {\n scores.set(targetKey, (scores.get(targetKey) ?? 0) + score)\n } else if (friendKeys.has(targetKey) && !friendKeys.has(sourceKey)) {\n scores.set(sourceKey, (scores.get(sourceKey) ?? 0) + score)\n }\n }\n return scores\n}\n\nfunction selectPanoramaMembers(\n contribution: GroupPanoramaContribution,\n nodeByKey: Map<string, NodeAccumulator>,\n friendKeys: Set<string>\n): Set<string> {\n const selected = new Set(friendKeys)\n const remainingLimit = () => Math.max(0, MAX_MEMBERS_PER_GROUP_FOR_PANORAMA - selected.size)\n\n addTopScoredKeys(selected, contribution.ownerEdgeScores, MAX_OWNER_CONNECTED_NON_FRIENDS_PER_GROUP, remainingLimit())\n addTopScoredKeys(\n selected,\n contribution.friendConnectedScores,\n MAX_FRIEND_CONNECTED_NON_FRIENDS_PER_GROUP,\n remainingLimit()\n )\n addTopScoredKeys(\n selected,\n computeHighSignalNonFriendScores(contribution, nodeByKey, friendKeys),\n MAX_HIGH_SIGNAL_NON_FRIENDS_PER_GROUP,\n remainingLimit()\n )\n return selected\n}\n\nfunction computeHighSignalNonFriendScores(\n contribution: GroupPanoramaContribution,\n nodeByKey: Map<string, NodeAccumulator>,\n friendKeys: Set<string>\n): Map<string, number> {\n const scores = new Map<string, number>()\n for (const key of contribution.memberKeys) {\n const node = nodeByKey.get(key)\n if (!node || node.kind === 'owner' || friendKeys.has(key)) continue\n const messageScore = Math.log1p(contribution.memberMessageCounts.get(key) ?? 0)\n const ownerScore = contribution.ownerEdgeScores.get(key) ?? 0\n const friendScore = contribution.friendConnectedScores.get(key) ?? 0\n const relationshipScore = sumRelationshipScoresForKey(contribution, key)\n const score = ownerScore * 2 + friendScore * 1.5 + relationshipScore + messageScore\n if (score > 0) scores.set(key, score)\n }\n return scores\n}\n\nfunction sumRelationshipScoresForKey(contribution: GroupPanoramaContribution, key: string): number {\n let total = 0\n for (const [edgeId, endpoints] of contribution.relationshipEdgeEndpoints) {\n if (endpoints[0] === key || endpoints[1] === key) total += contribution.relationshipEdgeScores.get(edgeId) ?? 0\n }\n return total\n}\n\nfunction addTopScoredKeys(\n selected: Set<string>,\n scores: Map<string, number>,\n limit: number,\n remainingLimit: number\n): void {\n if (limit <= 0 || remainingLimit <= 0) return\n const items = [...scores.entries()]\n .filter(([key, score]) => !selected.has(key) && score > 0)\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n for (const [key] of items.slice(0, Math.min(limit, remainingLimit))) {\n selected.add(key)\n }\n}\n\nfunction incrementPanoramaReason(diagnostics: PeopleRelationshipsDiagnostics, reason: string): void {\n diagnostics.panoramaGroupInclusionReasons[reason] = (diagnostics.panoramaGroupInclusionReasons[reason] ?? 0) + 1\n}\n\nfunction buildOwnerKeyForContribution(nodeByKey: Map<string, NodeAccumulator>, contactKey: string): string {\n const contact = nodeByKey.get(contactKey)\n return contact ? buildOwnerKey() : ''\n}\n\nfunction toGraphEdge(edge: EdgeAccumulator, weight: number): PeopleRelationshipGraphEdge {\n return {\n id: edgeId(edge.sourceKey, edge.targetKey),\n sourceKey: edge.sourceKey,\n targetKey: edge.targetKey,\n weight: roundNum(weight),\n coOccurrenceCount: edge.coOccurrenceCount,\n coOccurrenceRawScore: roundNum(edge.coOccurrenceRawScore),\n replyInteractionCount: edge.replyInteractionCount,\n repliesFromSourceToTarget: edge.repliesFromSourceToTarget,\n repliesFromTargetToSource: edge.repliesFromTargetToSource,\n sourceGroupCount: edge.sourceSessionIds.size,\n sourceSessionIds: [...edge.sourceSessionIds].sort(),\n lastInteractionTs: edge.lastInteractionTs,\n visibility: weight >= 8 ? 2 : 1,\n }\n}\n\nfunction createFactsCacheContext(dir: string): PeopleRelationshipsFactsCacheContext {\n return {\n dir,\n latestKey: buildPeopleRelationshipsSessionLatestCacheKey(PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION),\n stats: createEmptyPeopleRelationshipsFactsCacheStats(),\n }\n}\n\nfunction readLatestFacts(\n sessionId: string,\n factsCache: PeopleRelationshipsFactsCacheContext | null,\n dbVersion: string\n): PeopleRelationshipsSessionLatestFacts | null {\n if (!factsCache) return null\n const cached = readCachedPeopleRelationshipsSessionLatest(sessionId, factsCache.dir, factsCache.latestKey, dbVersion)\n if (!cached.hit) {\n factsCache.stats.latestMisses++\n return null\n }\n factsCache.stats.latestHits++\n return cached.data\n}\n\nfunction writeLatestFacts(\n adapter: SessionRuntimeAdapter,\n sessionId: string,\n factsCache: PeopleRelationshipsFactsCacheContext | null,\n data: PeopleRelationshipsSessionLatestFacts,\n expectedDbVersion: string\n): void {\n if (!factsCache) return\n const dbVersion = getSessionDbVersion(adapter, sessionId)\n if (dbVersion !== expectedDbVersion) {\n appLogger.debug('people-relationships', 'skipped latest facts cache write because db version changed', {\n sessionId,\n })\n return\n }\n writeCachedPeopleRelationshipsSessionLatest(sessionId, factsCache.dir, factsCache.latestKey, dbVersion, data)\n factsCache.stats.writes++\n}\n\nfunction readSessionFacts(\n sessionId: string,\n timeRange: ContactsTimeRangeState,\n factsCache: PeopleRelationshipsFactsCacheContext | null,\n dbVersion: string\n): PeopleRelationshipsSessionFacts | null {\n if (!factsCache) return null\n const cached = readCachedPeopleRelationshipsSessionFacts(\n sessionId,\n factsCache.dir,\n buildPeopleRelationshipsSessionFactsCacheKey(PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION, timeRange),\n dbVersion\n )\n if (!cached.hit) {\n factsCache.stats.factsMisses++\n return null\n }\n factsCache.stats.factsHits++\n return cached.data\n}\n\nfunction writeSessionFacts(\n adapter: SessionRuntimeAdapter,\n sessionId: string,\n timeRange: ContactsTimeRangeState,\n factsCache: PeopleRelationshipsFactsCacheContext | null,\n facts: PeopleRelationshipsSessionFacts,\n expectedDbVersion: string\n): void {\n if (!factsCache) return\n const dbVersion = getSessionDbVersion(adapter, sessionId)\n if (dbVersion !== expectedDbVersion) {\n appLogger.debug('people-relationships', 'skipped session facts cache write because db version changed', {\n sessionId,\n })\n return\n }\n writeCachedPeopleRelationshipsSessionFacts(\n sessionId,\n factsCache.dir,\n buildPeopleRelationshipsSessionFactsCacheKey(PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION, timeRange),\n dbVersion,\n facts\n )\n writeCachedPeopleRelationshipsSessionLatest(sessionId, factsCache.dir, factsCache.latestKey, dbVersion, {\n latestMessageTs: facts.latestMessageTs,\n })\n factsCache.stats.writes += 2\n}\n\nfunction getSessionDbVersion(adapter: SessionRuntimeAdapter, sessionId: string): string {\n return getDbFileVersion(adapter.getDbPath(sessionId))\n}\n\nfunction getOrCreateNode(\n nodes: Map<string, NodeAccumulator>,\n sessionId: string,\n meta: PeopleRelationshipsSessionMetaFacts,\n contact: ContactMemberRef\n): NodeAccumulator {\n const sessionScoped = shouldScopeContactToSession(meta.platform, contact)\n const key = buildContactKey(meta.platform, contact.platformId, sessionScoped ? sessionId : undefined)\n const existing = nodes.get(key)\n if (existing) {\n mergeContactIdentity(existing, contact)\n return existing\n }\n\n const created: NodeAccumulator = {\n key,\n kind: 'contact',\n platform: meta.platform,\n platformId: contact.platformId,\n sessionScoped,\n sessionId: sessionScoped ? sessionId : undefined,\n displayName: contact.name || contact.platformId,\n aliases: new Set([contact.platformId, contact.name, ...contact.aliases].filter(Boolean)),\n avatar: contact.avatar,\n isFriend: false,\n privateMessageCount: 0,\n activePrivateMonths: new Set(),\n groupMessageCount: 0,\n commonGroupSessionIds: new Set(),\n ownerCoOccurrenceCount: 0,\n ownerCoOccurrenceRawScore: 0,\n ownerReplyInteractionCount: 0,\n ownerRepliesFromOwnerToContact: 0,\n ownerRepliesFromContactToOwner: 0,\n communityWeights: new Map(),\n edgeWeight: 0,\n panoramaCandidate: false,\n lastInteractionTs: null,\n }\n nodes.set(key, created)\n return created\n}\n\nfunction getOrCreateOwnerNode(\n nodes: Map<string, NodeAccumulator>,\n meta: PeopleRelationshipsSessionMetaFacts\n): NodeAccumulator | null {\n if (!meta.owner) return null\n const key = buildOwnerKey()\n const existing = nodes.get(key)\n if (existing) {\n mergeContactIdentity(existing, meta.owner)\n return existing\n }\n\n const created: NodeAccumulator = {\n key,\n kind: 'owner',\n platform: meta.platform,\n platformId: meta.owner.platformId || meta.ownerId || OWNER_KEY_PREFIX,\n sessionScoped: false,\n displayName: meta.owner.name || meta.owner.platformId || 'Me',\n aliases: new Set(\n [meta.owner.platformId, meta.owner.name, ...meta.owner.aliases, '我', 'me', 'owner'].filter(Boolean)\n ),\n avatar: meta.owner.avatar,\n isFriend: true,\n privateMessageCount: 0,\n activePrivateMonths: new Set(),\n groupMessageCount: 0,\n commonGroupSessionIds: new Set(),\n ownerCoOccurrenceCount: 0,\n ownerCoOccurrenceRawScore: 0,\n ownerReplyInteractionCount: 0,\n ownerRepliesFromOwnerToContact: 0,\n ownerRepliesFromContactToOwner: 0,\n communityWeights: new Map(),\n edgeWeight: 0,\n panoramaCandidate: true,\n lastInteractionTs: null,\n }\n nodes.set(key, created)\n return created\n}\n\nfunction applyOwnerContactEdge(\n edges: Map<string, EdgeAccumulator>,\n ownerNode: NodeAccumulator,\n contactNode: NodeAccumulator,\n facts: {\n coOccurrenceCount: number\n coOccurrenceRawScore: number\n replyInteractionCount: number\n repliesFromOwnerToContact: number\n repliesFromContactToOwner: number\n lastInteractionTs: number | null\n sessionId: string\n panoramaEligible?: boolean\n }\n): void {\n const sourceKey = ownerNode.key < contactNode.key ? ownerNode.key : contactNode.key\n const targetKey = ownerNode.key < contactNode.key ? contactNode.key : ownerNode.key\n const edge = getOrCreateEdge(edges, sourceKey, targetKey)\n edge.coOccurrenceCount += facts.coOccurrenceCount\n edge.coOccurrenceRawScore += facts.coOccurrenceRawScore\n edge.replyInteractionCount += facts.replyInteractionCount\n if (sourceKey === ownerNode.key) {\n edge.repliesFromSourceToTarget += facts.repliesFromOwnerToContact\n edge.repliesFromTargetToSource += facts.repliesFromContactToOwner\n } else {\n edge.repliesFromSourceToTarget += facts.repliesFromContactToOwner\n edge.repliesFromTargetToSource += facts.repliesFromOwnerToContact\n }\n edge.sourceSessionIds.add(facts.sessionId)\n if (facts.panoramaEligible) edge.panoramaEligible = true\n edge.lastInteractionTs = maxNullableTs(edge.lastInteractionTs, facts.lastInteractionTs)\n contactNode.ownerCoOccurrenceCount += facts.coOccurrenceCount\n contactNode.ownerCoOccurrenceRawScore += facts.coOccurrenceRawScore\n contactNode.ownerReplyInteractionCount += facts.replyInteractionCount\n contactNode.ownerRepliesFromOwnerToContact += facts.repliesFromOwnerToContact\n contactNode.ownerRepliesFromContactToOwner += facts.repliesFromContactToOwner\n updateLastInteraction(contactNode, facts.lastInteractionTs)\n}\n\nfunction getOrCreateEdge(edges: Map<string, EdgeAccumulator>, sourceKey: string, targetKey: string): EdgeAccumulator {\n const id = edgeId(sourceKey, targetKey)\n const existing = edges.get(id)\n if (existing) return existing\n const created: EdgeAccumulator = {\n sourceKey,\n targetKey,\n coOccurrenceCount: 0,\n coOccurrenceRawScore: 0,\n replyInteractionCount: 0,\n repliesFromSourceToTarget: 0,\n repliesFromTargetToSource: 0,\n sourceSessionIds: new Set(),\n panoramaEligible: false,\n lastInteractionTs: null,\n }\n edges.set(id, created)\n return created\n}\n\nfunction toPeopleRelationshipsSessionMetaFacts(\n meta: SessionMeta,\n owner?: ContactMemberRef\n): PeopleRelationshipsSessionMetaFacts {\n return {\n name: meta.name,\n platform: meta.platform,\n type: meta.type as ChatType.PRIVATE | ChatType.GROUP,\n ownerId: meta.ownerId,\n owner,\n }\n}\n\nfunction shouldScopeContactToSession(platform: ChatPlatform, contact: ContactMemberRef): boolean {\n if (isNameMatchPlatform(platform)) return true\n return platform.trim().toLowerCase() === 'qq' && contact.platformId.trim() === contact.name.trim()\n}\n\nfunction buildContactKey(platform: ChatPlatform, platformId: string, sessionId?: string): string {\n const normalizedPlatform = platform.trim()\n const normalizedPlatformId = platformId.trim()\n if (!normalizedPlatform) throw new Error('platform is required')\n if (!normalizedPlatformId) throw new Error('platformId is required')\n return sessionId?.trim()\n ? `${normalizedPlatform}:${sessionId.trim()}:${normalizedPlatformId}`\n : `${normalizedPlatform}:${normalizedPlatformId}`\n}\n\nfunction buildOwnerKey(): string {\n return OWNER_KEY_PREFIX\n}\n\nfunction mergeContactIdentity(acc: NodeAccumulator, contact: ContactMemberRef): void {\n if (contact.name) acc.aliases.add(contact.name)\n acc.aliases.add(contact.platformId)\n for (const alias of contact.aliases) acc.aliases.add(alias)\n if ((!acc.displayName || acc.displayName === acc.platformId) && contact.name) acc.displayName = contact.name\n if (!acc.avatar && contact.avatar) acc.avatar = contact.avatar\n}\n\nfunction pickCommunityId(node: NodeAccumulator): string {\n let bestId = node.isFriend ? PRIVATE_COMMUNITY_ID : ''\n let bestWeight = node.isFriend ? 1 : 0\n for (const [id, weight] of node.communityWeights) {\n if (weight > bestWeight || (weight === bestWeight && id < bestId)) {\n bestId = id\n bestWeight = weight\n }\n }\n return bestId || PRIVATE_COMMUNITY_ID\n}\n\nfunction computeEdgeWeight(edge: EdgeAccumulator): number {\n return computeRawEdgeWeight(edge)\n}\n\nfunction computeRawEdgeWeight(edge: {\n coOccurrenceRawScore: number\n replyInteractionCount: number\n coOccurrenceCount: number\n}): number {\n return (\n edge.coOccurrenceRawScore +\n edge.replyInteractionCount * REPLY_WEIGHT +\n edge.coOccurrenceCount * CO_OCCURRENCE_COUNT_WEIGHT\n )\n}\n\n// 默认全景优先级复用联系人页评分;关系边权只作为同分时的补充,避免大群活跃成员挤掉真正联系人。\nfunction computeContactPriorityScores(nodes: NodeAccumulator[]): Map<NodeAccumulator, number> {\n const result = new Map<NodeAccumulator, number>()\n for (const node of nodes) {\n if (node.kind === 'owner') result.set(node, 1)\n }\n\n const friendInputs = nodes\n .filter((node) => node.kind !== 'owner' && node.isFriend)\n .map((node) => ({\n node,\n privateMessageCount: node.privateMessageCount,\n activeMonths: [...node.activePrivateMonths],\n commonGroupCount: node.commonGroupSessionIds.size,\n }))\n const nonFriendInputs = nodes\n .filter((node) => node.kind !== 'owner' && !node.isFriend)\n .map((node) => ({\n node,\n coOccurrenceRawScore: node.ownerCoOccurrenceRawScore,\n commonGroupCount: node.commonGroupSessionIds.size,\n replyInteractionCount: node.ownerReplyInteractionCount,\n coOccurrenceCount: node.ownerCoOccurrenceCount,\n repliesFromOwnerToContact: node.ownerRepliesFromOwnerToContact,\n repliesFromContactToOwner: node.ownerRepliesFromContactToOwner,\n }))\n\n const friendScores = computeFriendScores(friendInputs)\n const nonFriendScores = computeNonFriendScores(nonFriendInputs)\n for (const input of friendInputs) {\n result.set(input.node, friendScores.get(input)?.score ?? 0)\n }\n for (const input of nonFriendInputs) {\n result.set(input.node, nonFriendScores.get(input)?.score ?? 0)\n }\n return result\n}\n\nfunction compareRankedNodes(\n a: { node: NodeAccumulator; score: number; relationshipActivityScore: number },\n b: { node: NodeAccumulator; score: number; relationshipActivityScore: number }\n): number {\n const poolPriorityDiff = getNodePoolPriority(a.node) - getNodePoolPriority(b.node)\n if (poolPriorityDiff !== 0) return poolPriorityDiff\n return (\n b.score - a.score ||\n b.relationshipActivityScore - a.relationshipActivityScore ||\n a.node.displayName.localeCompare(b.node.displayName)\n )\n}\n\nfunction getNodePoolPriority(node: NodeAccumulator): number {\n if (node.kind === 'owner') return 0\n return node.isFriend ? 1 : 2\n}\n\nfunction computeRelationshipActivityScore(node: NodeAccumulator): number {\n return (\n (node.isFriend ? 60 : 0) +\n node.privateMessageCount * 1.8 +\n node.groupMessageCount * 0.35 +\n node.commonGroupSessionIds.size * 8 +\n node.edgeWeight * 6\n )\n}\n\nfunction normalizeLimits(limits: PeopleRelationshipsComputeLimits = {}): Required<PeopleRelationshipsComputeLimits> {\n return {\n coreNodeLimit: normalizePositiveLimit(limits.coreNodeLimit, 1500),\n coreEdgeLimit: normalizePositiveLimit(limits.coreEdgeLimit, 6000),\n perNodeEdgeLimit: normalizePositiveLimit(limits.perNodeEdgeLimit, 12),\n neighborhoodNodeLimit: normalizePositiveLimit(limits.neighborhoodNodeLimit, 80),\n neighborhoodEdgeLimit: normalizePositiveLimit(limits.neighborhoodEdgeLimit, 240),\n searchResultLimit: normalizePositiveLimit(limits.searchResultLimit, 20),\n }\n}\n\nfunction normalizePositiveLimit(value: number | undefined, fallback: number): number {\n if (!Number.isFinite(value)) return fallback\n return Math.max(1, Math.trunc(value!))\n}\n\nfunction createEmptyDiagnostics(): PeopleRelationshipsDiagnostics {\n return {\n processedPrivateSessions: 0,\n processedGroupSessions: 0,\n skippedMissingOwnerSessions: 0,\n skippedUnresolvedOwnerSessions: 0,\n skippedAmbiguousPrivateSessions: 0,\n skippedFailedSessions: 0,\n totalNodes: 0,\n totalEdges: 0,\n panoramaIncludedGroupSessions: 0,\n panoramaExcludedLowValueGroupSessions: 0,\n panoramaIncludedGroupMembers: 0,\n panoramaExcludedGroupMembers: 0,\n panoramaCandidateNodes: 0,\n panoramaGroupInclusionReasons: {},\n coreNodeCount: 0,\n coreEdgeCount: 0,\n warnings: [],\n }\n}\n\nfunction updateLastInteraction(acc: NodeAccumulator, ts: number | null): void {\n acc.lastInteractionTs = maxNullableTs(acc.lastInteractionTs, ts)\n}\n\nfunction maxNullableTs(current: number | null, next: number | null): number | null {\n if (next === null) return current\n return Math.max(current ?? 0, next)\n}\n\nfunction edgeId(sourceKey: string, targetKey: string): string {\n return `${sourceKey}__${targetKey}`\n}\n\nfunction sortedEdgeId(aKey: string, bKey: string): string {\n return aKey < bKey ? edgeId(aKey, bKey) : edgeId(bKey, aKey)\n}\n\nfunction colorForCommunity(id: string): string {\n return COMMUNITY_COLORS[stableHash(id) % COMMUNITY_COLORS.length]\n}\n\nfunction stableHash(value: string): number {\n let hash = 2166136261\n for (let index = 0; index < value.length; index++) {\n hash ^= value.charCodeAt(index)\n hash = Math.imul(hash, 16777619)\n }\n return hash >>> 0\n}\n\nexport function compareNodes(a: PeopleRelationshipGraphNode, b: PeopleRelationshipGraphNode): number {\n return a.rank - b.rank || a.displayName.localeCompare(b.displayName)\n}\n\nexport function compareEdges(a: PeopleRelationshipGraphEdge, b: PeopleRelationshipGraphEdge): number {\n return b.weight - a.weight || a.id.localeCompare(b.id)\n}\n\nfunction sortEdgesForDisplay(edges: PeopleRelationshipGraphEdge[]): PeopleRelationshipGraphEdge[] {\n const anchorTs = edges.reduce((max, edge) => Math.max(max, edge.lastInteractionTs ?? 0), 0)\n return [...edges].sort((a, b) => compareEdgesForDisplay(a, b, anchorTs))\n}\n\nfunction compareEdgesForDisplay(\n a: PeopleRelationshipGraphEdge,\n b: PeopleRelationshipGraphEdge,\n anchorTs: number\n): number {\n const bRecentWeight = getRecentEdgeWeight(b, anchorTs)\n const aRecentWeight = getRecentEdgeWeight(a, anchorTs)\n if (bRecentWeight !== aRecentWeight) return bRecentWeight - aRecentWeight\n return compareEdges(a, b)\n}\n\nfunction getRecentEdgeWeight(edge: PeopleRelationshipGraphEdge, anchorTs: number): number {\n if (!edge.lastInteractionTs || anchorTs <= 0) return edge.weight\n const ageSeconds = Math.max(0, anchorTs - edge.lastInteractionTs)\n const recencyFactor =\n EDGE_RECENCY_FLOOR + (1 - EDGE_RECENCY_FLOOR) * Math.pow(0.5, ageSeconds / EDGE_RECENCY_HALF_LIFE_SECONDS)\n return edge.weight * recencyFactor\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\nfunction roundNum(value: number, digits = 4): number {\n const factor = 10 ** digits\n return Math.round(value * factor) / factor\n}\n"],"mappings":"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","names":["edgeId"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.writing-vertical[data-v-5097a3ad]{writing-mode:vertical-rl;text-orientation:mixed}.data-flow-bg[data-v-5097a3ad]{background:repeating-linear-gradient(0deg,transparent,transparent 20px,currentColor 20px,currentColor 21px);animation:dataFlow-5097a3ad 20s linear infinite}@keyframes dataFlow-5097a3ad{0%{transform:translateY(0)}to{transform:translateY(-100px)}}.mention-menu-enter-active[data-v-6b40ada0],.mention-menu-leave-active[data-v-6b40ada0]{transition:opacity .16s ease,transform .16s ease}.mention-menu-enter-from[data-v-6b40ada0],.mention-menu-leave-to[data-v-6b40ada0]{transform:translateY(8px);opacity:0}.slash-menu-enter-active[data-v-89f6ec48],.slash-menu-leave-active[data-v-89f6ec48]{transition:opacity .16s ease,transform .16s ease}.slash-menu-enter-from[data-v-89f6ec48],.slash-menu-leave-to[data-v-89f6ec48]{transform:translateY(8px);opacity:0}.custom-scrollbar[data-v-61e036f4]::-webkit-scrollbar{width:4px}.custom-scrollbar[data-v-61e036f4]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-61e036f4]::-webkit-scrollbar-thumb{border-radius:4px;background-color:#9ca3af4d}.dark .custom-scrollbar[data-v-61e036f4]::-webkit-scrollbar-thumb{background-color:#9ca3af26}.slide-fade-enter-active[data-v-b4435ee7],.slide-fade-leave-active[data-v-b4435ee7]{transition:all .3s ease-out}.slide-fade-enter-from[data-v-b4435ee7],.slide-fade-leave-to[data-v-b4435ee7]{transform:translate(20px);opacity:0}.slide-up-enter-active[data-v-b4435ee7],.slide-up-leave-active[data-v-b4435ee7]{transition:all .3s ease-out}.slide-up-enter-from[data-v-b4435ee7],.slide-up-leave-to[data-v-b4435ee7]{transform:translateY(10px);opacity:0}.fade-up-enter-active[data-v-b4435ee7],.fade-up-leave-active[data-v-b4435ee7]{transition:opacity .2s ease-out}.fade-up-enter-from[data-v-b4435ee7],.fade-up-leave-to[data-v-b4435ee7]{opacity:0}.fade-enter-active[data-v-0df46b7b],.fade-leave-active[data-v-0df46b7b]{transition:opacity .15s ease}.fade-enter-from[data-v-0df46b7b],.fade-leave-to[data-v-0df46b7b]{opacity:0}.fade-enter-active[data-v-d712cb76],.fade-leave-active[data-v-d712cb76]{transition:opacity .15s ease}.fade-enter-from[data-v-d712cb76],.fade-leave-to[data-v-d712cb76]{opacity:0}
|