octomate 0.0.2__tar.gz

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 (513) hide show
  1. octomate-0.0.2/.dockerignore +11 -0
  2. octomate-0.0.2/.github/checks/changed.py +25 -0
  3. octomate-0.0.2/.github/checks/distributions.py +116 -0
  4. octomate-0.0.2/.github/checks/installed.py +96 -0
  5. octomate-0.0.2/.github/workflows/checks.yml +87 -0
  6. octomate-0.0.2/.github/workflows/pr-title.yml +16 -0
  7. octomate-0.0.2/.github/workflows/release.yml +120 -0
  8. octomate-0.0.2/.gitignore +213 -0
  9. octomate-0.0.2/.release-please-manifest.json +5 -0
  10. octomate-0.0.2/.vscode/launch.json +60 -0
  11. octomate-0.0.2/.vscode/settings.json +31 -0
  12. octomate-0.0.2/AGENTS.md +79 -0
  13. octomate-0.0.2/CHANGELOG.md +301 -0
  14. octomate-0.0.2/Dockerfile +13 -0
  15. octomate-0.0.2/LICENSE +661 -0
  16. octomate-0.0.2/PKG-INFO +575 -0
  17. octomate-0.0.2/README.md +530 -0
  18. octomate-0.0.2/alembic.ini +147 -0
  19. octomate-0.0.2/claude.md +1 -0
  20. octomate-0.0.2/cli/CHANGELOG.md +35 -0
  21. octomate-0.0.2/cli/LICENSE +661 -0
  22. octomate-0.0.2/cli/README.md +26 -0
  23. octomate-0.0.2/cli/octomate_cli/__init__.py +8 -0
  24. octomate-0.0.2/cli/octomate_cli/config.py +281 -0
  25. octomate-0.0.2/cli/octomate_cli/emit.py +153 -0
  26. octomate-0.0.2/cli/octomate_cli/launch.py +146 -0
  27. octomate-0.0.2/cli/octomate_cli/main.py +53 -0
  28. octomate-0.0.2/cli/octomate_cli/serve.py +444 -0
  29. octomate-0.0.2/cli/octomate_cli/streaming/__init__.py +1 -0
  30. octomate-0.0.2/cli/octomate_cli/streaming/deepseek.py +372 -0
  31. octomate-0.0.2/cli/octomate_cli/streaming/files.py +367 -0
  32. octomate-0.0.2/cli/octomate_cli/tentacles/__init__.py +1 -0
  33. octomate-0.0.2/cli/octomate_cli/tentacles/claude/__init__.py +68 -0
  34. octomate-0.0.2/cli/octomate_cli/tentacles/claude/config.py +24 -0
  35. octomate-0.0.2/cli/octomate_cli/tentacles/claude/hooks.py +283 -0
  36. octomate-0.0.2/cli/octomate_cli/tentacles/claude/mcp.py +179 -0
  37. octomate-0.0.2/cli/octomate_cli/tentacles/codex/__init__.py +83 -0
  38. octomate-0.0.2/cli/octomate_cli/tentacles/codex/hooks.py +231 -0
  39. octomate-0.0.2/cli/octomate_cli/tentacles/codex/mcp.py +127 -0
  40. octomate-0.0.2/cli/octomate_cli/tentacles/deepseek/__init__.py +97 -0
  41. octomate-0.0.2/cli/octomate_cli/tentacles/deepseek/config.py +88 -0
  42. octomate-0.0.2/cli/octomate_cli/tentacles/deepseek/hooks.py +254 -0
  43. octomate-0.0.2/cli/octomate_cli/tentacles/deepseek/mcp.py +148 -0
  44. octomate-0.0.2/cli/octomate_cli/tentacles/hooks.py +34 -0
  45. octomate-0.0.2/cli/octomate_cli/tentacles/mcp.py +65 -0
  46. octomate-0.0.2/cli/octomate_cli/tentacles/types.py +12 -0
  47. octomate-0.0.2/cli/pyproject.toml +35 -0
  48. octomate-0.0.2/docker-compose.yml +54 -0
  49. octomate-0.0.2/docs/deepseek-tentacle.md +167 -0
  50. octomate-0.0.2/docs/discord.md +127 -0
  51. octomate-0.0.2/docs/releases.md +133 -0
  52. octomate-0.0.2/docs/schemas.md +127 -0
  53. octomate-0.0.2/docs/server-deployment.md +426 -0
  54. octomate-0.0.2/docs/template/issue.md +69 -0
  55. octomate-0.0.2/docs/template/project.md +101 -0
  56. octomate-0.0.2/docs/workspaces.md +477 -0
  57. octomate-0.0.2/octomate/__init__.py +25 -0
  58. octomate-0.0.2/octomate/app.py +172 -0
  59. octomate-0.0.2/octomate/base.py +420 -0
  60. octomate-0.0.2/octomate/capabilities/__init__.py +42 -0
  61. octomate-0.0.2/octomate/capabilities/ask.py +47 -0
  62. octomate-0.0.2/octomate/capabilities/gateway.py +689 -0
  63. octomate-0.0.2/octomate/capabilities/harness/__init__.py +22 -0
  64. octomate-0.0.2/octomate/capabilities/harness/agent.py +358 -0
  65. octomate-0.0.2/octomate/capabilities/harness/deferred.py +141 -0
  66. octomate-0.0.2/octomate/capabilities/harness/events.py +301 -0
  67. octomate-0.0.2/octomate/capabilities/harness/react.py +624 -0
  68. octomate-0.0.2/octomate/capabilities/history.py +177 -0
  69. octomate-0.0.2/octomate/capabilities/mcp.py +115 -0
  70. octomate-0.0.2/octomate/capabilities/todos.py +384 -0
  71. octomate-0.0.2/octomate/capabilities/tools.py +53 -0
  72. octomate-0.0.2/octomate/config/__init__.py +140 -0
  73. octomate-0.0.2/octomate/config/agents.py +613 -0
  74. octomate-0.0.2/octomate/config/base.py +309 -0
  75. octomate-0.0.2/octomate/config/channels.py +284 -0
  76. octomate-0.0.2/octomate/config/database.py +60 -0
  77. octomate-0.0.2/octomate/config/defaults/agents.yaml +148 -0
  78. octomate-0.0.2/octomate/config/defaults/channels.yaml +73 -0
  79. octomate-0.0.2/octomate/config/defaults/mcp.yaml +31 -0
  80. octomate-0.0.2/octomate/config/defaults/oauth.yaml +8 -0
  81. octomate-0.0.2/octomate/config/defaults/observability.yaml +26 -0
  82. octomate-0.0.2/octomate/config/defaults/octomate.yaml +24 -0
  83. octomate-0.0.2/octomate/config/defaults/projects.yaml +12 -0
  84. octomate-0.0.2/octomate/config/defaults/providers.yaml +26 -0
  85. octomate-0.0.2/octomate/config/defaults/users.yaml +21 -0
  86. octomate-0.0.2/octomate/config/mcp/__init__.py +38 -0
  87. octomate-0.0.2/octomate/config/mcp/base.py +58 -0
  88. octomate-0.0.2/octomate/config/mcp/github.py +72 -0
  89. octomate-0.0.2/octomate/config/mcp/linear.py +52 -0
  90. octomate-0.0.2/octomate/config/mirrors.py +53 -0
  91. octomate-0.0.2/octomate/config/models.py +88 -0
  92. octomate-0.0.2/octomate/config/oauth.py +15 -0
  93. octomate-0.0.2/octomate/config/observability.py +54 -0
  94. octomate-0.0.2/octomate/config/projects.py +11 -0
  95. octomate-0.0.2/octomate/config/providers.py +78 -0
  96. octomate-0.0.2/octomate/config/users.py +63 -0
  97. octomate-0.0.2/octomate/config/workspaces.py +29 -0
  98. octomate-0.0.2/octomate/database.py +78 -0
  99. octomate-0.0.2/octomate/deployment.py +236 -0
  100. octomate-0.0.2/octomate/managers/__init__.py +17 -0
  101. octomate-0.0.2/octomate/managers/conversation.py +555 -0
  102. octomate-0.0.2/octomate/managers/deferred.py +214 -0
  103. octomate-0.0.2/octomate/managers/gateway.py +833 -0
  104. octomate-0.0.2/octomate/managers/oauth.py +746 -0
  105. octomate-0.0.2/octomate/managers/project.py +172 -0
  106. octomate-0.0.2/octomate/managers/spills.py +74 -0
  107. octomate-0.0.2/octomate/managers/thread.py +843 -0
  108. octomate-0.0.2/octomate/managers/todos.py +157 -0
  109. octomate-0.0.2/octomate/managers/user.py +322 -0
  110. octomate-0.0.2/octomate/managers/workspaces/__init__.py +24 -0
  111. octomate-0.0.2/octomate/managers/workspaces/base.py +869 -0
  112. octomate-0.0.2/octomate/managers/workspaces/dependencies.py +174 -0
  113. octomate-0.0.2/octomate/managers/workspaces/mirrors.py +251 -0
  114. octomate-0.0.2/octomate/mcp/__init__.py +8 -0
  115. octomate-0.0.2/octomate/mcp/base.py +62 -0
  116. octomate-0.0.2/octomate/mcp/gateway.py +357 -0
  117. octomate-0.0.2/octomate/mcp/history.py +133 -0
  118. octomate-0.0.2/octomate/mcp/oauth.py +214 -0
  119. octomate-0.0.2/octomate/mcp/server.py +146 -0
  120. octomate-0.0.2/octomate/migrations/README +1 -0
  121. octomate-0.0.2/octomate/migrations/alembic.ini +2 -0
  122. octomate-0.0.2/octomate/migrations/env.py +102 -0
  123. octomate-0.0.2/octomate/migrations/script.py.mako +28 -0
  124. octomate-0.0.2/octomate/migrations/versions/2026_07_03_1215-924f7e1ce5ac_initial_schema.py +590 -0
  125. octomate-0.0.2/octomate/migrations/versions/2026_07_15_1530-7a3e9c1b2f8d_external_agent_run_variant.py +73 -0
  126. octomate-0.0.2/octomate/migrations/versions/2026_07_17_0330-3f1c8ad42b91_thread_message_happened_at_orders_the_ledger.py +65 -0
  127. octomate-0.0.2/octomate/migrations/versions/2026_07_17_2303-417719624acf_subagent_run_tree.py +174 -0
  128. octomate-0.0.2/octomate/migrations/versions/2026_07_24_2337-f4a6f02876d3_user_identity_registry.py +230 -0
  129. octomate-0.0.2/octomate/migrations/versions/2026_07_26_2009-c38113f96d69_github_oauth_connections.py +107 -0
  130. octomate-0.0.2/octomate/migrations/versions/2026_07_31_1100-a7c31d9e5b48_authorization_code_operations.py +44 -0
  131. octomate-0.0.2/octomate/migrations/versions/2026_07_31_2054-e51c06d4b57c_tool_output_spill_store.py +48 -0
  132. octomate-0.0.2/octomate/migrations/versions/2026_08_04_2316-f1abd4106ca7_project_registry.py +68 -0
  133. octomate-0.0.2/octomate/migrations/versions/2026_08_05_2023-c4e2a91d0f38_project_dispatch.py +66 -0
  134. octomate-0.0.2/octomate/migrations/versions/2026_08_08_2042-9c2b7f4e13da_thread_kind_and_dm_chat_type.py +154 -0
  135. octomate-0.0.2/octomate/migrations/versions/2026_08_09_1442-c5917a21ede4_where_work_happens.py +70 -0
  136. octomate-0.0.2/octomate/migrations/versions/2026_08_10_2233-1bad2a5f6be5_disable_a_project_whose_root_is_gone.py +47 -0
  137. octomate-0.0.2/octomate/migrations/versions/2026_08_11_2010-02823d5dcce5_per_agent_permission_modes.py +108 -0
  138. octomate-0.0.2/octomate/migrations/versions/2026_08_18_1852-f54a9afc1e44_give_project_an_upstream.py +65 -0
  139. octomate-0.0.2/octomate/migrations/versions/2026_08_20_1210-9f541202305d_stop_registering_projects_from_sessions.py +52 -0
  140. octomate-0.0.2/octomate/migrations/versions/2026_08_31_0106-72af5e4bed47_a_user_s_secret_lives_on_their_row.py +61 -0
  141. octomate-0.0.2/octomate/migrations/versions/2026_09_02_0227-bdb96422fcdc_a_thread_and_a_session_carry_a_name.py +87 -0
  142. octomate-0.0.2/octomate/migrations/versions/2026_09_04_0011-1036c4c4f86b_the_handoff_names_its_source_agent.py +81 -0
  143. octomate-0.0.2/octomate/migrations/versions/2026_09_05_0200-0d0112888c17_a_chat_room_kick_works_in_a_sub_thread.py +108 -0
  144. octomate-0.0.2/octomate/models/__init__.py +50 -0
  145. octomate-0.0.2/octomate/models/base.py +56 -0
  146. octomate-0.0.2/octomate/models/conversation.py +130 -0
  147. octomate-0.0.2/octomate/models/deferred.py +168 -0
  148. octomate-0.0.2/octomate/models/messages.py +91 -0
  149. octomate-0.0.2/octomate/models/oauth.py +104 -0
  150. octomate-0.0.2/octomate/models/project.py +73 -0
  151. octomate-0.0.2/octomate/models/runs.py +128 -0
  152. octomate-0.0.2/octomate/models/spills.py +33 -0
  153. octomate-0.0.2/octomate/models/thread.py +427 -0
  154. octomate-0.0.2/octomate/models/todos.py +72 -0
  155. octomate-0.0.2/octomate/models/user.py +102 -0
  156. octomate-0.0.2/octomate/oauth/__init__.py +10 -0
  157. octomate-0.0.2/octomate/oauth/base.py +49 -0
  158. octomate-0.0.2/octomate/oauth/github.py +148 -0
  159. octomate-0.0.2/octomate/oauth/linear.py +214 -0
  160. octomate-0.0.2/octomate/oauth/routes.py +146 -0
  161. octomate-0.0.2/octomate/prompts.py +44 -0
  162. octomate-0.0.2/octomate/providers.py +173 -0
  163. octomate-0.0.2/octomate/reflex/__init__.py +27 -0
  164. octomate-0.0.2/octomate/reflex/crossing.py +78 -0
  165. octomate-0.0.2/octomate/reflex/graph.py +90 -0
  166. octomate-0.0.2/octomate/reflex/nodes/__init__.py +24 -0
  167. octomate-0.0.2/octomate/reflex/nodes/awake.py +113 -0
  168. octomate-0.0.2/octomate/reflex/nodes/handoff.py +132 -0
  169. octomate-0.0.2/octomate/reflex/nodes/react.py +492 -0
  170. octomate-0.0.2/octomate/reflex/nodes/resume_deferred.py +135 -0
  171. octomate-0.0.2/octomate/reflex/nodes/route.py +117 -0
  172. octomate-0.0.2/octomate/reflex/nodes/scheme.py +96 -0
  173. octomate-0.0.2/octomate/reflex/nodes/teleport.py +165 -0
  174. octomate-0.0.2/octomate/reflex/state.py +386 -0
  175. octomate-0.0.2/octomate/reflex/suspender.py +150 -0
  176. octomate-0.0.2/octomate/schemas/__init__.py +41 -0
  177. octomate-0.0.2/octomate/schemas/actions.py +58 -0
  178. octomate-0.0.2/octomate/schemas/awakes.py +68 -0
  179. octomate-0.0.2/octomate/schemas/base.py +3 -0
  180. octomate-0.0.2/octomate/schemas/conversation.py +142 -0
  181. octomate-0.0.2/octomate/schemas/deferred.py +261 -0
  182. octomate-0.0.2/octomate/schemas/events.py +80 -0
  183. octomate-0.0.2/octomate/schemas/messages.py +162 -0
  184. octomate-0.0.2/octomate/schemas/oauth.py +392 -0
  185. octomate-0.0.2/octomate/schemas/project.py +157 -0
  186. octomate-0.0.2/octomate/schemas/runs.py +62 -0
  187. octomate-0.0.2/octomate/schemas/segments.py +200 -0
  188. octomate-0.0.2/octomate/schemas/spills.py +23 -0
  189. octomate-0.0.2/octomate/schemas/thread.py +296 -0
  190. octomate-0.0.2/octomate/schemas/todos.py +42 -0
  191. octomate-0.0.2/octomate/schemas/triage.py +353 -0
  192. octomate-0.0.2/octomate/schemas/user.py +102 -0
  193. octomate-0.0.2/octomate/telemetry.py +32 -0
  194. octomate-0.0.2/octomate/tentacles/__init__.py +0 -0
  195. octomate-0.0.2/octomate/tentacles/agent.py +396 -0
  196. octomate-0.0.2/octomate/tentacles/base.py +98 -0
  197. octomate-0.0.2/octomate/tentacles/channel.py +499 -0
  198. octomate-0.0.2/octomate/tentacles/claude/__init__.py +7 -0
  199. octomate-0.0.2/octomate/tentacles/claude/adapter.py +539 -0
  200. octomate-0.0.2/octomate/tentacles/claude/base.py +1117 -0
  201. octomate-0.0.2/octomate/tentacles/claude/hooks.py +40 -0
  202. octomate-0.0.2/octomate/tentacles/claude/ingest.py +363 -0
  203. octomate-0.0.2/octomate/tentacles/claude/mcp.py +77 -0
  204. octomate-0.0.2/octomate/tentacles/claude/tailer.py +896 -0
  205. octomate-0.0.2/octomate/tentacles/claude/transcript.py +233 -0
  206. octomate-0.0.2/octomate/tentacles/claude/transport.py +90 -0
  207. octomate-0.0.2/octomate/tentacles/codex/__init__.py +11 -0
  208. octomate-0.0.2/octomate/tentacles/codex/adapter.py +794 -0
  209. octomate-0.0.2/octomate/tentacles/codex/base.py +1502 -0
  210. octomate-0.0.2/octomate/tentacles/codex/hooks.py +26 -0
  211. octomate-0.0.2/octomate/tentacles/codex/ingest.py +228 -0
  212. octomate-0.0.2/octomate/tentacles/codex/tailer.py +765 -0
  213. octomate-0.0.2/octomate/tentacles/codex/transcript.py +77 -0
  214. octomate-0.0.2/octomate/tentacles/deepseek/__init__.py +11 -0
  215. octomate-0.0.2/octomate/tentacles/deepseek/adapter.py +502 -0
  216. octomate-0.0.2/octomate/tentacles/deepseek/base.py +1187 -0
  217. octomate-0.0.2/octomate/tentacles/deepseek/client.py +149 -0
  218. octomate-0.0.2/octomate/tentacles/deepseek/hooks.py +36 -0
  219. octomate-0.0.2/octomate/tentacles/deepseek/ingest.py +122 -0
  220. octomate-0.0.2/octomate/tentacles/deepseek/process.py +206 -0
  221. octomate-0.0.2/octomate/tentacles/deepseek/tailer.py +466 -0
  222. octomate-0.0.2/octomate/tentacles/deepseek/wire.py +611 -0
  223. octomate-0.0.2/octomate/tentacles/discord/__init__.py +11 -0
  224. octomate-0.0.2/octomate/tentacles/discord/base.py +199 -0
  225. octomate-0.0.2/octomate/tentacles/discord/chromo.py +235 -0
  226. octomate-0.0.2/octomate/tentacles/discord/feelers/__init__.py +1 -0
  227. octomate-0.0.2/octomate/tentacles/discord/feelers/actions.py +201 -0
  228. octomate-0.0.2/octomate/tentacles/discord/feelers/approvals.py +180 -0
  229. octomate-0.0.2/octomate/tentacles/discord/feelers/oauth.py +49 -0
  230. octomate-0.0.2/octomate/tentacles/discord/feelers/output.py +375 -0
  231. octomate-0.0.2/octomate/tentacles/discord/feelers/questions.py +476 -0
  232. octomate-0.0.2/octomate/tentacles/discord/ink.py +204 -0
  233. octomate-0.0.2/octomate/tentacles/discord/schema.py +14 -0
  234. octomate-0.0.2/octomate/tentacles/feelers/__init__.py +29 -0
  235. octomate-0.0.2/octomate/tentacles/feelers/base.py +127 -0
  236. octomate-0.0.2/octomate/tentacles/feelers/deferred.py +100 -0
  237. octomate-0.0.2/octomate/tentacles/feelers/oauth.py +111 -0
  238. octomate-0.0.2/octomate/tentacles/feelers/output.py +1199 -0
  239. octomate-0.0.2/octomate/tentacles/github/__init__.py +3 -0
  240. octomate-0.0.2/octomate/tentacles/github/base.py +44 -0
  241. octomate-0.0.2/octomate/tentacles/hooks.py +88 -0
  242. octomate-0.0.2/octomate/tentacles/inkling/__init__.py +7 -0
  243. octomate-0.0.2/octomate/tentacles/inkling/base.py +825 -0
  244. octomate-0.0.2/octomate/tentacles/inkling/build.py +114 -0
  245. octomate-0.0.2/octomate/tentacles/inkling/prompts.py +58 -0
  246. octomate-0.0.2/octomate/tentacles/lark/__init__.py +17 -0
  247. octomate-0.0.2/octomate/tentacles/lark/base.py +347 -0
  248. octomate-0.0.2/octomate/tentacles/lark/chromo.py +273 -0
  249. octomate-0.0.2/octomate/tentacles/lark/feelers/__init__.py +13 -0
  250. octomate-0.0.2/octomate/tentacles/lark/feelers/actions.py +12 -0
  251. octomate-0.0.2/octomate/tentacles/lark/feelers/approvals.py +122 -0
  252. octomate-0.0.2/octomate/tentacles/lark/feelers/cards.py +114 -0
  253. octomate-0.0.2/octomate/tentacles/lark/feelers/oauth.py +88 -0
  254. octomate-0.0.2/octomate/tentacles/lark/feelers/output.py +661 -0
  255. octomate-0.0.2/octomate/tentacles/lark/feelers/questions.py +274 -0
  256. octomate-0.0.2/octomate/tentacles/lark/ink.py +553 -0
  257. octomate-0.0.2/octomate/tentacles/lark/schema.py +96 -0
  258. octomate-0.0.2/octomate/tentacles/linear/__init__.py +3 -0
  259. octomate-0.0.2/octomate/tentacles/linear/base.py +52 -0
  260. octomate-0.0.2/octomate/tentacles/locks.py +46 -0
  261. octomate-0.0.2/octomate/tentacles/mcp.py +209 -0
  262. octomate-0.0.2/octomate/tentacles/napcat/__init__.py +15 -0
  263. octomate-0.0.2/octomate/tentacles/napcat/base.py +137 -0
  264. octomate-0.0.2/octomate/tentacles/napcat/chromo.py +95 -0
  265. octomate-0.0.2/octomate/tentacles/napcat/ink.py +133 -0
  266. octomate-0.0.2/octomate/tentacles/napcat/schema.py +249 -0
  267. octomate-0.0.2/octomate/tentacles/slack/__init__.py +5 -0
  268. octomate-0.0.2/octomate/tentacles/slack/base.py +480 -0
  269. octomate-0.0.2/octomate/tentacles/slack/chromo.py +117 -0
  270. octomate-0.0.2/octomate/tentacles/slack/feelers/__init__.py +9 -0
  271. octomate-0.0.2/octomate/tentacles/slack/feelers/actions.py +14 -0
  272. octomate-0.0.2/octomate/tentacles/slack/feelers/approvals.py +223 -0
  273. octomate-0.0.2/octomate/tentacles/slack/feelers/cards.py +25 -0
  274. octomate-0.0.2/octomate/tentacles/slack/feelers/oauth.py +86 -0
  275. octomate-0.0.2/octomate/tentacles/slack/feelers/output.py +762 -0
  276. octomate-0.0.2/octomate/tentacles/slack/feelers/questions.py +327 -0
  277. octomate-0.0.2/octomate/tentacles/slack/ink.py +379 -0
  278. octomate-0.0.2/octomate/tentacles/slack/oauth.py +228 -0
  279. octomate-0.0.2/octomate/tentacles/slack/schema.py +158 -0
  280. octomate-0.0.2/octomate/tentacles/trunkline/__init__.py +15 -0
  281. octomate-0.0.2/octomate/tentacles/trunkline/base.py +591 -0
  282. octomate-0.0.2/octomate/tentacles/trunkline/routes.py +341 -0
  283. octomate-0.0.2/octomate/tentacles/vercel/__init__.py +15 -0
  284. octomate-0.0.2/octomate/tentacles/vercel/base.py +429 -0
  285. octomate-0.0.2/octomate/tentacles/vercel/event_stream.py +159 -0
  286. octomate-0.0.2/octomate/tentacles/vercel/routes.py +96 -0
  287. octomate-0.0.2/octomate/types/conversations.py +8 -0
  288. octomate-0.0.2/octomate/types/deferred.py +35 -0
  289. octomate-0.0.2/octomate/types/json.py +7 -0
  290. octomate-0.0.2/octomate/types/oauth.py +9 -0
  291. octomate-0.0.2/octomate/types/permissions.py +126 -0
  292. octomate-0.0.2/octomate/types/threads.py +35 -0
  293. octomate-0.0.2/octomate/types/todos.py +14 -0
  294. octomate-0.0.2/octomate/utils.py +29 -0
  295. octomate-0.0.2/protocol/CHANGELOG.md +10 -0
  296. octomate-0.0.2/protocol/LICENSE +661 -0
  297. octomate-0.0.2/protocol/README.md +14 -0
  298. octomate-0.0.2/protocol/octomate_protocol/__init__.py +1 -0
  299. octomate-0.0.2/protocol/octomate_protocol/deployment.py +16 -0
  300. octomate-0.0.2/protocol/octomate_protocol/stream.py +105 -0
  301. octomate-0.0.2/protocol/pyproject.toml +21 -0
  302. octomate-0.0.2/pyproject.toml +147 -0
  303. octomate-0.0.2/release-please-config.json +19 -0
  304. octomate-0.0.2/scripts/capture_inkling_events.py +496 -0
  305. octomate-0.0.2/tests/__init__.py +0 -0
  306. octomate-0.0.2/tests/agent/__init__.py +0 -0
  307. octomate-0.0.2/tests/agent/test_capability_parity.py +262 -0
  308. octomate-0.0.2/tests/agent/test_claude_adapter.py +559 -0
  309. octomate-0.0.2/tests/agent/test_claude_approval.py +504 -0
  310. octomate-0.0.2/tests/agent/test_claude_hook_ingest.py +375 -0
  311. octomate-0.0.2/tests/agent/test_claude_launch.py +237 -0
  312. octomate-0.0.2/tests/agent/test_claude_mcp.py +162 -0
  313. octomate-0.0.2/tests/agent/test_claude_session_relocation.py +64 -0
  314. octomate-0.0.2/tests/agent/test_claude_stream.py +402 -0
  315. octomate-0.0.2/tests/agent/test_claude_tail_client.py +222 -0
  316. octomate-0.0.2/tests/agent/test_claude_tailer.py +1066 -0
  317. octomate-0.0.2/tests/agent/test_claude_tentacle.py +767 -0
  318. octomate-0.0.2/tests/agent/test_claude_transport.py +77 -0
  319. octomate-0.0.2/tests/agent/test_codex_adapter.py +838 -0
  320. octomate-0.0.2/tests/agent/test_codex_emit.py +328 -0
  321. octomate-0.0.2/tests/agent/test_codex_native_ingest.py +638 -0
  322. octomate-0.0.2/tests/agent/test_codex_stream.py +460 -0
  323. octomate-0.0.2/tests/agent/test_codex_tentacle.py +1422 -0
  324. octomate-0.0.2/tests/agent/test_commission.py +314 -0
  325. octomate-0.0.2/tests/agent/test_conversation_manager.py +807 -0
  326. octomate-0.0.2/tests/agent/test_deepseek_adapter.py +420 -0
  327. octomate-0.0.2/tests/agent/test_deepseek_native_ingest.py +401 -0
  328. octomate-0.0.2/tests/agent/test_deepseek_process.py +130 -0
  329. octomate-0.0.2/tests/agent/test_deepseek_stream.py +212 -0
  330. octomate-0.0.2/tests/agent/test_deepseek_tail_client.py +135 -0
  331. octomate-0.0.2/tests/agent/test_deepseek_tentacle.py +1018 -0
  332. octomate-0.0.2/tests/agent/test_deepseek_wire.py +407 -0
  333. octomate-0.0.2/tests/agent/test_deferred_actions.py +204 -0
  334. octomate-0.0.2/tests/agent/test_dispatch.py +779 -0
  335. octomate-0.0.2/tests/agent/test_events.py +97 -0
  336. octomate-0.0.2/tests/agent/test_gateway.py +983 -0
  337. octomate-0.0.2/tests/agent/test_gateway_tools.py +580 -0
  338. octomate-0.0.2/tests/agent/test_history.py +386 -0
  339. octomate-0.0.2/tests/agent/test_hook_auth.py +112 -0
  340. octomate-0.0.2/tests/agent/test_inkling.py +888 -0
  341. octomate-0.0.2/tests/agent/test_inkling_project_context.py +323 -0
  342. octomate-0.0.2/tests/agent/test_mcp.py +494 -0
  343. octomate-0.0.2/tests/agent/test_mcp_serving.py +406 -0
  344. octomate-0.0.2/tests/agent/test_permissions.py +88 -0
  345. octomate-0.0.2/tests/agent/test_project_dispatch.py +464 -0
  346. octomate-0.0.2/tests/agent/test_project_spells.py +346 -0
  347. octomate-0.0.2/tests/agent/test_react_graph.py +614 -0
  348. octomate-0.0.2/tests/agent/test_reflex_graph.py +2365 -0
  349. octomate-0.0.2/tests/agent/test_run_working_directory.py +442 -0
  350. octomate-0.0.2/tests/agent/test_send.py +380 -0
  351. octomate-0.0.2/tests/agent/test_session_project_attribution.py +371 -0
  352. octomate-0.0.2/tests/agent/test_stream_normalizer.py +240 -0
  353. octomate-0.0.2/tests/agent/test_suspender.py +141 -0
  354. octomate-0.0.2/tests/agent/test_thread.py +308 -0
  355. octomate-0.0.2/tests/agent/test_thread_kind.py +203 -0
  356. octomate-0.0.2/tests/agent/test_thread_manager.py +763 -0
  357. octomate-0.0.2/tests/agent/test_todo_manager.py +82 -0
  358. octomate-0.0.2/tests/agent/test_todos.py +180 -0
  359. octomate-0.0.2/tests/agent/test_tool_failure.py +87 -0
  360. octomate-0.0.2/tests/agent/test_tool_output_config.py +195 -0
  361. octomate-0.0.2/tests/agent/test_tool_output_limits.py +152 -0
  362. octomate-0.0.2/tests/channels/__init__.py +0 -0
  363. octomate-0.0.2/tests/channels/discord/__init__.py +0 -0
  364. octomate-0.0.2/tests/channels/discord/fakes.py +117 -0
  365. octomate-0.0.2/tests/channels/discord/test_base.py +377 -0
  366. octomate-0.0.2/tests/channels/discord/test_chromo.py +188 -0
  367. octomate-0.0.2/tests/channels/discord/test_feelers.py +766 -0
  368. octomate-0.0.2/tests/channels/discord/test_ink.py +468 -0
  369. octomate-0.0.2/tests/channels/discord/test_streaming.py +382 -0
  370. octomate-0.0.2/tests/channels/lark/__init__.py +0 -0
  371. octomate-0.0.2/tests/channels/lark/fakes.py +220 -0
  372. octomate-0.0.2/tests/channels/lark/test_chromo.py +360 -0
  373. octomate-0.0.2/tests/channels/lark/test_feelers.py +383 -0
  374. octomate-0.0.2/tests/channels/lark/test_ink.py +219 -0
  375. octomate-0.0.2/tests/channels/lark/test_streaming.py +491 -0
  376. octomate-0.0.2/tests/channels/napcat/__init__.py +0 -0
  377. octomate-0.0.2/tests/channels/napcat/fakes.py +23 -0
  378. octomate-0.0.2/tests/channels/napcat/test_chromo.py +181 -0
  379. octomate-0.0.2/tests/channels/napcat/test_ink.py +275 -0
  380. octomate-0.0.2/tests/channels/slack/__init__.py +0 -0
  381. octomate-0.0.2/tests/channels/slack/fakes.py +358 -0
  382. octomate-0.0.2/tests/channels/slack/test_chromo.py +88 -0
  383. octomate-0.0.2/tests/channels/slack/test_dispatch.py +169 -0
  384. octomate-0.0.2/tests/channels/slack/test_feelers.py +724 -0
  385. octomate-0.0.2/tests/channels/slack/test_ink.py +71 -0
  386. octomate-0.0.2/tests/channels/slack/test_mcp.py +431 -0
  387. octomate-0.0.2/tests/channels/slack/test_oauth.py +199 -0
  388. octomate-0.0.2/tests/channels/slack/test_streaming.py +658 -0
  389. octomate-0.0.2/tests/channels/test_base.py +814 -0
  390. octomate-0.0.2/tests/channels/test_feelers.py +734 -0
  391. octomate-0.0.2/tests/channels/test_oauth_feelers.py +300 -0
  392. octomate-0.0.2/tests/channels/test_reply_targeting.py +143 -0
  393. octomate-0.0.2/tests/channels/trunkline/__init__.py +0 -0
  394. octomate-0.0.2/tests/channels/trunkline/test_web_app.py +915 -0
  395. octomate-0.0.2/tests/channels/trunkline/test_wire.py +159 -0
  396. octomate-0.0.2/tests/channels/vercel/__init__.py +0 -0
  397. octomate-0.0.2/tests/channels/vercel/test_event_stream.py +255 -0
  398. octomate-0.0.2/tests/channels/vercel/test_web_app.py +271 -0
  399. octomate-0.0.2/tests/config/octomate.yaml +17 -0
  400. octomate-0.0.2/tests/conftest.py +114 -0
  401. octomate-0.0.2/tests/managers/__init__.py +0 -0
  402. octomate-0.0.2/tests/managers/test_oauth.py +946 -0
  403. octomate-0.0.2/tests/managers/test_oauth_routes.py +156 -0
  404. octomate-0.0.2/tests/managers/test_project.py +515 -0
  405. octomate-0.0.2/tests/managers/test_spills.py +101 -0
  406. octomate-0.0.2/tests/managers/test_user.py +576 -0
  407. octomate-0.0.2/tests/managers/workspaces/__init__.py +0 -0
  408. octomate-0.0.2/tests/managers/workspaces/test_dependencies.py +140 -0
  409. octomate-0.0.2/tests/managers/workspaces/test_mirrors.py +402 -0
  410. octomate-0.0.2/tests/managers/workspaces/test_workspaces.py +1124 -0
  411. octomate-0.0.2/tests/oauth/__init__.py +0 -0
  412. octomate-0.0.2/tests/oauth/test_github.py +110 -0
  413. octomate-0.0.2/tests/oauth/test_linear.py +182 -0
  414. octomate-0.0.2/tests/src/README.md +8 -0
  415. octomate-0.0.2/tests/src/events/inkling_segments.jsonl +19 -0
  416. octomate-0.0.2/tests/src/events/inkling_subagents.jsonl +585 -0
  417. octomate-0.0.2/tests/src/events/inkling_text.jsonl +145 -0
  418. octomate-0.0.2/tests/src/images/usagi.jpg +0 -0
  419. octomate-0.0.2/tests/support/__init__.py +0 -0
  420. octomate-0.0.2/tests/support/agents.py +608 -0
  421. octomate-0.0.2/tests/support/channels.py +515 -0
  422. octomate-0.0.2/tests/support/config.py +52 -0
  423. octomate-0.0.2/tests/support/dependencies.py +51 -0
  424. octomate-0.0.2/tests/support/managers.py +573 -0
  425. octomate-0.0.2/tests/support/scenarios.py +742 -0
  426. octomate-0.0.2/tests/test_bearers.py +92 -0
  427. octomate-0.0.2/tests/test_cli.py +1079 -0
  428. octomate-0.0.2/tests/test_config.py +1283 -0
  429. octomate-0.0.2/tests/test_database.py +63 -0
  430. octomate-0.0.2/tests/test_deployment.py +199 -0
  431. octomate-0.0.2/tests/test_prompts.py +32 -0
  432. octomate-0.0.2/tests/test_protocol_compatibility.py +22 -0
  433. octomate-0.0.2/tests/test_providers.py +227 -0
  434. octomate-0.0.2/tests/test_segments.py +119 -0
  435. octomate-0.0.2/tests/test_server_cli.py +495 -0
  436. octomate-0.0.2/tests/test_tentacle_styles.py +38 -0
  437. octomate-0.0.2/tests/trigger/__init__.py +0 -0
  438. octomate-0.0.2/tests/trigger/conftest.py +185 -0
  439. octomate-0.0.2/tests/trigger/test_discord.py +295 -0
  440. octomate-0.0.2/tests/trigger/test_lark.py +187 -0
  441. octomate-0.0.2/tests/trigger/test_napcat.py +119 -0
  442. octomate-0.0.2/tests/trigger/test_slack.py +197 -0
  443. octomate-0.0.2/trunkline/.gitignore +24 -0
  444. octomate-0.0.2/trunkline/.oxlintrc.json +8 -0
  445. octomate-0.0.2/trunkline/DESIGN.md +122 -0
  446. octomate-0.0.2/trunkline/PRODUCT.md +80 -0
  447. octomate-0.0.2/trunkline/README.md +169 -0
  448. octomate-0.0.2/trunkline/index.html +30 -0
  449. octomate-0.0.2/trunkline/package.json +29 -0
  450. octomate-0.0.2/trunkline/pnpm-lock.yaml +2739 -0
  451. octomate-0.0.2/trunkline/public/favicon.svg +9 -0
  452. octomate-0.0.2/trunkline/public/fonts/FiraCode-400-latin-ext.woff2 +0 -0
  453. octomate-0.0.2/trunkline/public/fonts/FiraCode-400-latin.woff2 +0 -0
  454. octomate-0.0.2/trunkline/public/fonts/FiraCode-500-latin-ext.woff2 +0 -0
  455. octomate-0.0.2/trunkline/public/fonts/FiraCode-500-latin.woff2 +0 -0
  456. octomate-0.0.2/trunkline/public/fonts/FiraCode-700-latin-ext.woff2 +0 -0
  457. octomate-0.0.2/trunkline/public/fonts/FiraCode-700-latin.woff2 +0 -0
  458. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-400-latin-ext.woff2 +0 -0
  459. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-400-latin.woff2 +0 -0
  460. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-500-latin-ext.woff2 +0 -0
  461. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-500-latin.woff2 +0 -0
  462. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-700-latin-ext.woff2 +0 -0
  463. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-700-latin.woff2 +0 -0
  464. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-900-latin-ext.woff2 +0 -0
  465. octomate-0.0.2/trunkline/public/fonts/NotoSerifSC-900-latin.woff2 +0 -0
  466. octomate-0.0.2/trunkline/public/fonts/Novecentosanswide-DemiBold.otf +0 -0
  467. octomate-0.0.2/trunkline/public/fonts/Novecentosanswide-Light.otf +0 -0
  468. octomate-0.0.2/trunkline/public/fonts/Novecentosanswide-Normal.otf +0 -0
  469. octomate-0.0.2/trunkline/public/fonts/PlusJakartaSans.woff2 +0 -0
  470. octomate-0.0.2/trunkline/src/App.tsx +39 -0
  471. octomate-0.0.2/trunkline/src/components/BarChart.tsx +73 -0
  472. octomate-0.0.2/trunkline/src/components/Button.tsx +57 -0
  473. octomate-0.0.2/trunkline/src/components/Fold.tsx +19 -0
  474. octomate-0.0.2/trunkline/src/components/Icon.tsx +163 -0
  475. octomate-0.0.2/trunkline/src/components/Markdown.tsx +21 -0
  476. octomate-0.0.2/trunkline/src/components/TriStripe.tsx +23 -0
  477. octomate-0.0.2/trunkline/src/components/text.ts +55 -0
  478. octomate-0.0.2/trunkline/src/features/chat/ChatHeader.tsx +182 -0
  479. octomate-0.0.2/trunkline/src/features/chat/ChatLog.tsx +102 -0
  480. octomate-0.0.2/trunkline/src/features/chat/ChatMain.tsx +56 -0
  481. octomate-0.0.2/trunkline/src/features/chat/Composer.tsx +537 -0
  482. octomate-0.0.2/trunkline/src/features/chat/NewThreadStrip.tsx +171 -0
  483. octomate-0.0.2/trunkline/src/features/chat/ProjectStrip.tsx +127 -0
  484. octomate-0.0.2/trunkline/src/features/chat/SessionBar.tsx +138 -0
  485. octomate-0.0.2/trunkline/src/features/chat/cards.tsx +1088 -0
  486. octomate-0.0.2/trunkline/src/features/chat/runtime.tsx +67 -0
  487. octomate-0.0.2/trunkline/src/features/control/ControlPage.tsx +479 -0
  488. octomate-0.0.2/trunkline/src/features/control/ControlRail.tsx +180 -0
  489. octomate-0.0.2/trunkline/src/features/review/ReviewPanel.tsx +803 -0
  490. octomate-0.0.2/trunkline/src/features/shell/ConsoleShell.tsx +56 -0
  491. octomate-0.0.2/trunkline/src/features/shell/StatusBar.tsx +149 -0
  492. octomate-0.0.2/trunkline/src/features/threads/ThreadsSidebar.tsx +562 -0
  493. octomate-0.0.2/trunkline/src/features/timeline/TimelinePanel.tsx +753 -0
  494. octomate-0.0.2/trunkline/src/lib/api/client.ts +173 -0
  495. octomate-0.0.2/trunkline/src/lib/api/events.ts +524 -0
  496. octomate-0.0.2/trunkline/src/lib/api/fold.ts +558 -0
  497. octomate-0.0.2/trunkline/src/lib/api/hooks.ts +33 -0
  498. octomate-0.0.2/trunkline/src/lib/api/index.ts +105 -0
  499. octomate-0.0.2/trunkline/src/lib/api/live.ts +438 -0
  500. octomate-0.0.2/trunkline/src/lib/api/types.ts +446 -0
  501. octomate-0.0.2/trunkline/src/lib/queryClient.ts +4 -0
  502. octomate-0.0.2/trunkline/src/lib/useRailDrag.ts +46 -0
  503. octomate-0.0.2/trunkline/src/main.tsx +13 -0
  504. octomate-0.0.2/trunkline/src/state/console.ts +1280 -0
  505. octomate-0.0.2/trunkline/src/styles/console.css +398 -0
  506. octomate-0.0.2/trunkline/src/styles/decorators.css +29 -0
  507. octomate-0.0.2/trunkline/src/styles/lonetrail.css +422 -0
  508. octomate-0.0.2/trunkline/src/styles/motion.css +84 -0
  509. octomate-0.0.2/trunkline/tsconfig.app.json +28 -0
  510. octomate-0.0.2/trunkline/tsconfig.json +7 -0
  511. octomate-0.0.2/trunkline/tsconfig.node.json +23 -0
  512. octomate-0.0.2/trunkline/vite.config.ts +18 -0
  513. octomate-0.0.2/uv.lock +3467 -0
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ **/node_modules/
5
+ web/dist/
6
+ .git/
7
+ .github/
8
+ .vscode/
9
+ .octomate/
10
+ .env
11
+ /octomate.yaml
@@ -0,0 +1,25 @@
1
+ """Check changed Python files without adding unrelated repository cleanup to a PR."""
2
+
3
+ import subprocess
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ base = sys.argv[1]
8
+ command = (
9
+ ["git", "ls-files", "-z"]
10
+ if not base.strip("0")
11
+ else ["git", "diff", "--name-only", "--diff-filter=ACMR", "-z", base, "HEAD"]
12
+ )
13
+ paths = [
14
+ path
15
+ for path in subprocess.check_output(command).decode().split("\0")
16
+ if path.endswith(".py") and Path(path).is_file()
17
+ ]
18
+ if paths:
19
+ subprocess.run(["uvx", "ruff==0.16.4", "check", *paths], check=True)
20
+ subprocess.run(["uvx", "ruff==0.16.4", "format", "--check", *paths], check=True)
21
+ subprocess.run(
22
+ ["uvx", "pyright==1.1.409", "--pythonpath", sys.executable, *paths], check=True
23
+ )
24
+ else:
25
+ print("No changed Python files.")
@@ -0,0 +1,116 @@
1
+ """Rebuild source distributions and exercise wheels in isolated installations."""
2
+
3
+ import subprocess
4
+ import sys
5
+ import tempfile
6
+ import tomllib
7
+ from email import message_from_bytes
8
+ from pathlib import Path
9
+ from zipfile import ZipFile
10
+
11
+ from packaging.requirements import Requirement
12
+
13
+ root = Path(__file__).resolve().parents[2]
14
+ dist = root / "dist"
15
+ projects = [
16
+ tomllib.loads((root / path / "pyproject.toml").read_text())["project"]
17
+ for path in (".", "cli", "protocol")
18
+ ]
19
+ versions = {project["name"]: project["version"] for project in projects}
20
+ assert len(list(dist.glob("*.whl"))) == 3
21
+ assert len(list(dist.glob("*.tar.gz"))) == 3
22
+ for wheel in dist.glob("*.whl"):
23
+ with ZipFile(wheel) as archive:
24
+ metadata_file = next(
25
+ name for name in archive.namelist() if name.endswith("/METADATA")
26
+ )
27
+ metadata = message_from_bytes(archive.read(metadata_file))
28
+ assert metadata["Version"] == versions[metadata["Name"]], wheel
29
+ dependencies = {
30
+ dependency.name: dependency
31
+ for value in metadata.get_all("Requires-Dist", [])
32
+ if (dependency := Requirement(value)).name in versions
33
+ }
34
+ expected = {
35
+ "octomate": {"octomate-cli", "octomate-protocol"},
36
+ "octomate-cli": {"octomate-protocol"},
37
+ "octomate-protocol": set(),
38
+ }
39
+ assert dependencies.keys() == expected[metadata["Name"]], wheel
40
+ for name, dependency in dependencies.items():
41
+ assert versions[name] in dependency.specifier, (wheel, dependency)
42
+ assert all(spec.operator != "==" for spec in dependency.specifier)
43
+ if metadata["Name"] == "octomate":
44
+ assert "octomate/app.py" in archive.namelist()
45
+ assert "octomate/migrations/alembic.ini" in archive.namelist()
46
+ assert any(
47
+ name.startswith("octomate/migrations/versions/")
48
+ for name in archive.namelist()
49
+ )
50
+
51
+ with tempfile.TemporaryDirectory(prefix="octomate-distributions-") as temporary:
52
+ directory = Path(temporary)
53
+ constraints = directory / "constraints.txt"
54
+ subprocess.run(
55
+ [
56
+ "uv",
57
+ "export",
58
+ "--locked",
59
+ "--no-dev",
60
+ "--no-emit-workspace",
61
+ "--no-hashes",
62
+ "--output-file",
63
+ str(constraints),
64
+ ],
65
+ cwd=root,
66
+ check=True,
67
+ stdout=subprocess.DEVNULL,
68
+ )
69
+ for source in sorted(dist.glob("*.tar.gz")):
70
+ subprocess.run(
71
+ [
72
+ "uv",
73
+ "build",
74
+ "--wheel",
75
+ "--no-sources",
76
+ "--out-dir",
77
+ str(directory / "rebuilt"),
78
+ str(source),
79
+ ],
80
+ cwd=directory,
81
+ check=True,
82
+ )
83
+ for mode in ("client", "server"):
84
+ environment = directory / mode
85
+ subprocess.run(
86
+ ["uv", "venv", "--python", sys.executable, str(environment)],
87
+ cwd=directory,
88
+ check=True,
89
+ )
90
+ python = environment / "bin" / "python"
91
+ subprocess.run(
92
+ [
93
+ "uv",
94
+ "pip",
95
+ "install",
96
+ "--python",
97
+ str(python),
98
+ "--constraint",
99
+ str(constraints),
100
+ *[
101
+ str(wheel)
102
+ for wheel in sorted(dist.glob("*.whl"))
103
+ if mode == "server" or not wheel.name.startswith("octomate-")
104
+ ],
105
+ ],
106
+ cwd=directory,
107
+ check=True,
108
+ )
109
+ subprocess.run(
110
+ [str(python), "-I", str(root / ".github/checks/installed.py"), mode],
111
+ cwd=directory,
112
+ check=True,
113
+ )
114
+ print(
115
+ "Verified 3 wheels, 3 source distributions, and isolated client/server installations."
116
+ )
@@ -0,0 +1,96 @@
1
+ """Exercise an installed CLI or server without loading a source checkout."""
2
+
3
+ import importlib.util
4
+ import os
5
+ import socket
6
+ import subprocess
7
+ import sys
8
+ import tempfile
9
+ from pathlib import Path
10
+
11
+ from octomate_protocol import deployment, stream
12
+
13
+ assert "octomate_cli" not in sys.modules
14
+ assert "octomate" not in sys.modules
15
+ assert deployment.DatabaseBackup.__module__ == "octomate_protocol.deployment"
16
+ assert stream.STREAM_PROTOCOL >= 1
17
+ executable = Path(sys.executable).parent / "octomate"
18
+ for command in (["--version"], ["--help"], ["serve", "--help"], ["upgrade", "--help"]):
19
+ subprocess.run([str(executable), *command], check=True, stdout=subprocess.DEVNULL)
20
+
21
+ if sys.argv[1] == "client":
22
+ for package in ("octomate", "fastapi", "uvicorn", "alembic", "sqlalchemy"):
23
+ assert importlib.util.find_spec(package) is None, package
24
+ from octomate_cli.streaming import deepseek, files
25
+
26
+ assert "site-packages" in str(files.__file__)
27
+ assert "site-packages" in str(deepseek.__file__)
28
+ print("Client installation imports both transports without server dependencies.")
29
+ else:
30
+ with tempfile.TemporaryDirectory(prefix="octomate-installed-") as temporary:
31
+ directory = Path(temporary).resolve()
32
+ config = directory / "config"
33
+ config.mkdir()
34
+ (config / "users.yaml").write_text(
35
+ "users:\n tester:\n secret: release-check\n"
36
+ )
37
+ database = directory / "test.sqlite3"
38
+ with socket.socket() as listener:
39
+ listener.bind(("127.0.0.1", 0))
40
+ port = listener.getsockname()[1]
41
+ environment = {
42
+ key: value
43
+ for key, value in os.environ.items()
44
+ if not key.startswith(("OCTOMATE", "PYTHONPATH"))
45
+ }
46
+ environment.update(
47
+ {
48
+ "OCTOMATE_HOME": str(config),
49
+ "OCTOMATE_DB_URL": f"sqlite+aiosqlite:///{database}",
50
+ "OCTOMATE__PORT": str(port),
51
+ }
52
+ )
53
+ command = [sys.executable, "-I", "-m", "octomate.deployment"]
54
+ backup = subprocess.check_output(
55
+ [*command, "backup"], cwd=directory, env=environment, text=True
56
+ )
57
+ resolved = deployment.DatabaseBackup.model_validate_json(backup)
58
+ assert resolved.database == database
59
+ assert resolved.backup is None
60
+ assert database.parent == directory
61
+ assert not database.exists()
62
+ subprocess.run(
63
+ [*command, "migrate"],
64
+ cwd=directory,
65
+ env=environment,
66
+ input=backup,
67
+ text=True,
68
+ check=True,
69
+ )
70
+ assert database.is_file()
71
+ with (directory / "server.log").open("w+") as log:
72
+ server = subprocess.Popen(
73
+ [str(executable), "serve"],
74
+ cwd=directory,
75
+ env=environment,
76
+ stdout=log,
77
+ stderr=log,
78
+ )
79
+ try:
80
+ subprocess.run(
81
+ [*command, "verify"], cwd=directory, env=environment, check=True
82
+ )
83
+ except subprocess.CalledProcessError:
84
+ log.seek(0)
85
+ print(log.read())
86
+ raise
87
+ finally:
88
+ server.terminate()
89
+ try:
90
+ server.wait(timeout=15)
91
+ except subprocess.TimeoutExpired:
92
+ server.kill()
93
+ server.wait()
94
+ print(
95
+ "Installed server started, migrated a disposable database, and passed authenticated MCP verification."
96
+ )
@@ -0,0 +1,87 @@
1
+ name: Checks
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+ workflow_call:
10
+ inputs:
11
+ ref:
12
+ type: string
13
+ required: true
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ lint:
20
+ name: Ruff and types
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ ref: ${{ inputs.ref || github.sha }}
26
+ fetch-depth: 0
27
+ - uses: astral-sh/setup-uv@v10.0.1
28
+ with:
29
+ version: "0.8.13"
30
+ python-version: "3.12"
31
+ enable-cache: true
32
+ - run: uv sync --locked
33
+ - name: Check changed Python files
34
+ env:
35
+ BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before || 'HEAD^' }}
36
+ run: uv run --no-sync python .github/checks/changed.py "$BASE_SHA"
37
+
38
+ test:
39
+ name: Unit tests (Python ${{ matrix.python }})
40
+ runs-on: ubuntu-latest
41
+ strategy:
42
+ fail-fast: false
43
+ matrix:
44
+ python: ["3.12", "3.13"]
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ with:
48
+ ref: ${{ inputs.ref || github.sha }}
49
+ - uses: astral-sh/setup-uv@v10.0.1
50
+ with:
51
+ version: "0.8.13"
52
+ python-version: ${{ matrix.python }}
53
+ enable-cache: true
54
+ - run: uv sync --locked
55
+ - name: Run unit tests
56
+ run: uv run --no-sync pytest -q
57
+
58
+ packages:
59
+ name: Packages (Python ${{ matrix.python }})
60
+ needs: [lint, test]
61
+ runs-on: ubuntu-latest
62
+ strategy:
63
+ fail-fast: false
64
+ matrix:
65
+ python: ["3.12", "3.13"]
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ with:
69
+ ref: ${{ inputs.ref || github.sha }}
70
+ - uses: astral-sh/setup-uv@v10.0.1
71
+ with:
72
+ version: "0.8.13"
73
+ python-version: ${{ matrix.python }}
74
+ enable-cache: true
75
+ - run: uv sync --locked
76
+ - name: Build all distributions
77
+ run: uv build --all-packages --no-sources
78
+ - name: Validate distribution metadata
79
+ run: uvx twine check dist/*
80
+ - name: Test installed packages outside the checkout
81
+ run: uv run --no-sync python .github/checks/distributions.py
82
+ - uses: actions/upload-artifact@v4
83
+ if: matrix.python == '3.13'
84
+ with:
85
+ name: distributions
86
+ path: dist/*
87
+ if-no-files-found: error
@@ -0,0 +1,16 @@
1
+ name: PR title
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, edited, synchronize, reopened]
6
+
7
+ permissions:
8
+ pull-requests: read
9
+
10
+ jobs:
11
+ title:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: amannn/action-semantic-pull-request@v6
15
+ env:
16
+ GITHUB_TOKEN: ${{ github.token }}
@@ -0,0 +1,120 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: release
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ release:
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: write
20
+ pull-requests: write
21
+ issues: write
22
+ outputs:
23
+ created: ${{ steps.release.outputs.releases_created }}
24
+ packages: ${{ steps.packages.outputs.matrix }}
25
+ sha: ${{ steps.release.outputs.sha || steps.release.outputs['cli--sha'] || steps.release.outputs['protocol--sha'] }}
26
+ steps:
27
+ - uses: googleapis/release-please-action@v4
28
+ id: release
29
+ with:
30
+ token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
31
+ config-file: release-please-config.json
32
+ manifest-file: .release-please-manifest.json
33
+ - name: Verify releases share the checked commit
34
+ if: steps.release.outputs.releases_created == 'true'
35
+ env:
36
+ SERVER_SHA: ${{ steps.release.outputs.sha }}
37
+ CLI_SHA: ${{ steps.release.outputs['cli--sha'] }}
38
+ PROTOCOL_SHA: ${{ steps.release.outputs['protocol--sha'] }}
39
+ run: |
40
+ release_sha="${SERVER_SHA:-${CLI_SHA:-$PROTOCOL_SHA}}"
41
+ for sha in "$SERVER_SHA" "$CLI_SHA" "$PROTOCOL_SHA"; do
42
+ if [ -n "$sha" ]; then test "$sha" = "$release_sha"; fi
43
+ done
44
+ - name: Select released packages
45
+ id: packages
46
+ if: steps.release.outputs.releases_created == 'true'
47
+ env:
48
+ SERVER_TAG: ${{ steps.release.outputs.tag_name }}
49
+ CLI_TAG: ${{ steps.release.outputs['cli--tag_name'] }}
50
+ PROTOCOL_TAG: ${{ steps.release.outputs['protocol--tag_name'] }}
51
+ run: |
52
+ matrix=$(jq -cn \
53
+ --arg server "$SERVER_TAG" --arg cli "$CLI_TAG" --arg protocol "$PROTOCOL_TAG" \
54
+ '{include: [
55
+ {package: "protocol", distribution: "octomate_protocol", tag: $protocol},
56
+ {package: "cli", distribution: "octomate_cli", tag: $cli},
57
+ {package: "server", distribution: "octomate", tag: $server}
58
+ ] | map(select(.tag != ""))}')
59
+ echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
60
+ - uses: actions/checkout@v4
61
+ if: steps.release.outputs.prs_created == 'true'
62
+ with:
63
+ ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }}
64
+ token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
65
+ - uses: astral-sh/setup-uv@v10.0.1
66
+ if: steps.release.outputs.prs_created == 'true'
67
+ with:
68
+ version: "0.8.13"
69
+ - name: Synchronize the release PR lockfile
70
+ if: steps.release.outputs.prs_created == 'true'
71
+ run: |
72
+ uv lock
73
+ if ! git diff --quiet -- uv.lock; then
74
+ git config user.name 'github-actions[bot]'
75
+ git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
76
+ git add uv.lock
77
+ git commit -m 'chore: sync release lockfile'
78
+ git push
79
+ fi
80
+
81
+ checks:
82
+ needs: release
83
+ if: needs.release.outputs.created == 'true'
84
+ uses: ./.github/workflows/checks.yml
85
+ with:
86
+ ref: ${{ needs.release.outputs.sha }}
87
+
88
+ publish:
89
+ name: Publish ${{ matrix.package }}
90
+ needs: [release, checks]
91
+ if: needs.release.outputs.created == 'true'
92
+ runs-on: ubuntu-latest
93
+ strategy:
94
+ fail-fast: false
95
+ matrix: ${{ fromJSON(needs.release.outputs.packages) }}
96
+ environment: pypi-${{ matrix.package }}
97
+ permissions:
98
+ contents: write
99
+ id-token: write
100
+ steps:
101
+ - uses: actions/download-artifact@v4
102
+ with:
103
+ name: distributions
104
+ path: dist
105
+ - name: Select package distributions
106
+ env:
107
+ DISTRIBUTION: ${{ matrix.distribution }}
108
+ run: |
109
+ mkdir package
110
+ mv dist/"$DISTRIBUTION"-* package/
111
+ - uses: pypa/gh-action-pypi-publish@release/v1
112
+ with:
113
+ packages-dir: package/
114
+ skip-existing: true
115
+ - name: Attach package to its release
116
+ env:
117
+ GH_TOKEN: ${{ github.token }}
118
+ RELEASE_TAG: ${{ matrix.tag }}
119
+ GH_REPO: ${{ github.repository }}
120
+ run: gh release upload "$RELEASE_TAG" package/* --clobber
@@ -0,0 +1,213 @@
1
+ # Virtual environments
2
+ .venv/
3
+
4
+ # Environments / secrets
5
+ .env
6
+ # Written by `octomate claude mcp install --scope project`; holds the literal bearer.
7
+ /.mcp.json
8
+ # Anchored: a deployment's config home is `.octomate/` below, and an unanchored
9
+ # pattern would also swallow `octomate/config/defaults/octomate.yaml` and
10
+ # `tests/config/octomate.yaml` — both committed, and one of them ships in the wheel.
11
+ # This line covers the pre-config-home file only, and goes with it.
12
+ /octomate.yaml
13
+
14
+ # Github
15
+ .github/prompts/
16
+
17
+ # Octomate runtime data and this checkout's config home
18
+ .octomate/
19
+
20
+ # Agent tooling: local settings, and skills symlinked into a machine's own install
21
+ .claude/
22
+ .codex/
23
+
24
+ # Tarot card images (download manually, see octotools/tarot/resources/README.md)
25
+ octotools/tarot/resources/*/
26
+
27
+ # Byte-compiled / optimized / DLL files
28
+ __pycache__/
29
+ *.py[cod]
30
+ *$py.class
31
+
32
+ # C extensions
33
+ *.so
34
+
35
+ # Distribution / packaging
36
+ .Python
37
+ build/
38
+ develop-eggs/
39
+ dist/
40
+ downloads/
41
+ eggs/
42
+ .eggs/
43
+ # Anchored: the unanchored form swallowed web/src/lib/ (the console's API layer)
44
+ /lib/
45
+ /lib64/
46
+ parts/
47
+ sdist/
48
+ var/
49
+ wheels/
50
+ share/python-wheels/
51
+ *.egg-info/
52
+ .installed.cfg
53
+ *.egg
54
+ MANIFEST
55
+
56
+ # PyInstaller
57
+ *.manifest
58
+ *.spec
59
+
60
+ # Installer logs
61
+ pip-log.txt
62
+ pip-delete-this-directory.txt
63
+
64
+ # Unit test / coverage reports
65
+ htmlcov/
66
+ .tox/
67
+ .nox/
68
+ .coverage
69
+ .coverage.*
70
+ .cache
71
+ nosetests.xml
72
+ coverage.xml
73
+ *.cover
74
+ *.py,cover
75
+ .hypothesis/
76
+ .pytest_cache/
77
+ cover/
78
+
79
+ # Translations
80
+ *.mo
81
+ *.pot
82
+
83
+ # Django stuff:
84
+ *.log
85
+ local_settings.py
86
+ db.sqlite3
87
+ db.sqlite3-journal
88
+
89
+ # Flask stuff:
90
+ instance/
91
+ .webassets-cache
92
+
93
+ # Scrapy stuff:
94
+ .scrapy
95
+
96
+ # Sphinx documentation
97
+ docs/_build/
98
+
99
+ # PyBuilder
100
+ .pybuilder/
101
+ target/
102
+
103
+ # Jupyter Notebook
104
+ .ipynb_checkpoints
105
+
106
+ # IPython
107
+ profile_default/
108
+ ipython_config.py
109
+
110
+ # pyenv
111
+ .python-version
112
+
113
+ # pipenv
114
+ Pipfile.lock
115
+
116
+ # poetry
117
+ poetry.lock
118
+
119
+ # pdm
120
+ .pdm.toml
121
+ .pdm-python
122
+ .pdm-build/
123
+
124
+ # PEP 582
125
+ __pypackages__/
126
+
127
+ # Celery stuff
128
+ celerybeat-schedule
129
+ celerybeat.pid
130
+
131
+ # SageMath parsed files
132
+ *.sage.py
133
+
134
+ # Environments
135
+ .env
136
+ .venv
137
+ env/
138
+ venv/
139
+ ENV/
140
+ env.bak/
141
+ venv.bak/
142
+
143
+ # Spyder project settings
144
+ .spyderproject
145
+ .spyproject
146
+
147
+ # Rope project settings
148
+ .ropeproject
149
+
150
+ # mkdocs documentation
151
+ /site
152
+
153
+ # mypy
154
+ .mypy_cache/
155
+ .dmypy.json
156
+ dmypy.json
157
+
158
+ # Pyre type checker
159
+ .pyre/
160
+
161
+ # pytype static type analyzer
162
+ .pytype/
163
+
164
+ # Cython debug symbols
165
+ cython_debug/
166
+
167
+ # PyCharm
168
+ .idea/
169
+ *.iml
170
+ *.iws
171
+ .idea_modules/
172
+
173
+ # VS Code — shared editor setup is checked in; tasks are each developer's own.
174
+ .vscode/tasks.json
175
+ *.code-workspace
176
+ .history/
177
+
178
+ # Sublime Text
179
+ *.sublime-project
180
+ *.sublime-workspace
181
+
182
+ # Vim
183
+ *.swp
184
+ *.swo
185
+ *~
186
+
187
+ # Emacs
188
+ *~
189
+ \#*\#
190
+ /.emacs.desktop
191
+ /.emacs.desktop.lock
192
+ *.elc
193
+
194
+ # macOS
195
+ .DS_Store
196
+ .AppleDouble
197
+ .LSOverride
198
+ ._*
199
+
200
+ # Windows
201
+ Thumbs.db
202
+ Thumbs.db:encryptable
203
+ ehthumbs.db
204
+ ehthumbs_vista.db
205
+ *.stackdump
206
+ [Dd]esktop.ini
207
+ $RECYCLE.BIN/
208
+ *.lnk
209
+
210
+ # Linux
211
+ .directory
212
+ .Trash-*
213
+ .nfs*
@@ -0,0 +1,5 @@
1
+ {
2
+ ".": "0.0.2",
3
+ "cli": "0.0.2",
4
+ "protocol": "0.0.2"
5
+ }