codebee 0.1.103 → 0.1.104

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 (119) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE +21 -21
  3. package/README.md +2 -3
  4. package/app/core/acceptance.py +100 -100
  5. package/app/core/acp_client.py +457 -457
  6. package/app/core/aiflavor.py +197 -197
  7. package/app/core/analytics.py +38 -38
  8. package/app/core/artifacts.py +148 -148
  9. package/app/core/assets.py +110 -110
  10. package/app/core/attachments.py +623 -623
  11. package/app/core/audit.py +30 -30
  12. package/app/core/backend_profiles.py +188 -188
  13. package/app/core/backup.py +470 -470
  14. package/app/core/beekeeper.py +183 -183
  15. package/app/core/benchstore.py +102 -102
  16. package/app/core/bookmeta.py +1036 -1036
  17. package/app/core/bookmeta_catalog.py +180 -180
  18. package/app/core/branching.py +137 -137
  19. package/app/core/capability.py +144 -144
  20. package/app/core/chaptersafe.py +32 -32
  21. package/app/core/cleanup.py +303 -303
  22. package/app/core/command_auth.py +302 -302
  23. package/app/core/compaction.py +201 -201
  24. package/app/core/contracts.py +255 -255
  25. package/app/core/covergen.py +356 -356
  26. package/app/core/defectretro.py +43 -43
  27. package/app/core/diagnostics.py +114 -114
  28. package/app/core/dispatch_log.py +128 -128
  29. package/app/core/env_scrub.py +85 -85
  30. package/app/core/errorlog.py +137 -137
  31. package/app/core/eval_matrix.py +91 -91
  32. package/app/core/evaluation.py +174 -174
  33. package/app/core/failure_notify.py +290 -290
  34. package/app/core/flow_graph.py +33 -33
  35. package/app/core/goal_service.py +167 -167
  36. package/app/core/health.py +389 -389
  37. package/app/core/history.py +38 -38
  38. package/app/core/hooks.py +162 -162
  39. package/app/core/knowledge_pipeline.py +86 -86
  40. package/app/core/manager.py +2385 -2385
  41. package/app/core/mocks.py +64 -64
  42. package/app/core/notify.py +201 -201
  43. package/app/core/novel_quality.py +285 -181
  44. package/app/core/openapi.py +217 -217
  45. package/app/core/operations.py +228 -228
  46. package/app/core/paihang.py +145 -145
  47. package/app/core/pipeline.py +55 -3
  48. package/app/core/planner.py +7 -0
  49. package/app/core/portguard.py +111 -111
  50. package/app/core/presence.py +77 -77
  51. package/app/core/preview.py +293 -293
  52. package/app/core/project_memory.py +206 -206
  53. package/app/core/prompt_guard.py +78 -78
  54. package/app/core/publish/__init__.py +7 -7
  55. package/app/core/publish/auto.py +659 -659
  56. package/app/core/publish/chaprows.py +138 -138
  57. package/app/core/publish/flows-fanqie-calibrated.json +442 -442
  58. package/app/core/publish/manager.py +1185 -1185
  59. package/app/core/publish/qimao.py +193 -193
  60. package/app/core/publish/volumes.py +108 -108
  61. package/app/core/publish/ws.py +139 -139
  62. package/app/core/quality_gate.py +201 -201
  63. package/app/core/redact.py +38 -38
  64. package/app/core/repeat_guard.py +129 -129
  65. package/app/core/retrieval.py +137 -137
  66. package/app/core/sandbox_runtime.py +95 -95
  67. package/app/core/selfupdate.py +384 -384
  68. package/app/core/session_log.py +161 -161
  69. package/app/core/sessions.py +312 -312
  70. package/app/core/settings.py +215 -215
  71. package/app/core/settings_schema.py +282 -282
  72. package/app/core/share_page.py +114 -114
  73. package/app/core/skill_scan.py +139 -139
  74. package/app/core/skillpacks/market/character-bible.md +66 -66
  75. package/app/core/skillpacks/market/code-risk-checklist.md +58 -58
  76. package/app/core/skillpacks/market/git-workflow.md +57 -57
  77. package/app/core/skillpacks/market/release-notes.md +72 -72
  78. package/app/core/skillpacks/market/weekly-report.md +71 -71
  79. package/app/core/skillpacks/market/worldview-consistency.md +70 -70
  80. package/app/core/step_runner.py +132 -132
  81. package/app/core/story_tracking.py +275 -275
  82. package/app/core/task_compile.py +199 -199
  83. package/app/core/telemetry.py +292 -292
  84. package/app/core/tlsctx.py +64 -64
  85. package/app/core/token_meter.py +147 -147
  86. package/app/core/tool_outputs.py +107 -107
  87. package/app/core/tracing.py +207 -207
  88. package/app/core/upstream.py +41 -41
  89. package/app/core/usage.py +1038 -1038
  90. package/app/core/volumes.py +389 -389
  91. package/app/core/webhooks.py +89 -89
  92. package/app/core/wxdigest.py +865 -865
  93. package/app/core/zentao.py +2692 -2692
  94. package/app/mcp_server.py +244 -244
  95. package/app/pick_dialog.py +110 -110
  96. package/app/ui/artdiff.js +74 -74
  97. package/app/ui/icons/bee.svg +79 -79
  98. package/app/ui/manifest.json +16 -16
  99. package/app/ui/qrcode.js +2297 -2297
  100. package/bin/tutti.js +147 -147
  101. package/package.json +1 -1
  102. package/tools/wx_reader.py +261 -261
  103. package/app/.playwright-cli/console-2026-09-23T08-26-03-635Z.log +0 -88
  104. package/app/.playwright-cli/page-2026-09-23T08-26-03-845Z.yml +0 -126
  105. package/app/.playwright-cli/page-2026-09-23T08-29-44-203Z.png +0 -0
  106. package/app/.playwright-cli/page-2026-09-23T08-35-42-046Z.yml +0 -210
  107. package/app/.playwright-cli/page-2026-09-23T08-36-52-858Z.png +0 -0
  108. package/app/.playwright-cli/page-2026-09-23T08-37-33-938Z.png +0 -0
  109. package/app/.playwright-cli/run-detail-after.png +0 -0
  110. package/app/output/_createbook_body.json +0 -1
  111. package/app/output/_probe_fq_click.py +0 -50
  112. package/app/output/_probe_fq_form.py +0 -42
  113. package/app/output/_probe_fq_modal.py +0 -55
  114. package/app/output/_probe_fq_points.py +0 -71
  115. package/app/output/_probe_fq_submit.py +0 -34
  116. package/app/output/_probe_fq_watch.py +0 -62
  117. package/app/output/workbench-clean-preview.jpg +0 -0
  118. package/app/output/workbench-reference-render.png +0 -0
  119. package/app/output/workbench-shell.png +0 -0
