codebee 0.1.71 → 0.1.73
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 +601 -589
- package/LICENSE +21 -21
- package/README.md +508 -509
- package/app/core/acceptance.py +100 -100
- package/app/core/aiflavor.py +197 -197
- package/app/core/artifacts.py +148 -148
- package/app/core/assets.py +110 -110
- package/app/core/attachments.py +623 -623
- package/app/core/audit.py +30 -30
- package/app/core/backup.py +470 -470
- package/app/core/beekeeper.py +183 -183
- package/app/core/benchstore.py +95 -95
- package/app/core/board.py +209 -209
- package/app/core/bookmeta.py +935 -935
- package/app/core/bookmeta_catalog.py +180 -180
- package/app/core/branching.py +137 -137
- package/app/core/builtin_agent.py +1680 -1673
- package/app/core/capability.py +144 -144
- package/app/core/chaptersafe.py +32 -32
- package/app/core/cleanup.py +303 -303
- package/app/core/compaction.py +201 -201
- package/app/core/covergen.py +356 -356
- package/app/core/defectretro.py +43 -43
- package/app/core/diagnostics.py +114 -114
- package/app/core/dispatch.py +190 -190
- package/app/core/dispatch_log.py +128 -128
- package/app/core/env_scrub.py +85 -85
- package/app/core/errorlog.py +137 -137
- package/app/core/evalbench.py +836 -720
- package/app/core/evaluation.py +174 -174
- package/app/core/failure_notify.py +290 -290
- package/app/core/flows.py +8 -8
- package/app/core/goal_service.py +167 -167
- package/app/core/health.py +374 -374
- package/app/core/history.py +38 -38
- package/app/core/hooks.py +162 -162
- package/app/core/jobs.py +25 -1
- package/app/core/manager.py +2208 -2143
- package/app/core/market.py +90 -4
- package/app/core/market_remote.py +16 -0
- package/app/core/mocks.py +64 -64
- package/app/core/modelhub.py +3 -2
- package/app/core/notify.py +201 -201
- package/app/core/novel_quality.py +189 -189
- package/app/core/operations.py +228 -228
- package/app/core/paihang.py +145 -138
- package/app/core/pipeline.py +102 -30
- package/app/core/planner.py +2 -0
- package/app/core/plugins.py +34 -0
- package/app/core/portguard.py +111 -111
- package/app/core/preview.py +293 -293
- package/app/core/prompt_guard.py +78 -0
- package/app/core/publish/__init__.py +7 -7
- package/app/core/publish/auto.py +396 -367
- package/app/core/publish/browser.py +655 -655
- package/app/core/publish/fanqie.py +165 -165
- package/app/core/publish/flow.py +640 -589
- package/app/core/publish/flows-fanqie-calibrated.json +336 -336
- package/app/core/publish/ledger.py +307 -229
- package/app/core/publish/manager.py +1118 -824
- package/app/core/publish/qimao.py +176 -146
- package/app/core/publish/ws.py +139 -139
- package/app/core/quality_gate.py +194 -0
- package/app/core/redact.py +38 -38
- package/app/core/repeat_guard.py +129 -129
- package/app/core/router.py +398 -398
- package/app/core/runner.py +2142 -2142
- package/app/core/selfupdate.py +384 -384
- package/app/core/session_log.py +161 -161
- package/app/core/sessions.py +312 -312
- package/app/core/settings_schema.py +270 -270
- package/app/core/share_page.py +114 -114
- package/app/core/skill_scan.py +139 -122
- package/app/core/skillpacks/fanqie-novel.md +98 -80
- package/app/core/skillpacks/market/character-bible.md +66 -66
- package/app/core/skillpacks/market/code-risk-checklist.md +58 -58
- package/app/core/skillpacks/market/git-workflow.md +57 -57
- package/app/core/skillpacks/market/release-notes.md +72 -72
- package/app/core/skillpacks/market/weekly-report.md +71 -71
- package/app/core/skillpacks/market/worldview-consistency.md +70 -70
- package/app/core/skillpacks/qimao-signing.md +70 -59
- package/app/core/skills.py +58 -8
- package/app/core/step_runner.py +132 -132
- package/app/core/store.py +51 -0
- package/app/core/task_compile.py +199 -199
- package/app/core/telemetry.py +292 -292
- package/app/core/tlsctx.py +64 -64
- package/app/core/token_meter.py +147 -147
- package/app/core/tracing.py +144 -144
- package/app/core/upstream.py +41 -41
- package/app/core/usage.py +1035 -1035
- package/app/core/volumes.py +389 -389
- package/app/core/wxdigest.py +858 -858
- package/app/core/zentao.py +2692 -2614
- package/app/main.py +110 -39
- package/app/mcp_server.py +175 -175
- package/app/pick_dialog.py +110 -110
- package/app/ui/app.js +509 -114
- package/app/ui/artdiff.js +74 -74
- package/app/ui/board.html +162 -162
- package/app/ui/board.js +305 -305
- package/app/ui/i18n.js +41 -2
- package/app/ui/icons/bee.svg +79 -79
- package/app/ui/index.html +8 -3
- package/app/ui/manifest.json +16 -16
- package/app/ui/qrcode.js +2297 -2297
- package/app/ui/style.css +74 -26
- package/bin/tutti.js +147 -147
- package/package.json +48 -47
- package/tools/wx_reader.py +261 -261
- package/app/.playwright-cli/console-2026-09-23T08-26-03-635Z.log +0 -88
- package/app/.playwright-cli/page-2026-09-23T08-26-03-845Z.yml +0 -126
- package/app/.playwright-cli/page-2026-09-23T08-29-44-203Z.png +0 -0
- package/app/.playwright-cli/page-2026-09-23T08-35-42-046Z.yml +0 -210
- package/app/.playwright-cli/page-2026-09-23T08-36-52-858Z.png +0 -0
- package/app/.playwright-cli/page-2026-09-23T08-37-33-938Z.png +0 -0
- package/app/.playwright-cli/run-detail-after.png +0 -0
- package/app//344/275/234/345/223/201/344/277/241/346/201/257-/344/270/203/347/214/253.md +0 -18
package/app/ui/style.css
CHANGED
|
@@ -356,6 +356,9 @@ body {
|
|
|
356
356
|
*::-webkit-scrollbar-track { background: transparent; }
|
|
357
357
|
|
|
358
358
|
/* ---------------- 布局骨架 ---------------- */
|
|
359
|
+
/* ---------------- 布局骨架 ---------------- */
|
|
360
|
+
/* ⚠️ 此层列宽已被后发皮肤层(「46px rail + 216px project column」)整体覆盖,
|
|
361
|
+
侧栏宽度真源在那一层的 --side-w;此处保留原始骨架注释性记录 */
|
|
359
362
|
#app { display: grid; grid-template-columns: 264px 1fr; height: 100vh; }
|
|
360
363
|
body.side-collapsed #app { grid-template-columns: 0 1fr; }
|
|
361
364
|
#mainwrap { display: flex; flex-direction: column; min-width: 0; height: 100vh; }
|
|
@@ -366,8 +369,24 @@ body.side-collapsed #app { grid-template-columns: 0 1fr; }
|
|
|
366
369
|
background: var(--sidebar); border-right: 1px solid var(--border);
|
|
367
370
|
padding: 14px 12px 12px; min-width: 0; overflow: hidden;
|
|
368
371
|
transition: opacity .15s;
|
|
372
|
+
} padding: 14px 12px 12px; min-width: 0; overflow: hidden;
|
|
373
|
+
transition: opacity .15s;
|
|
374
|
+
position: relative;
|
|
369
375
|
}
|
|
370
376
|
body.side-collapsed #sidebar { border-right: none; padding-left: 0; padding-right: 0; opacity: 0; pointer-events: none; }
|
|
377
|
+
body.side-collapsed #sidebar { border-right: none; padding-left: 0; padding-right: 0; opacity: 0; pointer-events: none; }
|
|
378
|
+
/* 右缘拖拽手柄:贴右缘 7px 热区,hover/拖动中亮竖条;手柄属 sidebar 内,不受内容滚动影响 */
|
|
379
|
+
#side-resizer {
|
|
380
|
+
position: absolute; top: 0; bottom: 0; right: 0; width: 7px;
|
|
381
|
+
cursor: col-resize; z-index: 20; touch-action: none;
|
|
382
|
+
}
|
|
383
|
+
#side-resizer::after {
|
|
384
|
+
content: ""; position: absolute; top: 0; bottom: 0; right: 0; width: 3px;
|
|
385
|
+
background: transparent; transition: background .15s;
|
|
386
|
+
}
|
|
387
|
+
#side-resizer:hover::after, body.side-resizing #side-resizer::after { background: var(--accent); opacity: .5; }
|
|
388
|
+
body.side-resizing { cursor: col-resize; user-select: none; }
|
|
389
|
+
body.side-resizing iframe { pointer-events: none; }
|
|
371
390
|
/* 品牌:方形字母标磁贴 + 字标,单行位于侧栏最顶上 */
|
|
372
391
|
.brand { display: flex; align-items: center; gap: 10px; font-size: 15.5px; font-weight: 700; padding: 6px 8px 12px; white-space: nowrap; overflow: hidden; }
|
|
373
392
|
/* 品牌:Codex 式低调字标——纯正文色小字,无磁贴无渐变(2026-09-15 参考 Codex 桌面端定版) */
|
|
@@ -683,12 +702,15 @@ main { flex: 1; overflow-y: auto; padding: 28px 32px 96px; }
|
|
|
683
702
|
* 统一无框化:内容直接落在背景上,靠 panel-head 分隔线分节;
|
|
684
703
|
* 内部小卡片(.mgmt-panel/.opanel/.cards 卡片等)不受影响,仍保留边框 */
|
|
685
704
|
main .panel.wide { background: transparent; border: none; box-shadow: none; }
|
|
705
|
+
/* space-between 会把标题后的 ? 帮助钮当成独立一项推去行尾/行中——
|
|
706
|
+
* 改成起排 + .actions 自推右侧:标题旁的元素(? 问号、计数徽标)贴文字走 */
|
|
686
707
|
.panel-head {
|
|
687
|
-
display: flex;
|
|
708
|
+
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
|
688
709
|
margin: 0 0 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border);
|
|
689
710
|
}
|
|
690
711
|
.panel-head h2 { margin: 0; }
|
|
691
|
-
.panel-head .actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
|
|
712
|
+
.panel-head .actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-left: auto; }
|
|
713
|
+
.panel-head > .spacer { flex: 1; }
|
|
692
714
|
h2 { font-size: 15.5px; margin: 0 0 12px; font-weight: 700; }
|
|
693
715
|
h3 { font-size: 13px; margin: 18px 0 8px; color: var(--muted); }
|
|
694
716
|
/* 面板内分节标题:小号大写字距 + 贯穿分隔线 */
|
|
@@ -868,23 +890,24 @@ button.small { padding: 4px 10px; font-size: 12px; }
|
|
|
868
890
|
.route b { color: var(--text); }
|
|
869
891
|
|
|
870
892
|
.steps { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
|
|
893
|
+
/* 弹性行而非网格:行内子元素数量可变(st-model/st-prov 徽章有无),网格定死
|
|
894
|
+
* 7 列会把 chip+日志按钮挤到隐含第二行,「运行中」掉进 30px 窄列一字一行竖排 */
|
|
871
895
|
.step {
|
|
872
|
-
display:
|
|
873
|
-
align-items: center; gap: 12px;
|
|
896
|
+
display: flex; align-items: center; gap: 12px;
|
|
874
897
|
background: var(--panel2); border: 1px solid transparent; border-radius: var(--r-md);
|
|
875
898
|
padding: 10px 14px; cursor: pointer; font-size: 13px;
|
|
876
899
|
transition: border-color .15s;
|
|
877
900
|
}
|
|
878
901
|
.step:hover { border-color: var(--border-strong); }
|
|
879
902
|
.step .n {
|
|
880
|
-
width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
|
|
903
|
+
flex: none; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
|
|
881
904
|
background: var(--panel); border: 1px solid var(--border);
|
|
882
905
|
font-family: var(--mono); font-size: 11px; color: var(--muted);
|
|
883
906
|
}
|
|
884
|
-
.step .role { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
885
|
-
.step .who { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
886
|
-
.step .sum { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
887
|
-
.step .dur { color: var(--muted); font-size: 12px; font-family: var(--mono); }
|
|
907
|
+
.step .role { flex: 0 0 92px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
908
|
+
.step .who { flex: 0 0 118px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
909
|
+
.step .sum { flex: 1 1 auto; min-width: 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
910
|
+
.step .dur { flex: none; color: var(--muted); font-size: 12px; font-family: var(--mono); }
|
|
888
911
|
.step-log-btn {
|
|
889
912
|
border: 1px solid var(--border); border-radius: 999px; background: transparent;
|
|
890
913
|
color: var(--muted); padding: 3px 8px; font-size: 11px; line-height: 1.2;
|
|
@@ -1214,6 +1237,8 @@ body.inspector-open #inspector { display: flex; }
|
|
|
1214
1237
|
@media (max-width: 900px) {
|
|
1215
1238
|
#app { grid-template-columns: 1fr; }
|
|
1216
1239
|
body.side-collapsed #app { grid-template-columns: 1fr; }
|
|
1240
|
+
body.side-collapsed #app { grid-template-columns: 1fr; }
|
|
1241
|
+
#side-resizer { display: none; }
|
|
1217
1242
|
#sidebar {
|
|
1218
1243
|
position: fixed; z-index: 60; top: 0; left: 0; bottom: 0;
|
|
1219
1244
|
width: min(300px, 84vw);
|
|
@@ -2768,6 +2793,9 @@ details.sf-dir > summary i, a.sf-file i { font-style: normal; color: var(--muted
|
|
|
2768
2793
|
.bm-head .ico { color: var(--accent); width: 16px; height: 16px; }
|
|
2769
2794
|
.bm-head .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
|
|
2770
2795
|
.bm-warn { color: var(--warn); font-size: 12px; flex: none; }
|
|
2796
|
+
.bm-inherit { flex: none; font-size: 12px; color: var(--muted);
|
|
2797
|
+
border: 1px solid var(--border-strong); border-radius: 999px; padding: 1px 9px;
|
|
2798
|
+
max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2771
2799
|
.bm-guide { display: flex; gap: 12px; align-items: flex-start; padding: 14px 18px; margin: 12px 0 16px;
|
|
2772
2800
|
border: 1px dashed var(--border-strong); border-radius: var(--r-md); background: none; }
|
|
2773
2801
|
.bm-guide .ico { flex: none; margin-top: 2px; width: 18px; height: 18px; color: var(--accent); }
|
|
@@ -4641,8 +4669,8 @@ main:has(> #page-settings > #sub-runs:not(.hidden)) { padding-bottom: 28px; }
|
|
|
4641
4669
|
}
|
|
4642
4670
|
#sub-tasks #att-chips:empty { display: none; }
|
|
4643
4671
|
#sub-tasks .att-chip.att-image {
|
|
4644
|
-
position: relative; width:
|
|
4645
|
-
overflow: visible; border-radius:
|
|
4672
|
+
position: relative; width: 56px; height: 56px; max-width: none; padding: 0;
|
|
4673
|
+
overflow: visible; border-radius: 10px; background: var(--panel2);
|
|
4646
4674
|
border-color: var(--border); box-shadow: 0 2px 10px color-mix(in srgb, #000 10%, transparent);
|
|
4647
4675
|
}
|
|
4648
4676
|
#sub-tasks .att-chip.att-image img {
|
|
@@ -4654,13 +4682,13 @@ main:has(> #page-settings > #sub-runs:not(.hidden)) { padding-bottom: 28px; }
|
|
|
4654
4682
|
overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
|
|
4655
4683
|
}
|
|
4656
4684
|
#sub-tasks .att-chip.att-image .ax {
|
|
4657
|
-
position: absolute; z-index: 2; top: -
|
|
4685
|
+
position: absolute; z-index: 2; top: -5px; right: -5px;
|
|
4658
4686
|
display: inline-flex; align-items: center; justify-content: center;
|
|
4659
|
-
width:
|
|
4687
|
+
width: 18px; height: 18px; padding: 0; border: 1px solid var(--panel);
|
|
4660
4688
|
border-radius: 50%; background: var(--text); color: var(--panel);
|
|
4661
4689
|
box-shadow: 0 2px 6px color-mix(in srgb, #000 18%, transparent);
|
|
4662
4690
|
}
|
|
4663
|
-
#sub-tasks .att-chip.att-image .ax .ico { width:
|
|
4691
|
+
#sub-tasks .att-chip.att-image .ax .ico { width: 10px; height: 10px; }
|
|
4664
4692
|
#sub-tasks .att-chip.att-image .ax:hover,
|
|
4665
4693
|
#sub-tasks .att-chip.att-image .ax:focus-visible { background: var(--bad); color: #fff; outline: none; }
|
|
4666
4694
|
#sub-tasks .cmp-box > .att-chips + textarea { padding-top: 8px; }
|
|
@@ -4670,7 +4698,7 @@ main:has(> #page-settings > #sub-runs:not(.hidden)) { padding-bottom: 28px; }
|
|
|
4670
4698
|
left: 8px; right: 8px; width: auto; top: calc(100% + 2px);
|
|
4671
4699
|
}
|
|
4672
4700
|
#run-detail .rd-meta-popover #rd-overview { grid-template-columns: minmax(0, 1fr) auto; }
|
|
4673
|
-
#sub-tasks .att-chip.att-image { width:
|
|
4701
|
+
#sub-tasks .att-chip.att-image { width: 56px; height: 56px; }
|
|
4674
4702
|
}
|
|
4675
4703
|
|
|
4676
4704
|
/* ================= 详情页侧边栏重构 =================
|
|
@@ -5034,9 +5062,15 @@ main.chat-fill #run-detail.chat-mode > .rd-main { overflow: hidden; }
|
|
|
5034
5062
|
background: var(--panel); /* 浮卡实底,不透出底下时间线 */
|
|
5035
5063
|
box-shadow: 0 18px 44px rgba(6, 18, 35, .16), 0 2px 10px rgba(6, 18, 35, .08);
|
|
5036
5064
|
}
|
|
5065
|
+
/* 对话柱向左加宽(用户 2026-09-29):给浮卡让位的空白不再两侧对称预留,
|
|
5066
|
+
只在右缘留一份(版心右距 = 卡宽 + 2×间隙)——柱体在「版心左缘↔浮卡」
|
|
5067
|
+
之间自动居中,吃满原先空旷的左半边;宽帽 960→1120 */
|
|
5068
|
+
#run-detail.chat-mode .rd-pane[data-pane="chat"] {
|
|
5069
|
+
padding-right: calc(var(--rd-card-w) + 2 * var(--rd-card-gap));
|
|
5070
|
+
}
|
|
5037
5071
|
#run-detail.chat-mode .rd-chat-flow,
|
|
5038
5072
|
#run-detail.chat-mode .rd-chat-bar {
|
|
5039
|
-
max-width: min(
|
|
5073
|
+
max-width: min(1120px, 100%);
|
|
5040
5074
|
}
|
|
5041
5075
|
/* 对话模式里按需打开的其它分区(步骤/蜂巢…):右侧整体给浮卡让位 */
|
|
5042
5076
|
#run-detail.chat-mode .rd-pane:not([data-pane="chat"]) {
|
|
@@ -5963,23 +5997,24 @@ button.request-busy > * { opacity: .18; }
|
|
|
5963
5997
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
|
|
5964
5998
|
#mk-grid.mk-grouped .sec-title { margin: 16px 0 8px; }
|
|
5965
5999
|
|
|
5966
|
-
/* 首页 composer 图片附件缩略图:与任务页同款
|
|
6000
|
+
/* 首页 composer 图片附件缩略图:与任务页同款 56×56 紧凑缩略卡(此前样式只写在
|
|
5967
6001
|
* #sub-tasks 作用域,首页 img 按原始尺寸渲染直接压住输入文字——2026-09-21
|
|
5968
|
-
*
|
|
5969
|
-
|
|
5970
|
-
|
|
6002
|
+
* 用户实测「有遮挡」;2026-09-29 88×88 仍嫌太大挡视野,收紧到 56)。
|
|
6003
|
+
* 删除钮右上角悬浮。 */
|
|
6004
|
+
.att-chip.att-image { position: relative; width: 56px; height: 56px; max-width: none;
|
|
6005
|
+
padding: 0; overflow: visible; border-radius: 10px; background: var(--panel2);
|
|
5971
6006
|
border-color: var(--border); box-shadow: 0 2px 10px color-mix(in srgb, #000 10%, transparent); }
|
|
5972
6007
|
.att-chip.att-image img { display: block; width: 100%; height: 100%; object-fit: cover;
|
|
5973
6008
|
border-radius: inherit; background: var(--panel2); }
|
|
5974
6009
|
.att-chip.att-image .att-image-name { position: absolute; width: 1px; height: 1px;
|
|
5975
6010
|
padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0);
|
|
5976
6011
|
white-space: nowrap; border: 0; }
|
|
5977
|
-
.att-chip.att-image .ax { position: absolute; z-index: 2; top: -
|
|
5978
|
-
display: inline-flex; align-items: center; justify-content: center; width:
|
|
5979
|
-
height:
|
|
6012
|
+
.att-chip.att-image .ax { position: absolute; z-index: 2; top: -5px; right: -5px;
|
|
6013
|
+
display: inline-flex; align-items: center; justify-content: center; width: 18px;
|
|
6014
|
+
height: 18px; padding: 0; border: 1px solid var(--panel); border-radius: 50%;
|
|
5980
6015
|
background: var(--panel); color: var(--muted); }
|
|
5981
6016
|
.att-chip.att-image .ax:hover { background: var(--bad); color: #fff; }
|
|
5982
|
-
.att-chip.att-image .ax .ico { width:
|
|
6017
|
+
.att-chip.att-image .ax .ico { width: 10px; height: 10px; }
|
|
5983
6018
|
|
|
5984
6019
|
/* 对话气泡图片附件缩略图(2026-09-21 用户反馈:图片只显示文件名要点开才见):
|
|
5985
6020
|
* 96×96 圆角卡,点击仍走 att-open 弹大图 */
|
|
@@ -6623,7 +6658,9 @@ main { font-size: 14px; }
|
|
|
6623
6658
|
#f-goal::placeholder { color: color-mix(in srgb, var(--muted) 78%, #fff); }
|
|
6624
6659
|
|
|
6625
6660
|
/* Match the reference proportions: 46px rail + 216px project column. */
|
|
6626
|
-
#app { grid-template-columns: 46px 216px minmax(0, 1fr); }
|
|
6661
|
+
#app { grid-template-columns: 46px 216px minmax(0, 1fr); }/* Match the reference proportions: 46px rail + 216px project column.
|
|
6662
|
+
侧栏列宽走 --side-w(#side-resizer 拖动实时改,localStorage 记忆)。 */
|
|
6663
|
+
#app { grid-template-columns: 46px var(--side-w, 216px) minmax(0, 1fr); }
|
|
6627
6664
|
body.side-collapsed #app { grid-template-columns: 46px 0 minmax(0, 1fr); }
|
|
6628
6665
|
#sidebar { padding: 13px 0 10px; }
|
|
6629
6666
|
.brand { width: 100%; padding: 4px 12px 12px; justify-content: flex-start; text-align: left; }
|
|
@@ -6687,7 +6724,7 @@ body.side-collapsed #app { grid-template-columns: 46px 0 minmax(0, 1fr); }
|
|
|
6687
6724
|
Keep the rail and project column in the grid when the right detail panel opens;
|
|
6688
6725
|
the older three-column rule put the inspector on a new row and squeezed the main area. */
|
|
6689
6726
|
body.inspector-open #app {
|
|
6690
|
-
grid-template-columns: 46px 216px minmax(0, 1fr) minmax(280px, 340px);
|
|
6727
|
+
grid-template-columns: 46px 216px minmax(0, 1fr) minmax(280px, 340px); grid-template-columns: 46px var(--side-w, 216px) minmax(0, 1fr) minmax(280px, 340px);
|
|
6691
6728
|
}
|
|
6692
6729
|
body.side-collapsed.inspector-open #app {
|
|
6693
6730
|
grid-template-columns: 46px 0 minmax(0, 1fr) minmax(280px, 340px);
|
|
@@ -7010,3 +7047,14 @@ main.browser-page-active #page-settings > #sub-browser .browser-shell {
|
|
|
7010
7047
|
.browser-home-workflows { grid-template-columns: 1fr; }
|
|
7011
7048
|
.browser-home-action { min-height: 72px; }
|
|
7012
7049
|
}
|
|
7050
|
+
|
|
7051
|
+
/* 步骤行 flex 化后的防压缩补充(追加于文件尾防并行重排):徽章/按钮不许被
|
|
7052
|
+
* 挤压收缩,摘要列吸收余量——运行中行(无摘要/耗时)状态 chip 与 CLI 日志
|
|
7053
|
+
* 按钮才能稳定贴右单行,与完成行同构 */
|
|
7054
|
+
.step .st-model, .step .st-prov, .step .step-log-btn { flex: none; }
|
|
7055
|
+
|
|
7056
|
+
/* 供应商/模型状态过滤 chips(追加于文件尾防并行重排):默认只看启用,
|
|
7057
|
+
* 停用的点「已停用/全部」才现身;复用 .cat-chip 药丸,窄侧栏收紧行距 */
|
|
7058
|
+
.prov-status { margin: 2px 0 8px; }
|
|
7059
|
+
.prov-status .cat-chip { padding: 3px 9px; font-size: 12px; }
|
|
7060
|
+
.pm-status { margin: 10px 0 2px; }
|
package/bin/tutti.js
CHANGED
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
/*
|
|
4
|
-
* CodeBee 启动垫片:在本机找 Python 3.8+,以子进程方式运行包内 app/main.py。
|
|
5
|
-
* npm 只负责分发与版本管理,不携带解释器——所以运行时才探测 python,
|
|
6
|
-
* 找不到就报错并给出安装指引(不写 postinstall,避免在别人机器上制造环境事故)。
|
|
7
|
-
*
|
|
8
|
-
* 安全边界:
|
|
9
|
-
* - 子进程可执行文件全部是本文件内的字面量(py / python / python3)——包括
|
|
10
|
-
* TUTTI_PYTHON 覆盖时:它只允许在这三个字面量里选一个,绝不拼接任意路径;
|
|
11
|
-
* - 参数数组全由字面量常量拼成,不启用 shell;
|
|
12
|
-
* - 探测只传 `--version`(不向解释器传递任何代码);Windows 商店的 python.exe
|
|
13
|
-
* 假占位会非零退出,被 catch 后自然跳过;
|
|
14
|
-
* - 用户参数逐个过白名单校验(仅字母数字与 _ - . : = / @ % 空格),
|
|
15
|
-
* 含 shell 元字符/控制字符的参数直接拒绝。
|
|
16
|
-
*/
|
|
17
|
-
const { execFileSync, spawn } = require('child_process');
|
|
18
|
-
const path = require('path');
|
|
19
|
-
|
|
20
|
-
const MIN_MAJOR = 3;
|
|
21
|
-
const MIN_MINOR = 8;
|
|
22
|
-
const MAIN = path.join(__dirname, '..', 'app', 'main.py');
|
|
23
|
-
const SAFE_ARG = /^[A-Za-z0-9_\-.:=/@% ]+$/;
|
|
24
|
-
|
|
25
|
-
// 解析 `--version` 输出:形如 "Python 3.12.4",返回 {ver, major, minor} 或 null。
|
|
26
|
-
// 纯字符串切分,不用正则匹配执行路径。
|
|
27
|
-
function parseVersion(text) {
|
|
28
|
-
const at = String(text).indexOf('Python ');
|
|
29
|
-
if (at === -1) return null;
|
|
30
|
-
const parts = String(text).slice(at + 7).trim().split(' ')[0].split('.');
|
|
31
|
-
const major = Number(parts[0]);
|
|
32
|
-
const minor = Number(parts[1]);
|
|
33
|
-
if (!Number.isFinite(major) || !Number.isFinite(minor)) return null;
|
|
34
|
-
return { ver: major + '.' + minor, major: major, minor: minor };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function probePy() {
|
|
38
|
-
try {
|
|
39
|
-
return parseVersion(execFileSync('py', ['-3', '--version'],
|
|
40
|
-
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
41
|
-
} catch (e) { return null; }
|
|
42
|
-
}
|
|
43
|
-
function probePython() {
|
|
44
|
-
try {
|
|
45
|
-
return parseVersion(execFileSync('python', ['--version'],
|
|
46
|
-
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
47
|
-
} catch (e) { return null; }
|
|
48
|
-
}
|
|
49
|
-
function probePython3() {
|
|
50
|
-
try {
|
|
51
|
-
return parseVersion(execFileSync('python3', ['--version'],
|
|
52
|
-
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
53
|
-
} catch (e) { return null; }
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 探测顺序:win32 优先 py 启动器(跨版本选真 3.x),其余按 python3 → python。
|
|
57
|
-
function resolvePython() {
|
|
58
|
-
const order = process.platform === 'win32'
|
|
59
|
-
? [['py', probePy], ['python', probePython], ['python3', probePython3]]
|
|
60
|
-
: [['python3', probePython3], ['python', probePython]];
|
|
61
|
-
for (const [name, probe] of order) {
|
|
62
|
-
const hit = probe();
|
|
63
|
-
if (!hit) continue;
|
|
64
|
-
if (hit.major > MIN_MAJOR || (hit.major === MIN_MAJOR && hit.minor >= MIN_MINOR)) {
|
|
65
|
-
return { name: name };
|
|
66
|
-
}
|
|
67
|
-
return { tooOld: true, name: name, ver: hit.ver };
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function guide() {
|
|
73
|
-
const url = { win32: 'https://www.python.org/downloads/windows/',
|
|
74
|
-
darwin: 'https://www.python.org/downloads/macos/',
|
|
75
|
-
linux: 'https://docs.python.org/3/using/unix.html' }[process.platform]
|
|
76
|
-
|| 'https://www.python.org/downloads/';
|
|
77
|
-
return 'CodeBee 需要本机安装 Python 3.8+(npm 包不含解释器)。\n'
|
|
78
|
-
+ ' · 安装:' + url + '\n'
|
|
79
|
-
+ ' · Windows 安装时勾选 “Add python.exe to PATH”(自带 py 启动器)\n'
|
|
80
|
-
+ '装好后重新运行:codebee';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const py = resolvePython();
|
|
84
|
-
if (!py) {
|
|
85
|
-
console.error('[CodeBee] 未找到可用的 Python。\n' + guide());
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
if (py.tooOld) {
|
|
89
|
-
console.error('[CodeBee] 找到 ' + py.name + '(' + py.ver + '),但版本过低。\n' + guide());
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const userArgs = [];
|
|
94
|
-
for (const a of process.argv.slice(2)) {
|
|
95
|
-
if (typeof a === 'string' && SAFE_ARG.test(a)) {
|
|
96
|
-
userArgs.push(a);
|
|
97
|
-
} else {
|
|
98
|
-
console.error('[CodeBee] 参数含非法字符,已拒绝:' + String(a).slice(0, 80));
|
|
99
|
-
process.exit(2);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// CLI 转发契约:codebee 之后的用户参数(已过白名单)原样作为 main.py 的 argv。
|
|
104
|
-
// 控制台日志即见:GBK 控制台下强制 UTF-8 输出(否则中文 print 触发 UnicodeEncodeError 静默卡死)。
|
|
105
|
-
const childEnv = Object.assign({}, process.env, { PYTHONIOENCODING: 'utf-8', PYTHONUTF8: '1', PYTHONUNBUFFERED: '1' });
|
|
106
|
-
// TUTTI_PYTHON 覆盖解释器:只允许在三个字面量里选(py/python/python3,.exe
|
|
107
|
-
// 后缀可选、大小写不限)——环境变量永远只做「选择题」,不做「填空题」;
|
|
108
|
-
// 机器上有多个解释器且探测选错时,用它切换。
|
|
109
|
-
let exe = py.name;
|
|
110
|
-
const ovRaw = String(process.env.TUTTI_PYTHON || '').trim().toLowerCase();
|
|
111
|
-
const ov = ovRaw.endsWith('.exe') ? ovRaw.slice(0, -4) : ovRaw;
|
|
112
|
-
if (ov === 'python') {
|
|
113
|
-
exe = 'python';
|
|
114
|
-
} else if (ov === 'python3') {
|
|
115
|
-
exe = 'python3';
|
|
116
|
-
} else if (ov === 'py') {
|
|
117
|
-
exe = 'py';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
let child;
|
|
121
|
-
if (exe === 'py') {
|
|
122
|
-
child = spawn('py', ['-3', MAIN, ...userArgs], { stdio: 'inherit', env: childEnv });
|
|
123
|
-
} else if (exe === 'python') {
|
|
124
|
-
child = spawn('python', [MAIN, ...userArgs], { stdio: 'inherit', env: childEnv });
|
|
125
|
-
} else {
|
|
126
|
-
child = spawn('python3', [MAIN, ...userArgs], { stdio: 'inherit', env: childEnv });
|
|
127
|
-
}
|
|
128
|
-
console.log('[CodeBee] 正在启动(Python: ' + exe + ')… 浏览器将自动打开 http://127.0.0.1:8765;'
|
|
129
|
-
+ '本窗口保持开着就是服务,Ctrl+C 退出。');
|
|
130
|
-
|
|
131
|
-
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
132
|
-
process.on(sig, () => { try { child.kill(sig); } catch (e) { /* 已退出 */ } });
|
|
133
|
-
}
|
|
134
|
-
const t0 = Date.now();
|
|
135
|
-
child.on('exit', (code, signal) => {
|
|
136
|
-
if (!signal && code != null && code !== 0 && Date.now() - t0 < 4000) {
|
|
137
|
-
// 秒退:多半是 py 启动器指到了坏解释器(如损坏的 Anaconda)。给排障出口。
|
|
138
|
-
console.error('[CodeBee] 启动失败:Python 进程 ' + (code ? '退出码 ' + code : '异常终止') + '。'
|
|
139
|
-
+ '\n · 运行 python --version 确认可用且为 3.8+'
|
|
140
|
-
+ '\n · 若装有多个 Python,可设环境变量 TUTTI_PYTHON 切换(cmd:set TUTTI_PYTHON=python)');
|
|
141
|
-
}
|
|
142
|
-
process.exit(signal ? 1 : (code == null ? 0 : code));
|
|
143
|
-
});
|
|
144
|
-
child.on('error', (e) => {
|
|
145
|
-
console.error('[CodeBee] 无法启动 Python:' + e.message);
|
|
146
|
-
process.exit(1);
|
|
147
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/*
|
|
4
|
+
* CodeBee 启动垫片:在本机找 Python 3.8+,以子进程方式运行包内 app/main.py。
|
|
5
|
+
* npm 只负责分发与版本管理,不携带解释器——所以运行时才探测 python,
|
|
6
|
+
* 找不到就报错并给出安装指引(不写 postinstall,避免在别人机器上制造环境事故)。
|
|
7
|
+
*
|
|
8
|
+
* 安全边界:
|
|
9
|
+
* - 子进程可执行文件全部是本文件内的字面量(py / python / python3)——包括
|
|
10
|
+
* TUTTI_PYTHON 覆盖时:它只允许在这三个字面量里选一个,绝不拼接任意路径;
|
|
11
|
+
* - 参数数组全由字面量常量拼成,不启用 shell;
|
|
12
|
+
* - 探测只传 `--version`(不向解释器传递任何代码);Windows 商店的 python.exe
|
|
13
|
+
* 假占位会非零退出,被 catch 后自然跳过;
|
|
14
|
+
* - 用户参数逐个过白名单校验(仅字母数字与 _ - . : = / @ % 空格),
|
|
15
|
+
* 含 shell 元字符/控制字符的参数直接拒绝。
|
|
16
|
+
*/
|
|
17
|
+
const { execFileSync, spawn } = require('child_process');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
const MIN_MAJOR = 3;
|
|
21
|
+
const MIN_MINOR = 8;
|
|
22
|
+
const MAIN = path.join(__dirname, '..', 'app', 'main.py');
|
|
23
|
+
const SAFE_ARG = /^[A-Za-z0-9_\-.:=/@% ]+$/;
|
|
24
|
+
|
|
25
|
+
// 解析 `--version` 输出:形如 "Python 3.12.4",返回 {ver, major, minor} 或 null。
|
|
26
|
+
// 纯字符串切分,不用正则匹配执行路径。
|
|
27
|
+
function parseVersion(text) {
|
|
28
|
+
const at = String(text).indexOf('Python ');
|
|
29
|
+
if (at === -1) return null;
|
|
30
|
+
const parts = String(text).slice(at + 7).trim().split(' ')[0].split('.');
|
|
31
|
+
const major = Number(parts[0]);
|
|
32
|
+
const minor = Number(parts[1]);
|
|
33
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor)) return null;
|
|
34
|
+
return { ver: major + '.' + minor, major: major, minor: minor };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function probePy() {
|
|
38
|
+
try {
|
|
39
|
+
return parseVersion(execFileSync('py', ['-3', '--version'],
|
|
40
|
+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
41
|
+
} catch (e) { return null; }
|
|
42
|
+
}
|
|
43
|
+
function probePython() {
|
|
44
|
+
try {
|
|
45
|
+
return parseVersion(execFileSync('python', ['--version'],
|
|
46
|
+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
47
|
+
} catch (e) { return null; }
|
|
48
|
+
}
|
|
49
|
+
function probePython3() {
|
|
50
|
+
try {
|
|
51
|
+
return parseVersion(execFileSync('python3', ['--version'],
|
|
52
|
+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
53
|
+
} catch (e) { return null; }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 探测顺序:win32 优先 py 启动器(跨版本选真 3.x),其余按 python3 → python。
|
|
57
|
+
function resolvePython() {
|
|
58
|
+
const order = process.platform === 'win32'
|
|
59
|
+
? [['py', probePy], ['python', probePython], ['python3', probePython3]]
|
|
60
|
+
: [['python3', probePython3], ['python', probePython]];
|
|
61
|
+
for (const [name, probe] of order) {
|
|
62
|
+
const hit = probe();
|
|
63
|
+
if (!hit) continue;
|
|
64
|
+
if (hit.major > MIN_MAJOR || (hit.major === MIN_MAJOR && hit.minor >= MIN_MINOR)) {
|
|
65
|
+
return { name: name };
|
|
66
|
+
}
|
|
67
|
+
return { tooOld: true, name: name, ver: hit.ver };
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function guide() {
|
|
73
|
+
const url = { win32: 'https://www.python.org/downloads/windows/',
|
|
74
|
+
darwin: 'https://www.python.org/downloads/macos/',
|
|
75
|
+
linux: 'https://docs.python.org/3/using/unix.html' }[process.platform]
|
|
76
|
+
|| 'https://www.python.org/downloads/';
|
|
77
|
+
return 'CodeBee 需要本机安装 Python 3.8+(npm 包不含解释器)。\n'
|
|
78
|
+
+ ' · 安装:' + url + '\n'
|
|
79
|
+
+ ' · Windows 安装时勾选 “Add python.exe to PATH”(自带 py 启动器)\n'
|
|
80
|
+
+ '装好后重新运行:codebee';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const py = resolvePython();
|
|
84
|
+
if (!py) {
|
|
85
|
+
console.error('[CodeBee] 未找到可用的 Python。\n' + guide());
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
if (py.tooOld) {
|
|
89
|
+
console.error('[CodeBee] 找到 ' + py.name + '(' + py.ver + '),但版本过低。\n' + guide());
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const userArgs = [];
|
|
94
|
+
for (const a of process.argv.slice(2)) {
|
|
95
|
+
if (typeof a === 'string' && SAFE_ARG.test(a)) {
|
|
96
|
+
userArgs.push(a);
|
|
97
|
+
} else {
|
|
98
|
+
console.error('[CodeBee] 参数含非法字符,已拒绝:' + String(a).slice(0, 80));
|
|
99
|
+
process.exit(2);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// CLI 转发契约:codebee 之后的用户参数(已过白名单)原样作为 main.py 的 argv。
|
|
104
|
+
// 控制台日志即见:GBK 控制台下强制 UTF-8 输出(否则中文 print 触发 UnicodeEncodeError 静默卡死)。
|
|
105
|
+
const childEnv = Object.assign({}, process.env, { PYTHONIOENCODING: 'utf-8', PYTHONUTF8: '1', PYTHONUNBUFFERED: '1' });
|
|
106
|
+
// TUTTI_PYTHON 覆盖解释器:只允许在三个字面量里选(py/python/python3,.exe
|
|
107
|
+
// 后缀可选、大小写不限)——环境变量永远只做「选择题」,不做「填空题」;
|
|
108
|
+
// 机器上有多个解释器且探测选错时,用它切换。
|
|
109
|
+
let exe = py.name;
|
|
110
|
+
const ovRaw = String(process.env.TUTTI_PYTHON || '').trim().toLowerCase();
|
|
111
|
+
const ov = ovRaw.endsWith('.exe') ? ovRaw.slice(0, -4) : ovRaw;
|
|
112
|
+
if (ov === 'python') {
|
|
113
|
+
exe = 'python';
|
|
114
|
+
} else if (ov === 'python3') {
|
|
115
|
+
exe = 'python3';
|
|
116
|
+
} else if (ov === 'py') {
|
|
117
|
+
exe = 'py';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let child;
|
|
121
|
+
if (exe === 'py') {
|
|
122
|
+
child = spawn('py', ['-3', MAIN, ...userArgs], { stdio: 'inherit', env: childEnv });
|
|
123
|
+
} else if (exe === 'python') {
|
|
124
|
+
child = spawn('python', [MAIN, ...userArgs], { stdio: 'inherit', env: childEnv });
|
|
125
|
+
} else {
|
|
126
|
+
child = spawn('python3', [MAIN, ...userArgs], { stdio: 'inherit', env: childEnv });
|
|
127
|
+
}
|
|
128
|
+
console.log('[CodeBee] 正在启动(Python: ' + exe + ')… 浏览器将自动打开 http://127.0.0.1:8765;'
|
|
129
|
+
+ '本窗口保持开着就是服务,Ctrl+C 退出。');
|
|
130
|
+
|
|
131
|
+
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
132
|
+
process.on(sig, () => { try { child.kill(sig); } catch (e) { /* 已退出 */ } });
|
|
133
|
+
}
|
|
134
|
+
const t0 = Date.now();
|
|
135
|
+
child.on('exit', (code, signal) => {
|
|
136
|
+
if (!signal && code != null && code !== 0 && Date.now() - t0 < 4000) {
|
|
137
|
+
// 秒退:多半是 py 启动器指到了坏解释器(如损坏的 Anaconda)。给排障出口。
|
|
138
|
+
console.error('[CodeBee] 启动失败:Python 进程 ' + (code ? '退出码 ' + code : '异常终止') + '。'
|
|
139
|
+
+ '\n · 运行 python --version 确认可用且为 3.8+'
|
|
140
|
+
+ '\n · 若装有多个 Python,可设环境变量 TUTTI_PYTHON 切换(cmd:set TUTTI_PYTHON=python)');
|
|
141
|
+
}
|
|
142
|
+
process.exit(signal ? 1 : (code == null ? 0 : code));
|
|
143
|
+
});
|
|
144
|
+
child.on('error', (e) => {
|
|
145
|
+
console.error('[CodeBee] 无法启动 Python:' + e.message);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
package/package.json
CHANGED
|
@@ -1,47 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "codebee",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "CodeBee · 多智能体编排台 — 统一编排本机 AI 编码 CLI(Codex / Claude Code / QwenCode / OpenCode / Aider…):目标→拆解→路由→执行→验证→跨厂商评审→修复→报告。纯 Python 标准库实现,本地 Web UI。",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"bin": {
|
|
7
|
-
"codebee": "bin/tutti.js"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"app",
|
|
11
|
-
"!app/tests",
|
|
12
|
-
"bin",
|
|
13
|
-
"tools/wx_reader.py",
|
|
14
|
-
"CHANGELOG.md",
|
|
15
|
-
"README.md",
|
|
16
|
-
"LICENSE"
|
|
17
|
-
],
|
|
18
|
-
"engines": {
|
|
19
|
-
"node": ">=14"
|
|
20
|
-
},
|
|
21
|
-
"os": [
|
|
22
|
-
"win32",
|
|
23
|
-
"darwin",
|
|
24
|
-
"linux"
|
|
25
|
-
],
|
|
26
|
-
"keywords": [
|
|
27
|
-
"agent",
|
|
28
|
-
"orchestration",
|
|
29
|
-
"codex",
|
|
30
|
-
"claude",
|
|
31
|
-
"llm",
|
|
32
|
-
"cli",
|
|
33
|
-
"multi-agent"
|
|
34
|
-
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"release:gate": "python scripts/release_gate.py",
|
|
37
|
-
"release": "python scripts/release_gate.py --publish",
|
|
38
|
-
"prepublishOnly": "python scripts/release_gate.py"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "codebee",
|
|
3
|
+
"version": "0.1.73",
|
|
4
|
+
"description": "CodeBee · 多智能体编排台 — 统一编排本机 AI 编码 CLI(Codex / Claude Code / QwenCode / OpenCode / Aider…):目标→拆解→路由→执行→验证→跨厂商评审→修复→报告。纯 Python 标准库实现,本地 Web UI。",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"codebee": "bin/tutti.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"app",
|
|
11
|
+
"!app/tests",
|
|
12
|
+
"bin",
|
|
13
|
+
"tools/wx_reader.py",
|
|
14
|
+
"CHANGELOG.md",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=14"
|
|
20
|
+
},
|
|
21
|
+
"os": [
|
|
22
|
+
"win32",
|
|
23
|
+
"darwin",
|
|
24
|
+
"linux"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"agent",
|
|
28
|
+
"orchestration",
|
|
29
|
+
"codex",
|
|
30
|
+
"claude",
|
|
31
|
+
"llm",
|
|
32
|
+
"cli",
|
|
33
|
+
"multi-agent"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"release:gate": "python scripts/release_gate.py",
|
|
37
|
+
"release": "python scripts/release_gate.py --publish",
|
|
38
|
+
"prepublishOnly": "python scripts/release_gate.py",
|
|
39
|
+
"release:clean": "python scripts/prune_release_debris.py"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/Vercel-By-WXP/CodeBee.git"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|