codebee 0.1.101 → 0.1.102
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 +8 -7
- package/app/core/acp_client.py +34 -3
- package/app/core/board.py +21 -17
- package/app/core/builtin_agent.py +13 -4
- package/app/core/catalog.py +28 -6
- package/app/core/checkpoints.py +117 -31
- package/app/core/eval_matrix.py +10 -1
- package/app/core/mcp_client.py +7 -2
- package/app/core/openapi.py +8 -0
- package/app/core/pipeline.py +4 -1
- package/app/core/policy.py +9 -0
- package/app/core/publish/auto.py +106 -9
- package/app/core/publish/fanqie.py +16 -10
- package/app/core/publish/flow.py +29 -1
- package/app/core/publish/manager.py +8 -0
- package/app/core/sandbox_runtime.py +95 -0
- package/app/core/store.py +13 -3
- package/app/main.py +1 -0
- package/app/ui/app.js +163 -26
- package/app/ui/hive3d.js +491 -223
- package/app/ui/i18n.js +18 -0
- package/app/ui/index.html +24 -4
- package/app/ui/style.css +548 -18
- package/package.json +1 -1
package/app/ui/app.js
CHANGED
|
@@ -3123,7 +3123,20 @@ async function createTask() {
|
|
|
3123
3123
|
workdir: $("f-workdir").value.trim(),
|
|
3124
3124
|
thinking: $("f-thinking").value,
|
|
3125
3125
|
};
|
|
3126
|
-
|
|
3126
|
+
const sandboxBackend = $("f-sandbox-backend").value;
|
|
3127
|
+
if (sandboxBackend === "docker") {
|
|
3128
|
+
const dockerImage = $("f-sandbox-image").value.trim();
|
|
3129
|
+
if (!dockerImage) {
|
|
3130
|
+
msg.className = "msg err";
|
|
3131
|
+
msg.textContent = t("选择 Docker 后请填写镜像名");
|
|
3132
|
+
$("f-sandbox-image").focus();
|
|
3133
|
+
resetSubmit();
|
|
3134
|
+
return;
|
|
3135
|
+
}
|
|
3136
|
+
payload.sandbox = { backend: "docker", docker_image: dockerImage };
|
|
3137
|
+
}
|
|
3138
|
+
// 扫榜选材允许目标留空(菜单承诺:默认分析总榜热门题材),其余类型必填
|
|
3139
|
+
if (!payload.goal && payload.type !== "rank_scan") {
|
|
3127
3140
|
msg.className = "msg err";
|
|
3128
3141
|
msg.textContent = t("请先填写目标");
|
|
3129
3142
|
$("f-goal").focus();
|
|
@@ -3252,6 +3265,12 @@ async function createTask() {
|
|
|
3252
3265
|
}
|
|
3253
3266
|
}
|
|
3254
3267
|
|
|
3268
|
+
function syncSandboxComposer() {
|
|
3269
|
+
const docker = $("f-sandbox-backend") && $("f-sandbox-backend").value === "docker";
|
|
3270
|
+
const row = $("row-sandbox-image");
|
|
3271
|
+
if (row) row.classList.toggle("hidden", !docker);
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3255
3274
|
/* ---------------------------------------------------------- 附件(截图/文件) */
|
|
3256
3275
|
/* 待提交附件:选中/粘贴即上传到服务端 pending 区,创建任务时随 payload 落盘
|
|
3257
3276
|
* 到工作目录 _attachments/ 并注入上下文。图片另走 codex 原生 -i 直读;
|
|
@@ -3957,6 +3976,10 @@ async function newFromTaskAsync(id) {
|
|
|
3957
3976
|
// 不随预填带走:新任务要么重新上传,要么由 _attachments 路径引用
|
|
3958
3977
|
$("f-context").value = (tk.context || "").split("\n## 附件材料")[0].trimEnd();
|
|
3959
3978
|
$("f-workdir").value = tk.workdir || "";
|
|
3979
|
+
const taskSandbox = tk.sandbox || {};
|
|
3980
|
+
$("f-sandbox-backend").value = taskSandbox.backend === "docker" ? "docker" : "native";
|
|
3981
|
+
$("f-sandbox-image").value = taskSandbox.docker_image || "";
|
|
3982
|
+
syncSandboxComposer();
|
|
3960
3983
|
S.atts = []; renderAttachChips(); // 附件清单不继承:同目录引用已随 context 保留
|
|
3961
3984
|
queueGitProbe(); // 工作目录变了,重新探测代码版本
|
|
3962
3985
|
$("f-mode").value = ["fast", "expert", "manual"].includes(tk.mode) ? tk.mode : "auto";
|
|
@@ -4815,7 +4838,13 @@ window.loadRunCheckpoints = async function (requestedRunId) {
|
|
|
4815
4838
|
const run = (S.lastRun && S.lastRun.id === runId) ? S.lastRun : latest;
|
|
4816
4839
|
box.dataset.hasRestorable = files.some((file) => file.restorable) ? "true" : "false";
|
|
4817
4840
|
refreshCheckpointRestoreAvailability(run);
|
|
4818
|
-
|
|
4841
|
+
const checkpoint = data.checkpoint || {};
|
|
4842
|
+
const steps = Array.isArray(checkpoint.steps) ? checkpoint.steps : [];
|
|
4843
|
+
const stepSummary = steps.length ? '<div class="rd-checkpoint-steps"><strong>' + esc(t("步骤回放预览")) + '</strong>' +
|
|
4844
|
+
steps.map((step) => '<div class="rd-checkpoint-step"><span>#' + esc(String(step.step ?? "")) + ' · ' + esc(step.role || t("未命名步骤")) + '</span><span class="chip">' + esc(step.status || step.event || "unknown") + (step.attempt ? ' · ' + esc(t("第") + step.attempt + t("次")) : "") + '</span></div>').join("") +
|
|
4845
|
+
(checkpoint.truncated ? '<p class="hint">' + esc(t("仅显示最近 200 个步骤,共 ") + (checkpoint.total_steps || steps.length)) + '</p>' : '') +
|
|
4846
|
+
(checkpoint.replayable ? '<p class="hint">' + esc(t("所有步骤均已完成,可人工复核后继续")) + '</p>' : '<p class="hint">' + esc(t("无法安全自动回放:") + (checkpoint.blocked_reason || t("需要人工核对"))) + '</p>') + '</div>' : '';
|
|
4847
|
+
body.innerHTML = (data.files && data.files.warning ? '<p class="hint">' + esc(data.files.warning) + "</p>" : "") + stepSummary +
|
|
4819
4848
|
(files.length ? files.map((file) => '<article class="rd-checkpoint-row"><strong>' + esc(file.path) + '</strong><span class="chip">' + esc(file.status) + (file.restorable ? " · " + esc(t("可恢复")) : "") + '</span><pre>' + esc(file.diff || "") + "</pre></article>").join("") : '<span class="hint">' + esc(t("此运行没有文件快照")) + "</span>");
|
|
4820
4849
|
box.dataset.runId = runId;
|
|
4821
4850
|
box.classList.remove("needs-load");
|
|
@@ -6185,6 +6214,11 @@ function pbBlock(task, platform) {
|
|
|
6185
6214
|
S.pubAuto.running.platform === platform) ? S.pubAuto.running : null;
|
|
6186
6215
|
if (run && run.status === "running") {
|
|
6187
6216
|
btns += '<span class="pb-book">' + esc((run.as_draft ? t("存草稿中 ") : t("自动发布中 ")) + run.done + "/" + run.total) + "</span>";
|
|
6217
|
+
}
|
|
6218
|
+
if (run && Array.isArray(run.notes) && run.notes.length) {
|
|
6219
|
+
// 对账剔除/跳过/重试的过程记录(auto 层 notes),最近三条
|
|
6220
|
+
btns += '<div class="pb-hint">' +
|
|
6221
|
+
esc(run.notes.slice(-3).join(";")) + "</div>";
|
|
6188
6222
|
} else if (au.pending > 0) {
|
|
6189
6223
|
// 门禁不再禁用按钮:点了走 pbApiWithQualityOverride 的复审/强制对话,
|
|
6190
6224
|
// 死按钮只会让用户无路可走(2026-10-08 实案:guard false 全灰点不了)
|
|
@@ -6209,9 +6243,6 @@ function pbBlock(task, platform) {
|
|
|
6209
6243
|
const key = task.id + ":" + platform;
|
|
6210
6244
|
const sig = its.map((x) => x.n).join(",");
|
|
6211
6245
|
S.pbSel = S.pbSel || {};
|
|
6212
|
-
if (!S.pbSel[key] || S.pbSel[key].sig !== sig)
|
|
6213
|
-
S.pbSel[key] = { sig, sel: new Set(its.map((x) => x.n)) };
|
|
6214
|
-
const sel = S.pbSel[key].sel;
|
|
6215
6246
|
// 连续段按卷名分组;无卷计划的整块平铺不显示卷头
|
|
6216
6247
|
const groups = [];
|
|
6217
6248
|
for (const x of its) {
|
|
@@ -6219,10 +6250,22 @@ function pbBlock(task, platform) {
|
|
|
6219
6250
|
if (g && g.v === x.v) g.ns.push(x.n);
|
|
6220
6251
|
else groups.push({ v: x.v, ns: [x.n] });
|
|
6221
6252
|
}
|
|
6253
|
+
if (!S.pbSel[key] || S.pbSel[key].sig !== sig)
|
|
6254
|
+
S.pbSel[key] = { sig, sel: new Set(its.map((x) => x.n)), groups };
|
|
6255
|
+
const sel = S.pbSel[key].sel;
|
|
6222
6256
|
let chips = "";
|
|
6223
|
-
for (
|
|
6224
|
-
|
|
6225
|
-
|
|
6257
|
+
for (let gi = 0; gi < groups.length; gi++) {
|
|
6258
|
+
const g = groups[gi];
|
|
6259
|
+
if (groups.length > 1 || g.v) {
|
|
6260
|
+
// 卷头=整卷开关:全选打勾、部分选中显示 已选/总(2026-10-10 按卷选章)
|
|
6261
|
+
const cnt = g.ns.filter((n) => sel.has(n)).length;
|
|
6262
|
+
const allOn = cnt === g.ns.length;
|
|
6263
|
+
chips += '<div class="pb-vol"><label class="pb-vol-sel' + (allOn ? " on" : "") +
|
|
6264
|
+
'" title="' + esc(t("勾选卷头=整卷进所选,再点取消")) + '">' +
|
|
6265
|
+
'<input type="checkbox" ' + (allOn ? "checked" : "") +
|
|
6266
|
+
' onchange="pbSelVolume(\'' + esc(task.id) + "','" + platform + "'," + gi + ',this.checked)">' +
|
|
6267
|
+
esc(g.v || t("未分卷")) + t("(") + (allOn ? "" : cnt + "/") + g.ns.length + t(")") + "</label></div>";
|
|
6268
|
+
}
|
|
6226
6269
|
for (const n of g.ns)
|
|
6227
6270
|
chips += '<label class="pb-chip' + (sel.has(n) ? " on" : "") + '">' +
|
|
6228
6271
|
'<input type="checkbox" ' + (sel.has(n) ? "checked" : "") +
|
|
@@ -6580,6 +6623,17 @@ window.pbSelAll = function (taskId, platform, all) {
|
|
|
6580
6623
|
S._pbSig = ""; pbKick();
|
|
6581
6624
|
};
|
|
6582
6625
|
|
|
6626
|
+
window.pbSelVolume = function (taskId, platform, gi, on) {
|
|
6627
|
+
const key = taskId + ":" + platform;
|
|
6628
|
+
const ent = (S.pbSel || {})[key];
|
|
6629
|
+
const g = ent && ent.groups && ent.groups[gi];
|
|
6630
|
+
if (!g || !g.ns.length) return;
|
|
6631
|
+
if (on) for (const n of g.ns) ent.sel.add(n);
|
|
6632
|
+
else for (const n of g.ns) ent.sel.delete(n);
|
|
6633
|
+
pbSelCountSync(key);
|
|
6634
|
+
S._pbSig = ""; pbKick();
|
|
6635
|
+
};
|
|
6636
|
+
|
|
6583
6637
|
window.pbPublishSelected = async function (taskId, platform, autoSubmit) {
|
|
6584
6638
|
const key = taskId + ":" + platform;
|
|
6585
6639
|
const ent = (S.pbSel || {})[key];
|
|
@@ -8578,15 +8632,15 @@ function hiveThinkLine(lines) {
|
|
|
8578
8632
|
* localStorage 持久化/WebGL 不可用降级,以及把 renderHive 的泳道数据翻译给场景。 —— */
|
|
8579
8633
|
let hiveScene = null; // Hive3D 场景实例(懒创建)
|
|
8580
8634
|
let hiveSceneDead = false; // WebGL 不可用/上下文丢失——本次页面周期内不再尝试
|
|
8581
|
-
let hiveMode = "
|
|
8635
|
+
let hiveMode = "live3d"; // live3d is the real scene; reference and 2d remain opt-in views
|
|
8582
8636
|
let hiveRunId = ""; // 最近一次 renderHive 的 run.id(尾巴/思考缓存键前缀)
|
|
8583
8637
|
const hiveLiveMeta = {}; // rel -> { started_at }(3D 芯片秒表用)
|
|
8584
8638
|
let hiveDialogPoll = null;
|
|
8585
8639
|
let hiveDialogKey = "";
|
|
8586
8640
|
|
|
8587
|
-
function setHiveSceneButtons(
|
|
8641
|
+
function setHiveSceneButtons(mode) {
|
|
8588
8642
|
document.querySelectorAll("[data-hive-view]").forEach((button) => {
|
|
8589
|
-
const active = button.dataset.hiveView ===
|
|
8643
|
+
const active = button.dataset.hiveView === mode;
|
|
8590
8644
|
button.classList.toggle("active", active);
|
|
8591
8645
|
button.setAttribute("aria-pressed", active ? "true" : "false");
|
|
8592
8646
|
});
|
|
@@ -8657,28 +8711,80 @@ function closeHiveMonitorLog() {
|
|
|
8657
8711
|
function setHiveSceneMode(mode, opts) {
|
|
8658
8712
|
const viewport = $("rd-hive-viewport");
|
|
8659
8713
|
if (!viewport) return;
|
|
8660
|
-
let
|
|
8661
|
-
if (
|
|
8714
|
+
let selected = ["live3d", "2d"].includes(mode) ? mode : "reference";
|
|
8715
|
+
if (selected !== "2d") {
|
|
8662
8716
|
const sc = ensureHiveScene();
|
|
8663
8717
|
if (!sc) {
|
|
8664
|
-
|
|
8718
|
+
selected = "2d";
|
|
8665
8719
|
if (!(opts && opts.silent)) toast(t("当前环境不支持 WebGL,已切换 2D 列表"), true);
|
|
8666
8720
|
}
|
|
8667
8721
|
}
|
|
8668
|
-
hiveMode =
|
|
8669
|
-
if (hiveScene)
|
|
8670
|
-
|
|
8671
|
-
|
|
8722
|
+
hiveMode = selected;
|
|
8723
|
+
if (hiveScene) {
|
|
8724
|
+
hiveScene.setDisplayMode(selected);
|
|
8725
|
+
hiveScene.setActive(selected !== "2d");
|
|
8726
|
+
}
|
|
8727
|
+
viewport.classList.toggle("hive-mode-3d", selected === "reference");
|
|
8728
|
+
viewport.classList.toggle("hive-mode-live3d", selected === "live3d");
|
|
8729
|
+
viewport.classList.toggle("hive-mode-2d", selected === "2d");
|
|
8672
8730
|
const tools = document.querySelector(".hive-scene-tools");
|
|
8673
|
-
if (tools) tools.classList.toggle("hive-2d",
|
|
8674
|
-
setHiveSceneButtons(
|
|
8675
|
-
|
|
8731
|
+
if (tools) tools.classList.toggle("hive-2d", selected === "2d");
|
|
8732
|
+
setHiveSceneButtons(selected);
|
|
8733
|
+
const hint = document.querySelector(".hive-scene-hint");
|
|
8734
|
+
if (hint) {
|
|
8735
|
+
const hintKey = selected === "live3d"
|
|
8736
|
+
? "拖动旋转 · Shift+拖动平移 · 滚轮缩放 · 双击复位 · 点击屏幕看日志"
|
|
8737
|
+
: selected === "2d" ? "点击格子看日志"
|
|
8738
|
+
: "拖动平移 · 滚轮缩放 · 双击复位 · 点击屏幕看日志";
|
|
8739
|
+
hint.dataset.i18n = hintKey;
|
|
8740
|
+
hint.textContent = t(hintKey);
|
|
8741
|
+
}
|
|
8742
|
+
try { localStorage.setItem("orch.hiveView.v2", hiveMode); } catch (e) { /* 隐私模式等 */ }
|
|
8743
|
+
}
|
|
8744
|
+
|
|
8745
|
+
function syncHiveFullscreenButton() {
|
|
8746
|
+
const stage = $("hive-scene-stage");
|
|
8747
|
+
const button = $("hive-scene-fullscreen");
|
|
8748
|
+
const active = !!stage && document.fullscreenElement === stage;
|
|
8749
|
+
if (stage) stage.classList.toggle("is-fullscreen", active);
|
|
8750
|
+
if (!button) return;
|
|
8751
|
+
const textKey = active ? "退出全屏" : "全屏";
|
|
8752
|
+
const labelKey = active ? "退出全屏" : "进入全屏";
|
|
8753
|
+
button.dataset.i18n = textKey;
|
|
8754
|
+
button.dataset.i18nTitle = labelKey;
|
|
8755
|
+
button.dataset.i18nAria = labelKey;
|
|
8756
|
+
button.textContent = t(textKey);
|
|
8757
|
+
button.title = t(labelKey);
|
|
8758
|
+
button.setAttribute("aria-label", t(labelKey));
|
|
8759
|
+
button.setAttribute("aria-pressed", active ? "true" : "false");
|
|
8760
|
+
}
|
|
8761
|
+
|
|
8762
|
+
async function toggleHiveFullscreen() {
|
|
8763
|
+
const stage = $("hive-scene-stage");
|
|
8764
|
+
if (!stage) return;
|
|
8765
|
+
try {
|
|
8766
|
+
if (document.fullscreenElement === stage) {
|
|
8767
|
+
await document.exitFullscreen();
|
|
8768
|
+
return;
|
|
8769
|
+
}
|
|
8770
|
+
if (typeof stage.requestFullscreen !== "function" || document.fullscreenEnabled === false) {
|
|
8771
|
+
toast(t("当前浏览器不支持全屏"), true);
|
|
8772
|
+
return;
|
|
8773
|
+
}
|
|
8774
|
+
await stage.requestFullscreen();
|
|
8775
|
+
} catch (error) {
|
|
8776
|
+
toast(t("全屏失败:") + (error && error.message ? error.message : ""), true);
|
|
8777
|
+
}
|
|
8676
8778
|
}
|
|
8677
8779
|
|
|
8678
8780
|
function setupHiveSceneControls() {
|
|
8679
8781
|
const viewport = $("rd-hive-viewport");
|
|
8680
8782
|
if (!viewport || viewport.dataset.controlsReady) return;
|
|
8681
8783
|
viewport.dataset.controlsReady = "true";
|
|
8784
|
+
const fullscreenButton = $("hive-scene-fullscreen");
|
|
8785
|
+
if (fullscreenButton) fullscreenButton.addEventListener("click", toggleHiveFullscreen);
|
|
8786
|
+
document.addEventListener("fullscreenchange", syncHiveFullscreenButton);
|
|
8787
|
+
syncHiveFullscreenButton();
|
|
8682
8788
|
const hiveDialog = $("hive-log-dialog");
|
|
8683
8789
|
const hiveClose = $("hive-log-close");
|
|
8684
8790
|
if (hiveClose) hiveClose.addEventListener("click", closeHiveMonitorLog);
|
|
@@ -8691,14 +8797,23 @@ function setupHiveSceneControls() {
|
|
|
8691
8797
|
});
|
|
8692
8798
|
document.querySelectorAll("[data-hive-scene-action]").forEach((button) => {
|
|
8693
8799
|
button.addEventListener("click", () => {
|
|
8694
|
-
if (hiveMode
|
|
8800
|
+
if (hiveMode === "2d" || !hiveScene) return;
|
|
8695
8801
|
if (button.dataset.hiveSceneAction === "reset") hiveScene.resetView();
|
|
8696
8802
|
else hiveScene.zoomAt(button.dataset.hiveSceneAction === "zoom-in" ? 1 / 1.18 : 1.18);
|
|
8697
8803
|
});
|
|
8698
8804
|
});
|
|
8699
|
-
let saved = "
|
|
8700
|
-
try {
|
|
8701
|
-
|
|
8805
|
+
let saved = "live3d";
|
|
8806
|
+
try {
|
|
8807
|
+
saved = localStorage.getItem("orch.hiveView.v2") || "";
|
|
8808
|
+
if (!saved) {
|
|
8809
|
+
// Migrate an explicitly selected 2D/live3D preference; the old default "reference"
|
|
8810
|
+
// was auto-persisted for every new visitor, so it is not a reliable user preference.
|
|
8811
|
+
const legacy = localStorage.getItem("orch.hiveView");
|
|
8812
|
+
saved = legacy === "2d" || legacy === "live3d" ? legacy : "live3d";
|
|
8813
|
+
localStorage.setItem("orch.hiveView.v2", saved);
|
|
8814
|
+
}
|
|
8815
|
+
} catch (e) { /* ignore storage restrictions and keep the live 3D default */ }
|
|
8816
|
+
setHiveSceneMode(["reference", "live3d", "2d"].includes(saved) ? saved : "live3d", { silent: true });
|
|
8702
8817
|
}
|
|
8703
8818
|
|
|
8704
8819
|
/* renderHive → 场景数据翻译:泳道=蜂巢塔的一层,格子按状态映射高度/颜色。
|
|
@@ -8758,7 +8873,8 @@ function hiveSceneSync(run, lanes, byStage) {
|
|
|
8758
8873
|
const sc = ensureHiveScene();
|
|
8759
8874
|
if (!sc) return;
|
|
8760
8875
|
sc.sync(model); // 2D 模式也同步:切回 3D 时数据即 ready(画布未激活零 GPU 开销)
|
|
8761
|
-
sc.
|
|
8876
|
+
sc.setDisplayMode(hiveMode);
|
|
8877
|
+
sc.setActive(hiveMode !== "2d");
|
|
8762
8878
|
}
|
|
8763
8879
|
|
|
8764
8880
|
window.renderHive = function (run) {
|
|
@@ -9322,6 +9438,20 @@ function chatThinkHTML(it) {
|
|
|
9322
9438
|
'<div class="ct-body">' + esc(think) + "</div></details>";
|
|
9323
9439
|
}
|
|
9324
9440
|
|
|
9441
|
+
function chatAcpEventsHTML(it) {
|
|
9442
|
+
const events = Array.isArray(it.acp_events) ? it.acp_events.slice(-8) : [];
|
|
9443
|
+
if (!events.length) return "";
|
|
9444
|
+
return '<details class="chat-think chat-acp-events"><summary>' + esc(t("ACP 活动")) +
|
|
9445
|
+
'<span class="ct-len">' + events.length + ' ' + esc(t("条")) + '</span></summary>' +
|
|
9446
|
+
'<div class="ct-acts">' + events.map((event) => {
|
|
9447
|
+
const type = String(event.sessionUpdate || "event");
|
|
9448
|
+
const label = event.title || event.status || event.modeId || "";
|
|
9449
|
+
const entries = Array.isArray(event.entries) ? event.entries.map((entry) =>
|
|
9450
|
+
'<div class="rd-acp-plan-entry">' + esc(entry.status || "") + ' · ' + esc(entry.content || "") + '</div>').join("") : "";
|
|
9451
|
+
return '<div><code>' + esc(type) + '</code>' + (label ? ' · ' + esc(label) : "") + entries + '</div>';
|
|
9452
|
+
}).join("") + '</div></details>';
|
|
9453
|
+
}
|
|
9454
|
+
|
|
9325
9455
|
/* 运行中直连对话的快轮询:SSE/轮询最密 2s、闲时 8s,思考是逐句吐的——
|
|
9326
9456
|
* 1.2s 直拉时间线把增量打印出来。run 终态、切详情、分区隐藏即停。 */
|
|
9327
9457
|
function stopChatLive() {
|
|
@@ -9424,6 +9554,7 @@ function drawChatFlow(run, data, active) {
|
|
|
9424
9554
|
(it.status || "") + ":" + String(it.text || "").length + ":" +
|
|
9425
9555
|
String(it.thinking || "").length + ":" + String(it.stream || "").length + ":" +
|
|
9426
9556
|
(it.activity || []).length + ":" + (it.followups || []).length +
|
|
9557
|
+
":" + (it.acp_events || []).length +
|
|
9427
9558
|
":" + (it.consumed ? 1 : 0), "") + "|" + ((data && data.result) ? "r" : "");
|
|
9428
9559
|
if (liveSig === chatLiveSig && flow.childElementCount) return;
|
|
9429
9560
|
chatLiveSig = liveSig;
|
|
@@ -9497,6 +9628,7 @@ function drawChatFlow(run, data, active) {
|
|
|
9497
9628
|
'<span class="chat-avatar" aria-hidden="true"><svg class="ico"><use href="#i-bee"></use></svg></span>' +
|
|
9498
9629
|
'<div class="chat-bubble agent">' +
|
|
9499
9630
|
chatThinkHTML(it) +
|
|
9631
|
+
chatAcpEventsHTML(it) +
|
|
9500
9632
|
'<div class="chat-body">' + bodyHtml + "</div>" +
|
|
9501
9633
|
'<div class="chat-meta">' + esc(it.who || "") + " " + esc(chatTime(it.at)) +
|
|
9502
9634
|
(metaBad ? " · " + t(it.status === "failed" ? "失败" : "已取消") : "") + actsA + "</div>" +
|
|
@@ -16070,6 +16202,9 @@ window.suRestart = suRestart;
|
|
|
16070
16202
|
window.updDismiss = updDismiss;
|
|
16071
16203
|
|
|
16072
16204
|
document.addEventListener("DOMContentLoaded", () => {
|
|
16205
|
+
// Initialize Hive3D controls independently of run data. A fresh workspace may have no
|
|
16206
|
+
// active run yet, but fullscreen/view controls must still be wired and usable.
|
|
16207
|
+
setupHiveSceneControls();
|
|
16073
16208
|
// 远程地址里带的 ?token= 存起来并从地址栏抹掉,之后所有请求走请求头
|
|
16074
16209
|
const urlTok = new URLSearchParams(location.search).get("token");
|
|
16075
16210
|
if (urlTok) {
|
|
@@ -16411,6 +16546,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
16411
16546
|
localStorage.removeItem("orch.showArchived"); // 清掉旧版持久化残留,避免误解为默认选中
|
|
16412
16547
|
$("f-resume-agent").addEventListener("change", loadSessions);
|
|
16413
16548
|
$("f-resume-session").addEventListener("change", showResumeHint);
|
|
16549
|
+
$("f-sandbox-backend").addEventListener("change", syncSandboxComposer);
|
|
16550
|
+
syncSandboxComposer();
|
|
16414
16551
|
/* 工作目录不再用「上次用过」的旧记忆预填:那样改默认保存路径后,新建任务仍会被
|
|
16415
16552
|
* 旧目录盖过。首屏默认选中设置里的默认路径(loadSettings 落值),克隆/右键新建
|
|
16416
16553
|
* 等显式入口各自直接写字段值,不跨刷新持久化。清掉旧版残留键,避免误解为默认选中。 */
|