gobby 0.2.5__py3-none-any.whl → 0.2.7__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 +2 -1
- gobby/adapters/claude_code.py +13 -4
- gobby/adapters/codex_impl/__init__.py +28 -0
- gobby/adapters/codex_impl/adapter.py +722 -0
- gobby/adapters/codex_impl/client.py +679 -0
- gobby/adapters/codex_impl/protocol.py +20 -0
- gobby/adapters/codex_impl/types.py +68 -0
- gobby/agents/definitions.py +11 -1
- gobby/agents/isolation.py +395 -0
- gobby/agents/runner.py +8 -0
- gobby/agents/sandbox.py +261 -0
- gobby/agents/spawn.py +42 -287
- gobby/agents/spawn_executor.py +385 -0
- gobby/agents/spawners/__init__.py +24 -0
- gobby/agents/spawners/command_builder.py +189 -0
- gobby/agents/spawners/embedded.py +21 -2
- gobby/agents/spawners/headless.py +21 -2
- gobby/agents/spawners/prompt_manager.py +125 -0
- gobby/cli/__init__.py +6 -0
- gobby/cli/clones.py +419 -0
- gobby/cli/conductor.py +266 -0
- gobby/cli/install.py +4 -4
- gobby/cli/installers/antigravity.py +3 -9
- gobby/cli/installers/claude.py +15 -9
- gobby/cli/installers/codex.py +2 -8
- gobby/cli/installers/gemini.py +8 -8
- gobby/cli/installers/shared.py +175 -13
- gobby/cli/sessions.py +1 -1
- gobby/cli/skills.py +858 -0
- gobby/cli/tasks/ai.py +0 -440
- gobby/cli/tasks/crud.py +44 -6
- gobby/cli/tasks/main.py +0 -4
- gobby/cli/tui.py +2 -2
- gobby/cli/utils.py +12 -5
- gobby/clones/__init__.py +13 -0
- gobby/clones/git.py +547 -0
- gobby/conductor/__init__.py +16 -0
- gobby/conductor/alerts.py +135 -0
- gobby/conductor/loop.py +164 -0
- gobby/conductor/monitors/__init__.py +11 -0
- gobby/conductor/monitors/agents.py +116 -0
- gobby/conductor/monitors/tasks.py +155 -0
- gobby/conductor/pricing.py +234 -0
- gobby/conductor/token_tracker.py +160 -0
- gobby/config/__init__.py +12 -97
- gobby/config/app.py +69 -91
- gobby/config/extensions.py +2 -2
- gobby/config/features.py +7 -130
- gobby/config/search.py +110 -0
- gobby/config/servers.py +1 -1
- gobby/config/skills.py +43 -0
- gobby/config/tasks.py +9 -41
- gobby/hooks/__init__.py +0 -13
- gobby/hooks/event_handlers.py +188 -2
- gobby/hooks/hook_manager.py +50 -4
- gobby/hooks/plugins.py +1 -1
- gobby/hooks/skill_manager.py +130 -0
- gobby/hooks/webhooks.py +1 -1
- gobby/install/claude/hooks/hook_dispatcher.py +4 -4
- gobby/install/codex/hooks/hook_dispatcher.py +1 -1
- gobby/install/gemini/hooks/hook_dispatcher.py +87 -12
- gobby/llm/claude.py +22 -34
- gobby/llm/claude_executor.py +46 -256
- gobby/llm/codex_executor.py +59 -291
- gobby/llm/executor.py +21 -0
- gobby/llm/gemini.py +134 -110
- gobby/llm/litellm_executor.py +143 -6
- gobby/llm/resolver.py +98 -35
- gobby/mcp_proxy/importer.py +62 -4
- gobby/mcp_proxy/instructions.py +56 -0
- gobby/mcp_proxy/models.py +15 -0
- gobby/mcp_proxy/registries.py +68 -8
- gobby/mcp_proxy/server.py +33 -3
- gobby/mcp_proxy/services/recommendation.py +43 -11
- gobby/mcp_proxy/services/tool_proxy.py +81 -1
- gobby/mcp_proxy/stdio.py +2 -1
- gobby/mcp_proxy/tools/__init__.py +0 -2
- gobby/mcp_proxy/tools/agent_messaging.py +317 -0
- gobby/mcp_proxy/tools/agents.py +31 -731
- gobby/mcp_proxy/tools/clones.py +518 -0
- gobby/mcp_proxy/tools/memory.py +3 -26
- gobby/mcp_proxy/tools/metrics.py +65 -1
- gobby/mcp_proxy/tools/orchestration/__init__.py +3 -0
- gobby/mcp_proxy/tools/orchestration/cleanup.py +151 -0
- gobby/mcp_proxy/tools/orchestration/wait.py +467 -0
- gobby/mcp_proxy/tools/sessions/__init__.py +14 -0
- gobby/mcp_proxy/tools/sessions/_commits.py +232 -0
- gobby/mcp_proxy/tools/sessions/_crud.py +253 -0
- gobby/mcp_proxy/tools/sessions/_factory.py +63 -0
- gobby/mcp_proxy/tools/sessions/_handoff.py +499 -0
- gobby/mcp_proxy/tools/sessions/_messages.py +138 -0
- gobby/mcp_proxy/tools/skills/__init__.py +616 -0
- gobby/mcp_proxy/tools/spawn_agent.py +417 -0
- gobby/mcp_proxy/tools/task_orchestration.py +7 -0
- gobby/mcp_proxy/tools/task_readiness.py +14 -0
- gobby/mcp_proxy/tools/task_sync.py +1 -1
- gobby/mcp_proxy/tools/tasks/_context.py +0 -20
- gobby/mcp_proxy/tools/tasks/_crud.py +91 -4
- gobby/mcp_proxy/tools/tasks/_expansion.py +348 -0
- gobby/mcp_proxy/tools/tasks/_factory.py +6 -16
- gobby/mcp_proxy/tools/tasks/_lifecycle.py +110 -45
- gobby/mcp_proxy/tools/tasks/_lifecycle_validation.py +18 -29
- gobby/mcp_proxy/tools/workflows.py +1 -1
- gobby/mcp_proxy/tools/worktrees.py +0 -338
- gobby/memory/backends/__init__.py +6 -1
- gobby/memory/backends/mem0.py +6 -1
- gobby/memory/extractor.py +477 -0
- gobby/memory/ingestion/__init__.py +5 -0
- gobby/memory/ingestion/multimodal.py +221 -0
- gobby/memory/manager.py +73 -285
- gobby/memory/search/__init__.py +10 -0
- gobby/memory/search/coordinator.py +248 -0
- gobby/memory/services/__init__.py +5 -0
- gobby/memory/services/crossref.py +142 -0
- gobby/prompts/loader.py +5 -2
- gobby/runner.py +37 -16
- gobby/search/__init__.py +48 -6
- gobby/search/backends/__init__.py +159 -0
- gobby/search/backends/embedding.py +225 -0
- gobby/search/embeddings.py +238 -0
- gobby/search/models.py +148 -0
- gobby/search/unified.py +496 -0
- gobby/servers/http.py +24 -12
- gobby/servers/routes/admin.py +294 -0
- gobby/servers/routes/mcp/endpoints/__init__.py +61 -0
- gobby/servers/routes/mcp/endpoints/discovery.py +405 -0
- gobby/servers/routes/mcp/endpoints/execution.py +568 -0
- gobby/servers/routes/mcp/endpoints/registry.py +378 -0
- gobby/servers/routes/mcp/endpoints/server.py +304 -0
- gobby/servers/routes/mcp/hooks.py +1 -1
- gobby/servers/routes/mcp/tools.py +48 -1317
- gobby/servers/websocket.py +2 -2
- gobby/sessions/analyzer.py +2 -0
- gobby/sessions/lifecycle.py +1 -1
- gobby/sessions/processor.py +10 -0
- gobby/sessions/transcripts/base.py +2 -0
- gobby/sessions/transcripts/claude.py +79 -10
- gobby/skills/__init__.py +91 -0
- gobby/skills/loader.py +685 -0
- gobby/skills/manager.py +384 -0
- gobby/skills/parser.py +286 -0
- gobby/skills/search.py +463 -0
- gobby/skills/sync.py +119 -0
- gobby/skills/updater.py +385 -0
- gobby/skills/validator.py +368 -0
- gobby/storage/clones.py +378 -0
- gobby/storage/database.py +1 -1
- gobby/storage/memories.py +43 -13
- gobby/storage/migrations.py +162 -201
- gobby/storage/sessions.py +116 -7
- gobby/storage/skills.py +782 -0
- gobby/storage/tasks/_crud.py +4 -4
- gobby/storage/tasks/_lifecycle.py +57 -7
- gobby/storage/tasks/_manager.py +14 -5
- gobby/storage/tasks/_models.py +8 -3
- gobby/sync/memories.py +40 -5
- gobby/sync/tasks.py +83 -6
- gobby/tasks/__init__.py +1 -2
- gobby/tasks/external_validator.py +1 -1
- gobby/tasks/validation.py +46 -35
- gobby/tools/summarizer.py +91 -10
- gobby/tui/api_client.py +4 -7
- gobby/tui/app.py +5 -3
- gobby/tui/screens/orchestrator.py +1 -2
- gobby/tui/screens/tasks.py +2 -4
- gobby/tui/ws_client.py +1 -1
- gobby/utils/daemon_client.py +2 -2
- gobby/utils/project_context.py +2 -3
- gobby/utils/status.py +13 -0
- gobby/workflows/actions.py +221 -1135
- gobby/workflows/artifact_actions.py +31 -0
- gobby/workflows/autonomous_actions.py +11 -0
- gobby/workflows/context_actions.py +93 -1
- gobby/workflows/detection_helpers.py +115 -31
- gobby/workflows/enforcement/__init__.py +47 -0
- gobby/workflows/enforcement/blocking.py +269 -0
- gobby/workflows/enforcement/commit_policy.py +283 -0
- gobby/workflows/enforcement/handlers.py +269 -0
- gobby/workflows/{task_enforcement_actions.py → enforcement/task_policy.py} +29 -388
- gobby/workflows/engine.py +13 -2
- gobby/workflows/git_utils.py +106 -0
- gobby/workflows/lifecycle_evaluator.py +29 -1
- gobby/workflows/llm_actions.py +30 -0
- gobby/workflows/loader.py +19 -6
- gobby/workflows/mcp_actions.py +20 -1
- gobby/workflows/memory_actions.py +154 -0
- gobby/workflows/safe_evaluator.py +183 -0
- gobby/workflows/session_actions.py +44 -0
- gobby/workflows/state_actions.py +60 -1
- gobby/workflows/stop_signal_actions.py +55 -0
- gobby/workflows/summary_actions.py +111 -1
- gobby/workflows/task_sync_actions.py +347 -0
- gobby/workflows/todo_actions.py +34 -1
- gobby/workflows/webhook_actions.py +185 -0
- {gobby-0.2.5.dist-info → gobby-0.2.7.dist-info}/METADATA +87 -21
- {gobby-0.2.5.dist-info → gobby-0.2.7.dist-info}/RECORD +201 -172
- {gobby-0.2.5.dist-info → gobby-0.2.7.dist-info}/WHEEL +1 -1
- gobby/adapters/codex.py +0 -1292
- gobby/install/claude/commands/gobby/bug.md +0 -51
- gobby/install/claude/commands/gobby/chore.md +0 -51
- gobby/install/claude/commands/gobby/epic.md +0 -52
- gobby/install/claude/commands/gobby/eval.md +0 -235
- gobby/install/claude/commands/gobby/feat.md +0 -49
- gobby/install/claude/commands/gobby/nit.md +0 -52
- gobby/install/claude/commands/gobby/ref.md +0 -52
- gobby/install/codex/prompts/forget.md +0 -7
- gobby/install/codex/prompts/memories.md +0 -7
- gobby/install/codex/prompts/recall.md +0 -7
- gobby/install/codex/prompts/remember.md +0 -13
- gobby/llm/gemini_executor.py +0 -339
- gobby/mcp_proxy/tools/session_messages.py +0 -1056
- gobby/mcp_proxy/tools/task_expansion.py +0 -591
- gobby/prompts/defaults/expansion/system.md +0 -119
- gobby/prompts/defaults/expansion/user.md +0 -48
- gobby/prompts/defaults/external_validation/agent.md +0 -72
- gobby/prompts/defaults/external_validation/external.md +0 -63
- gobby/prompts/defaults/external_validation/spawn.md +0 -83
- gobby/prompts/defaults/external_validation/system.md +0 -6
- gobby/prompts/defaults/features/import_mcp.md +0 -22
- gobby/prompts/defaults/features/import_mcp_github.md +0 -17
- gobby/prompts/defaults/features/import_mcp_search.md +0 -16
- gobby/prompts/defaults/features/recommend_tools.md +0 -32
- gobby/prompts/defaults/features/recommend_tools_hybrid.md +0 -35
- gobby/prompts/defaults/features/recommend_tools_llm.md +0 -30
- gobby/prompts/defaults/features/server_description.md +0 -20
- gobby/prompts/defaults/features/server_description_system.md +0 -6
- gobby/prompts/defaults/features/task_description.md +0 -31
- gobby/prompts/defaults/features/task_description_system.md +0 -6
- gobby/prompts/defaults/features/tool_summary.md +0 -17
- gobby/prompts/defaults/features/tool_summary_system.md +0 -6
- gobby/prompts/defaults/research/step.md +0 -58
- gobby/prompts/defaults/validation/criteria.md +0 -47
- gobby/prompts/defaults/validation/validate.md +0 -38
- gobby/storage/migrations_legacy.py +0 -1359
- gobby/tasks/context.py +0 -747
- gobby/tasks/criteria.py +0 -342
- gobby/tasks/expansion.py +0 -626
- gobby/tasks/prompts/expand.py +0 -327
- gobby/tasks/research.py +0 -421
- gobby/tasks/tdd.py +0 -352
- {gobby-0.2.5.dist-info → gobby-0.2.7.dist-info}/entry_points.txt +0 -0
- {gobby-0.2.5.dist-info → gobby-0.2.7.dist-info}/licenses/LICENSE.md +0 -0
- {gobby-0.2.5.dist-info → gobby-0.2.7.dist-info}/top_level.txt +0 -0
gobby/config/features.py
CHANGED
|
@@ -42,45 +42,22 @@ class ToolSummarizerConfig(BaseModel):
|
|
|
42
42
|
default="claude-haiku-4-5",
|
|
43
43
|
description="Model to use for summarization (fast/cheap recommended)",
|
|
44
44
|
)
|
|
45
|
-
prompt: str = Field(
|
|
46
|
-
default="""Summarize this MCP tool description in 180 characters or less.
|
|
47
|
-
Keep it to three sentences or less. Be concise and preserve the key functionality.
|
|
48
|
-
Do not add quotes, extra formatting, or code examples.
|
|
49
45
|
|
|
50
|
-
Description: {description}
|
|
51
|
-
|
|
52
|
-
Summary:""",
|
|
53
|
-
description="DEPRECATED: Use prompt_path instead. Prompt template for tool description summarization",
|
|
54
|
-
)
|
|
55
46
|
prompt_path: str | None = Field(
|
|
56
47
|
default=None,
|
|
57
48
|
description="Path to custom tool summary prompt template (e.g., 'features/tool_summary')",
|
|
58
49
|
)
|
|
59
|
-
|
|
60
|
-
default="You are a technical summarizer. Create concise tool descriptions.",
|
|
61
|
-
description="DEPRECATED: Use system_prompt_path instead. System prompt for tool description summarization",
|
|
62
|
-
)
|
|
50
|
+
|
|
63
51
|
system_prompt_path: str | None = Field(
|
|
64
52
|
default=None,
|
|
65
53
|
description="Path to custom tool summary system prompt (e.g., 'features/tool_summary_system')",
|
|
66
54
|
)
|
|
67
|
-
server_description_prompt: str = Field(
|
|
68
|
-
default="""Write a single concise sentence describing what the '{server_name}' MCP server does based on its tools.
|
|
69
55
|
|
|
70
|
-
Tools:
|
|
71
|
-
{tools_list}
|
|
72
|
-
|
|
73
|
-
Description (1 sentence, try to keep under 100 characters):""",
|
|
74
|
-
description="DEPRECATED: Use server_description_prompt_path instead. Prompt template for server description generation",
|
|
75
|
-
)
|
|
76
56
|
server_description_prompt_path: str | None = Field(
|
|
77
57
|
default=None,
|
|
78
58
|
description="Path to custom server description prompt (e.g., 'features/server_description')",
|
|
79
59
|
)
|
|
80
|
-
|
|
81
|
-
default="You write concise technical descriptions.",
|
|
82
|
-
description="DEPRECATED: Use server_description_system_prompt_path instead. System prompt for server description generation",
|
|
83
|
-
)
|
|
60
|
+
|
|
84
61
|
server_description_system_prompt_path: str | None = Field(
|
|
85
62
|
default=None,
|
|
86
63
|
description="Path to custom server description system prompt (e.g., 'features/server_description_system')",
|
|
@@ -110,26 +87,12 @@ class TaskDescriptionConfig(BaseModel):
|
|
|
110
87
|
default=50,
|
|
111
88
|
description="Minimum length of structured extraction before LLM fallback triggers",
|
|
112
89
|
)
|
|
113
|
-
prompt: str = Field(
|
|
114
|
-
default="""Generate a concise task description for this task from a spec document.
|
|
115
|
-
|
|
116
|
-
Task title: {task_title}
|
|
117
|
-
Section: {section_title}
|
|
118
|
-
Section content: {section_content}
|
|
119
|
-
Existing context: {existing_context}
|
|
120
90
|
|
|
121
|
-
Write a 1-2 sentence description focusing on the goal and deliverable.
|
|
122
|
-
Do not add quotes, extra formatting, or implementation details.""",
|
|
123
|
-
description="DEPRECATED: Use prompt_path instead. Prompt template for task description generation",
|
|
124
|
-
)
|
|
125
91
|
prompt_path: str | None = Field(
|
|
126
92
|
default=None,
|
|
127
93
|
description="Path to custom task description prompt (e.g., 'features/task_description')",
|
|
128
94
|
)
|
|
129
|
-
|
|
130
|
-
default="You are a technical writer creating concise task descriptions for developers.",
|
|
131
|
-
description="DEPRECATED: Use system_prompt_path instead. System prompt for task description generation",
|
|
132
|
-
)
|
|
95
|
+
|
|
133
96
|
system_prompt_path: str | None = Field(
|
|
134
97
|
default=None,
|
|
135
98
|
description="Path to custom task description system prompt (e.g., 'features/task_description_system')",
|
|
@@ -159,83 +122,17 @@ class RecommendToolsConfig(BaseModel):
|
|
|
159
122
|
default="claude-sonnet-4-5",
|
|
160
123
|
description="Model to use for tool recommendations",
|
|
161
124
|
)
|
|
162
|
-
|
|
163
|
-
default="""You are a tool recommendation assistant for Claude Code with access to MCP servers.
|
|
164
|
-
|
|
165
|
-
CRITICAL PRIORITIZATION RULES:
|
|
166
|
-
1. Analyze the task type (code navigation, docs lookup, database query, planning, data processing, etc.)
|
|
167
|
-
2. Check available MCP server DESCRIPTIONS for capability matches
|
|
168
|
-
3. If ANY MCP server's description matches the task type -> recommend those tools FIRST
|
|
169
|
-
4. Only recommend built-in Claude Code tools (Grep, Read, Bash, WebSearch) if NO suitable MCP server exists
|
|
170
|
-
|
|
171
|
-
TASK TYPE MATCHING GUIDELINES:
|
|
172
|
-
- Task needs library/framework documentation -> Look for MCP servers describing "documentation", "library docs", "API reference"
|
|
173
|
-
- Task needs code navigation/architecture understanding -> Look for MCP servers describing "code analysis", "symbols", "semantic search"
|
|
174
|
-
- Task needs database operations -> Look for MCP servers describing "database", "PostgreSQL", "SQL"
|
|
175
|
-
- Task needs complex reasoning/planning -> Look for MCP servers describing "problem-solving", "thinking", "reasoning"
|
|
176
|
-
- Task needs data processing/large datasets -> Look for MCP servers describing "code execution", "data processing", "token optimization"
|
|
177
|
-
|
|
178
|
-
ANTI-PATTERNS (What NOT to recommend):
|
|
179
|
-
- Don't recommend WebSearch when an MCP server provides library/framework documentation
|
|
180
|
-
- Don't recommend Grep/Read for code architecture questions when an MCP server does semantic code analysis
|
|
181
|
-
- Don't recommend Bash for database queries when an MCP server provides database tools
|
|
182
|
-
- Don't recommend direct implementation when an MCP server provides structured reasoning
|
|
183
|
-
|
|
184
|
-
OUTPUT FORMAT:
|
|
185
|
-
Be concise and specific. Recommend 1-3 tools maximum with:
|
|
186
|
-
1. Which MCP server and tools to use (if applicable)
|
|
187
|
-
2. Brief rationale based on server description matching task type
|
|
188
|
-
3. Suggested workflow (e.g., "First call X, then use result with Y")
|
|
189
|
-
4. Only mention built-in tools if no MCP server is suitable""",
|
|
190
|
-
description="DEPRECATED: Use prompt_path instead. System prompt for recommend_tools() MCP tool.",
|
|
191
|
-
)
|
|
125
|
+
|
|
192
126
|
prompt_path: str | None = Field(
|
|
193
127
|
default=None,
|
|
194
128
|
description="Path to custom recommend tools system prompt (e.g., 'features/recommend_tools')",
|
|
195
129
|
)
|
|
196
|
-
|
|
197
|
-
default="""You are an expert at selecting tools for tasks.
|
|
198
|
-
Task: {task_description}
|
|
199
|
-
|
|
200
|
-
Candidate tools (ranked by semantic similarity):
|
|
201
|
-
{candidate_list}
|
|
202
|
-
|
|
203
|
-
Re-rank these tools by relevance to the task and provide reasoning.
|
|
204
|
-
Return the top {top_k} most relevant as JSON:
|
|
205
|
-
{{
|
|
206
|
-
"recommendations": [
|
|
207
|
-
{{
|
|
208
|
-
"server": "server_name",
|
|
209
|
-
"tool": "tool_name",
|
|
210
|
-
"reason": "Why this tool is the best choice"
|
|
211
|
-
}}
|
|
212
|
-
]
|
|
213
|
-
}}""",
|
|
214
|
-
description="DEPRECATED: Use hybrid_rerank_prompt_path instead. Prompt template for hybrid mode re-ranking",
|
|
215
|
-
)
|
|
130
|
+
|
|
216
131
|
hybrid_rerank_prompt_path: str | None = Field(
|
|
217
132
|
default=None,
|
|
218
133
|
description="Path to custom hybrid re-rank prompt (e.g., 'features/recommend_tools_hybrid')",
|
|
219
134
|
)
|
|
220
|
-
|
|
221
|
-
default="""You are an expert at selecting the right tools for a given task.
|
|
222
|
-
Task: {task_description}
|
|
223
|
-
|
|
224
|
-
Available Servers: {available_servers}
|
|
225
|
-
|
|
226
|
-
Please recommend which tools from these servers would be most useful for this task.
|
|
227
|
-
Return a JSON object with this structure:
|
|
228
|
-
{{
|
|
229
|
-
"recommendations": [
|
|
230
|
-
{{
|
|
231
|
-
"server": "server_name",
|
|
232
|
-
"tool": "tool_name",
|
|
233
|
-
"reason": "Why this tool is useful"
|
|
234
|
-
}}
|
|
235
|
-
]
|
|
236
|
-
}}""",
|
|
237
|
-
description="DEPRECATED: Use llm_prompt_path instead. Prompt template for LLM mode recommendations",
|
|
238
|
-
)
|
|
135
|
+
|
|
239
136
|
llm_prompt_path: str | None = Field(
|
|
240
137
|
default=None,
|
|
241
138
|
description="Path to custom LLM recommendation prompt (e.g., 'features/recommend_tools_llm')",
|
|
@@ -276,37 +173,17 @@ class ImportMCPServerConfig(BaseModel):
|
|
|
276
173
|
default="claude-haiku-4-5",
|
|
277
174
|
description="Model to use for config extraction",
|
|
278
175
|
)
|
|
279
|
-
|
|
280
|
-
default=DEFAULT_IMPORT_MCP_SERVER_PROMPT,
|
|
281
|
-
description="DEPRECATED: Use prompt_path instead. System prompt for MCP server config extraction",
|
|
282
|
-
)
|
|
176
|
+
|
|
283
177
|
prompt_path: str | None = Field(
|
|
284
178
|
default=None,
|
|
285
179
|
description="Path to custom import MCP system prompt (e.g., 'features/import_mcp')",
|
|
286
180
|
)
|
|
287
|
-
github_fetch_prompt: str = Field(
|
|
288
|
-
default="""Fetch the README from this GitHub repository and extract MCP server configuration:
|
|
289
|
-
|
|
290
|
-
{github_url}
|
|
291
|
-
|
|
292
|
-
If the URL doesn't point directly to a README, try to find and fetch the README.md file.
|
|
293
181
|
|
|
294
|
-
After reading the documentation, extract the MCP server configuration as a JSON object.""",
|
|
295
|
-
description="DEPRECATED: Use github_fetch_prompt_path instead. User prompt template for GitHub import",
|
|
296
|
-
)
|
|
297
182
|
github_fetch_prompt_path: str | None = Field(
|
|
298
183
|
default=None,
|
|
299
184
|
description="Path to custom GitHub fetch prompt (e.g., 'features/import_mcp_github')",
|
|
300
185
|
)
|
|
301
|
-
search_fetch_prompt: str = Field(
|
|
302
|
-
default="""Search for MCP server: {search_query}
|
|
303
|
-
|
|
304
|
-
Find the official documentation or GitHub repository for this MCP server.
|
|
305
|
-
Then fetch and read the README or installation docs.
|
|
306
186
|
|
|
307
|
-
After reading the documentation, extract the MCP server configuration as a JSON object.""",
|
|
308
|
-
description="DEPRECATED: Use search_fetch_prompt_path instead. User prompt template for search-based import",
|
|
309
|
-
)
|
|
310
187
|
search_fetch_prompt_path: str | None = Field(
|
|
311
188
|
default=None,
|
|
312
189
|
description="Path to custom search fetch prompt (e.g., 'features/import_mcp_search')",
|
gobby/config/search.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Search configuration for Gobby daemon.
|
|
2
|
+
|
|
3
|
+
Provides configuration for the unified search layer with embedding
|
|
4
|
+
support and TF-IDF fallback.
|
|
5
|
+
|
|
6
|
+
Example usage in config.yaml:
|
|
7
|
+
search:
|
|
8
|
+
mode: auto # tfidf, embedding, auto, hybrid
|
|
9
|
+
embedding_model: text-embedding-3-small
|
|
10
|
+
tfidf_weight: 0.4
|
|
11
|
+
embedding_weight: 0.6
|
|
12
|
+
notify_on_fallback: true
|
|
13
|
+
|
|
14
|
+
For Ollama (local embeddings):
|
|
15
|
+
search:
|
|
16
|
+
mode: auto
|
|
17
|
+
embedding_model: openai/nomic-embed-text
|
|
18
|
+
embedding_api_base: http://localhost:11434/v1
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from pydantic import BaseModel, Field
|
|
22
|
+
|
|
23
|
+
from gobby.search.models import SearchMode
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SearchConfig(BaseModel):
|
|
27
|
+
"""Configuration for unified search with fallback.
|
|
28
|
+
|
|
29
|
+
This config controls how UnifiedSearcher behaves, including:
|
|
30
|
+
- Which search mode to use (tfidf, embedding, auto, hybrid)
|
|
31
|
+
- Which embedding model to use (LiteLLM format)
|
|
32
|
+
- Weights for hybrid mode
|
|
33
|
+
- Whether to notify on fallback
|
|
34
|
+
|
|
35
|
+
Supported modes:
|
|
36
|
+
- tfidf: TF-IDF only (always works, no API needed)
|
|
37
|
+
- embedding: Embedding-based search only (fails if unavailable)
|
|
38
|
+
- auto: Try embedding, fallback to TF-IDF if unavailable
|
|
39
|
+
- hybrid: Combine both with weighted scores
|
|
40
|
+
|
|
41
|
+
LiteLLM model format examples:
|
|
42
|
+
- OpenAI: text-embedding-3-small (needs OPENAI_API_KEY)
|
|
43
|
+
- Ollama: openai/nomic-embed-text (with embedding_api_base)
|
|
44
|
+
- Azure: azure/azure-embedding-model
|
|
45
|
+
- Vertex AI: vertex_ai/text-embedding-004
|
|
46
|
+
- Gemini: gemini/text-embedding-004 (needs GEMINI_API_KEY)
|
|
47
|
+
- Mistral: mistral/mistral-embed (needs MISTRAL_API_KEY)
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
mode: str = Field(
|
|
51
|
+
default="auto",
|
|
52
|
+
description="Search mode: tfidf, embedding, auto, hybrid",
|
|
53
|
+
)
|
|
54
|
+
embedding_model: str = Field(
|
|
55
|
+
default="text-embedding-3-small",
|
|
56
|
+
description="LiteLLM model string (e.g., text-embedding-3-small, openai/nomic-embed-text)",
|
|
57
|
+
)
|
|
58
|
+
embedding_api_base: str | None = Field(
|
|
59
|
+
default=None,
|
|
60
|
+
description="API base URL for Ollama/custom endpoints (e.g., http://localhost:11434/v1)",
|
|
61
|
+
)
|
|
62
|
+
embedding_api_key: str | None = Field(
|
|
63
|
+
default=None,
|
|
64
|
+
description="API key for embedding provider (uses env var if not set)",
|
|
65
|
+
)
|
|
66
|
+
tfidf_weight: float = Field(
|
|
67
|
+
default=0.4,
|
|
68
|
+
ge=0.0,
|
|
69
|
+
le=1.0,
|
|
70
|
+
description="Weight for TF-IDF scores in hybrid mode",
|
|
71
|
+
)
|
|
72
|
+
embedding_weight: float = Field(
|
|
73
|
+
default=0.6,
|
|
74
|
+
ge=0.0,
|
|
75
|
+
le=1.0,
|
|
76
|
+
description="Weight for embedding scores in hybrid mode",
|
|
77
|
+
)
|
|
78
|
+
notify_on_fallback: bool = Field(
|
|
79
|
+
default=True,
|
|
80
|
+
description="Log warning when falling back to TF-IDF",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def get_normalized_weights(self) -> tuple[float, float]:
|
|
84
|
+
"""Get normalized weights that sum to 1.0.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Tuple of (tfidf_weight, embedding_weight) normalized to sum to 1.0
|
|
88
|
+
"""
|
|
89
|
+
total = self.tfidf_weight + self.embedding_weight
|
|
90
|
+
if total == 0:
|
|
91
|
+
# Default to equal weights if both are 0
|
|
92
|
+
return (0.5, 0.5)
|
|
93
|
+
return (self.tfidf_weight / total, self.embedding_weight / total)
|
|
94
|
+
|
|
95
|
+
def get_mode_enum(self) -> SearchMode:
|
|
96
|
+
"""Get the SearchMode enum instance for the configured mode.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
SearchMode enum corresponding to the mode string value
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
ValueError: If the configured mode is not a valid SearchMode
|
|
103
|
+
"""
|
|
104
|
+
try:
|
|
105
|
+
return SearchMode(self.mode)
|
|
106
|
+
except ValueError as e:
|
|
107
|
+
valid_modes = [m.value for m in SearchMode]
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"Invalid search mode '{self.mode}'. Valid modes are: {', '.join(valid_modes)}"
|
|
110
|
+
) from e
|
gobby/config/servers.py
CHANGED
|
@@ -23,7 +23,7 @@ class WebSocketSettings(BaseModel):
|
|
|
23
23
|
description="Enable WebSocket server for real-time communication",
|
|
24
24
|
)
|
|
25
25
|
port: int = Field(
|
|
26
|
-
default=
|
|
26
|
+
default=60888,
|
|
27
27
|
description="Port for WebSocket server to listen on",
|
|
28
28
|
)
|
|
29
29
|
ping_interval: int = Field(
|
gobby/config/skills.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skills configuration for Gobby daemon.
|
|
3
|
+
|
|
4
|
+
Provides configuration for skill injection and discovery.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, Field, field_validator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SkillsConfig(BaseModel):
|
|
15
|
+
"""
|
|
16
|
+
Configuration for skill injection and discovery.
|
|
17
|
+
|
|
18
|
+
Controls whether and how skills are injected into session context.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
inject_core_skills: bool = Field(
|
|
22
|
+
default=True,
|
|
23
|
+
description="Whether to inject core skills into session context",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
core_skills_path: str | None = Field(
|
|
27
|
+
default=None,
|
|
28
|
+
description="Override path for core skills (default: install/shared/skills/)",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
injection_format: Literal["summary", "full", "none"] = Field(
|
|
32
|
+
default="summary",
|
|
33
|
+
description="Format for skill injection: 'summary' (names only), 'full' (with content), 'none' (disabled)",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
@field_validator("injection_format")
|
|
37
|
+
@classmethod
|
|
38
|
+
def validate_injection_format(cls, v: str) -> str:
|
|
39
|
+
"""Validate injection_format is one of the allowed values."""
|
|
40
|
+
allowed = {"summary", "full", "none"}
|
|
41
|
+
if v not in allowed:
|
|
42
|
+
raise ValueError(f"injection_format must be one of {allowed}, got '{v}'")
|
|
43
|
+
return v
|
gobby/config/tasks.py
CHANGED
|
@@ -38,14 +38,6 @@ class CompactHandoffConfig(BaseModel):
|
|
|
38
38
|
default=True,
|
|
39
39
|
description="Enable compact handoff context extraction and injection",
|
|
40
40
|
)
|
|
41
|
-
# DEPRECATED: prompt field is no longer used.
|
|
42
|
-
# Template is now defined in session-handoff.yaml workflow file.
|
|
43
|
-
# Kept for backwards compatibility but will be removed in a future version.
|
|
44
|
-
prompt: str | None = Field(
|
|
45
|
-
default=None,
|
|
46
|
-
description="DEPRECATED: Template moved to session-handoff.yaml workflow. "
|
|
47
|
-
"This field is ignored.",
|
|
48
|
-
)
|
|
49
41
|
|
|
50
42
|
|
|
51
43
|
class PatternCriteriaConfig(BaseModel):
|
|
@@ -147,10 +139,7 @@ class TaskExpansionConfig(BaseModel):
|
|
|
147
139
|
default="claude-opus-4-5",
|
|
148
140
|
description="Model to use for expansion",
|
|
149
141
|
)
|
|
150
|
-
|
|
151
|
-
default=None,
|
|
152
|
-
description="DEPRECATED: Use prompt_path instead. Custom prompt template for task expansion",
|
|
153
|
-
)
|
|
142
|
+
|
|
154
143
|
prompt_path: str | None = Field(
|
|
155
144
|
default=None,
|
|
156
145
|
description="Path to custom user prompt template (e.g., 'expansion/user')",
|
|
@@ -175,22 +164,11 @@ class TaskExpansionConfig(BaseModel):
|
|
|
175
164
|
default="You are a senior developer researching a codebase. Use tools to find relevant code.",
|
|
176
165
|
description="System prompt for the research agent",
|
|
177
166
|
)
|
|
178
|
-
|
|
179
|
-
default=None,
|
|
180
|
-
description="DEPRECATED: Use system_prompt_path instead. Custom system prompt for task expansion",
|
|
181
|
-
)
|
|
182
|
-
tdd_prompt: str | None = Field(
|
|
183
|
-
default=None,
|
|
184
|
-
description="DEPRECATED: TDD mode is now integrated into the system prompt template via Jinja2 conditionals",
|
|
185
|
-
)
|
|
167
|
+
|
|
186
168
|
web_research_enabled: bool = Field(
|
|
187
169
|
default=True,
|
|
188
170
|
description="Enable web research for task expansion using MCP tools",
|
|
189
171
|
)
|
|
190
|
-
tdd_mode: bool = Field(
|
|
191
|
-
default=True,
|
|
192
|
-
description="Enable TDD mode: create test->implement task pairs with appropriate blocking for coding tasks",
|
|
193
|
-
)
|
|
194
172
|
max_subtasks: int = Field(
|
|
195
173
|
default=15,
|
|
196
174
|
description="Maximum number of subtasks to create per expansion",
|
|
@@ -232,10 +210,7 @@ class TaskValidationConfig(BaseModel):
|
|
|
232
210
|
default="You are a QA validator. Output ONLY valid JSON. No markdown, no explanation, no code blocks. Just the raw JSON object.",
|
|
233
211
|
description="System prompt for task validation",
|
|
234
212
|
)
|
|
235
|
-
|
|
236
|
-
default=None,
|
|
237
|
-
description="DEPRECATED: Use prompt_path instead. Custom prompt template for task validation",
|
|
238
|
-
)
|
|
213
|
+
|
|
239
214
|
prompt_path: str | None = Field(
|
|
240
215
|
default=None,
|
|
241
216
|
description="Path to custom validation prompt template (e.g., 'validation/validate')",
|
|
@@ -264,10 +239,7 @@ class TaskValidationConfig(BaseModel):
|
|
|
264
239
|
default="You are a QA engineer writing acceptance criteria. CRITICAL: Only include requirements explicitly stated in the task. Do NOT invent specific values, thresholds, timeouts, or edge cases that aren't mentioned. Vague tasks get vague criteria. Use markdown checkboxes.",
|
|
265
240
|
description="System prompt for generating validation criteria",
|
|
266
241
|
)
|
|
267
|
-
|
|
268
|
-
default=None,
|
|
269
|
-
description="DEPRECATED: Use criteria_prompt_path instead. Custom prompt template for generating validation criteria",
|
|
270
|
-
)
|
|
242
|
+
|
|
271
243
|
# Validation loop control
|
|
272
244
|
max_iterations: int = Field(
|
|
273
245
|
default=10,
|
|
@@ -724,10 +696,6 @@ class WorkflowVariablesConfig(BaseModel):
|
|
|
724
696
|
default=False,
|
|
725
697
|
description="Require an active task (in_progress) before allowing file edits",
|
|
726
698
|
)
|
|
727
|
-
tdd_mode: bool = Field(
|
|
728
|
-
default=True,
|
|
729
|
-
description="Enable TDD mode for task expansion (test-implementation pairs)",
|
|
730
|
-
)
|
|
731
699
|
session_task: str | list[str] | None = Field(
|
|
732
700
|
default=None,
|
|
733
701
|
description="Task(s) to complete before stopping. "
|
|
@@ -759,13 +727,13 @@ def merge_workflow_variables(
|
|
|
759
727
|
ValidationError: If validate=True and merged values fail validation.
|
|
760
728
|
|
|
761
729
|
Example:
|
|
762
|
-
>>> yaml_defaults = {"
|
|
763
|
-
>>> db_overrides = {"
|
|
730
|
+
>>> yaml_defaults = {"require_task_before_edit": False, "session_task": None}
|
|
731
|
+
>>> db_overrides = {"require_task_before_edit": True}
|
|
764
732
|
>>> effective = merge_workflow_variables(yaml_defaults, db_overrides)
|
|
765
|
-
>>> effective["tdd_mode"]
|
|
766
|
-
False
|
|
767
733
|
>>> effective["require_task_before_edit"]
|
|
768
|
-
|
|
734
|
+
True
|
|
735
|
+
>>> effective["session_task"]
|
|
736
|
+
None
|
|
769
737
|
"""
|
|
770
738
|
# Start with defaults
|
|
771
739
|
effective = dict(yaml_defaults)
|
gobby/hooks/__init__.py
CHANGED
|
@@ -65,14 +65,6 @@ from gobby.hooks.plugins import (
|
|
|
65
65
|
from gobby.hooks.session_coordinator import SessionCoordinator
|
|
66
66
|
from gobby.hooks.webhooks import WebhookDispatcher
|
|
67
67
|
|
|
68
|
-
# Legacy imports for backward compatibility
|
|
69
|
-
from gobby.sessions.manager import SessionManager
|
|
70
|
-
from gobby.sessions.summary import SummaryFileGenerator
|
|
71
|
-
from gobby.sessions.transcripts.claude import ClaudeTranscriptParser
|
|
72
|
-
|
|
73
|
-
# Backward-compatible alias
|
|
74
|
-
TranscriptProcessor = ClaudeTranscriptParser
|
|
75
|
-
|
|
76
68
|
__all__ = [
|
|
77
69
|
# Core coordinator
|
|
78
70
|
"HookManager",
|
|
@@ -96,9 +88,4 @@ __all__ = [
|
|
|
96
88
|
"RegisteredHandler",
|
|
97
89
|
"hook_handler",
|
|
98
90
|
"run_plugin_handlers",
|
|
99
|
-
# Legacy exports (backward compatibility)
|
|
100
|
-
"SessionManager",
|
|
101
|
-
"SummaryFileGenerator",
|
|
102
|
-
"TranscriptProcessor",
|
|
103
|
-
"ClaudeTranscriptParser",
|
|
104
91
|
]
|