codebee 0.1.102 → 0.1.103

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 (121) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -21
  3. package/README.md +4 -8
  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/core/acceptance.py +100 -100
  12. package/app/core/acp_client.py +457 -457
  13. package/app/core/aiflavor.py +197 -197
  14. package/app/core/analytics.py +38 -38
  15. package/app/core/artifacts.py +148 -148
  16. package/app/core/assets.py +110 -110
  17. package/app/core/attachments.py +623 -623
  18. package/app/core/audit.py +30 -30
  19. package/app/core/backend_profiles.py +188 -188
  20. package/app/core/backup.py +470 -470
  21. package/app/core/beekeeper.py +183 -183
  22. package/app/core/benchstore.py +102 -102
  23. package/app/core/bookmeta.py +1036 -1036
  24. package/app/core/bookmeta_catalog.py +180 -180
  25. package/app/core/branching.py +137 -137
  26. package/app/core/capability.py +144 -144
  27. package/app/core/chaptersafe.py +32 -32
  28. package/app/core/cleanup.py +303 -303
  29. package/app/core/command_auth.py +302 -302
  30. package/app/core/compaction.py +201 -201
  31. package/app/core/contracts.py +255 -255
  32. package/app/core/covergen.py +356 -356
  33. package/app/core/defectretro.py +43 -43
  34. package/app/core/diagnostics.py +114 -114
  35. package/app/core/dispatch.py +1 -1
  36. package/app/core/dispatch_log.py +128 -128
  37. package/app/core/env_scrub.py +85 -85
  38. package/app/core/errorlog.py +137 -137
  39. package/app/core/eval_matrix.py +91 -91
  40. package/app/core/evaluation.py +174 -174
  41. package/app/core/failure_notify.py +290 -290
  42. package/app/core/flow_graph.py +33 -33
  43. package/app/core/goal_service.py +167 -167
  44. package/app/core/health.py +389 -389
  45. package/app/core/history.py +38 -38
  46. package/app/core/hooks.py +162 -162
  47. package/app/core/knowledge_pipeline.py +86 -86
  48. package/app/core/manager.py +2385 -2385
  49. package/app/core/mocks.py +64 -64
  50. package/app/core/notify.py +201 -201
  51. package/app/core/novel_quality.py +181 -181
  52. package/app/core/openapi.py +217 -217
  53. package/app/core/operations.py +228 -228
  54. package/app/core/paihang.py +145 -145
  55. package/app/core/pipeline.py +2 -2
  56. package/app/core/portguard.py +111 -111
  57. package/app/core/presence.py +77 -77
  58. package/app/core/preview.py +293 -293
  59. package/app/core/project_memory.py +206 -206
  60. package/app/core/prompt_guard.py +78 -78
  61. package/app/core/publish/__init__.py +7 -7
  62. package/app/core/publish/auto.py +659 -659
  63. package/app/core/publish/chaprows.py +138 -138
  64. package/app/core/publish/flows-fanqie-calibrated.json +442 -442
  65. package/app/core/publish/manager.py +1185 -1185
  66. package/app/core/publish/qimao.py +193 -193
  67. package/app/core/publish/volumes.py +108 -108
  68. package/app/core/publish/ws.py +139 -139
  69. package/app/core/quality_gate.py +201 -201
  70. package/app/core/redact.py +38 -38
  71. package/app/core/repeat_guard.py +129 -129
  72. package/app/core/retrieval.py +137 -137
  73. package/app/core/sandbox_runtime.py +95 -95
  74. package/app/core/selfupdate.py +384 -384
  75. package/app/core/session_log.py +161 -161
  76. package/app/core/sessions.py +312 -312
  77. package/app/core/settings.py +215 -215
  78. package/app/core/settings_schema.py +282 -282
  79. package/app/core/share_page.py +114 -114
  80. package/app/core/skill_scan.py +139 -139
  81. package/app/core/skillpacks/market/character-bible.md +66 -66
  82. package/app/core/skillpacks/market/code-risk-checklist.md +58 -58
  83. package/app/core/skillpacks/market/git-workflow.md +57 -57
  84. package/app/core/skillpacks/market/release-notes.md +72 -72
  85. package/app/core/skillpacks/market/weekly-report.md +71 -71
  86. package/app/core/skillpacks/market/worldview-consistency.md +70 -70
  87. package/app/core/step_runner.py +132 -132
  88. package/app/core/story_tracking.py +275 -275
  89. package/app/core/task_compile.py +199 -199
  90. package/app/core/telemetry.py +292 -292
  91. package/app/core/tlsctx.py +64 -64
  92. package/app/core/token_meter.py +147 -147
  93. package/app/core/tool_outputs.py +107 -107
  94. package/app/core/tracing.py +207 -207
  95. package/app/core/upstream.py +41 -41
  96. package/app/core/usage.py +1038 -1038
  97. package/app/core/volumes.py +389 -389
  98. package/app/core/webhooks.py +89 -89
  99. package/app/core/wxdigest.py +865 -865
  100. package/app/core/zentao.py +2692 -2692
  101. package/app/mcp_server.py +244 -244
  102. package/app/output/_createbook_body.json +1 -0
  103. package/app/output/_probe_fq_click.py +50 -0
  104. package/app/output/_probe_fq_form.py +42 -0
  105. package/app/output/_probe_fq_modal.py +55 -0
  106. package/app/output/_probe_fq_points.py +71 -0
  107. package/app/output/_probe_fq_submit.py +34 -0
  108. package/app/output/_probe_fq_watch.py +62 -0
  109. package/app/output/workbench-clean-preview.jpg +0 -0
  110. package/app/output/workbench-reference-render.png +0 -0
  111. package/app/output/workbench-shell.png +0 -0
  112. package/app/pick_dialog.py +110 -110
  113. package/app/ui/app.js +2 -3
  114. package/app/ui/artdiff.js +74 -74
  115. package/app/ui/i18n.js +0 -1
  116. package/app/ui/icons/bee.svg +79 -79
  117. package/app/ui/manifest.json +16 -16
  118. package/app/ui/qrcode.js +2297 -2297
  119. package/bin/tutti.js +147 -147
  120. package/package.json +1 -1
  121. package/tools/wx_reader.py +261 -261
