gobby 0.2.8__py3-none-any.whl → 0.2.11__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 (168) hide show
  1. gobby/__init__.py +1 -1
  2. gobby/adapters/__init__.py +6 -0
  3. gobby/adapters/base.py +11 -2
  4. gobby/adapters/claude_code.py +5 -28
  5. gobby/adapters/codex_impl/adapter.py +38 -43
  6. gobby/adapters/copilot.py +324 -0
  7. gobby/adapters/cursor.py +373 -0
  8. gobby/adapters/gemini.py +2 -26
  9. gobby/adapters/windsurf.py +359 -0
  10. gobby/agents/definitions.py +162 -2
  11. gobby/agents/isolation.py +33 -1
  12. gobby/agents/pty_reader.py +192 -0
  13. gobby/agents/registry.py +10 -1
  14. gobby/agents/runner.py +24 -8
  15. gobby/agents/sandbox.py +8 -3
  16. gobby/agents/session.py +4 -0
  17. gobby/agents/spawn.py +9 -2
  18. gobby/agents/spawn_executor.py +49 -61
  19. gobby/agents/spawners/command_builder.py +4 -4
  20. gobby/app_context.py +64 -0
  21. gobby/cli/__init__.py +4 -0
  22. gobby/cli/install.py +259 -4
  23. gobby/cli/installers/__init__.py +12 -0
  24. gobby/cli/installers/copilot.py +242 -0
  25. gobby/cli/installers/cursor.py +244 -0
  26. gobby/cli/installers/shared.py +3 -0
  27. gobby/cli/installers/windsurf.py +242 -0
  28. gobby/cli/pipelines.py +639 -0
  29. gobby/cli/sessions.py +3 -1
  30. gobby/cli/skills.py +209 -0
  31. gobby/cli/tasks/crud.py +6 -5
  32. gobby/cli/tasks/search.py +1 -1
  33. gobby/cli/ui.py +116 -0
  34. gobby/cli/utils.py +5 -17
  35. gobby/cli/workflows.py +38 -17
  36. gobby/config/app.py +5 -0
  37. gobby/config/features.py +0 -20
  38. gobby/config/skills.py +23 -2
  39. gobby/config/tasks.py +4 -0
  40. gobby/hooks/broadcaster.py +9 -0
  41. gobby/hooks/event_handlers/__init__.py +155 -0
  42. gobby/hooks/event_handlers/_agent.py +175 -0
  43. gobby/hooks/event_handlers/_base.py +92 -0
  44. gobby/hooks/event_handlers/_misc.py +66 -0
  45. gobby/hooks/event_handlers/_session.py +487 -0
  46. gobby/hooks/event_handlers/_tool.py +196 -0
  47. gobby/hooks/events.py +48 -0
  48. gobby/hooks/hook_manager.py +27 -3
  49. gobby/install/copilot/hooks/hook_dispatcher.py +203 -0
  50. gobby/install/cursor/hooks/hook_dispatcher.py +203 -0
  51. gobby/install/gemini/hooks/hook_dispatcher.py +8 -0
  52. gobby/install/windsurf/hooks/hook_dispatcher.py +205 -0
  53. gobby/llm/__init__.py +14 -1
  54. gobby/llm/claude.py +594 -43
  55. gobby/llm/service.py +149 -0
  56. gobby/mcp_proxy/importer.py +4 -41
  57. gobby/mcp_proxy/instructions.py +9 -27
  58. gobby/mcp_proxy/manager.py +13 -3
  59. gobby/mcp_proxy/models.py +1 -0
  60. gobby/mcp_proxy/registries.py +66 -5
  61. gobby/mcp_proxy/server.py +6 -2
  62. gobby/mcp_proxy/services/recommendation.py +2 -28
  63. gobby/mcp_proxy/services/tool_filter.py +7 -0
  64. gobby/mcp_proxy/services/tool_proxy.py +19 -1
  65. gobby/mcp_proxy/stdio.py +37 -21
  66. gobby/mcp_proxy/tools/agents.py +7 -0
  67. gobby/mcp_proxy/tools/artifacts.py +3 -3
  68. gobby/mcp_proxy/tools/hub.py +30 -1
  69. gobby/mcp_proxy/tools/orchestration/cleanup.py +5 -5
  70. gobby/mcp_proxy/tools/orchestration/monitor.py +1 -1
  71. gobby/mcp_proxy/tools/orchestration/orchestrate.py +8 -3
  72. gobby/mcp_proxy/tools/orchestration/review.py +17 -4
  73. gobby/mcp_proxy/tools/orchestration/wait.py +7 -7
  74. gobby/mcp_proxy/tools/pipelines/__init__.py +254 -0
  75. gobby/mcp_proxy/tools/pipelines/_discovery.py +67 -0
  76. gobby/mcp_proxy/tools/pipelines/_execution.py +281 -0
  77. gobby/mcp_proxy/tools/sessions/_crud.py +4 -4
  78. gobby/mcp_proxy/tools/sessions/_handoff.py +1 -1
  79. gobby/mcp_proxy/tools/skills/__init__.py +184 -30
  80. gobby/mcp_proxy/tools/spawn_agent.py +229 -14
  81. gobby/mcp_proxy/tools/task_readiness.py +27 -4
  82. gobby/mcp_proxy/tools/tasks/_context.py +8 -0
  83. gobby/mcp_proxy/tools/tasks/_crud.py +27 -1
  84. gobby/mcp_proxy/tools/tasks/_helpers.py +1 -1
  85. gobby/mcp_proxy/tools/tasks/_lifecycle.py +125 -8
  86. gobby/mcp_proxy/tools/tasks/_lifecycle_validation.py +2 -1
  87. gobby/mcp_proxy/tools/tasks/_search.py +1 -1
  88. gobby/mcp_proxy/tools/workflows/__init__.py +273 -0
  89. gobby/mcp_proxy/tools/workflows/_artifacts.py +225 -0
  90. gobby/mcp_proxy/tools/workflows/_import.py +112 -0
  91. gobby/mcp_proxy/tools/workflows/_lifecycle.py +332 -0
  92. gobby/mcp_proxy/tools/workflows/_query.py +226 -0
  93. gobby/mcp_proxy/tools/workflows/_resolution.py +78 -0
  94. gobby/mcp_proxy/tools/workflows/_terminal.py +175 -0
  95. gobby/mcp_proxy/tools/worktrees.py +54 -15
  96. gobby/memory/components/__init__.py +0 -0
  97. gobby/memory/components/ingestion.py +98 -0
  98. gobby/memory/components/search.py +108 -0
  99. gobby/memory/context.py +5 -5
  100. gobby/memory/manager.py +16 -25
  101. gobby/paths.py +51 -0
  102. gobby/prompts/loader.py +1 -35
  103. gobby/runner.py +131 -16
  104. gobby/servers/http.py +193 -150
  105. gobby/servers/routes/__init__.py +2 -0
  106. gobby/servers/routes/admin.py +56 -0
  107. gobby/servers/routes/mcp/endpoints/execution.py +33 -32
  108. gobby/servers/routes/mcp/endpoints/registry.py +8 -8
  109. gobby/servers/routes/mcp/hooks.py +10 -1
  110. gobby/servers/routes/pipelines.py +227 -0
  111. gobby/servers/websocket.py +314 -1
  112. gobby/sessions/analyzer.py +89 -3
  113. gobby/sessions/manager.py +5 -5
  114. gobby/sessions/transcripts/__init__.py +3 -0
  115. gobby/sessions/transcripts/claude.py +5 -0
  116. gobby/sessions/transcripts/codex.py +5 -0
  117. gobby/sessions/transcripts/gemini.py +5 -0
  118. gobby/skills/hubs/__init__.py +25 -0
  119. gobby/skills/hubs/base.py +234 -0
  120. gobby/skills/hubs/claude_plugins.py +328 -0
  121. gobby/skills/hubs/clawdhub.py +289 -0
  122. gobby/skills/hubs/github_collection.py +465 -0
  123. gobby/skills/hubs/manager.py +263 -0
  124. gobby/skills/hubs/skillhub.py +342 -0
  125. gobby/skills/parser.py +23 -0
  126. gobby/skills/sync.py +5 -4
  127. gobby/storage/artifacts.py +19 -0
  128. gobby/storage/memories.py +4 -4
  129. gobby/storage/migrations.py +118 -3
  130. gobby/storage/pipelines.py +367 -0
  131. gobby/storage/sessions.py +23 -4
  132. gobby/storage/skills.py +48 -8
  133. gobby/storage/tasks/_aggregates.py +2 -2
  134. gobby/storage/tasks/_lifecycle.py +4 -4
  135. gobby/storage/tasks/_models.py +7 -1
  136. gobby/storage/tasks/_queries.py +3 -3
  137. gobby/sync/memories.py +4 -3
  138. gobby/tasks/commits.py +48 -17
  139. gobby/tasks/external_validator.py +4 -17
  140. gobby/tasks/validation.py +13 -87
  141. gobby/tools/summarizer.py +18 -51
  142. gobby/utils/status.py +13 -0
  143. gobby/workflows/actions.py +80 -0
  144. gobby/workflows/context_actions.py +265 -27
  145. gobby/workflows/definitions.py +119 -1
  146. gobby/workflows/detection_helpers.py +23 -11
  147. gobby/workflows/enforcement/__init__.py +11 -1
  148. gobby/workflows/enforcement/blocking.py +96 -0
  149. gobby/workflows/enforcement/handlers.py +35 -1
  150. gobby/workflows/enforcement/task_policy.py +18 -0
  151. gobby/workflows/engine.py +26 -4
  152. gobby/workflows/evaluator.py +8 -5
  153. gobby/workflows/lifecycle_evaluator.py +59 -27
  154. gobby/workflows/loader.py +567 -30
  155. gobby/workflows/lobster_compat.py +147 -0
  156. gobby/workflows/pipeline_executor.py +801 -0
  157. gobby/workflows/pipeline_state.py +172 -0
  158. gobby/workflows/pipeline_webhooks.py +206 -0
  159. gobby/workflows/premature_stop.py +5 -0
  160. gobby/worktrees/git.py +135 -20
  161. {gobby-0.2.8.dist-info → gobby-0.2.11.dist-info}/METADATA +56 -22
  162. {gobby-0.2.8.dist-info → gobby-0.2.11.dist-info}/RECORD +166 -122
  163. gobby/hooks/event_handlers.py +0 -1008
  164. gobby/mcp_proxy/tools/workflows.py +0 -1023
  165. {gobby-0.2.8.dist-info → gobby-0.2.11.dist-info}/WHEEL +0 -0
  166. {gobby-0.2.8.dist-info → gobby-0.2.11.dist-info}/entry_points.txt +0 -0
  167. {gobby-0.2.8.dist-info → gobby-0.2.11.dist-info}/licenses/LICENSE.md +0 -0
  168. {gobby-0.2.8.dist-info → gobby-0.2.11.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,147 @@
1
+ """Lobster compatibility utilities for pipeline migration.
2
+
3
+ This module provides utilities to convert Lobster-format pipelines
4
+ to Gobby's native PipelineDefinition format.
5
+
6
+ Lobster field mappings:
7
+ - command → exec
8
+ - stdin: $step.stdout → input: $step.output
9
+ - approval: true → approval: {required: true}
10
+ - condition: $step.approved → condition (preserved as string)
11
+ """
12
+
13
+ import re
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ import yaml
18
+
19
+ from gobby.workflows.definitions import PipelineApproval, PipelineDefinition, PipelineStep
20
+
21
+
22
+ class LobsterImporter:
23
+ """Converts Lobster-format pipelines to Gobby PipelineDefinition.
24
+
25
+ Example:
26
+ importer = LobsterImporter()
27
+ lobster_step = {"id": "build", "command": "npm run build"}
28
+ gobby_step = importer.convert_step(lobster_step)
29
+ """
30
+
31
+ def convert_step(self, lobster_step: dict[str, Any]) -> PipelineStep:
32
+ """Convert a Lobster step to a Gobby PipelineStep.
33
+
34
+ Args:
35
+ lobster_step: Dictionary with Lobster step format
36
+
37
+ Returns:
38
+ PipelineStep with converted fields
39
+
40
+ Field mappings:
41
+ - id: preserved as-is
42
+ - command → exec
43
+ - stdin: $step.stdout → input: $step.output
44
+ - approval: true → approval: {required: true}
45
+ - approval: {required: true, message: "..."} → approval object
46
+ - condition: preserved as-is
47
+ """
48
+ step_id = lobster_step.get("id", "")
49
+
50
+ # Map command → exec
51
+ exec_cmd = lobster_step.get("command")
52
+
53
+ # Map stdin: $step.stdout → input: $step.output
54
+ input_ref = None
55
+ stdin_value = lobster_step.get("stdin")
56
+ if stdin_value:
57
+ # Replace .stdout with .output in the reference
58
+ input_ref = re.sub(r"\.stdout\b", ".output", stdin_value)
59
+
60
+ # Map approval
61
+ approval = None
62
+ approval_value = lobster_step.get("approval")
63
+ if approval_value is True:
64
+ # Simple boolean approval
65
+ approval = PipelineApproval(required=True)
66
+ elif isinstance(approval_value, dict):
67
+ # Detailed approval object
68
+ approval = PipelineApproval(
69
+ required=approval_value.get("required", True),
70
+ message=approval_value.get("message"),
71
+ timeout_seconds=approval_value.get("timeout_seconds"),
72
+ )
73
+
74
+ # Preserve condition as-is
75
+ condition = lobster_step.get("condition")
76
+
77
+ return PipelineStep(
78
+ id=step_id,
79
+ exec=exec_cmd,
80
+ input=input_ref,
81
+ approval=approval,
82
+ condition=condition,
83
+ )
84
+
85
+ def convert_pipeline(self, lobster_pipeline: dict[str, Any]) -> PipelineDefinition:
86
+ """Convert a Lobster pipeline to a Gobby PipelineDefinition.
87
+
88
+ Args:
89
+ lobster_pipeline: Dictionary with Lobster pipeline format
90
+
91
+ Returns:
92
+ PipelineDefinition with converted steps
93
+
94
+ Field mappings:
95
+ - name: preserved as-is
96
+ - description: preserved as-is
97
+ - args → inputs
98
+ - steps: converted via convert_step()
99
+ """
100
+ name = lobster_pipeline.get("name", "")
101
+ description = lobster_pipeline.get("description", "")
102
+
103
+ # Map args → inputs
104
+ inputs = lobster_pipeline.get("args", {})
105
+
106
+ steps = []
107
+ for lobster_step in lobster_pipeline.get("steps", []):
108
+ steps.append(self.convert_step(lobster_step))
109
+
110
+ return PipelineDefinition(
111
+ name=name,
112
+ description=description,
113
+ inputs=inputs,
114
+ steps=steps,
115
+ )
116
+
117
+ def import_file(self, path: str | Path) -> PipelineDefinition:
118
+ """Import a Lobster pipeline from a YAML file.
119
+
120
+ Args:
121
+ path: Path to the .lobster or .yaml file
122
+
123
+ Returns:
124
+ PipelineDefinition with converted pipeline
125
+
126
+ Raises:
127
+ FileNotFoundError: If the pipeline file doesn't exist
128
+ ValueError: If the file cannot be read or parsed
129
+
130
+ Example:
131
+ importer = LobsterImporter()
132
+ pipeline = importer.import_file("ci.lobster")
133
+ """
134
+ file_path = Path(path)
135
+ try:
136
+ content = file_path.read_text()
137
+ except FileNotFoundError:
138
+ raise FileNotFoundError(f"Pipeline file not found: {path}") from None
139
+ except UnicodeDecodeError as e:
140
+ raise ValueError(f"Cannot read pipeline file {path}: {e}") from e
141
+
142
+ try:
143
+ lobster_pipeline = yaml.safe_load(content)
144
+ except yaml.YAMLError as e:
145
+ raise ValueError(f"Invalid YAML in pipeline file {path}: {e}") from e
146
+
147
+ return self.convert_pipeline(lobster_pipeline)