codebee 0.1.96 → 0.1.97

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
@@ -6,6 +6,14 @@ README 元数据带回,供老版本在「发现新版本」时展示新版更
6
6
 
7
7
  ## 未发布
8
8
 
9
+ - **蜂巢「3D 场景」重做为真 3D 蜜蜂办公室(WebGL)**:此前的 3D 只是把平面卡片整体斜切(CSS 透视),现换成零依赖 WebGL2 引擎渲染的蜜蜂办公室——每个流水线阶段是一排工位,每个步骤是一只坐在桌前对着显示器的低多边形蜜蜂:运行中的屏幕亮蓝脉动+蜜蜂打字颤翅、完成绿屏、失败红屏+趴桌、排队黑屏打盹;蜂王戴皇冠坐讲台、始终面向当前在干活的工位,巡逻蜂平时绕场巡查、有格子跑起来就飞去悬停督工。左键拖动旋转/滚轮缩放/右键升降/双击空白复位,空闲 8 秒缓慢自转(尊重系统减弱动效设置);悬停工位出气泡卡(角色/模型/实时输出/思考行),点按直接开日志抽屉;换肤与明暗主题自动跟随;WebGL 不可用或上下文丢失自动回落 2D 列表并记忆视图偏好。
10
+
11
+ ## v0.1.97(2026-10-09)
12
+
13
+ - **知识注入扩展到全部任务类型**:引擎经验库与知识库此前只在连载链命中,现按任务类型全量覆盖(代码/文档/翻译/调研等全部受益)
14
+ - 命中计数不重复累加:同条目同轮只记一次;被预算丢弃的条目不记 hits——修复「从未被读到的内容反而升权、挤占预算」的反馈回路缺陷
15
+ - 注入结果与旧版字节一致(回归保障);66 班全类型矩阵回归测试 84 项
16
+
9
17
  ## v0.1.96(2026-10-08)
10
18
 
11
19
  - **3D 交互式蜂巢工作台视图**:任务流程以三维场景呈现,节点/连线/状态立体可视化,支持旋转缩放拖拽交互
package/README.md CHANGED
@@ -25,9 +25,10 @@ Trae Agent、OpenClaw……),提供
25
25
  ---
26
26
 
27
27
  <!-- relnotes:start -->
28
- ### 最新版更新内容(v0.1.96)
28
+ ### 最新版更新内容(v0.1.97)
29
29
 
30
- - 新增 3D 交互式蜂巢工作台视图:任务流程三维可视化(旋转/缩放/拖拽交互)
30
+ - 知识注入扩展到全部任务类型:引擎经验库/知识库全量覆盖,不再只有连载链受益
31
+ - 命中计数不重复累加,修复「从未被读到反而升权」的反馈回路缺陷
31
32
  <!-- relnotes:end -->
32
33
 
33
34
 
@@ -19,16 +19,34 @@ MAX_FILE_CHARS = 8000
19
19
  MAX_PROMPT_CHARS = 24000
20
20
 
21
21
 
22
- def _roots(workdir):
22
+ def _roots(workdir, boundary=None):
23
23
  try:
24
24
  current = Path(workdir).expanduser().resolve()
25
25
  except (TypeError, OSError, ValueError):
26
26
  return []
27
27
  if not current.is_dir():
28
28
  return []
29
+ # Trust instructions only through the nearest repository root. Outside a
30
+ # repository, the selected workdir itself is the boundary; never walk into
31
+ # an unrelated parent directory (or drive root).
32
+ try:
33
+ if boundary:
34
+ stop = Path(boundary).expanduser().resolve()
35
+ else:
36
+ stop = current
37
+ for candidate in (current, *current.parents):
38
+ if (candidate / ".git").exists():
39
+ stop = candidate
40
+ break
41
+ except (TypeError, OSError, ValueError):
42
+ stop = current
43
+ if current != stop and stop not in current.parents:
44
+ stop = current
29
45
  roots = []
30
46
  while True:
31
47
  roots.append(current)
48
+ if current == stop:
49
+ break
32
50
  parent = current.parent
