skydeckai-code 0.1.40__tar.gz → 0.1.41__tar.gz
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.
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/PKG-INFO +111 -3
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/README.md +109 -1
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/pyproject.toml +2 -2
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/__init__.py +16 -0
- skydeckai_code-0.1.41/src/aidd/tools/todo_store.py +257 -0
- skydeckai_code-0.1.41/src/aidd/tools/todo_tools.py +157 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/.claude/settings.local.json +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/.gitignore +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/Dockerfile +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/LICENSE +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/screenshots/mseep_ai_helper.png +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/smithery.yaml +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/__init__.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/__init__.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/cli.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/server.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/base.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/code_analysis.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/code_execution.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/code_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/directory_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/file_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/get_active_apps_tool.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/get_available_windows_tool.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/image_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/other_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/path_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/screenshot_tool.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/state.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/system_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/web_tools.py +0 -0
- {skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/uv.lock +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: skydeckai-code
|
3
|
-
Version: 0.1.
|
4
|
-
Summary: This MCP server provides a comprehensive set of tools for AI-driven Development workflows including file operations, code analysis, multi-language execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, and system information retrieval.
|
3
|
+
Version: 0.1.41
|
4
|
+
Summary: This MCP server provides a comprehensive set of tools for AI-driven Development workflows including file operations, code analysis, multi-language execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, persistent task management, and system information retrieval.
|
5
5
|
Project-URL: Homepage, https://github.com/skydeckai/skydeckai-code
|
6
6
|
Project-URL: Repository, https://github.com/skydeckai/skydeckai-code
|
7
7
|
Project-URL: Documentation, https://github.com/skydeckai/skydeckai-code/blob/main/README.md
|
@@ -87,7 +87,7 @@ If you're using MseeP AI Helper app, you can search for "SkyDeckAI Code" and ins
|
|
87
87
|
- Screenshot and screen context tools
|
88
88
|
- Image handling tools
|
89
89
|
|
90
|
-
## Available Tools (
|
90
|
+
## Available Tools (29)
|
91
91
|
|
92
92
|
| Category | Tool Name | Description |
|
93
93
|
| ---------------- | -------------------------- | -------------------------------------------- |
|
@@ -117,6 +117,9 @@ If you're using MseeP AI Helper app, you can search for "SkyDeckAI Code" and ins
|
|
117
117
|
| **System** | `get_system_info` | Get detailed system information |
|
118
118
|
| **Utility** | `batch_tools` | Run multiple tool operations together |
|
119
119
|
| | `think` | Document reasoning without making changes |
|
120
|
+
| **Todo** | `todo_read` | Read current workspace todo list |
|
121
|
+
| | `todo_write` | Replace entire todo list with validation |
|
122
|
+
| | `todo_update` | Update specific todo item by ID |
|
120
123
|
|
121
124
|
## Detailed Tool Documentation
|
122
125
|
|
@@ -614,6 +617,111 @@ This tool executes arbitrary shell commands on your system. Always:
|
|
614
617
|
4. Be aware of potential system impacts
|
615
618
|
5. Monitor execution output
|
616
619
|
|
620
|
+
### Todo Tools
|
621
|
+
|
622
|
+
The todo tools provide sequential task management capabilities for workspace-first development workflows. Tasks are executed in order without priority systems, ensuring structured progress through development phases.
|
623
|
+
|
624
|
+
#### todo_read
|
625
|
+
|
626
|
+
Read the current todo list for the workspace.
|
627
|
+
|
628
|
+
```json
|
629
|
+
{}
|
630
|
+
```
|
631
|
+
|
632
|
+
**Returns:**
|
633
|
+
```json
|
634
|
+
{
|
635
|
+
"todos": [
|
636
|
+
{
|
637
|
+
"id": "abc123",
|
638
|
+
"content": "Implement user authentication",
|
639
|
+
"status": "in_progress",
|
640
|
+
"metadata": {
|
641
|
+
"custom_key": "custom_value"
|
642
|
+
},
|
643
|
+
"created_at": "2023-10-01T10:00:00Z",
|
644
|
+
"updated_at": "2023-10-01T11:30:00Z"
|
645
|
+
}
|
646
|
+
],
|
647
|
+
"count": 1,
|
648
|
+
"workspace": "/path/to/workspace"
|
649
|
+
}
|
650
|
+
```
|
651
|
+
|
652
|
+
#### todo_write
|
653
|
+
|
654
|
+
Replace the entire todo list for sequential execution workflow. Tasks are executed in array order, building upon previous work.
|
655
|
+
|
656
|
+
```json
|
657
|
+
{
|
658
|
+
"todos": [
|
659
|
+
{
|
660
|
+
"id": "task1",
|
661
|
+
"content": "Set up database schema",
|
662
|
+
"status": "pending"
|
663
|
+
},
|
664
|
+
{
|
665
|
+
"id": "task2",
|
666
|
+
"content": "Create API endpoints",
|
667
|
+
"status": "pending",
|
668
|
+
"metadata": {
|
669
|
+
"custom_key": "custom_value"
|
670
|
+
}
|
671
|
+
}
|
672
|
+
]
|
673
|
+
}
|
674
|
+
```
|
675
|
+
|
676
|
+
**Sequential Workflow Rules:**
|
677
|
+
- Each todo must have unique ID
|
678
|
+
- Only one task can be "in_progress" at a time (sequential execution)
|
679
|
+
- Tasks execute in array order - no priority system
|
680
|
+
- Required fields: id, content, status
|
681
|
+
- Status values: "pending", "in_progress", "completed"
|
682
|
+
- Workspace-first: Todo management is mandatory for all workspace operations
|
683
|
+
|
684
|
+
#### todo_update
|
685
|
+
|
686
|
+
Update a specific todo item by ID for sequential workflow progression.
|
687
|
+
|
688
|
+
```json
|
689
|
+
{
|
690
|
+
"todo_id": "task1",
|
691
|
+
"updates": {
|
692
|
+
"status": "in_progress",
|
693
|
+
"metadata": {
|
694
|
+
"new_key": "new_value"
|
695
|
+
}
|
696
|
+
}
|
697
|
+
}
|
698
|
+
```
|
699
|
+
|
700
|
+
**Returns:**
|
701
|
+
```json
|
702
|
+
{
|
703
|
+
"success": true,
|
704
|
+
"updated_todo": {
|
705
|
+
"id": "task1",
|
706
|
+
"content": "Set up database schema",
|
707
|
+
"status": "in_progress",
|
708
|
+
"updated_at": "2023-10-01T12:00:00Z",
|
709
|
+
"metadata": {
|
710
|
+
"new_key": "new_value"
|
711
|
+
}
|
712
|
+
},
|
713
|
+
"counts": {
|
714
|
+
"pending": 1,
|
715
|
+
"in_progress": 1,
|
716
|
+
"completed": 0,
|
717
|
+
"total": 2
|
718
|
+
},
|
719
|
+
"workspace": "/path/to/workspace"
|
720
|
+
}
|
721
|
+
```
|
722
|
+
|
723
|
+
The todo system maintains separate sequential task lists for each workspace, enforcing mandatory usage for all workspace operations. Tasks execute in order, building upon previous work without priority-based scheduling.
|
724
|
+
|
617
725
|
## Configuration
|
618
726
|
|
619
727
|
Configuration file: `~/.skydeckai_code/config.json`
|
@@ -52,7 +52,7 @@ If you're using MseeP AI Helper app, you can search for "SkyDeckAI Code" and ins
|
|
52
52
|
- Screenshot and screen context tools
|
53
53
|
- Image handling tools
|
54
54
|
|
55
|
-
## Available Tools (
|
55
|
+
## Available Tools (29)
|
56
56
|
|
57
57
|
| Category | Tool Name | Description |
|
58
58
|
| ---------------- | -------------------------- | -------------------------------------------- |
|
@@ -82,6 +82,9 @@ If you're using MseeP AI Helper app, you can search for "SkyDeckAI Code" and ins
|
|
82
82
|
| **System** | `get_system_info` | Get detailed system information |
|
83
83
|
| **Utility** | `batch_tools` | Run multiple tool operations together |
|
84
84
|
| | `think` | Document reasoning without making changes |
|
85
|
+
| **Todo** | `todo_read` | Read current workspace todo list |
|
86
|
+
| | `todo_write` | Replace entire todo list with validation |
|
87
|
+
| | `todo_update` | Update specific todo item by ID |
|
85
88
|
|
86
89
|
## Detailed Tool Documentation
|
87
90
|
|
@@ -579,6 +582,111 @@ This tool executes arbitrary shell commands on your system. Always:
|
|
579
582
|
4. Be aware of potential system impacts
|
580
583
|
5. Monitor execution output
|
581
584
|
|
585
|
+
### Todo Tools
|
586
|
+
|
587
|
+
The todo tools provide sequential task management capabilities for workspace-first development workflows. Tasks are executed in order without priority systems, ensuring structured progress through development phases.
|
588
|
+
|
589
|
+
#### todo_read
|
590
|
+
|
591
|
+
Read the current todo list for the workspace.
|
592
|
+
|
593
|
+
```json
|
594
|
+
{}
|
595
|
+
```
|
596
|
+
|
597
|
+
**Returns:**
|
598
|
+
```json
|
599
|
+
{
|
600
|
+
"todos": [
|
601
|
+
{
|
602
|
+
"id": "abc123",
|
603
|
+
"content": "Implement user authentication",
|
604
|
+
"status": "in_progress",
|
605
|
+
"metadata": {
|
606
|
+
"custom_key": "custom_value"
|
607
|
+
},
|
608
|
+
"created_at": "2023-10-01T10:00:00Z",
|
609
|
+
"updated_at": "2023-10-01T11:30:00Z"
|
610
|
+
}
|
611
|
+
],
|
612
|
+
"count": 1,
|
613
|
+
"workspace": "/path/to/workspace"
|
614
|
+
}
|
615
|
+
```
|
616
|
+
|
617
|
+
#### todo_write
|
618
|
+
|
619
|
+
Replace the entire todo list for sequential execution workflow. Tasks are executed in array order, building upon previous work.
|
620
|
+
|
621
|
+
```json
|
622
|
+
{
|
623
|
+
"todos": [
|
624
|
+
{
|
625
|
+
"id": "task1",
|
626
|
+
"content": "Set up database schema",
|
627
|
+
"status": "pending"
|
628
|
+
},
|
629
|
+
{
|
630
|
+
"id": "task2",
|
631
|
+
"content": "Create API endpoints",
|
632
|
+
"status": "pending",
|
633
|
+
"metadata": {
|
634
|
+
"custom_key": "custom_value"
|
635
|
+
}
|
636
|
+
}
|
637
|
+
]
|
638
|
+
}
|
639
|
+
```
|
640
|
+
|
641
|
+
**Sequential Workflow Rules:**
|
642
|
+
- Each todo must have unique ID
|
643
|
+
- Only one task can be "in_progress" at a time (sequential execution)
|
644
|
+
- Tasks execute in array order - no priority system
|
645
|
+
- Required fields: id, content, status
|
646
|
+
- Status values: "pending", "in_progress", "completed"
|
647
|
+
- Workspace-first: Todo management is mandatory for all workspace operations
|
648
|
+
|
649
|
+
#### todo_update
|
650
|
+
|
651
|
+
Update a specific todo item by ID for sequential workflow progression.
|
652
|
+
|
653
|
+
```json
|
654
|
+
{
|
655
|
+
"todo_id": "task1",
|
656
|
+
"updates": {
|
657
|
+
"status": "in_progress",
|
658
|
+
"metadata": {
|
659
|
+
"new_key": "new_value"
|
660
|
+
}
|
661
|
+
}
|
662
|
+
}
|
663
|
+
```
|
664
|
+
|
665
|
+
**Returns:**
|
666
|
+
```json
|
667
|
+
{
|
668
|
+
"success": true,
|
669
|
+
"updated_todo": {
|
670
|
+
"id": "task1",
|
671
|
+
"content": "Set up database schema",
|
672
|
+
"status": "in_progress",
|
673
|
+
"updated_at": "2023-10-01T12:00:00Z",
|
674
|
+
"metadata": {
|
675
|
+
"new_key": "new_value"
|
676
|
+
}
|
677
|
+
},
|
678
|
+
"counts": {
|
679
|
+
"pending": 1,
|
680
|
+
"in_progress": 1,
|
681
|
+
"completed": 0,
|
682
|
+
"total": 2
|
683
|
+
},
|
684
|
+
"workspace": "/path/to/workspace"
|
685
|
+
}
|
686
|
+
```
|
687
|
+
|
688
|
+
The todo system maintains separate sequential task lists for each workspace, enforcing mandatory usage for all workspace operations. Tasks execute in order, building upon previous work without priority-based scheduling.
|
689
|
+
|
582
690
|
## Configuration
|
583
691
|
|
584
692
|
Configuration file: `~/.skydeckai_code/config.json`
|
@@ -1,7 +1,7 @@
|
|
1
1
|
[project]
|
2
2
|
name = "skydeckai-code"
|
3
|
-
version = "0.1.
|
4
|
-
description = "This MCP server provides a comprehensive set of tools for AI-driven Development workflows including file operations, code analysis, multi-language execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, and system information retrieval."
|
3
|
+
version = "0.1.41"
|
4
|
+
description = "This MCP server provides a comprehensive set of tools for AI-driven Development workflows including file operations, code analysis, multi-language execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, persistent task management, and system information retrieval."
|
5
5
|
readme = "README.md"
|
6
6
|
requires-python = ">=3.11"
|
7
7
|
authors = [{name = "SkyDeck.ai", email = "support@skydeck.ai"}]
|
@@ -47,6 +47,14 @@ from .screenshot_tool import (
|
|
47
47
|
handle_capture_screenshot,
|
48
48
|
)
|
49
49
|
from .system_tools import get_system_info_tool, handle_get_system_info
|
50
|
+
from .todo_tools import (
|
51
|
+
todo_read_tool,
|
52
|
+
todo_write_tool,
|
53
|
+
todo_update_tool,
|
54
|
+
handle_todo_read,
|
55
|
+
handle_todo_write,
|
56
|
+
handle_todo_update,
|
57
|
+
)
|
50
58
|
from .web_tools import web_fetch_tool, handle_web_fetch, web_search_tool, handle_web_search
|
51
59
|
|
52
60
|
# Export all tools definitions
|
@@ -82,6 +90,10 @@ TOOL_DEFINITIONS = [
|
|
82
90
|
web_search_tool(),
|
83
91
|
# System tools
|
84
92
|
get_system_info_tool(),
|
93
|
+
# Todo tools
|
94
|
+
todo_read_tool(),
|
95
|
+
todo_write_tool(),
|
96
|
+
todo_update_tool(),
|
85
97
|
]
|
86
98
|
|
87
99
|
# Export all handlers
|
@@ -116,4 +128,8 @@ TOOL_HANDLERS = {
|
|
116
128
|
# Web handlers
|
117
129
|
"web_fetch": handle_web_fetch,
|
118
130
|
"web_search": handle_web_search,
|
131
|
+
# Todo handlers
|
132
|
+
"todo_read": handle_todo_read,
|
133
|
+
"todo_write": handle_todo_write,
|
134
|
+
"todo_update": handle_todo_update,
|
119
135
|
}
|
@@ -0,0 +1,257 @@
|
|
1
|
+
from .state import state
|
2
|
+
from datetime import datetime
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Any, Dict, List
|
5
|
+
import json
|
6
|
+
|
7
|
+
|
8
|
+
class TodoStore:
|
9
|
+
"""Manages todo persistence and operations."""
|
10
|
+
|
11
|
+
def __init__(self):
|
12
|
+
self._cached_store = None
|
13
|
+
self._last_workspace = None
|
14
|
+
|
15
|
+
@property
|
16
|
+
def workspace_path(self) -> Path:
|
17
|
+
"""Get the current workspace directory."""
|
18
|
+
return Path(state.allowed_directory)
|
19
|
+
|
20
|
+
@property
|
21
|
+
def todos_file_path(self) -> Path:
|
22
|
+
"""Get the path to the global todos file."""
|
23
|
+
return state.config_dir / "todos.json"
|
24
|
+
|
25
|
+
def _detect_workspace_change(self) -> bool:
|
26
|
+
"""Check if workspace has changed since last access."""
|
27
|
+
current_workspace = str(self.workspace_path)
|
28
|
+
if self._last_workspace != current_workspace:
|
29
|
+
self._last_workspace = current_workspace
|
30
|
+
self._cached_store = None
|
31
|
+
return True
|
32
|
+
return False
|
33
|
+
|
34
|
+
def _load_store(self) -> Dict[str, Any]:
|
35
|
+
"""Load todos from file with caching."""
|
36
|
+
self._detect_workspace_change()
|
37
|
+
|
38
|
+
if self._cached_store is not None:
|
39
|
+
return self._cached_store
|
40
|
+
|
41
|
+
workspace_key = str(self.workspace_path)
|
42
|
+
|
43
|
+
if not self.todos_file_path.exists():
|
44
|
+
self._cached_store = {"lastModified": datetime.now().isoformat(), "todos": []}
|
45
|
+
return self._cached_store
|
46
|
+
|
47
|
+
try:
|
48
|
+
with open(self.todos_file_path, "r", encoding="utf-8") as f:
|
49
|
+
global_data = json.load(f)
|
50
|
+
workspace_data = global_data.get(workspace_key, {})
|
51
|
+
self._cached_store = {"lastModified": workspace_data.get("lastModified", datetime.now().isoformat()), "todos": workspace_data.get("todos", [])}
|
52
|
+
return self._cached_store
|
53
|
+
except (json.JSONDecodeError, IOError, OSError):
|
54
|
+
# Return empty store if file is corrupted
|
55
|
+
self._cached_store = {"lastModified": datetime.now().isoformat(), "todos": []}
|
56
|
+
return self._cached_store
|
57
|
+
|
58
|
+
def _save_store(self, store: Dict[str, Any]) -> None:
|
59
|
+
"""Save todos to file atomically."""
|
60
|
+
# Ensure the ~/.skydeckai-code directory exists
|
61
|
+
self.todos_file_path.parent.mkdir(exist_ok=True)
|
62
|
+
|
63
|
+
workspace_key = str(self.workspace_path)
|
64
|
+
|
65
|
+
# Load existing global data
|
66
|
+
global_data = {}
|
67
|
+
if self.todos_file_path.exists():
|
68
|
+
try:
|
69
|
+
with open(self.todos_file_path, "r", encoding="utf-8") as f:
|
70
|
+
global_data = json.load(f)
|
71
|
+
except (json.JSONDecodeError, IOError, OSError):
|
72
|
+
global_data = {}
|
73
|
+
|
74
|
+
# Update the workspace data
|
75
|
+
global_data[workspace_key] = store
|
76
|
+
|
77
|
+
# Write to temporary file first (atomic write)
|
78
|
+
temp_path = self.todos_file_path.with_suffix(".json.tmp")
|
79
|
+
|
80
|
+
try:
|
81
|
+
with open(temp_path, "w", encoding="utf-8") as f:
|
82
|
+
json.dump(global_data, f, indent=2, ensure_ascii=False)
|
83
|
+
|
84
|
+
# Atomic rename
|
85
|
+
temp_path.replace(self.todos_file_path)
|
86
|
+
|
87
|
+
# Update cache
|
88
|
+
self._cached_store = store
|
89
|
+
|
90
|
+
except Exception:
|
91
|
+
# Clean up temp file if something went wrong
|
92
|
+
if temp_path.exists():
|
93
|
+
temp_path.unlink()
|
94
|
+
raise
|
95
|
+
|
96
|
+
def _add_to_gitignore(self) -> None:
|
97
|
+
"""No longer needed since todos are stored in ~/.skydeckai-code/todo.json"""
|
98
|
+
pass
|
99
|
+
|
100
|
+
def read_todos(self) -> List[Dict[str, Any]]:
|
101
|
+
"""Read all todos from storage."""
|
102
|
+
store = self._load_store()
|
103
|
+
return store["todos"]
|
104
|
+
|
105
|
+
def write_todos(self, todos: List[Dict[str, Any]]) -> int:
|
106
|
+
"""Write todos to storage with validation."""
|
107
|
+
# Validate todos
|
108
|
+
self._validate_todos(todos)
|
109
|
+
|
110
|
+
# Process todos (add timestamps, etc.)
|
111
|
+
processed_todos = []
|
112
|
+
current_time = datetime.now().isoformat()
|
113
|
+
|
114
|
+
for todo in todos:
|
115
|
+
processed_todo = dict(todo)
|
116
|
+
|
117
|
+
# Ensure required fields have defaults
|
118
|
+
processed_todo.setdefault("id", self._generate_id())
|
119
|
+
processed_todo.setdefault("status", "pending")
|
120
|
+
processed_todo.setdefault("created_at", current_time)
|
121
|
+
processed_todo["updated_at"] = current_time
|
122
|
+
|
123
|
+
processed_todos.append(processed_todo)
|
124
|
+
|
125
|
+
# Create new store
|
126
|
+
new_store = {"lastModified": current_time, "todos": processed_todos}
|
127
|
+
|
128
|
+
# Save to file
|
129
|
+
self._save_store(new_store)
|
130
|
+
|
131
|
+
return len(processed_todos)
|
132
|
+
|
133
|
+
def update_todo(self, todo_id: str, updates: Dict[str, Any]) -> Dict[str, Any]:
|
134
|
+
"""Update a specific todo by ID."""
|
135
|
+
store = self._load_store()
|
136
|
+
todos = store["todos"]
|
137
|
+
|
138
|
+
# Find the todo to update
|
139
|
+
todo_index = None
|
140
|
+
original_todo = None
|
141
|
+
for i, todo in enumerate(todos):
|
142
|
+
if todo["id"] == todo_id:
|
143
|
+
todo_index = i
|
144
|
+
original_todo = todo
|
145
|
+
break
|
146
|
+
|
147
|
+
if todo_index is None or original_todo is None:
|
148
|
+
raise ValueError(f"Todo with ID '{todo_id}' not found")
|
149
|
+
|
150
|
+
# Check if status is changing to completed
|
151
|
+
original_status = original_todo["status"]
|
152
|
+
new_status = updates.get("status", original_status)
|
153
|
+
is_completing = original_status != "completed" and new_status == "completed"
|
154
|
+
|
155
|
+
# Create updated todo
|
156
|
+
updated_todo = dict(todos[todo_index])
|
157
|
+
updated_todo.update(updates)
|
158
|
+
updated_todo["updated_at"] = datetime.now().isoformat()
|
159
|
+
|
160
|
+
# Replace the todo in the list
|
161
|
+
updated_todos = todos.copy()
|
162
|
+
updated_todos[todo_index] = updated_todo
|
163
|
+
|
164
|
+
# Validate the entire list with the update
|
165
|
+
self._validate_todos(updated_todos)
|
166
|
+
|
167
|
+
# Save updated list
|
168
|
+
new_store = {"lastModified": datetime.now().isoformat(), "todos": updated_todos}
|
169
|
+
self._save_store(new_store)
|
170
|
+
|
171
|
+
# Return status counts
|
172
|
+
pending_count = sum(1 for t in updated_todos if t["status"] == "pending")
|
173
|
+
in_progress_count = sum(1 for t in updated_todos if t["status"] == "in_progress")
|
174
|
+
completed_count = sum(1 for t in updated_todos if t["status"] == "completed")
|
175
|
+
|
176
|
+
result = {"updated_todo": updated_todo, "counts": {"pending": pending_count, "in_progress": in_progress_count, "completed": completed_count, "total": len(updated_todos)}}
|
177
|
+
|
178
|
+
# If a todo was just completed, find and include the next pending todo
|
179
|
+
if is_completing:
|
180
|
+
next_todo = self._find_next_pending_todo(updated_todos, todo_index)
|
181
|
+
if next_todo:
|
182
|
+
result["next_todo"] = next_todo
|
183
|
+
else:
|
184
|
+
result["next_todo"] = None
|
185
|
+
result["message"] = "All todos completed! No more pending tasks."
|
186
|
+
|
187
|
+
return result
|
188
|
+
|
189
|
+
def _find_next_pending_todo(self, todos: List[Dict[str, Any]], completed_index: int) -> Dict[str, Any] | None:
|
190
|
+
"""Find the next pending todo after the completed one in sequential order."""
|
191
|
+
# Look for the next pending todo starting from the position after the completed one
|
192
|
+
for i in range(completed_index + 1, len(todos)):
|
193
|
+
if todos[i]["status"] == "pending":
|
194
|
+
return todos[i]
|
195
|
+
|
196
|
+
# If no pending todo found after the completed one, look from the beginning
|
197
|
+
# This handles cases where todos might be reordered or the completed one wasn't the first in-progress
|
198
|
+
for i in range(completed_index):
|
199
|
+
if todos[i]["status"] == "pending":
|
200
|
+
return todos[i]
|
201
|
+
|
202
|
+
# No pending todos found
|
203
|
+
return None
|
204
|
+
|
205
|
+
def _validate_todos(self, todos: List[Dict[str, Any]]) -> None:
|
206
|
+
"""Validate todos according to business rules."""
|
207
|
+
if not isinstance(todos, list):
|
208
|
+
raise ValueError("Todos must be a list")
|
209
|
+
|
210
|
+
# Check for required fields and collect IDs
|
211
|
+
required_fields = {"id", "content", "status"}
|
212
|
+
seen_ids = set()
|
213
|
+
in_progress_count = 0
|
214
|
+
|
215
|
+
for i, todo in enumerate(todos):
|
216
|
+
if not isinstance(todo, dict):
|
217
|
+
raise ValueError(f"Todo at index {i} must be a dictionary")
|
218
|
+
|
219
|
+
# Check required fields
|
220
|
+
missing_fields = required_fields - set(todo.keys())
|
221
|
+
if missing_fields:
|
222
|
+
raise ValueError(f"Todo at index {i} missing required fields: {missing_fields}")
|
223
|
+
|
224
|
+
# Validate ID uniqueness
|
225
|
+
todo_id = todo["id"]
|
226
|
+
if not isinstance(todo_id, str) or not todo_id.strip():
|
227
|
+
raise ValueError(f"Todo at index {i} must have a non-empty string ID")
|
228
|
+
|
229
|
+
if todo_id in seen_ids:
|
230
|
+
raise ValueError(f"Duplicate todo ID found: {todo_id}")
|
231
|
+
seen_ids.add(todo_id)
|
232
|
+
|
233
|
+
# Validate status
|
234
|
+
if todo["status"] not in ["pending", "in_progress", "completed"]:
|
235
|
+
raise ValueError(f"Todo at index {i} has invalid status: {todo['status']}")
|
236
|
+
|
237
|
+
if todo["status"] == "in_progress":
|
238
|
+
in_progress_count += 1
|
239
|
+
|
240
|
+
|
241
|
+
# Validate content
|
242
|
+
if not isinstance(todo["content"], str) or not todo["content"].strip():
|
243
|
+
raise ValueError(f"Todo at index {i} must have non-empty content")
|
244
|
+
|
245
|
+
# Business rule: only one task can be in progress
|
246
|
+
if in_progress_count > 1:
|
247
|
+
raise ValueError("Only one task can be in_progress at a time")
|
248
|
+
|
249
|
+
def _generate_id(self) -> str:
|
250
|
+
"""Generate a unique ID for a todo."""
|
251
|
+
import uuid
|
252
|
+
|
253
|
+
return str(uuid.uuid4())[:8]
|
254
|
+
|
255
|
+
|
256
|
+
# Global todo store instance
|
257
|
+
todo_store = TodoStore()
|
@@ -0,0 +1,157 @@
|
|
1
|
+
import json
|
2
|
+
from .todo_store import todo_store
|
3
|
+
from mcp.types import TextContent
|
4
|
+
|
5
|
+
|
6
|
+
def todo_read_tool():
|
7
|
+
"""Define the todo_read tool."""
|
8
|
+
return {
|
9
|
+
"name": "todo_read",
|
10
|
+
"description": "Read the current task list from the workspace-specific todo storage. "
|
11
|
+
"MANDATORY: This tool MUST be called FIRST before ANY workspace operations including file reads, code analysis, development tasks, project creation, or directory manipulation. "
|
12
|
+
"WORKSPACE-FIRST RULE: Every LLM interaction with workspaces, directories, projects, or repositories requires todo management. "
|
13
|
+
"WHEN TO USE: Always when starting workspace operations - check task status, review pending/completed work, understand project context, pick up previous progress. "
|
14
|
+
"Essential for: Project initialization, code development, file operations, debugging, testing, deployment, refactoring. "
|
15
|
+
"WHEN NOT TO USE: Pure informational queries unrelated to workspace development. "
|
16
|
+
"RETURNS: Sequential task list with status and metadata. Tasks execute in order - no priority system. "
|
17
|
+
"Each workspace maintains isolated todo lists for project organization. "
|
18
|
+
"CRITICAL: Bypassing this tool for workspace operations violates mandatory protocol. "
|
19
|
+
"EXAMPLES: \n- Creating new projects: Read todos to check existing project structure tasks\n- Code development: Check current development phase and next sequential steps\n- File modifications: Understand task context before making changes\n- Project analysis: Review completed analysis and next investigation steps",
|
20
|
+
"inputSchema": {
|
21
|
+
"type": "object",
|
22
|
+
"properties": {},
|
23
|
+
"required": [],
|
24
|
+
},
|
25
|
+
}
|
26
|
+
|
27
|
+
|
28
|
+
def todo_write_tool():
|
29
|
+
"""Define the todo_write tool."""
|
30
|
+
return {
|
31
|
+
"name": "todo_write",
|
32
|
+
"description": "Update the entire task list (complete replacement) for the current workspace. "
|
33
|
+
"MANDATORY: This tool MUST be called when planning, adding, or reorganizing tasks during ANY workspace operations. "
|
34
|
+
"WORKSPACE-FIRST RULE: All workspace development requires structured task management through sequential execution. "
|
35
|
+
"WHEN TO USE: Task planning for new projects, adding development phases, reorganizing workflow, batch status updates. "
|
36
|
+
"Sequential execution model: Tasks are completed in order, building upon previous work. No priority system - order determines execution. "
|
37
|
+
"Essential for: Project planning, development workflows, feature implementation, debugging sequences, deployment phases. "
|
38
|
+
"WHEN NOT TO USE: Single task updates (use todo_update), pure reading (use todo_read). "
|
39
|
+
"RETURNS: Success status and task count. Enforces sequential execution (only one in-progress task). "
|
40
|
+
"CRITICAL: Sequential task management is mandatory for all workspace development activities. "
|
41
|
+
"EXAMPLES: \n- New project setup: Create sequential tasks for initialization, structure, dependencies\n- Feature development: Plan design, implementation, testing, documentation phases\n- Bug fixing: Create investigation, fix, test, validation sequence\n- Code refactoring: Plan analysis, changes, testing, cleanup steps",
|
42
|
+
"inputSchema": {
|
43
|
+
"type": "object",
|
44
|
+
"properties": {
|
45
|
+
"todos": {
|
46
|
+
"type": "array",
|
47
|
+
"description": "Complete list of todo items to replace the current list for sequential execution. Each todo must contain id, content, and status fields. Tasks execute in array order.",
|
48
|
+
"items": {
|
49
|
+
"type": "object",
|
50
|
+
"properties": {
|
51
|
+
"id": {"type": "string", "description": "Unique identifier for the task. Must be unique across all todos."},
|
52
|
+
"content": {"type": "string", "description": "Task description or content. Cannot be empty."},
|
53
|
+
"status": {"type": "string", "enum": ["pending", "in_progress", "completed"], "description": "Current status of the task. Only one task can be 'in_progress' at a time."},
|
54
|
+
"metadata": {"type": "object", "description": "Optional additional data for the task.", "additionalProperties": True},
|
55
|
+
},
|
56
|
+
"required": ["id", "content", "status"],
|
57
|
+
"additionalProperties": True,
|
58
|
+
},
|
59
|
+
}
|
60
|
+
},
|
61
|
+
"required": ["todos"],
|
62
|
+
},
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
def todo_update_tool():
|
67
|
+
"""Define the todo_update tool."""
|
68
|
+
return {
|
69
|
+
"name": "todo_update",
|
70
|
+
"description": "Update a specific todo item by ID for sequential workflow management. "
|
71
|
+
"MANDATORY: This tool MUST be called when progressing through tasks during workspace operations. "
|
72
|
+
"WORKSPACE-FIRST RULE: Task progress updates are required for all workspace development activities. "
|
73
|
+
"WHEN TO USE: Mark tasks in-progress when starting, completed when finished, update content for clarification. "
|
74
|
+
"Sequential workflow: Progress through tasks in order, maintaining single active task constraint. "
|
75
|
+
"Essential for: Task status transitions, progress tracking, workflow advancement, content updates. "
|
76
|
+
"WHEN NOT TO USE: Multiple task updates (use todo_write), adding new tasks (use todo_write). "
|
77
|
+
"RETURNS: Updated todo with status counts showing workflow progress. "
|
78
|
+
"Enforces sequential execution - only one task can be in-progress at any time. "
|
79
|
+
"CRITICAL: Sequential progress tracking is mandatory for workspace development workflows. "
|
80
|
+
"EXAMPLES: \n- Starting work: Update task from 'pending' to 'in_progress'\n- Completing work: Update task from 'in_progress' to 'completed'\n- Task refinement: Update content for better clarity\n- Workflow progression: Move to next sequential task",
|
81
|
+
"inputSchema": {
|
82
|
+
"type": "object",
|
83
|
+
"properties": {
|
84
|
+
"todo_id": {"type": "string", "description": "The unique ID of the todo to update."},
|
85
|
+
"updates": {
|
86
|
+
"type": "object",
|
87
|
+
"description": "Fields to update in the todo for sequential workflow. Can include content, status, or metadata.",
|
88
|
+
"properties": {
|
89
|
+
"content": {"type": "string", "description": "New task description or content."},
|
90
|
+
"status": {"type": "string", "enum": ["pending", "in_progress", "completed"], "description": "New status of the task."},
|
91
|
+
"metadata": {"type": "object", "description": "Additional data for the task.", "additionalProperties": True},
|
92
|
+
},
|
93
|
+
"additionalProperties": True,
|
94
|
+
},
|
95
|
+
},
|
96
|
+
"required": ["todo_id", "updates"],
|
97
|
+
},
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
async def handle_todo_read(arguments: dict) -> list[TextContent]:
|
102
|
+
"""Handle reading todos from storage."""
|
103
|
+
try:
|
104
|
+
todos = todo_store.read_todos()
|
105
|
+
|
106
|
+
result = {"todos": todos, "count": len(todos), "workspace": str(todo_store.workspace_path)}
|
107
|
+
|
108
|
+
return [TextContent(type="text", text=json.dumps(result, indent=2))]
|
109
|
+
|
110
|
+
except Exception as e:
|
111
|
+
error_result = {"error": {"code": "READ_ERROR", "message": f"Failed to read todos: {str(e)}"}}
|
112
|
+
return [TextContent(type="text", text=json.dumps(error_result, indent=2))]
|
113
|
+
|
114
|
+
|
115
|
+
async def handle_todo_write(arguments: dict) -> list[TextContent]:
|
116
|
+
"""Handle writing todos to storage."""
|
117
|
+
try:
|
118
|
+
todos = arguments.get("todos", [])
|
119
|
+
|
120
|
+
if not isinstance(todos, list):
|
121
|
+
raise ValueError("Todos must be provided as a list")
|
122
|
+
|
123
|
+
count = todo_store.write_todos(todos)
|
124
|
+
|
125
|
+
result = {"success": True, "count": count, "workspace": str(todo_store.workspace_path)}
|
126
|
+
|
127
|
+
return [TextContent(type="text", text=json.dumps(result, indent=2))]
|
128
|
+
|
129
|
+
except Exception as e:
|
130
|
+
error_result = {"error": {"code": "VALIDATION_ERROR" if "validation" in str(e).lower() or "invalid" in str(e).lower() or "duplicate" in str(e).lower() else "WRITE_ERROR", "message": str(e)}}
|
131
|
+
return [TextContent(type="text", text=json.dumps(error_result, indent=2))]
|
132
|
+
|
133
|
+
|
134
|
+
async def handle_todo_update(arguments: dict) -> list[TextContent]:
|
135
|
+
"""Handle updating a specific todo."""
|
136
|
+
try:
|
137
|
+
todo_id = arguments.get("todo_id")
|
138
|
+
updates = arguments.get("updates", {})
|
139
|
+
|
140
|
+
if not todo_id:
|
141
|
+
raise ValueError("todo_id is required")
|
142
|
+
|
143
|
+
if not isinstance(updates, dict):
|
144
|
+
raise ValueError("Updates must be provided as a dictionary")
|
145
|
+
|
146
|
+
if not updates:
|
147
|
+
raise ValueError("Updates cannot be empty")
|
148
|
+
|
149
|
+
result = todo_store.update_todo(todo_id, updates)
|
150
|
+
result["success"] = True
|
151
|
+
result["workspace"] = str(todo_store.workspace_path)
|
152
|
+
|
153
|
+
return [TextContent(type="text", text=json.dumps(result, indent=2))]
|
154
|
+
|
155
|
+
except Exception as e:
|
156
|
+
error_result = {"error": {"code": "VALIDATION_ERROR" if "validation" in str(e).lower() or "invalid" in str(e).lower() or "not found" in str(e).lower() else "UPDATE_ERROR", "message": str(e)}}
|
157
|
+
return [TextContent(type="text", text=json.dumps(error_result, indent=2))]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{skydeckai_code-0.1.40 → skydeckai_code-0.1.41}/src/aidd/tools/get_available_windows_tool.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|