codebee 0.1.59 → 0.1.60
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 +2 -3
- package/app/core/pipeline.py +44 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -24,6 +24,11 @@ README 元数据带回,供老版本在「发现新版本」时展示新版更
|
|
|
24
24
|
|
|
25
25
|
- **首选 KEY 超限自动切备用了**:同厂商多密钥此前只认欠费类文案——首选 KEY 撞上 429 限流(智谱「并发数超过限制」「每分钟Token数已超过上限」、claude 的 rate_limit_error、codex 的 "429 Too Many Requests" 等)只记一笔错误、不进冷却,每个新步骤仍从超限的首选 KEY 重新烧起。现在限流文案与欠费同口径:进冷却 30 分钟、密钥镜像自动切下一把、链展开跳过冷却中的 KEY(到期或「恢复」按钮一键回首选)。顺带补一处漏账:无显式链时「换模型回退」的链条目不带 KEY 标记,这类重试失败此前完全不记 KEY 账。
|
|
26
26
|
|
|
27
|
+
## v0.1.60(2026-09-23)
|
|
28
|
+
|
|
29
|
+
- 同工作目录并行硬限制:两个任务共用同一工作目录时,后来者自动排队等待(每 60 秒重试,先来者完成自动放行)——不再只是告警,彻底杜绝任务计划/项目记忆/分支检出互相覆盖(禅道双单实案)
|
|
30
|
+
- 工作目录被占用时任务卡片显示「将于 HH:MM 自动续跑」,排队原因可见
|
|
31
|
+
|
|
27
32
|
## v0.1.59(2026-09-23)
|
|
28
33
|
|
|
29
34
|
- 评审器故障不再伪装「评审未通过」:评审器鉴权失效/崩溃时(实案:Invalid API Key 整晚空转修复轮),任务以「评审器故障(评审未执行)」明确收口,不再烧无意义的修复轮
|
package/README.md
CHANGED
|
@@ -21,10 +21,9 @@ Kimi Code、MiMo Code、Grok Build、Pi、DeepSeek Harness……),提供
|
|
|
21
21
|
不会把你的任务内容交给任何第三方。
|
|
22
22
|
|
|
23
23
|
<!-- relnotes:start -->
|
|
24
|
-
### 最新版更新内容(v0.1.
|
|
24
|
+
### 最新版更新内容(v0.1.60)
|
|
25
25
|
|
|
26
|
-
-
|
|
27
|
-
- 同工作目录并行任务自动告警;后台标签页让出连接,多标签不再互相挤超时
|
|
26
|
+
- 同工作目录并行硬限制:后来任务自动排队等待(60 秒重试、先来者完成自动放行),不再互相覆盖
|
|
28
27
|
<!-- relnotes:end -->
|
|
29
28
|
|
|
30
29
|
---
|
package/app/core/pipeline.py
CHANGED
|
@@ -4114,6 +4114,23 @@ def _write_task_plan(task, workdir, plan):
|
|
|
4114
4114
|
return ""
|
|
4115
4115
|
|
|
4116
4116
|
|
|
4117
|
+
def _workdir_blocker(task, run_id):
|
|
4118
|
+
"""同工作目录互斥:返回占用该目录的运行中/排队任务(无则 None)。
|
|
4119
|
+
任务计划/项目记忆/任务分支检出都是工作目录级共享状态,并行会互相覆盖
|
|
4120
|
+
(2026-09-23 禅道双单实案),故同目录只允许一个任务在跑。"""
|
|
4121
|
+
wd = (task.get("workdir") or "").rstrip("/\\")
|
|
4122
|
+
if not wd:
|
|
4123
|
+
return None
|
|
4124
|
+
for t in store.list_tasks(200):
|
|
4125
|
+
if (t.get("id") == task.get("id")
|
|
4126
|
+
or t.get("status") not in ("running", "queued")
|
|
4127
|
+
or (t.get("workdir") or "").rstrip("/\\") != wd):
|
|
4128
|
+
continue
|
|
4129
|
+
if jobs._task_active_run(t.get("id"), exclude_run_id=run_id):
|
|
4130
|
+
return t
|
|
4131
|
+
return None
|
|
4132
|
+
|
|
4133
|
+
|
|
4117
4134
|
def execute_run(run_id):
|
|
4118
4135
|
run = store.get_run(run_id)
|
|
4119
4136
|
if not run:
|
|
@@ -4157,23 +4174,35 @@ def execute_run(run_id):
|
|
|
4157
4174
|
task["difficulty"] = task_spec["difficulty"]
|
|
4158
4175
|
# 同理,历史任务可能保存非法/过期 engine;执行以编译后的流程引擎为准。
|
|
4159
4176
|
task["engine"] = task_spec["engine"]
|
|
4160
|
-
#
|
|
4161
|
-
#
|
|
4162
|
-
#
|
|
4163
|
-
#
|
|
4177
|
+
# 同工作目录互斥(2026-09-23 用户拍板「不能并行就要限制」):任务计划
|
|
4178
|
+
# (.codebee/task_plan.md)、项目记忆与任务分支检出都是工作目录级共享状态,
|
|
4179
|
+
# 两任务同目录并行会互相覆盖/干扰(禅道双单实案:A 的评审 diff 混进 B 的
|
|
4180
|
+
# 任务计划)。后来者回滚 queued 并挂 60s 重试 Timer——先来者完成后的
|
|
4181
|
+
# 下一拍自动放行(「将于 HH:MM 自动续跑」对用户可见)。
|
|
4164
4182
|
try:
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4183
|
+
_blocker = _workdir_blocker(task, run_id)
|
|
4184
|
+
if True:
|
|
4185
|
+
_wd = (task.get("workdir") or "").rstrip("/\\")
|
|
4186
|
+
if _blocker is not None:
|
|
4187
|
+
_resume_at = time.strftime("%Y-%m-%d %H:%M:%S",
|
|
4188
|
+
time.localtime(time.time() + 60))
|
|
4189
|
+
store.update_run(run_id, expected_status="running", status="queued",
|
|
4190
|
+
started_at="", resume_enqueue_at=_resume_at,
|
|
4191
|
+
warnings=["工作目录被运行中任务「%s」占用,排队等待(每 60 秒自动重试)"
|
|
4192
|
+
% ((_blocker.get("title") or _blocker.get("id") or "")[:24])])
|
|
4193
|
+
try:
|
|
4194
|
+
store.update_task_status(task.get("id"), "queued")
|
|
4195
|
+
except Exception:
|
|
4196
|
+
pass
|
|
4197
|
+
jobs._schedule_enqueue(
|
|
4198
|
+
{"kind": "orchestration", "run_id": run_id,
|
|
4199
|
+
"task_id": task.get("id")}, 60)
|
|
4200
|
+
print("[CodeBee] 工作目录被「%s」占用:%s 排队等待,60 秒后自动重试"
|
|
4201
|
+
% ((_blocker.get("title") or _blocker.get("id") or "")[:24],
|
|
4202
|
+
task.get("title") or task.get("id")), flush=True)
|
|
4203
|
+
return
|
|
4175
4204
|
except Exception:
|
|
4176
|
-
pass
|
|
4205
|
+
pass # 检测失败不挡主流程
|
|
4177
4206
|
# 代码版本检出:任务指定了基线版本时,先检出任务分支 tutti/<task-id> 再跑流水线。
|
|
4178
4207
|
# 显式意图不容静默降级——仓库缺失/脏工作区/引用不存在一律中止运行并报错,
|
|
4179
4208
|
# 绝不带着用户未提交改动切分支、也不悄悄退回当前 HEAD。
|
package/package.json
CHANGED