gobby 0.2.5__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 (383) hide show
  1. gobby/__init__.py +3 -0
  2. gobby/adapters/__init__.py +30 -0
  3. gobby/adapters/base.py +93 -0
  4. gobby/adapters/claude_code.py +276 -0
  5. gobby/adapters/codex.py +1292 -0
  6. gobby/adapters/gemini.py +343 -0
  7. gobby/agents/__init__.py +37 -0
  8. gobby/agents/codex_session.py +120 -0
  9. gobby/agents/constants.py +112 -0
  10. gobby/agents/context.py +362 -0
  11. gobby/agents/definitions.py +133 -0
  12. gobby/agents/gemini_session.py +111 -0
  13. gobby/agents/registry.py +618 -0
  14. gobby/agents/runner.py +968 -0
  15. gobby/agents/session.py +259 -0
  16. gobby/agents/spawn.py +916 -0
  17. gobby/agents/spawners/__init__.py +77 -0
  18. gobby/agents/spawners/base.py +142 -0
  19. gobby/agents/spawners/cross_platform.py +266 -0
  20. gobby/agents/spawners/embedded.py +225 -0
  21. gobby/agents/spawners/headless.py +226 -0
  22. gobby/agents/spawners/linux.py +125 -0
  23. gobby/agents/spawners/macos.py +277 -0
  24. gobby/agents/spawners/windows.py +308 -0
  25. gobby/agents/tty_config.py +319 -0
  26. gobby/autonomous/__init__.py +32 -0
  27. gobby/autonomous/progress_tracker.py +447 -0
  28. gobby/autonomous/stop_registry.py +269 -0
  29. gobby/autonomous/stuck_detector.py +383 -0
  30. gobby/cli/__init__.py +67 -0
  31. gobby/cli/__main__.py +8 -0
  32. gobby/cli/agents.py +529 -0
  33. gobby/cli/artifacts.py +266 -0
  34. gobby/cli/daemon.py +329 -0
  35. gobby/cli/extensions.py +526 -0
  36. gobby/cli/github.py +263 -0
  37. gobby/cli/init.py +53 -0
  38. gobby/cli/install.py +614 -0
  39. gobby/cli/installers/__init__.py +37 -0
  40. gobby/cli/installers/antigravity.py +65 -0
  41. gobby/cli/installers/claude.py +363 -0
  42. gobby/cli/installers/codex.py +192 -0
  43. gobby/cli/installers/gemini.py +294 -0
  44. gobby/cli/installers/git_hooks.py +377 -0
  45. gobby/cli/installers/shared.py +737 -0
  46. gobby/cli/linear.py +250 -0
  47. gobby/cli/mcp.py +30 -0
  48. gobby/cli/mcp_proxy.py +698 -0
  49. gobby/cli/memory.py +304 -0
  50. gobby/cli/merge.py +384 -0
  51. gobby/cli/projects.py +79 -0
  52. gobby/cli/sessions.py +622 -0
  53. gobby/cli/tasks/__init__.py +30 -0
  54. gobby/cli/tasks/_utils.py +658 -0
  55. gobby/cli/tasks/ai.py +1025 -0
  56. gobby/cli/tasks/commits.py +169 -0
  57. gobby/cli/tasks/crud.py +685 -0
  58. gobby/cli/tasks/deps.py +135 -0
  59. gobby/cli/tasks/labels.py +63 -0
  60. gobby/cli/tasks/main.py +273 -0
  61. gobby/cli/tasks/search.py +178 -0
  62. gobby/cli/tui.py +34 -0
  63. gobby/cli/utils.py +513 -0
  64. gobby/cli/workflows.py +927 -0
  65. gobby/cli/worktrees.py +481 -0
  66. gobby/config/__init__.py +129 -0
  67. gobby/config/app.py +551 -0
  68. gobby/config/extensions.py +167 -0
  69. gobby/config/features.py +472 -0
  70. gobby/config/llm_providers.py +98 -0
  71. gobby/config/logging.py +66 -0
  72. gobby/config/mcp.py +346 -0
  73. gobby/config/persistence.py +247 -0
  74. gobby/config/servers.py +141 -0
  75. gobby/config/sessions.py +250 -0
  76. gobby/config/tasks.py +784 -0
  77. gobby/hooks/__init__.py +104 -0
  78. gobby/hooks/artifact_capture.py +213 -0
  79. gobby/hooks/broadcaster.py +243 -0
  80. gobby/hooks/event_handlers.py +723 -0
  81. gobby/hooks/events.py +218 -0
  82. gobby/hooks/git.py +169 -0
  83. gobby/hooks/health_monitor.py +171 -0
  84. gobby/hooks/hook_manager.py +856 -0
  85. gobby/hooks/hook_types.py +575 -0
  86. gobby/hooks/plugins.py +813 -0
  87. gobby/hooks/session_coordinator.py +396 -0
  88. gobby/hooks/verification_runner.py +268 -0
  89. gobby/hooks/webhooks.py +339 -0
  90. gobby/install/claude/commands/gobby/bug.md +51 -0
  91. gobby/install/claude/commands/gobby/chore.md +51 -0
  92. gobby/install/claude/commands/gobby/epic.md +52 -0
  93. gobby/install/claude/commands/gobby/eval.md +235 -0
  94. gobby/install/claude/commands/gobby/feat.md +49 -0
  95. gobby/install/claude/commands/gobby/nit.md +52 -0
  96. gobby/install/claude/commands/gobby/ref.md +52 -0
  97. gobby/install/claude/hooks/HOOK_SCHEMAS.md +632 -0
  98. gobby/install/claude/hooks/hook_dispatcher.py +364 -0
  99. gobby/install/claude/hooks/validate_settings.py +102 -0
  100. gobby/install/claude/hooks-template.json +118 -0
  101. gobby/install/codex/hooks/hook_dispatcher.py +153 -0
  102. gobby/install/codex/prompts/forget.md +7 -0
  103. gobby/install/codex/prompts/memories.md +7 -0
  104. gobby/install/codex/prompts/recall.md +7 -0
  105. gobby/install/codex/prompts/remember.md +13 -0
  106. gobby/install/gemini/hooks/hook_dispatcher.py +268 -0
  107. gobby/install/gemini/hooks-template.json +138 -0
  108. gobby/install/shared/plugins/code_guardian.py +456 -0
  109. gobby/install/shared/plugins/example_notify.py +331 -0
  110. gobby/integrations/__init__.py +10 -0
  111. gobby/integrations/github.py +145 -0
  112. gobby/integrations/linear.py +145 -0
  113. gobby/llm/__init__.py +40 -0
  114. gobby/llm/base.py +120 -0
  115. gobby/llm/claude.py +578 -0
  116. gobby/llm/claude_executor.py +503 -0
  117. gobby/llm/codex.py +322 -0
  118. gobby/llm/codex_executor.py +513 -0
  119. gobby/llm/executor.py +316 -0
  120. gobby/llm/factory.py +34 -0
  121. gobby/llm/gemini.py +258 -0
  122. gobby/llm/gemini_executor.py +339 -0
  123. gobby/llm/litellm.py +287 -0
  124. gobby/llm/litellm_executor.py +303 -0
  125. gobby/llm/resolver.py +499 -0
  126. gobby/llm/service.py +236 -0
  127. gobby/mcp_proxy/__init__.py +29 -0
  128. gobby/mcp_proxy/actions.py +175 -0
  129. gobby/mcp_proxy/daemon_control.py +198 -0
  130. gobby/mcp_proxy/importer.py +436 -0
  131. gobby/mcp_proxy/lazy.py +325 -0
  132. gobby/mcp_proxy/manager.py +798 -0
  133. gobby/mcp_proxy/metrics.py +609 -0
  134. gobby/mcp_proxy/models.py +139 -0
  135. gobby/mcp_proxy/registries.py +215 -0
  136. gobby/mcp_proxy/schema_hash.py +381 -0
  137. gobby/mcp_proxy/semantic_search.py +706 -0
  138. gobby/mcp_proxy/server.py +549 -0
  139. gobby/mcp_proxy/services/__init__.py +0 -0
  140. gobby/mcp_proxy/services/fallback.py +306 -0
  141. gobby/mcp_proxy/services/recommendation.py +224 -0
  142. gobby/mcp_proxy/services/server_mgmt.py +214 -0
  143. gobby/mcp_proxy/services/system.py +72 -0
  144. gobby/mcp_proxy/services/tool_filter.py +231 -0
  145. gobby/mcp_proxy/services/tool_proxy.py +309 -0
  146. gobby/mcp_proxy/stdio.py +565 -0
  147. gobby/mcp_proxy/tools/__init__.py +27 -0
  148. gobby/mcp_proxy/tools/agents.py +1103 -0
  149. gobby/mcp_proxy/tools/artifacts.py +207 -0
  150. gobby/mcp_proxy/tools/hub.py +335 -0
  151. gobby/mcp_proxy/tools/internal.py +337 -0
  152. gobby/mcp_proxy/tools/memory.py +543 -0
  153. gobby/mcp_proxy/tools/merge.py +422 -0
  154. gobby/mcp_proxy/tools/metrics.py +283 -0
  155. gobby/mcp_proxy/tools/orchestration/__init__.py +23 -0
  156. gobby/mcp_proxy/tools/orchestration/cleanup.py +619 -0
  157. gobby/mcp_proxy/tools/orchestration/monitor.py +380 -0
  158. gobby/mcp_proxy/tools/orchestration/orchestrate.py +746 -0
  159. gobby/mcp_proxy/tools/orchestration/review.py +736 -0
  160. gobby/mcp_proxy/tools/orchestration/utils.py +16 -0
  161. gobby/mcp_proxy/tools/session_messages.py +1056 -0
  162. gobby/mcp_proxy/tools/task_dependencies.py +219 -0
  163. gobby/mcp_proxy/tools/task_expansion.py +591 -0
  164. gobby/mcp_proxy/tools/task_github.py +393 -0
  165. gobby/mcp_proxy/tools/task_linear.py +379 -0
  166. gobby/mcp_proxy/tools/task_orchestration.py +77 -0
  167. gobby/mcp_proxy/tools/task_readiness.py +522 -0
  168. gobby/mcp_proxy/tools/task_sync.py +351 -0
  169. gobby/mcp_proxy/tools/task_validation.py +843 -0
  170. gobby/mcp_proxy/tools/tasks/__init__.py +25 -0
  171. gobby/mcp_proxy/tools/tasks/_context.py +112 -0
  172. gobby/mcp_proxy/tools/tasks/_crud.py +516 -0
  173. gobby/mcp_proxy/tools/tasks/_factory.py +176 -0
  174. gobby/mcp_proxy/tools/tasks/_helpers.py +129 -0
  175. gobby/mcp_proxy/tools/tasks/_lifecycle.py +517 -0
  176. gobby/mcp_proxy/tools/tasks/_lifecycle_validation.py +301 -0
  177. gobby/mcp_proxy/tools/tasks/_resolution.py +55 -0
  178. gobby/mcp_proxy/tools/tasks/_search.py +215 -0
  179. gobby/mcp_proxy/tools/tasks/_session.py +125 -0
  180. gobby/mcp_proxy/tools/workflows.py +973 -0
  181. gobby/mcp_proxy/tools/worktrees.py +1264 -0
  182. gobby/mcp_proxy/transports/__init__.py +0 -0
  183. gobby/mcp_proxy/transports/base.py +95 -0
  184. gobby/mcp_proxy/transports/factory.py +44 -0
  185. gobby/mcp_proxy/transports/http.py +139 -0
  186. gobby/mcp_proxy/transports/stdio.py +213 -0
  187. gobby/mcp_proxy/transports/websocket.py +136 -0
  188. gobby/memory/backends/__init__.py +116 -0
  189. gobby/memory/backends/mem0.py +408 -0
  190. gobby/memory/backends/memu.py +485 -0
  191. gobby/memory/backends/null.py +111 -0
  192. gobby/memory/backends/openmemory.py +537 -0
  193. gobby/memory/backends/sqlite.py +304 -0
  194. gobby/memory/context.py +87 -0
  195. gobby/memory/manager.py +1001 -0
  196. gobby/memory/protocol.py +451 -0
  197. gobby/memory/search/__init__.py +66 -0
  198. gobby/memory/search/text.py +127 -0
  199. gobby/memory/viz.py +258 -0
  200. gobby/prompts/__init__.py +13 -0
  201. gobby/prompts/defaults/expansion/system.md +119 -0
  202. gobby/prompts/defaults/expansion/user.md +48 -0
  203. gobby/prompts/defaults/external_validation/agent.md +72 -0
  204. gobby/prompts/defaults/external_validation/external.md +63 -0
  205. gobby/prompts/defaults/external_validation/spawn.md +83 -0
  206. gobby/prompts/defaults/external_validation/system.md +6 -0
  207. gobby/prompts/defaults/features/import_mcp.md +22 -0
  208. gobby/prompts/defaults/features/import_mcp_github.md +17 -0
  209. gobby/prompts/defaults/features/import_mcp_search.md +16 -0
  210. gobby/prompts/defaults/features/recommend_tools.md +32 -0
  211. gobby/prompts/defaults/features/recommend_tools_hybrid.md +35 -0
  212. gobby/prompts/defaults/features/recommend_tools_llm.md +30 -0
  213. gobby/prompts/defaults/features/server_description.md +20 -0
  214. gobby/prompts/defaults/features/server_description_system.md +6 -0
  215. gobby/prompts/defaults/features/task_description.md +31 -0
  216. gobby/prompts/defaults/features/task_description_system.md +6 -0
  217. gobby/prompts/defaults/features/tool_summary.md +17 -0
  218. gobby/prompts/defaults/features/tool_summary_system.md +6 -0
  219. gobby/prompts/defaults/research/step.md +58 -0
  220. gobby/prompts/defaults/validation/criteria.md +47 -0
  221. gobby/prompts/defaults/validation/validate.md +38 -0
  222. gobby/prompts/loader.py +346 -0
  223. gobby/prompts/models.py +113 -0
  224. gobby/py.typed +0 -0
  225. gobby/runner.py +488 -0
  226. gobby/search/__init__.py +23 -0
  227. gobby/search/protocol.py +104 -0
  228. gobby/search/tfidf.py +232 -0
  229. gobby/servers/__init__.py +7 -0
  230. gobby/servers/http.py +636 -0
  231. gobby/servers/models.py +31 -0
  232. gobby/servers/routes/__init__.py +23 -0
  233. gobby/servers/routes/admin.py +416 -0
  234. gobby/servers/routes/dependencies.py +118 -0
  235. gobby/servers/routes/mcp/__init__.py +24 -0
  236. gobby/servers/routes/mcp/hooks.py +135 -0
  237. gobby/servers/routes/mcp/plugins.py +121 -0
  238. gobby/servers/routes/mcp/tools.py +1337 -0
  239. gobby/servers/routes/mcp/webhooks.py +159 -0
  240. gobby/servers/routes/sessions.py +582 -0
  241. gobby/servers/websocket.py +766 -0
  242. gobby/sessions/__init__.py +13 -0
  243. gobby/sessions/analyzer.py +322 -0
  244. gobby/sessions/lifecycle.py +240 -0
  245. gobby/sessions/manager.py +563 -0
  246. gobby/sessions/processor.py +225 -0
  247. gobby/sessions/summary.py +532 -0
  248. gobby/sessions/transcripts/__init__.py +41 -0
  249. gobby/sessions/transcripts/base.py +125 -0
  250. gobby/sessions/transcripts/claude.py +386 -0
  251. gobby/sessions/transcripts/codex.py +143 -0
  252. gobby/sessions/transcripts/gemini.py +195 -0
  253. gobby/storage/__init__.py +21 -0
  254. gobby/storage/agents.py +409 -0
  255. gobby/storage/artifact_classifier.py +341 -0
  256. gobby/storage/artifacts.py +285 -0
  257. gobby/storage/compaction.py +67 -0
  258. gobby/storage/database.py +357 -0
  259. gobby/storage/inter_session_messages.py +194 -0
  260. gobby/storage/mcp.py +680 -0
  261. gobby/storage/memories.py +562 -0
  262. gobby/storage/merge_resolutions.py +550 -0
  263. gobby/storage/migrations.py +860 -0
  264. gobby/storage/migrations_legacy.py +1359 -0
  265. gobby/storage/projects.py +166 -0
  266. gobby/storage/session_messages.py +251 -0
  267. gobby/storage/session_tasks.py +97 -0
  268. gobby/storage/sessions.py +817 -0
  269. gobby/storage/task_dependencies.py +223 -0
  270. gobby/storage/tasks/__init__.py +42 -0
  271. gobby/storage/tasks/_aggregates.py +180 -0
  272. gobby/storage/tasks/_crud.py +449 -0
  273. gobby/storage/tasks/_id.py +104 -0
  274. gobby/storage/tasks/_lifecycle.py +311 -0
  275. gobby/storage/tasks/_manager.py +889 -0
  276. gobby/storage/tasks/_models.py +300 -0
  277. gobby/storage/tasks/_ordering.py +119 -0
  278. gobby/storage/tasks/_path_cache.py +110 -0
  279. gobby/storage/tasks/_queries.py +343 -0
  280. gobby/storage/tasks/_search.py +143 -0
  281. gobby/storage/workflow_audit.py +393 -0
  282. gobby/storage/worktrees.py +547 -0
  283. gobby/sync/__init__.py +29 -0
  284. gobby/sync/github.py +333 -0
  285. gobby/sync/linear.py +304 -0
  286. gobby/sync/memories.py +284 -0
  287. gobby/sync/tasks.py +641 -0
  288. gobby/tasks/__init__.py +8 -0
  289. gobby/tasks/build_verification.py +193 -0
  290. gobby/tasks/commits.py +633 -0
  291. gobby/tasks/context.py +747 -0
  292. gobby/tasks/criteria.py +342 -0
  293. gobby/tasks/enhanced_validator.py +226 -0
  294. gobby/tasks/escalation.py +263 -0
  295. gobby/tasks/expansion.py +626 -0
  296. gobby/tasks/external_validator.py +764 -0
  297. gobby/tasks/issue_extraction.py +171 -0
  298. gobby/tasks/prompts/expand.py +327 -0
  299. gobby/tasks/research.py +421 -0
  300. gobby/tasks/tdd.py +352 -0
  301. gobby/tasks/tree_builder.py +263 -0
  302. gobby/tasks/validation.py +712 -0
  303. gobby/tasks/validation_history.py +357 -0
  304. gobby/tasks/validation_models.py +89 -0
  305. gobby/tools/__init__.py +0 -0
  306. gobby/tools/summarizer.py +170 -0
  307. gobby/tui/__init__.py +5 -0
  308. gobby/tui/api_client.py +281 -0
  309. gobby/tui/app.py +327 -0
  310. gobby/tui/screens/__init__.py +25 -0
  311. gobby/tui/screens/agents.py +333 -0
  312. gobby/tui/screens/chat.py +450 -0
  313. gobby/tui/screens/dashboard.py +377 -0
  314. gobby/tui/screens/memory.py +305 -0
  315. gobby/tui/screens/metrics.py +231 -0
  316. gobby/tui/screens/orchestrator.py +904 -0
  317. gobby/tui/screens/sessions.py +412 -0
  318. gobby/tui/screens/tasks.py +442 -0
  319. gobby/tui/screens/workflows.py +289 -0
  320. gobby/tui/screens/worktrees.py +174 -0
  321. gobby/tui/widgets/__init__.py +21 -0
  322. gobby/tui/widgets/chat.py +210 -0
  323. gobby/tui/widgets/conductor.py +104 -0
  324. gobby/tui/widgets/menu.py +132 -0
  325. gobby/tui/widgets/message_panel.py +160 -0
  326. gobby/tui/widgets/review_gate.py +224 -0
  327. gobby/tui/widgets/task_tree.py +99 -0
  328. gobby/tui/widgets/token_budget.py +166 -0
  329. gobby/tui/ws_client.py +258 -0
  330. gobby/utils/__init__.py +3 -0
  331. gobby/utils/daemon_client.py +235 -0
  332. gobby/utils/git.py +222 -0
  333. gobby/utils/id.py +38 -0
  334. gobby/utils/json_helpers.py +161 -0
  335. gobby/utils/logging.py +376 -0
  336. gobby/utils/machine_id.py +135 -0
  337. gobby/utils/metrics.py +589 -0
  338. gobby/utils/project_context.py +182 -0
  339. gobby/utils/project_init.py +263 -0
  340. gobby/utils/status.py +256 -0
  341. gobby/utils/validation.py +80 -0
  342. gobby/utils/version.py +23 -0
  343. gobby/workflows/__init__.py +4 -0
  344. gobby/workflows/actions.py +1310 -0
  345. gobby/workflows/approval_flow.py +138 -0
  346. gobby/workflows/artifact_actions.py +103 -0
  347. gobby/workflows/audit_helpers.py +110 -0
  348. gobby/workflows/autonomous_actions.py +286 -0
  349. gobby/workflows/context_actions.py +394 -0
  350. gobby/workflows/definitions.py +130 -0
  351. gobby/workflows/detection_helpers.py +208 -0
  352. gobby/workflows/engine.py +485 -0
  353. gobby/workflows/evaluator.py +669 -0
  354. gobby/workflows/git_utils.py +96 -0
  355. gobby/workflows/hooks.py +169 -0
  356. gobby/workflows/lifecycle_evaluator.py +613 -0
  357. gobby/workflows/llm_actions.py +70 -0
  358. gobby/workflows/loader.py +333 -0
  359. gobby/workflows/mcp_actions.py +60 -0
  360. gobby/workflows/memory_actions.py +272 -0
  361. gobby/workflows/premature_stop.py +164 -0
  362. gobby/workflows/session_actions.py +139 -0
  363. gobby/workflows/state_actions.py +123 -0
  364. gobby/workflows/state_manager.py +104 -0
  365. gobby/workflows/stop_signal_actions.py +163 -0
  366. gobby/workflows/summary_actions.py +344 -0
  367. gobby/workflows/task_actions.py +249 -0
  368. gobby/workflows/task_enforcement_actions.py +901 -0
  369. gobby/workflows/templates.py +52 -0
  370. gobby/workflows/todo_actions.py +84 -0
  371. gobby/workflows/webhook.py +223 -0
  372. gobby/workflows/webhook_executor.py +399 -0
  373. gobby/worktrees/__init__.py +5 -0
  374. gobby/worktrees/git.py +690 -0
  375. gobby/worktrees/merge/__init__.py +20 -0
  376. gobby/worktrees/merge/conflict_parser.py +177 -0
  377. gobby/worktrees/merge/resolver.py +485 -0
  378. gobby-0.2.5.dist-info/METADATA +351 -0
  379. gobby-0.2.5.dist-info/RECORD +383 -0
  380. gobby-0.2.5.dist-info/WHEEL +5 -0
  381. gobby-0.2.5.dist-info/entry_points.txt +2 -0
  382. gobby-0.2.5.dist-info/licenses/LICENSE.md +193 -0
  383. gobby-0.2.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,575 @@
