codebee 0.1.23 → 0.1.25
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 +26 -0
- package/README.md +23 -4
- package/app/core/attachments.py +174 -4
- package/app/core/dispatch.py +34 -5
- package/app/core/dispatch_log.py +113 -0
- package/app/core/errorlog.py +1 -43
- package/app/core/jobs.py +30 -4
- package/app/core/modelhub.py +2 -0
- package/app/core/paths.py +2 -2
- package/app/core/pipeline.py +92 -28
- package/app/core/portguard.py +111 -0
- package/app/core/portscan.py +188 -188
- package/app/core/redact.py +38 -0
- package/app/core/router.py +34 -8
- package/app/core/runner.py +15 -8
- package/app/core/selfupdate.py +86 -27
- package/app/core/store.py +35 -15
- package/app/core/usage.py +226 -24
- package/app/main.py +54 -22
- package/app/pet.py +34 -11
- package/app/ui/app.js +55 -3
- package/app/ui/i18n.js +2 -0
- package/app/ui/index.html +1 -0
- package/package.json +1 -1
package/app/pet.py
CHANGED
|
@@ -1283,7 +1283,8 @@ class PetApp:
|
|
|
1283
1283
|
command=lambda: self._set_lang("en"),
|
|
1284
1284
|
variable=self._lang_var, value="en")
|
|
1285
1285
|
m.add_separator()
|
|
1286
|
-
m.add_command(label=self._L("close"),
|
|
1286
|
+
m.add_command(label=self._L("close"),
|
|
1287
|
+
command=lambda: self._bye(write_setting=True))
|
|
1287
1288
|
return m
|
|
1288
1289
|
|
|
1289
1290
|
def _set_mode(self, mode):
|
|
@@ -1308,6 +1309,8 @@ class PetApp:
|
|
|
1308
1309
|
cv = self.cv
|
|
1309
1310
|
self._press = None
|
|
1310
1311
|
self._moved = False
|
|
1312
|
+
self._drag_to = None
|
|
1313
|
+
self._drag_pending = False
|
|
1311
1314
|
cv.bind("<ButtonPress-1>", self._on_press)
|
|
1312
1315
|
cv.bind("<B1-Motion>", self._on_motion)
|
|
1313
1316
|
cv.bind("<ButtonRelease-1>", self._on_release)
|
|
@@ -1316,22 +1319,32 @@ class PetApp:
|
|
|
1316
1319
|
self.root.protocol("WM_DELETE_WINDOW", self._bye)
|
|
1317
1320
|
|
|
1318
1321
|
def _on_press(self, e):
|
|
1319
|
-
|
|
1322
|
+
# 窗口拖动起点:屏幕坐标 + 窗口原点一起记(scan_mark/scan_dragto 是
|
|
1323
|
+
# canvas 系 widget 的子命令,顶层窗口没有——此前绑定在这里的拖动
|
|
1324
|
+
# 实际全部抛 AttributeError 被 except 吞掉,表现为「拖不动」)
|
|
1325
|
+
self._press = (e.x_root, e.y_root, self.root.winfo_x(), self.root.winfo_y())
|
|
1320
1326
|
self._moved = False
|
|
1321
|
-
try:
|
|
1322
|
-
self.root.scan_mark(e.x_root, e.y_root) # Tk 内置 C 级拖动,跟手
|
|
1323
|
-
except Exception:
|
|
1324
|
-
pass
|
|
1325
1327
|
|
|
1326
1328
|
def _on_motion(self, e):
|
|
1327
1329
|
if not self._press:
|
|
1328
1330
|
return
|
|
1329
|
-
|
|
1331
|
+
px, py, wx, wy = self._press
|
|
1332
|
+
if (abs(e.x_root - px) + abs(e.y_root - py) > 4):
|
|
1330
1333
|
self._moved = True
|
|
1331
|
-
#
|
|
1332
|
-
#
|
|
1334
|
+
# geometry 逐事件会卡成 PPT;这里合并到 ~60fps 节流(事件风暴只在
|
|
1335
|
+
# 节流窗内记终点,一次 geometry 落位),实测跟手且不吃 CPU
|
|
1336
|
+
self._drag_to = (wx + (e.x_root - px), wy + (e.y_root - py))
|
|
1337
|
+
if self._drag_pending:
|
|
1338
|
+
return
|
|
1339
|
+
self._drag_pending = True
|
|
1340
|
+
self.root.after(16, self._apply_drag)
|
|
1341
|
+
|
|
1342
|
+
def _apply_drag(self):
|
|
1343
|
+
self._drag_pending = False
|
|
1344
|
+
if not self._drag_to:
|
|
1345
|
+
return
|
|
1333
1346
|
try:
|
|
1334
|
-
self.root.
|
|
1347
|
+
self.root.geometry("+%d+%d" % self._drag_to)
|
|
1335
1348
|
except Exception:
|
|
1336
1349
|
pass
|
|
1337
1350
|
|
|
@@ -1344,7 +1357,17 @@ class PetApp:
|
|
|
1344
1357
|
else:
|
|
1345
1358
|
self._open_ui()
|
|
1346
1359
|
|
|
1347
|
-
def _bye(self):
|
|
1360
|
+
def _bye(self, write_setting=False):
|
|
1361
|
+
"""退出。write_setting=True(右键菜单「关闭桌宠」)先把 pet_enabled=False
|
|
1362
|
+
写回服务端设置——否则看护/下次启动都会按设置里的 enabled 把蜜蜂复活,
|
|
1363
|
+
用户点关闭等于没关(2026-09-21 用户实测「宠物关不了」的根因:菜单
|
|
1364
|
+
关闭只销毁窗口不落设置,与注释宣称的契约相反)。服务端 pet_enabled
|
|
1365
|
+
已为 False 的自离路径(轮询发现/miss 超限)无需再写。"""
|
|
1366
|
+
if write_setting:
|
|
1367
|
+
try:
|
|
1368
|
+
self._post_settings({"pet_enabled": False})
|
|
1369
|
+
except Exception:
|
|
1370
|
+
pass
|
|
1348
1371
|
try:
|
|
1349
1372
|
self._save_cfg(x=self.root.winfo_x(), y=self.root.winfo_y())
|
|
1350
1373
|
except Exception:
|
package/app/ui/app.js
CHANGED
|
@@ -2026,7 +2026,8 @@ async function createTask() {
|
|
|
2026
2026
|
msg.textContent = t("目标有点简短,先问几个问题…");
|
|
2027
2027
|
try {
|
|
2028
2028
|
const cq = await api("/api/tasks/clarify", {
|
|
2029
|
-
|
|
2029
|
+
// 澄清只是增强,不能让建任务被模型调用拖住;超时后直接按原目标开跑。
|
|
2030
|
+
method: "POST", timeout: 8000,
|
|
2030
2031
|
body: JSON.stringify({ goal: payload.goal, type: payload.type }) });
|
|
2031
2032
|
const qs = (cq && cq.questions) || [];
|
|
2032
2033
|
if (qs.length) {
|
|
@@ -2034,7 +2035,10 @@ async function createTask() {
|
|
|
2034
2035
|
renderClarify(qs, payload.goal, resetSubmit);
|
|
2035
2036
|
return;
|
|
2036
2037
|
}
|
|
2037
|
-
} catch (e) {
|
|
2038
|
+
} catch (e) {
|
|
2039
|
+
// 澄清服务不可用或超时不阻塞主流程,明确告诉用户已经自动继续。
|
|
2040
|
+
msg.textContent = t("澄清响应较慢,已直接创建任务…");
|
|
2041
|
+
}
|
|
2038
2042
|
}
|
|
2039
2043
|
S.clarifyDone = false;
|
|
2040
2044
|
if (!payload.workdir) delete payload.workdir; // 留空 → 服务端用「默认保存路径」(编排设置可改)
|
|
@@ -2378,6 +2382,7 @@ async function deleteTask(id) {
|
|
|
2378
2382
|
if (!await uiConfirm(t("删除该任务及其全部运行记录(含日志与报告)?不可恢复。"), { ok: t("删除"), danger: true })) return;
|
|
2379
2383
|
let gone = false;
|
|
2380
2384
|
try {
|
|
2385
|
+
toast(t("正在删除任务…"));
|
|
2381
2386
|
await api("/api/tasks/" + encodeURIComponent(id) + "/delete", { method: "POST" });
|
|
2382
2387
|
} catch (e) {
|
|
2383
2388
|
// 任务已不在(他端删过 / 重复点):不报错晾着,照常把视图清掉
|
|
@@ -3315,6 +3320,24 @@ function setEditRetry(taskId, status, taskExists) {
|
|
|
3315
3320
|
if (bn) bn.classList.toggle("hidden", !taskExists || failedish);
|
|
3316
3321
|
}
|
|
3317
3322
|
|
|
3323
|
+
/* 详情页归档按钮:非运行中显示;已归档任务显示「取消归档」。
|
|
3324
|
+
* 点击走 archiveTask(与右键菜单同一链路:取消归档会自动恢复侧栏目录显示)。 */
|
|
3325
|
+
function syncArchBtn(task, active) {
|
|
3326
|
+
const b = $("btn-arch");
|
|
3327
|
+
if (!b) return;
|
|
3328
|
+
const show = !!task && !active;
|
|
3329
|
+
b.classList.toggle("hidden", !show);
|
|
3330
|
+
if (!show) return;
|
|
3331
|
+
const archived = !!task.archived;
|
|
3332
|
+
b.textContent = archived ? t("取消归档") : t("归档任务");
|
|
3333
|
+
b.onclick = async () => {
|
|
3334
|
+
try {
|
|
3335
|
+
await archiveTask(task.id, !archived);
|
|
3336
|
+
b.textContent = archived ? t("归档任务") : t("取消归档");
|
|
3337
|
+
} catch (e) { /* archiveTask 内部已 toast */ }
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
|
|
3318
3341
|
/* 重试按钮三态:失败/取消 → 「↻ 继续任务」(断点续跑语义);连载任务完整跑完
|
|
3319
3342
|
* 但质量未达标(verdict.publishable=false)→ 「↻ 重写未达标章」——后端 retry
|
|
3320
3343
|
* 会把未过线章从继承清单剔除,只重写重评这几章(store.retry_task 未达标分支);
|
|
@@ -3346,6 +3369,7 @@ function renderTaskDetail() {
|
|
|
3346
3369
|
if (bc) bc.classList.toggle("hidden",
|
|
3347
3370
|
!(tk && tk.serial && tk.status !== "running" && tk.status !== "queued"));
|
|
3348
3371
|
setEditRetry(tk ? tk.id : "", tk ? tk.status : "", !!tk);
|
|
3372
|
+
syncArchBtn(tk, tk && (tk.status === "running" || tk.status === "queued"));
|
|
3349
3373
|
const isTask = ((S.state || {}).tasks || []).some((t2) => t2.id === key);
|
|
3350
3374
|
if (isTask) {
|
|
3351
3375
|
api("/api/tasks/" + encodeURIComponent(key) + "/runs")
|
|
@@ -3779,6 +3803,9 @@ async function renderRunDetail() {
|
|
|
3779
3803
|
$("btn-share").classList.toggle("hidden", active); // 分享页:结束后可生成自包含 HTML
|
|
3780
3804
|
$("btn-talk").classList.toggle("hidden", !(run.task_id && !chatEngineIsDirect(run)));
|
|
3781
3805
|
const rcTask = ((S.state || {}).tasks || []).find((x) => x.id === run.task_id);
|
|
3806
|
+
// 归档按钮:非运行中任务可归档/取消归档(此前只有侧栏右键菜单入口,
|
|
3807
|
+
// 用户反馈「归档按钮不见了」——补显式入口,文案随状态切换)
|
|
3808
|
+
syncArchBtn(rcTask, active);
|
|
3782
3809
|
setRetryBtn(run, rcTask);
|
|
3783
3810
|
$("btn-continue").classList.toggle("hidden",
|
|
3784
3811
|
!(rcTask && rcTask.serial && run.status !== "running" && run.status !== "queued"));
|
|
@@ -9287,7 +9314,7 @@ function renderSu() {
|
|
|
9287
9314
|
t(" ") + "<a href=\"#\" onclick=\"event.preventDefault();suApply()\">" + t("立即升级") + "</a></b></p>";
|
|
9288
9315
|
if (SU.notes) {
|
|
9289
9316
|
html += "<div class=\"hint\"><b>" + t("新版本更新内容") + t(":") + "</b>" +
|
|
9290
|
-
|
|
9317
|
+
renderRelnotes(SU.notes) + "</div>";
|
|
9291
9318
|
}
|
|
9292
9319
|
} else if (SU.mode === "npm" && !SU.note) {
|
|
9293
9320
|
html += "<p class=\"hint\">" + t("已是最新版。") + "</p>";
|
|
@@ -9303,6 +9330,31 @@ function renderSu() {
|
|
|
9303
9330
|
renderUpdPill();
|
|
9304
9331
|
}
|
|
9305
9332
|
|
|
9333
|
+
/* 更新说明分类渲染:### 行渲染为小节标题,- 行渲染为条目(对照主流产品的
|
|
9334
|
+
* 更新日志样式:问题修复/新功能分组,一眼看懂)。全部 esc 后拼接。 */
|
|
9335
|
+
function renderRelnotes(txt) {
|
|
9336
|
+
const lines = String(txt || "").replace(/\r/g, "").split("\n");
|
|
9337
|
+
let html = "", inList = false;
|
|
9338
|
+
const closeList = () => { if (inList) { html += "</div>"; inList = false; } };
|
|
9339
|
+
for (const raw of lines) {
|
|
9340
|
+
const line = raw.trim();
|
|
9341
|
+
if (!line) continue;
|
|
9342
|
+
if (/^#{2,4}\s+/.test(line)) {
|
|
9343
|
+
closeList();
|
|
9344
|
+
html += "<p style=\"margin:6px 0 2px\"><b>" + esc(line.replace(/^#{2,4}\s+/, "")) + "</b></p>";
|
|
9345
|
+
} else if (/^[-*]\s+/.test(line)) {
|
|
9346
|
+
if (!inList) { html += "<div style=\"margin:2px 0 2px 4px\">"; inList = true; }
|
|
9347
|
+
html += "<div style=\"display:flex;gap:6px\"><span style=\"opacity:.6\">·</span>" +
|
|
9348
|
+
"<span style=\"flex:1\">" + esc(line.replace(/^[-*]\s+/, "")) + "</span></div>";
|
|
9349
|
+
} else {
|
|
9350
|
+
closeList();
|
|
9351
|
+
html += "<p style=\"margin:2px 0\">" + esc(line) + "</p>";
|
|
9352
|
+
}
|
|
9353
|
+
}
|
|
9354
|
+
closeList();
|
|
9355
|
+
return html || ("<pre class=\"su-notes\">" + esc(txt) + "</pre>");
|
|
9356
|
+
}
|
|
9357
|
+
|
|
9306
9358
|
/* 顶栏左上角常驻更新胶囊:有新版才出现(同版本被忽略后不再出现),
|
|
9307
9359
|
* 点击直达「关于与更新」,× 忽略本版本(与 su.seen 记账键同一套语义) */
|
|
9308
9360
|
function renderUpdPill() {
|
package/app/ui/i18n.js
CHANGED
|
@@ -584,6 +584,8 @@
|
|
|
584
584
|
"勾选可批量删除": "Tick to bulk delete",
|
|
585
585
|
"取消归档": "Unarchive",
|
|
586
586
|
"归档": "Archive",
|
|
587
|
+
"归档任务": "Archive Task",
|
|
588
|
+
"归档后任务从侧栏收起,可随时用左下角时钟图标找回并取消归档": "Archiving hides the task from the sidebar; use the clock icon at the bottom-left to find it back and unarchive anytime",
|
|
587
589
|
"重命名任务": "Rename task",
|
|
588
590
|
"↻ 继续任务": "↻ Resume task",
|
|
589
591
|
"↻ 重写未达标章": "↻ Rewrite unqualified chapters",
|
package/app/ui/index.html
CHANGED
|
@@ -388,6 +388,7 @@
|
|
|
388
388
|
<button data-i18n="✎ 编辑重试" id="btn-editretry" class="ghost hidden" data-i18n-title="取回原任务的目标/目录/评审设置,修改后提交即重新开跑" title="取回原任务的目标/目录/评审设置,修改后提交即重新开跑">✎ 编辑重试</button>
|
|
389
389
|
<button data-i18n="继续连载" id="btn-continue" class="ghost hidden">继续连载</button>
|
|
390
390
|
<button data-i18n="基于此任务新建" id="btn-newfrom" class="ghost hidden">基于此任务新建</button>
|
|
391
|
+
<button data-i18n="归档任务" id="btn-arch" class="ghost hidden" data-i18n-title="归档后任务从侧栏收起,可随时用左下角时钟图标找回并取消归档" title="归档后任务从侧栏收起,可随时用左下角时钟图标找回并取消归档">归档任务</button>
|
|
391
392
|
<button data-i18n="分享页" id="btn-share" class="ghost hidden" data-i18n-title="生成自包含分享页(单文件 HTML),可直接发给他人查看任务成果" title="生成自包含分享页(单文件 HTML),可直接发给他人查看任务成果">分享页</button>
|
|
392
393
|
<button data-i18n="删除记录" id="btn-delete" class="danger hidden">删除记录</button>
|
|
393
394
|
<button data-i18n="✉ 继续对话" id="btn-talk" class="ghost hidden" data-i18n-title="人工检查有问题?告诉主智能体,由它判断怎么引导执行" title="人工检查有问题?告诉主智能体,由它判断怎么引导执行">✉ 继续对话</button>
|
package/package.json
CHANGED