codebee 0.1.103 → 0.1.105
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 +12 -0
- package/LICENSE +21 -21
- package/README.md +5 -3
- package/app/core/acceptance.py +100 -100
- package/app/core/acp_client.py +457 -457
- package/app/core/aiflavor.py +197 -197
- package/app/core/analytics.py +38 -38
- 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/backend_profiles.py +188 -188
- package/app/core/backup.py +470 -470
- package/app/core/beekeeper.py +183 -183
- package/app/core/benchstore.py +102 -102
- package/app/core/bookmeta.py +1036 -1036
- package/app/core/bookmeta_catalog.py +180 -180
- package/app/core/branching.py +137 -137
- package/app/core/capability.py +144 -144
- package/app/core/chaptersafe.py +32 -32
- package/app/core/checkpoints.py +48 -5
- package/app/core/cleanup.py +303 -303
- package/app/core/command_auth.py +302 -302
- package/app/core/compaction.py +201 -201
- package/app/core/contracts.py +255 -255
- 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_log.py +128 -128
- package/app/core/env_scrub.py +85 -85
- package/app/core/errorlog.py +137 -137
- package/app/core/eval_matrix.py +91 -91
- package/app/core/evaluation.py +174 -174
- package/app/core/failure_notify.py +290 -290
- package/app/core/flow_graph.py +33 -33
- package/app/core/goal_service.py +167 -167
- package/app/core/health.py +389 -389
- package/app/core/history.py +38 -38
- package/app/core/hooks.py +162 -162
- package/app/core/knowledge_pipeline.py +86 -86
- package/app/core/manager.py +2386 -2385
- package/app/core/mocks.py +64 -64
- package/app/core/notify.py +201 -201
- package/app/core/novel_quality.py +285 -181
- package/app/core/openapi.py +246 -217
- package/app/core/operations.py +228 -228
- package/app/core/paihang.py +145 -145
- package/app/core/pipeline.py +81 -11
- package/app/core/planner.py +7 -0
- package/app/core/portguard.py +111 -111
- package/app/core/presence.py +77 -77
- package/app/core/preview.py +293 -293
- package/app/core/project_memory.py +252 -206
- package/app/core/prompt_guard.py +78 -78
- package/app/core/publish/__init__.py +7 -7
- package/app/core/publish/auto.py +659 -659
- package/app/core/publish/chaprows.py +138 -138
- package/app/core/publish/flows-fanqie-calibrated.json +442 -442
- package/app/core/publish/manager.py +1185 -1185
- package/app/core/publish/qimao.py +193 -193
- package/app/core/publish/volumes.py +108 -108
- package/app/core/publish/ws.py +139 -139
- package/app/core/quality_gate.py +201 -201
- package/app/core/redact.py +38 -38
- package/app/core/registry.py +35 -0
- package/app/core/repeat_guard.py +129 -129
- package/app/core/retrieval.py +137 -137
- package/app/core/review_requests.py +119 -0
- package/app/core/runner.py +5 -1
- package/app/core/sandbox_runtime.py +95 -95
- 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.py +215 -215
- package/app/core/settings_schema.py +282 -282
- package/app/core/share_page.py +114 -114
- package/app/core/skill_scan.py +139 -139
- 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/step_runner.py +132 -132
- package/app/core/story_tracking.py +275 -275
- 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/tool_outputs.py +107 -107
- package/app/core/tracing.py +207 -207
- package/app/core/upstream.py +41 -41
- package/app/core/usage.py +1038 -1038
- package/app/core/volumes.py +389 -389
- package/app/core/webhooks.py +89 -89
- package/app/core/wxdigest.py +865 -865
- package/app/core/zentao.py +2692 -2692
- package/app/main.py +43 -0
- package/app/mcp_server.py +244 -244
- package/app/pick_dialog.py +110 -110
- package/app/ui/app.js +21 -2
- package/app/ui/artdiff.js +74 -74
- package/app/ui/hive3d.js +54 -31
- package/app/ui/i18n.js +32 -1
- package/app/ui/icons/bee.svg +79 -79
- package/app/ui/index.html +1 -0
- package/app/ui/manifest.json +16 -16
- package/app/ui/qrcode.js +2297 -2297
- package/bin/tutti.js +147 -147
- package/package.json +1 -1
- 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/output/_createbook_body.json +0 -1
- package/app/output/_probe_fq_click.py +0 -50
- package/app/output/_probe_fq_form.py +0 -42
- package/app/output/_probe_fq_modal.py +0 -55
- package/app/output/_probe_fq_points.py +0 -71
- package/app/output/_probe_fq_submit.py +0 -34
- package/app/output/_probe_fq_watch.py +0 -62
- package/app/output/workbench-clean-preview.jpg +0 -0
- package/app/output/workbench-reference-render.png +0 -0
- package/app/output/workbench-shell.png +0 -0
package/app/core/runner.py
CHANGED
|
@@ -1775,7 +1775,11 @@ def run_agent(agent, prompt, workdir=None, readonly=True,
|
|
|
1775
1775
|
bash = find_git_bash()
|
|
1776
1776
|
if bash:
|
|
1777
1777
|
base_env.setdefault("CLAUDE_CODE_GIT_BASH_PATH", bash)
|
|
1778
|
-
|
|
1778
|
+
# 32000=claude CLI 官方默认(自定义网关模型常见上限):旧值 16000 在
|
|
1779
|
+
# 全局评审读 40 万字书稿时被输出顶爆——CLI 按 16000/轮反复续烧 23.5
|
|
1780
|
+
# 分钟、$3 后报 "response exceeded the 16000 output token maximum"
|
|
1781
|
+
# (2026-10-11 实案×3);setdefault 保留:用户显式配置不覆盖
|
|
1782
|
+
base_env.setdefault("CLAUDE_CODE_MAX_OUTPUT_TOKENS", "32000")
|
|
1779
1783
|
sid = (resume or "").strip() if agent.get("mode") == "real" else ""
|
|
1780
1784
|
if sid and kind == "generic" and not agent.get("resume_argv_template"):
|
|
1781
1785
|
return {"ok": False, "text": "", "json": None, "cost_usd": 0.0, "tokens": 0,
|
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
"""Optional process sandbox launchers.
|
|
2
|
-
|
|
3
|
-
The default CodeBee install has no container dependency. Docker is an explicit
|
|
4
|
-
opt-in backend selected by a task policy and a configured image; this module
|
|
5
|
-
only builds argv and never silently falls back to a weaker backend.
|
|
6
|
-
"""
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import os
|
|
10
|
-
import re
|
|
11
|
-
import shutil
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class SandboxUnavailable(RuntimeError):
|
|
16
|
-
pass
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def requested_backend(sandbox):
|
|
20
|
-
value = str((sandbox or {}).get("backend") or "native").strip().lower()
|
|
21
|
-
return value or "native"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def docker_argv(command, *, sandbox, workdir, image=None, extra_args=(),
|
|
25
|
-
container_workdir=None,
|
|
26
|
-
container_command=("/bin/sh", "-lc")):
|
|
27
|
-
"""Build a restricted ``docker run`` argv for a command or stdio server."""
|
|
28
|
-
if requested_backend(sandbox) != "docker":
|
|
29
|
-
raise SandboxUnavailable("Docker 后端未被任务策略启用")
|
|
30
|
-
docker = shutil.which("docker")
|
|
31
|
-
if not docker:
|
|
32
|
-
raise SandboxUnavailable("当前系统没有可用的 Docker CLI")
|
|
33
|
-
root = Path(workdir or ".").expanduser().resolve(strict=True)
|
|
34
|
-
image = str(image or (sandbox or {}).get("docker_image") or "").strip()
|
|
35
|
-
if not image or len(image) > 240 or not re.match(r"^[A-Za-z0-9][A-Za-z0-9._/:@-]*$", image):
|
|
36
|
-
raise SandboxUnavailable("Docker 后端必须配置可信镜像")
|
|
37
|
-
roots = []
|
|
38
|
-
for value in (sandbox or {}).get("allowed_roots") or [str(root)]:
|
|
39
|
-
candidate = Path(value).expanduser().resolve(strict=True)
|
|
40
|
-
# Docker currently mounts exactly one root. Require the task workspace
|
|
41
|
-
# itself; narrower roots need a separately resolved container cwd and
|
|
42
|
-
# must never accidentally broaden into an ancestor mount.
|
|
43
|
-
if candidate != root:
|
|
44
|
-
raise SandboxUnavailable("Docker 目前只支持挂载任务工作目录")
|
|
45
|
-
if candidate not in roots:
|
|
46
|
-
roots.append(candidate)
|
|
47
|
-
if not roots:
|
|
48
|
-
raise SandboxUnavailable("Docker 后端没有允许目录")
|
|
49
|
-
selected_root = next((candidate for candidate in roots
|
|
50
|
-
if candidate == root or candidate in root.parents
|
|
51
|
-
or root in candidate.parents), None)
|
|
52
|
-
if selected_root is None:
|
|
53
|
-
raise SandboxUnavailable("当前工作目录不在 Docker 允许目录内")
|
|
54
|
-
if len(roots) != 1:
|
|
55
|
-
raise SandboxUnavailable("Docker 暂只支持一个明确的允许目录")
|
|
56
|
-
argv = [docker, "run", "--rm", "--init", "--read-only",
|
|
57
|
-
"--security-opt", "no-new-privileges", "--cap-drop=ALL",
|
|
58
|
-
"--ipc=none", "--pids-limit", "256", "--memory", "2g", "--cpus", "2",
|
|
59
|
-
"--tmpfs", "/tmp:rw,noexec,nosuid,size=64m"]
|
|
60
|
-
if hasattr(os, "getuid") and hasattr(os, "getgid"):
|
|
61
|
-
argv += ["--user", "%d:%d" % (os.getuid(), os.getgid())]
|
|
62
|
-
else:
|
|
63
|
-
argv += ["--user", "65534:65534"]
|
|
64
|
-
argv += ["--network", "none" if not bool((sandbox or {}).get("network", True)) else "bridge"]
|
|
65
|
-
for name in (sandbox or {}).get("env_allowlist") or []:
|
|
66
|
-
name = str(name)
|
|
67
|
-
if name and name in os.environ:
|
|
68
|
-
# Value is supplied through the filtered Docker client environment;
|
|
69
|
-
# never place credentials in argv, where process/log inspection sees them.
|
|
70
|
-
argv += ["--env", name]
|
|
71
|
-
for candidate in roots:
|
|
72
|
-
if "," in str(candidate):
|
|
73
|
-
raise SandboxUnavailable("Docker 允许目录包含不支持的逗号")
|
|
74
|
-
argv += ["--mount", "type=bind,src=%s,dst=/workspace" % str(candidate)]
|
|
75
|
-
if container_workdir is None:
|
|
76
|
-
rel_workdir = root.relative_to(selected_root).as_posix()
|
|
77
|
-
container_workdir = "/workspace" + ("/" + rel_workdir if rel_workdir != "." else "")
|
|
78
|
-
if not str(container_workdir).startswith("/") or ".." in Path(container_workdir).parts:
|
|
79
|
-
raise SandboxUnavailable("Docker 容器工作目录无效")
|
|
80
|
-
argv += ["--workdir", str(container_workdir), *list(extra_args), image]
|
|
81
|
-
if isinstance(command, (list, tuple)):
|
|
82
|
-
argv += [str(x) for x in command]
|
|
83
|
-
else:
|
|
84
|
-
argv += list(container_command) + [str(command)]
|
|
85
|
-
return argv
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def docker_env(sandbox):
|
|
89
|
-
"""Docker receives only explicitly allowed host environment values."""
|
|
90
|
-
out = {"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
91
|
-
"HOME": "/tmp", "TMPDIR": "/tmp"}
|
|
92
|
-
for name in (sandbox or {}).get("env_allowlist") or []:
|
|
93
|
-
if name in os.environ:
|
|
94
|
-
out[str(name)] = os.environ[str(name)]
|
|
95
|
-
return out
|
|
1
|
+
"""Optional process sandbox launchers.
|
|
2
|
+
|
|
3
|
+
The default CodeBee install has no container dependency. Docker is an explicit
|
|
4
|
+
opt-in backend selected by a task policy and a configured image; this module
|
|
5
|
+
only builds argv and never silently falls back to a weaker backend.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import re
|
|
11
|
+
import shutil
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SandboxUnavailable(RuntimeError):
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def requested_backend(sandbox):
|
|
20
|
+
value = str((sandbox or {}).get("backend") or "native").strip().lower()
|
|
21
|
+
return value or "native"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def docker_argv(command, *, sandbox, workdir, image=None, extra_args=(),
|
|
25
|
+
container_workdir=None,
|
|
26
|
+
container_command=("/bin/sh", "-lc")):
|
|
27
|
+
"""Build a restricted ``docker run`` argv for a command or stdio server."""
|
|
28
|
+
if requested_backend(sandbox) != "docker":
|
|
29
|
+
raise SandboxUnavailable("Docker 后端未被任务策略启用")
|
|
30
|
+
docker = shutil.which("docker")
|
|
31
|
+
if not docker:
|
|
32
|
+
raise SandboxUnavailable("当前系统没有可用的 Docker CLI")
|
|
33
|
+
root = Path(workdir or ".").expanduser().resolve(strict=True)
|
|
34
|
+
image = str(image or (sandbox or {}).get("docker_image") or "").strip()
|
|
35
|
+
if not image or len(image) > 240 or not re.match(r"^[A-Za-z0-9][A-Za-z0-9._/:@-]*$", image):
|
|
36
|
+
raise SandboxUnavailable("Docker 后端必须配置可信镜像")
|
|
37
|
+
roots = []
|
|
38
|
+
for value in (sandbox or {}).get("allowed_roots") or [str(root)]:
|
|
39
|
+
candidate = Path(value).expanduser().resolve(strict=True)
|
|
40
|
+
# Docker currently mounts exactly one root. Require the task workspace
|
|
41
|
+
# itself; narrower roots need a separately resolved container cwd and
|
|
42
|
+
# must never accidentally broaden into an ancestor mount.
|
|
43
|
+
if candidate != root:
|
|
44
|
+
raise SandboxUnavailable("Docker 目前只支持挂载任务工作目录")
|
|
45
|
+
if candidate not in roots:
|
|
46
|
+
roots.append(candidate)
|
|
47
|
+
if not roots:
|
|
48
|
+
raise SandboxUnavailable("Docker 后端没有允许目录")
|
|
49
|
+
selected_root = next((candidate for candidate in roots
|
|
50
|
+
if candidate == root or candidate in root.parents
|
|
51
|
+
or root in candidate.parents), None)
|
|
52
|
+
if selected_root is None:
|
|
53
|
+
raise SandboxUnavailable("当前工作目录不在 Docker 允许目录内")
|
|
54
|
+
if len(roots) != 1:
|
|
55
|
+
raise SandboxUnavailable("Docker 暂只支持一个明确的允许目录")
|
|
56
|
+
argv = [docker, "run", "--rm", "--init", "--read-only",
|
|
57
|
+
"--security-opt", "no-new-privileges", "--cap-drop=ALL",
|
|
58
|
+
"--ipc=none", "--pids-limit", "256", "--memory", "2g", "--cpus", "2",
|
|
59
|
+
"--tmpfs", "/tmp:rw,noexec,nosuid,size=64m"]
|
|
60
|
+
if hasattr(os, "getuid") and hasattr(os, "getgid"):
|
|
61
|
+
argv += ["--user", "%d:%d" % (os.getuid(), os.getgid())]
|
|
62
|
+
else:
|
|
63
|
+
argv += ["--user", "65534:65534"]
|
|
64
|
+
argv += ["--network", "none" if not bool((sandbox or {}).get("network", True)) else "bridge"]
|
|
65
|
+
for name in (sandbox or {}).get("env_allowlist") or []:
|
|
66
|
+
name = str(name)
|
|
67
|
+
if name and name in os.environ:
|
|
68
|
+
# Value is supplied through the filtered Docker client environment;
|
|
69
|
+
# never place credentials in argv, where process/log inspection sees them.
|
|
70
|
+
argv += ["--env", name]
|
|
71
|
+
for candidate in roots:
|
|
72
|
+
if "," in str(candidate):
|
|
73
|
+
raise SandboxUnavailable("Docker 允许目录包含不支持的逗号")
|
|
74
|
+
argv += ["--mount", "type=bind,src=%s,dst=/workspace" % str(candidate)]
|
|
75
|
+
if container_workdir is None:
|
|
76
|
+
rel_workdir = root.relative_to(selected_root).as_posix()
|
|
77
|
+
container_workdir = "/workspace" + ("/" + rel_workdir if rel_workdir != "." else "")
|
|
78
|
+
if not str(container_workdir).startswith("/") or ".." in Path(container_workdir).parts:
|
|
79
|
+
raise SandboxUnavailable("Docker 容器工作目录无效")
|
|
80
|
+
argv += ["--workdir", str(container_workdir), *list(extra_args), image]
|
|
81
|
+
if isinstance(command, (list, tuple)):
|
|
82
|
+
argv += [str(x) for x in command]
|
|
83
|
+
else:
|
|
84
|
+
argv += list(container_command) + [str(command)]
|
|
85
|
+
return argv
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def docker_env(sandbox):
|
|
89
|
+
"""Docker receives only explicitly allowed host environment values."""
|
|
90
|
+
out = {"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
91
|
+
"HOME": "/tmp", "TMPDIR": "/tmp"}
|
|
92
|
+
for name in (sandbox or {}).get("env_allowlist") or []:
|
|
93
|
+
if name in os.environ:
|
|
94
|
+
out[str(name)] = os.environ[str(name)]
|
|
95
|
+
return out
|