codebee 0.1.29 → 0.1.30

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/app/ui/app.js CHANGED
@@ -1,6 +1,9 @@
1
1
  /* CodeBee 前端(无依赖;状态走 SSE 实时推送,断线自动降级轮询) */
2
2
  "use strict";
3
3
 
4
+ // 桌宠通过窗口标题里的端口识别并复用当前 CodeBee 实例。
5
+ document.title = "CodeBee [" + (location.port || (location.protocol === "https:" ? "443" : "80")) + "]";
6
+
4
7
  const $ = (id) => document.getElementById(id);
5
8
  const S = { state: null, catalog: null, catSig: "", providers: null, bindings: null, modelsSig: "", bindSig: "", tab: "tasks", detailRunId: null, pollTimer: null, showArchived: false, /* 会话内开关:每次加载默认隐藏已归档、图标不选中(不持久化,见 btn-side-arch) */ selProvs: {}, selModels: {}, selRuns: {}, bindSel: {}, catalogChecking: false, updateCheckAt: 0, control: null, sseLive: false, es: null, flows: null, orch: null, skills: null, orchSig: "", settings: null, sessionAgents: new Set(), atts: [], gitInfo: null, gitWb: null, gitWbKey: "", gitWbAt: 0, gitWbBusy: false, creatingTask: false, inspKey: null, inspData: null, inspSig: "", inspAt: 0, inspTab: "git", inspAutoSig: "", rdTab: null, rdTabSig: "", rdTabPin: false, _rdCtx: {}, lastPrefs: null };
6
9
 
