codebee 0.1.31 → 0.1.33

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 CHANGED
@@ -4,9 +4,28 @@ CodeBee 的用户可感知变更记录。发布新版时:最上面加一节,
4
4
  `<!-- relnotes:start -->…<!-- relnotes:end -->` 段(那段会被 `npm view` 的
5
5
  README 元数据带回,供老版本在「发现新版本」时展示新版更新内容)。
6
6
 
7
- ## 未发布
7
+ ## 未发布
8
+
9
+ ## v0.1.33(2026-09-21)
10
+
11
+ ### ✨ 新功能
12
+
13
+ - 创建任务支持快速/自动/专家/手动四档编排,以及独立的自动/快速/标准/深度思考程度;所有预置类型按风险动态决定规划、评审、修复和换将步骤。
14
+ - 对话默认使用系统推荐,也可仅为本次对话指定厂商或模型;指定渠道不可用时明确失败,不修改全局 CLI 绑定。
15
+ - 创建前显示同类历史或流程基线 ETA/P90,运行中显示剩余时间与超出预估状态;满载时不排队,异常退出的运行自动收口为失败。
16
+
17
+ ### 🛠 问题修复
18
+
19
+ - 修复 Windows GBK 控制台因特殊符号导致服务启动崩溃;Aider 启动前增加 Git 仓库可读性诊断,避免损坏仓库长时间卡住。
20
+ - 修复 Anthropic 兼容接口误收到 OpenAI `reasoning_effort` 字段;修复语言切换覆盖端口标题导致桌宠重复开窗;过滤 CLI 历史和评审中间文件,成果页只展示可交付产物。
21
+
22
+ ## v0.1.32(2026-09-21)
8
23
 
9
- ## v0.1.31(2026-09-21)
24
+ ### ✨ 新功能
25
+
26
+ - 连载任务详情新增「章节评审」卡片:每章的维度评分(低分标红)、达标状态、字数与修订轮数一目了然;每章按大纲逐项核对的判定结果(已完成/未完成/待核实)以红绿灰行直接展示——哪章哪个要点没写到一眼可查。
27
+
28
+ ## v0.1.31(2026-09-21)
10
29
 
11
30
  ### ✨ 新功能
12
31
 
package/README.md CHANGED
@@ -23,6 +23,17 @@ Kimi Code、MiMo Code、Grok Build、Pi、DeepSeek Harness……),提供
23
23
  <!-- relnotes:start -->
24
24
  ### ✨ 新功能 · New
25
25
 
26
+ - 创建任务支持快速/自动/专家/手动编排与独立思考程度;代码、写作、翻译、邮件、汇报、调研等全类型按风险动态选择步骤。
27
+ - 新建对话默认系统推荐,也可只对当前对话指定厂商/模型;创建前和运行中显示 ETA/P90 与剩余时间。
28
+ - New tasks support Fast/Auto/Expert/Manual orchestration and an independent reasoning level; every task type adapts its workflow to risk.
29
+ - Conversations use the system recommendation by default, with optional per-conversation provider/model selection plus ETA/P90 visibility.
30
+
31
+ - 修复 Windows 控制台启动崩溃、损坏 Git 仓库导致 Aider 长时间等待、Anthropic 接口收到不兼容思考字段,以及桌宠语言切换后重复开窗。
32
+ - Fixed Windows console startup crashes, Aider stalls on unreadable Git repositories, incompatible Anthropic reasoning fields, and duplicate pet windows after language changes.
33
+
34
+ - 连载任务详情新增「章节评审」卡片:每章维度评分(低分标红)与达标状态,大纲要点逐项核对结果红绿灰直读。
35
+ - Serial runs now show a Chapter Reviews card: per-chapter dimension scores (low ones in red) plus beat-by-beat checks color-coded green/red/gray.
36
+
26
37
  - 群摘要搬进正式页面:设置 →「微信群聊汇报」里配置与摘要列表一体呈现,右下角悬浮小窗已移除;桌面蜜蜂右键「群摘要」直达。
27
38
  - Group digests now live on a proper settings page (config + digest list in one place); the floating bottom-right widget is gone, and the desktop bee links straight to it.
