codebee 0.1.69 → 0.1.71

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.
Files changed (133) hide show
  1. package/CHANGELOG.md +589 -543
  2. package/LICENSE +21 -21
  3. package/README.md +509 -508
  4. package/app/.playwright-cli/console-2026-09-23T08-26-03-635Z.log +88 -0
  5. package/app/.playwright-cli/page-2026-09-23T08-26-03-845Z.yml +126 -0
  6. package/app/.playwright-cli/page-2026-09-23T08-29-44-203Z.png +0 -0
  7. package/app/.playwright-cli/page-2026-09-23T08-35-42-046Z.yml +210 -0
  8. package/app/.playwright-cli/page-2026-09-23T08-36-52-858Z.png +0 -0
  9. package/app/.playwright-cli/page-2026-09-23T08-37-33-938Z.png +0 -0
  10. package/app/.playwright-cli/run-detail-after.png +0 -0
  11. package/app/browser-final-1440.png +0 -0
  12. package/app/browser-final-390.png +0 -0
  13. package/app/browser-google-fallback.png +0 -0
  14. package/app/browser-google-test.png +0 -0
  15. package/app/browser-workbench-1440.png +0 -0
  16. package/app/browser-workbench-390.png +0 -0
  17. package/app/browser-workspace-google.png +0 -0
  18. package/app/browser-workspace-smoke.png +0 -0
  19. package/app/browser-workspace.png +0 -0
  20. package/app/core/acceptance.py +100 -100
  21. package/app/core/aiflavor.py +197 -197
  22. package/app/core/artifacts.py +148 -148
  23. package/app/core/assets.py +110 -110
  24. package/app/core/attachments.py +623 -623
  25. package/app/core/audit.py +30 -0
  26. package/app/core/automation.py +107 -12
  27. package/app/core/backup.py +470 -470
  28. package/app/core/beekeeper.py +183 -183
  29. package/app/core/benchstore.py +95 -0
  30. package/app/core/board.py +209 -209
  31. package/app/core/bookmeta.py +935 -930
  32. package/app/core/bookmeta_catalog.py +180 -180
  33. package/app/core/branching.py +137 -137
  34. package/app/core/builtin_agent.py +1673 -1234
  35. package/app/core/capability.py +144 -144
  36. package/app/core/catalog.py +7 -1
  37. package/app/core/chaptersafe.py +32 -32
  38. package/app/core/cleanup.py +303 -303
  39. package/app/core/compaction.py +201 -201
  40. package/app/core/covergen.py +356 -356
  41. package/app/core/defectretro.py +43 -43
  42. package/app/core/diagnostics.py +114 -114
  43. package/app/core/dispatch.py +190 -173
  44. package/app/core/dispatch_log.py +128 -128
  45. package/app/core/env_scrub.py +85 -85
  46. package/app/core/error_codes.py +11 -2
  47. package/app/core/errorlog.py +137 -137
  48. package/app/core/evalbench.py +720 -0
  49. package/app/core/evaluation.py +174 -174
  50. package/app/core/failure_notify.py +290 -290
  51. package/app/core/flows.py +234 -9
  52. package/app/core/goal_service.py +167 -167
  53. package/app/core/health.py +374 -374
  54. package/app/core/history.py +38 -38
  55. package/app/core/hooks.py +162 -162
  56. package/app/core/jobs.py +22 -1
  57. package/app/core/manager.py +2143 -2122
  58. package/app/core/market_remote.py +10 -0
  59. package/app/core/mcp_client.py +287 -0
  60. package/app/core/mocks.py +64 -64
  61. package/app/core/modelhub.py +185 -2
  62. package/app/core/notify.py +201 -106
  63. package/app/core/novel_quality.py +189 -0
  64. package/app/core/operations.py +228 -228
  65. package/app/core/paihang.py +138 -138
  66. package/app/core/paths.py +4 -0
  67. package/app/core/pipeline.py +426 -28
  68. package/app/core/planner.py +243 -22
  69. package/app/core/plugins.py +525 -0
  70. package/app/core/portguard.py +111 -111
  71. package/app/core/preview.py +293 -293
  72. package/app/core/publish/__init__.py +7 -7
  73. package/app/core/publish/auto.py +367 -367
  74. package/app/core/publish/browser.py +655 -539
  75. package/app/core/publish/fanqie.py +165 -159
  76. package/app/core/publish/flow.py +589 -440
  77. package/app/core/publish/flows-fanqie-calibrated.json +336 -332
  78. package/app/core/publish/ledger.py +229 -203
  79. package/app/core/publish/manager.py +824 -692
  80. package/app/core/publish/qimao.py +146 -141
  81. package/app/core/publish/ws.py +139 -139
  82. package/app/core/redact.py +38 -38
  83. package/app/core/remotesync.py +121 -0
  84. package/app/core/repeat_guard.py +129 -129
  85. package/app/core/router.py +398 -398
  86. package/app/core/runner.py +2142 -2067
  87. package/app/core/selfupdate.py +384 -384
  88. package/app/core/session_log.py +161 -161
  89. package/app/core/sessions.py +312 -312
  90. package/app/core/settings.py +42 -4
  91. package/app/core/settings_schema.py +270 -262
  92. package/app/core/share_page.py +114 -114
  93. package/app/core/skill_scan.py +122 -122
  94. package/app/core/skillpacks/fanqie-novel.md +80 -80
  95. package/app/core/skillpacks/market/character-bible.md +66 -66
  96. package/app/core/skillpacks/market/code-risk-checklist.md +58 -58
  97. package/app/core/skillpacks/market/git-workflow.md +57 -57
  98. package/app/core/skillpacks/market/release-notes.md +72 -72
  99. package/app/core/skillpacks/market/weekly-report.md +71 -71
  100. package/app/core/skillpacks/market/worldview-consistency.md +70 -70
  101. package/app/core/step_runner.py +132 -132
  102. package/app/core/store.py +30 -8
  103. package/app/core/task_compile.py +199 -199
  104. package/app/core/telemetry.py +292 -292
  105. package/app/core/tlsctx.py +64 -64
  106. package/app/core/token_meter.py +147 -147
  107. package/app/core/tracing.py +144 -144
  108. package/app/core/upstream.py +41 -41
  109. package/app/core/usage.py +1035 -862
  110. package/app/core/volumes.py +389 -389
  111. package/app/core/wxdigest.py +858 -858
  112. package/app/core/zentao.py +2614 -2465
  113. package/app/current-browser.png +0 -0
  114. package/app/main.py +316 -17
  115. package/app/mcp_server.py +175 -0
  116. package/app/pet.py +83 -22
  117. package/app/pick_dialog.py +110 -110
  118. package/app/plugins/code-review-helper/.codex-plugin/plugin.json +18 -0
  119. package/app/plugins/code-review-helper/skills/review.md +16 -0
  120. package/app/ui/app.js +1391 -77
  121. package/app/ui/artdiff.js +74 -74
  122. package/app/ui/board.html +162 -162
  123. package/app/ui/board.js +305 -305
  124. package/app/ui/i18n.js +249 -7
  125. package/app/ui/icons/bee.svg +79 -79
  126. package/app/ui/index.html +277 -13
  127. package/app/ui/manifest.json +16 -16
  128. package/app/ui/qrcode.js +2297 -2297
  129. package/app/ui/style.css +845 -12
  130. package/app//344/275/234/345/223/201/344/277/241/346/201/257-/344/270/203/347/214/253.md +18 -0
  131. package/bin/tutti.js +147 -147
  132. package/package.json +47 -46
  133. package/tools/wx_reader.py +261 -261
