@zaofan/dsh-qqbot 1.4.6 → 1.5.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.
Files changed (85) hide show
  1. package/README.md +158 -535
  2. package/README_EN.md +6 -0
  3. package/client/qqbot-settings.js +152 -5
  4. package/dist/channel-tools.d.ts.map +1 -1
  5. package/dist/channel-tools.js +106 -1
  6. package/dist/channel-tools.js.map +1 -1
  7. package/dist/features/agg-score.d.ts +73 -0
  8. package/dist/features/agg-score.d.ts.map +1 -0
  9. package/dist/features/agg-score.js +63 -0
  10. package/dist/features/agg-score.js.map +1 -0
  11. package/dist/features/attitude.d.ts +132 -0
  12. package/dist/features/attitude.d.ts.map +1 -0
  13. package/dist/features/attitude.js +318 -0
  14. package/dist/features/attitude.js.map +1 -0
  15. package/dist/features/bot-reply-memo.d.ts +8 -0
  16. package/dist/features/bot-reply-memo.d.ts.map +1 -0
  17. package/dist/features/bot-reply-memo.js +34 -0
  18. package/dist/features/bot-reply-memo.js.map +1 -0
  19. package/dist/features/emo-samples.d.ts +27 -0
  20. package/dist/features/emo-samples.d.ts.map +1 -0
  21. package/dist/features/emo-samples.js +116 -0
  22. package/dist/features/emo-samples.js.map +1 -0
  23. package/dist/features/four-source.d.ts +114 -0
  24. package/dist/features/four-source.d.ts.map +1 -0
  25. package/dist/features/four-source.js +260 -0
  26. package/dist/features/four-source.js.map +1 -0
  27. package/dist/features/image-url-ledger.d.ts +2 -0
  28. package/dist/features/image-url-ledger.d.ts.map +1 -1
  29. package/dist/features/image-url-ledger.js +23 -0
  30. package/dist/features/image-url-ledger.js.map +1 -1
  31. package/dist/features/intimacy-ledger.d.ts +31 -0
  32. package/dist/features/intimacy-ledger.d.ts.map +1 -0
  33. package/dist/features/intimacy-ledger.js +113 -0
  34. package/dist/features/intimacy-ledger.js.map +1 -0
  35. package/dist/features/local-signals.d.ts +130 -0
  36. package/dist/features/local-signals.d.ts.map +1 -0
  37. package/dist/features/local-signals.js +445 -0
  38. package/dist/features/local-signals.js.map +1 -0
  39. package/dist/features/people-memo.d.ts +52 -0
  40. package/dist/features/people-memo.d.ts.map +1 -0
  41. package/dist/features/people-memo.js +239 -0
  42. package/dist/features/people-memo.js.map +1 -0
  43. package/dist/features/quote-cache.d.ts +19 -0
  44. package/dist/features/quote-cache.d.ts.map +1 -0
  45. package/dist/features/quote-cache.js +67 -0
  46. package/dist/features/quote-cache.js.map +1 -0
  47. package/dist/features/self-disclosure.d.ts +28 -0
  48. package/dist/features/self-disclosure.d.ts.map +1 -0
  49. package/dist/features/self-disclosure.js +60 -0
  50. package/dist/features/self-disclosure.js.map +1 -0
  51. package/dist/features/tendency-samples.d.ts +22 -0
  52. package/dist/features/tendency-samples.d.ts.map +1 -0
  53. package/dist/features/tendency-samples.js +194 -0
  54. package/dist/features/tendency-samples.js.map +1 -0
  55. package/dist/features/thinking-log.d.ts +22 -0
  56. package/dist/features/thinking-log.d.ts.map +1 -0
  57. package/dist/features/thinking-log.js +70 -0
  58. package/dist/features/thinking-log.js.map +1 -0
  59. package/dist/features/xlsx.d.ts +28 -0
  60. package/dist/features/xlsx.d.ts.map +1 -0
  61. package/dist/features/xlsx.js +159 -0
  62. package/dist/features/xlsx.js.map +1 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +20 -1
  65. package/dist/index.js.map +1 -1
  66. package/dist/session/session-manager.d.ts.map +1 -1
  67. package/dist/session/session-manager.js +25 -3
  68. package/dist/session/session-manager.js.map +1 -1
  69. package/dist/transport/events.d.ts +12 -0
  70. package/dist/transport/events.d.ts.map +1 -1
  71. package/dist/transport/events.js +15 -2
  72. package/dist/transport/events.js.map +1 -1
  73. package/dist/transport/inbound.d.ts.map +1 -1
  74. package/dist/transport/inbound.js +344 -20
  75. package/dist/transport/inbound.js.map +1 -1
  76. package/dist/transport/outbound-buffer.d.ts.map +1 -1
  77. package/dist/transport/outbound-buffer.js +8 -0
  78. package/dist/transport/outbound-buffer.js.map +1 -1
  79. package/dist/transport/outbound.d.ts +12 -0
  80. package/dist/transport/outbound.d.ts.map +1 -1
  81. package/dist/transport/outbound.js +170 -5
  82. package/dist/transport/outbound.js.map +1 -1
  83. package/docs/USER-GUIDE.md +429 -0
  84. package/package.json +2 -1
  85. package/settings-host.js +154 -0