@@ -155,6 +158,8 @@ function onTypeChange() {
155
158
  // 直连:验证命令与评审参数都不适用,两块一起收起(目标+附件即全部输入)
156
159
  if (codeOnly) codeOnly.classList.toggle("hidden", isReview || isDirect);
157
160
  if (reviewOnly) reviewOnly.classList.toggle("hidden", !isReview);
161
+ if ($("f-direct-model")) $("f-direct-model").classList.toggle("hidden", !isDirect);
162
+ if (isDirect) renderDirectModelPicker();
158
163
  const bibleCreate = $("bible-create-field");
159
164
  const isSerialReview = isReview && !!(flow && flow.serial);
160
165
  if (bibleCreate) bibleCreate.classList.toggle("hidden", !isSerialReview);
@@ -196,6 +201,46 @@ function onTypeChange() {
196
201
  refreshEstimate();
197
202
  }
198
203
 
204
+ function directProviders() {
205
+ return (S.providers || []).filter((p) => p.enabled !== false && p.api_key);
206
+ }
207
+
208
+ function renderDirectModelPicker() {
209
+ const ps = $("f-direct-provider"), ms = $("f-direct-model-name");
210
+ if (!ps || !ms) return;
211
+ const prev = ps.value;
212
+ const provs = directProviders();
213
+ ps.innerHTML = '<option value="">' + t("自动推荐") + '</option>' + provs.map((p) =>
214
+ '<option value="' + esc(p.id) + '">' + esc(p.name || p.id) + "</option>").join("");
215
+ if (prev && provs.some((p) => p.id === prev)) ps.value = prev;
216
+ const p = provs.find((x) => x.id === ps.value);
217
+ const oldModel = ms.value;
218
+ const names = p ? (p.models || []).filter((m) => m.enabled !== false && !m.hidden)
219
+ .map((m) => m.name).filter(Boolean) : [];
220
+ ms.innerHTML = '<option value="">' + t("随厂商推荐") + '</option>' + names.map((name) =>
221
+ '<option value="' + esc(name) + '">' + esc(name) + "</option>").join("");
222
+ if (oldModel && names.includes(oldModel)) ms.value = oldModel;
223
+ }
224
+
225
+ function recommendTaskType(goal) {
226
+ const s = String(goal || "").toLowerCase();
227
+ const rules = [
228
+ ["code", /(代码|bug|报错|修复|重构|接口|数据库|前端|后端|python|javascript|typescript|java|go\b|git)/i],
229
+ ["translation", /(翻译|译成|translate|translation|中译英|英译中)/i],
230
+ ["email", /(邮件|email|e-mail|回信|邀约信|商务函)/i],
231
+ ["weekly_report", /(周报|月报|述职|工作汇报|工作总结)/i],
232
+ ["video_script", /(短视频|口播|分镜|抖音|视频脚本)/i],
233
+ ["speech", /(演讲稿|发言稿|致辞|演讲)/i],
234
+ ["tech_proposal", /(技术方案|架构方案|选型方案|实施方案)/i],
235
+ ["research", /(调研报告|竞品调研|市场调研|深度研究)/i],
236
+ ["serial_novel", /(连载|续写.*章|网文|长篇小说)/i],
237
+ ["novel", /(小说|故事|短篇|章节)/i],
238
+ ["article", /(公众号|自媒体|文章|博客|小红书)/i],
239
+ ];
240
+ const hit = rules.find((x) => x[1].test(s));
241
+ return hit && flowById(hit[0]) ? hit[0] : "";
242
+ }
243
+
199
244
  /* 快捷类型 chips(Composer 框下方):内置流程一键选定,选中态跟 #f-type 走 */
200
245
  function renderQuickChips() {
201
246
  const box = $("cmp-quick");
@@ -919,6 +964,9 @@ async function poll() {
919
964
  S.providers = models.providers; S.bindings = models.bindings;
920
965
  S.modelCatalog = models.catalog || [];
921
966
  S.sourceNames = models.source_names || S.sourceNames || {};
967
+ if ($("f-direct-model") && !$('f-direct-model').classList.contains("hidden")) {
968
+ renderDirectModelPicker();
969
+ }
922
970
  // 供应商集合/启停/密钥变了才重拉编排者:否则「生效中」状态点会在停用厂商后失真
923
971
  const provSig = JSON.stringify((S.providers || []).map((p) => [p.id, p.enabled, !!p.api_key]));
924
972
  if (provSig !== S.provSig) { S.provSig = provSig; loadOrchestrator(); }
@@ -2145,6 +2193,7 @@ async function createTask() {
2145
2193
  goal: $("f-goal").value.trim(),
2146
2194
  context: $("f-context").value.trim(),
2147
2195
  workdir: $("f-workdir").value.trim(),
2196
+ thinking: $("f-thinking").value,
2148
2197
  };
2149
2198
  if (!payload.goal) {
2150
2199
  msg.className = "msg err";
@@ -2153,6 +2202,22 @@ async function createTask() {
2153
2202
  resetSubmit();
2154
2203
  return;
2155
2204
  }
2205
+ if (payload.type === "direct" && !S.typeSuggestionDone) {
2206
+ const suggested = recommendTaskType(payload.goal);
2207
+ if (suggested) {
2208
+ const flow = flowById(suggested) || {};
2209
+ resetSubmit();
2210
+ const yes = await uiConfirm(
2211
+ t("这个需求更适合「{0}」流程,能使用对应的规划与质量门禁。是否切换后执行?")
2212
+ .replace("{0}", t(flow.name || suggested)),
2213
+ { title: t("推荐任务类型"), ok: t("切换类型") });
2214
+ S.typeSuggestionDone = true;
2215
+ if (yes) pickType(suggested);
2216
+ $("btn-create").click();
2217
+ return;
2218
+ }
2219
+ }
2220
+ S.typeSuggestionDone = false;
2156
2221
  // 需求拷问闸(借鉴 grill-me):goal 很短且没写背景时先问 1-3 个澄清问题;
2157
2222
  // 采访失败/无问题照常创建——是增强不是闸门
2158
2223
  if (payload.goal.length < 12 && !payload.context && !S.clarifyDone) {
@@ -2198,6 +2263,8 @@ async function createTask() {
2198
2263
  payload.verify_command = $("f-verify").value.trim();
2199
2264
  } else if (_eng === "direct") {
2200
2265
  // 直连:目标+附件即全部输入,不带验证/评审参数
2266
+ payload.direct_provider_id = $("f-direct-provider").value;
2267
+ payload.direct_model = $("f-direct-model-name").value;
2201
2268
  } else {
2202
2269
  payload.manuscript = $("f-manuscript").value.trim() || "manuscript.md";
2203
2270
  payload.rounds = parseInt($("f-rounds").value, 10) || 2;
@@ -2863,11 +2930,19 @@ function newFromTask(id) {
2863
2930
  $("f-workdir").value = tk.workdir || "";
2864
2931
  S.atts = []; renderAttachChips(); // 附件清单不继承:同目录引用已随 context 保留
2865
2932
  queueGitProbe(); // 工作目录变了,重新探测代码版本
2866
- $("f-mode").value = tk.mode === "manual" ? "manual" : "auto";
2933
+ $("f-mode").value = ["fast", "expert", "manual"].includes(tk.mode) ? tk.mode : "auto";
2934
+ $("f-thinking").value = ["low", "standard", "high"].includes(tk.thinking)
2935
+ ? tk.thinking : "auto";
2936
+ $("f-manual-only").classList.toggle("hidden", $("f-mode").value !== "manual");
2867
2937
  renderImplSelects();
2868
2938
  if (tk.implementer) $("f-impl").value = tk.implementer;
2869
2939
  if (flow && flow.engine === "code") {
2870
2940
  $("f-verify").value = tk.verify_command || "";
2941
+ } else if (flow && flow.engine === "direct") {
2942
+ renderDirectModelPicker();
2943
+ $("f-direct-provider").value = tk.direct_provider_id || "";
2944
+ renderDirectModelPicker();
2945
+ $("f-direct-model-name").value = tk.direct_model || "";
2871
2946
  } else {
2872
2947
  $("f-manuscript").value = tk.manuscript || "manuscript.md";
2873
2948
  $("f-rounds").value = tk.rounds || 2;
@@ -11112,6 +11187,7 @@ document.addEventListener("DOMContentLoaded", () => {
11112
11187
  $("f-mode").addEventListener("change", () => {
11113
11188
  $("f-manual-only").classList.toggle("hidden", $("f-mode").value !== "manual");
11114
11189
  });
11190
+ $("f-direct-provider").addEventListener("change", renderDirectModelPicker);
11115
11191
  $("f-type").dispatchEvent(new Event("change"));
11116
11192
  cmpGreeting(); // 问候语按时段刷新(切语言/回任务页也会重算)
11117
11193
  $("btn-reload-catalog").addEventListener("click", async () => {
@@ -11552,8 +11628,17 @@ async function beeScan() {
11552
11628
  });
11553
11629
  $("bee-groups-search").addEventListener("input", beeRenderGroups);
11554
11630
  $("bee-groups-refresh").addEventListener("click", beeRefreshGroups);
11631
+ // 64 位 Python 自动扫描 + 一键安装 wechatauto-replica(借鉴用户诉求:
11632
+ // 别手填解释器路径、别自己开 conda 装依赖)
11633
+ $("bee-py-scan").addEventListener("click", beePyScan);
11634
+ $("bee-py-install").addEventListener("click", beePyInstall);
11555
11635
  beeRefresh();
11556
11636
  setInterval(beeRefresh, 60000);
11637
+ // 桌宠右键「群摘要」直达:URL 带 #bee=1 时自动展开蜜蜂坞面板
11638
+ if (/bee=1/.test(location.hash)) {
11639
+ setTimeout(() => beeToggle(true), 800);
11640
+ history.replaceState(null, "", location.pathname + location.search);
11641
+ }
11557
11642
  };
11558
11643
  // 错开首屏:令牌门/状态首帧先走,群摘要轮询晚 2s 再起
11559
11644
  if (document.readyState === "loading") {
@@ -11562,3 +11647,93 @@ async function beeScan() {
11562
11647
  setTimeout(boot, 2000);
11563
11648
  }
11564
11649
  })();
11650
+
11651
+ /* ---- 64 位 Python 扫描/一键安装(蜜蜂坞微信直连配置)---- */
11652
+ let beePyTimer = null;
11653
+ async function beePyScan() {
11654
+ const btn = $("bee-py-scan"), box = $("bee-py-cands");
11655
+ if (!btn) return;
11656
+ btn.disabled = true;
11657
+ try { await api("/api/wxdigest/pythons/scan", { method: "POST", body: "{}" }); }
11658
+ catch (e) { toast(t("扫描失败:") + (e.message || e), true); btn.disabled = false; return; }
11659
+ box.classList.remove("hidden");
11660
+ box.innerHTML = '<span class="hint">' + esc(t("正在扫描本机 Python…")) + "</span>";
11661
+ beePyTimer = setInterval(async () => {
11662
+ try {
11663
+ const st = await api("/api/wxdigest/pythons");
11664
+ if (st.scanning) return;
11665
+ clearInterval(beePyTimer); beePyTimer = null;
11666
+ btn.disabled = false;
11667
+ beePyRender(st.results || []);
11668
+ } catch (e) { /* 轮询失败下一拍再试 */ }
11669
+ }, 1500);
11670
+ }
11671
+ function beePyRender(list) {
11672
+ const box = $("bee-py-cands"), st = $("bee-py-status"), ib = $("bee-py-install");
11673
+ if (!box) return;
11674
+ if (!list.length) { box.innerHTML = '<span class="hint">' + esc(t("没有找到可用的 Python,请手动填写路径")) + "</span>"; return; }
11675
+ const cur = ($("bee-reader-py").value || "").trim();
11676
+ box.innerHTML = list.map((p, idx) => {
11677
+ const tag = p.has_replica ? t("已装 wechatauto-replica") : t("未装依赖");
11678
+ const cls = "bee-py-item" + (p.path === cur ? " on" : "");
11679
+ return '<button type="button" class="' + cls + '" data-i="' + idx + '">' +
11680
+ '<span class="bee-py-path">' + esc(p.path) + "</span>" +
11681
+ '<span class="bee-py-meta">' + esc("Py" + p.version + " · " + p.bits + "bit · " + tag) + "</span></button>";
11682
+ }).join("");
11683
+ box.querySelectorAll(".bee-py-item").forEach((b) => {
11684
+ b.addEventListener("click", () => {
11685
+ const p = list[Number(b.dataset.i)];
11686
+ $("bee-reader-py").value = p.path;
11687
+ box.querySelectorAll(".bee-py-item").forEach((x) => x.classList.remove("on"));
11688
+ b.classList.add("on");
11689
+ beePyInstallVisibility(p);
11690
+ });
11691
+ });
11692
+ // 默认选中:当前输入框命中的;否则第一个已装依赖的 64 位
11693
+ const hit = list.find((p) => p.path === cur) ||
11694
+ list.find((p) => p.bits >= 64 && p.has_replica) ||
11695
+ list.find((p) => p.bits >= 64);
11696
+ if (hit) {
11697
+ $("bee-reader-py").value = hit.path;
11698
+ beePyInstallVisibility(hit);
11699
+ const btn = box.querySelector('.bee-py-item[data-i="' + list.indexOf(hit) + '"]');
11700
+ if (btn) btn.classList.add("on");
11701
+ }
11702
+ }
11703
+ function beePyInstallVisibility(p) {
11704
+ const ib = $("bee-py-install"), st = $("bee-py-status");
11705
+ if (!ib) return;
11706
+ const need = p && p.bits >= 64 && !p.has_replica;
11707
+ ib.classList.toggle("hidden", !need);
11708
+ if (st && !need) st.textContent = "";
11709
+ }
11710
+ async function beePyInstall() {
11711
+ const py = ($("bee-reader-py").value || "").trim();
11712
+ if (!py) { toast(t("请先选择或填写 Python 路径"), true); return; }
11713
+ const ib = $("bee-py-install"), st = $("bee-py-status");
11714
+ ib.disabled = true;
11715
+ if (st) st.textContent = t("正在安装 wechatauto-replica…(约 1-3 分钟)");
11716
+ try { await api("/api/wxdigest/replica/install", { method: "POST", body: JSON.stringify({ python: py }) }); }
11717
+ catch (e) {
11718
+ toast(t("安装失败:") + (e.message || e), true);
11719
+ ib.disabled = false;
11720
+ return;
11721
+ }
11722
+ const timer = setInterval(async () => {
11723
+ try {
11724
+ const s = await api("/api/wxdigest/replica/status");
11725
+ if (!s.running) {
11726
+ clearInterval(timer); timer = null;
11727
+ ib.disabled = false;
11728
+ if (s.ok) {
11729
+ if (st) st.textContent = t("安装完成,依赖已就绪");
11730
+ toast(t("wechatauto-replica 安装完成"));
11731
+ } else {
11732
+ if (st) st.textContent = (s.log || []).slice(-3).join(" ").slice(0, 200);
11733
+ toast(t("安装失败,详见状态行"), true);
11734
+ }
11735
+ beePyScan(); // 重扫刷新 has_replica 标记
11736
+ }
11737
+ } catch (e) { /* 轮询失败下一拍再试 */ }
11738
+ }, 3000);
11739
+ }
package/app/ui/i18n.js CHANGED
@@ -28,6 +28,24 @@
28
28
  // —— 表单字段/标签 ——
29
29
 
30
30
  // —— 智能/手动 模式 ——
31
+ "编排模式": "Orchestration mode",
32
+ "自动(推荐):按任务类型与风险动态决定步骤": "Auto (recommended): adapt steps to task type and risk",
33
+ "快速:少步骤优先,先做确定性验收": "Fast: fewer steps with deterministic checks first",
34
+ "专家:完整规划、多评审、失败修复与换将": "Expert: full planning, reviews, repairs, and fallback agents",
35
+ "手动:自行指定实现者与评审组": "Manual: choose implementer and reviewers",
36
+ "思考程度": "Reasoning effort",
37
+ "自动:随任务难度调整": "Auto: adapt to task difficulty",
38
+ "快速:少推理、优先响应": "Fast: less reasoning, faster response",
39
+ "标准:平衡质量与速度": "Standard: balance quality and speed",
40
+ "深度:更多推理与检查": "Deep: more reasoning and checks",
41
+ "对话模型(可选)": "Chat model (optional)",
42
+ "对话厂商": "Chat provider",
43
+ "对话模型": "Chat model",
44
+ "随厂商推荐": "Provider default",
45
+ "只对本次对话生效,不会修改全局绑定;指定渠道不可用时会明确报错。": "Applies only to this chat and does not change global bindings. An unavailable selected route returns an explicit error.",
46
+ "推荐任务类型": "Recommended task type",
47
+ "切换类型": "Switch type",
48
+ "这个需求更适合「{0}」流程,能使用对应的规划与质量门禁。是否切换后执行?": "This request fits the {0} workflow, which provides matching planning and quality gates. Switch before running?",
31
49
 
32
50
  // —— 引擎/角色 ——
33
51
 
@@ -1894,6 +1912,18 @@
1894
1912
  "反馈摘要生成失败:": "Failed to build issue summary: ",
1895
1913
  "端口占用": "Port Usage",
1896
1914
  "扫描本机端口": "Scan local ports",
1915
+ "扫描": "Scan",
1916
+ "一键安装 wechatauto-replica": "Install wechatauto-replica",
1917
+ "已装 wechatauto-replica": "replica installed",
1918
+ "未装依赖": "dependency missing",
1919
+ "正在扫描本机 Python…": "Scanning local Pythons…",
1920
+ "没有找到可用的 Python,请手动填写路径": "No usable Python found — please fill in the path manually",
1921
+ "请先选择或填写 Python 路径": "Pick or type a Python path first",
1922
+ "正在安装 wechatauto-replica…(约 1-3 分钟)": "Installing wechatauto-replica… (1-3 minutes)",
1923
+ "安装完成,依赖已就绪": "Installed — dependency ready",
1924
+ "安装失败,详见状态行": "Install failed — see status line",
1925
+ "扫描失败:": "Scan failed: ",
1926
+ "安装失败:": "Install failed: ",
1897
1927
  "谁占着端口、属于哪个项目一目了然;「仅本机」的端口外网不可达。关闭只发温和信号,系统进程与本服务自身拒绝关闭。": "See at a glance which process holds each port and which project it belongs to; \"local only\" ports are unreachable from outside. Close sends a gentle termination signal only — system processes and this service itself are refused.",
1898
1928
  "端口": "Port",
1899
1929
  "进程": "Process",
package/app/ui/index.html CHANGED
@@ -329,10 +329,24 @@
329
329
  <div class="field">
330
330
  <label data-i18n="编排模式">编排模式</label>
331
331
  <select id="f-mode">
332
- <option data-i18n="智能(推荐):自动拆解 + 智能路由 + 失败自动修复/换将" value="auto">智能(推荐):自动拆解 + 智能路由 + 失败自动修复/换将</option>
332
+ <option data-i18n="自动(推荐):按任务类型与风险动态决定步骤" value="auto">自动(推荐):按任务类型与风险动态决定步骤</option>
333
+ <option data-i18n="快速:少步骤优先,先做确定性验收" value="fast">快速:少步骤优先,先做确定性验收</option>
334
+ <option data-i18n="专家:完整规划、多评审、失败修复与换将" value="expert">专家:完整规划、多评审、失败修复与换将</option>
333
335
  <option data-i18n="手动:自行指定实现者与评审组" value="manual">手动:自行指定实现者与评审组</option>
334
336
  </select>
335
337
  </div>
338
+ <div class="grid-2">
339
+ <div class="field"><label data-i18n="思考程度">思考程度</label><select id="f-thinking">
340
+ <option data-i18n="标准:平衡质量与速度" value="standard" selected>标准:平衡质量与速度</option>
341
+ <option data-i18n="自动:随任务难度调整" value="auto">自动:随任务难度调整</option>
342
+ <option data-i18n="快速:少推理、优先响应" value="low">快速:少推理、优先响应</option>
343
+ <option data-i18n="深度:更多推理与检查" value="high">深度:更多推理与检查</option>
344
+ </select></div>
345
+ <div id="f-direct-model" class="field hidden"><label data-i18n="对话模型(可选)">对话模型(可选)</label><div class="grid-2">
346
+ <select id="f-direct-provider" aria-label="对话厂商" data-i18n-aria="对话厂商"><option data-i18n="自动推荐">自动推荐</option></select>
347
+ <select id="f-direct-model-name" aria-label="对话模型" data-i18n-aria="对话模型"><option data-i18n="随厂商推荐">随厂商推荐</option></select>
348
+ </div><p class="hint" data-i18n="只对本次对话生效,不会修改全局绑定;指定渠道不可用时会明确报错。">只对本次对话生效,不会修改全局绑定;指定渠道不可用时会明确报错。</p></div>
349
+ </div>
336
350
 
337
351
  <div id="f-code-only">
338
352
  <div class="field"><label data-i18n="验证命令">验证命令</label><input id="f-verify" placeholder="例:python -m pytest -q(可空=只评审)" data-i18n-ph="例:python -m pytest -q(可空=只评审)"></div>
@@ -1131,7 +1145,13 @@
1131
1145
  <label class="toggle"><input id="bee-reader" type="checkbox"> <span data-i18n="从本机微信自动拉取(微信直连)">从本机微信自动拉取(微信直连)</span></label>
1132
1146
  <div id="bee-reader-box" class="hidden">
1133
1147
  <span class="bee-lab" data-i18n="64 位 Python 路径(需装 wechatauto-replica)">64 位 Python 路径(需装 wechatauto-replica)</span>
1134
- <input id="bee-reader-py" type="text" spellcheck="false" data-i18n-ph="例如 C:\Users\HP\anaconda3\envs\wxprobe\python.exe" placeholder="例如 C:\Users\HP\anaconda3\envs\wxprobe\python.exe">
1148
+ <div class="bee-dir-row">
1149
+ <input id="bee-reader-py" type="text" spellcheck="false" style="flex:1" data-i18n-ph="例如 C:\Users\HP\anaconda3\envs\wxprobe\python.exe" placeholder="例如 C:\Users\HP\anaconda3\envs\wxprobe\python.exe">
1150
+ <button id="bee-py-scan" class="ghost small" data-i18n="扫描">扫描</button>
1151
+ </div>
1152
+ <div id="bee-py-cands" class="bee-py-cands hidden"></div>
1153
+ <button id="bee-py-install" class="ghost small hidden" data-i18n="一键安装 wechatauto-replica">一键安装 wechatauto-replica</button>
1154
+ <span id="bee-py-status" class="hint"></span>
1135
1155
  <div class="bee-dir-row">
1136
1156
  <button id="bee-groups-btn" class="ghost small" data-i18n="选择要监听的群(0)">选择要监听的群(0)</button>
1137
1157
  </div>
package/app/ui/style.css CHANGED
@@ -5552,3 +5552,34 @@ button.request-busy > * { opacity: .18; }
5552
5552
  .zt-auto-options .zt-interval-field { grid-column: 1 / -1; }
5553
5553
  .zt-prof .head .zt-p-product { min-width: 0; }
5554
5554
  }
5555
+
5556
+ /* 禅道自动化开关行:紧凑排成一行(四开关 + 扫描间隔同行,窄屏自动换行;
5557
+ 间隔输入改行内「标签+输入」,不再独占一格上下分层——用户反馈排成一行) */
5558
+ .zt-auto-options {
5559
+ display: flex; flex-wrap: wrap; align-items: center;
5560
+ gap: 8px 22px; grid-template-columns: none;
5561
+ }
5562
+ .zt-auto-options > .toggle { min-height: 0; margin: 0; align-self: auto; }
5563
+ .zt-auto-options .zt-interval-field {
5564
+ display: inline-flex; align-items: center; gap: 8px;
5565
+ grid-template-columns: none; min-width: 0;
5566
+ margin-left: auto; color: var(--muted); font-size: 12.5px;
5567
+ }
5568
+ .zt-auto-options .zt-interval-field input { width: 72px; }
5569
+ @media (max-width: 900px) {
5570
+ .zt-auto-options .zt-interval-field { margin-left: 0; }
5571
+ }
5572
+
5573
+ /* 蜜蜂坞微信直连:Python 扫描候选列表(样式对齐 bee-cfg 卡片内风格) */
5574
+ .bee-py-cands {
5575
+ display: flex; flex-direction: column; gap: 4px;
5576
+ max-height: 168px; overflow: auto; margin: 6px 0;
5577
+ }
5578
+ .bee-py-item {
5579
+ display: flex; flex-direction: column; gap: 2px; text-align: left;
5580
+ padding: 6px 8px; border: 1px solid var(--border, rgba(128,128,128,.25));
5581
+ border-radius: 6px; background: transparent; cursor: pointer; color: inherit;
5582
+ }
5583
+ .bee-py-item.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
5584
+ .bee-py-path { font-size: 12px; word-break: break-all; }
5585
+ .bee-py-meta { font-size: 11px; opacity: .65; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebee",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "description": "CodeBee · 多智能体编排台 — 统一编排本机 AI 编码 CLI(Codex / Claude Code / QwenCode / OpenCode / Aider…):目标→拆解→路由→执行→验证→跨厂商评审→修复→报告。纯 Python 标准库实现,本地 Web UI。",
5
5
  "license": "MIT",
6
6
  "bin": {