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.
- gobby/__init__.py +3 -0
- gobby/adapters/__init__.py +30 -0
- gobby/adapters/base.py +93 -0
- gobby/adapters/claude_code.py +276 -0
- gobby/adapters/codex.py +1292 -0
- gobby/adapters/gemini.py +343 -0
- gobby/agents/__init__.py +37 -0
- gobby/agents/codex_session.py +120 -0
- gobby/agents/constants.py +112 -0
- gobby/agents/context.py +362 -0
- gobby/agents/definitions.py +133 -0
- gobby/agents/gemini_session.py +111 -0
- gobby/agents/registry.py +618 -0
- gobby/agents/runner.py +968 -0
- gobby/agents/session.py +259 -0
- gobby/agents/spawn.py +916 -0
- gobby/agents/spawners/__init__.py +77 -0
- gobby/agents/spawners/base.py +142 -0
- gobby/agents/spawners/cross_platform.py +266 -0
- gobby/agents/spawners/embedded.py +225 -0
- gobby/agents/spawners/headless.py +226 -0
- gobby/agents/spawners/linux.py +125 -0
- gobby/agents/spawners/macos.py +277 -0
- gobby/agents/spawners/windows.py +308 -0
- gobby/agents/tty_config.py +319 -0
- gobby/autonomous/__init__.py +32 -0
- gobby/autonomous/progress_tracker.py +447 -0
- gobby/autonomous/stop_registry.py +269 -0
- gobby/autonomous/stuck_detector.py +383 -0
- gobby/cli/__init__.py +67 -0
- gobby/cli/__main__.py +8 -0
- gobby/cli/agents.py +529 -0
- gobby/cli/artifacts.py +266 -0
- gobby/cli/daemon.py +329 -0
- gobby/cli/extensions.py +526 -0
- gobby/cli/github.py +263 -0
- gobby/cli/init.py +53 -0
- gobby/cli/install.py +614 -0
- gobby/cli/installers/__init__.py +37 -0
- gobby/cli/installers/antigravity.py +65 -0
- gobby/cli/installers/claude.py +363 -0
- gobby/cli/installers/codex.py +192 -0
- gobby/cli/installers/gemini.py +294 -0
- gobby/cli/installers/git_hooks.py +377 -0
- gobby/cli/installers/shared.py +737 -0
- gobby/cli/linear.py +250 -0
- gobby/cli/mcp.py +30 -0
- gobby/cli/mcp_proxy.py +698 -0
- gobby/cli/memory.py +304 -0
- gobby/cli/merge.py +384 -0
- gobby/cli/projects.py +79 -0
- gobby/cli/sessions.py +622 -0
- gobby/cli/tasks/__init__.py +30 -0
- gobby/cli/tasks/_utils.py +658 -0
- gobby/cli/tasks/ai.py +1025 -0
- gobby/cli/tasks/commits.py +169 -0
- gobby/cli/tasks/crud.py +685 -0
- gobby/cli/tasks/deps.py +135 -0
- gobby/cli/tasks/labels.py +63 -0
- gobby/cli/tasks/main.py +273 -0
- gobby/cli/tasks/search.py +178 -0
- gobby/cli/tui.py +34 -0
- gobby/cli/utils.py +513 -0
- gobby/cli/workflows.py +927 -0
- gobby/cli/worktrees.py +481 -0
- gobby/config/__init__.py +129 -0
- gobby/config/app.py +551 -0
- gobby/config/extensions.py +167 -0
- gobby/config/features.py +472 -0
- gobby/config/llm_providers.py +98 -0
- gobby/config/logging.py +66 -0
- gobby/config/mcp.py +346 -0
- gobby/config/persistence.py +247 -0
- gobby/config/servers.py +141 -0
- gobby/config/sessions.py +250 -0
- gobby/config/tasks.py +784 -0
- gobby/hooks/__init__.py +104 -0
- gobby/hooks/artifact_capture.py +213 -0
- gobby/hooks/broadcaster.py +243 -0
- gobby/hooks/event_handlers.py +723 -0
- gobby/hooks/events.py +218 -0
- gobby/hooks/git.py +169 -0
- gobby/hooks/health_monitor.py +171 -0
- gobby/hooks/hook_manager.py +856 -0
- gobby/hooks/hook_types.py +575 -0
- gobby/hooks/plugins.py +813 -0
- gobby/hooks/session_coordinator.py +396 -0
- gobby/hooks/verification_runner.py +268 -0
- gobby/hooks/webhooks.py +339 -0
- gobby/install/claude/commands/gobby/bug.md +51 -0
- gobby/install/claude/commands/gobby/chore.md +51 -0
- gobby/install/claude/commands/gobby/epic.md +52 -0
- gobby/install/claude/commands/gobby/eval.md +235 -0
- gobby/install/claude/commands/gobby/feat.md +49 -0
- gobby/install/claude/commands/gobby/nit.md +52 -0
- gobby/install/claude/commands/gobby/ref.md +52 -0
- gobby/install/claude/hooks/HOOK_SCHEMAS.md +632 -0
- gobby/install/claude/hooks/hook_dispatcher.py +364 -0
- gobby/install/claude/hooks/validate_settings.py +102 -0
- gobby/install/claude/hooks-template.json +118 -0
- gobby/install/codex/hooks/hook_dispatcher.py +153 -0
- gobby/install/codex/prompts/forget.md +7 -0
- gobby/install/codex/prompts/memories.md +7 -0
- gobby/install/codex/prompts/recall.md +7 -0
- gobby/install/codex/prompts/remember.md +13 -0
- gobby/install/gemini/hooks/hook_dispatcher.py +268 -0
- gobby/install/gemini/hooks-template.json +138 -0
- gobby/install/shared/plugins/code_guardian.py +456 -0
- gobby/install/shared/plugins/example_notify.py +331 -0
- gobby/integrations/__init__.py +10 -0
- gobby/integrations/github.py +145 -0
- gobby/integrations/linear.py +145 -0
- gobby/llm/__init__.py +40 -0
- gobby/llm/base.py +120 -0
- gobby/llm/claude.py +578 -0
- gobby/llm/claude_executor.py +503 -0
- gobby/llm/codex.py +322 -0
- gobby/llm/codex_executor.py +513 -0
- gobby/llm/executor.py +316 -0
- gobby/llm/factory.py +34 -0
- gobby/llm/gemini.py +258 -0
- gobby/llm/gemini_executor.py +339 -0
- gobby/llm/litellm.py +287 -0
- gobby/llm/litellm_executor.py +303 -0
- gobby/llm/resolver.py +499 -0
- gobby/llm/service.py +236 -0
- gobby/mcp_proxy/__init__.py +29 -0
- gobby/mcp_proxy/actions.py +175 -0
- gobby/mcp_proxy/daemon_control.py +198 -0
- gobby/mcp_proxy/importer.py +436 -0
- gobby/mcp_proxy/lazy.py +325 -0
- gobby/mcp_proxy/manager.py +798 -0
- gobby/mcp_proxy/metrics.py +609 -0
- gobby/mcp_proxy/models.py +139 -0
- gobby/mcp_proxy/registries.py +215 -0
- gobby/mcp_proxy/schema_hash.py +381 -0
- gobby/mcp_proxy/semantic_search.py +706 -0
- gobby/mcp_proxy/server.py +549 -0
- gobby/mcp_proxy/services/__init__.py +0 -0
- gobby/mcp_proxy/services/fallback.py +306 -0
- gobby/mcp_proxy/services/recommendation.py +224 -0
- gobby/mcp_proxy/services/server_mgmt.py +214 -0
- gobby/mcp_proxy/services/system.py +72 -0
- gobby/mcp_proxy/services/tool_filter.py +231 -0
- gobby/mcp_proxy/services/tool_proxy.py +309 -0
- gobby/mcp_proxy/stdio.py +565 -0
- gobby/mcp_proxy/tools/__init__.py +27 -0
- gobby/mcp_proxy/tools/agents.py +1103 -0
- gobby/mcp_proxy/tools/artifacts.py +207 -0
- gobby/mcp_proxy/tools/hub.py +335 -0
- gobby/mcp_proxy/tools/internal.py +337 -0
- gobby/mcp_proxy/tools/memory.py +543 -0
- gobby/mcp_proxy/tools/merge.py +422 -0
- gobby/mcp_proxy/tools/metrics.py +283 -0
- gobby/mcp_proxy/tools/orchestration/__init__.py +23 -0
- gobby/mcp_proxy/tools/orchestration/cleanup.py +619 -0
- gobby/mcp_proxy/tools/orchestration/monitor.py +380 -0
- gobby/mcp_proxy/tools/orchestration/orchestrate.py +746 -0
- gobby/mcp_proxy/tools/orchestration/review.py +736 -0
- gobby/mcp_proxy/tools/orchestration/utils.py +16 -0
- gobby/mcp_proxy/tools/session_messages.py +1056 -0
- gobby/mcp_proxy/tools/task_dependencies.py +219 -0
- gobby/mcp_proxy/tools/task_expansion.py +591 -0
- gobby/mcp_proxy/tools/task_github.py +393 -0
- gobby/mcp_proxy/tools/task_linear.py +379 -0
- gobby/mcp_proxy/tools/task_orchestration.py +77 -0
- gobby/mcp_proxy/tools/task_readiness.py +522 -0
- gobby/mcp_proxy/tools/task_sync.py +351 -0
- gobby/mcp_proxy/tools/task_validation.py +843 -0
- gobby/mcp_proxy/tools/tasks/__init__.py +25 -0
- gobby/mcp_proxy/tools/tasks/_context.py +112 -0
- gobby/mcp_proxy/tools/tasks/_crud.py +516 -0
- gobby/mcp_proxy/tools/tasks/_factory.py +176 -0
- gobby/mcp_proxy/tools/tasks/_helpers.py +129 -0
- gobby/mcp_proxy/tools/tasks/_lifecycle.py +517 -0
- gobby/mcp_proxy/tools/tasks/_lifecycle_validation.py +301 -0
- gobby/mcp_proxy/tools/tasks/_resolution.py +55 -0
- gobby/mcp_proxy/tools/tasks/_search.py +215 -0
- gobby/mcp_proxy/tools/tasks/_session.py +125 -0
- gobby/mcp_proxy/tools/workflows.py +973 -0
- gobby/mcp_proxy/tools/worktrees.py +1264 -0
- gobby/mcp_proxy/transports/__init__.py +0 -0
- gobby/mcp_proxy/transports/base.py +95 -0
- gobby/mcp_proxy/transports/factory.py +44 -0
- gobby/mcp_proxy/transports/http.py +139 -0
- gobby/mcp_proxy/transports/stdio.py +213 -0
- gobby/mcp_proxy/transports/websocket.py +136 -0
- gobby/memory/backends/__init__.py +116 -0
- gobby/memory/backends/mem0.py +408 -0
- gobby/memory/backends/memu.py +485 -0
- gobby/memory/backends/null.py +111 -0
- gobby/memory/backends/openmemory.py +537 -0
- gobby/memory/backends/sqlite.py +304 -0
- gobby/memory/context.py +87 -0
- gobby/memory/manager.py +1001 -0
- gobby/memory/protocol.py +451 -0
- gobby/memory/search/__init__.py +66 -0
- gobby/memory/search/text.py +127 -0
- gobby/memory/viz.py +258 -0
- gobby/prompts/__init__.py +13 -0
- gobby/prompts/defaults/expansion/system.md +119 -0
- gobby/prompts/defaults/expansion/user.md +48 -0
- gobby/prompts/defaults/external_validation/agent.md +72 -0
- gobby/prompts/defaults/external_validation/external.md +63 -0
- gobby/prompts/defaults/external_validation/spawn.md +83 -0
- gobby/prompts/defaults/external_validation/system.md +6 -0
- gobby/prompts/defaults/features/import_mcp.md +22 -0
- gobby/prompts/defaults/features/import_mcp_github.md +17 -0
- gobby/prompts/defaults/features/import_mcp_search.md +16 -0
- gobby/prompts/defaults/features/recommend_tools.md +32 -0
- gobby/prompts/defaults/features/recommend_tools_hybrid.md +35 -0
- gobby/prompts/defaults/features/recommend_tools_llm.md +30 -0
- gobby/prompts/defaults/features/server_description.md +20 -0
- gobby/prompts/defaults/features/server_description_system.md +6 -0
- gobby/prompts/defaults/features/task_description.md +31 -0
- gobby/prompts/defaults/features/task_description_system.md +6 -0
- gobby/prompts/defaults/features/tool_summary.md +17 -0
- gobby/prompts/defaults/features/tool_summary_system.md +6 -0
- gobby/prompts/defaults/research/step.md +58 -0
- gobby/prompts/defaults/validation/criteria.md +47 -0
- gobby/prompts/defaults/validation/validate.md +38 -0
- gobby/prompts/loader.py +346 -0
- gobby/prompts/models.py +113 -0
- gobby/py.typed +0 -0
- gobby/runner.py +488 -0
- gobby/search/__init__.py +23 -0
- gobby/search/protocol.py +104 -0
- gobby/search/tfidf.py +232 -0
- gobby/servers/__init__.py +7 -0
- gobby/servers/http.py +636 -0
- gobby/servers/models.py +31 -0
- gobby/servers/routes/__init__.py +23 -0
- gobby/servers/routes/admin.py +416 -0
- gobby/servers/routes/dependencies.py +118 -0
- gobby/servers/routes/mcp/__init__.py +24 -0
- gobby/servers/routes/mcp/hooks.py +135 -0
- gobby/servers/routes/mcp/plugins.py +121 -0
- gobby/servers/routes/mcp/tools.py +1337 -0
- gobby/servers/routes/mcp/webhooks.py +159 -0
- gobby/servers/routes/sessions.py +582 -0
- gobby/servers/websocket.py +766 -0
- gobby/sessions/__init__.py +13 -0
- gobby/sessions/analyzer.py +322 -0
- gobby/sessions/lifecycle.py +240 -0
- gobby/sessions/manager.py +563 -0
- gobby/sessions/processor.py +225 -0
- gobby/sessions/summary.py +532 -0
- gobby/sessions/transcripts/__init__.py +41 -0
- gobby/sessions/transcripts/base.py +125 -0
- gobby/sessions/transcripts/claude.py +386 -0
- gobby/sessions/transcripts/codex.py +143 -0
- gobby/sessions/transcripts/gemini.py +195 -0
- gobby/storage/__init__.py +21 -0
- gobby/storage/agents.py +409 -0
- gobby/storage/artifact_classifier.py +341 -0
- gobby/storage/artifacts.py +285 -0
- gobby/storage/compaction.py +67 -0
- gobby/storage/database.py +357 -0
- gobby/storage/inter_session_messages.py +194 -0
- gobby/storage/mcp.py +680 -0
- gobby/storage/memories.py +562 -0
- gobby/storage/merge_resolutions.py +550 -0
- gobby/storage/migrations.py +860 -0
- gobby/storage/migrations_legacy.py +1359 -0
- gobby/storage/projects.py +166 -0
- gobby/storage/session_messages.py +251 -0
- gobby/storage/session_tasks.py +97 -0
- gobby/storage/sessions.py +817 -0
- gobby/storage/task_dependencies.py +223 -0
- gobby/storage/tasks/__init__.py +42 -0
- gobby/storage/tasks/_aggregates.py +180 -0
- gobby/storage/tasks/_crud.py +449 -0
- gobby/storage/tasks/_id.py +104 -0
- gobby/storage/tasks/_lifecycle.py +311 -0
- gobby/storage/tasks/_manager.py +889 -0
- gobby/storage/tasks/_models.py +300 -0
- gobby/storage/tasks/_ordering.py +119 -0
- gobby/storage/tasks/_path_cache.py +110 -0
- gobby/storage/tasks/_queries.py +343 -0
- gobby/storage/tasks/_search.py +143 -0
- gobby/storage/workflow_audit.py +393 -0
- gobby/storage/worktrees.py +547 -0
- gobby/sync/__init__.py +29 -0
- gobby/sync/github.py +333 -0
- gobby/sync/linear.py +304 -0
- gobby/sync/memories.py +284 -0
- gobby/sync/tasks.py +641 -0
- gobby/tasks/__init__.py +8 -0
- gobby/tasks/build_verification.py +193 -0
- gobby/tasks/commits.py +633 -0
- gobby/tasks/context.py +747 -0
- gobby/tasks/criteria.py +342 -0
- gobby/tasks/enhanced_validator.py +226 -0
- gobby/tasks/escalation.py +263 -0
- gobby/tasks/expansion.py +626 -0
- gobby/tasks/external_validator.py +764 -0
- gobby/tasks/issue_extraction.py +171 -0
- gobby/tasks/prompts/expand.py +327 -0
- gobby/tasks/research.py +421 -0
- gobby/tasks/tdd.py +352 -0
- gobby/tasks/tree_builder.py +263 -0
- gobby/tasks/validation.py +712 -0
- gobby/tasks/validation_history.py +357 -0
- gobby/tasks/validation_models.py +89 -0
- gobby/tools/__init__.py +0 -0
- gobby/tools/summarizer.py +170 -0
- gobby/tui/__init__.py +5 -0
- gobby/tui/api_client.py +281 -0
- gobby/tui/app.py +327 -0
- gobby/tui/screens/__init__.py +25 -0
- gobby/tui/screens/agents.py +333 -0
- gobby/tui/screens/chat.py +450 -0
- gobby/tui/screens/dashboard.py +377 -0
- gobby/tui/screens/memory.py +305 -0
- gobby/tui/screens/metrics.py +231 -0
- gobby/tui/screens/orchestrator.py +904 -0
- gobby/tui/screens/sessions.py +412 -0
- gobby/tui/screens/tasks.py +442 -0
- gobby/tui/screens/workflows.py +289 -0
- gobby/tui/screens/worktrees.py +174 -0
- gobby/tui/widgets/__init__.py +21 -0
- gobby/tui/widgets/chat.py +210 -0
- gobby/tui/widgets/conductor.py +104 -0
- gobby/tui/widgets/menu.py +132 -0
- gobby/tui/widgets/message_panel.py +160 -0
- gobby/tui/widgets/review_gate.py +224 -0
- gobby/tui/widgets/task_tree.py +99 -0
- gobby/tui/widgets/token_budget.py +166 -0
- gobby/tui/ws_client.py +258 -0
- gobby/utils/__init__.py +3 -0
- gobby/utils/daemon_client.py +235 -0
- gobby/utils/git.py +222 -0
- gobby/utils/id.py +38 -0
- gobby/utils/json_helpers.py +161 -0
- gobby/utils/logging.py +376 -0
- gobby/utils/machine_id.py +135 -0
- gobby/utils/metrics.py +589 -0
- gobby/utils/project_context.py +182 -0
- gobby/utils/project_init.py +263 -0
- gobby/utils/status.py +256 -0
- gobby/utils/validation.py +80 -0
- gobby/utils/version.py +23 -0
- gobby/workflows/__init__.py +4 -0
- gobby/workflows/actions.py +1310 -0
- gobby/workflows/approval_flow.py +138 -0
- gobby/workflows/artifact_actions.py +103 -0
- gobby/workflows/audit_helpers.py +110 -0
- gobby/workflows/autonomous_actions.py +286 -0
- gobby/workflows/context_actions.py +394 -0
- gobby/workflows/definitions.py +130 -0
- gobby/workflows/detection_helpers.py +208 -0
- gobby/workflows/engine.py +485 -0
- gobby/workflows/evaluator.py +669 -0
- gobby/workflows/git_utils.py +96 -0
- gobby/workflows/hooks.py +169 -0
- gobby/workflows/lifecycle_evaluator.py +613 -0
- gobby/workflows/llm_actions.py +70 -0
- gobby/workflows/loader.py +333 -0
- gobby/workflows/mcp_actions.py +60 -0
- gobby/workflows/memory_actions.py +272 -0
- gobby/workflows/premature_stop.py +164 -0
- gobby/workflows/session_actions.py +139 -0
- gobby/workflows/state_actions.py +123 -0
- gobby/workflows/state_manager.py +104 -0
- gobby/workflows/stop_signal_actions.py +163 -0
- gobby/workflows/summary_actions.py +344 -0
- gobby/workflows/task_actions.py +249 -0
- gobby/workflows/task_enforcement_actions.py +901 -0
- gobby/workflows/templates.py +52 -0
- gobby/workflows/todo_actions.py +84 -0
- gobby/workflows/webhook.py +223 -0
- gobby/workflows/webhook_executor.py +399 -0
- gobby/worktrees/__init__.py +5 -0
- gobby/worktrees/git.py +690 -0
- gobby/worktrees/merge/__init__.py +20 -0
- gobby/worktrees/merge/conflict_parser.py +177 -0
- gobby/worktrees/merge/resolver.py +485 -0
- gobby-0.2.5.dist-info/METADATA +351 -0
- gobby-0.2.5.dist-info/RECORD +383 -0
- gobby-0.2.5.dist-info/WHEEL +5 -0
- gobby-0.2.5.dist-info/entry_points.txt +2 -0
- gobby-0.2.5.dist-info/licenses/LICENSE.md +193 -0
- gobby-0.2.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Task dependency MCP tools module.
|
|
3
|
+
|
|
4
|
+
Provides tools for managing task dependencies:
|
|
5
|
+
- add_dependency: Add a dependency between tasks
|
|
6
|
+
- remove_dependency: Remove a dependency
|
|
7
|
+
- get_dependency_tree: Get upstream/downstream dependencies
|
|
8
|
+
- check_dependency_cycles: Detect circular dependencies
|
|
9
|
+
|
|
10
|
+
Extracted from tasks.py using Strangler Fig pattern for code decomposition.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
15
|
+
|
|
16
|
+
from gobby.mcp_proxy.tools.internal import InternalToolRegistry
|
|
17
|
+
from gobby.storage.tasks import TaskNotFoundError
|
|
18
|
+
from gobby.utils.project_context import get_project_context
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from gobby.storage.task_dependencies import TaskDependencyManager
|
|
22
|
+
from gobby.storage.tasks import LocalTaskManager
|
|
23
|
+
|
|
24
|
+
__all__ = ["create_dependency_registry"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_current_project_id() -> str | None:
|
|
28
|
+
"""Get the current project ID from context."""
|
|
29
|
+
context = get_project_context()
|
|
30
|
+
return context.get("id") if context else None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DependencyToolRegistry(InternalToolRegistry):
|
|
34
|
+
"""Registry for dependency tools with test-friendly get_tool method."""
|
|
35
|
+
|
|
36
|
+
def get_tool(self, name: str) -> Callable[..., Any] | None:
|
|
37
|
+
"""Get a tool function by name (for testing)."""
|
|
38
|
+
tool = self._tools.get(name)
|
|
39
|
+
return tool.func if tool else None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def create_dependency_registry(
|
|
43
|
+
task_manager: "LocalTaskManager | None" = None,
|
|
44
|
+
dep_manager: "TaskDependencyManager | None" = None,
|
|
45
|
+
) -> DependencyToolRegistry:
|
|
46
|
+
"""
|
|
47
|
+
Create a registry with task dependency tools.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
task_manager: LocalTaskManager instance (required for task ID resolution)
|
|
51
|
+
dep_manager: TaskDependencyManager instance
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
DependencyToolRegistry with dependency tools registered
|
|
55
|
+
"""
|
|
56
|
+
# Lazy import to avoid circular dependency
|
|
57
|
+
from gobby.mcp_proxy.tools.tasks import resolve_task_id_for_mcp
|
|
58
|
+
|
|
59
|
+
registry = DependencyToolRegistry(
|
|
60
|
+
name="gobby-tasks-dependencies",
|
|
61
|
+
description="Task dependency management tools",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if dep_manager is None:
|
|
65
|
+
raise ValueError("dep_manager is required")
|
|
66
|
+
if task_manager is None:
|
|
67
|
+
raise ValueError("task_manager is required for task ID resolution")
|
|
68
|
+
|
|
69
|
+
# --- add_dependency ---
|
|
70
|
+
|
|
71
|
+
def add_dependency(
|
|
72
|
+
task_id: str,
|
|
73
|
+
depends_on: str,
|
|
74
|
+
dep_type: Literal["blocks", "discovered-from", "related"] = "blocks",
|
|
75
|
+
) -> dict[str, Any]:
|
|
76
|
+
"""Add a dependency between tasks."""
|
|
77
|
+
# Resolve task references
|
|
78
|
+
try:
|
|
79
|
+
resolved_task_id = resolve_task_id_for_mcp(task_manager, task_id)
|
|
80
|
+
except (TaskNotFoundError, ValueError) as e:
|
|
81
|
+
return {"error": f"Invalid task_id: {e}"}
|
|
82
|
+
try:
|
|
83
|
+
resolved_depends_on = resolve_task_id_for_mcp(task_manager, depends_on)
|
|
84
|
+
except (TaskNotFoundError, ValueError) as e:
|
|
85
|
+
return {"error": f"Invalid depends_on: {e}"}
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
dep_manager.add_dependency(resolved_task_id, resolved_depends_on, dep_type)
|
|
89
|
+
return {
|
|
90
|
+
"added": True,
|
|
91
|
+
"task_id": resolved_task_id,
|
|
92
|
+
"depends_on": resolved_depends_on,
|
|
93
|
+
"dep_type": dep_type,
|
|
94
|
+
}
|
|
95
|
+
except ValueError as e:
|
|
96
|
+
return {"error": str(e)}
|
|
97
|
+
|
|
98
|
+
registry.register(
|
|
99
|
+
name="add_dependency",
|
|
100
|
+
description="Add a dependency between tasks. Creates a blocking relationship where depends_on must complete before task_id.",
|
|
101
|
+
input_schema={
|
|
102
|
+
"type": "object",
|
|
103
|
+
"properties": {
|
|
104
|
+
"task_id": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "The dependent task (blocked by depends_on): #N, N (seq_num), path (1.2.3), or UUID",
|
|
107
|
+
},
|
|
108
|
+
"depends_on": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "The blocker task (must complete first): #N, N (seq_num), path (1.2.3), or UUID",
|
|
111
|
+
},
|
|
112
|
+
"dep_type": {
|
|
113
|
+
"type": "string",
|
|
114
|
+
"description": 'Dependency type: "blocks" (default), "discovered-from", or "related"',
|
|
115
|
+
"default": "blocks",
|
|
116
|
+
"enum": ["blocks", "discovered-from", "related"],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
"required": ["task_id", "depends_on"],
|
|
120
|
+
},
|
|
121
|
+
func=add_dependency,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# --- remove_dependency ---
|
|
125
|
+
|
|
126
|
+
def remove_dependency(task_id: str, depends_on: str) -> dict[str, Any]:
|
|
127
|
+
"""Remove a dependency between tasks."""
|
|
128
|
+
# Resolve task references
|
|
129
|
+
try:
|
|
130
|
+
resolved_task_id = resolve_task_id_for_mcp(task_manager, task_id)
|
|
131
|
+
except (TaskNotFoundError, ValueError) as e:
|
|
132
|
+
return {"error": f"Invalid task_id: {e}"}
|
|
133
|
+
try:
|
|
134
|
+
resolved_depends_on = resolve_task_id_for_mcp(task_manager, depends_on)
|
|
135
|
+
except (TaskNotFoundError, ValueError) as e:
|
|
136
|
+
return {"error": f"Invalid depends_on: {e}"}
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
dep_manager.remove_dependency(resolved_task_id, resolved_depends_on)
|
|
140
|
+
return {"removed": True, "task_id": resolved_task_id, "depends_on": resolved_depends_on}
|
|
141
|
+
except ValueError as e:
|
|
142
|
+
return {"error": str(e)}
|
|
143
|
+
|
|
144
|
+
registry.register(
|
|
145
|
+
name="remove_dependency",
|
|
146
|
+
description="Remove a dependency between tasks.",
|
|
147
|
+
input_schema={
|
|
148
|
+
"type": "object",
|
|
149
|
+
"properties": {
|
|
150
|
+
"task_id": {
|
|
151
|
+
"type": "string",
|
|
152
|
+
"description": "The dependent task: #N, N (seq_num), path (1.2.3), or UUID",
|
|
153
|
+
},
|
|
154
|
+
"depends_on": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"description": "The blocker task to unlink: #N, N (seq_num), path (1.2.3), or UUID",
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
"required": ["task_id", "depends_on"],
|
|
160
|
+
},
|
|
161
|
+
func=remove_dependency,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# --- get_dependency_tree ---
|
|
165
|
+
|
|
166
|
+
def get_dependency_tree(task_id: str, direction: str = "both") -> dict[str, Any]:
|
|
167
|
+
"""Get dependency tree for a task."""
|
|
168
|
+
# Resolve task reference
|
|
169
|
+
try:
|
|
170
|
+
resolved_task_id = resolve_task_id_for_mcp(task_manager, task_id)
|
|
171
|
+
except (TaskNotFoundError, ValueError) as e:
|
|
172
|
+
return {"error": f"Invalid task_id: {e}"}
|
|
173
|
+
|
|
174
|
+
tree: dict[str, Any] = dep_manager.get_dependency_tree(resolved_task_id)
|
|
175
|
+
if direction == "blockers":
|
|
176
|
+
return {"blockers": tree.get("blockers", [])}
|
|
177
|
+
elif direction == "blocking":
|
|
178
|
+
return {"blocking": tree.get("blocking", [])}
|
|
179
|
+
return tree
|
|
180
|
+
|
|
181
|
+
registry.register(
|
|
182
|
+
name="get_dependency_tree",
|
|
183
|
+
description="Get dependency tree showing upstream blockers and downstream dependents.",
|
|
184
|
+
input_schema={
|
|
185
|
+
"type": "object",
|
|
186
|
+
"properties": {
|
|
187
|
+
"task_id": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"description": "Root task reference: #N, N (seq_num), path (1.2.3), or UUID",
|
|
190
|
+
},
|
|
191
|
+
"direction": {
|
|
192
|
+
"type": "string",
|
|
193
|
+
"description": '"blockers" (upstream), "blocking" (downstream), or "both"',
|
|
194
|
+
"default": "both",
|
|
195
|
+
"enum": ["blockers", "blocking", "both"],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
"required": ["task_id"],
|
|
199
|
+
},
|
|
200
|
+
func=get_dependency_tree,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# --- check_dependency_cycles ---
|
|
204
|
+
|
|
205
|
+
def check_dependency_cycles() -> dict[str, Any]:
|
|
206
|
+
"""Detect circular dependencies in the project."""
|
|
207
|
+
cycles = dep_manager.check_cycles()
|
|
208
|
+
if cycles:
|
|
209
|
+
return {"has_cycles": True, "cycles": cycles}
|
|
210
|
+
return {"has_cycles": False}
|
|
211
|
+
|
|
212
|
+
registry.register(
|
|
213
|
+
name="check_dependency_cycles",
|
|
214
|
+
description="Detect circular dependencies in the project. Returns any cycles found.",
|
|
215
|
+
input_schema={"type": "object", "properties": {}},
|
|
216
|
+
func=check_dependency_cycles,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
return registry
|