28
39
 
@@ -961,7 +961,7 @@ def _run_code(run, task, agents, ev, stats, mode):
961
961
  and not task.get("attachments")
962
962
  and user_context_len < 600))
963
963
  planned = False
964
- if mode == "auto" and not fast_path:
964
+ if mode in ("auto", "expert") and not fast_path:
965
965
  _wait_gate(run_id, ev)
966
966
  plan_step, plan_log = store.add_step(run_id, "plan", impl["id"], impl.get("label"),
967
967
  note=route.get("implementer", ""))
@@ -1003,7 +1003,7 @@ def _run_code(run, task, agents, ev, stats, mode):
1003
1003
  if not workflow["review_required"]:
1004
1004
  reviewer = None
1005
1005
  route["reviewer"] = workflow["reason"]
1006
- elif mode == "auto":
1006
+ elif mode in ("auto", "expert"):
1007
1007
  reviewer, route["reviewer"] = router.pick_reviewer(agents, impl, "code", stats)
1008
1008
  else:
1009
1009
  reviewer, route["reviewer"] = _pick_reviewer_legacy(agents, impl)
@@ -3121,7 +3121,7 @@ def _run_content_review(run, task, agents, ev, stats, mode):
3121
3121
  error="没有可用智能体", ended_at=_now())
3122
3122
  return
3123
3123
  if resume_ctx is not None:
3124
- if mode == "auto":
3124
+ if mode != "manual":
3125
3125
  critics, route["critics"] = router.pick_critics(
3126
3126
  agents, task.get("type") or "novel", stats, impl=impl)
3127
3127
  else:
@@ -3153,7 +3153,7 @@ def _run_content_review(run, task, agents, ev, stats, mode):
3153
3153
  except Exception:
3154
3154
  return ""
3155
3155
 
3156
- draft_note = route.get("author", "") if mode == "auto" else ""
3156
+ draft_note = route.get("author", "") if mode != "manual" else ""
3157
3157
 
3158
3158
  # 编排者大纲:只对真实执行有意义;失败静默退回无大纲(喂入带指令的任务副本)
