cube-agent-harness 0.1.0__py3-none-any.whl

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 (373) hide show
  1. cube/README.md +369 -0
  2. cube/__init__.py +1 -0
  3. cube/_optional.py +17 -0
  4. cube/cluster/README.md +277 -0
  5. cube/cluster/__init__.py +52 -0
  6. cube/cluster/_config.py +118 -0
  7. cube/cluster/_health.py +39 -0
  8. cube/cluster/_schema.py +51 -0
  9. cube/cluster/_services.py +25 -0
  10. cube/cluster/gateway/__init__.py +3 -0
  11. cube/cluster/gateway/_events.py +58 -0
  12. cube/cluster/gateway/_gateway.py +365 -0
  13. cube/cluster/gateway/_pending.py +26 -0
  14. cube/cluster/mysql/__init__.py +4 -0
  15. cube/cluster/mysql/_config.py +31 -0
  16. cube/cluster/mysql/_provider.py +55 -0
  17. cube/cluster/protocol/__init__.py +16 -0
  18. cube/cluster/protocol/_codec.py +20 -0
  19. cube/cluster/protocol/_constants.py +3 -0
  20. cube/cluster/protocol/_envelope.py +50 -0
  21. cube/cluster/redis/__init__.py +6 -0
  22. cube/cluster/redis/_client.py +46 -0
  23. cube/cluster/redis/_config.py +15 -0
  24. cube/cluster/redis/_keys.py +44 -0
  25. cube/cluster/redis/_request_cache.py +31 -0
  26. cube/cluster/routing/__init__.py +21 -0
  27. cube/cluster/routing/_directory.py +60 -0
  28. cube/cluster/routing/_lease.py +129 -0
  29. cube/cluster/routing/_resolver.py +86 -0
  30. cube/cluster/routing/_worker_select.py +41 -0
  31. cube/cluster/worker/__init__.py +3 -0
  32. cube/cluster/worker/__main__.py +4 -0
  33. cube/cluster/worker/_drain.py +16 -0
  34. cube/cluster/worker/_entrypoint.py +19 -0
  35. cube/cluster/worker/_env.py +98 -0
  36. cube/cluster/worker/_worker.py +661 -0
  37. cube/core/README.md +116 -0
  38. cube/core/__init__.py +168 -0
  39. cube/core/common/__init__.py +23 -0
  40. cube/core/common/_cancellation.py +56 -0
  41. cube/core/common/_event_bus.py +220 -0
  42. cube/core/common/_event_registry.py +69 -0
  43. cube/core/common/_id.py +18 -0
  44. cube/core/common/_status.py +14 -0
  45. cube/core/common/_time.py +16 -0
  46. cube/core/hook/README.md +152 -0
  47. cube/core/hook/__init__.py +136 -0
  48. cube/core/hook/_core_extensions.py +184 -0
  49. cube/core/hook/_decorators.py +78 -0
  50. cube/core/hook/_dispatch.py +96 -0
  51. cube/core/hook/_extension.py +76 -0
  52. cube/core/hook/_record.py +260 -0
  53. cube/core/hook/_reducer.py +138 -0
  54. cube/core/hook/_registry.py +143 -0
  55. cube/core/hook/_runtime.py +38 -0
  56. cube/core/hook/types.py +342 -0
  57. cube/core/llm/__init__.py +160 -0
  58. cube/core/llm/_base_client.py +536 -0
  59. cube/core/llm/_catalog.py +147 -0
  60. cube/core/llm/_lite_llm_client.py +599 -0
  61. cube/core/llm/_model.py +362 -0
  62. cube/core/llm/_router.py +219 -0
  63. cube/core/llm/_router_client.py +395 -0
  64. cube/core/llm/_router_compile.py +126 -0
  65. cube/core/llm/_token.py +55 -0
  66. cube/core/mcp/__init__.py +27 -0
  67. cube/core/mcp/_adapter.py +90 -0
  68. cube/core/mcp/_config.py +117 -0
  69. cube/core/mcp/_manager.py +319 -0
  70. cube/core/runtime/README.md +138 -0
  71. cube/core/runtime/__init__.py +158 -0
  72. cube/core/runtime/_agent_loop.py +1473 -0
  73. cube/core/runtime/_agent_runtime.py +1359 -0
  74. cube/core/runtime/_background_render.py +61 -0
  75. cube/core/runtime/_compact_contract.py +77 -0
  76. cube/core/runtime/_events.py +353 -0
  77. cube/core/runtime/_llm_msg_adapter.py +301 -0
  78. cube/core/runtime/_message.py +376 -0
  79. cube/core/runtime/_message_registry.py +87 -0
  80. cube/core/runtime/_model.py +577 -0
  81. cube/core/runtime/_shutdown.py +139 -0
  82. cube/core/tool/__init__.py +173 -0
  83. cube/core/tool/_base_tool.py +882 -0
  84. cube/core/tool/_call_executor.py +662 -0
  85. cube/core/tool/_decorator.py +128 -0
  86. cube/core/tool/_dynamic.py +201 -0
  87. cube/core/tool/_file_access.py +173 -0
  88. cube/core/tool/_file_mutation.py +100 -0
  89. cube/core/tool/_orchestrator.py +385 -0
  90. cube/core/tool/_registry.py +192 -0
  91. cube/core/tool/_result_storage.py +308 -0
  92. cube/core/tool/_runtime_access.py +142 -0
  93. cube/core/tool/_tool_runtime.py +1584 -0
  94. cube/core/tool/_tool_task.py +931 -0
  95. cube/platform/README.md +163 -0
  96. cube/platform/__init__.py +77 -0
  97. cube/platform/agency/__init__.py +67 -0
  98. cube/platform/agency/_errors.py +2 -0
  99. cube/platform/agency/_model.py +133 -0
  100. cube/platform/agency/_service.py +842 -0
  101. cube/platform/agency/_skill.py +829 -0
  102. cube/platform/agency/_subagent.py +379 -0
  103. cube/platform/agent/__init__.py +59 -0
  104. cube/platform/agent/_agent.py +377 -0
  105. cube/platform/agent/_option.py +238 -0
  106. cube/platform/agent/_state.py +28 -0
  107. cube/platform/agent/_subagent.py +45 -0
  108. cube/platform/agent/_worker.py +41 -0
  109. cube/platform/assembly/__init__.py +15 -0
  110. cube/platform/assembly/_config.py +22 -0
  111. cube/platform/assembly/_loader.py +49 -0
  112. cube/platform/assembly/_runtime.py +27 -0
  113. cube/platform/assembly/_validation.py +74 -0
  114. cube/platform/channel/__init__.py +13 -0
  115. cube/platform/channel/_coordinator.py +198 -0
  116. cube/platform/channel/_errors.py +2 -0
  117. cube/platform/channel/_model.py +15 -0
  118. cube/platform/channel/_service.py +197 -0
  119. cube/platform/channel/_session_gate.py +51 -0
  120. cube/platform/channel/_state.py +300 -0
  121. cube/platform/command/__init__.py +37 -0
  122. cube/platform/command/_executor.py +384 -0
  123. cube/platform/command/_local.py +29 -0
  124. cube/platform/command/_model.py +180 -0
  125. cube/platform/command/_protocol.py +15 -0
  126. cube/platform/database/README.md +123 -0
  127. cube/platform/database/__init__.py +58 -0
  128. cube/platform/database/_config.py +28 -0
  129. cube/platform/database/_json.py +23 -0
  130. cube/platform/database/_paths.py +12 -0
  131. cube/platform/database/_provider.py +21 -0
  132. cube/platform/database/_providers/__init__.py +3 -0
  133. cube/platform/database/_providers/_sqlite.py +74 -0
  134. cube/platform/database/_retry.py +37 -0
  135. cube/platform/database/_schema.py +364 -0
  136. cube/platform/database/_service.py +138 -0
  137. cube/platform/database/_table_config.py +32 -0
  138. cube/platform/database/_table_init.py +42 -0
  139. cube/platform/database/_table_loader.py +59 -0
  140. cube/platform/database/_table_registry.py +132 -0
  141. cube/platform/database/_table_spec.py +72 -0
  142. cube/platform/database/_tables.py +22 -0
  143. cube/platform/database/_types.py +11 -0
  144. cube/platform/database/repository/__init__.py +47 -0
  145. cube/platform/database/repository/_agency_user_membership_repository.py +65 -0
  146. cube/platform/database/repository/_agent_run_state_repository.py +135 -0
  147. cube/platform/database/repository/_background_tool_task_repository.py +120 -0
  148. cube/platform/database/repository/_base.py +44 -0
  149. cube/platform/database/repository/_config_repository.py +43 -0
  150. cube/platform/database/repository/_llm_call_metric_repository.py +179 -0
  151. cube/platform/database/repository/_notification_repository.py +95 -0
  152. cube/platform/database/repository/_session_member_repository.py +106 -0
  153. cube/platform/database/repository/_session_message_repository.py +168 -0
  154. cube/platform/database/repository/_session_repository.py +61 -0
  155. cube/platform/database/table/__init__.py +38 -0
  156. cube/platform/database/table/_agency_user_membership.py +44 -0
  157. cube/platform/database/table/_agent_run_state.py +21 -0
  158. cube/platform/database/table/_background_tool_task.py +63 -0
  159. cube/platform/database/table/_config.py +23 -0
  160. cube/platform/database/table/_llm_call_metric.py +93 -0
  161. cube/platform/database/table/_notification.py +62 -0
  162. cube/platform/database/table/_session.py +56 -0
  163. cube/platform/database/table/_session_member.py +33 -0
  164. cube/platform/database/table/_session_message.py +53 -0
  165. cube/platform/event/__init__.py +25 -0
  166. cube/platform/event/_local.py +118 -0
  167. cube/platform/event/_model.py +18 -0
  168. cube/platform/event/_protocol.py +36 -0
  169. cube/platform/event/_snapshot.py +49 -0
  170. cube/platform/event/_stream.py +94 -0
  171. cube/platform/host/__init__.py +47 -0
  172. cube/platform/host/_config.py +38 -0
  173. cube/platform/host/_health.py +68 -0
  174. cube/platform/host/_local_app.py +152 -0
  175. cube/platform/host/_runtime.py +306 -0
  176. cube/platform/host/_services.py +180 -0
  177. cube/platform/mcp/__init__.py +15 -0
  178. cube/platform/mcp/_runtime.py +158 -0
  179. cube/platform/notification/__init__.py +23 -0
  180. cube/platform/notification/_events.py +26 -0
  181. cube/platform/notification/_model.py +68 -0
  182. cube/platform/notification/_service.py +203 -0
  183. cube/platform/plugin/README.md +203 -0
  184. cube/platform/plugin/__init__.py +173 -0
  185. cube/platform/plugin/_agent.py +50 -0
  186. cube/platform/plugin/_assembly.py +92 -0
  187. cube/platform/plugin/_catalog.py +60 -0
  188. cube/platform/plugin/_channel.py +287 -0
  189. cube/platform/plugin/_config.py +254 -0
  190. cube/platform/plugin/_context.py +127 -0
  191. cube/platform/plugin/_database.py +37 -0
  192. cube/platform/plugin/_discovery.py +144 -0
  193. cube/platform/plugin/_errors.py +35 -0
  194. cube/platform/plugin/_loader.py +30 -0
  195. cube/platform/plugin/_manager.py +44 -0
  196. cube/platform/plugin/_materializer.py +166 -0
  197. cube/platform/plugin/_model.py +169 -0
  198. cube/platform/plugin/_registration.py +63 -0
  199. cube/platform/plugin/_registry.py +252 -0
  200. cube/platform/plugin/_resolver.py +144 -0
  201. cube/platform/plugin/_selection.py +34 -0
  202. cube/platform/plugin/_session.py +330 -0
  203. cube/platform/sandbox/__init__.py +16 -0
  204. cube/platform/sandbox/_base.py +33 -0
  205. cube/platform/sandbox/_config.py +93 -0
  206. cube/platform/sandbox/_srt.py +448 -0
  207. cube/platform/session/README.md +117 -0
  208. cube/platform/session/__init__.py +163 -0
  209. cube/platform/session/_agent_helpers.py +213 -0
  210. cube/platform/session/_capabilities.py +65 -0
  211. cube/platform/session/_construction.py +42 -0
  212. cube/platform/session/_errors.py +35 -0
  213. cube/platform/session/_file_mounts.py +162 -0
  214. cube/platform/session/_history.py +30 -0
  215. cube/platform/session/_manifest/__init__.py +27 -0
  216. cube/platform/session/_manifest/_registry.py +163 -0
  217. cube/platform/session/_prompt/__init__.py +109 -0
  218. cube/platform/session/_prompt/_build.py +68 -0
  219. cube/platform/session/_prompt/_document.py +118 -0
  220. cube/platform/session/_prompt/_environment.py +277 -0
  221. cube/platform/session/_prompt/_errors.py +5 -0
  222. cube/platform/session/_prompt/_layers.py +672 -0
  223. cube/platform/session/_prompt/_models.py +74 -0
  224. cube/platform/session/_prompt/_snapshot.py +269 -0
  225. cube/platform/session/_prompt/_workspace.py +138 -0
  226. cube/platform/session/_role.py +50 -0
  227. cube/platform/session/_runtime/__init__.py +99 -0
  228. cube/platform/session/_runtime/_async.py +37 -0
  229. cube/platform/session/_runtime/_background.py +237 -0
  230. cube/platform/session/_runtime/_background_control.py +71 -0
  231. cube/platform/session/_runtime/_recovery.py +74 -0
  232. cube/platform/session/_runtime/_registry.py +638 -0
  233. cube/platform/session/_runtime/_run_state.py +614 -0
  234. cube/platform/session/_runtime/_services.py +62 -0
  235. cube/platform/session/_runtime/_tool_access.py +194 -0
  236. cube/platform/session/_schema/__init__.py +69 -0
  237. cube/platform/session/_schema/_events.py +44 -0
  238. cube/platform/session/_schema/_lifecycle.py +58 -0
  239. cube/platform/session/_schema/_messages.py +92 -0
  240. cube/platform/session/_schema/_model.py +176 -0
  241. cube/platform/session/_schema/_receive.py +71 -0
  242. cube/platform/session/_schema/_state.py +39 -0
  243. cube/platform/session/_schema/_workspace.py +30 -0
  244. cube/platform/session/_service.py +688 -0
  245. cube/platform/session/_session.py +1264 -0
  246. cube/platform/session/_transcript/__init__.py +11 -0
  247. cube/platform/session/_transcript/_codec.py +26 -0
  248. cube/platform/session/_transcript/_transcript.py +251 -0
  249. cube/platform/workspace/__init__.py +73 -0
  250. cube/platform/workspace/_agency_workspace.py +99 -0
  251. cube/platform/workspace/_agent_workspace.py +82 -0
  252. cube/platform/workspace/_channel_workspace.py +73 -0
  253. cube/platform/workspace/_coordination.py +727 -0
  254. cube/platform/workspace/_file_workspace.py +347 -0
  255. cube/platform/workspace/_key_file_schema.py +219 -0
  256. cube/platform/workspace/_key_file_service.py +237 -0
  257. cube/platform/workspace/_metadata_cache.py +211 -0
  258. cube/platform/workspace/_vfs.py +110 -0
  259. cube/platform/workspace/_workspace_service.py +111 -0
  260. cube/plugins/README.md +56 -0
  261. cube/plugins/__init__.py +1 -0
  262. cube/plugins/channels/__init__.py +1 -0
  263. cube/plugins/channels/chat/__init__.py +14 -0
  264. cube/plugins/channels/chat/_config.py +14 -0
  265. cube/plugins/channels/chat/_provider.py +92 -0
  266. cube/plugins/channels/chat/plugin.py +54 -0
  267. cube/plugins/channels/project/__init__.py +18 -0
  268. cube/plugins/channels/project/_config.py +10 -0
  269. cube/plugins/channels/project/_provider.py +50 -0
  270. cube/plugins/channels/project/_query_service.py +176 -0
  271. cube/plugins/channels/project/plugin.py +45 -0
  272. cube/plugins/hooks/__init__.py +26 -0
  273. cube/plugins/hooks/compaction/__init__.py +17 -0
  274. cube/plugins/hooks/compaction/_micro.py +57 -0
  275. cube/plugins/hooks/compaction/_policy.py +16 -0
  276. cube/plugins/hooks/compaction/_shared.py +165 -0
  277. cube/plugins/hooks/compaction/_summary.py +131 -0
  278. cube/plugins/hooks/internal_tool_policy.py +58 -0
  279. cube/plugins/hooks/llm_metric_recorder.py +63 -0
  280. cube/plugins/hooks/normalize_tool_input.py +53 -0
  281. cube/plugins/hooks/plugin.py +27 -0
  282. cube/plugins/sessions/__init__.py +3 -0
  283. cube/plugins/sessions/chat/__init__.py +41 -0
  284. cube/plugins/sessions/chat/_compaction.py +31 -0
  285. cube/plugins/sessions/chat/_file_space.py +173 -0
  286. cube/plugins/sessions/chat/_hooks.py +54 -0
  287. cube/plugins/sessions/chat/_llm_msg_adapter.py +140 -0
  288. cube/plugins/sessions/chat/_messages.py +129 -0
  289. cube/plugins/sessions/chat/_model.py +168 -0
  290. cube/plugins/sessions/chat/_prompt.py +102 -0
  291. cube/plugins/sessions/chat/_service.py +151 -0
  292. cube/plugins/sessions/chat/_session.py +1543 -0
  293. cube/plugins/sessions/chat/_state.py +15 -0
  294. cube/plugins/sessions/chat/_workspace.py +54 -0
  295. cube/plugins/sessions/chat/plugin.py +43 -0
  296. cube/plugins/sessions/chat/tools/__init__.py +6 -0
  297. cube/plugins/sessions/chat/tools/send_message.py +309 -0
  298. cube/plugins/sessions/task/README.md +35 -0
  299. cube/plugins/sessions/task/__init__.py +228 -0
  300. cube/plugins/sessions/task/_agent_text.py +18 -0
  301. cube/plugins/sessions/task/_command_service.py +123 -0
  302. cube/plugins/sessions/task/_compaction.py +56 -0
  303. cube/plugins/sessions/task/_event.py +23 -0
  304. cube/plugins/sessions/task/_executor.py +825 -0
  305. cube/plugins/sessions/task/_llm_msg_adapter.py +255 -0
  306. cube/plugins/sessions/task/_messages.py +130 -0
  307. cube/plugins/sessions/task/_models.py +434 -0
  308. cube/plugins/sessions/task/_notification_topics.py +15 -0
  309. cube/plugins/sessions/task/_notifications.py +97 -0
  310. cube/plugins/sessions/task/_persistence_service.py +48 -0
  311. cube/plugins/sessions/task/_query_service.py +120 -0
  312. cube/plugins/sessions/task/_repositories.py +30 -0
  313. cube/plugins/sessions/task/_state.py +67 -0
  314. cube/plugins/sessions/task/_tables.py +11 -0
  315. cube/plugins/sessions/task/_task_file_space.py +114 -0
  316. cube/plugins/sessions/task/_task_prompt.py +101 -0
  317. cube/plugins/sessions/task/_task_session.py +2182 -0
  318. cube/plugins/sessions/task/_task_workspace.py +56 -0
  319. cube/plugins/sessions/task/_workflow_file_space.py +167 -0
  320. cube/plugins/sessions/task/_workflow_messages.py +68 -0
  321. cube/plugins/sessions/task/_workflow_projection.py +305 -0
  322. cube/plugins/sessions/task/_workflow_prompt.py +98 -0
  323. cube/plugins/sessions/task/_workflow_session.py +824 -0
  324. cube/plugins/sessions/task/_workflow_workspace.py +68 -0
  325. cube/plugins/sessions/task/persistence/__init__.py +17 -0
  326. cube/plugins/sessions/task/persistence/_task_run.py +96 -0
  327. cube/plugins/sessions/task/persistence/_task_run_repository.py +118 -0
  328. cube/plugins/sessions/task/persistence/_task_schedule.py +64 -0
  329. cube/plugins/sessions/task/persistence/_task_schedule_repository.py +73 -0
  330. cube/plugins/sessions/task/plugin.py +77 -0
  331. cube/plugins/sessions/task/tools/__init__.py +48 -0
  332. cube/plugins/sessions/task/tools/task_cancel.py +143 -0
  333. cube/plugins/sessions/task/tools/task_create.py +226 -0
  334. cube/plugins/sessions/task/tools/task_list.py +94 -0
  335. cube/plugins/sessions/task/tools/task_start.py +139 -0
  336. cube/plugins/sessions/task/tools/task_status.py +84 -0
  337. cube/plugins/sessions/task/tools/workflow_run.py +406 -0
  338. cube/plugins/subagent/__init__.py +44 -0
  339. cube/plugins/subagent/_assembly.py +121 -0
  340. cube/plugins/subagent/_compaction.py +34 -0
  341. cube/plugins/subagent/_definition.py +140 -0
  342. cube/plugins/subagent/_definition_service.py +94 -0
  343. cube/plugins/subagent/_file_space.py +106 -0
  344. cube/plugins/subagent/_models.py +41 -0
  345. cube/plugins/subagent/_prompt.py +70 -0
  346. cube/plugins/subagent/_provider.py +40 -0
  347. cube/plugins/subagent/_session.py +419 -0
  348. cube/plugins/subagent/_subagent.py +96 -0
  349. cube/plugins/subagent/_workspace.py +52 -0
  350. cube/plugins/subagent/plugin.py +48 -0
  351. cube/plugins/subagent/tools/__init__.py +8 -0
  352. cube/plugins/subagent/tools/subagent.py +138 -0
  353. cube/plugins/tools/README.md +178 -0
  354. cube/plugins/tools/__init__.py +100 -0
  355. cube/plugins/tools/_media_reader.py +293 -0
  356. cube/plugins/tools/_text_reader.py +569 -0
  357. cube/plugins/tools/ask_user.py +243 -0
  358. cube/plugins/tools/background_tool_cancel.py +84 -0
  359. cube/plugins/tools/background_tool_status.py +91 -0
  360. cube/plugins/tools/bash.py +357 -0
  361. cube/plugins/tools/edit.py +282 -0
  362. cube/plugins/tools/glob.py +140 -0
  363. cube/plugins/tools/grep.py +591 -0
  364. cube/plugins/tools/plugin.py +53 -0
  365. cube/plugins/tools/read.py +530 -0
  366. cube/plugins/tools/skill.py +125 -0
  367. cube/plugins/tools/write.py +196 -0
  368. cube/py.typed +1 -0
  369. cube_agent_harness-0.1.0.dist-info/METADATA +331 -0
  370. cube_agent_harness-0.1.0.dist-info/RECORD +373 -0
  371. cube_agent_harness-0.1.0.dist-info/WHEEL +4 -0
  372. cube_agent_harness-0.1.0.dist-info/entry_points.txt +8 -0
  373. cube_agent_harness-0.1.0.dist-info/licenses/LICENSE +21 -0
