codebee 0.1.80 → 0.1.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +3 -2
- package/app/core/pipeline.py +15 -8
- package/app/core/skills.py +9 -2
- package/app/ui/app.js +3 -0
- package/app/ui/i18n.js +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@ README 元数据带回,供老版本在「发现新版本」时展示新版更
|
|
|
6
6
|
|
|
7
7
|
## 未发布
|
|
8
8
|
|
|
9
|
+
## v0.1.81(2026-10-04)
|
|
10
|
+
|
|
11
|
+
- **连载超时重试的「分层降级」修准了**:此前起草超时重试把经验库/圣经/知识库折成一整块再收缩,只能整体 4K 硬截——现在三块分开留底,重试时按各自身份降级(经验库 4K、圣经按二级标题保整段、模块库按模块边界保整模块),大纲/前情/本章要点永不动。重试提示词保住的是结构化上下文,不是一截碎尾巴。
|
|
12
|
+
- **经验教训新增「没用」一键负反馈**:教训卡上可直接点「没用」——停用该条并记一次显式负证据(按失守同权计入排序,粘滞下沉)。此前用户只能绕道停用+手动台账,负反馈口径从台账推断的「没防住」变成用户亲口说。
|
|
13
|
+
|
|
9
14
|
## v0.1.80(2026-10-04)
|
|
10
15
|
|
|
11
16
|
- **翻译任务交稿前自查「翻译腔」**:翻译起草要求在术语表之外新增一条交稿自查——欧化句式/逐词直译当面清(长句拆短、被动改主动,清掉「被……所」「……性」「……的存在」这类直译腔标记),译文读感应是「用目标语写出来的」、不是「翻出来的」。此前翻译腔只能靠评审 rubric「流畅度」事后抓,现在起草侧先过一遍,少一轮返工。
|
package/README.md
CHANGED
|
@@ -33,9 +33,10 @@ Trae Agent、OpenClaw……),提供
|
|
|
33
33
|
---
|
|
34
34
|
|
|
35
35
|
<!-- relnotes:start -->
|
|
36
|
-
### 最新版更新内容(v0.1.
|
|
36
|
+
### 最新版更新内容(v0.1.81)
|
|
37
37
|
|
|
38
|
-
-
|
|
38
|
+
- 连载超时重试「分层降级」修准:经验库/圣经/知识库三块分开留底,重试按各自身份降级(经验库 4K、圣经保整段、模块库保整模块),大纲/前情永不动——重试提示词保住结构化上下文,不再整体 4K 硬截
|
|
39
|
+
- 经验教训新增「没用」一键负反馈:点了即停用+记显式负证据,排序粘滞下沉
|
|
39
40
|
<!-- relnotes:end -->
|
|
40
41
|
|
|
41
42
|
|
package/app/core/pipeline.py
CHANGED
|
@@ -2481,7 +2481,7 @@ def _shrink_context_block(sk_block, bible, budget=12000):
|
|
|
2481
2481
|
- 圣经截断保整段(按二级标题边界,无边界才硬截)
|
|
2482
2482
|
- 模块库截断保整模块(按「## 」标题边界)
|
|
2483
2483
|
- 经验库直接硬截(条目本身短,损失最小)
|
|
2484
|
-
返回 (新 sk_block, 降级说明)
|
|
2484
|
+
返回 (新 sk_block, 新 bible, 降级说明)。无降级原样返回(说明为空串)。"""
|
|
2485
2485
|
total = len(sk_block or "") + len(bible or "")
|
|
2486
2486
|
if total <= budget:
|
|
2487
2487
|
return sk_block, bible, ""
|
|
@@ -2516,6 +2516,14 @@ def _shrink_context_block(sk_block, bible, budget=12000):
|
|
|
2516
2516
|
return sk_block, bible, ";".join(notes)
|
|
2517
2517
|
|
|
2518
2518
|
|
|
2519
|
+
def _serial_shrunk_block(lessons, bible, kb_block, budget=12000):
|
|
2520
|
+
"""连载起草重试的分层降级组装:经验库与圣经按各自身份过 _shrink_context_block
|
|
2521
|
+
(经验库→4K、模块库按模块边界、圣经按二级标题边界),知识库块与大纲/前情
|
|
2522
|
+
同待遇永不动。返回重组后的替换块——调用方整块 replace,字节级对位。"""
|
|
2523
|
+
sk2, bible2, _note = _shrink_context_block(lessons, bible, budget=budget)
|
|
2524
|
+
return "\n\n".join(p for p in (sk2, bible2, kb_block) if p)
|
|
2525
|
+
|
|
2526
|
+
|
|
2519
2527
|
def _critic_lens(critics, agent):
|
|
2520
2528
|
"""该评审的专属视角;单评审/手动指定时不播种(无从轮换,也别稀释注意力)。"""
|
|
2521
2529
|
try:
|
|
@@ -3522,12 +3530,11 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
|
|
|
3522
3530
|
stale_note = ("- 注意:目录里已有一版**未通过评审**的旧稿 `%s`——不要校验沿用、"
|
|
3523
3531
|
"不要增量修补,按本章任务直接覆盖重写。" % ch_file)
|
|
3524
3532
|
# stable_order:同一任务 8 个章节的技能块必须字节级一致(§07 T1.2' 前缀缓存)
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3533
|
+
# 三块分开留底:起草重试的分层降级(_serial_shrunk_block)要按
|
|
3534
|
+
# 「经验库/圣经」各自的身份收缩,折成一整块就只剩 4K 硬截一层了
|
|
3535
|
+
sk_lessons, _ = skills.block_for(task, stable_order=True, run_id=run_id)
|
|
3528
3536
|
kb_block = knowledge.block_for(task)
|
|
3529
|
-
if
|
|
3530
|
-
sk_block = (sk_block + "\n\n" + kb_block) if sk_block else kb_block
|
|
3537
|
+
sk_block = "\n\n".join(p for p in (sk_lessons, bible, kb_block) if p)
|
|
3531
3538
|
scope = ("本章 = 大纲第 %d 章" % i) if start == 1 else (
|
|
3532
3539
|
"本批为第 %d–%d 章,下列按全书章号列出各章要点" % (start, end))
|
|
3533
3540
|
|
|
@@ -3602,8 +3609,8 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
|
|
|
3602
3609
|
# ——分层降级:经验库→4K、模块库按模块边界、圣经按二级标题
|
|
3603
3610
|
# 边界,保大纲/前情/本章要点(2026-09-17 七猫实测:全量
|
|
3604
3611
|
# 30KB 对讯飞必挂)
|
|
3605
|
-
|
|
3606
|
-
|
|
3612
|
+
use_prompt = prompt.replace(
|
|
3613
|
+
sk_block, _serial_shrunk_block(sk_lessons, bible, kb_block))
|
|
3607
3614
|
# 超时重试必须有新变量才值得做(2026-09-22):提示词与上次逐字节
|
|
3608
3615
|
# 相同、上次又是超时/停滞收场时,重试只是把同一个超时再烧一遍
|
|
3609
3616
|
# (2400s × N)。此时直接跳出交替换将——换 CLI/模型才是新机会。
|
package/app/core/skills.py
CHANGED
|
@@ -336,6 +336,8 @@ def _karma(item):
|
|
|
336
336
|
lost = max(0, int(item.get("lost") or 0))
|
|
337
337
|
if lost > hits:
|
|
338
338
|
lost = hits # 台账被手工改坏时不失守倒挂
|
|
339
|
+
useless = min(max(0, int(item.get("useless") or 0)), hits)
|
|
340
|
+
lost = max(lost, useless) # 用户显式「标记无用」按失守同权计入(粘滞负证据)
|
|
339
341
|
return (hits - lost + _KARMA_PRIOR) / (hits + 2 * _KARMA_PRIOR)
|
|
340
342
|
|
|
341
343
|
|
|
@@ -351,6 +353,7 @@ def _surplus_decay(item, now=None):
|
|
|
351
353
|
被再次触及即重置。只压排序,不删除、不改数据。"""
|
|
352
354
|
hits = max(0, int(item.get("hits") or 0))
|
|
353
355
|
lost = min(max(0, int(item.get("lost") or 0)), hits)
|
|
356
|
+
lost = max(lost, min(max(0, int(item.get("useless") or 0)), hits))
|
|
354
357
|
if int(item.get("won") or 0) > 0:
|
|
355
358
|
return hits - lost, lost
|
|
356
359
|
stamp = item.get("updated_at") or item.get("created_at")
|
|
@@ -489,8 +492,9 @@ def upsert_lesson(scope, title, content, source="", category=None, dim=None):
|
|
|
489
492
|
|
|
490
493
|
|
|
491
494
|
def lesson_op(lesson_id, op):
|
|
492
|
-
"""
|
|
493
|
-
|
|
495
|
+
"""启用/停用/删除教训;useless=用户显式「标记无用」(停用+记粘滞负证据)。
|
|
496
|
+
返回错误或 None。"""
|
|
497
|
+
if op not in ("enable", "disable", "delete", "useless"):
|
|
494
498
|
return "未知操作 " + str(op)
|
|
495
499
|
with _LOCK:
|
|
496
500
|
data = _load()
|
|
@@ -500,6 +504,9 @@ def lesson_op(lesson_id, op):
|
|
|
500
504
|
return "教训不存在"
|
|
501
505
|
if op == "delete":
|
|
502
506
|
data["lessons"] = [x for x in items if x.get("id") != lesson_id]
|
|
507
|
+
elif op == "useless":
|
|
508
|
+
hit["enabled"] = False # 显式负反馈即停用:不再注入
|
|
509
|
+
hit["useless"] = int(hit.get("useless") or 0) + 1
|
|
503
510
|
else:
|
|
504
511
|
hit["enabled"] = (op == "enable")
|
|
505
512
|
_save(data)
|
package/app/ui/app.js
CHANGED
|
@@ -11032,11 +11032,13 @@ function renderSkills() {
|
|
|
11032
11032
|
(x.hits ? '<span class="tag">' + t("已注入 ") + x.hits + t(" 次") + "</span>" : "") +
|
|
11033
11033
|
(x.won > 0 ? '<span class="tag ok" title="' + t("注入后任务过审的次数(真实帮上忙)") + '">' + t("有效 ") + x.won + "</span>" : "") +
|
|
11034
11034
|
(x.lost > 0 ? '<span class="tag" style="color:var(--bad)" title="' + t("注入后任务仍失败的次数(没防住)") + '">' + t("失守 ") + x.lost + "</span>" : "") +
|
|
11035
|
+
(x.useless ? '<span class="tag" style="color:var(--bad)" title="' + t("用户标记无用的次数(显式负反馈,排序下沉)") + '">' + t("没用 ") + x.useless + "</span>" : "") +
|
|
11035
11036
|
(x.enabled === false ? '<span class="tag">' + t("已停用") + "</span>" : "") + "</div>" +
|
|
11036
11037
|
'<div class="note">' + esc(t(x.content)) + "</div>" +
|
|
11037
11038
|
'<div class="ops">' +
|
|
11038
11039
|
'<button class="ghost small" onclick="skillLessonOp(\'' + esc(x.id) + '\', \'' +
|
|
11039
11040
|
(x.enabled === false ? "enable" : "disable") + '\')">' + (x.enabled === false ? t("启用") : t("停用")) + "</button>" +
|
|
11041
|
+
'<button class="ghost small" onclick="skillLessonOp(\'' + esc(x.id) + '\', \'useless\')" title="' + t("标记这条教训没帮上忙?将停用并记一次无用反馈") + '">' + t("没用") + "</button>" +
|
|
11040
11042
|
'<button class="danger small" onclick="skillLessonOp(\'' + esc(x.id) + '\', \'delete\')">' + t("删除") + "</button>" +
|
|
11041
11043
|
"</div></div>").join("") ||
|
|
11042
11044
|
(filt ? '<div class="empty">' + t("该分类下暂无教训") + "</div>"
|
|
@@ -11055,6 +11057,7 @@ async function skillPackOp(id, op) {
|
|
|
11055
11057
|
}
|
|
11056
11058
|
|
|
11057
11059
|
async function skillLessonOp(id, op) {
|
|
11060
|
+
if (op === "useless" && !await uiConfirm(t("标记这条教训没帮上忙?将停用并记一次无用反馈"), { ok: t("没用"), danger: true })) return;
|
|
11058
11061
|
if (op === "delete" && !await uiConfirm(t("删除这条教训?"), { ok: t("删除"), danger: true })) return;
|
|
11059
11062
|
try { await api("/api/skills/lesson-op", { method: "POST", body: JSON.stringify({ id, op }) }); }
|
|
11060
11063
|
catch (e) { toast(e.message, true); return; }
|
package/app/ui/i18n.js
CHANGED
|
@@ -728,6 +728,10 @@
|
|
|
728
728
|
"删除该任务及其全部运行记录(含日志与报告)?不可恢复。": "Delete this task and all its runs (logs and reports)? This cannot be undone.",
|
|
729
729
|
"删除该运行记录(含全部日志与报告)?不可恢复。": "Delete this run (with logs and reports)? This cannot be undone.",
|
|
730
730
|
"删除这条教训?": "Delete this lesson?",
|
|
731
|
+
"没用": "Useless",
|
|
732
|
+
"没用 ": "Useless ",
|
|
733
|
+
"标记这条教训没帮上忙?将停用并记一次无用反馈": "Mark this lesson as unhelpful? It gets disabled and recorded as negative feedback.",
|
|
734
|
+
"用户标记无用的次数(显式负反馈,排序下沉)": "Times the user marked this useless (explicit negative feedback; sinks in ranking)",
|
|
731
735
|
"删除全部已结束的运行记录(运行中的会保留)": "Delete all finished runs (active ones are kept)",
|
|
732
736
|
"清除全部运行记录(含日志与报告)?运行中的记录会保留,需先取消。不可恢复。": "Clear all runs (logs and reports)? Active runs are kept — cancel them first. This cannot be undone.",
|
|
733
737
|
"急停": "Kill all",
|
package/package.json
CHANGED