@@ -1,71 +1,71 @@
1
- ---
2
- name: 周报晨报生成器守则
3
- note: 从任务与运行记录生成汇报:先取材再总结 / 晨报三段 / 周报四段 / 量化纪律与模板
4
- scopes:
5
- - "*"
6
- source: market
7
- market_id: weekly-report
8
- ---
9
-
10
- # 周报 / 晨报生成器守则(市场包)
11
-
12
- 适用:为个人或团队生成晨报(昨日 / 今日 / 阻塞)与周报(本周 / 风险 / 下周)。
13
- 第一原则:**先取材,再总结,不许凭印象编**。事实原料来自任务系统、运行记录、
14
- 提交历史与日志;生成器的工作是把原料提炼成「能支撑决策」的信息,不是文学创作。
15
-
16
- ## 一、取材清单(动笔前先收集)
17
- - 已完成:本周关闭的任务、成功结束的运行、合并的提交 / PR(git log --since 起止)。
18
- - 进行中:各任务当前状态、最近一次运行结论、卡在哪一步。
19
- - 信号类:评审打分、测试通过率、失败与重试次数、耗时的环比变化——量化的来源。
20
- - 未进系统的口头承诺 / 临时插活:单独列出并标注「口头事项」,不混进正式条目。
21
-
22
- ## 二、晨报结构(10 行以内,站着读完)
23
- - **昨日完成**:2-4 条,每条写一个**结果**(不是动作)。
24
- - **今日计划**:2-4 条,每条可验证(「提测搜索分页」,而不是「继续做搜索」)。
25
- - **阻塞**:0-2 条,每条带「需要谁 / 需要什么」;没有就写「无」,不硬凑。
26
-
27
- ## 三、周报结构
28
- 1. **本周一句话**:本周最重要的结果或结论。上级只读这一行也能掌握大局。
29
- 2. **关键进展**:按目标 / 项目分组,每组 1-3 条;每条 = 结果 + 量化 + 对照计划
30
- (提前 / 按期 / 延期几天)。流水账禁止——「周一做了 A,周二做了 B」是日志,
31
- 不是汇报。
32
- 3. **风险与阻塞**:每条 = 风险描述 + 影响面 + 需要的支持或缓解方案。
33
- **只报风险不给方案 = 把问题原样上交;报喜不报忧 = 把雷埋到下周。**
34
- 4. **下周计划**:2-5 条可验证的目标,与风险呼应,高风险项排前面。
35
-
36
- ## 四、写作纪律
37
- - **量化**:能带数字必带数字(章数、字数、通过率、耗时、条数);
38
- 「大量」「明显」「基本完成」这类模糊词出现即重写。
39
- - **结果导向**:写「完成了 X,达到 Y」;「在做 X」「推进中」放进计划或阻塞,不进步进展。
40
- - **动词开头、一条一意**:每条脱离上下文独立可懂。
41
- - **诚实纪律**:延期就写延期,附原因与新预计时间;数据缺失标注「缺」,不估算充数。
42
- - **篇幅纪律**:周报正文 ≤400 字(附录与链接不计);超了说明没提炼。
43
-
44
- ## 五、常见毛病对照(反例 → 正例)
45
- - 反例:「本周推进了 A 项目。」→ 正例:「A 项目完成搜索分页改造并提测,1 万条数据下翻页响应小于 200ms。」
46
- - 反例:「一切顺利。」→ 正例:「整体按期;联调依赖的 B 接口周三可用,已与对方确认。」
47
- - 反例:「风险:时间紧。」→ 正例:「风险:评审通过率低于阈值会触发返工,预计延期 2 天;已加排一轮预审。」
48
- - 反例:把 12 条流水账逐日列出 → 正例:归并成 3 条按目标分组的结果,逐日明细放附录链接。
49
-
50
- ## 六、周报模板(可直接复制)
51
- ```
52
- # 周报(MM.DD - MM.DD)
53
-
54
- 一句话:完成xxx,指标y环比+z%;主要风险:xxx。
55
-
56
- ## 关键进展
57
- - 【目标A】交付xxx(量化数据);对照计划:按期 / 延期n天
58
- - 【目标B】……
59
-
60
- ## 风险与阻塞
61
- - 风险:……;影响:……;需要:……(或已采取措施:……)
62
-
63
- ## 下周计划
64
- - ……
65
- ```
66
-
67
- ## 七、自检
68
- - [ ] 每个数字都能在任务 / 运行记录 / git log 里找到出处
69
- - [ ] 无「继续推进」「持续优化」这类无信息量条目
70
- - [ ] 风险条目全部带缓解方案或明确的求助对象
71
- - [ ] 下周计划每条都有可验证的完成标志
1
+ ---
2
+ name: 周报晨报生成器守则
3
+ note: 从任务与运行记录生成汇报:先取材再总结 / 晨报三段 / 周报四段 / 量化纪律与模板
4
+ scopes:
5
+ - "*"
6
+ source: market
7
+ market_id: weekly-report
8
+ ---
9
+
10
+ # 周报 / 晨报生成器守则(市场包)
11
+
12
+ 适用:为个人或团队生成晨报(昨日 / 今日 / 阻塞)与周报(本周 / 风险 / 下周)。
13
+ 第一原则:**先取材,再总结,不许凭印象编**。事实原料来自任务系统、运行记录、
14
+ 提交历史与日志;生成器的工作是把原料提炼成「能支撑决策」的信息,不是文学创作。
15
+
16
+ ## 一、取材清单(动笔前先收集)
17
+ - 已完成:本周关闭的任务、成功结束的运行、合并的提交 / PR(git log --since 起止)。
18
+ - 进行中:各任务当前状态、最近一次运行结论、卡在哪一步。
19
+ - 信号类:评审打分、测试通过率、失败与重试次数、耗时的环比变化——量化的来源。
20
+ - 未进系统的口头承诺 / 临时插活:单独列出并标注「口头事项」,不混进正式条目。
21
+
22
+ ## 二、晨报结构(10 行以内,站着读完)
23
+ - **昨日完成**:2-4 条,每条写一个**结果**(不是动作)。
24
+ - **今日计划**:2-4 条,每条可验证(「提测搜索分页」,而不是「继续做搜索」)。
25
+ - **阻塞**:0-2 条,每条带「需要谁 / 需要什么」;没有就写「无」,不硬凑。
26
+
27
+ ## 三、周报结构
28
+ 1. **本周一句话**:本周最重要的结果或结论。上级只读这一行也能掌握大局。
29
+ 2. **关键进展**:按目标 / 项目分组,每组 1-3 条;每条 = 结果 + 量化 + 对照计划
30
+ (提前 / 按期 / 延期几天)。流水账禁止——「周一做了 A,周二做了 B」是日志,
31
+ 不是汇报。
32
+ 3. **风险与阻塞**:每条 = 风险描述 + 影响面 + 需要的支持或缓解方案。
33
+ **只报风险不给方案 = 把问题原样上交;报喜不报忧 = 把雷埋到下周。**
34
+ 4. **下周计划**:2-5 条可验证的目标,与风险呼应,高风险项排前面。
35
+
36
+ ## 四、写作纪律
37
+ - **量化**:能带数字必带数字(章数、字数、通过率、耗时、条数);
38
+ 「大量」「明显」「基本完成」这类模糊词出现即重写。
39
+ - **结果导向**:写「完成了 X,达到 Y」;「在做 X」「推进中」放进计划或阻塞,不进步进展。
40
+ - **动词开头、一条一意**:每条脱离上下文独立可懂。
41
+ - **诚实纪律**:延期就写延期,附原因与新预计时间;数据缺失标注「缺」,不估算充数。
42
+ - **篇幅纪律**:周报正文 ≤400 字(附录与链接不计);超了说明没提炼。
43
+
44
+ ## 五、常见毛病对照(反例 → 正例)
45
+ - 反例:「本周推进了 A 项目。」→ 正例:「A 项目完成搜索分页改造并提测,1 万条数据下翻页响应小于 200ms。」
46
+ - 反例:「一切顺利。」→ 正例:「整体按期;联调依赖的 B 接口周三可用,已与对方确认。」
47
+ - 反例:「风险:时间紧。」→ 正例:「风险:评审通过率低于阈值会触发返工,预计延期 2 天;已加排一轮预审。」
48
+ - 反例:把 12 条流水账逐日列出 → 正例:归并成 3 条按目标分组的结果,逐日明细放附录链接。
49
+
50
+ ## 六、周报模板(可直接复制)
51
+ ```
52
+ # 周报(MM.DD - MM.DD)
53
+
54
+ 一句话:完成xxx,指标y环比+z%;主要风险:xxx。
55
+
56
+ ## 关键进展
57
+ - 【目标A】交付xxx(量化数据);对照计划:按期 / 延期n天
58
+ - 【目标B】……
59
+
60
+ ## 风险与阻塞
61
+ - 风险:……;影响:……;需要:……(或已采取措施:……)
62
+
63
+ ## 下周计划
64
+ - ……
65
+ ```
66
+
67
+ ## 七、自检
68
+ - [ ] 每个数字都能在任务 / 运行记录 / git log 里找到出处
69
+ - [ ] 无「继续推进」「持续优化」这类无信息量条目
70
+ - [ ] 风险条目全部带缓解方案或明确的求助对象
71
+ - [ ] 下周计划每条都有可验证的完成标志
@@ -1,70 +1,70 @@
1
- ---
2
- name: 世界观设定一致性台账守则
3
- note: 设定台账五件套 / 设定变更三步流程 / 高频吃书场景 / 章前查章后记闭环
4
- scopes:
5
- - novel
6
- - serial_novel
7
- source: market
8
- market_id: worldview-consistency
9
- ---
10
-
11
- # 世界观设定一致性台账守则(市场包)
12
-
13
- 适用:连载与长篇的设定管理。吃书(前后矛盾)是长篇差评第一来源,且几乎全部
14
- 源于**「没有台账」而不是「记性差」**——几十万字跨度下,任何人都记不住自己写过的
15
- 每个数字与专名。本包给出一套零工具依赖的台账纪律。
16
-
17
- ## 一、台账五件套(开书第一天建立,一个文件即可)
18
- 1. **规则体系**:力量 / 能力等级、代价与限制、禁忌(什么绝对做不到)。
19
- **限制比能力更重要**——能赢只是爽,不能做什么才产生剧情。
20
- 2. **地理与组织**:地名 / 势力名清单(含从属关系)。一地一名,写法逐字固定
21
- (定了「云州」就不能又写「云洲」)。
22
- 3. **时间线**:故事内历法 + 大事件年表(含「现在」的锚点日期);每章推进了
23
- 多长时间记一笔,跨章对表。
24
- 4. **专有名词表**:自造词、称谓、咒语、物品名,逐字锁定。
25
- 5. **数字台账**:金额、距离、年龄、队伍人数、库存——正文出现过的每个数字。
26
- 数字是最容易吃书的类别,因为最枯燥、最没人记。
27
-
28
- ## 二、铁律
29
- - **设定一经正文确认,不可静默更改。**要改,走三步:登记「改了什么 / 从哪章起
30
- 生效」→ 排查并修订前文旧描述(或用剧情解释)→ 更新台账。三步缺一不可。
31
- - 设定揭示分层:世界观全貌不必第一章交底,但**已揭示的部分永不反悔**。
32
- 未揭示的可以随时丰富——区分「未揭示」与「矛盾」:读者无从知晓的不算吃书。
33
- - 新设定入正文前先对台账查重:与既有规则冲突吗?冲突就要么改新、要么改旧,
34
- 不许「先写上再说」。
35
- - 跨书 / 跨卷沿用设定时,以台账为准重读一遍,不凭上一本的记忆。
36
-
37
- ## 三、高频吃书场景(评审时重点排查)
38
- - 时间线对不上:上一段还是「昨天」,三天后又被称作「昨天」;旅程三天的两头
39
- 都只过了一夜。
40
- - 能力凭空升级 / 降级:前面明确做不到的事,后面无解释做到了(或反之)。
41
- - 称谓漂移:同一人物 / 势力的称呼前后不一;称呼随剧情需要临时变化。
42
- - 死人复活 / 物品复用:已确认死亡的角色、已消耗或损毁的物品再次登场。
43
- - 年龄与亲缘错位:年龄推算矛盾、辈分关系前后颠倒。
44
-
45
- ## 四、闭环纪律:章前查、章后记
46
- - **章前查**:写 / 审每一章前,读一遍本章涉及的台账条目(出场地名、势力、规则、
47
- 上次时间锚点)。30 秒的事,防 30 万字后的大返工。
48
- - **章后记**:本章产生的任何新设定、新专名、新数字、时间推进,**当章写入台账,
49
- 不过夜**。攒三章再补 = 必漏。
50
- - 一致性评审给出的矛盾项,当轮修复并回填台账;同类矛盾出现第二次 = 台账结构
51
- 要补一类条目,而不是「下次更小心一点」。
52
-
53
- ## 五、台账文件模板(可直接复制)
54
- > ## 规则体系
55
- > - 等级:……;代价:……;禁忌(绝对做不到的事):……
56
- > ## 地理与组织
57
- > - 云州(州)> 落霞城(城);青岚宗(宗门,驻落霞城)
58
- > ## 时间线
59
- > - 第 1 章:启程日(春三月初七);第 2 章:+3 日 → 三月十一
60
- > ## 专有名词表
61
- > - 破妄瞳(术法名,逐字锁定);称「宗主」不写「掌门」
62
- > ## 数字台账
63
- > - 主角 16 岁;启程盘缠 3 两银;落霞城至云州城 700 里
64
-
65
- ## 六、交稿前自检
66
- - [ ] 本章新设定已查重并入台账,未与既有规则冲突
67
- - [ ] 时间推进已记账,与上一章锚点衔接无误
68
- - [ ] 数字(金额 / 距离 / 人数 / 年龄)与台账一致,新数字已登记
69
- - [ ] 专名写法与名词表逐字一致
70
- - [ ] 若改过既有设定:三步流程(登记 / 排查前文 / 更新台账)已走完
1
+ ---
2
+ name: 世界观设定一致性台账守则
3
+ note: 设定台账五件套 / 设定变更三步流程 / 高频吃书场景 / 章前查章后记闭环
4
+ scopes:
5
+ - novel
6
+ - serial_novel
7
+ source: market
8
+ market_id: worldview-consistency
9
+ ---
10
+
11
+ # 世界观设定一致性台账守则(市场包)
12
+
13
+ 适用:连载与长篇的设定管理。吃书(前后矛盾)是长篇差评第一来源,且几乎全部
14
+ 源于**「没有台账」而不是「记性差」**——几十万字跨度下,任何人都记不住自己写过的
15
+ 每个数字与专名。本包给出一套零工具依赖的台账纪律。
16
+
17
+ ## 一、台账五件套(开书第一天建立,一个文件即可)
18
+ 1. **规则体系**:力量 / 能力等级、代价与限制、禁忌(什么绝对做不到)。
19
+ **限制比能力更重要**——能赢只是爽,不能做什么才产生剧情。
20
+ 2. **地理与组织**:地名 / 势力名清单(含从属关系)。一地一名,写法逐字固定
21
+ (定了「云州」就不能又写「云洲」)。
22
+ 3. **时间线**:故事内历法 + 大事件年表(含「现在」的锚点日期);每章推进了
23
+ 多长时间记一笔,跨章对表。
24
+ 4. **专有名词表**:自造词、称谓、咒语、物品名,逐字锁定。
25
+ 5. **数字台账**:金额、距离、年龄、队伍人数、库存——正文出现过的每个数字。
26
+ 数字是最容易吃书的类别,因为最枯燥、最没人记。
27
+
28
+ ## 二、铁律
29
+ - **设定一经正文确认,不可静默更改。**要改,走三步:登记「改了什么 / 从哪章起
30
+ 生效」→ 排查并修订前文旧描述(或用剧情解释)→ 更新台账。三步缺一不可。
31
+ - 设定揭示分层:世界观全貌不必第一章交底,但**已揭示的部分永不反悔**。
32
+ 未揭示的可以随时丰富——区分「未揭示」与「矛盾」:读者无从知晓的不算吃书。
33
+ - 新设定入正文前先对台账查重:与既有规则冲突吗?冲突就要么改新、要么改旧,
34
+ 不许「先写上再说」。
35
+ - 跨书 / 跨卷沿用设定时,以台账为准重读一遍,不凭上一本的记忆。
36
+
37
+ ## 三、高频吃书场景(评审时重点排查)
38
+ - 时间线对不上:上一段还是「昨天」,三天后又被称作「昨天」;旅程三天的两头
39
+ 都只过了一夜。
40
+ - 能力凭空升级 / 降级:前面明确做不到的事,后面无解释做到了(或反之)。
41
+ - 称谓漂移:同一人物 / 势力的称呼前后不一;称呼随剧情需要临时变化。
42
+ - 死人复活 / 物品复用:已确认死亡的角色、已消耗或损毁的物品再次登场。
43
+ - 年龄与亲缘错位:年龄推算矛盾、辈分关系前后颠倒。
44
+
45
+ ## 四、闭环纪律:章前查、章后记
46
+ - **章前查**:写 / 审每一章前,读一遍本章涉及的台账条目(出场地名、势力、规则、
47
+ 上次时间锚点)。30 秒的事,防 30 万字后的大返工。
48
+ - **章后记**:本章产生的任何新设定、新专名、新数字、时间推进,**当章写入台账,
49
+ 不过夜**。攒三章再补 = 必漏。
50
+ - 一致性评审给出的矛盾项,当轮修复并回填台账;同类矛盾出现第二次 = 台账结构
51
+ 要补一类条目,而不是「下次更小心一点」。
52
+
53
+ ## 五、台账文件模板(可直接复制)
54
+ > ## 规则体系
55
+ > - 等级:……;代价:……;禁忌(绝对做不到的事):……
56
+ > ## 地理与组织
57
+ > - 云州(州)> 落霞城(城);青岚宗(宗门,驻落霞城)
58
+ > ## 时间线
59
+ > - 第 1 章:启程日(春三月初七);第 2 章:+3 日 → 三月十一
60
+ > ## 专有名词表
61
+ > - 破妄瞳(术法名,逐字锁定);称「宗主」不写「掌门」
62
+ > ## 数字台账
63
+ > - 主角 16 岁;启程盘缠 3 两银;落霞城至云州城 700 里
64
+
65
+ ## 六、交稿前自检
66
+ - [ ] 本章新设定已查重并入台账,未与既有规则冲突
67
+ - [ ] 时间推进已记账,与上一章锚点衔接无误
68
+ - [ ] 数字(金额 / 距离 / 人数 / 年龄)与台账一致,新数字已登记
69
+ - [ ] 专名写法与名词表逐字一致
70
+ - [ ] 若改过既有设定:三步流程(登记 / 排查前文 / 更新台账)已走完
@@ -1,133 +1,133 @@
1
- # -*- coding: utf-8 -*-
2
- """Step 执行器:压缩触发的重试守门(复用已渲染 prompt,不重复组装)。
3
-
4
- 设计稿:docs/migration/02-context-compaction.md §1D。
5
- 参考 dsh packages/core/agent-loop/src/agent.ts:307-378:
6
- 失败重试只在「前进 surface generation」时返回 {kind:'retry'},
7
- 复用已渲染 PromptAssembly,不重跑 pre-step / 组装 / 用户消息准入。
8
-
9
- Tutti 语境:runner.run_agent 自带 prompt(已渲染);重试的风险不是重复渲染
10
- (prompt 是同一个字符串),而是「不压缩直接重试」必然再次撑爆。
11
- 本模块的守门:仅当 maybe_compact 真正前进了 surface generation 才重试一次。
12
- """
13
- from __future__ import annotations
14
-
15
- import logging
16
-
17
- from .compaction import maybe_compact, DEFAULT_PRESSURE_THRESHOLD
18
- from .error_codes import ErrorCode
19
-
20
- log = logging.getLogger(__name__)
21
-
22
- # 触发「压缩后重试」的错误码
23
- _OVERFLOW_CODES = {ErrorCode.CONTEXT_OVERFLOW, ErrorCode.MAX_TOKENS}
24
-
25
- # 事前预检阈值:最近一次调用的上下文锚点已占本步模型容量九成 → 第一个请求
26
- # 大概率被供应商拒。只拦「大概率必死」,不提前压缩平时的高压(used() 是累计
27
- # 口径,比真实上下文偏大;0.8 的响应式阈值语义与此不同,勿混用)。
28
- _PRECHECK_RATIO = 0.9
29
-
30
-
31
- def _v2_compaction_tuning():
32
- """settings_v2 orchestrator.compaction 微调 → (threshold|None, retain|None)。
33
-
34
- None = 未配置(走 maybe_compact 的模块默认);读取/注册失败静默回落。
35
- retain 允许 0(尾部不保留),与 None(未配置)语义不同,勿合并。"""
36
- try:
37
- from .settings_schema import get as ss_get, register_default_namespaces
38
- register_default_namespaces()
39
- c = (ss_get("orchestrator") or {}).get("compaction") or {}
40
- th = c.get("pressure_threshold")
41
- rt = c.get("retain_tail_tokens")
42
- return (float(th) if th else None,
43
- int(rt) if rt is not None else None)
44
- except Exception:
45
- return None, None
46
-
47
-
48
- def execute_step(session, run_agent_fn, prompt, *, model: str = "",
49
- llm_caller=None, retain_tail_tokens=None, **kwargs):
50
- """执行一次 step;撑爆时压缩并守门重试一次。
51
-
52
- 事前预检(借鉴 freebuff base-chat 每步容量重估):换将切到小窗口模型后,
53
- 响应式路径要等供应商报 CONTEXT_OVERFLOW 才压缩——报得不干净就直接卡死。
54
- 先用「最近一次调用上下文 vs 本步模型容量」判一次,超阈先压缩再发。
55
-
56
- Args:
57
- session: session_log.Session(记录 replace_generation)
58
- run_agent_fn: runner.run_agent(或测试替身),签名 (prompt, **kwargs) -> dict
59
- prompt: 已渲染的提示词(重试时原样复用,不重新渲染)
60
- model: 本步将要使用的模型名(容量与压力估算都按它算)
61
- llm_caller: 压缩摘要 LLM(None = 不压缩,永不重试)
62
- **kwargs: 透传 run_agent_fn
63
-
64
- Returns:
65
- (result, retried: bool)
66
- """
67
- v2_th, v2_rt = _v2_compaction_tuning()
68
- compact_kwargs = {}
69
- if retain_tail_tokens is not None:
70
- compact_kwargs["retain_tail_tokens"] = retain_tail_tokens
71
- elif v2_rt is not None:
72
- compact_kwargs["retain_tail_tokens"] = v2_rt
73
- if v2_th is not None:
74
- compact_kwargs["threshold"] = v2_th
75
- if llm_caller is not None and model:
76
- try:
77
- from .token_meter import token_meter
78
- ctx = token_meter.last_context(session.run_id)
79
- cap = token_meter.capacity(model)
80
- if ctx > 0 and cap > 0 and ctx > cap * _PRECHECK_RATIO:
81
- gen_p0 = session.replace_generation()
82
- if maybe_compact(session, model=model, llm_caller=llm_caller,
83
- run_id=session.run_id, **compact_kwargs) \
84
- and session.replace_generation() > gen_p0:
85
- log.info("precheck: last ctx~%d > %.0f%% of cap(%s)=%d, "
86
- "compacted before step", ctx, _PRECHECK_RATIO * 100,
87
- model, cap)
88
- except Exception:
89
- log.debug("precheck skipped", exc_info=True)
90
- gen0 = session.replace_generation()
91
- result = run_agent_fn(prompt, **kwargs)
92
- code = result.get("error_code") or ""
93
- if code not in _OVERFLOW_CODES or llm_caller is None:
94
- return result, False
95
- # 撑爆 → 尝试压缩
96
- compacted = maybe_compact(session, model=model, llm_caller=llm_caller,
97
- run_id=session.run_id, **compact_kwargs)
98
- gen1 = session.replace_generation()
99
- if not compacted or gen1 <= gen0:
100
- # 压缩未发生或未前进 generation:重试必然再次撑爆,不重试
101
- log.info("overflow but no compaction progress (gen %s->%s), no retry",
102
- gen0, gen1)
103
- return result, False
104
- # 压缩生效:surface 已折叠。**真正替换 CLI 请求上下文**(2026-09-21
105
- # 清最老待深挖项:此前重试仍发原 prompt + 续旧 resume 会话——摘要只进
106
- # 审计日志,CLI 看到的上下文一点没小,重试必然再爆):
107
- # ①重试 prompt 改用 session 派生转录(折叠摘要 + 近尾消息,体量骤降);
108
- # ②弃 resume(旧会话本体仍是膨胀态,续上就前功尽弃)。
109
- msgs = []
110
- try:
111
- msgs = session.derive_messages()
112
- except Exception:
113
- log.debug("derive_messages failed on retry", exc_info=True)
114
- kwargs2 = dict(kwargs)
115
- if msgs:
116
- transcript = "\n\n".join("[%s] %s" % (m.get("role"), m.get("content"))
117
- for m in msgs)
118
- if len(transcript) > 24_000:
119
- transcript = transcript[-24_000:]
120
- retry_prompt = transcript
121
- # 本步指令必须在场:被折叠/截断掉就显式补在尾部(缺失指令比重复严重)
122
- tail = transcript[-2000:]
123
- if prompt[:400] not in tail:
124
- retry_prompt = transcript + "\n\n" + prompt
125
- kwargs2.pop("resume", None)
126
- log.info("compaction advanced gen %s->%s, retrying with derived "
127
- "context (%d msgs, resume dropped)", gen0, gen1, len(msgs))
128
- result2 = run_agent_fn(retry_prompt, **kwargs2)
129
- else:
130
- log.info("compaction advanced gen %s->%s but no surface derived, "
131
- "retrying same prompt", gen0, gen1)
132
- result2 = run_agent_fn(prompt, **kwargs)
1
+ # -*- coding: utf-8 -*-
2
+ """Step 执行器:压缩触发的重试守门(复用已渲染 prompt,不重复组装)。
3
+
4
+ 设计稿:docs/migration/02-context-compaction.md §1D。
5
+ 参考 dsh packages/core/agent-loop/src/agent.ts:307-378:
6
+ 失败重试只在「前进 surface generation」时返回 {kind:'retry'},
7
+ 复用已渲染 PromptAssembly,不重跑 pre-step / 组装 / 用户消息准入。
8
+
9
+ Tutti 语境:runner.run_agent 自带 prompt(已渲染);重试的风险不是重复渲染
10
+ (prompt 是同一个字符串),而是「不压缩直接重试」必然再次撑爆。
11
+ 本模块的守门:仅当 maybe_compact 真正前进了 surface generation 才重试一次。
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import logging
16
+
17
+ from .compaction import maybe_compact, DEFAULT_PRESSURE_THRESHOLD
18
+ from .error_codes import ErrorCode
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+ # 触发「压缩后重试」的错误码
23
+ _OVERFLOW_CODES = {ErrorCode.CONTEXT_OVERFLOW, ErrorCode.MAX_TOKENS}
24
+
25
+ # 事前预检阈值:最近一次调用的上下文锚点已占本步模型容量九成 → 第一个请求
26
+ # 大概率被供应商拒。只拦「大概率必死」,不提前压缩平时的高压(used() 是累计
27
+ # 口径,比真实上下文偏大;0.8 的响应式阈值语义与此不同,勿混用)。
28
+ _PRECHECK_RATIO = 0.9
29
+
30
+
31
+ def _v2_compaction_tuning():
32
+ """settings_v2 orchestrator.compaction 微调 → (threshold|None, retain|None)。
33
+
34
+ None = 未配置(走 maybe_compact 的模块默认);读取/注册失败静默回落。
35
+ retain 允许 0(尾部不保留),与 None(未配置)语义不同,勿合并。"""
36
+ try:
37
+ from .settings_schema import get as ss_get, register_default_namespaces
38
+ register_default_namespaces()
39
+ c = (ss_get("orchestrator") or {}).get("compaction") or {}
40
+ th = c.get("pressure_threshold")
41
+ rt = c.get("retain_tail_tokens")
42
+ return (float(th) if th else None,
43
+ int(rt) if rt is not None else None)
44
+ except Exception:
45
+ return None, None
46
+
47
+
48
+ def execute_step(session, run_agent_fn, prompt, *, model: str = "",
49
+ llm_caller=None, retain_tail_tokens=None, **kwargs):
50
+ """执行一次 step;撑爆时压缩并守门重试一次。
51
+
52
+ 事前预检(借鉴 freebuff base-chat 每步容量重估):换将切到小窗口模型后,
53
+ 响应式路径要等供应商报 CONTEXT_OVERFLOW 才压缩——报得不干净就直接卡死。
54
+ 先用「最近一次调用上下文 vs 本步模型容量」判一次,超阈先压缩再发。
55
+
56
+ Args:
57
+ session: session_log.Session(记录 replace_generation)
58
+ run_agent_fn: runner.run_agent(或测试替身),签名 (prompt, **kwargs) -> dict
59
+ prompt: 已渲染的提示词(重试时原样复用,不重新渲染)
60
+ model: 本步将要使用的模型名(容量与压力估算都按它算)
61
+ llm_caller: 压缩摘要 LLM(None = 不压缩,永不重试)
62
+ **kwargs: 透传 run_agent_fn
63
+
64
+ Returns:
65
+ (result, retried: bool)
66
+ """
67
+ v2_th, v2_rt = _v2_compaction_tuning()
68
+ compact_kwargs = {}
69
+ if retain_tail_tokens is not None:
70
+ compact_kwargs["retain_tail_tokens"] = retain_tail_tokens
71
+ elif v2_rt is not None:
72
+ compact_kwargs["retain_tail_tokens"] = v2_rt
73
+ if v2_th is not None:
74
+ compact_kwargs["threshold"] = v2_th
75
+ if llm_caller is not None and model:
76
+ try:
77
+ from .token_meter import token_meter
78
+ ctx = token_meter.last_context(session.run_id)
79
+ cap = token_meter.capacity(model)
80
+ if ctx > 0 and cap > 0 and ctx > cap * _PRECHECK_RATIO:
81
+ gen_p0 = session.replace_generation()
82
+ if maybe_compact(session, model=model, llm_caller=llm_caller,
83
+ run_id=session.run_id, **compact_kwargs) \
84
+ and session.replace_generation() > gen_p0:
85
+ log.info("precheck: last ctx~%d > %.0f%% of cap(%s)=%d, "
86
+ "compacted before step", ctx, _PRECHECK_RATIO * 100,
87
+ model, cap)
88
+ except Exception:
89
+ log.debug("precheck skipped", exc_info=True)
90
+ gen0 = session.replace_generation()
91
+ result = run_agent_fn(prompt, **kwargs)
92
+ code = result.get("error_code") or ""
93
+ if code not in _OVERFLOW_CODES or llm_caller is None:
94
+ return result, False
95
+ # 撑爆 → 尝试压缩
96
+ compacted = maybe_compact(session, model=model, llm_caller=llm_caller,
97
+ run_id=session.run_id, **compact_kwargs)
98
+ gen1 = session.replace_generation()
99
+ if not compacted or gen1 <= gen0:
100
+ # 压缩未发生或未前进 generation:重试必然再次撑爆,不重试
101
+ log.info("overflow but no compaction progress (gen %s->%s), no retry",
102
+ gen0, gen1)
103
+ return result, False
104
+ # 压缩生效:surface 已折叠。**真正替换 CLI 请求上下文**(2026-09-21
105
+ # 清最老待深挖项:此前重试仍发原 prompt + 续旧 resume 会话——摘要只进
106
+ # 审计日志,CLI 看到的上下文一点没小,重试必然再爆):
107
+ # ①重试 prompt 改用 session 派生转录(折叠摘要 + 近尾消息,体量骤降);
108
+ # ②弃 resume(旧会话本体仍是膨胀态,续上就前功尽弃)。
109
+ msgs = []
110
+ try:
111
+ msgs = session.derive_messages()
112
+ except Exception:
113
+ log.debug("derive_messages failed on retry", exc_info=True)
114
+ kwargs2 = dict(kwargs)
115
+ if msgs:
116
+ transcript = "\n\n".join("[%s] %s" % (m.get("role"), m.get("content"))
117
+ for m in msgs)
118
+ if len(transcript) > 24_000:
119
+ transcript = transcript[-24_000:]
120
+ retry_prompt = transcript
121
+ # 本步指令必须在场:被折叠/截断掉就显式补在尾部(缺失指令比重复严重)
122
+ tail = transcript[-2000:]
123
+ if prompt[:400] not in tail:
124
+ retry_prompt = transcript + "\n\n" + prompt
125
+ kwargs2.pop("resume", None)
126
+ log.info("compaction advanced gen %s->%s, retrying with derived "
127
+ "context (%d msgs, resume dropped)", gen0, gen1, len(msgs))
128
+ result2 = run_agent_fn(retry_prompt, **kwargs2)
129
+ else:
130
+ log.info("compaction advanced gen %s->%s but no surface derived, "
131
+ "retrying same prompt", gen0, gen1)
132
+ result2 = run_agent_fn(prompt, **kwargs)
133
133
  return result2, True