gobby 0.2.9__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.
- gobby/__init__.py +1 -1
- gobby/adapters/__init__.py +6 -0
- gobby/adapters/base.py +11 -2
- gobby/adapters/claude_code.py +2 -2
- gobby/adapters/codex_impl/adapter.py +38 -43
- gobby/adapters/copilot.py +324 -0
- gobby/adapters/cursor.py +373 -0
- gobby/adapters/gemini.py +2 -26
- gobby/adapters/windsurf.py +359 -0
- gobby/agents/definitions.py +162 -2
- gobby/agents/isolation.py +33 -1
- gobby/agents/pty_reader.py +192 -0
- gobby/agents/registry.py +10 -1
- gobby/agents/runner.py +24 -8
- gobby/agents/sandbox.py +8 -3
- gobby/agents/session.py +4 -0
- gobby/agents/spawn.py +9 -2
- gobby/agents/spawn_executor.py +49 -61
- gobby/agents/spawners/command_builder.py +4 -4
- gobby/app_context.py +5 -0
- gobby/cli/__init__.py +4 -0
- gobby/cli/install.py +259 -4
- gobby/cli/installers/__init__.py +12 -0
- gobby/cli/installers/copilot.py +242 -0
- gobby/cli/installers/cursor.py +244 -0
- gobby/cli/installers/shared.py +3 -0
- gobby/cli/installers/windsurf.py +242 -0
- gobby/cli/pipelines.py +639 -0
- gobby/cli/sessions.py +3 -1
- gobby/cli/skills.py +209 -0
- gobby/cli/tasks/crud.py +6 -5
- gobby/cli/tasks/search.py +1 -1
- gobby/cli/ui.py +116 -0
- gobby/cli/workflows.py +38 -17
- gobby/config/app.py +5 -0
- gobby/config/skills.py +23 -2
- gobby/hooks/broadcaster.py +9 -0
- gobby/hooks/event_handlers/_base.py +6 -1
- gobby/hooks/event_handlers/_session.py +44 -130
- gobby/hooks/events.py +48 -0
- gobby/hooks/hook_manager.py +25 -3
- gobby/install/copilot/hooks/hook_dispatcher.py +203 -0
- gobby/install/cursor/hooks/hook_dispatcher.py +203 -0
- gobby/install/gemini/hooks/hook_dispatcher.py +8 -0
- gobby/install/windsurf/hooks/hook_dispatcher.py +205 -0
- gobby/llm/__init__.py +14 -1
- gobby/llm/claude.py +217 -1
- gobby/llm/service.py +149 -0
- gobby/mcp_proxy/instructions.py +9 -27
- gobby/mcp_proxy/models.py +1 -0
- gobby/mcp_proxy/registries.py +56 -9
- gobby/mcp_proxy/server.py +6 -2
- gobby/mcp_proxy/services/tool_filter.py +7 -0
- gobby/mcp_proxy/services/tool_proxy.py +19 -1
- gobby/mcp_proxy/stdio.py +37 -21
- gobby/mcp_proxy/tools/agents.py +7 -0
- gobby/mcp_proxy/tools/hub.py +30 -1
- gobby/mcp_proxy/tools/orchestration/cleanup.py +5 -5
- gobby/mcp_proxy/tools/orchestration/monitor.py +1 -1
- gobby/mcp_proxy/tools/orchestration/orchestrate.py +8 -3
- gobby/mcp_proxy/tools/orchestration/review.py +17 -4
- gobby/mcp_proxy/tools/orchestration/wait.py +7 -7
- gobby/mcp_proxy/tools/pipelines/__init__.py +254 -0
- gobby/mcp_proxy/tools/pipelines/_discovery.py +67 -0
- gobby/mcp_proxy/tools/pipelines/_execution.py +281 -0
- gobby/mcp_proxy/tools/sessions/_crud.py +4 -4
- gobby/mcp_proxy/tools/sessions/_handoff.py +1 -1
- gobby/mcp_proxy/tools/skills/__init__.py +184 -30
- gobby/mcp_proxy/tools/spawn_agent.py +229 -14
- gobby/mcp_proxy/tools/tasks/_context.py +8 -0
- gobby/mcp_proxy/tools/tasks/_crud.py +27 -1
- gobby/mcp_proxy/tools/tasks/_helpers.py +1 -1
- gobby/mcp_proxy/tools/tasks/_lifecycle.py +125 -8
- gobby/mcp_proxy/tools/tasks/_lifecycle_validation.py +2 -1
- gobby/mcp_proxy/tools/tasks/_search.py +1 -1
- gobby/mcp_proxy/tools/workflows/__init__.py +9 -2
- gobby/mcp_proxy/tools/workflows/_lifecycle.py +12 -1
- gobby/mcp_proxy/tools/workflows/_query.py +45 -26
- gobby/mcp_proxy/tools/workflows/_terminal.py +39 -3
- gobby/mcp_proxy/tools/worktrees.py +54 -15
- gobby/memory/context.py +5 -5
- gobby/runner.py +108 -6
- gobby/servers/http.py +7 -1
- gobby/servers/routes/__init__.py +2 -0
- gobby/servers/routes/admin.py +44 -0
- gobby/servers/routes/mcp/endpoints/execution.py +18 -25
- gobby/servers/routes/mcp/hooks.py +10 -1
- gobby/servers/routes/pipelines.py +227 -0
- gobby/servers/websocket.py +314 -1
- gobby/sessions/analyzer.py +87 -1
- gobby/sessions/manager.py +5 -5
- gobby/sessions/transcripts/__init__.py +3 -0
- gobby/sessions/transcripts/claude.py +5 -0
- gobby/sessions/transcripts/codex.py +5 -0
- gobby/sessions/transcripts/gemini.py +5 -0
- gobby/skills/hubs/__init__.py +25 -0
- gobby/skills/hubs/base.py +234 -0
- gobby/skills/hubs/claude_plugins.py +328 -0
- gobby/skills/hubs/clawdhub.py +289 -0
- gobby/skills/hubs/github_collection.py +465 -0
- gobby/skills/hubs/manager.py +263 -0
- gobby/skills/hubs/skillhub.py +342 -0
- gobby/storage/memories.py +4 -4
- gobby/storage/migrations.py +95 -3
- gobby/storage/pipelines.py +367 -0
- gobby/storage/sessions.py +23 -4
- gobby/storage/skills.py +1 -1
- gobby/storage/tasks/_aggregates.py +2 -2
- gobby/storage/tasks/_lifecycle.py +4 -4
- gobby/storage/tasks/_models.py +7 -1
- gobby/storage/tasks/_queries.py +3 -3
- gobby/sync/memories.py +4 -3
- gobby/tasks/commits.py +48 -17
- gobby/workflows/actions.py +75 -0
- gobby/workflows/context_actions.py +246 -5
- gobby/workflows/definitions.py +119 -1
- gobby/workflows/detection_helpers.py +23 -11
- gobby/workflows/enforcement/task_policy.py +18 -0
- gobby/workflows/engine.py +20 -1
- gobby/workflows/evaluator.py +8 -5
- gobby/workflows/lifecycle_evaluator.py +57 -26
- gobby/workflows/loader.py +567 -30
- gobby/workflows/lobster_compat.py +147 -0
- gobby/workflows/pipeline_executor.py +801 -0
- gobby/workflows/pipeline_state.py +172 -0
- gobby/workflows/pipeline_webhooks.py +206 -0
- gobby/workflows/premature_stop.py +5 -0
- gobby/worktrees/git.py +135 -20
- {gobby-0.2.9.dist-info → gobby-0.2.11.dist-info}/METADATA +56 -22
- {gobby-0.2.9.dist-info → gobby-0.2.11.dist-info}/RECORD +134 -106
- {gobby-0.2.9.dist-info → gobby-0.2.11.dist-info}/WHEEL +0 -0
- {gobby-0.2.9.dist-info → gobby-0.2.11.dist-info}/entry_points.txt +0 -0
- {gobby-0.2.9.dist-info → gobby-0.2.11.dist-info}/licenses/LICENSE.md +0 -0
- {gobby-0.2.9.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)
|