codebee 0.1.79 → 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 +9 -0
- package/README.md +3 -2
- package/app/core/pipeline.py +47 -23
- package/app/core/planner.py +11 -6
- 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,15 @@ README 元数据带回,供老版本在「发现新版本」时展示新版更
|
|
|
6
6
|
|
|
7
7
|
## 未发布
|
|
8
8
|
|
|
9
|
+
## v0.1.81(2026-10-04)
|
|
10
|
+
|
|
11
|
+
- **连载超时重试的「分层降级」修准了**:此前起草超时重试把经验库/圣经/知识库折成一整块再收缩,只能整体 4K 硬截——现在三块分开留底,重试时按各自身份降级(经验库 4K、圣经按二级标题保整段、模块库按模块边界保整模块),大纲/前情/本章要点永不动。重试提示词保住的是结构化上下文,不是一截碎尾巴。
|
|
12
|
+
- **经验教训新增「没用」一键负反馈**:教训卡上可直接点「没用」——停用该条并记一次显式负证据(按失守同权计入排序,粘滞下沉)。此前用户只能绕道停用+手动台账,负反馈口径从台账推断的「没防住」变成用户亲口说。
|
|
13
|
+
|
|
14
|
+
## v0.1.80(2026-10-04)
|
|
15
|
+
|
|
16
|
+
- **翻译任务交稿前自查「翻译腔」**:翻译起草要求在术语表之外新增一条交稿自查——欧化句式/逐词直译当面清(长句拆短、被动改主动,清掉「被……所」「……性」「……的存在」这类直译腔标记),译文读感应是「用目标语写出来的」、不是「翻出来的」。此前翻译腔只能靠评审 rubric「流畅度」事后抓,现在起草侧先过一遍,少一轮返工。
|
|
17
|
+
|
|
9
18
|
## v0.1.79(2026-10-04)
|
|
10
19
|
|
|
11
20
|
- **周报起草补上「本周提交素材」取材半边**:交付契约一直承诺取材清单第一项「合并的提交(git log)」,但此前只有禅道素材半边落地、git log 全仓无实现——模型写周报时提交记录缺源,容易凭印象编。现在起草提示词在禅道素材旁并列注入最近 7 天提交摘要(40 条封顶);非 git 仓/空仓/命令失败一律静默跳过,绝不阻塞起草。
|
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
|
@@ -2313,7 +2313,9 @@ RESEARCH_APPENDIX = """
|
|
|
2313
2313
|
# 翻译类稿件的追加要求(借鉴 andrewyng/translation-agent 三步法 translate→reflect→improve
|
|
2314
2314
|
# 的 glossary 机制):动笔前先提炼术语表、全篇译名以表为准——术语一致性此前只靠
|
|
2315
2315
|
# 评审 rubric「术语一致性」事后抓,起草侧无约定,长文译名漂移只能靠修订轮返工。
|
|
2316
|
-
#
|
|
2316
|
+
# 翻译腔自查条借鉴 yomiyasu(翻译腔检查器):欧化句式/逐词直译前置到起草侧自查,
|
|
2317
|
+
# 不再只靠评审 rubric「流畅度」事后抓。TransAgents(多智能体文学翻译)的出版社
|
|
2318
|
+
# 角色分工不借鉴:评审链已有对应物。
|
|
2317
2319
|
TRANSLATION_APPENDIX = """
|
|
2318
2320
|
|
|
2319
2321
|
## 翻译要求(术语表先行)
|
|
@@ -2321,7 +2323,10 @@ TRANSLATION_APPENDIX = """
|
|
|
2321
2323
|
作品名/产品名/机构名)与反复出现的领域术语,逐条给出「源文 → 译名」。
|
|
2322
2324
|
- 全篇译名以术语表为准:同一源文术语从头到尾一个译法,不随上下文漂移;业界已有
|
|
2323
2325
|
通用译名的从通用,没有的定一个贴切的并全篇保持一致。
|
|
2324
|
-
- 无术语可提炼的短文可省略术语表,译名一致性要求不变。
|
|
2326
|
+
- 无术语可提炼的短文可省略术语表,译名一致性要求不变。
|
|
2327
|
+
- 交稿前自查翻译腔(欧化句式/逐词直译):长句拆短、被动改主动,清掉「被……所」
|
|
2328
|
+
「……性」「……的存在」这类直译腔标记;译文读感应是「用目标语写出来的」,
|
|
2329
|
+
不是「翻出来的」。"""
|
|
2325
2330
|
|
|
2326
2331
|
NOVEL_REVISE_PROMPT = """你是__ROLE__。请根据下方汇总评审意见修订稿件文件:`__FILE__`(直接写入该文件)。文件必须以 UTF-8 编码保存(PowerShell 写文件显式加 -Encoding UTF8,禁止依赖默认编码)。
|
|
2327
2332
|
|
|
@@ -2476,7 +2481,7 @@ def _shrink_context_block(sk_block, bible, budget=12000):
|
|
|
2476
2481
|
- 圣经截断保整段(按二级标题边界,无边界才硬截)
|
|
2477
2482
|
- 模块库截断保整模块(按「## 」标题边界)
|
|
2478
2483
|
- 经验库直接硬截(条目本身短,损失最小)
|
|
2479
|
-
返回 (新 sk_block, 降级说明)
|
|
2484
|
+
返回 (新 sk_block, 新 bible, 降级说明)。无降级原样返回(说明为空串)。"""
|
|
2480
2485
|
total = len(sk_block or "") + len(bible or "")
|
|
2481
2486
|
if total <= budget:
|
|
2482
2487
|
return sk_block, bible, ""
|
|
@@ -2511,6 +2516,14 @@ def _shrink_context_block(sk_block, bible, budget=12000):
|
|
|
2511
2516
|
return sk_block, bible, ";".join(notes)
|
|
2512
2517
|
|
|
2513
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
|
+
|
|
2514
2527
|
def _critic_lens(critics, agent):
|
|
2515
2528
|
"""该评审的专属视角;单评审/手动指定时不播种(无从轮换,也别稀释注意力)。"""
|
|
2516
2529
|
try:
|
|
@@ -2870,25 +2883,36 @@ _CH_MENTION_RE = re.compile(r"第\s*(\d{1,4})\s*(?:[—–\-~至到]\s*(\d{1,4})
|
|
|
2870
2883
|
|
|
2871
2884
|
|
|
2872
2885
|
def _archived_preface(workdir, start):
|
|
2873
|
-
"""
|
|
2874
|
-
|
|
2875
|
-
|
|
2886
|
+
"""前文回退:续写批次里从第 1 章起连续归档的前缀(chapter-NN.md 不在场)
|
|
2887
|
+
从「已成稿/」目录找回,供全书评审与合并成书使用。返回 (文本, 归档覆盖
|
|
2888
|
+
到的章号):第 1 章仍在场返回 ("", 0)(正常路径零影响);混合态(如
|
|
2889
|
+
1–20 已归档、21–28 在场)按连续缺失前缀计入——2026-10-04 实案:旧版
|
|
2890
|
+
见任一章在场就整体放弃,1–20 被静默丢出成书。同题名 .md/.txt 并存只
|
|
2891
|
+
取一份,不重复计字。"""
|
|
2876
2892
|
if start <= 1:
|
|
2877
|
-
return ""
|
|
2893
|
+
return "", 0
|
|
2894
|
+
covered = 0
|
|
2878
2895
|
for i in range(1, start):
|
|
2879
2896
|
if _read_chapter(workdir, i):
|
|
2880
|
-
|
|
2897
|
+
break
|
|
2898
|
+
covered = i
|
|
2899
|
+
if covered < 1:
|
|
2900
|
+
return "", 0
|
|
2881
2901
|
adir = os.path.join(str(workdir), _ARCHIVE_DIR)
|
|
2882
2902
|
try:
|
|
2883
2903
|
names = sorted(os.listdir(adir))
|
|
2884
2904
|
except OSError:
|
|
2885
|
-
return ""
|
|
2905
|
+
return "", 0
|
|
2886
2906
|
parts = []
|
|
2907
|
+
stems = set()
|
|
2887
2908
|
for name in names:
|
|
2888
2909
|
if not name.lower().endswith((".md", ".txt")):
|
|
2889
2910
|
continue
|
|
2890
2911
|
if "目录" in name: # 阅读目录/章节目录是索引不是正文
|
|
2891
2912
|
continue
|
|
2913
|
+
stem = os.path.splitext(name)[0]
|
|
2914
|
+
if stem in stems: # 同题名 .md/.txt 是同一份内容的两种格式
|
|
2915
|
+
continue
|
|
2892
2916
|
p = os.path.join(adir, name)
|
|
2893
2917
|
if not os.path.isfile(p):
|
|
2894
2918
|
continue
|
|
@@ -2898,7 +2922,8 @@ def _archived_preface(workdir, start):
|
|
|
2898
2922
|
continue
|
|
2899
2923
|
if t and t.strip():
|
|
2900
2924
|
parts.append(t.strip())
|
|
2901
|
-
|
|
2925
|
+
stems.add(stem)
|
|
2926
|
+
return "\n\n".join(parts), covered
|
|
2902
2927
|
|
|
2903
2928
|
|
|
2904
2929
|
def _full_manuscript(workdir, start, end, cap=60000):
|
|
@@ -2910,7 +2935,7 @@ def _full_manuscript(workdir, start, end, cap=60000):
|
|
|
2910
2935
|
old_text = "\n\n".join(t for t in (_read_chapter(workdir, i)
|
|
2911
2936
|
for i in range(1, start)) if t)
|
|
2912
2937
|
if not old_text and start > 1:
|
|
2913
|
-
old_text = _archived_preface(workdir, start)
|
|
2938
|
+
old_text = _archived_preface(workdir, start)[0]
|
|
2914
2939
|
budget = cap - len(new_text) - 2
|
|
2915
2940
|
if budget <= 0:
|
|
2916
2941
|
return new_text[:cap]
|
|
@@ -3505,12 +3530,11 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
|
|
|
3505
3530
|
stale_note = ("- 注意:目录里已有一版**未通过评审**的旧稿 `%s`——不要校验沿用、"
|
|
3506
3531
|
"不要增量修补,按本章任务直接覆盖重写。" % ch_file)
|
|
3507
3532
|
# stable_order:同一任务 8 个章节的技能块必须字节级一致(§07 T1.2' 前缀缓存)
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3533
|
+
# 三块分开留底:起草重试的分层降级(_serial_shrunk_block)要按
|
|
3534
|
+
# 「经验库/圣经」各自的身份收缩,折成一整块就只剩 4K 硬截一层了
|
|
3535
|
+
sk_lessons, _ = skills.block_for(task, stable_order=True, run_id=run_id)
|
|
3511
3536
|
kb_block = knowledge.block_for(task)
|
|
3512
|
-
if
|
|
3513
|
-
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)
|
|
3514
3538
|
scope = ("本章 = 大纲第 %d 章" % i) if start == 1 else (
|
|
3515
3539
|
"本批为第 %d–%d 章,下列按全书章号列出各章要点" % (start, end))
|
|
3516
3540
|
|
|
@@ -3585,8 +3609,8 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
|
|
|
3585
3609
|
# ——分层降级:经验库→4K、模块库按模块边界、圣经按二级标题
|
|
3586
3610
|
# 边界,保大纲/前情/本章要点(2026-09-17 七猫实测:全量
|
|
3587
3611
|
# 30KB 对讯飞必挂)
|
|
3588
|
-
|
|
3589
|
-
|
|
3612
|
+
use_prompt = prompt.replace(
|
|
3613
|
+
sk_block, _serial_shrunk_block(sk_lessons, bible, kb_block))
|
|
3590
3614
|
# 超时重试必须有新变量才值得做(2026-09-22):提示词与上次逐字节
|
|
3591
3615
|
# 相同、上次又是超时/停滞收场时,重试只是把同一个超时再烧一遍
|
|
3592
3616
|
# (2400s × N)。此时直接跳出交替换将——换 CLI/模型才是新机会。
|
|
@@ -4383,11 +4407,11 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
|
|
|
4383
4407
|
ms_name = _ms_name(task.get("manuscript"))
|
|
4384
4408
|
book_title = outline.get("book_title") or task["title"]
|
|
4385
4409
|
parts = ["# %s" % book_title, ""]
|
|
4386
|
-
#
|
|
4387
|
-
#
|
|
4388
|
-
arch_preface = _archived_preface(workdir, start) if start > 1 else ""
|
|
4410
|
+
# 前文归档回退:从第 1 章起连续归档的前缀(chapter-NN.md 不在场)时,
|
|
4411
|
+
# 合并成品不能只剩本批——否则续写批次的「成书」会静默丢掉归档前文
|
|
4412
|
+
arch_preface, arch_upto = _archived_preface(workdir, start) if start > 1 else ("", 0)
|
|
4389
4413
|
if arch_preface:
|
|
4390
|
-
parts.append("## 前文(第 1–%d 章 · 归档稿)" %
|
|
4414
|
+
parts.append("## 前文(第 1–%d 章 · 归档稿)" % arch_upto)
|
|
4391
4415
|
parts.append("")
|
|
4392
4416
|
parts.append(arch_preface)
|
|
4393
4417
|
parts.append("")
|
|
@@ -4414,7 +4438,7 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
|
|
|
4414
4438
|
summary="已合并 %d 章为 %s(约 %d 字%s%s)" % (
|
|
4415
4439
|
n, ms_name, total_words,
|
|
4416
4440
|
",分 %d 卷" % len(vol_heads) if vol_heads else "",
|
|
4417
|
-
",前文 1–%d 章取自归档" %
|
|
4441
|
+
",前文 1–%d 章取自归档" % arch_upto if arch_preface else ""),
|
|
4418
4442
|
duration_s=0.1)
|
|
4419
4443
|
|
|
4420
4444
|
chapters_pass = all(c["passed"] for c in chapter_scores)
|
package/app/core/planner.py
CHANGED
|
@@ -530,19 +530,24 @@ def locked_chapter_outline_text(workdir, chapter, cap=3000):
|
|
|
530
530
|
return _read_workdir_text(hits[-1], cap)
|
|
531
531
|
|
|
532
532
|
|
|
533
|
-
def locked_serial_outline_block(task, start, end, per_cap=2500, total_cap=
|
|
533
|
+
def locked_serial_outline_block(task, start, end, per_cap=2500, total_cap=None):
|
|
534
534
|
"""续写大纲生成的锁定章纲注入块:本批 [start, end] 逐章汇总章纲全文。
|
|
535
|
-
|
|
536
|
-
|
|
535
|
+
总量上限随批大小缩放(下限 16000、上限 32000)——2026-10-04 实案:12 章
|
|
536
|
+
批次章纲共 2.4 万字,旧固定 16000 截尾,第 45—48 章被生成成「待核:原
|
|
537
|
+
章名未提供」。一份章纲都没有时回退 大纲/*.md(截断兜底,至少锚住卷纲
|
|
538
|
+
方向);两者皆无返回 ""(零噪音)。"""
|
|
539
|
+
n = max(1, int(end) - int(start) + 1)
|
|
540
|
+
if total_cap is None:
|
|
541
|
+
total_cap = max(16000, min(32000, per_cap * n))
|
|
537
542
|
workdir = str(task.get("workdir") or "")
|
|
538
543
|
parts, used = [], 0
|
|
539
544
|
if workdir:
|
|
540
|
-
for
|
|
545
|
+
for num in range(int(start), int(end) + 1):
|
|
541
546
|
if used >= total_cap:
|
|
542
547
|
break
|
|
543
|
-
t = locked_chapter_outline_text(workdir,
|
|
548
|
+
t = locked_chapter_outline_text(workdir, num, cap=per_cap)
|
|
544
549
|
if t:
|
|
545
|
-
head = "### 第 %d 章锁定章纲" %
|
|
550
|
+
head = "### 第 %d 章锁定章纲" % num
|
|
546
551
|
parts.append(head + "\n" + t)
|
|
547
552
|
used += len(head) + len(t) + 2
|
|
548
553
|
if parts:
|
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