Repository navigation
Expand file tree
/
Copy pathconfig.yaml.example
More file actions
846 lines (823 loc) · 58.1 KB
/
Copy pathconfig.yaml.example
File metadata and controls
846 lines (823 loc) · 58.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
# ============================================================
# 灵桥 (Linkora) — 企业 AI 智能连接平台 · 配置文件示例
# ============================================================
#
# 使用方法:
# 1. 复制本文件为 config.yaml:cp config.yaml.example config.yaml
# 2. 修改以下配置项(带 * 为必填项;涉及密钥/密码的请务必修改)
# 3. 启动程序:python main.py --web 8080
# 4. 修改配置后无需重启,程序会自动热重载(Hot Reload)
#
# 配置结构总览:
# ★ platforms —— 多平台隔离主配置段(每个 IM 平台独立适配器/数据库/轮询器),运行期以本段为准
# ① dws / ② embedding / ③ llm / ③b llm_throttle / ④ logging / ⑤ memory
# ⑥ poller(legacy) / ⑦ rules / ⑧ safety / ⑨ rag / ⑩ skills / ⑪ dead_letter / ⑫ web / ⑬ tools / ⑭ storage(legacy)
# 说明:legacy 段(dws / poller / storage)由 config_manage 工具读取状态,请与 platforms 中对应平台保持一致。
# ============================================================
# ★ 多平台隔离配置(platforms)—— 主配置段
# - 每个 IM 平台一个独立配置:独立适配器 / 独立数据库(./data/<id>-ai.db) / 独立轮询器。
# - 运行期以本段为准;新增飞书/企微时在列表内追加对应条目
# (adapter_type: feishu / wecom,并配置 adapter.cli_path 为 lark-cli / wecom-cli)。
# - 下方 ① dws / ⑥ poller / ⑭ storage 为 legacy 兼容段(config_manage 读取),
# 值与本段 dingtalk 平台保持一致即可。
# ============================================================
platforms:
# —— 高级:多平台与按平台覆盖(override)——
# 本模板仅列单平台实例。生产可配置多个平台(钉钉/飞书/企微),platforms 为列表,
# 每个元素对应一个平台实例,adapter_type 决定适配器(见 config_models.PlatformConfig)。
# 每个平台支持 override 覆盖全局配置,键为 platform.<id>.override.{llm,rag,tools},
# 仅对当前平台生效;空值沿用全局。覆盖结构详见 config_models.PlatformConfig 的
# PlatformConfig.override / llm / rag / tools 字段。
# 参考骨架(脱敏,endpoint/密钥请按需从 live config.yaml 复制,切勿提交真实值):
# - id: feishu
# display_name: 飞书
# enabled: true
# adapter_type: feishu
# override:
# rag: { enabled: false } # 该平台关闭 RAG
# tools: { enable_kb_search: false } # 该平台禁用知识库搜索工具
# 另:safety.sensitive_words(敏感词过滤)已在下方 safety 段提供占位,按需填充。
- id: dingtalk
display_name: 钉钉
enabled: true
adapter_type: dingtalk
storage:
type: sqlite # 数据库类型(当前仅支持 sqlite)
path: ./data/linkora.db # 数据库文件路径(按平台隔离,勿与 legacy 段混淆)
backup_enabled: true # 是否启用自动备份
backup_dir: ./data/backups # 备份文件目录
backup_interval_hours: 24 # 备份间隔(小时),24 = 每天一次
backup_max_count: 5 # 保留最近多少份备份
backup_on_start: true # 启动时立即备份一次
decisions_retention_days: 14 # 决策追踪表留存天数(≤0 表示不按时间清理)
messages_retention_days: 90 # 消息记录留存天数(≤0 表示不清理)
doc_sync_interval_hours: 1 # 钉钉文档自动同步间隔(小时),≤0 禁用
poller:
# —— 基础轮询 ——
interval_seconds: 20 # 轮询间隔(秒)。stream 长连接启用时轮询仅为兜底,20s 兼顾实时性与 DWS 调用频率
# P0 Stream 长连接(v1.0.59+,需 dws event 子命令支持):true 启用 dws event
# +listen-im 实时接收消息,替代 5s 全量轮询,API 调用量降 90%+。默认 false(保留
# 轮询为主通道,兼容存量行为)。启用后轮询仍运行(兜底/历史回填),stream 消息
# 实时入队、每轮 drain 派发。stream_kinds 可选 all-direct(单聊)/all-group(群)/at-me(@我)。
stream_enabled: false
stream_kinds:
- all-direct
- all-group
unread_conversation_count: 50 # 单轮拉取的未读会话数上限
unread_convs_cache_ttl_seconds: 30 # 未读会话列表 TTL 缓存(秒):缓存期内复用上次结果,未读列表调用降到约 1/TTL 轮一次;新消息仍由 list-all 每轮全量拉取,不丢消息。0=每轮都拉
messages_per_conversation: 16 # 每个会话单次拉取的最大消息数
merge_window_seconds: 5 # 同会话多条消息在此时间内合并处理
history_window: 12 # 带入 LLM 上下文的历史消息条数(= max_recent + 2,原料窗需 > 近期条数才能触发 H2-A 异步摘要;feishu/wecom 同为 12)
history_days: 3 # 历史消息取最近 N 天
history_session_gap_minutes: 360 # 会话切分间隔:相邻历史消息间隔超此值视为新对话轮次(0=禁用切分)
max_processed_msg_ids: 500 # 跨轮次去重内存缓存上限(LRU)
first_run_ignore_older_than_minutes: 5 # 首次运行/重启后忽略超过 N 分钟的老消息(0=不忽略)
reply_cooldown_seconds: 10 # 同一会话回复冷却时间(秒),防止短时间反复回复
reply_shard_limit: 4000 # 单条回复分片上限(字符),超长自动分片发送
reply_send_min_interval: 0.2 # 两条回复最小发送间隔(秒),防刷屏
reply_send_rate_limit_backoff_seconds: 60.0 # 发送被限流后的退避时长(秒)
owner_present_cooldown_seconds: 600 # 真人在场冷却(秒):窗口内真人活跃则 AI 不插嘴,离场超时后接管
poll_new_message_max_age_hours: 24 # 轮询侧「新消息」年龄门槛(小时):超过则不触发 AI 回复。取 min(history_days, 本值/24);与 history_days(上下文取数窗口)解耦,防止去重漏标时把几天前的老消息重放成新消息。0=不额外收紧
suppress_when_owner_read: true # 已读闸门:DWS 判定会话已读(无未读)则 AI 不回;新未读消息仍照常回。失真漏回时设 false
read_grace_seconds: 3 # 已读反悔窗口(秒):回复生成好后先等这么久再发,期间你标记已读则直接取消发送(我已读的会话绝不发自动回复)。0=不等待
mark_read_after_process: true # 处理完后将该会话消息标记为已读
mark_read_delay_seconds: 120 # 回复发出后延迟 N 秒再标记会话已读(默认120):给追问留出未读窗口,避免 AI 自己标已读把后续消息吞掉。0=立即标记(旧行为)
# —— 背压 / 并发 ——
max_dispatch_per_cycle: 30 # 单轮最多派发给 handler 的消息数(0=不限制)
max_concurrent_replies: 4 # 同时进行的回复(LLM 调用)上限
reply_concurrency_timeout_seconds: 30 # 等待并发槽位超时(秒);超时降级串行,不丢消息
# —— list-all 主通道 ——
list_all_time_window_minutes: 30 # list-all 时间窗口(分钟)
list_all_first_run_minutes: 5 # list-all 首次运行时间窗口(分钟)
list_all_full_scan_interval_minutes: 60 # 飞书全量扫描间隔(分钟):每隔这么久做一次完整 +chat-list 翻页发现新会话;0=永不自动全量扫描
list_all_empty_alert_rounds: 6 # 连续 N 轮 list-all 零新消息则告警(0=关闭)
empty_poll_protection_minutes: 5 # 空转保护间隔(分钟)
# —— list-all 分页与窗口保护(防止宽时间窗每轮重扫全部历史、永远撞分页上限)——
list_all_max_pages: 50 # list-all 单轮分页硬上限(每页 limit 条,默认 100);0=不限制。原硬编码 20 在活跃群易触顶漏消息
list_all_max_window_days: 14 # list-all 实时轮询扫描窗口上限(天):把误配的 22 天等超宽窗钳制到最近 N 天。深度回填请走 sync_history
# —— 跳过策略 ——
skip_msg_types: # 直接跳过的消息类型(不处理)
- system
- app
- file
- call
- voice
- video
- read_receipt # 已读回执类系统通知([已读]/已读回执/英文 read receipt 等)
graceful_fallback_msg_types: [] # 优雅回退类型:当前 voice/video 已并入 skip_msg_types 彻底静默跳过,故留空
# 通知抑制(结构优先 + 窄签名):
# 绝大多数通知已由 msgType(skip_msg_types)+ 系统/机器人发送者(系统账号名单)结构层静默拦截。
# 本字段仅作「以真人身份推送的纯文本机器通知」的安全网:
# - 只写【机器生成物】的窄正则(固定模板/报错栈),绝不写宽泛裸词,以免误伤真人消息。
# - 默认空=不静默,交给 LLM 处理(如 U9C 报错由 AI 提炼要点)。
# - 例:r"^\d{4}-\d{2}-\d{2}\d+发货通知单[::]" 可精确命中某 ERP 推送。
skip_notification_patterns: []
# 按发送者 ID 精确静默机器人/三方应用账号(结构性静音,强于按名匹配)
skip_notification_sender_ids: []
# —— 图片 OCR ——
image_ocr_enabled: true # 启用后下载截图并 OCR,让 LLM 能"看懂"图片
image_temp_dir: ./data/tmp_images # OCR 临时下载目录(处理完即删)
# —— 多组织 / 跨组织 ——
target_org_corp_id: '' # 多组织环境下仅轮询该组织;留空=当前登录 profile 所属组织
# —— 会话黑名单容错 ——
blacklist_min_consecutive_failures: 3 # 群聊权限错误需连续失败达此次数才拉黑(0=立即拉黑)
blacklist_reconcile_every: 20 # 黑名单自愈对账间隔(轮数)
reconcile_probe_batch_size: 5 # 自愈每轮直接探测上限(轮转分批)
# —— 缓存 / 限频 ——
top_convs_cache_ttl_seconds: 180 # 置顶/最近会话列表缓存 TTL(秒)
min_conversation_poll_interval_seconds: 60 # 长尾会话最小抓取间隔(秒);未读会话不受影响
forced_fetch_min_interval_seconds: 30 # 未读(forced)会话抓取下限间隔(秒):不再每轮必打,per-conversation 只是健壮性冗余通道,新消息由 list-all 主通道每轮全量拉取。0=关闭下限
conv_info_negative_cache_ttl_seconds: 300 # 单聊对方解析(chat_conversation_info/联系人搜索)失败负缓存 TTL(秒):TTL 内不再重打元数据接口;消息仍由 list-all 投递、对方 ID 由消息 sender 兜底。0=失败后下轮即重试
chat_rate_limit_cooldown_seconds: 120 # 命中 RATE_LIMIT_ERROR 后暂停该平台 chat 抓取的冷却(秒):给服务端限流窗口留恢复时间,不丢消息
# —— 合规透明 ——
ai_tag_enabled: true # 发送时携带"由AI发送"标签(合规透明);false=与本人手发无区别
adapter: # 钉钉 → DwsConfig 字段
cli_path: dws # DWS CLI 可执行文件路径(默认 "dws" 表示使用 PATH 中的命令)
dry_run: false # true = 只模拟,不真正发送消息
profile: '' # DWS 登录 profile(多账号场景;默认空=默认账号)
retries: 2 # DWS 命令重试次数
timeout: 30 # DWS 命令超时(秒)
# ── 飞书 / 企业微信:可选平台,默认关闭 ──
# 启用步骤:① 安装对应 CLI(lark-cli / wecom-cli);② 取消下方注释;③ 把 enabled 改为 true。
# poller / storage / adapter 字段含义与上方 dingtalk 完全一致(钉钉段已逐行注释)。
# - id: feishu
# display_name: 飞书
# enabled: false
# adapter_type: feishu
# storage:
# type: sqlite
# path: ./data/feishu-ai.db
# backup_enabled: true
# backup_dir: ./data/backups
# backup_interval_hours: 24
# backup_max_count: 5
# backup_on_start: true
# decisions_retention_days: 14
# messages_retention_days: 90
# doc_sync_interval_hours: 1
# poller:
# interval_seconds: 20
# unread_conversation_count: 50
# messages_per_conversation: 16
# merge_window_seconds: 5
# history_window: 6
# history_days: 3
# history_session_gap_minutes: 360
# max_processed_msg_ids: 500
# first_run_ignore_older_than_minutes: 5
# reply_cooldown_seconds: 10
# owner_present_cooldown_seconds: 600
# poll_new_message_max_age_hours: 24
# suppress_when_owner_read: true
# mark_read_after_process: true
# mark_read_delay_seconds: 120
# max_dispatch_per_cycle: 30
# max_concurrent_replies: 4
# reply_concurrency_timeout_seconds: 30
# list_all_time_window_minutes: 30
# list_all_first_run_minutes: 5
# list_all_full_scan_interval_minutes: 60
# list_all_empty_alert_rounds: 6
# empty_poll_protection_minutes: 5
# list_all_max_pages: 50
# list_all_max_window_days: 14
# skip_msg_types:
# - system
# - app
# - file
# - call
# - voice
# - video
# - read_receipt
# graceful_fallback_msg_types: []
# skip_notification_patterns: []
# skip_notification_sender_ids: []
# image_ocr_enabled: true
# image_temp_dir: ./data/tmp_images
# target_org_corp_id: ''
# blacklist_min_consecutive_failures: 3
# blacklist_reconcile_every: 20
# reconcile_probe_batch_size: 5
# top_convs_cache_ttl_seconds: 180
# min_conversation_poll_interval_seconds: 60
# ai_tag_enabled: true
# adapter:
# cli_path: lark-cli # 已安装的飞书 CLI(lark-cli v1.0.72+)
# dry_run: false
# profile: ''
# retries: 2
# timeout: 30
# - id: wecom
# display_name: 企业微信
# enabled: false
# adapter_type: wecom
# storage:
# type: sqlite
# path: ./data/wecom-ai.db
# backup_enabled: true
# backup_dir: ./data/backups
# backup_interval_hours: 24
# backup_max_count: 5
# backup_on_start: true
# decisions_retention_days: 14
# messages_retention_days: 90
# doc_sync_interval_hours: 1
# poller:
# interval_seconds: 20
# unread_conversation_count: 50
# messages_per_conversation: 16
# merge_window_seconds: 5
# history_window: 6
# history_days: 3
# history_session_gap_minutes: 360
# max_processed_msg_ids: 500
# first_run_ignore_older_than_minutes: 5
# reply_cooldown_seconds: 10
# owner_present_cooldown_seconds: 600
# poll_new_message_max_age_hours: 24
# suppress_when_owner_read: true
# mark_read_after_process: true
# mark_read_delay_seconds: 120
# max_dispatch_per_cycle: 30
# max_concurrent_replies: 4
# reply_concurrency_timeout_seconds: 30
# list_all_time_window_minutes: 30
# list_all_first_run_minutes: 5
# list_all_full_scan_interval_minutes: 60
# list_all_empty_alert_rounds: 6
# empty_poll_protection_minutes: 5
# list_all_max_pages: 50
# list_all_max_window_days: 14
# skip_msg_types:
# - system
# - app
# - file
# - call
# - voice
# - video
# - read_receipt
# graceful_fallback_msg_types: []
# skip_notification_patterns: []
# skip_notification_sender_ids: []
# image_ocr_enabled: true
# image_temp_dir: ./data/tmp_images
# target_org_corp_id: ''
# blacklist_min_consecutive_failures: 3
# blacklist_reconcile_every: 20
# reconcile_probe_batch_size: 5
# top_convs_cache_ttl_seconds: 180
# min_conversation_poll_interval_seconds: 60
# ai_tag_enabled: true
# adapter:
# cli_path: wecom-cli # 已安装的企业微信 CLI(wecom-cli v0.1.9+)
# dry_run: false
# profile: ''
# retries: 2
# timeout: 30
# ── 平台级覆盖(可选 · 进阶)─────────────────────────────────────
# 每个平台块(与 storage / poller / adapter 同级)可内嵌 rag / llm / tools
# 三个可选覆盖块,用于覆盖全局对应配置。全部字段可选;省略该块或字段留空
# 均表示「沿用全局值」,无行为差异(代码见 src/config_models.py 的 PlatformConfig)。
# 典型用途:
# ① 按平台分模型控成本(如飞书用便宜模型、钉钉用主力模型)
# ② 按平台隔离知识库(不同 embedding 模型或 chunk 策略)
# ③ 按平台收窄工具集(如某平台关闭文件操作)
# 下方为「参考示例」(已注释,取消注释并填入即生效;只需保留要覆盖的字段):
# - id: feishu
# display_name: 飞书
# enabled: true
# adapter_type: feishu
# adapter: { cli_path: lark-cli } # 飞书 CLI(lark-cli v1.0.72+)
# rag: # 平台级 KB 覆盖(不配则沿用全局 rag)
# embedding_model: BAAI/bge-small-zh-v1.5
# chunk_size: 800
# chunk_overlap: 120
# chunk_hard_max: 1600
# llm: # 平台级 LLM 覆盖(不配则沿用全局 llm)
# provider: openai
# base_url: https://api.openai.com/v1
# api_key: sk-xxx
# model: gpt-4o-mini
# temperature: 0.3
# max_tokens: 2000
# timeout: 60
# fallback_model: gpt-4o
# fallback_api_key: sk-xxx
# fallback_base_url: https://api.openai.com/v1
# tools: # 平台级 Tools 覆盖(不配则沿用全局 tools)
# search_enabled: true
# file_ops_enabled: false
# enabled: true
# ============================================================
# ① DWS 适配器配置(钉钉 CLI 接口)—— legacy 兼容段(config_manage 读取)
# 值与上方 platforms.dingtalk.adapter 保持一致即可。
# ============================================================
dws:
cli_path: dws # * DWS CLI 可执行文件路径(默认 "dws" 使用 PATH 中的命令)
dry_run: false # 是否启用 dry_run 模式(true = 只模拟,不真正发送消息)
profile: '' # DWS 登录 profile 名称(多账号场景;默认空=默认账号)
retries: 2 # DWS 命令重试次数
timeout: 30 # DWS 命令超时时间(秒)
# ============================================================
# ② Embedding 模型配置(用于 RAG 知识库检索)
# ============================================================
embedding:
api_key: '' # Embedding API Key(使用 local 模式时可为空)
base_url: '' # Embedding API Base URL(使用 local 模式时可为空)
enabled: true # * 是否启用 Embedding(false = 禁用 RAG 知识库检索)
hf_token: '' # HuggingFace Token(用于下载模型,可选)
model: BAAI/bge-small-zh-v1.5 # * Embedding 模型名称(local 模式自动下载到 ~/.cache/huggingface;须与预建 FAISS 索引维度一致,默认 512 维)
provider: local # * 提供商类型(local = 本地模型,openai = OpenAI API 等)
top_k: 5 # 向量检索返回的候选数量(top-k)
offline: false # 是否纯离线(true=禁止联网下载,仅用本地缓存)
device: auto # 本地推理设备(auto/cpu/mps/cuda);MPS 会常驻约 1GB 驱动显存且无法回收,内存吃紧时改 cpu
heartbeat_interval: 300 # 心跳保活间隔(秒):模型就绪后周期 dummy 推理,防闲置被卸载;下限 30s
# ============================================================
# ③ LLM 客户端配置(大模型接口)
# ============================================================
llm:
advanced: # 高级限制参数(防止输出过长或过短)
hard_truncation_chars: 300 # 硬质截断字符数(极端超长安全网;与代码默认一致)
max_chars_daily_chat: 50 # 日常闲聊场景最大字符数(代码默认 50,避免过长)
max_chars_tech_issue: 100 # 技术问题场景最大字符数(代码默认 100)
rag_auto_inject: true # 是否自动注入 RAG 相关知识到 system prompt
rag_intent_only: true # 仅当 query 含文档/知识查询意图时才注入(闲聊/天气/问候等不注入;省 token、抗弱相关)
rag_min_similarity: 0.6 # 自动注入最低相似度门槛(收紧召回,避免弱相关内容进 prompt)
rag_max_results: 1 # 自动注入最多返回几条(越少越省 token,关键信息通常在最相关的前 1 条)
rag_max_content_chars: 1200 # 单条注入知识展示上限(>= 分块大小,避免答案被切)
rag_empty_fallback_enabled: true # 空-RAG 强制兜底:知识库无匹配时,架构层硬编码固定回复(防止 LLM 编造)
rag_empty_fallback_reply: "知识库中暂未收录相关信息,请联系IT部门或查阅内部文档确认。" # 空-RAG 兜底回复文案
low_confidence_handoff_enabled: true # 低置信度转人工/草稿(RAG 未命中时推主人审签)
low_confidence_threshold: 0.35 # RAG 最佳相似度低于此值视为低置信(默认放宽以减少草稿审签打扰)
# Phase 2 RAG 引文溯源+置信度页脚(默认关,灰度开;开启后回复末尾附「依据:《标题》(相关度88%)」)
citation_enabled: false # 引文页脚总开关(默认关;生产环境 config.yaml 已置 true 开启)
citation_in_group: false # 群聊是否也附引文(默认关,更克制)
citation_high_threshold: 0.75 # ≥此值标「依据」,[low,high) 标「参考」
citation_low_threshold: 0.5 # 相关度低于此值不追加页脚
citation_max_items: 2 # 页脚最多列几条引文
citation_show_score: false # 引文页脚是否显示相关度分数
citation_hide_generated: true # 隐藏「由 AI 生成」标记
max_input_tokens: 12000 # 单次请求最大输入 Token 数
rag_fallback_min_similarity: 0.2 # RAG 兜底最小相似度
rag_fallback_max_results: 2 # RAG 兜底最大返回条数
rag_max_retry_rounds: 1 # RAG 检索最大重试轮次
# RAG 严格问答模式(智能问答,默认关):开启后所有问答只依据知识库检索内容作答,
# 不使用通用大模型知识;知识库无相关内容时直接返回下方文案(不调用 LLM、不编造)
rag_strict_mode: false # 严格问答模式总开关
rag_strict_min_similarity: 0.5 # 严格模式召回相似度门槛(覆盖 rag_min_similarity)
rag_strict_max_results: 3 # 严格模式最多注入几条知识片段
rag_strict_no_hit_reply: "知识库中暂未收录相关内容,我无法凭已有信息作答。" # 未命中时的固定回复
# Phase 2 P2-6 BGE 本地离线重排(默认关;开启需本地已缓存 bge-reranker-base 权重)
rerank_enabled: false # 重排总开关(默认关;opt-in 高级特性:开启需本地 BGE 权重并引入推理开销,属有意默认关;当前运行实例已开,效果见 docs/phase2_citation_confidence_design.md §6)
rerank_model: BAAI/bge-reranker-base # 重排模型
rerank_offline: false # 纯离线加载(local_files_only)
rerank_top_k: 10 # 参与重排的候选窗口(0=全部)
rerank_timeout: 2.0 # 重排超时(秒),超时降级原始顺序
# H5/H6 + H2-A 历史分级注入 / 后台异步摘要阈值(未配置时全部走代码内保守默认值,向后兼容)
history_tiering_recent: 8 # 注入 LLM 的近期完整条数(默认 8=扩大风格学习窗口;调小如 4 可省 token 并激活 H2-A 异步摘要)
summary_async_enabled: true # H2-A 后台异步摘要总开关(True=主回复只快读缓存,摘要在 daemon 线程写回)
summary_max_age_seconds: 600 # H2-A 缓存摘要新鲜度窗口(秒),过期则降级并补算
summary_min_coverage_ratio: 0.6 # H2-A 缓存摘要需覆盖 older 段的至少该比例才采用
summary_max_messages: 0 # H2-A 透传 summarize_conversation 的 max_messages(0=不限制)
summary_min_older: 2 # H2-A older 段至少 N 条才压摘要(不足则仅注入 recent)
api_key: '' # * LLM API Key(必填)
base_url: '' # * LLM API Base URL(必填,如 https://api.deepseek.com/v1 或本地 http://localhost:11434/v1)
fallback_api_key: '' # 备用 API Key(主 API 失败时自动切换)
fallback_base_url: '' # 备用 API Base URL
fallback_model: '' # 备用模型(单模型,旧):主模型+主池全部失败时使用
fallback_model_pool: [] # 备用模型池(跨服务商兜底):主模型+主池全失败按列表顺序逐个尝试;401/403 立即终止
secondary_fallback_model: '' # 二级备用模型(主模型+主池+备用池全失败后的最后兜底)
secondary_fallback_model_pool: [] # 二级备用模型池(跨服务商,按列表顺序尝试;401/502 立即终止)
secondary_fallback_api_key: '' # 二级备用 API Key
secondary_fallback_base_url: '' # 二级备用 API Base URL
model: gpt-4o # * 使用的模型名称(如 deepseek-chat / gpt-4o / 本地 llama3)
model_pool: [] # 同服务商模型池(免费额度轮换):与主模型共用 base_url/api_key 的备选模型
provider: openai-compatible # * 提供商类型(openai-compatible = OpenAI 兼容接口)
system_prompt: '你是 {user_name} 的 {platform} 数字分身,代表 {user_name} 回复消息。语气专业、简洁、有礼貌。' # * System Prompt,可用 {user_name} / {platform}
temperature: 0.6 # 生成温度(0.0 = 确定性,1.0 = 创造性;0.6 平衡保真与稳定性)
max_tokens: 2048 # * 每次请求最大生成 Token 数
max_tool_rounds: 5 # * 工具调用最大轮次(防止死循环)
converge_after_tool_rounds: 3 # 连续 N 轮都在调工具则强制收敛(0=关闭)
max_retries: 3 # 主模型单轮最大重试次数(含首次;耗尽后切备用模型)
base_backoff: 2.0 # 退避基数(秒):第 n 次等待 base_backoff * 2**n
backoff_jitter: 0.3 # 退避 jitter 比例(0-1);0=关闭,>0 时等待时间在 [base, base*2^(n+1)] 随机取,避免惊群
rate_limit_cooldown: 30.0 # 模型触发 429 后的冷却期(秒);若服务端返回 Retry-After 则优先使用
timeout_cooldown: 10.0 # 模型重试耗尽仍失败后的短冷却期(秒),避免下一轮继续砸同一个模型
max_concurrency: 0 # 全局 LLM 并发上限(0=不限制);免费额度/低并发模型建议设为 3-5
timeout: 60 # LLM API 超时时间(秒)
few_shot_examples: [] # 本人语气 few-shot 样例(让数字分路口吻更像本人)
persona_style_prompt: '' # 主人沟通风格覆盖(留空则由历史消息自动画像兜底)
persona_history_max_versions: 10 # 画像历史版本最大保留数(超量滚动删除旧版本)
model_pricing: {} # 模型计费(如 {"gpt-4o": {"input": 0.005, "output": 0.015}}),用于成本看板
persona_style_prompts: {} # 多场景语气覆盖(覆盖单一 persona_style_prompt),如 {"正式": "...", "轻松": "..."}
dynamic_few_shot: false # 动态 few-shot:按场景检索主人原话注入 system prompt(提升口吻还原度)
dynamic_few_shot_n: 4 # 检索注入的最像原话条数
dynamic_few_shot_method: hybrid # trigram / embedding / hybrid(默认 hybrid,零额外开销)
backtest_judge_loose: false # 回测还原度评委宽松口径(仅影响 /api/persona/backtest 打分,不影响真实回复)
brevity_hard_cap: 0 # 回复硬截断上限(0=沿用 hard_truncation_chars;正数覆盖普通回复截断)
# ============================================================
# ③b 后台 LLM 任务限速(对话摘要 / 记忆提取)—— 保护免费额度
# ============================================================
llm_throttle:
enabled: true # 是否启用后台限速
background_min_interval_seconds: 20 # 活跃时两次后台 LLM 调用最小间隔(秒)
idle_threshold_seconds: 300 # 多久无真实消息处理算"空闲"
idle_min_interval_seconds: 180 # 空闲时两次后台调用最小间隔(秒)
rate_limit_backoff_seconds: 600 # 主模型触发 429/超时时后台任务暂停时长(秒)
extract_memory_cooldown_seconds: 600 # 同一会话记忆提取最小冷却(秒)
extract_memory_min_new_chars: 30 # 本轮新增内容低于此字符数则不提取记忆
max_summaries_per_cycle: 20 # 单周期最多处理的摘要会话数
summary_history_limit: 40 # 摘要时最多取的非归档近期消息条数
# ============================================================
# ④ 日志配置
# ============================================================
logging:
file: ./logs/linkora.log # 日志文件路径(相对于项目根目录)
level: info # 日志级别(debug / info / warning / error)
max_backups: 7 # 最大备份文件数(超过后自动删除最旧的)
max_size_mb: 50 # 单个日志文件最大大小(MB)
# ============================================================
# ⑤ 记忆管理配置(长期记忆清理、检索与对话摘要)
# ============================================================
memory:
cleanup: # 记忆清理策略
enabled: true # 是否启用自动清理
check_interval_days: 7 # 清理检查间隔(天)
max_age_days: 90 # 记忆最大保留天数(超过后标记过期)
min_similarity_threshold: 0.3 # 相似度阈值(低于此值的记忆会被清理)
retrieval: # 记忆检索策略
min_similarity: 0.6 # 检索最小相似度阈值(低于此值的结果会被过滤)
conversation_summary: # 对话摘要策略
enabled: true # 是否启用对话摘要
max_messages_per_conversation: 50 # 单会话参与摘要的最大消息数
summary_interval_hours: 24 # 摘要间隔(小时)
summary_ratio: 0.4 # 摘要压缩比
dynamic: # 动态(信号驱动)摘要:取代原固定 1 小时周期轮询(H2-B)
enabled: true # 是否启用动态摘要
check_interval_seconds: 60 # 轻量评估心跳(秒),仅做 DB 查询、不调 LLM
quiet_minutes: 10 # 会话静默达到该时长且有新内容 → 触发摘要
min_messages: 3 # 自上次摘要以来的未摘要消息数下限
max_messages_per_chat: 100 # 未摘要消息数达上限 → 立即摘要(防无限增长)
max_age_hours: 24 # 距上次摘要超过该时长且有新内容 → 刷新
scan_days: 7 # 扫描最近 N 天内有更新的会话
display: # 展示用全量摘要:专供 Web「对话摘要」页(与 H2-A/动态摘要解耦)
enabled: true # 是否启用;关闭则页面回退读 H2-A/动态摘要表
check_interval_seconds: 120 # 轻量评估心跳(秒),仅做 DB 查询、不调 LLM
min_messages: 4 # 会话消息数下限(不足则不生成展示摘要)
display_limit: 40 # 收集「近期全量消息」的窗口上限(覆盖整段对话,而非仅 older 段)
interval_hours: 2 # 同一会话两次展示摘要的最小间隔(小时)
freshness_seconds: 1800 # 已有覆盖充分的展示摘要在此时长内视为新鲜、跳过重摘要
scan_days: 7 # 扫描最近 N 天内有更新的会话
# 向量索引(F18 RAG 检索规模化):类型与幽灵向量自动清理
vector_index_type: flat # flat=精确暴力检索(默认);hnsw=近似检索,规模增长时提速显著
vector_index_hnsw_ef: 64 # HNSW efConstruction/efSearch(仅 hnsw 生效)
vector_phantom_rebuild_ratio: 0.3 # 幽灵向量占比超此阈值自动重建回收空间(0=禁用自动重建)
vector_cache_embeddings: true # 索引内缓存归一化 embedding,支撑精确重建
# ============================================================
# ⑦ 规则引擎配置(关键词回复、意图过滤、黑白名单)
# ============================================================
rules:
enabled: true # 是否启用规则引擎
regex_timeout_seconds: 1.0 # ReDoS 防护:用户/DB 正则单次匹配超时(秒);0/负=禁用
blacklist: # 黑名单(黑名单中的用户/群组消息不处理;置空 [] 即不生效)
groups: [] # 黑名单群组 ID 列表
users: # 黑名单用户名称列表
- 张三
whitelist: # 白名单(仅处理白名单中的用户/群组;空=不启用)
enabled: false # 是否启用白名单模式
groups: [] # 白名单群组 ID 列表
users: [] # 白名单用户名称列表
keywords: # 关键词自动回复(匹配到关键词直接回复,不调 LLM)
# 仅匹配「纯问候」消息,避免命中嵌入在业务请求里的 "您好"
# (如 "徐工您好,麻烦调整下流程人员..." 会误触发此回复)。
- match: '\A\s*(在吗|在不在|您好)[!。??\s]*\Z' # 匹配的正则表达式
reply: 在的,请问有什么事? # 自动回复内容(可用 {now} 变量插入当前时间)
stop_words: # 停用词(消息仅含这些词时不触发 LLM)
- 好的, 嗯, 哦
- 谢谢, 感谢, 请问, 麻烦, 帮我
- 你好, 您好, 请, 劳驾
keyword_denylist: # 高频关键词黑名单:从词云强制剔除的机器生成 token
- dingtalkclient
- mobilelink
- dingtalk
- mobile
- client
- link
- oauth
- callback
- redirect
- android
- ios
- robot
- webbot
- miniapp
intent_filter: # 意图过滤:识别并跳过无业务价值的消息
enabled: true
pure_thank_max_length: 20 # 纯感谢消息最大长度(超过可能含业务内容)
pure_ack_max_length: 10 # 纯确认收到最大长度
business_ratio_threshold: 0.3 # 业务关键词占比阈值(低于则视为主要是感谢)
thank_you: # 感谢类关键词
- 谢谢
- 感谢
- 辛苦了
- 多谢
acknowledge: # 确认收到类关键词
- 收到
- 好的
- 明白
- 知道了
- 了解
closing: # 结束语类关键词
- 再见
- 拜拜
- 晚安
- 先忙了
polite: # 礼貌开场类关键词
- 你好
- 您好
- 在吗
- 请问
compliment: # 称赞/夸奖类关键词(扩充子型)
- 厉害
- 太棒了
- 666
- yyds
smalltalk: # 闲聊/寒暄类关键词(扩充子型)
- 在忙吗
- 最近好吗
- 吃饭了吗
emotion: # 情绪/感叹类关键词(扩充子型)
- 哈哈
- 无语
- 服了
- emo
business_keywords: # 业务关键词(用于判断消息是否含业务内容)
- 问题
- 错误
- 故障
- 怎么
- 如何
- 为什么
- 帮我
- 配置
- 设置
- 安装
- 排查
- 解决
- 查询
- 审批
- 账号
- 密码
- 权限
- 登录
- 接口
- 服务
- 系统
- 数据
- 文档
- 资料
- 文件
# ============================================================
# ⑧ 安全配置(敏感词过滤和默认回复)
# ============================================================
safety:
default_fallback: 抱歉,我暂时无法回答这个问题。 # 默认兜底回复(LLM 处理失败或返回空时使用)
media_fallback_text: 请发文字,我暂时无法处理语音/视频消息,谢谢理解~ # 媒体类型优雅回退文案
sensitive_words: [] # 敏感词列表(回复内容包含这些词时会被过滤)
# ============================================================
# ⑨ RAG 知识库分块配置
# ============================================================
rag:
chunk_size: 500 # 分块软目标/上限参考(字符数)
chunk_overlap: 50 # 分块重叠大小(字符数)
# chunk_hard_max: 1000 # 安全天花板(字符数);留空=chunk_size*2
# # 仅拦病态超长单元,建议 < embedding 模型字符容量
# llm_clean_enabled: true # 入库文档用 LLM 语义清洗(正则作预清洗/回退)
# llm_clean_max_chars: 8000 # 单次 LLM 清洗字符上限;超长文档按段落分片
# ============================================================
# ⑩ 技能引擎配置(Skills)
# ============================================================
skills:
enabled: true # 是否启用技能引擎
auto_activate: true # 是否允许关键词自动激活技能
semantic_routing: true # Phase 2 语义路由:max(关键词命中, 语义相似度×weight)
semantic_skill_threshold: 0.40 # 技能语义命中阈值(余弦相似度,0~1)
combo_enabled: true # Phase 3 组合激活:接近平局的多个 composable 技能同时激活
combo_gap: 0.12 # 平局判定阈值(top1 - top2 <= combo_gap 视为接近平局)
hot_reload: false # 生产默认关闭:避免运行时自动加载 skills 目录新文件(供应链风险);开发态显式开启
hot_reload_interval: 15.0 # 热加载轮询间隔(秒)
ai_intent_generation_enabled: false # AI 意图词生成(默认关闭,避免意外消耗 LLM 额度)
module_hot_reload: false # 技能模块运行时热重载(自动重载 skills 模块)
module_hot_reload_interval: 5.0 # 模块热重载轮询间隔(秒)
# ============================================================
# ⑩½ SkillHub 市场(skill 榜单)配置
# ============================================================
skillhub:
# 是否允许 Web 运行时自动拉取并执行 skillhub 安装脚本。
# 安全默认关闭——开启后仅当 skillhub CLI 未安装时,才会下载白名单内的安装脚本
# 并做 SHA256 钉值校验后以非 shell 方式执行(钉值经环境变量 SKILLHUB_INSTALL_SHA256 注入,
# 或钉死在 web/dependencies.py)。生产环境建议由 Dockerfile/部署脚本预装 CLI,保持关闭。
auto_install: false
# ============================================================
# ⑩¾ OA 审批转发处理策略(钉钉专属)
# ============================================================
oa_approval:
enabled: true # 是否启用 OA 审批转发处理
urge_reply_text: 请稍候,审批正在处理中,请耐心等待。 # 催审批固定回复话术(不调 LLM)
question_markers: # 含以下标记视为「提问」转交 LLM 正常处理
- "?"
- "?"
- 怎么
- 为什么
- 为何
- 什么情况
- 什么意思
- 合理吗
- 对吗
- 对不对
- 帮我看
- 帮我分析
- 分析一下
- 查一下
- 看看
- 哪
- 如何
action_markers: # 含以下标记视为「动作指令」调用审批工具(transfer_approval 等)
- 转给
- 转交
- 转由
- 移交
- 交接
- 离职
- 换人
- 代批
- 帮忙批
- 改成
- 转移给
# ============================================================
# ⑩⅔ OCR 后处理管线
# ============================================================
ocr_postprocess:
enabled: true # 是否启用 OCR 后处理
min_chars: 5 # 有效字符数阈值,低于此值跳过不投喂 LLM
enabled_steps: # 各清洗步骤独立开关
remove_invisible: true # 零宽/不可见控制字符剔除
dedup_punctuation: true # 连续重复标点压缩(>2 → 1)
remove_fillers: true # 口语填充词/语气词剔除
normalize_layout: true # 合并空行、去除首尾空白
cjk_spacing: false # 中文/英文/数字间加空格(默认关,避免改变原文排版)
# ============================================================
# ⑪ 死信队列(Dead Letter)—— LLM/发消息彻底失败时落库而非静默丢弃
# ============================================================
dead_letter:
enabled: true # 是否启用 DLQ(关闭则退回旧行为:仅回 fallback 文本)
# ============================================================
# ⑪-B 主动触达(P4-13):每日定时把近期对话摘要主动推送给主人
# ============================================================
# 默认关闭。开启后由后台 daemon 线程在每日 hour:minute(本地时区)触发一次:
# 汇总最近 lookback_hours 内、至多 max_conversations 个有缓存摘要的对话,生成中文
# 摘要经钉钉推送给主人(1:1)。复用既有对话缓存摘要,不额外消耗 LLM。
# 发送目标二选一:owner_user_id(钉钉 user_id)或 owner_open_dingtalk_id(open_id);
# 两者皆空则调度器不启动(fail-safe)。
proactive:
enabled: false # 主动触达总开关(默认关)
hour: 9 # 每日触发小时(0-23,本地时区)
minute: 0 # 每日触发分钟(0-59)
owner_user_id: "" # 钉钉 user_id(与下面 open_dingtalk_id 二选一)
owner_open_dingtalk_id: "" # 钉钉 open_dingtalk_id;两者皆空则不启动
lookback_hours: 24 # 滚动回溯窗口(小时):取过去 N 小时内有更新的对话,跨自然日生效(如 17:30 推送覆盖昨日 17:30→今日 17:30)
max_conversations: 10 # 单次摘要最多纳入的对话数
max_summary_chars: 200 # 单条对话摘要截断长度(字符)
# ============================================================
# ⑪-C 摘要连续性补跑(P4-14):启动检测停机时长,按自然日补齐遗漏摘要
# ============================================================
# 默认开启。进程中断期间 RollingSummary / ProactiveDigest 不写缓存也不补跑错过的那一天;
# 本机制启动读主库 meta.last_run_at,算停机天数,把遗漏窗口切成自然日,对每天有消息的会话
# 现场调 LLM 生成当日摘要,写回 conversation_summaries(与正常周期同源同格式),使「当天 /
# 近七天」摘要连续完整。与 ProactiveDigest 共用同一份缓存,补跑后主动推送的近七天视图自然补全。
# 失败全部非致命,绝不拖垮主回复链路;补跑后刷新 last_run_at 防误判持续停机。
summary_backfill:
enabled: true # 是否启用启动期摘要补跑(默认开)
max_backfill_days: 14 # 最多补跑最近 N 天(防止极端停机刷爆 LLM)
min_messages_per_chat: 3 # 单会话某日不足此条数则跳过(避免噪声摘要)
max_summary_age_days: 7 # 摘要时间上限:早于「现在-N天」的旧自然日/旧消息不再生成摘要(省 token);0=不启用
# ============================================================
# ⑫ Web 管理后台配置
# ============================================================
web:
port: 8080 # 监听端口
host: 127.0.0.1 # 监听地址(安全默认仅本机回环;公网访问请经反代+认证)
auth_enabled: true # 是否开启认证(安全默认开启;关闭=管理后台裸奔,高危)
auth_username: admin # * 登录用户名
auth_password: 'Admin@P0sw0rd' # * 出厂默认登录密码(账号 admin)——仅供本地/内网开箱即用;公网暴露(下方 host=0.0.0.0)时**必须**先改强密码,否则启动报错。支持明文(legacy)或 PBKDF2 哈希(pbkdf2_sha256$...,推荐);生成:python -c "from web.auth_middleware import hash_password; print(hash_password('你的密码'))"。弱口令/空值/出厂口令在公网暴露下均 fail-closed 拒绝启动 # gitleaks:allow
jwt_secret: '' # * JWT 签名密钥——生产务必设置固定高熵值;留空则运行时生成临时随机密钥(重启失效)
# ============================================================
# ⑬ 工具配置(可用工具和速率限制)
# ============================================================
tools:
enabled: true # 是否启用工具调用
allow_skill_tools: true # 是否允许技能引擎自动包装未声明白名单的技能为标准 Tool
expose_all_tools: true # 是否每轮全量暴露所有工具(详见 tool_routing_mode)
tool_routing_mode: smart # 工具按需暴露策略:smart(推荐) / all / keyword
semantic_routing: true # 语义路由:substring 未命中时用 embedding 兜底补充相关工具
semantic_tool_threshold: 0.42 # 工具语义命中阈值(余弦相似度,0~1)
kb_search_enabled: true # 是否注册 RAG 检索工具 kb_search(false = 彻底关闭 RAG 检索能力)
block_outbound_to_third_party: true # 硬拦截 AI 主动联系第三方(安全默认开)
max_tool_seconds: 120.0 # 工具外层统一超时(秒):防止单工具卡死永久阻塞共享线程;0/负=不启用护栏
# 注意:从下方 available 里删掉 kb_search 只是不向 LLM 暴露 schema,
# 工具本身仍会被注册;要完全不注册必须用本开关。
available: # 启用的工具列表
- kb_search # 知识库语义检索(RAG)
- send_message # 发送消息
- search_doc # 搜索文档
- get_doc_content # 获取文档内容
- search_contact # 搜索联系人
- get_calendar_events # 获取日历事件
- create_todo # 创建待办事项
- schedule_meeting # 会议协调(冲突/空闲/建议时间)
- list_todos # 列出待办事项
- complete_todo # 完成待办事项
- recall_memory # 回忆长期记忆
- save_memory # 保存长期记忆
- web_search # 联网搜索
- get_weather # 获取天气信息
- system_status # 系统状态查询
- message_stats # 消息统计
- keyword_rules # 关键词规则管理
- config_manage # 配置管理
- get_unread # 获取未读消息
- get_conversation_info # 获取会话信息
- search_messages # 搜索消息
- get_my_profile # 获取我的资料
- list_orgs # 列出组织
- get_current_org # 获取当前组织
- transfer_approval # 转交审批任务(原审批人离职等场景,仅钉钉)
- get_attendance # 获取考勤
- send_ding # 发送钉(DING)
- upload_image # 上传图片
- list_minutes # 列出 AI 听记/会议纪要(仅钉钉)
- get_minutes # 获取听记摘要/待办/转写/信息(仅钉钉)
- wiki_space_list # 列出钉钉知识库空间(仅钉钉)
- wiki_space_search # 在知识库中搜索空间(仅钉钉)
- wiki_node_list # 列出知识库空间下的节点(仅钉钉)
- wiki_node_search # 在知识库内搜索节点(仅钉钉)
- approval_list_forms # 列出审批表单模板(仅钉钉)
- approval_search_forms # 搜索审批表单模板(仅钉钉)
- approval_get_detail # 查看审批实例详情(仅钉钉)
- approval_get_form_schema # 查看审批表单字段配置(仅钉钉)
- approval_list_pending # 查询待我审批(仅钉钉)
- approval_list_tasks # 查询审批实例下的审批任务(仅钉钉)
- approval_list_initiated # 查询已发起审批记录(仅钉钉)
- approval_list_executed # 查询我已处理的审批(仅钉钉)
- approval_list_org # 管理员视角查全组织审批实例(别人转发的流程用这个查,仅钉钉)
- approval_list_cc # 查询抄送我的审批(仅钉钉)
- list_reports # 列出钉钉日志(日报/周报,仅钉钉)
- get_report_detail # 读取单份钉钉日志正文(仅钉钉)
- list_report_templates # 搜索钉钉日志模板(仅钉钉)
- search_enterprise_content # 跨类型语义检索企业内容(仅钉钉)
- search_enterprise_behavior # 追溯企业行为记录(仅钉钉)
rate_limit: # 工具速率限制(防止滥用,单位:每小时)
create_todo: { per_hour: 20 }
get_attendance: { per_hour: 20 }
get_conversation_info: { per_hour: 60 }
get_current_org: { per_hour: 30 }
transfer_approval: { per_hour: 10 }
get_my_profile: { per_hour: 30 }
get_unread: { per_hour: 60 }
get_weather: { per_hour: 30 }
list_orgs: { per_hour: 30 }
search_messages: { per_hour: 60 }
send_ding: { per_hour: 20 }
send_message: { per_hour: 30 }
upload_image: { per_hour: 30 }
web_search: { per_hour: 50 }
# ============================================================
# ⑭ 存储配置(数据库)—— legacy 兼容段(config_manage 读取)
# 值与上方 platforms.dingtalk.storage 保持一致即可。
# ============================================================
storage:
path: ./data/linkora.db # 数据库文件路径(按平台隔离)
type: sqlite # 数据库类型(当前仅支持 sqlite)
backup_enabled: true # 是否启用自动备份
backup_dir: ./data/backups # 备份文件目录
backup_interval_hours: 24 # 备份间隔(小时)
backup_max_count: 7 # 保留最近多少份备份
backup_on_start: true # 启动时立即备份一次
decisions_retention_days: 14 # 决策追踪表留存天数(≤0 表示不按时间清理)
messages_retention_days: 90 # 消息记录留存天数(≤0 表示不清理)
doc_sync_interval_hours: 1 # 钉钉文档自动同步间隔(小时),≤0 禁用
busy_timeout_ms: 20000 # SQLite 写锁等待窗口(毫秒)
# 双进程架构(run_linkora.py 默认拉起 web + worker)下 web 与 worker 会同时写
# 同一批库,跨进程写锁争用会报 "database is locked"。本值让短时锁竞争等过去。
# ⚠️ 治标不治本:根治请用 `scripts/run_linkora.py --single-process` 合并为单进程。
# ⚠️ 对「陈旧读快照」类立即失败无效(那种只能丢弃连接重建,见 write_with_retry)。
# ============================================================
# 配置文件结束
# ============================================================
# 提示:
# 1. 所有带 * 的配置项为必填项(密钥/密码请务必修改,勿留空或默认值)
# 2. 列表类型的配置项(如 skip_notification_patterns)可留空([])
# 3. 布尔类型配置项:true / false(小写)
# 4. 修改配置后无需重启,程序会自动热重载(Hot Reload)
# 5. 多平台:运行期以 platforms 段为准;legacy 段(dws/poller/storage)仅供 config_manage 工具读取,保持一致即可
# ============================================================