1
+ """
2
+ Hook Type Definitions and Pydantic Models.
3
+
4
+ This module defines all Claude Code hook types and their associated input/output models
5
+ using Pydantic for validation. Each hook type has specific input and output schemas
6
+ that ensure type safety and validation across the hook execution pipeline.
7
+
8
+ Hook Types (13 total):
9
+ 1. session-start: Triggered when a Claude Code session starts
10
+ 2. session-end: Triggered when a session ends
11
+ 3. user-prompt-submit: Triggered before user prompt is submitted
12
+ 4. pre-tool-use: Triggered before a tool is executed
13
+ 5. post-tool-use: Triggered after a tool is executed
14
+ 6. pre-compact: Triggered before context window compaction
15
+ 7. stop: Triggered when agent stops
16
+ 8. subagent-start: Triggered when a subagent starts
17
+ 9. subagent-stop: Triggered when a subagent stops
18
+ 10. notification: Triggered for system notifications
19
+ 11. before-model: Triggered before model inference (Gemini)
20
+ 12. after-model: Triggered after model inference (Gemini)
21
+ 13. permission-request: Triggered when permission is requested (Claude)
22
+
23
+ Example:
24
+ ```python
25
+ from gobby.hooks.hook_types import HookType, SessionStartInput
26
+
27
+ # Validate input
28
+ input_data = SessionStartInput(
29
+ external_id="abc123",
30
+ transcript_path="/path/to/transcript.jsonl",
31
+ source="startup"
32
+ )
33
+ ```
34
+ """
35
+
36
+ from enum import Enum
37
+ from typing import Any
38
+
39
+ from pydantic import BaseModel, ConfigDict, Field
40
+
41
+ # ==================== Enums ====================
42
+
43
+
44
+ class HookType(str, Enum):
45
+ """
46
+ Enumeration of all Claude Code hook types.
47
+
48
+ Each hook type corresponds to a specific lifecycle event in Claude Code.
49
+ Hook names use kebab-case to match Claude Code's hook naming convention.
50
+ """
51
+
52
+ SESSION_START = "session-start"
53
+ """Triggered when a new Claude Code session starts (startup, resume, clear, compact)"""
54
+
55
+ SESSION_END = "session-end"
56
+ """Triggered when a Claude Code session ends (clear, logout, exit)"""
57
+
58
+ USER_PROMPT_SUBMIT = "user-prompt-submit"
59
+ """Triggered before user prompt is submitted for validation/filtering"""
60
+
61
+ PRE_TOOL_USE = "pre-tool-use"
62
+ """Triggered before a tool is executed (for context injection)"""
63
+
64
+ POST_TOOL_USE = "post-tool-use"
65
+ """Triggered after a tool is executed (for memory saving)"""
66
+
67
+ PRE_COMPACT = "pre-compact"
68
+ """Triggered before context window compaction (for summary generation)"""
69
+
70
+ STOP = "stop"
71
+ """Triggered when the main agent stops"""
72
+
73
+ SUBAGENT_START = "subagent-start"
74
+ """Triggered when a subagent (spawned via Task tool) starts"""
75
+
76
+ SUBAGENT_STOP = "subagent-stop"
77
+ """Triggered when a subagent (spawned via Task tool) stops"""
78
+
79
+ NOTIFICATION = "notification"
80
+ """Triggered for system notifications and alerts"""
81
+
82
+ BEFORE_MODEL = "before-model"
83
+ """Triggered before model inference (Gemini only)"""
84
+
85
+ AFTER_MODEL = "after-model"
86
+ """Triggered after model inference (Gemini only)"""
87
+
88
+ PERMISSION_REQUEST = "permission-request"
89
+ """Triggered when permission is requested (Claude only)"""
90
+
91
+
92
+ class SessionStartSource(str, Enum):
93
+ """Source trigger for session start events."""
94
+
95
+ STARTUP = "startup"
96
+ """New session started from scratch"""
97
+
98
+ RESUME = "resume"
99
+ """Session resumed from previous state"""
100
+
101
+ CLEAR = "clear"
102
+ """Session cleared and restarted"""
103
+
104
+ COMPACT = "compact"
105
+ """Session compacted and restarted"""
106
+
107
+
108
+ class SessionEndReason(str, Enum):
109
+ """Reason for session end events."""
110
+
111
+ CLEAR = "clear"
112
+ """User cleared the session"""
113
+
114
+ LOGOUT = "logout"
115
+ """User logged out"""
116
+
117
+ PROMPT_INPUT_EXIT = "prompt_input_exit"
118
+ """User exited from prompt input"""
119
+
120
+ OTHER = "other"
121
+ """Other/unspecified reason"""
122
+
123
+
124
+ class CompactTrigger(str, Enum):
125
+ """Trigger type for context compaction."""
126
+
127
+ AUTO = "auto"
128
+ """Automatic compaction triggered by token limit"""
129
+
130
+ MANUAL = "manual"
131
+ """Manual compaction triggered by user"""
132
+
133
+
134
+ class NotificationSeverity(str, Enum):
135
+ """Severity level for notifications."""
136
+
137
+ INFO = "info"
138
+ """Informational notification"""
139
+
140
+ WARNING = "warning"
141
+ """Warning notification"""
142
+
143
+ ERROR = "error"
144
+ """Error notification"""
145
+
146
+
147
+ # ==================== Base Models ====================
148
+
149
+
150
+ class HookInput(BaseModel):
151
+ """
152
+ Base class for all hook input models.
153
+
154
+ Provides common fields and configuration for hook inputs.
155
+ All hook-specific input models should inherit from this base.
156
+ """
157
+
158
+ model_config = ConfigDict(
159
+ extra="allow", # Allow extra fields for future extensibility
160
+ validate_assignment=True, # Validate on attribute assignment
161
+ str_strip_whitespace=True, # Strip whitespace from strings
162
+ )
163
+
164
+
165
+ class HookOutput(BaseModel):
166
+ """
167
+ Base class for all hook output models.
168
+
169
+ Provides common fields for hook responses.
170
+ All hook-specific output models should inherit from this base.
171
+ """
172
+
173
+ status: str = Field(default="success", description="Execution status (success/error/queued)")
174
+ message: str | None = Field(default=None, description="Optional message or error details")
175
+
176
+ model_config = ConfigDict(
177
+ extra="allow", # Allow extra fields for future extensibility
178
+ validate_assignment=True,
179
+ )
180
+
181
+
182
+ # ==================== Session Start Hook ====================
183
+
184
+
185
+ class SessionStartInput(HookInput):
186
+ """
187
+ Input model for session-start hook.
188
+
189
+ Triggered when a Claude Code session starts. Contains session metadata
190
+ and context about how the session was initiated.
191
+ """
192
+
193
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
194
+ transcript_path: str | None = Field(
195
+ default=None, description="Path to conversation transcript file (Claude Code only)"
196
+ )
197
+ source: SessionStartSource = Field(
198
+ default=SessionStartSource.STARTUP, description="Session start source trigger"
199
+ )
200
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
201
+ cwd: str | None = Field(default=None, description="Current working directory")
202
+
203
+
204
+ class SessionStartOutput(HookOutput):
205
+ """
206
+ Output model for session-start hook.
207
+
208
+ Returns session context to inject into Claude Code (if any).
209
+ """
210
+
211
+ context: dict[str, Any] = Field(default_factory=dict, description="Session context to inject")
212
+
213
+
214
+ # ==================== Session End Hook ====================
215
+
216
+
217
+ class SessionEndInput(HookInput):
218
+ """Input model for session-end hook."""
219
+
220
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
221
+ reason: SessionEndReason = Field(
222
+ default=SessionEndReason.OTHER, description="Reason for session end"
223
+ )
224
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
225
+
226
+
227
+ class SessionEndOutput(HookOutput):
228
+ """Output model for session-end hook."""
229
+
230
+ pass # Uses base HookOutput fields only
231
+
232
+
233
+ # ==================== User Prompt Submit Hook ====================
234
+
235
+
236
+ class UserPromptSubmitInput(HookInput):
237
+ """
238
+ Input model for user-prompt-submit hook.
239
+
240
+ Triggered before user prompt is submitted for validation/filtering.
241
+ Can be used for cost estimation, content filtering, or rate limiting.
242
+ """
243
+
244
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
245
+ prompt_text: str = Field(..., min_length=1, description="User's prompt text to validate")
246
+ estimated_tokens: int | None = Field(default=None, ge=0, description="Estimated token count")
247
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
248
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
249
+
250
+
251
+ class UserPromptSubmitOutput(HookOutput):
252
+ """
253
+ Output model for user-prompt-submit hook.
254
+
255
+ Returns validation result with allow/block decision.
256
+ """
257
+
258
+ allowed: bool = Field(default=True, description="Whether prompt is allowed to proceed")
259
+ block_message: str | None = Field(
260
+ default=None, description="Message to show user if blocked (required if allowed=False)"
261
+ )
262
+
263
+
264
+ # ==================== Pre-Tool-Use Hook ====================
265
+
266
+
267
+ class PreToolUseInput(HookInput):
268
+ """
269
+ Input model for pre-tool-use hook.
270
+
271
+ Triggered before a tool is executed. Can be used to inject relevant context
272
+ based on the tool being used.
273
+ """
274
+
275
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
276
+ tool_name: str = Field(..., min_length=1, description="Name of tool about to be used")
277
+ tool_input: dict[str, Any] = Field(default_factory=dict, description="Tool input parameters")
278
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
279
+
280
+
281
+ class ContextItem(BaseModel):
282
+ """A single context item to inject before tool execution."""
283
+
284
+ type: str = Field(
285
+ ..., min_length=1, description="Context item type (e.g., 'text', 'code', 'memory')"
286
+ )
287
+ content: str = Field(..., min_length=1, description="Context content")
288
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
289
+
290
+ model_config = ConfigDict(extra="allow")
291
+
292
+
293
+ class PreToolUseOutput(HookOutput):
294
+ """
295
+ Output model for pre-tool-use hook.
296
+
297
+ Returns context items to inject before tool execution.
298
+ """
299
+
300
+ items: list[ContextItem] = Field(default_factory=list, description="Context items to inject")
301
+
302
+
303
+ # ==================== Post-Tool-Use Hook ====================
304
+
305
+
306
+ class PostToolUseInput(HookInput):
307
+ """
308
+ Input model for post-tool-use hook.
309
+
310
+ Triggered after a tool is executed. Can be used to save execution context
311
+ for future retrieval.
312
+ """
313
+
314
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
315
+ tool_name: str = Field(..., min_length=1, description="Name of tool that was executed")
316
+ tool_input: dict[str, Any] = Field(default_factory=dict, description="Tool input parameters")
317
+ transcript_path: str | None = Field(default=None, description="Path to transcript file")
318
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
319
+
320
+
321
+ class PostToolUseOutput(HookOutput):
322
+ """
323
+ Output model for post-tool-use hook.
324
+
325
+ Fire-and-forget acknowledgment.
326
+ """
327
+
328
+ pass # Uses base HookOutput fields (status="queued" typical)
329
+
330
+
331
+ # ==================== Pre-Compact Hook ====================
332
+
333
+
334
+ class PreCompactInput(HookInput):
335
+ """
336
+ Input model for pre-compact hook.
337
+
338
+ Triggered before context window compaction. Can be used to generate
339
+ summaries or save compaction checkpoints.
340
+ """
341
+
342
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
343
+ transcript_path: str = Field(..., min_length=1, description="Path to conversation transcript")
344
+ trigger: CompactTrigger = Field(
345
+ default=CompactTrigger.AUTO, description="Compaction trigger type"
346
+ )
347
+ custom_instructions: str | None = Field(
348
+ default=None, description="Custom instructions if manually triggered"
349
+ )
350
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
351
+
352
+
353
+ class PreCompactOutput(HookOutput):
354
+ """
355
+ Output model for pre-compact hook.
356
+
357
+ Returns summary data for compaction.
358
+ """
359
+
360
+ summary: dict[str, Any] = Field(default_factory=dict, description="Summary data for compaction")
361
+
362
+
363
+ # ==================== Stop Hook ====================
364
+
365
+
366
+ class StopInput(HookInput):
367
+ """
368
+ Input model for stop hook.
369
+
370
+ Triggered when the main agent stops. Can be used for cleanup and
371
+ final state persistence.
372
+ """
373
+
374
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
375
+ reason: str | None = Field(default=None, description="Reason for stopping")
376
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
377
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
378
+
379
+
380
+ class StopOutput(HookOutput):
381
+ """Output model for stop hook."""
382
+
383
+ pass # Uses base HookOutput fields only
384
+
385
+
386
+ # ==================== Subagent Stop Hook ====================
387
+
388
+
389
+ # ==================== Subagent Start Hook ====================
390
+
391
+
392
+ class SubagentStartInput(HookInput):
393
+ """
394
+ Input model for subagent-start hook.
395
+
396
+ Triggered when a subagent (spawned via Task tool) starts.
397
+ """
398
+
399
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
400
+ subagent_id: str = Field(..., min_length=1, description="Unique subagent identifier")
401
+ agent_id: str | None = Field(default=None, description="Agent ID of the subagent")
402
+ agent_transcript_path: str | None = Field(
403
+ default=None, description="Path to the subagent's transcript file"
404
+ )
405
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
406
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
407
+
408
+
409
+ class SubagentStartOutput(HookOutput):
410
+ """Output model for subagent-start hook."""
411
+
412
+ pass # Uses base HookOutput fields only
413
+
414
+
415
+ class SubagentStopInput(HookInput):
416
+ """
417
+ Input model for subagent-stop hook.
418
+
419
+ Triggered when a subagent (spawned via Task tool) stops.
420
+ """
421
+
422
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
423
+ subagent_id: str = Field(..., min_length=1, description="Unique subagent identifier")
424
+ agent_id: str | None = Field(default=None, description="Agent ID of the subagent")
425
+ agent_transcript_path: str | None = Field(
426
+ default=None, description="Path to the subagent's transcript file"
427
+ )
428
+ reason: str | None = Field(default=None, description="Reason for stopping subagent")
429
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
430
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
431
+
432
+
433
+ class SubagentStopOutput(HookOutput):
434
+ """Output model for subagent-stop hook."""
435
+
436
+ pass # Uses base HookOutput fields only
437
+
438
+
439
+ # ==================== Notification Hook ====================
440
+
441
+
442
+ class NotificationInput(HookInput):
443
+ """
444
+ Input model for notification hook.
445
+
446
+ Triggered for system notifications and alerts.
447
+ """
448
+
449
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
450
+ notification_type: str = Field(..., min_length=1, description="Type of notification")
451
+ message: str = Field(..., min_length=1, description="Notification message")
452
+ severity: NotificationSeverity = Field(
453
+ default=NotificationSeverity.INFO, description="Severity level"
454
+ )
455
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
456
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
457
+
458
+
459
+ class NotificationOutput(HookOutput):
460
+ """Output model for notification hook."""
461
+
462
+ pass # Uses base HookOutput fields (status="queued" typical)
463
+
464
+
465
+ # ==================== Before Model Hook (Gemini) ====================
466
+
467
+
468
+ class BeforeModelInput(HookInput):
469
+ """
470
+ Input model for before-model hook.
471
+
472
+ Triggered before model inference (Gemini only). Can be used to
473
+ modify or inspect prompts before they are sent to the model.
474
+ """
475
+
476
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
477
+ model_name: str | None = Field(default=None, description="Name of the model being used")
478
+ prompt: str | None = Field(default=None, description="Prompt being sent to model")
479
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
480
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
481
+
482
+
483
+ class BeforeModelOutput(HookOutput):
484
+ """Output model for before-model hook."""
485
+
486
+ pass # Uses base HookOutput fields only
487
+
488
+
489
+ # ==================== After Model Hook (Gemini) ====================
490
+
491
+
492
+ class AfterModelInput(HookInput):
493
+ """
494
+ Input model for after-model hook.
495
+
496
+ Triggered after model inference (Gemini only). Can be used to
497
+ inspect or log model responses.
498
+ """
499
+
500
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
501
+ model_name: str | None = Field(default=None, description="Name of the model used")
502
+ response: str | None = Field(default=None, description="Model response")
503
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
504
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
505
+
506
+
507
+ class AfterModelOutput(HookOutput):
508
+ """Output model for after-model hook."""
509
+
510
+ pass # Uses base HookOutput fields only
511
+
512
+
513
+ # ==================== Permission Request Hook (Claude) ====================
514
+
515
+
516
+ class PermissionRequestInput(HookInput):
517
+ """
518
+ Input model for permission-request hook.
519
+
520
+ Triggered when Claude Code requests permission for an action (Claude only).
521
+ """
522
+
523
+ external_id: str = Field(..., min_length=1, description="Unique session identifier")
524
+ permission_type: str = Field(..., min_length=1, description="Type of permission requested")
525
+ resource: str | None = Field(default=None, description="Resource requiring permission")
526
+ action: str | None = Field(default=None, description="Action requiring permission")
527
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
528
+ machine_id: str | None = Field(default=None, description="Unique machine identifier")
529
+
530
+
531
+ class PermissionRequestOutput(HookOutput):
532
+ """
533
+ Output model for permission-request hook.
534
+
535
+ Returns permission decision.
536
+ """
537
+
538
+ granted: bool = Field(default=True, description="Whether permission is granted")
539
+ reason: str | None = Field(default=None, description="Reason for decision")
540
+
541
+
542
+ # ==================== Type Mappings ====================
543
+
544
+ # Mapping of hook types to their input/output model classes
545
+ HOOK_INPUT_MODELS: dict[HookType, type[HookInput]] = {
546
+ HookType.SESSION_START: SessionStartInput,
547
+ HookType.SESSION_END: SessionEndInput,
548
+ HookType.USER_PROMPT_SUBMIT: UserPromptSubmitInput,
549
+ HookType.PRE_TOOL_USE: PreToolUseInput,
550
+ HookType.POST_TOOL_USE: PostToolUseInput,
551
+ HookType.PRE_COMPACT: PreCompactInput,
552
+ HookType.STOP: StopInput,
553
+ HookType.SUBAGENT_START: SubagentStartInput,
554
+ HookType.SUBAGENT_STOP: SubagentStopInput,
555
+ HookType.NOTIFICATION: NotificationInput,
556
+ HookType.BEFORE_MODEL: BeforeModelInput,
557
+ HookType.AFTER_MODEL: AfterModelInput,
558
+ HookType.PERMISSION_REQUEST: PermissionRequestInput,
559
+ }
560
+
561
+ HOOK_OUTPUT_MODELS: dict[HookType, type[HookOutput]] = {
562
+ HookType.SESSION_START: SessionStartOutput,
563
+ HookType.SESSION_END: SessionEndOutput,
564
+ HookType.USER_PROMPT_SUBMIT: UserPromptSubmitOutput,
565
+ HookType.PRE_TOOL_USE: PreToolUseOutput,
566
+ HookType.POST_TOOL_USE: PostToolUseOutput,
567
+ HookType.PRE_COMPACT: PreCompactOutput,
568
+ HookType.STOP: StopOutput,
569
+ HookType.SUBAGENT_START: SubagentStartOutput,
570
+ HookType.SUBAGENT_STOP: SubagentStopOutput,
571
+ HookType.NOTIFICATION: NotificationOutput,
572
+ HookType.BEFORE_MODEL: BeforeModelOutput,
573
+ HookType.AFTER_MODEL: AfterModelOutput,
574
+ HookType.PERMISSION_REQUEST: PermissionRequestOutput,
575
+ }