cube/README.md ADDED
@@ -0,0 +1,369 @@
1
+ # Cube SDK
2
+
3
+ `cube` 是 `cube-agent-harness` 发行包安装后的 Python import 包:
4
+
5
+ ```bash
6
+ pip install cube-agent-harness
7
+ ```
8
+
9
+ ```python
10
+ import cube
11
+ ```
12
+
13
+ Cube 是一个用于构建可嵌入、可使用工具、可通过插件扩展的 Agent Harness
14
+ Python SDK。它拆成一个轻量 runtime kernel、可选的本地应用宿主、可选的分布式
15
+ runtime,以及官方能力插件。
16
+
17
+ ## 包结构
18
+
19
+ | 包 | 适用场景 | 主要入口 |
20
+ | --- | --- | --- |
21
+ | `cube.core` | 需要不依赖 platform 的 Agent runtime kernel。 | `AgentRuntime`, `AgentRunRequest`, `ToolRuntime`, `HookRuntime`, LLM/MCP contracts |
22
+ | `cube.platform` | 需要本地可嵌入 Cube 应用,包含 SQLite、sessions、workspaces、plugins 和本地 runtime 激活。 | `CubeLocalApp`, `CubeLocalAppConfig`, `create_cube_local_app`, `PlatformServices`, `PlatformRuntime` |
23
+ | `cube.cluster` | 需要基于 MySQL、Redis 和共享 workspace 的 Backend/Worker 分布式部署。 | `ClusterGateway`, `ClusterGatewayConfig`, `ClusterPlatformServicesConfig`, `ClusterWorker`, `ClusterWorkerConfig` |
24
+ | `cube.plugins` | 需要官方具体 tools、hooks 和 session kinds。 | plugin entry points, bundled tools, chat/task/subagent sessions |
25
+
26
+ 独立 CLI 应用通过 `cube-cli` 单独发布,并安装 `cube` 命令。Playground 应用也不属于
27
+ SDK wheel。
28
+
29
+ ## 安装配置
30
+
31
+ 基础安装保持轻量:
32
+
33
+ ```bash
34
+ pip install cube-agent-harness
35
+ ```
36
+
37
+ 按需安装可选能力:
38
+
39
+ ```bash
40
+ pip install "cube-agent-harness[llm]" # LiteLLM client/router 支持
41
+ pip install "cube-agent-harness[mcp]" # MCP client 支持
42
+ pip install "cube-agent-harness[platform]" # 本地 platform host 和 SQLite
43
+ pip install "cube-agent-harness[cluster]" # 分布式 runtime:MySQL + Redis
44
+ pip install "cube-agent-harness[all]" # 全部官方 SDK extras
45
+ ```
46
+
47
+ ## 应该使用哪个入口?
48
+
49
+ 本地嵌入使用 `cube.platform.CubeLocalApp`:
50
+
51
+ ```python
52
+ from cube.platform import CubeLocalAppConfig, create_cube_local_app
53
+
54
+ app = create_cube_local_app(CubeLocalAppConfig.from_root_dir("./cube-data"))
55
+
56
+ async with app.lifespan():
57
+ services = app.services
58
+ commands = app.commands
59
+ events = app.events
60
+ ```
61
+
62
+ 分布式 Backend 进程中,显式组合 durable services 和 live Gateway:
63
+
64
+ ```python
65
+ from pathlib import Path
66
+
67
+ from cube.cluster import (
68
+ ClusterConfig,
69
+ ClusterGateway,
70
+ ClusterGatewayConfig,
71
+ ClusterPlatformServicesConfig,
72
+ GatewayConfig,
73
+ MySQLConfig,
74
+ RedisConfig,
75
+ create_cluster_platform_services,
76
+ )
77
+ from cube.platform import RuntimeAssemblyConfig
78
+
79
+ assembly = RuntimeAssemblyConfig(rollout_tag="v1")
80
+ services = create_cluster_platform_services(
81
+ ClusterPlatformServicesConfig(
82
+ root_dir=Path("/cube"),
83
+ assembly=assembly,
84
+ mysql=MySQLConfig(
85
+ url="mysql+asyncmy://cube:secret@mysql:3306/cube?charset=utf8mb4",
86
+ ),
87
+ )
88
+ )
89
+ gateway = ClusterGateway(
90
+ config=ClusterGatewayConfig(
91
+ assembly=assembly,
92
+ cluster=ClusterConfig(namespace="cube-prod"),
93
+ redis=RedisConfig(url="redis://:secret@redis:6379/0"),
94
+ gateway=GatewayConfig(),
95
+ )
96
+ )
97
+
98
+ await services.startup()
99
+ await gateway.startup()
100
+ commands = gateway
101
+ events = gateway
102
+ ```
103
+
104
+ 分布式 Worker 进程使用 `cube.cluster.ClusterWorker`:
105
+
106
+ ```bash
107
+ CUBE_ROOT_DIR=/cube \
108
+ CUBE_CLUSTER_NAMESPACE=cube-prod \
109
+ CUBE_ROLLOUT_TAG=v1 \
110
+ CUBE_MYSQL_URL='mysql+asyncmy://cube:secret@mysql:3306/cube?charset=utf8mb4' \
111
+ CUBE_REDIS_URL='redis://:secret@redis:6379/0' \
112
+ CUBE_WORKER_ID=worker-1 \
113
+ python -m cube.cluster.worker
114
+ ```
115
+
116
+ 只有当你希望自己完整负责 persistence、session 语义、workspace 布局和 UI projection
117
+ 时,才直接使用 `cube.core.AgentRuntime`。
118
+
119
+ ## 统一应用接入面
120
+
121
+ 本地和分布式 composition 都应该向业务代码暴露同一组高层应用接入面:
122
+
123
+ - `services`:durable agency/channel/session/workspace/database services。
124
+ - `commands`:与 transport 无关的 live session command dispatcher。
125
+ - `events`:按 session 订阅的 live event subscriber。
126
+
127
+ 这样 application services 可以依赖稳定协议,而不是依赖具体的本地 runtime 或 cluster
128
+ gateway 类。
129
+
130
+ 应用后端通常应该在自己的 composition root 中隐藏部署形态选择:
131
+
132
+ ```python
133
+ from dataclasses import dataclass
134
+
135
+ from cube.platform import PlatformServices
136
+ from cube.platform.command import SessionCommandDispatcher
137
+ from cube.platform.event import SessionEventSubscriber
138
+
139
+
140
+ @dataclass(frozen=True)
141
+ class CubeComponents:
142
+ services: PlatformServices
143
+ commands: SessionCommandDispatcher
144
+ events: SessionEventSubscriber
145
+ ```
146
+
147
+ 本地 backend composition 从 `CubeLocalApp` 填充这些字段:
148
+
149
+ ```python
150
+ from cube.platform import CubeLocalAppConfig, create_cube_local_app
151
+
152
+
153
+ cube_app = create_cube_local_app(
154
+ CubeLocalAppConfig.from_root_dir("./cube-data"),
155
+ )
156
+ cube = CubeComponents(
157
+ services=cube_app.services,
158
+ commands=cube_app.commands,
159
+ events=cube_app.events,
160
+ )
161
+ ```
162
+
163
+ 分布式 backend composition 从 distributed services 和 Gateway 填充同样的字段:
164
+
165
+ ```python
166
+ services = create_cluster_platform_services(...)
167
+ gateway = ClusterGateway(...)
168
+ cube = CubeComponents(
169
+ services=services,
170
+ commands=gateway,
171
+ events=gateway,
172
+ )
173
+ ```
174
+
175
+ Route handlers 和 application services 应该按职责使用这些字段:
176
+
177
+ ```python
178
+ # Durable 查询和管理不会激活 live sessions。
179
+ channel = await cube.services.channels.get(agency_code, channel_code)
180
+ history = await cube.services.sessions.get_history(address.session_id)
181
+
182
+ # Live commands 通过 transport-neutral command boundary。
183
+ result = await cube.commands.dispatch(command)
184
+
185
+ # Live UI 更新通过 event boundary 订阅。
186
+ async with cube.events.subscribe(address) as stream:
187
+ async for event in stream:
188
+ ...
189
+ ```
190
+
191
+ 分布式模式下,Backend 禁止创建 `PlatformRuntime`,也禁止在同一进程内启动 Worker。
192
+ Worker 是独立的 `ClusterWorker` 进程。
193
+
194
+ ## Runtime Assembly
195
+
196
+ Cube 从 runtime-local manifests 加载 plugins 和 tables:
197
+
198
+ ```text
199
+ <root_dir>/plugins.toml
200
+ <root_dir>/tables.toml
201
+ ```
202
+
203
+ `RuntimeAssembly` 会在注入 `PlatformServices` 前冻结已选择的 plugin registry、table
204
+ registry 和 capability assembly。
205
+
206
+ 应用拥有自己的默认 manifests。SDK 不会自动 import 所有已安装 plugins,也不会自动
207
+ import 所有 table modules。
208
+
209
+ ## 插件扩展
210
+
211
+ 插件通过 `cube.plugins` entry point group 暴露 `PluginSpec`:
212
+
213
+ ```python
214
+ from cube.platform.plugin import PluginSpec
215
+
216
+
217
+ def register(ctx):
218
+ ctx.tools("my_tools", my_tool)
219
+
220
+
221
+ plugin = PluginSpec(
222
+ name="my.company.plugin",
223
+ version="0.1.0",
224
+ register=register,
225
+ )
226
+ ```
227
+
228
+ ```toml
229
+ [project.entry-points."cube.plugins"]
230
+ "my.company.plugin" = "my_company.plugin:plugin"
231
+ ```
232
+
233
+ 插件可以贡献 tools、hooks、hook event contracts 和 session kinds。带持久化能力的
234
+ plugins 需要单独声明 `TableSpec` 对象,并在 `PluginSpec.requires_tables` 中列出
235
+ 所需的逻辑 table names。
236
+
237
+ ## 本地模式与分布式模式
238
+
239
+ 本地模式:
240
+
241
+ - 使用 `cube.platform.CubeLocalApp`
242
+ - 使用 SQLite 和本地 POSIX workspace
243
+ - 在应用进程内激活 sessions
244
+ - 使用进程内 event delivery
245
+
246
+ 分布式模式:
247
+
248
+ - Backend 进程使用 `cube.cluster.ClusterGateway`
249
+ - Worker 进程使用 `cube.cluster.ClusterWorker`
250
+ - 使用 MySQL 存储 Cube durable domain data
251
+ - 使用 Redis 承载 worker heartbeat、owner leases、command ACKs 和 live events
252
+ - 要求所有节点可见同一个共享 POSIX workspace
253
+
254
+ 分布式模式有意不提供 `CubeApp` facade。本地嵌入仍然使用
255
+ `cube.platform.CubeLocalApp`;分布式 Backend composition 直接连接
256
+ `PlatformServices` 和 `ClusterGateway`。
257
+
258
+ ## 本地快捷调试:分布式模式
259
+
260
+ 在 Cube 源码仓库中开发 Playground、`cube.cluster`、Worker、tools 或 sessions
261
+ 时,推荐使用根目录 `Makefile` 提供的本地多进程模式。它不使用 Docker 包住源码,
262
+ 但运行拓扑仍然是完整的分布式模式:
263
+
264
+ ```text
265
+ Next.js frontend :3000
266
+ |
267
+ distributed Playground backend :8000
268
+ |
269
+ ClusterGateway -- Redis -- ClusterWorker(s)
270
+ | |
271
+ +------ MySQL ----------+
272
+ +--- shared root_dir ---+
273
+ ```
274
+
275
+ ### macOS 一次性准备
276
+
277
+ 本机需要 Git、Make、`uv`、npm,以及 Node.js 20.11 或更高版本;推荐与官方
278
+ Worker 镜像一致使用 Node.js 22。Python 3.12/3.13 和项目 Python 依赖由 `uv`
279
+ 根据 workspace 配置准备。
280
+
281
+ 把部署配置放在仓库根目录 `.env`。最少需要正确配置:
282
+
283
+ ```text
284
+ CUBE_ROOT_DIR
285
+ CUBE_CLUSTER_NAMESPACE
286
+ CUBE_ROLLOUT_TAG
287
+ CUBE_MYSQL_URL
288
+ CUBE_REDIS_URL
289
+ PLAYGROUND_DATABASE_URL
290
+ PLAYGROUND_AUTH_SECRET
291
+ ```
292
+
293
+ `CUBE_MYSQL_URL` 使用 Cube runtime 数据库;`PLAYGROUND_DATABASE_URL` 使用
294
+ Playground 自己的 account 数据库。两个 database 需要提前存在并允许对应账号建表。
295
+ 本机单套 backend/worker 可以共用一个本地可写的 `CUBE_ROOT_DIR`;跨机器运行时,
296
+ 所有 backend/worker 必须看到同一个共享 POSIX/NAS 路径。
297
+
298
+ 每位开发者应使用独立的 cluster namespace、worker-id prefix、Cube database、
299
+ Playground database 和本地 root directory。只共享 MySQL/Redis、却各用一份本地
300
+ workspace,会让不同 Worker 看到同一批 sessions 但看到不同文件,不是有效拓扑。
301
+
302
+ ### 标准 Make 流程
303
+
304
+ 首次拿到代码和 `.env` 后:
305
+
306
+ ```bash
307
+ make doctor
308
+ make local-start
309
+ ```
310
+
311
+ `make doctor` 只读检查 macOS host tools、Node.js 版本、root directory 权限,
312
+ 以及 MySQL、Redis、Playground database 连通性,不创建表。`make local-start`
313
+ 随后会依次:
314
+
315
+ 1. 在 `deploy/local/sandbox-tools/` 安装或校验固定版本的 SRT 和 ripgrep;不安装
316
+ 全局 npm 包,macOS 也不需要手工安装 Linux 的 `bubblewrap`/`socat`。
317
+ 2. 保留已有 `plugins.toml` / `tables.toml`,缺失时写入 Playground defaults。
318
+ 3. 创建并校验 Cube MySQL tables。
319
+ 4. 启动默认两个 `ClusterWorker`,等待它们在 Redis 发布匹配 namespace/rollout 的
320
+ heartbeat。
321
+ 5. 启动 distributed Playground backend 并等待 HTTP readiness。
322
+ 6. 启动带热更新的 Next.js frontend 并等待 `http://localhost:3000` 可访问。
323
+
324
+ 日常命令:
325
+
326
+ ```bash
327
+ make local-status
328
+ make local-logs
329
+ make local-restart # 修改 Worker/cube runtime 代码后使用
330
+ make local-shutdown
331
+ ```
332
+
333
+ backend 和 frontend 启用源码热更新;Worker/runtime 代码变更需要
334
+ `make local-restart`。启动任一环节 readiness 失败时,launcher 会输出相关日志、
335
+ 停止已记录的本地进程并以失败状态退出。
336
+
337
+ 常用覆盖参数:
338
+
339
+ ```bash
340
+ make doctor ENV_FILE=config/alice.env
341
+ make local-start ENV_FILE=config/alice.env LOCAL_WORKERS=1
342
+ make local-start LOCAL_CLUSTER_READY_TIMEOUT_SECONDS=120
343
+ make local-prepare LOCAL_OVERWRITE_MANIFESTS=1
344
+ ```
345
+
346
+ `make local-prepare` 只用于“初始化但不启动”;它不是 `local-start` 的必需前置。
347
+ `LOCAL_OVERWRITE_MANIFESTS=1` 会有意覆盖已有 runtime manifests,应只在需要恢复
348
+ 当前 Playground defaults 时使用。
349
+
350
+ 如果目标是验证镜像而不是源码热调试,使用:
351
+
352
+ ```bash
353
+ make docker-build
354
+ make docker-up
355
+ make docker-down
356
+ ```
357
+
358
+ Docker Compose 会把源码和依赖构建进镜像、把 frontend 导出为静态资源,不挂载
359
+ 源码,也不提供本地热更新。完整环境变量、sandbox policy、日志位置和故障处理见
360
+ 仓库根目录 `deploy/README.md`。
361
+
362
+ ## 更多文档
363
+
364
+ - `cube/core/README.md`:core runtime、tools、hooks、LLM、MCP。
365
+ - `cube/platform/README.md`:local app host、durable services、session command
366
+ 和 event protocols。
367
+ - `cube/cluster/README.md`:distributed Backend/Worker runtime。
368
+ - `cube/platform/plugin/README.md`:plugin SPI 和 registration model。
369
+ - `cube/plugins/README.md`:官方 bundled plugin implementations。
cube/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Cube package."""
cube/_optional.py ADDED
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ from typing import Any
5
+
6
+
7
+ def import_optional_dependency(module_name: str, *, extra: str, feature: str) -> Any:
8
+ try:
9
+ return importlib.import_module(module_name)
10
+ except ImportError as error:
11
+ raise RuntimeError(
12
+ f"{feature} requires optional dependency {module_name!r}. "
13
+ f"Install Cube with the '{extra}' extra."
14
+ ) from error
15
+
16
+
17
+ __all__ = ["import_optional_dependency"]
cube/cluster/README.md ADDED
@@ -0,0 +1,277 @@
1
+ # cube.cluster
2
+
3
+ `cube.cluster` is Cube's distributed runtime SDK surface. It adds the minimum
4
+ coordination layer needed to run Cube sessions across multiple application
5
+ backend and worker processes.
6
+
7
+ The package is intentionally separate from `cube.platform`:
8
+
9
+ - `cube.platform` owns the local app host and durable platform services.
10
+ - `cube.cluster` owns Redis/MySQL-backed distributed command routing, owner
11
+ leases, worker heartbeat, and live event forwarding.
12
+ - `cube.plugins` still owns concrete tools, hooks, and session kinds.
13
+
14
+ Install with the `cluster` extra:
15
+
16
+ ```bash
17
+ pip install "cube-agent-harness[cluster]"
18
+ ```
19
+
20
+ In this repository use:
21
+
22
+ ```bash
23
+ uv sync --all-packages --all-extras
24
+ ```
25
+
26
+ ## Runtime Shape
27
+
28
+ Distributed mode has two process roles.
29
+
30
+ | Role | SDK entry | Owns | Does not own |
31
+ | --- | --- | --- | --- |
32
+ | Backend / Gateway | `PlatformServices` + `cube.cluster.ClusterGateway` | durable services, command dispatch, event subscription | `PlatformRuntime`, live Session execution |
33
+ | Worker | `cube.cluster.ClusterWorker` | `PlatformServices`, `PlatformRuntime`, owner leases, command handling, event forwarding | HTTP routes, accounts, frontend projection |
34
+
35
+ The backend receives application HTTP/WebSocket traffic, performs durable reads,
36
+ and submits live commands through `ClusterGateway`. Workers claim session owner
37
+ leases and execute the actual `PlatformRuntime` work.
38
+
39
+ There is intentionally no distributed `CubeApp` facade. Local embedding still
40
+ uses `cube.platform.CubeLocalApp`; distributed Backend applications compose
41
+ `PlatformServices` and `ClusterGateway` directly.
42
+
43
+ ## Public API
44
+
45
+ Top-level exports:
46
+
47
+ ```python
48
+ from cube.cluster import (
49
+ CLUSTER_PROTOCOL_VERSION,
50
+ ClusterConfig,
51
+ ClusterGateway,
52
+ ClusterGatewayConfig,
53
+ ClusterPlatformServicesConfig,
54
+ ClusterWorker,
55
+ ClusterWorkerConfig,
56
+ GatewayConfig,
57
+ MySQLConfig,
58
+ RedisConfig,
59
+ WorkerConfig,
60
+ create_cluster_platform_services,
61
+ init_cluster_schema,
62
+ validate_cluster_schema,
63
+ )
64
+ ```
65
+
66
+ Important config objects:
67
+
68
+ - `ClusterConfig`: shared coordination namespace used in Redis key prefixes and
69
+ envelopes.
70
+ - `ClusterPlatformServicesConfig`: Backend/Worker durable service config for
71
+ MySQL, shared root directory, and runtime assembly.
72
+ - `ClusterGatewayConfig`: Backend-side Gateway config for cluster namespace,
73
+ Redis, rollout tag, request limits, and command timeout.
74
+ - `ClusterWorkerConfig`: worker-side config for `ClusterWorker`.
75
+ - `GatewayConfig`: request timeout, pending request limit, optional gateway id,
76
+ and optional worker active-session capacity filter.
77
+ - `WorkerConfig`: optional worker id, heartbeat interval/TTL, owner lease TTL,
78
+ request ACK TTL, dependency grace, and shutdown grace.
79
+ - `MySQLConfig`: SQLAlchemy async MySQL URL and pool settings.
80
+ - `RedisConfig`: Redis URL and socket timeout settings.
81
+
82
+ ## Backend Usage
83
+
84
+ Backend applications usually compose durable services and Gateway at their
85
+ composition root.
86
+
87
+ ```python
88
+ from pathlib import Path
89
+
90
+ from cube.cluster import (
91
+ ClusterConfig,
92
+ ClusterGateway,
93
+ ClusterGatewayConfig,
94
+ ClusterPlatformServicesConfig,
95
+ GatewayConfig,
96
+ MySQLConfig,
97
+ RedisConfig,
98
+ create_cluster_platform_services,
99
+ )
100
+ from cube.platform import RuntimeAssemblyConfig
101
+
102
+ assembly = RuntimeAssemblyConfig(rollout_tag="v1")
103
+ services = create_cluster_platform_services(
104
+ ClusterPlatformServicesConfig(
105
+ root_dir=Path("/cube"),
106
+ assembly=assembly,
107
+ mysql=MySQLConfig(
108
+ url="mysql+asyncmy://cube:secret@mysql:3306/cube?charset=utf8mb4",
109
+ ),
110
+ )
111
+ )
112
+ gateway = ClusterGateway(
113
+ config=ClusterGatewayConfig(
114
+ assembly=assembly,
115
+ cluster=ClusterConfig(namespace="cube-prod"),
116
+ redis=RedisConfig(url="redis://:secret@redis:6379/0"),
117
+ gateway=GatewayConfig(command_timeout_seconds=30),
118
+ )
119
+ )
120
+
121
+ await services.startup()
122
+ await gateway.startup()
123
+ commands = gateway
124
+ events = gateway
125
+ ```
126
+
127
+ Use the surfaces by responsibility:
128
+
129
+ - Durable reads and management go through `app.services`.
130
+ - Live session commands go through `app.commands.dispatch(...)`.
131
+ - Live session events go through `app.events.subscribe(...)`.
132
+
133
+ Backend code must not create `PlatformRuntime` in distributed mode.
134
+
135
+ ## Worker Usage
136
+
137
+ Workers can be constructed directly:
138
+
139
+ ```python
140
+ from pathlib import Path
141
+
142
+ from cube.cluster import (
143
+ ClusterConfig,
144
+ ClusterWorker,
145
+ ClusterWorkerConfig,
146
+ MySQLConfig,
147
+ RedisConfig,
148
+ WorkerConfig,
149
+ )
150
+ from cube.platform import RuntimeAssemblyConfig
151
+
152
+ worker = ClusterWorker(
153
+ config=ClusterWorkerConfig(
154
+ root_dir=Path("/cube"),
155
+ assembly=RuntimeAssemblyConfig(rollout_tag="v1"),
156
+ cluster=ClusterConfig(namespace="cube-prod"),
157
+ mysql=MySQLConfig(
158
+ url="mysql+asyncmy://cube:secret@mysql:3306/cube?charset=utf8mb4",
159
+ ),
160
+ redis=RedisConfig(url="redis://:secret@redis:6379/0"),
161
+ worker=WorkerConfig(worker_id="worker-1"),
162
+ )
163
+ )
164
+
165
+ async with worker.lifespan():
166
+ await worker.run()
167
+ ```
168
+
169
+ The built-in worker entrypoint reads environment variables:
170
+
171
+ ```bash
172
+ CUBE_ROOT_DIR=/cube \
173
+ CUBE_CLUSTER_NAMESPACE=cube-prod \
174
+ CUBE_ROLLOUT_TAG=v1 \
175
+ CUBE_MYSQL_URL='mysql+asyncmy://cube:secret@mysql:3306/cube?charset=utf8mb4' \
176
+ CUBE_REDIS_URL='redis://:secret@redis:6379/0' \
177
+ CUBE_WORKER_ID=worker-1 \
178
+ python -m cube.cluster.worker
179
+ ```
180
+
181
+ `CUBE_WORKER_ID` is optional. If omitted, the SDK generates a process-local
182
+ worker id.
183
+
184
+ ## Schema Lifecycle
185
+
186
+ Distributed runtime uses MySQL for Cube durable domain tables. For production,
187
+ DDL is usually owned by deployment or database operations. For a first test
188
+ deployment, the SDK exposes explicit helpers:
189
+
190
+ ```python
191
+ await init_cluster_schema(config)
192
+ await validate_cluster_schema(config)
193
+ ```
194
+
195
+ `init_cluster_schema(...)` creates the tables selected by the current
196
+ `tables.toml`. `validate_cluster_schema(...)` checks compatibility without
197
+ running DDL. Runtime startup validates schema but does not automatically create
198
+ or migrate tables.
199
+
200
+ ## Required Runtime Files
201
+
202
+ Both backend and worker processes must see the same runtime assembly files under
203
+ `<root_dir>/`:
204
+
205
+ ```text
206
+ <root_dir>/plugins.toml
207
+ <root_dir>/tables.toml
208
+ ```
209
+
210
+ The selected plugins, tables, package version, and `rollout_tag` should match
211
+ between backends and workers.
212
+
213
+ `root_dir` must be shared across nodes in distributed mode. For multi-ECS
214
+ deployments this should be a shared POSIX mount such as NAS, not a local
215
+ disk path that differs by machine.
216
+
217
+ ## Command And Event Flow
218
+
219
+ The core live path is:
220
+
221
+ ```text
222
+ Backend
223
+ -> ClusterGateway
224
+ -> Redis Pub/Sub command request
225
+ -> ClusterWorker
226
+ -> owner lease claim or owner verification
227
+ -> PlatformRuntime / Session
228
+ -> durable state in MySQL and shared workspace
229
+ -> Redis Pub/Sub live event
230
+ -> Backend event subscription
231
+ ```
232
+
233
+ `CommandStatus.TIMEOUT` means the Gateway did not receive a worker ACK before
234
+ the request deadline. It does not prove the worker did not execute the request.
235
+ V1 does not automatically replay timed-out commands.
236
+
237
+ ## Health
238
+
239
+ Backend applications can combine `services.health()` and `gateway.health()` for
240
+ readiness. `ClusterWorker.health()` reports platform service health plus Redis
241
+ heartbeat and command subscriber state.
242
+
243
+ Health snapshots are for readiness/diagnostics. They are not a scheduler or
244
+ durable recovery mechanism.
245
+
246
+ ## Playground Integration
247
+
248
+ The Playground backend supports distributed mode through environment variables:
249
+
250
+ ```bash
251
+ PLAYGROUND_RUNTIME_PROFILE=distributed
252
+ CUBE_ROOT_DIR=/cube
253
+ CUBE_CLUSTER_NAMESPACE=cube-prod
254
+ CUBE_ROLLOUT_TAG=v1
255
+ CUBE_MYSQL_URL='mysql+asyncmy://cube:secret@mysql:3306/cube?charset=utf8mb4'
256
+ CUBE_REDIS_URL='redis://:secret@redis:6379/0'
257
+ PLAYGROUND_AUTH_SECRET='at-least-32-random-characters'
258
+ ```
259
+
260
+ When this profile is selected, the backend creates distributed `PlatformServices`
261
+ and a `ClusterGateway`, then exposes `services`, `commands`, and `events` to
262
+ application routes. Worker processes still run separately.
263
+
264
+ ## V1 Boundaries
265
+
266
+ The current V1 skeleton intentionally keeps recovery small:
267
+
268
+ - No Redis Streams/List durable command queue.
269
+ - No transactional outbox or event replay.
270
+ - No automatic retry/reconciliation for timed-out commands.
271
+ - No distributed `WarmupSession`; it is rejected in distributed mode.
272
+ - No local fallback when Redis/MySQL/shared workspace is unavailable.
273
+ - No Session-to-Session routing or mailbox.
274
+
275
+ Frontend or application users should handle clear failures by retrying or
276
+ starting a new request. Durable state remains in MySQL and the shared workspace;
277
+ live events are best effort.