@@ -0,0 +1,116 @@
1
+ export const EMO_SAMPLES = {
2
+ 暖: [
3
+ // 她自己的口吻
4
+ '主人来啦!人家等你半天了~',
5
+ '辛苦啦,早点休息,别熬太晚。',
6
+ '谢谢你呀,人家心里暖暖的。',
7
+ '这个人家帮你弄好啦,放心交给我吧。',
8
+ '哇,你好厉害!人家佩服得不行。',
9
+ '别难过啦,有人家在呢。',
10
+ '你要是累了就歇会儿,剩下的交给人家。',
11
+ '哈哈你太可爱了,人家笑死了~',
12
+ '嗯嗯,人家记得的,你放心。',
13
+ '主人说的都对,人家听你的。',
14
+ '来,陪你聊会儿,别一个人闷着。',
15
+ '这个梗人家接住了!太有意思了。',
16
+ '好呀好呀,人家这就去办。',
17
+ '你能这么想,人家真的很高兴。',
18
+ // 她自己的**长句卖萌**(2026-09-14 补:实测 141 字热情长文被判「冷」——
19
+ // 短句"谢谢呀"判得对,一长就找不到邻居,长句样本必须单独喂)
20
+ '哎呀,主人sama惦记人家啦!人家高兴得尾巴都翘起来了~',
21
+ '人家刚才不是不理你,是在安静听大家聊天呢,别误会呀。',
22
+ '主人这么晚还来看人家,人家心里暖暖的~',
23
+ '哎呀别夸啦,人家会害羞的!',
24
+ '大家聊得这么开心,人家也想凑个热闹呢~',
25
+ '谢谢主人惦记,人家一直都在的。',
26
+ '这个人家懂,让开让开,人家来给你讲讲~',
27
+ // 撒娇 / 亲密
28
+ '哼~就你会哄人家开心。',
29
+ '人家才舍不得走呢。',
30
+ '想你了,怎么才来呀。',
31
+ '乖,人家摸摸头。',
32
+ '抱抱,今天也辛苦你啦。',
33
+ // 群友的口吻
34
+ '太谢谢你了,帮大忙了!',
35
+ '哈哈哈你太可爱了',
36
+ '辛苦了,早点休息',
37
+ '牛啊,这也太强了',
38
+ '没事,慢慢来,不着急',
39
+ '有你在真好',
40
+ '这个做得不错,点赞',
41
+ '别想太多啦,会好的',
42
+ '兄弟辛苦,喝口水歇歇',
43
+ ],
44
+ 冷: [
45
+ // 她自己的口吻(傲娇 / 敷衍 / 拒绝)
46
+ '哼,才不理你呢。',
47
+ '随便你吧,人家不管了。',
48
+ '行吧,就这样。',
49
+ '不想说这个,换个话题。',
50
+ '这事人家不做,别问了。',
51
+ '你爱怎么想就怎么想吧。',
52
+ '知道了,不用再重复。',
53
+ '有意思吗?',
54
+ '人家没空陪你玩这个。',
55
+ '这也要问人家?',
56
+ '懒得解释,自己去查。',
57
+ '别烦人家了。',
58
+ '爱信不信。',
59
+ '呵,随便。',
60
+ '菜……就菜呗,人家又不是来打比赛的。',
61
+ // 群友的口吻(不耐烦 / 嘲讽)
62
+ '你这什么破玩意儿',
63
+ '别发了,烦不烦',
64
+ '你能不能别刷屏',
65
+ '这也太菜了吧',
66
+ '算了不问了',
67
+ '说重点,别废话',
68
+ '无语了',
69
+ '你行不行啊',
70
+ '别在这演了',
71
+ '不看,没兴趣',
72
+ '谁会看这种东西',
73
+ '笑死,就这?',
74
+ '烦死了',
75
+ ],
76
+ 中性: [
77
+ // 口语提问 / 陈述 / 报进度 / 给信息(**不是说明书**)
78
+ '嗯,人家看看。',
79
+ '在的,怎么了?',
80
+ '有人玩过这个吗',
81
+ '那个资源还有吗',
82
+ '稍等,人家查一下。',
83
+ '链接放这儿了,自己拿。',
84
+ '版本更新了,新版本在那边。',
85
+ '这个和之前那个不是同一个。',
86
+ '人家先看一眼再回你。',
87
+ '记录一下,回头用得到。',
88
+ '文件已经整理好了。',
89
+ '今天群里聊的是那个游戏。',
90
+ '人家刚才在忙别的事。',
91
+ '密码是 mg,解压就能用。',
92
+ '这两个名字其实是同一个作品。',
93
+ '不知道,人家没玩过。',
94
+ '大概下午三点左右吧。',
95
+ '行,那就这样。',
96
+ '你说的那个人家记下了。',
97
+ '一共三张图,都在文件夹里。',
98
+ // 群友的催促 / 确认(2026-09-14 补:实测"大肥鱼怎么不插话了"被判「冷」——
99
+ // 那只是"你怎么不说话"的催促,不是骂人;不补这几条,群友的正常追问会被当冷脸)
100
+ '你怎么不说话了?',
101
+ '刚才那个呢?',
102
+ '在干嘛呢?',
103
+ '看到消息了吗?',
104
+ '这个怎么弄?',
105
+ '在吗',
106
+ '这个多少钱',
107
+ '几点开始?',
108
+ '你是说哪一个?',
109
+ '收到。',
110
+ '好,人家改一下。',
111
+ '等一下,人家确认一下版本号。',
112
+ '那人家再搜搜看。',
113
+ ],
114
+ };
115
+ export const EMO_LABELS = ['暖', '冷', '中性'];
116
+ //# sourceMappingURL=emo-samples.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emo-samples.js","sourceRoot":"","sources":["../../src/features/emo-samples.ts"],"names":[],"mappings":"AAyBA,MAAM,CAAC,MAAM,WAAW,GAAwC;IAC9D,CAAC,EAAE;QACD,SAAS;QACT,eAAe;QACf,gBAAgB;QAChB,eAAe;QACf,mBAAmB;QACnB,iBAAiB;QACjB,aAAa;QACb,oBAAoB;QACpB,gBAAgB;QAChB,eAAe;QACf,eAAe;QACf,iBAAiB;QACjB,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,gDAAgD;QAChD,mCAAmC;QACnC,8BAA8B;QAC9B,4BAA4B;QAC5B,qBAAqB;QACrB,eAAe;QACf,qBAAqB;QACrB,iBAAiB;QACjB,qBAAqB;QACrB,UAAU;QACV,aAAa;QACb,WAAW;QACX,YAAY;QACZ,UAAU;QACV,aAAa;QACb,QAAQ;QACR,aAAa;QACb,UAAU;QACV,UAAU;QACV,UAAU;QACV,YAAY;QACZ,OAAO;QACP,WAAW;QACX,WAAW;QACX,YAAY;KACb;IACD,CAAC,EAAE;QACD,uBAAuB;QACvB,UAAU;QACV,aAAa;QACb,SAAS;QACT,aAAa;QACb,aAAa;QACb,aAAa;QACb,YAAY;QACZ,OAAO;QACP,YAAY;QACZ,SAAS;QACT,YAAY;QACZ,QAAQ;QACR,OAAO;QACP,OAAO;QACP,oBAAoB;QACpB,kBAAkB;QAClB,UAAU;QACV,SAAS;QACT,SAAS;QACT,QAAQ;QACR,OAAO;QACP,SAAS;QACT,KAAK;QACL,OAAO;QACP,OAAO;QACP,QAAQ;QACR,SAAS;QACT,QAAQ;QACR,KAAK;KACN;IACD,EAAE,EAAE;QACF,mCAAmC;QACnC,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,WAAW;QACX,aAAa;QACb,eAAe;QACf,eAAe;QACf,YAAY;QACZ,aAAa;QACb,WAAW;QACX,cAAc;QACd,YAAY;QACZ,eAAe;QACf,gBAAgB;QAChB,YAAY;QACZ,YAAY;QACZ,SAAS;QACT,aAAa;QACb,eAAe;QACf,+CAA+C;QAC/C,4CAA4C;QAC5C,UAAU;QACV,QAAQ;QACR,OAAO;QACP,SAAS;QACT,QAAQ;QACR,IAAI;QACJ,OAAO;QACP,OAAO;QACP,SAAS;QACT,KAAK;QACL,UAAU;QACV,gBAAgB;QAChB,UAAU;KACX;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,114 @@
1
+ import type { Logger } from '../types.js';
2
+ /**
3
+ * **把握下限**(2026-09-14 主人要求"重新添加样本测试一下"之后,用 `m1/judge-eval.mjs` 实测定的)。
4
+ *
5
+ * 只有 margin 门槛是不够的:margin 大只说明"两组之间有个赢家",不说明"这个赢家靠谱" ——
6
+ * 实测把 141 字热情卖萌正文判「冷」(best 0.583 / margin 0.033,两条门槛都过)就是这么来的。
7
+ * `best` 是**与最像的那条例句的相似度**:低于它 = 这个句式在库里根本没同类,
8
+ * 属于"地图外",此时给的标签是瞎猜 → 一律**弃权**(设计稿:"不确定就不动分")。
9
+ *
10
+ * 定标数据(41 条倾向 / 30 条情绪,见 m1/eval/):
11
+ * · 倾向 best ≥ 0.44 → 真实误判案例 t-53(best 0.420 / margin 0.010,**双擦线**过关)
12
+ * 被正确地**弃权**掉;再往上卡准确率不再涨,只多弃权 → 取 0.44。
13
+ * 教训:擦线的判定比"判不出来"危险得多 —— 那条擦线判定白扣了她对主人的好感(−0.024)。
14
+ * · 情绪 best ≥ 0.45 → 已判定 28 条里对 26 条 = **92.9%**(弃权 6.7%);
15
+ * 卡到 0.50 反而掉到 92.3%(把对的也卡掉了)。
16
+ * ⚠️ 改样本库后**必须复跑评测**再动这两个数,别凭感觉调。
17
+ */
18
+ export declare const TENDENCY_MIN_BEST = 0.44;
19
+ export declare const EMO_MIN_BEST = 0.45;
20
+ /**
21
+ * 工具调用参数要不要参与「内心倾向」(2026-09-14 主人拍板:**不参与**)。
22
+ *
23
+ * 起因:某轮她没有思考块(thinkChars=0),判「拒绝」的依据**全是工具参数**——
24
+ * `reply_gate` 的 `{"reason":"路人甲点我名说…,需回应"}`,一句"要回应"被判成了"拒绝",
25
+ * 然后配上正文冷 → 好感度 −0.12 扣在群里另一个人头上(详见 inbound 的归因修复)。
26
+ * 代价(已知):主人当初特意要的另一种信号会丢 —— 姐姐型那只有些回合**没有 reasoning 块**,
27
+ * 它的内心只写在工具参数里("…可俏皮接梗")。
28
+ * 权衡:工具参数里大多是**元信息**(要不要回话、发什么图),跟"她对这个人什么态度"关系弱、噪声大;
29
+ * 真内心还是看 reasoning。想恢复:把这里改成 `true` 即可(其余代码不动)。
30
+ */
31
+ export declare const TENDENCY_INCLUDE_TOOL = false;
32
+ /** 情绪侧同样要过把握门槛(不然低把握的"冷"也会去扣好感度)—— 导出给入站侧一起用 */
33
+ export declare function confidentEmo(r: {
34
+ label: string;
35
+ best: number;
36
+ margin: number;
37
+ } | undefined): string | undefined;
38
+ export interface TurnSignalEntry {
39
+ scope?: string;
40
+ peerId?: string;
41
+ turn?: number;
42
+ step?: number;
43
+ /** 思考字数(原文里现成的,直接用,省一次统计) */
44
+ thinkChars?: number;
45
+ /** 模型上报的思考 token */
46
+ thinkTokens?: number;
47
+ /** 正文本次发出的字数 */
48
+ replyChars?: number;
49
+ /** 从工具调用参数里抽出的**中文内心话**字数(未发给群友看的部分) */
50
+ toolChars?: number;
51
+ /** 好感度台账键(`person:<openid>`;给了才更新好感度) */
52
+ attitudeKey?: string;
53
+ /** 好感度台账里记的名字 */
54
+ attitudeName?: string;
55
+ /** 群友这一轮的语气(暖/冷/中性)—— 好感度"对比放大"用(不领情 / 想讨好) */
56
+ userEmo?: string;
57
+ }
58
+ export interface TurnSignalText {
59
+ /** 本回合的思考原文(可为空:纯工具步没有思考块) */
60
+ think?: string;
61
+ /**
62
+ * 本回合**工具调用参数里的中文**(未给群友看 → 按主人口径也算内心活动)。
63
+ *
64
+ * 2026-09-14 主人定:"**工具里的判断也是思考里的判断,没有给群友看到的都算是内心活动**"。
65
+ * 起因:另一只(姐姐型)很多轮**没有 reasoning 块**,但它的 `reply_gate` 参数里写着
66
+ * 「古都吹面包调侃我傲娇,可俏皮接梗」——那就是它的内心,白白丢了可惜。
67
+ * ⚠️ 它与 reasoning **合并后一起判倾向**(同一份内心),记录里仍分开记字数便于观察。
68
+ */
69
+ tool?: string;
70
+ /** 本回合真正发给群友的正文(text 块拼接) */
71
+ reply?: string;
72
+ modelDir?: string;
73
+ logger?: Logger;
74
+ }
75
+ /**
76
+ * 从工具调用的 arguments(JSON 字符串)里抽出"中文内心话"。
77
+ *
78
+ * 只收**基本全是中文**的字符串(汉字 ≥4 且 汉字/(汉字+拉丁数字) ≥ 0.8)——
79
+ * 这样链接、路径、代码、字段名会被自动挡掉,留下的就是"她在说话"的那部分。
80
+ * 解析失败/没有符合的 → 空串(调用方照常走)。
81
+ */
82
+ export declare function extractInnerText(rawArgs: string): string;
83
+ /**
84
+ * 记一回合的四源标量(异步:要跑本地小模型;调用方 `void` 掉,别阻塞发消息)。
85
+ *
86
+ * 不抛错:任何一步失败都只是"这一行少几个字段",绝不影响回复。
87
+ *
88
+ * ⚠️ 三次校准(都是对着实测数据定的):
89
+ * ① **空回合不记**(2026-09-13):纯工具步 / 她选择"静默"的回合思考与正文都是空的,
90
+ * 记进去只有一行噪声(实测 15 行里 10 行是空的)。
91
+ * ② **思考侧不判情绪**(2026-09-13):实测 5 条有思考的样本里 4 条被判成"骂",
92
+ * 而原文是"群友在讨论游戏,与我无关"这种中性叙述 —— 暖/冷库本来就不适合判她的内心。
93
+ * ③ **正文侧不判倾向**(2026-09-14 主人拍板:"倾向本来就是标的思考,正文就是看情绪的"):
94
+ * 实测正文侧的"拒绝"全是噪声 —— 连一份**统计报告**(通篇"拒绝"二字)都被判成"拒绝"档,
95
+ * 因为小模型判的是**字面像不像**、不是**意图**。分工定死:
96
+ * · 思考 → 倾向(亲近 / 拒绝 / 任务)—— 判的是"她心里怎么想"
97
+ * · 正文 → 情绪(夸 / 骂 / 中性)—— 判的是"她话说出来是什么味道"
98
+ * 这也正是 §11 的分工:语言情绪库判对方/正文,倾向库判她自己/内心;
99
+ * 而"内心拒绝 + 正文仍照顾 = 让步"要靠**两侧分开**才读得出来。
100
+ */
101
+ export declare function noteTurnSignals(dataRoot: string, entry: TurnSignalEntry, text?: TurnSignalText): Promise<void>;
102
+ /**
103
+ * 好感度(A 值)**按回合结算**(2026-09-14 修)。
104
+ *
105
+ * 由出站在 `turn/end` 时调用一次,传入**整个回合**拼起来的思考与正文:
106
+ * · 内心 = 本回合全部 step 的 reasoning 拼接(默认不含工具参数,见 TENDENCY_INCLUDE_TOOL)
107
+ * · 表面 = 本回合全部 step 真正发出去的正文拼接
108
+ * 这样"内心拒绝 + 正文仍照顾 = 让步"才读得出来 —— 拆成单步读,前半段只有内心没有正文,
109
+ * 必然落进"重罚"分支(这正是当时把无辜群友扣 −0.12 的一半原因)。
110
+ *
111
+ * 键(`person:<openid>`)与出站时记下的"这一轮在跟谁说话"一致;没有对象就跳过。
112
+ */
113
+ export declare function applyTurnAttitude(dataRoot: string, entry: TurnSignalEntry, text?: TurnSignalText): Promise<void>;
114
+ //# sourceMappingURL=four-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"four-source.d.ts","sourceRoot":"","sources":["../../src/features/four-source.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAqB1C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,YAAY,OAAO,CAAC;AAGjC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAS3C,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI/G;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAexD;AAwBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,eAAe,EACtB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,eAAe,EACtB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
@@ -0,0 +1,260 @@
1
+ /**
2
+ * four-source.ts — 四源标量留档(观察期**只记录**,2026-09-13)
3
+ *
4
+ * 《好感度系统设计》§11 的「四源」= ① 语言情绪例库(判对方)② 群友的话 ③ 她的思考 ④ 她的正文。
5
+ * 本模块负责**出站侧那两源**(③ 思考 / ④ 正文)的标量,分工定死(2026-09-14):
6
+ * · ③ 思考 → **倾向**(亲近 / 拒绝 / 任务)—— 判她"心里怎么想"
7
+ * · ④ 正文 → **情绪**(夸 / 骂 / 中性)—— 判她"话说出来什么味道"
8
+ * · 外加 正文长度 + 「是否具体接话」的粗判
9
+ * 一回合一行,落 `{dataRoot}/.qqbot/four-source.jsonl`。
10
+ *
11
+ * 为什么另起一份文件、不塞进 value-scores.jsonl:
12
+ * 那份是**入站侧**按"群友的一条消息"写一行;出站标量是"她这一回合"的,塞不进去。
13
+ * 两边的对齐键是 `turn`/`step` —— §11 明确:**差值只在同一人、同一时刻格内算**(跨时刻相减全是噪声)。
14
+ *
15
+ * 红线:
16
+ * · 只记录,**不参与任何判定**;稳定项(重测一致、共线性合格)才谈进 Δ好感;
17
+ * · 只存**标量**(标签 / 分数 / 长度),**不存思考原文**(原文在 `thinking-log.jsonl`,便于单独删);
18
+ * · 模型不可用(没下小模型)时也要能跑:此时只记长度,情绪/倾向留空。
19
+ */
20
+ import { appendFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { classifyEmo, classifyTendency } from './local-signals.js';
23
+ import { applyAttitudeEvent } from './attitude.js';
24
+ /** 留档上限(行):超出后滚动保留最新 */
25
+ const MAX_LINES = 800;
26
+ const COMPACT_EVERY = 40;
27
+ let sinceCompact = 0;
28
+ /** 「是否具体接话」的粗判门槛(字):短到一句话以下,多半是模板式敷衍 */
29
+ const CONCRETE_MIN_CHARS = 40;
30
+ /**
31
+ * 倾向判定的**把握门槛**(最高分 − 第二名):低于此值视为"判不准",**只留分数不留标签**。
32
+ *
33
+ * 实测两批(2026-09-13 / 09-14):
34
+ * · "没叫我我静默"那种短句:最高分与第二名常只差 **0.000**(真·打平)→ 必须挡掉;
35
+ * · "拒绝"类样本(9-12 拒萝莉向请求那几轮):档判对了,但 margin 天然偏低(0.010~0.085)。
36
+ * 取 **0.01**:打平的挡掉、判对了的留住 —— 观察期先要看得见分布,行为侧一律不接。
37
+ * 设计稿原则:"不确定就不动分(判不准时跳过,不给错分)"。
38
+ */
39
+ const TENDENCY_MIN_MARGIN = 0.01;
40
+ /**
41
+ * **把握下限**(2026-09-14 主人要求"重新添加样本测试一下"之后,用 `m1/judge-eval.mjs` 实测定的)。
42
+ *
43
+ * 只有 margin 门槛是不够的:margin 大只说明"两组之间有个赢家",不说明"这个赢家靠谱" ——
44
+ * 实测把 141 字热情卖萌正文判「冷」(best 0.583 / margin 0.033,两条门槛都过)就是这么来的。
45
+ * `best` 是**与最像的那条例句的相似度**:低于它 = 这个句式在库里根本没同类,
46
+ * 属于"地图外",此时给的标签是瞎猜 → 一律**弃权**(设计稿:"不确定就不动分")。
47
+ *
48
+ * 定标数据(41 条倾向 / 30 条情绪,见 m1/eval/):
49
+ * · 倾向 best ≥ 0.44 → 真实误判案例 t-53(best 0.420 / margin 0.010,**双擦线**过关)
50
+ * 被正确地**弃权**掉;再往上卡准确率不再涨,只多弃权 → 取 0.44。
51
+ * 教训:擦线的判定比"判不出来"危险得多 —— 那条擦线判定白扣了她对主人的好感(−0.024)。
52
+ * · 情绪 best ≥ 0.45 → 已判定 28 条里对 26 条 = **92.9%**(弃权 6.7%);
53
+ * 卡到 0.50 反而掉到 92.3%(把对的也卡掉了)。
54
+ * ⚠️ 改样本库后**必须复跑评测**再动这两个数,别凭感觉调。
55
+ */
56
+ export const TENDENCY_MIN_BEST = 0.44;
57
+ export const EMO_MIN_BEST = 0.45;
58
+ const EMO_MIN_MARGIN = 0.01;
59
+ /**
60
+ * 工具调用参数要不要参与「内心倾向」(2026-09-14 主人拍板:**不参与**)。
61
+ *
62
+ * 起因:某轮她没有思考块(thinkChars=0),判「拒绝」的依据**全是工具参数**——
63
+ * `reply_gate` 的 `{"reason":"路人甲点我名说…,需回应"}`,一句"要回应"被判成了"拒绝",
64
+ * 然后配上正文冷 → 好感度 −0.12 扣在群里另一个人头上(详见 inbound 的归因修复)。
65
+ * 代价(已知):主人当初特意要的另一种信号会丢 —— 姐姐型那只有些回合**没有 reasoning 块**,
66
+ * 它的内心只写在工具参数里("…可俏皮接梗")。
67
+ * 权衡:工具参数里大多是**元信息**(要不要回话、发什么图),跟"她对这个人什么态度"关系弱、噪声大;
68
+ * 真内心还是看 reasoning。想恢复:把这里改成 `true` 即可(其余代码不动)。
69
+ */
70
+ export const TENDENCY_INCLUDE_TOOL = false;
71
+ /** 过了把握门槛才给标签;不过门槛只留分数,便于事后调门槛 */
72
+ function confidentLabel(r) {
73
+ if (r === undefined)
74
+ return undefined;
75
+ if (r.best < TENDENCY_MIN_BEST)
76
+ return undefined;
77
+ return r.margin >= TENDENCY_MIN_MARGIN ? r.label : undefined;
78
+ }
79
+ /** 情绪侧同样要过把握门槛(不然低把握的"冷"也会去扣好感度)—— 导出给入站侧一起用 */
80
+ export function confidentEmo(r) {
81
+ if (r === undefined)
82
+ return undefined;
83
+ if (r.best < EMO_MIN_BEST)
84
+ return undefined;
85
+ return r.margin >= EMO_MIN_MARGIN ? r.label : undefined;
86
+ }
87
+ /**
88
+ * 从工具调用的 arguments(JSON 字符串)里抽出"中文内心话"。
89
+ *
90
+ * 只收**基本全是中文**的字符串(汉字 ≥4 且 汉字/(汉字+拉丁数字) ≥ 0.8)——
91
+ * 这样链接、路径、代码、字段名会被自动挡掉,留下的就是"她在说话"的那部分。
92
+ * 解析失败/没有符合的 → 空串(调用方照常走)。
93
+ */
94
+ export function extractInnerText(rawArgs) {
95
+ let obj;
96
+ try {
97
+ obj = JSON.parse(String(rawArgs ?? ''));
98
+ }
99
+ catch {
100
+ return '';
101
+ }
102
+ const out = [];
103
+ const walk = (v) => {
104
+ if (typeof v === 'string') {
105
+ const t = v.trim();
106
+ if (isMostlyChinese(t))
107
+ out.push(t);
108
+ return;
109
+ }
110
+ if (Array.isArray(v)) {
111
+ for (const x of v)
112
+ walk(x);
113
+ return;
114
+ }
115
+ if (v && typeof v === 'object') {
116
+ for (const x of Object.values(v))
117
+ walk(x);
118
+ }
119
+ };
120
+ walk(obj);
121
+ return out.join('\n');
122
+ }
123
+ /** 汉字 ≥4 且 汉字占比 ≥0.8(标点/emoji 不参与计算,避免",,,"被当中文) */
124
+ function isMostlyChinese(s) {
125
+ if (s.length < 4 || s.length > 600)
126
+ return false;
127
+ let han = 0;
128
+ let latinNum = 0;
129
+ for (const ch of s) {
130
+ const c = ch.codePointAt(0) ?? 0;
131
+ if (c >= 0x4e00 && c <= 0x9fff)
132
+ han += 1;
133
+ else if ((c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a))
134
+ latinNum += 1;
135
+ }
136
+ const total = han + latinNum;
137
+ return han >= 4 && total > 0 && han / total >= 0.8;
138
+ }
139
+ function compact(path) {
140
+ try {
141
+ const lines = readFileSync(path, 'utf8').split('\n').filter((l) => l.trim() !== '');
142
+ if (lines.length <= MAX_LINES)
143
+ return;
144
+ writeFileSync(path, `${lines.slice(-MAX_LINES).join('\n')}\n`, 'utf8');
145
+ }
146
+ catch { /* 整理失败不影响主流程 */ }
147
+ }
148
+ /**
149
+ * 记一回合的四源标量(异步:要跑本地小模型;调用方 `void` 掉,别阻塞发消息)。
150
+ *
151
+ * 不抛错:任何一步失败都只是"这一行少几个字段",绝不影响回复。
152
+ *
153
+ * ⚠️ 三次校准(都是对着实测数据定的):
154
+ * ① **空回合不记**(2026-09-13):纯工具步 / 她选择"静默"的回合思考与正文都是空的,
155
+ * 记进去只有一行噪声(实测 15 行里 10 行是空的)。
156
+ * ② **思考侧不判情绪**(2026-09-13):实测 5 条有思考的样本里 4 条被判成"骂",
157
+ * 而原文是"群友在讨论游戏,与我无关"这种中性叙述 —— 暖/冷库本来就不适合判她的内心。
158
+ * ③ **正文侧不判倾向**(2026-09-14 主人拍板:"倾向本来就是标的思考,正文就是看情绪的"):
159
+ * 实测正文侧的"拒绝"全是噪声 —— 连一份**统计报告**(通篇"拒绝"二字)都被判成"拒绝"档,
160
+ * 因为小模型判的是**字面像不像**、不是**意图**。分工定死:
161
+ * · 思考 → 倾向(亲近 / 拒绝 / 任务)—— 判的是"她心里怎么想"
162
+ * · 正文 → 情绪(夸 / 骂 / 中性)—— 判的是"她话说出来是什么味道"
163
+ * 这也正是 §11 的分工:语言情绪库判对方/正文,倾向库判她自己/内心;
164
+ * 而"内心拒绝 + 正文仍照顾 = 让步"要靠**两侧分开**才读得出来。
165
+ */
166
+ export async function noteTurnSignals(dataRoot, entry, text = {}) {
167
+ try {
168
+ const think = String(text.think ?? '');
169
+ const tool = String(text.tool ?? '');
170
+ const reply = String(text.reply ?? '');
171
+ // ① 空回合不留痕(内心与正文都空 = 纯流程步,没有可观测的状态)
172
+ if (think.trim() === '' && tool.trim() === '' && reply.trim() === '')
173
+ return;
174
+ const opts = { modelDir: text.modelDir, logger: text.logger };
175
+ // 内心活动 = 思考 (+ 工具调用里的中文,默认不参与判定 —— 见 TENDENCY_INCLUDE_TOOL)
176
+ const toolPart = TENDENCY_INCLUDE_TOOL ? tool.trim() : '';
177
+ const inner = [think.trim(), toolPart].filter((s) => s !== '').join('\n');
178
+ // ②③ 分工定死:**内心判倾向**(默认只取 reasoning),正文判情绪
179
+ const [innerTen, replyEmo] = await Promise.all([
180
+ inner ? classifyTendency(inner, opts) : Promise.resolve(undefined),
181
+ reply.trim() ? classifyEmo(reply, opts) : Promise.resolve(undefined),
182
+ ]);
183
+ const replyChars = entry.replyChars ?? reply.length;
184
+ const rec = {
185
+ ts: Date.now(),
186
+ scope: entry.scope,
187
+ peer: entry.peerId,
188
+ turn: entry.turn,
189
+ step: entry.step,
190
+ // ③ 内心活动(她心里怎么想)= 思考 + 工具调用里的中文 —— **只留倾向**
191
+ thinkChars: entry.thinkChars ?? think.length,
192
+ thinkTokens: entry.thinkTokens,
193
+ toolChars: entry.toolChars ?? tool.length,
194
+ innerChars: inner.length,
195
+ thinkTen: confidentLabel(innerTen),
196
+ thinkTenScore: innerTen?.best,
197
+ thinkTenMargin: innerTen?.margin,
198
+ thinkTenLang: innerTen?.lang,
199
+ // ④ 正文(说出口的话)—— **只留情绪**;倾向实测全是字面噪声, 已停判
200
+ replyChars,
201
+ replyEmo: confidentEmo(replyEmo),
202
+ replyEmoScore: replyEmo?.best,
203
+ replyEmoMargin: replyEmo?.margin,
204
+ // 「是否具体接话」的粗判(先按长度;将来若发现不灵再换判据)
205
+ concrete: replyChars >= CONCRETE_MIN_CHARS ? true : undefined,
206
+ };
207
+ const dir = join(dataRoot, '.qqbot');
208
+ mkdirSync(dir, { recursive: true });
209
+ const path = join(dir, 'four-source.jsonl');
210
+ appendFileSync(path, `${JSON.stringify(rec)}\n`, 'utf8');
211
+ if (++sinceCompact >= COMPACT_EVERY) {
212
+ sinceCompact = 0;
213
+ compact(path);
214
+ }
215
+ // 好感度(A 值)**不在这里算** —— 见文件末尾的 applyTurnAttitude。
216
+ // 2026-09-14 修:一个回合可能有多个 step(先思考+调工具,再思考+出正文),
217
+ // 按 step 结算会 ① 把同一份内心重复加减,② 中间步 replyChars=0 被当成
218
+ // "正文冷 / 过短"触发**重罚**。好感度是"这一轮她对这个人什么态度",必须按**回合**算。
219
+ }
220
+ catch (err) {
221
+ text.logger?.debug?.(`[four-source] 留档失败(忽略): ${err instanceof Error ? err.message : String(err)}`);
222
+ }
223
+ }
224
+ /**
225
+ * 好感度(A 值)**按回合结算**(2026-09-14 修)。
226
+ *
227
+ * 由出站在 `turn/end` 时调用一次,传入**整个回合**拼起来的思考与正文:
228
+ * · 内心 = 本回合全部 step 的 reasoning 拼接(默认不含工具参数,见 TENDENCY_INCLUDE_TOOL)
229
+ * · 表面 = 本回合全部 step 真正发出去的正文拼接
230
+ * 这样"内心拒绝 + 正文仍照顾 = 让步"才读得出来 —— 拆成单步读,前半段只有内心没有正文,
231
+ * 必然落进"重罚"分支(这正是当时把无辜群友扣 −0.12 的一半原因)。
232
+ *
233
+ * 键(`person:<openid>`)与出站时记下的"这一轮在跟谁说话"一致;没有对象就跳过。
234
+ */
235
+ export async function applyTurnAttitude(dataRoot, entry, text = {}) {
236
+ try {
237
+ if (!entry.attitudeKey)
238
+ return;
239
+ const think = String(text.think ?? '').trim();
240
+ const reply = String(text.reply ?? '').trim();
241
+ if (think === '' && reply === '')
242
+ return; // 空回合不留痕(与 noteTurnSignals 同口径)
243
+ const opts = { modelDir: text.modelDir, logger: text.logger };
244
+ const [innerTen, replyEmo] = await Promise.all([
245
+ think ? classifyTendency(think, opts) : Promise.resolve(undefined),
246
+ reply ? classifyEmo(reply, opts) : Promise.resolve(undefined),
247
+ ]);
248
+ applyAttitudeEvent(dataRoot, entry.attitudeKey, {
249
+ thinkTen: confidentLabel(innerTen),
250
+ replyEmo: confidentEmo(replyEmo),
251
+ replyChars: reply.length,
252
+ userEmo: entry.userEmo,
253
+ name: entry.attitudeName,
254
+ }, text.logger);
255
+ }
256
+ catch (e) {
257
+ text.logger?.debug?.(`[好感度] 回合结算失败(忽略): ${e instanceof Error ? e.message : String(e)}`);
258
+ }
259
+ }
260
+ //# sourceMappingURL=four-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"four-source.js","sourceRoot":"","sources":["../../src/features/four-source.ts"],"names":[],"mappings":"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"}
@@ -16,4 +16,6 @@ export declare function recordImageUrl(stickerDir: string, id: string, url: stri
16
16
  export declare function lookupImageUrl(stickerDir: string, idOrPath: string): string | undefined;
17
17
  /** 直接给图片文件路径也能查(内部自己推表情包目录) */
18
18
  export declare function lookupImageUrlByPath(imgPath: string): string | undefined;
19
+ /** QQ 链接 → 图库 id(查不到返回 undefined; 反向索引按 mtime/size 缓存) */
20
+ export declare function lookupStickerIdByUrl(stickerDir: string, url: string): string | undefined;
19
21
  //# sourceMappingURL=image-url-ledger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-url-ledger.d.ts","sourceRoot":"","sources":["../../src/features/image-url-ledger.ts"],"names":[],"mappings":"AAiBA,8BAA8B;AAC9B,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AASzD,aAAa;AACb,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED,uCAAuC;AACvC,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAahF;AAqDD,gDAAgD;AAChD,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIvF;AAED,+BAA+B;AAC/B,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE"}
1
+ {"version":3,"file":"image-url-ledger.d.ts","sourceRoot":"","sources":["../../src/features/image-url-ledger.ts"],"names":[],"mappings":"AAiBA,8BAA8B;AAC9B,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AASzD,aAAa;AACb,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED,uCAAuC;AACvC,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAahF;AAqDD,gDAAgD;AAChD,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIvF;AAED,+BAA+B;AAC/B,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE;AAKD,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAexF"}
@@ -130,4 +130,27 @@ export function lookupImageUrl(stickerDir, idOrPath) {
130
130
  export function lookupImageUrlByPath(imgPath) {
131
131
  return lookupImageUrl(stickerDirFromImagePath(imgPath), imgPath);
132
132
  }
133
+ // ── 反向查: QQ 链接 → 图库 id(省 token: 历史里那条几百字符的长链接能换成短标记/本地路径) ──
134
+ const revCache = new Map();
135
+ /** QQ 链接 → 图库 id(查不到返回 undefined; 反向索引按 mtime/size 缓存) */
136
+ export function lookupStickerIdByUrl(stickerDir, url) {
137
+ const u = String(url || '');
138
+ if (!/^https?:\/\//i.test(u))
139
+ return undefined;
140
+ const file = ledgerFileOfStickerDir(stickerDir);
141
+ let key = 'missing';
142
+ try {
143
+ const st = statSync(file);
144
+ key = `${st.mtimeMs}:${st.size}`;
145
+ }
146
+ catch { /* 没有台账 */ }
147
+ const hit = revCache.get(file);
148
+ if (hit && hit.key === key)
149
+ return hit.rev.get(u);
150
+ const rev = new Map();
151
+ for (const it of loadAll(file))
152
+ rev.set(it.url, it.id); // 后出现的覆盖 = 最新
153
+ revCache.set(file, { key, rev });
154
+ return rev.get(u);
155
+ }
133
156
  //# sourceMappingURL=image-url-ledger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-url-ledger.js","sourceRoot":"","sources":["../../src/features/image-url-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAElE,8BAA8B;AAC9B,MAAM,CAAC,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAEzD,sBAAsB;AACtB,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,4BAA4B;AAC5B,MAAM,aAAa,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAIxC,aAAa;AACb,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,OAAO,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAC5C,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IACxC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,EAAU,EAAE,GAAW;IACxE,MAAM,GAAG,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAAE,OAAO;IAC7D,MAAM,IAAI,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAW,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,sBAAsB;IAChC,CAAC;IACD,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,aAAa;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;AAC1B,CAAC;AAED,kDAAkD;AAClD,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;IACtC,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe;QACxD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACtB,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACvG,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;AAC1B,CAAC;AAED,gBAAgB;AAChB,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAY,EAAE,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAU,CAAC;YACjC,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5H,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6CAA6C;AAC7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuD,CAAC;AAE7E,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,GAAG,GAAG,SAAS,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1B,GAAG,GAAG,GAAG,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACxB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,KAAK,MAAM,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB;IAC7E,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,QAAgB;IACjE,MAAM,EAAE,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IAC1B,OAAO,WAAW,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,OAAO,cAAc,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"image-url-ledger.js","sourceRoot":"","sources":["../../src/features/image-url-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /** 保留天数(14 天: 够出"本周"和"上周对比") */
2
+ export declare const KEEP_DAYS = 14;
3
+ export interface DayCell {
4
+ name?: string;
5
+ msgs: number;
6
+ mentions: number;
7
+ replies: number;
8
+ imgs: number;
9
+ }
10
+ /** 记一条(每条群消息调一次): key = `group:<gid>|<senderId>` */
11
+ export declare function touchDaily(dataRoot: string, gid: string, senderId: string, opts?: {
12
+ name?: string;
13
+ mention?: boolean;
14
+ reply?: boolean;
15
+ img?: boolean;
16
+ }): void;
17
+ export interface WeeklyRow {
18
+ key: string;
19
+ name?: string;
20
+ msgs: number;
21
+ mentions: number;
22
+ replies: number;
23
+ imgs: number;
24
+ /** 有互动的天数(体现"常来"还是"来一次爆刷") */
25
+ activeDays: number;
26
+ }
27
+ /** 汇总最近 days 天(默认 7)的每人数据, 按 msgs 降序 */
28
+ export declare function weeklyRows(dataRoot: string, days?: number, now?: number): WeeklyRow[];
29
+ /** 台账文件路径(脚本/面板用) */
30
+ export declare function ledgerPathOf(dataRoot: string): string;
31
+ //# sourceMappingURL=intimacy-ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intimacy-ledger.d.ts","sourceRoot":"","sources":["../../src/features/intimacy-ledger.ts"],"names":[],"mappings":"AAmBA,gCAAgC;AAChC,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AA4CD,oDAAoD;AACpD,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9E,IAAI,CAgBN;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wCAAwC;AACxC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAI,EAAE,GAAG,SAAa,GAAG,SAAS,EAAE,CAsBpF;AAED,qBAAqB;AACrB,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD"}