@@ -1,111 +1,111 @@
1
- # -*- coding: utf-8 -*-
2
- """启动端口清场(用户拍板 2026-09-21):端口被占时先清场再启动。
3
-
4
- - **自家旧实例**(命令行含本包 main.py 完整路径,或 npm 包内 app/main.py)
5
- → 杀树(TerminateProcess 直杀)——升级/重启最常见的占用者就是没退干净
6
- 的 CodeBee 自己;控制台进程对温和信号(WM_CLOSE)无反应,温和关不掉
7
- 正是用户「旧进程太难杀」的痛点,所以自家实例直接强杀。
8
- - **别人的进程** → 只报告占用者,不发送任何信号;启动流程不得替用户
9
- 关闭可能正在开发中的服务。
10
- - 系统/自身进程拒关(portscan 内置护栏)。
11
- """
12
- from __future__ import annotations
13
-
14
- import logging
15
- import os
16
- import shlex
17
- import subprocess
18
-
19
- from . import portscan, runner
20
-
21
- log = logging.getLogger(__name__)
22
-
23
- PS_EXE = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
24
-
25
-
26
- def proc_cmdline(pid):
27
- """读进程命令行;失败返回空串。仅用于确认旧 CodeBee 实例身份。"""
28
- try:
29
- pid = int(pid)
30
- except (TypeError, ValueError):
31
- return ""
32
- if pid <= 0:
33
- return ""
34
- if os.name != "nt":
35
- try:
36
- with open("/proc/%d/cmdline" % pid, "rb") as fh:
37
- return fh.read().decode("utf-8", "replace").replace("\x00", " ").strip()
38
- except Exception:
39
- return ""
40
- try:
41
- r = subprocess.run(
42
- [PS_EXE, "-NoProfile", "-Command",
43
- "(Get-CimInstance Win32_Process -Filter 'ProcessId = %d').CommandLine" % pid],
44
- capture_output=True, timeout=10)
45
- return r.stdout.decode("utf-8", "replace").strip() if r.returncode == 0 else ""
46
- except Exception:
47
- return ""
48
-
49
-
50
- def _command_tokens(cmdline):
51
- try:
52
- return [token.strip().strip('"').strip("'")
53
- for token in shlex.split(str(cmdline or ""), posix=False)]
54
- except (TypeError, ValueError):
55
- return []
56
-
57
-
58
- def is_own_instance(cmdline, main_script, port=None):
59
- """按启动器、脚本独立参数和端口精确确认 CodeBee 实例。"""
60
- tokens = _command_tokens(cmdline)
61
- if len(tokens) < 2:
62
- return False
63
- launcher = os.path.splitext(os.path.basename(tokens[0]))[0].lower()
64
- if launcher not in ("python", "python3", "py"):
65
- return False
66
- script = ""
67
- for token in tokens[1:]:
68
- if token.startswith("-"):
69
- continue
70
- script = token
71
- break
72
- if not script or not os.path.isabs(script):
73
- return False
74
- actual = os.path.normcase(os.path.normpath(os.path.abspath(script)))
75
- expected = os.path.normcase(os.path.normpath(os.path.abspath(str(main_script))))
76
- packaged = actual.replace("\\", "/").lower().endswith(
77
- "/node_modules/codebee/app/main.py")
78
- if actual != expected and not packaged:
79
- return False
80
- if port is None:
81
- return True
82
- try:
83
- wanted = str(int(port))
84
- except (TypeError, ValueError):
85
- return False
86
- explicit_port = None
87
- for i, token in enumerate(tokens):
88
- if token == "--port" and i + 1 < len(tokens):
89
- explicit_port = tokens[i + 1]
90
- elif token.startswith("--port="):
91
- explicit_port = token.split("=", 1)[1]
92
- # argparse 默认端口可不出现在旧实例参数中;非默认端口必须显式相符。
93
- return ((explicit_port == wanted) if explicit_port is not None
94
- else wanted == "8765")
95
-
96
-
97
- def clear_stale_port(port, main_script):
98
- """清掉占用端口的进程。返回 (是否清掉, 人话说明)。"""
99
- holders = [p for p in portscan.listening_ports() if p.get("port") == int(port)]
100
- if not holders:
101
- return True, ""
102
- pid = int(holders[0].get("pid") or 0)
103
- if pid <= 4 or pid == os.getpid():
104
- return False, "占用者是系统进程/自身,拒绝清理"
105
- if is_own_instance(proc_cmdline(pid), main_script, port=port):
106
- try:
107
- runner._kill_tree(pid)
108
- return True, "已结束旧实例 PID %d" % pid
109
- except Exception as e:
110
- return False, "旧实例 PID %d 清理失败 %s" % (pid, str(e)[:80])
111
- return False, "占用者非 CodeBee(PID %d),未自动关闭" % pid
1
+ # -*- coding: utf-8 -*-
2
+ """启动端口清场(用户拍板 2026-09-21):端口被占时先清场再启动。
3
+
4
+ - **自家旧实例**(命令行含本包 main.py 完整路径,或 npm 包内 app/main.py)
5
+ → 杀树(TerminateProcess 直杀)——升级/重启最常见的占用者就是没退干净
6
+ 的 CodeBee 自己;控制台进程对温和信号(WM_CLOSE)无反应,温和关不掉
7
+ 正是用户「旧进程太难杀」的痛点,所以自家实例直接强杀。
8
+ - **别人的进程** → 只报告占用者,不发送任何信号;启动流程不得替用户
9
+ 关闭可能正在开发中的服务。
10
+ - 系统/自身进程拒关(portscan 内置护栏)。
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import logging
15
+ import os
16
+ import shlex
17
+ import subprocess
18
+
19
+ from . import portscan, runner
20
+
21
+ log = logging.getLogger(__name__)
22
+
23
+ PS_EXE = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
24
+
25
+
26
+ def proc_cmdline(pid):
27
+ """读进程命令行;失败返回空串。仅用于确认旧 CodeBee 实例身份。"""
28
+ try:
29
+ pid = int(pid)
30
+ except (TypeError, ValueError):
31
+ return ""
32
+ if pid <= 0:
33
+ return ""
34
+ if os.name != "nt":
35
+ try:
36
+ with open("/proc/%d/cmdline" % pid, "rb") as fh:
37
+ return fh.read().decode("utf-8", "replace").replace("\x00", " ").strip()
38
+ except Exception:
39
+ return ""
40
+ try:
41
+ r = subprocess.run(
42
+ [PS_EXE, "-NoProfile", "-Command",
43
+ "(Get-CimInstance Win32_Process -Filter 'ProcessId = %d').CommandLine" % pid],
44
+ capture_output=True, timeout=10)
45
+ return r.stdout.decode("utf-8", "replace").strip() if r.returncode == 0 else ""
46
+ except Exception:
47
+ return ""
48
+
49
+
50
+ def _command_tokens(cmdline):
51
+ try:
52
+ return [token.strip().strip('"').strip("'")
53
+ for token in shlex.split(str(cmdline or ""), posix=False)]
54
+ except (TypeError, ValueError):
55
+ return []
56
+
57
+
58
+ def is_own_instance(cmdline, main_script, port=None):
59
+ """按启动器、脚本独立参数和端口精确确认 CodeBee 实例。"""
60
+ tokens = _command_tokens(cmdline)
61
+ if len(tokens) < 2:
62
+ return False
63
+ launcher = os.path.splitext(os.path.basename(tokens[0]))[0].lower()
64
+ if launcher not in ("python", "python3", "py"):
65
+ return False
66
+ script = ""
67
+ for token in tokens[1:]:
68
+ if token.startswith("-"):
69
+ continue
70
+ script = token
71
+ break
72
+ if not script or not os.path.isabs(script):
73
+ return False
74
+ actual = os.path.normcase(os.path.normpath(os.path.abspath(script)))
75
+ expected = os.path.normcase(os.path.normpath(os.path.abspath(str(main_script))))
76
+ packaged = actual.replace("\\", "/").lower().endswith(
77
+ "/node_modules/codebee/app/main.py")
78
+ if actual != expected and not packaged:
79
+ return False
80
+ if port is None:
81
+ return True
82
+ try:
83
+ wanted = str(int(port))
84
+ except (TypeError, ValueError):
85
+ return False
86
+ explicit_port = None
87
+ for i, token in enumerate(tokens):
88
+ if token == "--port" and i + 1 < len(tokens):
89
+ explicit_port = tokens[i + 1]
90
+ elif token.startswith("--port="):
91
+ explicit_port = token.split("=", 1)[1]
92
+ # argparse 默认端口可不出现在旧实例参数中;非默认端口必须显式相符。
93
+ return ((explicit_port == wanted) if explicit_port is not None
94
+ else wanted == "8765")
95
+
96
+
97
+ def clear_stale_port(port, main_script):
98
+ """清掉占用端口的进程。返回 (是否清掉, 人话说明)。"""
99
+ holders = [p for p in portscan.listening_ports() if p.get("port") == int(port)]
100
+ if not holders:
101
+ return True, ""
102
+ pid = int(holders[0].get("pid") or 0)
103
+ if pid <= 4 or pid == os.getpid():
104
+ return False, "占用者是系统进程/自身,拒绝清理"
105
+ if is_own_instance(proc_cmdline(pid), main_script, port=port):
106
+ try:
107
+ runner._kill_tree(pid)
108
+ return True, "已结束旧实例 PID %d" % pid
109
+ except Exception as e:
110
+ return False, "旧实例 PID %d 清理失败 %s" % (pid, str(e)[:80])
111
+ return False, "占用者非 CodeBee(PID %d),未自动关闭" % pid