codebee 0.1.103 → 0.1.104

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 (119) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE +21 -21
  3. package/README.md +2 -3
  4. package/app/core/acceptance.py +100 -100
  5. package/app/core/acp_client.py +457 -457
  6. package/app/core/aiflavor.py +197 -197
  7. package/app/core/analytics.py +38 -38
  8. package/app/core/artifacts.py +148 -148
  9. package/app/core/assets.py +110 -110
  10. package/app/core/attachments.py +623 -623
  11. package/app/core/audit.py +30 -30
  12. package/app/core/backend_profiles.py +188 -188
  13. package/app/core/backup.py +470 -470
  14. package/app/core/beekeeper.py +183 -183
  15. package/app/core/benchstore.py +102 -102
  16. package/app/core/bookmeta.py +1036 -1036
  17. package/app/core/bookmeta_catalog.py +180 -180
  18. package/app/core/branching.py +137 -137
  19. package/app/core/capability.py +144 -144
  20. package/app/core/chaptersafe.py +32 -32
  21. package/app/core/cleanup.py +303 -303
  22. package/app/core/command_auth.py +302 -302
  23. package/app/core/compaction.py +201 -201
  24. package/app/core/contracts.py +255 -255
  25. package/app/core/covergen.py +356 -356
  26. package/app/core/defectretro.py +43 -43
  27. package/app/core/diagnostics.py +114 -114
  28. package/app/core/dispatch_log.py +128 -128
  29. package/app/core/env_scrub.py +85 -85
  30. package/app/core/errorlog.py +137 -137
  31. package/app/core/eval_matrix.py +91 -91
  32. package/app/core/evaluation.py +174 -174
  33. package/app/core/failure_notify.py +290 -290
  34. package/app/core/flow_graph.py +33 -33
  35. package/app/core/goal_service.py +167 -167
  36. package/app/core/health.py +389 -389
  37. package/app/core/history.py +38 -38
  38. package/app/core/hooks.py +162 -162
  39. package/app/core/knowledge_pipeline.py +86 -86
  40. package/app/core/manager.py +2385 -2385
  41. package/app/core/mocks.py +64 -64
  42. package/app/core/notify.py +201 -201
  43. package/app/core/novel_quality.py +285 -181
  44. package/app/core/openapi.py +217 -217
  45. package/app/core/operations.py +228 -228
  46. package/app/core/paihang.py +145 -145
  47. package/app/core/pipeline.py +55 -3
  48. package/app/core/planner.py +7 -0
  49. package/app/core/portguard.py +111 -111
  50. package/app/core/presence.py +77 -77
  51. package/app/core/preview.py +293 -293
  52. package/app/core/project_memory.py +206 -206
  53. package/app/core/prompt_guard.py +78 -78
  54. package/app/core/publish/__init__.py +7 -7
  55. package/app/core/publish/auto.py +659 -659
  56. package/app/core/publish/chaprows.py +138 -138
  57. package/app/core/publish/flows-fanqie-calibrated.json +442 -442
  58. package/app/core/publish/manager.py +1185 -1185
  59. package/app/core/publish/qimao.py +193 -193
  60. package/app/core/publish/volumes.py +108 -108
  61. package/app/core/publish/ws.py +139 -139
  62. package/app/core/quality_gate.py +201 -201
  63. package/app/core/redact.py +38 -38
  64. package/app/core/repeat_guard.py +129 -129
  65. package/app/core/retrieval.py +137 -137
  66. package/app/core/sandbox_runtime.py +95 -95
  67. package/app/core/selfupdate.py +384 -384
  68. package/app/core/session_log.py +161 -161
  69. package/app/core/sessions.py +312 -312
  70. package/app/core/settings.py +215 -215
  71. package/app/core/settings_schema.py +282 -282
  72. package/app/core/share_page.py +114 -114
  73. package/app/core/skill_scan.py +139 -139
  74. package/app/core/skillpacks/market/character-bible.md +66 -66
  75. package/app/core/skillpacks/market/code-risk-checklist.md +58 -58
  76. package/app/core/skillpacks/market/git-workflow.md +57 -57
  77. package/app/core/skillpacks/market/release-notes.md +72 -72
  78. package/app/core/skillpacks/market/weekly-report.md +71 -71
  79. package/app/core/skillpacks/market/worldview-consistency.md +70 -70
  80. package/app/core/step_runner.py +132 -132
  81. package/app/core/story_tracking.py +275 -275
  82. package/app/core/task_compile.py +199 -199
  83. package/app/core/telemetry.py +292 -292
  84. package/app/core/tlsctx.py +64 -64
  85. package/app/core/token_meter.py +147 -147
  86. package/app/core/tool_outputs.py +107 -107
  87. package/app/core/tracing.py +207 -207
  88. package/app/core/upstream.py +41 -41
  89. package/app/core/usage.py +1038 -1038
  90. package/app/core/volumes.py +389 -389
  91. package/app/core/webhooks.py +89 -89
  92. package/app/core/wxdigest.py +865 -865
  93. package/app/core/zentao.py +2692 -2692
  94. package/app/mcp_server.py +244 -244
  95. package/app/pick_dialog.py +110 -110
  96. package/app/ui/artdiff.js +74 -74
  97. package/app/ui/icons/bee.svg +79 -79
  98. package/app/ui/manifest.json +16 -16
  99. package/app/ui/qrcode.js +2297 -2297
  100. package/bin/tutti.js +147 -147
  101. package/package.json +1 -1
  102. package/tools/wx_reader.py +261 -261
  103. package/app/.playwright-cli/console-2026-09-23T08-26-03-635Z.log +0 -88
  104. package/app/.playwright-cli/page-2026-09-23T08-26-03-845Z.yml +0 -126
  105. package/app/.playwright-cli/page-2026-09-23T08-29-44-203Z.png +0 -0
  106. package/app/.playwright-cli/page-2026-09-23T08-35-42-046Z.yml +0 -210
  107. package/app/.playwright-cli/page-2026-09-23T08-36-52-858Z.png +0 -0
  108. package/app/.playwright-cli/page-2026-09-23T08-37-33-938Z.png +0 -0
  109. package/app/.playwright-cli/run-detail-after.png +0 -0
  110. package/app/output/_createbook_body.json +0 -1
  111. package/app/output/_probe_fq_click.py +0 -50
  112. package/app/output/_probe_fq_form.py +0 -42
  113. package/app/output/_probe_fq_modal.py +0 -55
  114. package/app/output/_probe_fq_points.py +0 -71
  115. package/app/output/_probe_fq_submit.py +0 -34
  116. package/app/output/_probe_fq_watch.py +0 -62
  117. package/app/output/workbench-clean-preview.jpg +0 -0
  118. package/app/output/workbench-reference-render.png +0 -0
  119. package/app/output/workbench-shell.png +0 -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