3159
3159
  outline = (planner.make_review_outline(_steered_task(run_id, task))
package/app/core/store.py CHANGED
@@ -486,6 +486,15 @@ def load_all():
486
486
 
487
487
  # ---------------------------------------------------------------- 运行(含管理操作)
488
488
 
489
+ _RUN_ESTIMATOR = None
490
+
491
+
492
+ def set_run_estimator(estimator):
493
+ """由应用入口注入 ETA 估算器,保持存储层不反向依赖用量模块。"""
494
+ global _RUN_ESTIMATOR
495
+ _RUN_ESTIMATOR = estimator if callable(estimator) else None
496
+
497
+
489
498
  def create_run(kind, title, task_id=None, entry_id=None, op=None):
490
499
  run = {
491
500
  "id": _new_id("r" if kind == "orchestration" else "m"),
@@ -501,8 +510,7 @@ def create_run(kind, title, task_id=None, entry_id=None, op=None):
501
510
  if kind == "orchestration" and task_id:
502
511
  task = get_task(task_id) or {}
503
512
  try:
504
- from . import usage
505
- eta = usage.estimate(
513
+ eta = _RUN_ESTIMATOR(
506
514
  task_type=task.get("type") or "", mode=task.get("mode") or "auto",
507
515
  thinking=task.get("thinking") or "standard",
508
516
  rounds=task.get("rounds"))
package/app/main.py CHANGED
@@ -2386,6 +2386,7 @@ def main():
2386
2386
  except Exception:
2387
2387
  pass
2388
2388
  from core import usage
2389
+ store.set_run_estimator(usage.estimate)
2389
2390
  _step("正在回填用量台账…")
2390
2391
  n_bf = usage.backfill_from_runs() # 历史运行 token 回填台账(幂等,仅补缺失步骤)
2391
2392
  if n_bf:
@@ -2536,7 +2537,8 @@ def main():
2536
2537
 
2537
2538
  print("[CodeBee] 本机 http://127.0.0.1:%d" % args.port, flush=True)
2538
2539
  print("[CodeBee] 数据目录 %s" % paths.DATA_DIR, flush=True)
2539
- print("[CodeBee] ✔ 已就绪,浏览器即将自动打开;不要关闭本窗口。", flush=True)
2540
+ # Windows 的默认 GBK 控制台无法编码部分符号,启动日志必须保持控制台安全。
2541
+ print("[CodeBee] [OK] 已就绪,浏览器即将自动打开;不要关闭本窗口。", flush=True)
2540
2542
  try:
2541
2543
  import faulthandler
2542
2544
  faulthandler.cancel_dump_traceback_later() # 启动完成,看门狗退役(否则运行期每 20s 误报堆栈)
package/app/ui/app.js CHANGED
@@ -4057,6 +4057,7 @@ async function renderRunDetail() {
4057
4057
  if (S.detailSide) fillMetaTask(S.detailSide.stats || {}); // 缓存命中:轮询重画不闪丢累计组
4058
4058
  renderPlan(run);
4059
4059
  renderRouting(run);
4060
+ renderChapterScores(run);
4060
4061
  // 详情页优先展示最近一步,排查运行中的任务时无需滚到底部;
4061
4062
  // 蜂巢泳道仍按原始流程顺序呈现,避免破坏阶段语义。
4062
4063
  $("rd-steps").innerHTML = (run.steps || []).slice().reverse().map((s) =>
@@ -5684,6 +5685,38 @@ function stepsMatch(runs, current) {
5684
5685
  (r.steps || []).some((s) => s.log === current.rel));
5685
5686
  }
5686
5687
 
5688
+ /* 连载章节评审卡:每章均分/是否达标/字数 + 逐项目标审稿结果(event_check,
5689
+ * 借鉴 AI-Novel-Writer:大纲要点逐项判定+正文证据)。非连载 run 无
5690
+ * chapter_scores 保持隐藏。 */
5691
+ function renderChapterScores(run) {
5692
+ const box = $("rd-chapters");
5693
+ if (!box) return;
5694
+ const cs = run && run.chapter_scores;
5695
+ if (!Array.isArray(cs) || !cs.length) { box.classList.add("hidden"); return; }
5696
+ box.classList.remove("hidden");
5697
+ box.innerHTML = '<h3 class="sec-title">' + t("章节评审") +
5698
+ '<span class="tag">' + cs.filter((c) => c.passed).length + "/" + cs.length + " " + t("达标") + "</span></h3>" +
5699
+ cs.map((c) => {
5700
+ const means = c.means || {};
5701
+ const dims = Object.keys(means).map((d) =>
5702
+ '<span class="cs-dim' + (means[d] >= 7 ? "" : " low") + '">' + esc(d) + " " + means[d] + "</span>").join("");
5703
+ const ev = (c.event_check || []).map((line) => {
5704
+ const ok = /已完成/.test(line), bad = /未完成/.test(line);
5705
+ return '<div class="cs-ev' + (ok ? " ok" : bad ? " bad" : "") + '">' + esc(line) + "</div>";
5706
+ }).join("");
5707
+ return '<div class="cs-row' + (c.passed ? "" : " fail") + '">' +
5708
+ '<div class="cs-head"><b>' + esc(t("第") + " " + c.chapter + " " + t("章")) + '</b>' +
5709
+ '<span class="cs-title">' + esc(c.title || "") + "</span>" +
5710
+ '<span class="tag">' + (c.passed ? t("达标") : t("未达标")) + "</span>" +
5711
+ (c.reused ? '<span class="tag">' + t("沿用") + "</span>" : "") +
5712
+ '<span class="cs-meta">' + Number(c.words || 0) + t(" 字") +
5713
+ (c.rounds > 1 ? " · " + c.rounds + t(" 轮") : "") + "</span></div>" +
5714
+ (dims ? '<div class="cs-dims">' + dims + "</div>" : "") +
5715
+ (ev ? '<div class="cs-evs"><span class="hint">' + t("逐项目标核对:") + "</span>" + ev + "</div>" : "") +
5716
+ "</div>";
5717
+ }).join("");
5718
+ }
5719
+
5687
5720
  function renderPlan(run) {
5688
5721
  const box = $("rd-plan");
5689
5722
  const plan = run.plan;
package/app/ui/i18n.js CHANGED
@@ -607,6 +607,15 @@
607
607
  "重命名任务": "Rename task",
608
608
  "↻ 继续任务": "↻ Resume task",
609
609
  "↻ 重写未达标章": "↻ Rewrite unqualified chapters",
610
+ "章节评审": "Chapter Reviews",
611
+ "达标": "passed",
612
+ "未达标": "missed",
613
+ "沿用": "reused",
614
+ "逐项目标核对:": "Beat-by-beat check: ",
615
+ "第": "Ch.",
616
+ "章": "",
617
+ " 字": " words",
618
+ " 轮": " rounds",
610
619
  "只重写上一遍未过线的章节,已过线章节沿用成稿与评分": "Rewrites only the chapters that missed the threshold last run; passing chapters keep their drafts and scores.",
611
620
  "再跑一次这个任务;连载任务会断点续跑,已完成章节不重写": "Run this task again; serial novels resume from the breakpoint — finished chapters are kept.",
612
621
  "✎ 编辑重试": "✎ Edit & retry",
package/app/ui/index.html CHANGED
@@ -508,6 +508,8 @@
508
508
  </div>
509
509
  <div id="rd-pane-steps" class="rd-pane" role="tabpanel" aria-labelledby="rd-tab-steps" data-pane="steps">
510
510
  <div id="rd-plan" class="hidden"></div>
511
+ <div id="rd-routing" class="rd-routing hidden"></div>
512
+ <div id="rd-chapters" class="rd-chapters hidden"></div>
511
513
  <div id="rd-steps" class="steps"></div>
512
514
  </div>
513
515
  <div id="rd-pane-result" class="rd-pane" role="tabpanel" aria-labelledby="rd-tab-result" data-pane="result">
package/app/ui/style.css CHANGED
@@ -5596,3 +5596,20 @@ button.request-busy > * { opacity: .18; }
5596
5596
  #sub-__wxdigest .bee-cfg { display: flex; flex-direction: column; gap: 10px; }
5597
5597
  #sub-__wxdigest .bee-list { max-height: 52vh; overflow: auto; }
5598
5598
  #sub-__wxdigest .bee-groups-list { max-height: 240px; }
5599
+
5600
+ /* 连载章节评审卡:均分徽标 + 逐项目标审稿(event_check)行级红绿 */
5601
+ .rd-chapters { margin: 8px 0; }
5602
+ .cs-row { border: 1px solid var(--border, rgba(128,128,128,.22)); border-radius: 8px;
5603
+ padding: 8px 10px; margin: 6px 0; display: flex; flex-direction: column; gap: 4px; }
5604
+ .cs-row.fail { border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
5605
+ .cs-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
5606
+ .cs-title { color: var(--muted); font-size: 12.5px; }
5607
+ .cs-meta { margin-left: auto; color: var(--muted); font-size: 12px; }
5608
+ .cs-dims { display: flex; gap: 6px; flex-wrap: wrap; }
5609
+ .cs-dim { font-size: 11.5px; padding: 1px 8px; border-radius: 999px;
5610
+ background: color-mix(in srgb, var(--ok) 12%, transparent); }
5611
+ .cs-dim.low { background: color-mix(in srgb, var(--bad) 14%, transparent); }
5612
+ .cs-evs { display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
5613
+ .cs-ev { padding-left: 10px; border-left: 2px solid var(--border); color: var(--muted); }
5614
+ .cs-ev.ok { border-left-color: var(--ok); color: inherit; }
5615
+ .cs-ev.bad { border-left-color: var(--bad); color: inherit; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebee",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "description": "CodeBee · 多智能体编排台 — 统一编排本机 AI 编码 CLI(Codex / Claude Code / QwenCode / OpenCode / Aider…):目标→拆解→路由→执行→验证→跨厂商评审→修复→报告。纯 Python 标准库实现,本地 Web UI。",
5
5
  "license": "MIT",
6
6
  "bin": {