@@ -1,217 +1,217 @@
1
- """OpenAPI 3 contract for the stable headless CodeBee integrations."""
2
-
3
-
4
- def document():
5
- schemas = {
6
- "Error": {"type": "object", "required": ["error"], "properties": {
7
- "error": {"type": "string"}, "control": {"$ref": "#/components/schemas/Control"}}},
8
- "Control": {"type": "object", "properties": {
9
- "mode": {"type": "string", "enum": ["free", "held"]},
10
- "mine": {"type": "boolean"}, "holder": {"type": "string"},
11
- "expires_in": {"type": "integer", "minimum": 0}}},
12
- "TaskCreate": {"type": "object", "required": ["goal"], "properties": {
13
- "type": {"type": "string"}, "title": {"type": "string"},
14
- "goal": {"type": "string", "maxLength": 4000}, "workdir": {"type": "string"},
15
- "sandbox": {"type": "object", "properties": {
16
- "backend": {"type": "string", "enum": ["native", "docker"]},
17
- "docker_image": {"type": "string", "maxLength": 240},
18
- "allowed_roots": {"type": "array", "maxItems": 16,
19
- "items": {"type": "string", "maxLength": 1024}},
20
- "env_allowlist": {"type": "array", "maxItems": 64,
21
- "items": {"type": "string", "maxLength": 128}},
22
- "network": {"type": "boolean"}, "timeout_s": {"type": "integer"}}},
23
- "acceptance_criteria": {"type": "array", "maxItems": 40,
24
- "items": {"type": "string", "maxLength": 500}},
25
- "approval_required": {"type": "boolean"}}},
26
- "TaskResult": {"type": "object", "required": ["task_id", "run_id"], "properties": {
27
- "task_id": {"type": "string"}, "run_id": {"type": "string"}}},
28
- "Evidence": {"type": "object", "required": ["status"], "properties": {
29
- "id": {"type": "string"}, "criterion": {"type": "string", "maxLength": 500},
30
- "status": {"type": "string", "enum": ["passed", "failed", "unknown", "not_evaluated"]},
31
- "summary": {"type": "string", "maxLength": 2000},
32
- "source": {"type": "string", "maxLength": 80}, "created_at": {"type": "string"}}},
33
- "Contract": {"type": "object", "properties": {
34
- "task_id": {"type": "string"},
35
- "acceptance_criteria": {"type": "array", "items": {"type": "string"}},
36
- "evidence": {"type": "array", "items": {"$ref": "#/components/schemas/Evidence"}},
37
- "approval_required": {"type": "boolean"}, "approval": {"type": "object"},
38
- "blocked_reason": {"type": "string"}, "completion_receipt": {"type": "object"}}},
39
- "StoryChapter": {"type": "object", "properties": {
40
- "op": {"type": "string"},
41
- "chapter": {"type": "integer", "minimum": 1, "maximum": 5000},
42
- "outline": {"type": "string", "maxLength": 12000}, "prose": {"type": "string"},
43
- "facts": {"type": "array", "items": {"type": "string"}},
44
- "characters": {"type": "array", "items": {"type": "string"}},
45
- "timeline": {"type": "array", "items": {"type": "string"}},
46
- "foreshadowing": {"type": "array", "items": {"type": "object"}},
47
- "next_promises": {"type": "array", "items": {"type": "string"}},
48
- "author_truth": {"type": "array", "items": {"type": "string"}},
49
- "reader_known": {"type": "array", "items": {"type": "string"}}},
50
- "oneOf": [
51
- {"required": ["op"], "properties": {"op": {"const": "init"}}},
52
- {"required": ["chapter", "outline", "prose"]},
53
- ]},
54
- "StoryTrackingResult": {"type": "object", "properties": {
55
- "state": {"type": "object"}, "check": {"type": "object"}}},
56
- "Presence": {"type": "object", "required": ["agent_id"], "properties": {
57
- "agent_id": {"type": "string", "maxLength": 100}, "label": {"type": "string", "maxLength": 120},
58
- "capabilities": {"type": "array", "maxItems": 30,
59
- "items": {"type": "string", "maxLength": 80}},
60
- "task_id": {"type": "string", "maxLength": 100}, "status": {"type": "string", "maxLength": 30},
61
- "metadata": {"type": "object"}}},
62
- "BackendProfile": {"type": "object", "required": ["label", "command"], "properties": {
63
- "id": {"type": "string"}, "agent_id": {"type": "string"},
64
- "label": {"type": "string", "maxLength": 80}, "command": {"type": "string", "maxLength": 500},
65
- "args": {"type": "array", "maxItems": 80, "items": {"type": "string"}},
66
- "env": {"type": "object", "additionalProperties": {"type": "string"}},
67
- "workspace_path": {"type": "string"}, "enabled": {"type": "boolean"}}},
68
- "CommandAuth": {"type": "object", "properties": {
69
- "mode": {"type": "string", "enum": ["legacy", "restricted"]},
70
- "pending": {"type": "array"}, "rules": {"type": "array"}, "audit": {"type": "array"}}},
71
- }
72
-
73
- def body(schema):
74
- return {"required": True, "content": {"application/json": {"schema": schema}}}
75
-
76
- def response(description, schema=None):
77
- out = {"description": description}
78
- if schema is not None:
79
- out["content"] = {"application/json": {"schema": schema}}
80
- return out
81
-
82
- ref = lambda name: {"$ref": "#/components/schemas/" + name}
83
- security = [{"codebeeToken": []}, {"codebeeQueryToken": []}]
84
- errors = {code: response(desc, ref("Error")) for code, desc in (
85
- ("400", "请求无效"), ("401", "缺少或错误的访问令牌"),
86
- ("404", "资源不存在"), ("409", "状态冲突或审批未完成"),
87
- ("423", "其他设备持有控制权"))}
88
- ok = response("成功", {"type": "object", "properties": {"ok": {"type": "boolean"}}})
89
-
90
- paths = {
91
- "/api/tasks": {"post": {"summary": "创建并启动任务", "security": security,
92
- "requestBody": body(ref("TaskCreate")),
93
- "responses": {"200": response("已排队", ref("TaskResult")),
94
- "503": response("运行记录或入队失败", ref("Error")), **errors}}},
95
- "/api/a2a/tasks": {"post": {"summary": "A2A-lite 创建任务", "security": security,
96
- "requestBody": body(ref("TaskCreate")),
97
- "responses": {"200": response("已排队", ref("TaskResult")), "400": errors["400"],
98
- "401": errors["401"], "423": errors["423"]}}},
99
- "/api/a2a/tasks/{task_id}": {"get": {"summary": "A2A-lite 读取任务状态", "security": security,
100
- "responses": {"200": response("任务、运行和契约", {"type": "object"}),
101
- "401": errors["401"], "404": errors["404"]}}},
102
- "/api/tasks/{task_id}/detail": {"get": {"summary": "读取任务详情和契约", "security": security,
103
- "responses": {"200": response("任务详情", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
104
- "/api/tasks/{task_id}/contract": {
105
- "get": {"summary": "读取任务契约", "security": security,
106
- "responses": {"200": response("契约", ref("Contract")), "401": errors["401"], "404": errors["404"]}},
107
- "post": {"summary": "更新契约、追加证据或审批任务", "security": security,
108
- "requestBody": body({"type": "object", "properties": {
109
- "op": {"type": "string", "enum": ["update", "create", "evidence", "approve", "reject", "blocked"]},
110
- "acceptance_criteria": {"type": "array", "items": {"type": "string"}},
111
- "approval_required": {"type": "boolean"}, "evidence": ref("Evidence"),
112
- "note": {"type": "string", "maxLength": 1000}, "reason": {"type": "string", "maxLength": 1000}}}),
113
- "responses": {"200": response("契约已更新", {"type": "object", "properties": {"contract": ref("Contract")}}), **errors}}},
114
- "/api/tasks/{task_id}/story-tracking": {
115
- "get": {"summary": "读取小说追踪状态", "security": security,
116
- "responses": {"200": response("追踪状态", ref("StoryTrackingResult")), "401": errors["401"],
117
- "404": errors["404"], "409": errors["409"]}},
118
- "post": {"summary": "提交章节结构化状态", "security": security, "requestBody": body(ref("StoryChapter")),
119
- "responses": {"200": response("追踪状态已更新", ref("StoryTrackingResult")), **errors}}},
120
- "/api/agents/presence": {
121
- "get": {"summary": "Agent 在线状态", "security": security,
122
- "responses": {"200": response("在线 Agent 列表", {"type": "object"}), "401": errors["401"]}},
123
- "post": {"summary": "Agent 心跳", "security": security, "requestBody": body(ref("Presence")),
124
- "responses": {"200": response("心跳已记录", {"type": "object"}), "400": errors["400"],
125
- "401": errors["401"], "423": errors["423"]}}},
126
- "/api/backend-profiles": {
127
- "get": {"summary": "读取 ACP Backend Profiles(密钥脱敏)", "security": security,
128
- "responses": {"200": response("Profiles", {"type": "object"}), "401": errors["401"]}},
129
- "post": {"summary": "保存 ACP Backend Profile", "security": security,
130
- "requestBody": body(ref("BackendProfile")),
131
- "responses": {"200": response("Profile", {"type": "object"}), "400": errors["400"], "401": errors["401"]}}},
132
- "/api/backend-profiles/{profile_id}/delete": {
133
- "post": {"summary": "删除 ACP Backend Profile", "security": security,
134
- "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"]}}},
135
- "/api/command-auth": {
136
- "get": {"summary": "读取命令授权策略与待处理请求", "security": security,
137
- "responses": {"200": response("Authorization state", ref("CommandAuth")), "401": errors["401"]}},
138
- "post": {"summary": "切换命令授权策略", "security": security,
139
- "requestBody": body({"type": "object", "properties": {"mode": {"type": "string", "enum": ["legacy", "restricted"]}}}),
140
- "responses": {"200": response("Authorization state", ref("CommandAuth")), "400": errors["400"], "401": errors["401"]}}},
141
- "/api/command-auth/requests/{request_id}": {
142
- "post": {"summary": "批准或拒绝等待中的命令", "security": security,
143
- "requestBody": body({"type": "object", "required": ["approve"], "properties": {
144
- "approve": {"type": "boolean"}, "scope": {"type": "string"}, "match": {"type": "string"}, "prefix": {"type": "string"}}}),
145
- "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"]}}},
146
- "/api/command-auth/rules/{rule_id}/revoke": {
147
- "post": {"summary": "撤销命令授权规则", "security": security,
148
- "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"]}}},
149
- "/api/retrieval/search": {"get": {"summary": "本地检索", "security": security,
150
- "parameters": [{"name": "q", "in": "query", "required": True,
151
- "schema": {"type": "string", "maxLength": 500}},
152
- {"name": "limit", "in": "query",
153
- "schema": {"type": "integer", "minimum": 1, "maximum": 50}}],
154
- "responses": {"200": response("检索结果", {"type": "object"}), "400": errors["400"], "401": errors["401"]}}},
155
- "/api/retrieval/index": {"post": {"summary": "为配置工作区/任务目录建立本地检索索引", "security": security,
156
- "requestBody": body({"type": "object", "properties": {
157
- "source": {"type": "string"}, "text": {"type": "string"}, "metadata": {"type": "object"},
158
- "doc_id": {"type": "string"}, "root": {"type": "string"}, "task_id": {"type": "string"},
159
- "limit": {"type": "integer", "minimum": 1, "maximum": 500}}}),
160
- "responses": {"200": response("索引已更新", {"type": "object"}), "400": errors["400"],
161
- "401": errors["401"], "404": errors["404"], "423": errors["423"]}}},
162
- "/api/analytics": {"get": {"summary": "任务成本质量分析", "security": security,
163
- "responses": {"200": response("分析摘要", {"type": "object"}), "401": errors["401"]}}},
164
- "/api/runs/{run_id}": {"get": {"summary": "读取运行状态", "security": security,
165
- "responses": {"200": response("运行状态", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
166
- "/api/runs/{run_id}/trace": {"get": {"summary": "读取脱敏 trace", "security": security,
167
- "responses": {"200": response("Trace", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
168
- "/api/runs/{run_id}/otel": {"get": {"summary": "导出 OTLP JSON trace", "security": security,
169
- "responses": {"200": response("OTLP trace", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
170
- "/api/runs/{run_id}/checkpoints": {"get": {"summary": "读取 checkpoint 回放预览", "security": security,
171
- "responses": {"200": response("Checkpoint", {"type": "object"}), "401": errors["401"]}}},
172
- "/api/flows/{flow_id}/graph": {"get": {"summary": "读取流程图投影", "security": security,
173
- "responses": {"200": response("Flow graph", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
174
- "/api/hooks/run": {"post": {"summary": "Webhook 触发任务(可选 HMAC)", "security": security,
175
- "requestBody": body(ref("TaskCreate")),
176
- "responses": {"200": response("已排队", ref("TaskResult")), "401": errors["401"], "403": errors["401"], "400": errors["400"]}}},
177
- "/api/eval-matrix/normalize": {"post": {"summary": "规范化评测矩阵 manifest", "security": security,
178
- "requestBody": body({"type": "object"}), "responses": {"200": response("Manifest", {"type": "object"}), "400": errors["400"]}}},
179
- "/api/eval-matrix/evaluate": {"post": {"summary": "对比评测矩阵与 baseline", "security": security,
180
- "requestBody": body({"type": "object"}), "responses": {"200": response("Report", {"type": "object"}), "400": errors["400"]}}},
181
- "/api/knowledge/pipeline": {"get": {"summary": "读取知识管线质量报告", "security": security,
182
- "parameters": [{"name": "ingest_id", "in": "query", "schema": {"type": "string"}}],
183
- "responses": {"200": response("Quality report", {"type": "object"})}},
184
- "post": {"summary": "分块并建立知识索引", "security": security,
185
- "requestBody": body({"type": "object"}), "responses": {"200": response("Ingest report", {"type": "object"}), "400": errors["400"]}}},
186
- "/api/policy": {"get": {"summary": "读取规范化沙箱策略", "security": security,
187
- "parameters": [{"name": "workdir", "in": "query", "schema": {"type": "string"}}],
188
- "responses": {"200": response("Sandbox policy", {"type": "object"})}}},
189
- "/api/runs/{run_id}/resume_now": {"post": {"summary": "立即重试运行", "security": security,
190
- "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"], "423": errors["423"]}}},
191
- "/api/control": {
192
- "get": {"summary": "读取当前控制权", "security": security,
193
- "responses": {"200": response("控制权状态", {"type": "object"}), "401": errors["401"]}},
194
- "post": {"summary": "接管或释放控制权", "security": security,
195
- "requestBody": body({"type": "object", "required": ["action"], "properties": {
196
- "action": {"type": "string", "enum": ["acquire", "release"]},
197
- "force": {"type": "boolean"}}}),
198
- "responses": {"200": response("控制权已更新", {"type": "object"}),
199
- "400": errors["400"], "401": errors["401"], "423": errors["423"]}}},
200
- "/api/control/heartbeat": {
201
- "get": {"summary": "续期当前控制权", "security": security,
202
- "responses": {"200": response("控制权状态", {"type": "object"}), "401": errors["401"]}},
203
- "post": {"summary": "续期当前控制权", "security": security,
204
- "responses": {"200": response("控制权状态", {"type": "object"}), "401": errors["401"]}}},
205
- "/api/openapi.json": {"get": {"summary": "读取 OpenAPI 文档", "security": security,
206
- "responses": {"200": response("OpenAPI 文档", {"type": "object"}), "401": errors["401"]}}},
207
- "/api/health": {"get": {"summary": "读取服务健康状态", "security": security,
208
- "responses": {"200": response("健康状态", {"type": "object"}), "401": errors["401"]}}},
209
- "/api/state": {"get": {"summary": "读取任务状态聚合", "security": security,
210
- "responses": {"200": response("状态聚合", {"type": "object"}), "401": errors["401"]}}},
211
- }
212
- return {"openapi": "3.0.3", "info": {"title": "CodeBee API", "version": "1.0",
213
- "description": "本机/局域网 API。远程请求需 X-CodeBee-Token 或 token 查询参数;本机 loopback 默认免令牌。"},
214
- "servers": [{"url": "/"}], "components": {"securitySchemes": {
215
- "codebeeToken": {"type": "apiKey", "in": "header", "name": "X-CodeBee-Token"},
216
- "codebeeQueryToken": {"type": "apiKey", "in": "query", "name": "token"}},
217
- "schemas": schemas}, "paths": paths}
1
+ """OpenAPI 3 contract for the stable headless CodeBee integrations."""
2
+
3
+
4
+ def document():
5
+ schemas = {
6
+ "Error": {"type": "object", "required": ["error"], "properties": {
7
+ "error": {"type": "string"}, "control": {"$ref": "#/components/schemas/Control"}}},
8
+ "Control": {"type": "object", "properties": {
9
+ "mode": {"type": "string", "enum": ["free", "held"]},
10
+ "mine": {"type": "boolean"}, "holder": {"type": "string"},
11
+ "expires_in": {"type": "integer", "minimum": 0}}},
12
+ "TaskCreate": {"type": "object", "required": ["goal"], "properties": {
13
+ "type": {"type": "string"}, "title": {"type": "string"},
14
+ "goal": {"type": "string", "maxLength": 4000}, "workdir": {"type": "string"},
15
+ "sandbox": {"type": "object", "properties": {
16
+ "backend": {"type": "string", "enum": ["native", "docker"]},
17
+ "docker_image": {"type": "string", "maxLength": 240},
18
+ "allowed_roots": {"type": "array", "maxItems": 16,
19
+ "items": {"type": "string", "maxLength": 1024}},
20
+ "env_allowlist": {"type": "array", "maxItems": 64,
21
+ "items": {"type": "string", "maxLength": 128}},
22
+ "network": {"type": "boolean"}, "timeout_s": {"type": "integer"}}},
23
+ "acceptance_criteria": {"type": "array", "maxItems": 40,
24
+ "items": {"type": "string", "maxLength": 500}},
25
+ "approval_required": {"type": "boolean"}}},
26
+ "TaskResult": {"type": "object", "required": ["task_id", "run_id"], "properties": {
27
+ "task_id": {"type": "string"}, "run_id": {"type": "string"}}},
28
+ "Evidence": {"type": "object", "required": ["status"], "properties": {
29
+ "id": {"type": "string"}, "criterion": {"type": "string", "maxLength": 500},
30
+ "status": {"type": "string", "enum": ["passed", "failed", "unknown", "not_evaluated"]},
31
+ "summary": {"type": "string", "maxLength": 2000},
32
+ "source": {"type": "string", "maxLength": 80}, "created_at": {"type": "string"}}},
33
+ "Contract": {"type": "object", "properties": {
34
+ "task_id": {"type": "string"},
35
+ "acceptance_criteria": {"type": "array", "items": {"type": "string"}},
36
+ "evidence": {"type": "array", "items": {"$ref": "#/components/schemas/Evidence"}},
37
+ "approval_required": {"type": "boolean"}, "approval": {"type": "object"},
38
+ "blocked_reason": {"type": "string"}, "completion_receipt": {"type": "object"}}},
39
+ "StoryChapter": {"type": "object", "properties": {
40
+ "op": {"type": "string"},
41
+ "chapter": {"type": "integer", "minimum": 1, "maximum": 5000},
42
+ "outline": {"type": "string", "maxLength": 12000}, "prose": {"type": "string"},
43
+ "facts": {"type": "array", "items": {"type": "string"}},
44
+ "characters": {"type": "array", "items": {"type": "string"}},
45
+ "timeline": {"type": "array", "items": {"type": "string"}},
46
+ "foreshadowing": {"type": "array", "items": {"type": "object"}},
47
+ "next_promises": {"type": "array", "items": {"type": "string"}},
48
+ "author_truth": {"type": "array", "items": {"type": "string"}},
49
+ "reader_known": {"type": "array", "items": {"type": "string"}}},
50
+ "oneOf": [
51
+ {"required": ["op"], "properties": {"op": {"const": "init"}}},
52
+ {"required": ["chapter", "outline", "prose"]},
53
+ ]},
54
+ "StoryTrackingResult": {"type": "object", "properties": {
55
+ "state": {"type": "object"}, "check": {"type": "object"}}},
56
+ "Presence": {"type": "object", "required": ["agent_id"], "properties": {
57
+ "agent_id": {"type": "string", "maxLength": 100}, "label": {"type": "string", "maxLength": 120},
58
+ "capabilities": {"type": "array", "maxItems": 30,
59
+ "items": {"type": "string", "maxLength": 80}},
60
+ "task_id": {"type": "string", "maxLength": 100}, "status": {"type": "string", "maxLength": 30},
61
+ "metadata": {"type": "object"}}},
62
+ "BackendProfile": {"type": "object", "required": ["label", "command"], "properties": {
63
+ "id": {"type": "string"}, "agent_id": {"type": "string"},
64
+ "label": {"type": "string", "maxLength": 80}, "command": {"type": "string", "maxLength": 500},
65
+ "args": {"type": "array", "maxItems": 80, "items": {"type": "string"}},
66
+ "env": {"type": "object", "additionalProperties": {"type": "string"}},
67
+ "workspace_path": {"type": "string"}, "enabled": {"type": "boolean"}}},
68
+ "CommandAuth": {"type": "object", "properties": {
69
+ "mode": {"type": "string", "enum": ["legacy", "restricted"]},
70
+ "pending": {"type": "array"}, "rules": {"type": "array"}, "audit": {"type": "array"}}},
71
+ }
72
+
73
+ def body(schema):
74
+ return {"required": True, "content": {"application/json": {"schema": schema}}}
75
+
76
+ def response(description, schema=None):
77
+ out = {"description": description}
78
+ if schema is not None:
79
+ out["content"] = {"application/json": {"schema": schema}}
80
+ return out
81
+
82
+ ref = lambda name: {"$ref": "#/components/schemas/" + name}
83
+ security = [{"codebeeToken": []}, {"codebeeQueryToken": []}]
84
+ errors = {code: response(desc, ref("Error")) for code, desc in (
85
+ ("400", "请求无效"), ("401", "缺少或错误的访问令牌"),
86
+ ("404", "资源不存在"), ("409", "状态冲突或审批未完成"),
87
+ ("423", "其他设备持有控制权"))}
88
+ ok = response("成功", {"type": "object", "properties": {"ok": {"type": "boolean"}}})
89
+
90
+ paths = {
91
+ "/api/tasks": {"post": {"summary": "创建并启动任务", "security": security,
92
+ "requestBody": body(ref("TaskCreate")),
93
+ "responses": {"200": response("已排队", ref("TaskResult")),
94
+ "503": response("运行记录或入队失败", ref("Error")), **errors}}},
95
+ "/api/a2a/tasks": {"post": {"summary": "A2A-lite 创建任务", "security": security,
96
+ "requestBody": body(ref("TaskCreate")),
97
+ "responses": {"200": response("已排队", ref("TaskResult")), "400": errors["400"],
98
+ "401": errors["401"], "423": errors["423"]}}},
99
+ "/api/a2a/tasks/{task_id}": {"get": {"summary": "A2A-lite 读取任务状态", "security": security,
100
+ "responses": {"200": response("任务、运行和契约", {"type": "object"}),
101
+ "401": errors["401"], "404": errors["404"]}}},
102
+ "/api/tasks/{task_id}/detail": {"get": {"summary": "读取任务详情和契约", "security": security,
103
+ "responses": {"200": response("任务详情", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
104
+ "/api/tasks/{task_id}/contract": {
105
+ "get": {"summary": "读取任务契约", "security": security,
106
+ "responses": {"200": response("契约", ref("Contract")), "401": errors["401"], "404": errors["404"]}},
107
+ "post": {"summary": "更新契约、追加证据或审批任务", "security": security,
108
+ "requestBody": body({"type": "object", "properties": {
109
+ "op": {"type": "string", "enum": ["update", "create", "evidence", "approve", "reject", "blocked"]},
110
+ "acceptance_criteria": {"type": "array", "items": {"type": "string"}},
111
+ "approval_required": {"type": "boolean"}, "evidence": ref("Evidence"),
112
+ "note": {"type": "string", "maxLength": 1000}, "reason": {"type": "string", "maxLength": 1000}}}),
113
+ "responses": {"200": response("契约已更新", {"type": "object", "properties": {"contract": ref("Contract")}}), **errors}}},
114
+ "/api/tasks/{task_id}/story-tracking": {
115
+ "get": {"summary": "读取小说追踪状态", "security": security,
116
+ "responses": {"200": response("追踪状态", ref("StoryTrackingResult")), "401": errors["401"],
117
+ "404": errors["404"], "409": errors["409"]}},
118
+ "post": {"summary": "提交章节结构化状态", "security": security, "requestBody": body(ref("StoryChapter")),
119
+ "responses": {"200": response("追踪状态已更新", ref("StoryTrackingResult")), **errors}}},
120
+ "/api/agents/presence": {
121
+ "get": {"summary": "Agent 在线状态", "security": security,
122
+ "responses": {"200": response("在线 Agent 列表", {"type": "object"}), "401": errors["401"]}},
123
+ "post": {"summary": "Agent 心跳", "security": security, "requestBody": body(ref("Presence")),
124
+ "responses": {"200": response("心跳已记录", {"type": "object"}), "400": errors["400"],
125
+ "401": errors["401"], "423": errors["423"]}}},
126
+ "/api/backend-profiles": {
127
+ "get": {"summary": "读取 ACP Backend Profiles(密钥脱敏)", "security": security,
128
+ "responses": {"200": response("Profiles", {"type": "object"}), "401": errors["401"]}},
129
+ "post": {"summary": "保存 ACP Backend Profile", "security": security,
130
+ "requestBody": body(ref("BackendProfile")),
131
+ "responses": {"200": response("Profile", {"type": "object"}), "400": errors["400"], "401": errors["401"]}}},
132
+ "/api/backend-profiles/{profile_id}/delete": {
133
+ "post": {"summary": "删除 ACP Backend Profile", "security": security,
134
+ "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"]}}},
135
+ "/api/command-auth": {
136
+ "get": {"summary": "读取命令授权策略与待处理请求", "security": security,
137
+ "responses": {"200": response("Authorization state", ref("CommandAuth")), "401": errors["401"]}},
138
+ "post": {"summary": "切换命令授权策略", "security": security,
139
+ "requestBody": body({"type": "object", "properties": {"mode": {"type": "string", "enum": ["legacy", "restricted"]}}}),
140
+ "responses": {"200": response("Authorization state", ref("CommandAuth")), "400": errors["400"], "401": errors["401"]}}},
141
+ "/api/command-auth/requests/{request_id}": {
142
+ "post": {"summary": "批准或拒绝等待中的命令", "security": security,
143
+ "requestBody": body({"type": "object", "required": ["approve"], "properties": {
144
+ "approve": {"type": "boolean"}, "scope": {"type": "string"}, "match": {"type": "string"}, "prefix": {"type": "string"}}}),
145
+ "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"]}}},
146
+ "/api/command-auth/rules/{rule_id}/revoke": {
147
+ "post": {"summary": "撤销命令授权规则", "security": security,
148
+ "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"]}}},
149
+ "/api/retrieval/search": {"get": {"summary": "本地检索", "security": security,
150
+ "parameters": [{"name": "q", "in": "query", "required": True,
151
+ "schema": {"type": "string", "maxLength": 500}},
152
+ {"name": "limit", "in": "query",
153
+ "schema": {"type": "integer", "minimum": 1, "maximum": 50}}],
154
+ "responses": {"200": response("检索结果", {"type": "object"}), "400": errors["400"], "401": errors["401"]}}},
155
+ "/api/retrieval/index": {"post": {"summary": "为配置工作区/任务目录建立本地检索索引", "security": security,
156
+ "requestBody": body({"type": "object", "properties": {
157
+ "source": {"type": "string"}, "text": {"type": "string"}, "metadata": {"type": "object"},
158
+ "doc_id": {"type": "string"}, "root": {"type": "string"}, "task_id": {"type": "string"},
159
+ "limit": {"type": "integer", "minimum": 1, "maximum": 500}}}),
160
+ "responses": {"200": response("索引已更新", {"type": "object"}), "400": errors["400"],
161
+ "401": errors["401"], "404": errors["404"], "423": errors["423"]}}},
162
+ "/api/analytics": {"get": {"summary": "任务成本质量分析", "security": security,
163
+ "responses": {"200": response("分析摘要", {"type": "object"}), "401": errors["401"]}}},
164
+ "/api/runs/{run_id}": {"get": {"summary": "读取运行状态", "security": security,
165
+ "responses": {"200": response("运行状态", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
166
+ "/api/runs/{run_id}/trace": {"get": {"summary": "读取脱敏 trace", "security": security,
167
+ "responses": {"200": response("Trace", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
168
+ "/api/runs/{run_id}/otel": {"get": {"summary": "导出 OTLP JSON trace", "security": security,
169
+ "responses": {"200": response("OTLP trace", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
170
+ "/api/runs/{run_id}/checkpoints": {"get": {"summary": "读取 checkpoint 回放预览", "security": security,
171
+ "responses": {"200": response("Checkpoint", {"type": "object"}), "401": errors["401"]}}},
172
+ "/api/flows/{flow_id}/graph": {"get": {"summary": "读取流程图投影", "security": security,
173
+ "responses": {"200": response("Flow graph", {"type": "object"}), "401": errors["401"], "404": errors["404"]}}},
174
+ "/api/hooks/run": {"post": {"summary": "Webhook 触发任务(可选 HMAC)", "security": security,
175
+ "requestBody": body(ref("TaskCreate")),
176
+ "responses": {"200": response("已排队", ref("TaskResult")), "401": errors["401"], "403": errors["401"], "400": errors["400"]}}},
177
+ "/api/eval-matrix/normalize": {"post": {"summary": "规范化评测矩阵 manifest", "security": security,
178
+ "requestBody": body({"type": "object"}), "responses": {"200": response("Manifest", {"type": "object"}), "400": errors["400"]}}},
179
+ "/api/eval-matrix/evaluate": {"post": {"summary": "对比评测矩阵与 baseline", "security": security,
180
+ "requestBody": body({"type": "object"}), "responses": {"200": response("Report", {"type": "object"}), "400": errors["400"]}}},
181
+ "/api/knowledge/pipeline": {"get": {"summary": "读取知识管线质量报告", "security": security,
182
+ "parameters": [{"name": "ingest_id", "in": "query", "schema": {"type": "string"}}],
183
+ "responses": {"200": response("Quality report", {"type": "object"})}},
184
+ "post": {"summary": "分块并建立知识索引", "security": security,
185
+ "requestBody": body({"type": "object"}), "responses": {"200": response("Ingest report", {"type": "object"}), "400": errors["400"]}}},
186
+ "/api/policy": {"get": {"summary": "读取规范化沙箱策略", "security": security,
187
+ "parameters": [{"name": "workdir", "in": "query", "schema": {"type": "string"}}],
188
+ "responses": {"200": response("Sandbox policy", {"type": "object"})}}},
189
+ "/api/runs/{run_id}/resume_now": {"post": {"summary": "立即重试运行", "security": security,
190
+ "responses": {"200": ok, "400": errors["400"], "401": errors["401"], "404": errors["404"], "423": errors["423"]}}},
191
+ "/api/control": {
192
+ "get": {"summary": "读取当前控制权", "security": security,
193
+ "responses": {"200": response("控制权状态", {"type": "object"}), "401": errors["401"]}},
194
+ "post": {"summary": "接管或释放控制权", "security": security,
195
+ "requestBody": body({"type": "object", "required": ["action"], "properties": {
196
+ "action": {"type": "string", "enum": ["acquire", "release"]},
197
+ "force": {"type": "boolean"}}}),
198
+ "responses": {"200": response("控制权已更新", {"type": "object"}),
199
+ "400": errors["400"], "401": errors["401"], "423": errors["423"]}}},
200
+ "/api/control/heartbeat": {
201
+ "get": {"summary": "续期当前控制权", "security": security,
202
+ "responses": {"200": response("控制权状态", {"type": "object"}), "401": errors["401"]}},
203
+ "post": {"summary": "续期当前控制权", "security": security,
204
+ "responses": {"200": response("控制权状态", {"type": "object"}), "401": errors["401"]}}},
205
+ "/api/openapi.json": {"get": {"summary": "读取 OpenAPI 文档", "security": security,
206
+ "responses": {"200": response("OpenAPI 文档", {"type": "object"}), "401": errors["401"]}}},
207
+ "/api/health": {"get": {"summary": "读取服务健康状态", "security": security,
208
+ "responses": {"200": response("健康状态", {"type": "object"}), "401": errors["401"]}}},
209
+ "/api/state": {"get": {"summary": "读取任务状态聚合", "security": security,
210
+ "responses": {"200": response("状态聚合", {"type": "object"}), "401": errors["401"]}}},
211
+ }
212
+ return {"openapi": "3.0.3", "info": {"title": "CodeBee API", "version": "1.0",
213
+ "description": "本机/局域网 API。远程请求需 X-CodeBee-Token 或 token 查询参数;本机 loopback 默认免令牌。"},
214
+ "servers": [{"url": "/"}], "components": {"securitySchemes": {
215
+ "codebeeToken": {"type": "apiKey", "in": "header", "name": "X-CodeBee-Token"},
216
+ "codebeeQueryToken": {"type": "apiKey", "in": "query", "name": "token"}},
217
+ "schemas": schemas}, "paths": paths}