33
51
  if parent == current:
34
52
  break
@@ -50,7 +68,7 @@ def _read(path):
50
68
  return ""
51
69
 
52
70
 
53
- def discover(workdir, *, max_files=MAX_FILES, max_chars=MAX_PROMPT_CHARS):
71
+ def discover(workdir, *, boundary=None, max_files=MAX_FILES, max_chars=MAX_PROMPT_CHARS):
54
72
  """Return nearest-first AGENTS.md guidance and stable metadata."""
55
73
  try:
56
74
  file_limit = max(1, min(MAX_FILES, int(max_files)))
@@ -60,7 +78,7 @@ def discover(workdir, *, max_files=MAX_FILES, max_chars=MAX_PROMPT_CHARS):
60
78
  records = []
61
79
  chunks = []
62
80
  used = 0
63
- for root in _roots(workdir):
81
+ for root in _roots(workdir, boundary=boundary):
64
82
  if len(records) >= file_limit:
65
83
  break
66
84
  path = root / "AGENTS.md"
package/app/core/board.py CHANGED
@@ -13,8 +13,8 @@ _CACHE = {"ts": 0.0, "data": None}
13
13
  _TTL = 8.0
14
14
 
15
15
  _TAIL_MAX = 150 # 跑马灯尾行截断
16
- _TAIL_LINES = 6 # 实时流窗口行数
17
- _TAIL_LINE_CHARS = 56 # 实时流单行截断(卡内 11px 等宽不换行的安全宽度)
16
+ _TAIL_LINES = 14 # 实时流窗口行数(单任务卡的终端约 20 行,留余量)
17
+ _TAIL_LINE_CHARS = 110 # 实时流单行截断;卡内 pre-wrap,超宽会折行而不是切掉
18
18
  _RECENT_LIMIT = 10 # 最近完成/失败条数
19
19
  _RUN_WINDOW = 300 # 今日计数扫描的运行窗口(id 字典序=时间序)
20
20
 
@@ -29,6 +29,43 @@ def payload():
29
29
  return data
30
30
 
31
31
 
32
+ def run_detail(run_id):
33
+ """单条运行的步骤链,供大屏下钻抽屉;不进 8 秒缓存(点开即要最新)。
34
+
35
+ 只给步骤概要,日志正文不在这里搬——前端选中某一步时走现成的
36
+ /api/runs/<id>/log?step=<log>&pretty=1,那份已有目录穿越防护和 tail 夹取。
37
+ """
38
+ from . import store
39
+
40
+ run = store.get_run(str(run_id or ""))
41
+ if not run:
42
+ return None
43
+ steps = []
44
+ for s in (run.get("steps") or []):
45
+ steps.append({
46
+ "n": s.get("n"), "role": s.get("role") or "",
47
+ "agent": s.get("agent") or "",
48
+ "agent_label": s.get("agent_label") or s.get("agent") or "",
49
+ "status": s.get("status") or "",
50
+ "started_at": s.get("started_at") or "", "ended_at": s.get("ended_at") or "",
51
+ "duration_s": s.get("duration_s"),
52
+ "summary": (s.get("summary") or "")[:120],
53
+ "log": s.get("log") or "",
54
+ "tokens": s.get("tokens") or 0,
55
+ "cost_usd": round(float(s.get("cost_usd") or 0.0), 4),
56
+ "exit_code": s.get("exit_code"),
57
+ "error": (s.get("error") or "")[:160],
58
+ })
59
+ return {
60
+ "run_id": run.get("id"), "task_id": run.get("task_id") or "",
61
+ "title": run.get("title") or "", "status": run.get("status") or "",
62
+ "started_at": run.get("started_at") or run.get("created_at") or "",
63
+ "ended_at": run.get("ended_at") or "",
64
+ "error": (run.get("error") or "")[:200],
65
+ "steps": steps,
66
+ }
67
+
68
+
32
69
  def _tail(step):
33
70
  """步骤实时流(正文优先,其次思考)的最后一行,给大屏跑马灯。"""
34
71
  for key in ("stream", "thinking"):