krita-cli 1.0.0__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.
- krita_cli/__init__.py +5 -0
- krita_cli/_shared.py +94 -0
- krita_cli/app.py +149 -0
- krita_cli/cli.py +59 -0
- krita_cli/commands/__init__.py +1 -0
- krita_cli/commands/batch.py +86 -0
- krita_cli/commands/brush.py +58 -0
- krita_cli/commands/call.py +49 -0
- krita_cli/commands/canvas.py +77 -0
- krita_cli/commands/color.py +42 -0
- krita_cli/commands/config.py +48 -0
- krita_cli/commands/file_ops.py +27 -0
- krita_cli/commands/health.py +32 -0
- krita_cli/commands/history_cmd.py +64 -0
- krita_cli/commands/introspect.py +46 -0
- krita_cli/commands/layers.py +112 -0
- krita_cli/commands/navigation.py +33 -0
- krita_cli/commands/replay.py +126 -0
- krita_cli/commands/rollback.py +39 -0
- krita_cli/commands/selection.py +364 -0
- krita_cli/commands/stroke.py +101 -0
- krita_cli/config_cmd.py +68 -0
- krita_cli/history.py +198 -0
- krita_cli-1.0.0.dist-info/METADATA +103 -0
- krita_cli-1.0.0.dist-info/RECORD +35 -0
- krita_cli-1.0.0.dist-info/WHEEL +4 -0
- krita_cli-1.0.0.dist-info/entry_points.txt +2 -0
- krita_cli-1.0.0.dist-info/licenses/LICENSE +21 -0
- krita_client/__init__.py +68 -0
- krita_client/client.py +690 -0
- krita_client/config.py +53 -0
- krita_client/models.py +507 -0
- krita_client/schema.py +109 -0
- krita_mcp/__init__.py +1 -0
- krita_mcp/server.py +1022 -0
krita_cli/history.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from datetime import UTC, datetime
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from krita_client import ClientConfig, KritaClient, KritaError
|
|
7
|
+
|
|
8
|
+
SYSTEM_HISTORY_DIR = Path.home() / ".krita-cli"
|
|
9
|
+
SYSTEM_HISTORY_FILE = SYSTEM_HISTORY_DIR / "history.log"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CommandHistory:
|
|
13
|
+
"""Manages command history recording and replay."""
|
|
14
|
+
|
|
15
|
+
def __init__(self) -> None:
|
|
16
|
+
self._history: list[dict[str, Any]] = []
|
|
17
|
+
self._recording_enabled: bool = False
|
|
18
|
+
self._history_file: Path | None = None
|
|
19
|
+
|
|
20
|
+
def enable_recording(self, file_path: str | Path | None = None) -> None:
|
|
21
|
+
"""Enable command recording, optionally persisting to a file."""
|
|
22
|
+
self._recording_enabled = True
|
|
23
|
+
self._history_file = Path(file_path) if file_path else None
|
|
24
|
+
|
|
25
|
+
def disable_recording(self) -> None:
|
|
26
|
+
"""Disable command recording."""
|
|
27
|
+
self._recording_enabled = False
|
|
28
|
+
|
|
29
|
+
def is_recording(self) -> bool:
|
|
30
|
+
"""Return whether recording is currently enabled."""
|
|
31
|
+
return self._recording_enabled
|
|
32
|
+
|
|
33
|
+
def _append_to_system_log(self, entry: dict[str, Any]) -> None:
|
|
34
|
+
"""Append a command entry to the systemic history log (JSONL)."""
|
|
35
|
+
try:
|
|
36
|
+
SYSTEM_HISTORY_DIR.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
log_entry = {
|
|
38
|
+
"timestamp": datetime.now(UTC).isoformat(),
|
|
39
|
+
**entry,
|
|
40
|
+
}
|
|
41
|
+
with SYSTEM_HISTORY_FILE.open("a", encoding="utf-8") as f:
|
|
42
|
+
f.write(json.dumps(log_entry) + "\n")
|
|
43
|
+
except Exception:
|
|
44
|
+
# Persistent logging should not crash the CLI if it fails (e.g. permission issues)
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
def record_command(
|
|
48
|
+
self,
|
|
49
|
+
action: str,
|
|
50
|
+
params: dict[str, Any] | None,
|
|
51
|
+
result: dict[str, Any] | None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Record a command invocation to the in-memory history."""
|
|
54
|
+
entry: dict[str, Any] = {
|
|
55
|
+
"action": action,
|
|
56
|
+
"params": params or {},
|
|
57
|
+
"result": result,
|
|
58
|
+
}
|
|
59
|
+
self._history.append(entry)
|
|
60
|
+
self._append_to_system_log(entry)
|
|
61
|
+
|
|
62
|
+
if self._recording_enabled and self._history_file is not None:
|
|
63
|
+
try:
|
|
64
|
+
self._history_file.parent.mkdir(parents=True, exist_ok=True)
|
|
65
|
+
self._history_file.write_text(json.dumps(self._history, indent=2))
|
|
66
|
+
except Exception:
|
|
67
|
+
# Persistent history write should not crash the CLI
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
def get_history(self) -> list[dict[str, Any]]:
|
|
71
|
+
"""Return the current command history."""
|
|
72
|
+
return list(self._history)
|
|
73
|
+
|
|
74
|
+
def clear_history(self) -> None:
|
|
75
|
+
"""Clear the in-memory history."""
|
|
76
|
+
self._history.clear()
|
|
77
|
+
|
|
78
|
+
def load_history(self, file_path: str | Path) -> list[dict[str, Any]]:
|
|
79
|
+
"""Load command history from a JSON file or JSONL log."""
|
|
80
|
+
path = Path(file_path)
|
|
81
|
+
if not path.exists():
|
|
82
|
+
return []
|
|
83
|
+
|
|
84
|
+
content = path.read_text(encoding="utf-8").strip()
|
|
85
|
+
if not content:
|
|
86
|
+
return []
|
|
87
|
+
|
|
88
|
+
# Try parsing as JSONL first (system log)
|
|
89
|
+
if content.startswith("{") and "\n" in content:
|
|
90
|
+
return [json.loads(line) for line in content.splitlines() if line.strip()]
|
|
91
|
+
|
|
92
|
+
# Fallback to standard JSON array
|
|
93
|
+
data = json.loads(content)
|
|
94
|
+
if not isinstance(data, list):
|
|
95
|
+
return []
|
|
96
|
+
return data
|
|
97
|
+
|
|
98
|
+
def rollback_batch(self, count: int, client: KritaClient) -> list[dict[str, Any]]:
|
|
99
|
+
"""Rollback the last N operations by calling undo."""
|
|
100
|
+
results: list[dict[str, Any]] = []
|
|
101
|
+
for i in range(count):
|
|
102
|
+
try:
|
|
103
|
+
result = client.undo()
|
|
104
|
+
results.append({"action": "undo", "status": "ok", "iteration": i + 1, "result": result})
|
|
105
|
+
except KritaError as exc:
|
|
106
|
+
results.append({"action": "undo", "status": "error", "iteration": i + 1, "error": exc.message})
|
|
107
|
+
return results
|
|
108
|
+
|
|
109
|
+
def replay_commands(
|
|
110
|
+
self,
|
|
111
|
+
file_path: str | Path | None = None,
|
|
112
|
+
client: KritaClient | None = None,
|
|
113
|
+
) -> list[dict[str, Any]]:
|
|
114
|
+
"""Replay recorded commands against a Krita client.
|
|
115
|
+
|
|
116
|
+
If *file_path* is given, load history from that file.
|
|
117
|
+
Otherwise replay the in-memory history.
|
|
118
|
+
|
|
119
|
+
Returns a list of results (one per command).
|
|
120
|
+
"""
|
|
121
|
+
commands = self.load_history(file_path) if file_path is not None else self.get_history()
|
|
122
|
+
|
|
123
|
+
if client is None:
|
|
124
|
+
client = KritaClient(ClientConfig())
|
|
125
|
+
|
|
126
|
+
results: list[dict[str, Any]] = []
|
|
127
|
+
for entry in commands:
|
|
128
|
+
action = entry["action"]
|
|
129
|
+
params = entry.get("params", {})
|
|
130
|
+
try:
|
|
131
|
+
result = client.send_command(action, params)
|
|
132
|
+
status = result.get("status", "ok")
|
|
133
|
+
results.append({"action": action, "status": status, "result": result})
|
|
134
|
+
except KritaError as exc:
|
|
135
|
+
results.append({"action": action, "status": "error", "error": exc.message})
|
|
136
|
+
|
|
137
|
+
return results
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Module-level singleton for backward compatibility
|
|
141
|
+
_history = CommandHistory()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def enable_recording(file_path: str | Path | None = None) -> None:
|
|
145
|
+
"""Enable command recording, optionally persisting to a file."""
|
|
146
|
+
_history.enable_recording(file_path)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def disable_recording() -> None:
|
|
150
|
+
"""Disable command recording."""
|
|
151
|
+
_history.disable_recording()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def is_recording() -> bool:
|
|
155
|
+
"""Return whether recording is currently enabled."""
|
|
156
|
+
return _history.is_recording()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def record_command(
|
|
160
|
+
action: str,
|
|
161
|
+
params: dict[str, Any] | None,
|
|
162
|
+
result: dict[str, Any] | None,
|
|
163
|
+
) -> None:
|
|
164
|
+
"""Record a command invocation to the in-memory history."""
|
|
165
|
+
_history.record_command(action, params, result)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def get_history() -> list[dict[str, Any]]:
|
|
169
|
+
"""Return the current command history."""
|
|
170
|
+
return _history.get_history()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def clear_history() -> None:
|
|
174
|
+
"""Clear the in-memory history."""
|
|
175
|
+
_history.clear_history()
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def load_history(file_path: str | Path) -> list[dict[str, Any]]:
|
|
179
|
+
"""Load command history from a JSON file."""
|
|
180
|
+
return _history.load_history(file_path)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def replay_commands(
|
|
184
|
+
file_path: str | Path | None = None,
|
|
185
|
+
client: KritaClient | None = None,
|
|
186
|
+
) -> list[dict[str, Any]]:
|
|
187
|
+
"""Replay recorded commands against a Krita client."""
|
|
188
|
+
return _history.replay_commands(file_path=file_path, client=client)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def rollback_batch(count: int, client: KritaClient) -> list[dict[str, Any]]:
|
|
192
|
+
"""Rollback the last N operations by calling undo."""
|
|
193
|
+
return _history.rollback_batch(count, client)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def get_system_log_path() -> Path:
|
|
197
|
+
"""Return the path to the systemic history log."""
|
|
198
|
+
return SYSTEM_HISTORY_FILE
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: krita-cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: SOTA CLI + MCP server for programmatic painting in Krita
|
|
5
|
+
Project-URL: Homepage, https://github.com/github/krita-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/github/krita-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/github/krita-cli/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/github/krita-cli/blob/master/CHANGELOG.md
|
|
9
|
+
Author: Krita MCP Contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,automation,claude,cli,fastmcp,krita,mcp,painting
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Multimedia :: Graphics :: Editors :: Raster-Based
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: fastmcp>=3.1.0
|
|
23
|
+
Requires-Dist: httpx>=0.28.1
|
|
24
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
25
|
+
Requires-Dist: pydantic>=2.12.5
|
|
26
|
+
Requires-Dist: rich>=13.0.0
|
|
27
|
+
Requires-Dist: typer>=0.9.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: beartype>=0.18.0; extra == 'dev'
|
|
30
|
+
Provides-Extra: numpy
|
|
31
|
+
Requires-Dist: numpy>=1.26.0; extra == 'numpy'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# Krita MCP Server & CLI
|
|
35
|
+
|
|
36
|
+
Let AI agents paint in [Krita](https://krita.org/) via the [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
37
|
+
|
|
38
|
+
This subproject provides the core implementation of the Krita-MCP ecosystem, including the FastMCP server, the `krita` CLI, and the high-performance Python plugin.
|
|
39
|
+
|
|
40
|
+
## 🛠️ Components
|
|
41
|
+
|
|
42
|
+
1. **Krita Plugin** (`krita-plugin/`) — A Python plugin for Krita that exposes a thread-safe HTTP server on `localhost:5678`.
|
|
43
|
+
2. **MCP Server** (`src/krita_mcp/`) — A FastMCP server exposing 40+ painting and manipulation tools.
|
|
44
|
+
3. **Krita CLI** (`src/krita_cli/`) — A Typer-based command line interface for human operators.
|
|
45
|
+
4. **Krita Client** (`src/krita_client/`) — A reusable, fully-typed Python library for Krita automation.
|
|
46
|
+
|
|
47
|
+
## 🚀 Setup
|
|
48
|
+
|
|
49
|
+
### 1. Krita Plugin Installation
|
|
50
|
+
Copy the contents of `krita-plugin/` to your Krita resources:
|
|
51
|
+
- **Windows**: `%APPDATA%\krita\pykrita\`
|
|
52
|
+
- **Linux**: `~/.local/share/krita/pykrita/`
|
|
53
|
+
- **macOS**: `~/Library/Application Support/krita/pykrita/`
|
|
54
|
+
|
|
55
|
+
Enable **"Krita MCP Bridge"** in Krita (Configure Krita → Python Plugin Manager) and restart.
|
|
56
|
+
|
|
57
|
+
### 2. Environment Setup
|
|
58
|
+
```bash
|
|
59
|
+
# Install dependencies with uv
|
|
60
|
+
uv sync
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 🔧 CLI Commands
|
|
64
|
+
|
|
65
|
+
The `krita` CLI is grouped into logical subcommands:
|
|
66
|
+
|
|
67
|
+
- **Painting**: `stroke`, `fill`, `clear`, `draw-shape`
|
|
68
|
+
- **Layers**: `layers list`, `layers create`, `layers select`, `layers delete`
|
|
69
|
+
- **Selection**: `selection select-rect`, `selection transform`, `selection save-channel`
|
|
70
|
+
- **Canvas**: `canvas-info`, `current-color`, `current-brush`
|
|
71
|
+
- **Session**: `history`, `replay`, `rollback`, `batch`
|
|
72
|
+
- **System**: `health`, `config`, `capabilities`, `security-status`
|
|
73
|
+
|
|
74
|
+
Run `uv run krita --help` for full details.
|
|
75
|
+
|
|
76
|
+
## 🤖 MCP Server Tools (40 Total)
|
|
77
|
+
|
|
78
|
+
The MCP server exposes a vast range of capabilities to AI agents:
|
|
79
|
+
|
|
80
|
+
| Category | Key Tools |
|
|
81
|
+
|----------|-----------|
|
|
82
|
+
| **Core** | `krita_health`, `krita_new_canvas`, `krita_save`, `krita_open_file` |
|
|
83
|
+
| **Painting** | `krita_stroke`, `krita_fill`, `krita_draw_shape`, `krita_set_color`, `krita_set_brush` |
|
|
84
|
+
| **Selection** | `krita_select_rect`, `krita_select_ellipse`, `krita_select_polygon`, `krita_select_by_color`, `krita_select_by_alpha` |
|
|
85
|
+
| **Selection Ops** | `krita_transform_selection`, `krita_grow_selection`, `krita_combine_selections`, `krita_invert_selection` |
|
|
86
|
+
| **Persistence** | `krita_save_selection`, `krita_load_selection`, `krita_save_selection_channel`, `krita_list_selection_channels` |
|
|
87
|
+
| **Automation** | `krita_batch`, `krita_rollback`, `krita_get_command_history` |
|
|
88
|
+
| **Inspection** | `krita_get_canvas_info`, `krita_get_color_at`, `krita_selection_stats`, `krita_security_status` |
|
|
89
|
+
|
|
90
|
+
## ⚡ Performance
|
|
91
|
+
|
|
92
|
+
The plugin uses **numpy-accelerated** direct pixel manipulation for rendering. This ensures that strokes and shapes are rendered significantly faster than standard Python loops, especially on high-resolution canvases.
|
|
93
|
+
|
|
94
|
+
## 🔒 Security
|
|
95
|
+
|
|
96
|
+
Krita MCP includes a built-in security layer to protect your system:
|
|
97
|
+
- **Path Sanitization**: Restricts file operations to allowed directories.
|
|
98
|
+
- **Resource Limits**: Prevents OOM by limiting max canvas dimensions and layer counts.
|
|
99
|
+
- **Rate Limiting**: Throttles rapid command execution.
|
|
100
|
+
- **Security Tool**: `krita_security_status` allows agents to check active limits.
|
|
101
|
+
|
|
102
|
+
## 📄 License
|
|
103
|
+
MIT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
krita_cli/__init__.py,sha256=TYbvkpB_Ps1X-ewTEVeBEQt8Ab5K6e7gyJVkKFB1K8I,106
|
|
2
|
+
krita_cli/_shared.py,sha256=rZ_WvpHZxLAFlQIxaIvAmJFoh-gjjjX6OMb67s2adUM,3287
|
|
3
|
+
krita_cli/app.py,sha256=BPOLTznFbgCzGllRm5SRlhV-LJtduBRSXe1ev4gkikQ,3760
|
|
4
|
+
krita_cli/cli.py,sha256=1-2URcrjosJCe0tFAt_R6HXUhPDc2FNvFqf3_u-RJyE,904
|
|
5
|
+
krita_cli/config_cmd.py,sha256=ql0fHc8Ve7ahQf59oNXpqsf5fdtil2mjLy2FI9orbGw,2013
|
|
6
|
+
krita_cli/history.py,sha256=F0K_9739kGium7uqVUMQvRwWPOxT3Iw5lNk9JLlypzc,6722
|
|
7
|
+
krita_cli/commands/__init__.py,sha256=ke2w9d8hQ7_h85DmKwvcVEiyLoMCvkTiKafzdMGlBjA,36
|
|
8
|
+
krita_cli/commands/batch.py,sha256=PU1sHbC5X33NRHO7CBl03y2wwNtjmTr9iJErIfoQZ5w,3323
|
|
9
|
+
krita_cli/commands/brush.py,sha256=gwJewjlVifcBGsl05bp8mbH5gGeDUkzuPanhgW_hF1A,1978
|
|
10
|
+
krita_cli/commands/call.py,sha256=z4QGXeGbdOngxxrYCtlh5cdrPOfgya22za-P4yQcO6c,1352
|
|
11
|
+
krita_cli/commands/canvas.py,sha256=ILBtjTrpO7eEbDsKN2KGr_WaRAJbsEhZqy4wPLj5qNw,2490
|
|
12
|
+
krita_cli/commands/color.py,sha256=MAyZq8rZaZSPgd3x40NM2xCdcZRvw-JUei6Agep1cLs,1112
|
|
13
|
+
krita_cli/commands/config.py,sha256=alVwNY4CQCQnJP4oJJdlCcTJZnnvV24w32m215YrTCE,1456
|
|
14
|
+
krita_cli/commands/file_ops.py,sha256=qpg4GKdWFe1A0yY5KYmZcfRWpIpQayta4iF3e_3wYCM,651
|
|
15
|
+
krita_cli/commands/health.py,sha256=08Adqh45c6u9d5YAOUNimHSCDX27zq5oGwju4Z8KHo4,911
|
|
16
|
+
krita_cli/commands/history_cmd.py,sha256=tJaGKRu53gNlVgv3ER6HzuI_toUlHdbc648N5-StlDM,1835
|
|
17
|
+
krita_cli/commands/introspect.py,sha256=BskBm3MpkmYdXTKwiLXRKcZd9WZzO1KYdZ1T1xwbPbc,1252
|
|
18
|
+
krita_cli/commands/layers.py,sha256=hC6DLDoNEJohQWzOQBOWpnYpGvTLRpcMS_ZqPncIq6k,3334
|
|
19
|
+
krita_cli/commands/navigation.py,sha256=fe5FPuF7AEDXop_kclBXodUtmgDSSD2GbK5cbCFGbik,756
|
|
20
|
+
krita_cli/commands/replay.py,sha256=UD_Ui1JD89FGJ1sD0Lt1CxVb_2BdjQrHE5qMLlhReGg,3824
|
|
21
|
+
krita_cli/commands/rollback.py,sha256=ljbREETPMuEO0mDiAK6b8XwRwlh0569dKRWcsREykRU,1081
|
|
22
|
+
krita_cli/commands/selection.py,sha256=CQRT8K9CLLjWMeWzII6lIrLZJJCmnWbyYbDnEltKfEc,13338
|
|
23
|
+
krita_cli/commands/stroke.py,sha256=xbDU6Bmq_S6ySk6KW1TZUhiwVYd9W0Cps6mIDb2mnkM,3550
|
|
24
|
+
krita_client/__init__.py,sha256=RM4zCMP82QbKgTsXRQx-vSmXMGijvL0rYEVm_8a5-ws,1505
|
|
25
|
+
krita_client/client.py,sha256=HUweZ6hXWDsTjlHPtVNT4YIx_6RflOMVyXZsKq2YdV4,25200
|
|
26
|
+
krita_client/config.py,sha256=Kc8wX1cXZZxawGdD0zdCNaLpEdqiZSehIhIPnf7T1yU,1586
|
|
27
|
+
krita_client/models.py,sha256=zCBF0WIvLhSXp1Hs4OB6RmApjCjDcmQOzgZfLHHSmsA,13647
|
|
28
|
+
krita_client/schema.py,sha256=UCYoeoWeNGDPvCEukNVadXgRNYqIe9DI_nhEBLrrXPw,3816
|
|
29
|
+
krita_mcp/__init__.py,sha256=dr6IyEhZXliSB7CxR6fI65RLwkc5gvtiVXwSa_kgqQ4,60
|
|
30
|
+
krita_mcp/server.py,sha256=w-u1g68kQ1Wr3yuK0bL3eUZbv3dK5xinA6jYbmoKK50,33180
|
|
31
|
+
krita_cli-1.0.0.dist-info/METADATA,sha256=dQMtXuAghQFEN397FKeGaeXD8aGdTHOPbYUL3A2hr50,4647
|
|
32
|
+
krita_cli-1.0.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
33
|
+
krita_cli-1.0.0.dist-info/entry_points.txt,sha256=144liQ6zPDeWWSNFDnr3IEawJLZ1PWYX8eQAMtHtxbw,44
|
|
34
|
+
krita_cli-1.0.0.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
|
|
35
|
+
krita_cli-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
krita_client/__init__.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Krita MCP Client — Typed HTTP client for the Krita plugin.
|
|
2
|
+
|
|
3
|
+
This package provides:
|
|
4
|
+
- ``ClientConfig``: Configuration via pydantic-settings.
|
|
5
|
+
- ``KritaClient``: Typed HTTP client with validated commands.
|
|
6
|
+
- Pydantic models for all 14 command parameter sets.
|
|
7
|
+
- OpenAPI schema generation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from krita_client.client import (
|
|
13
|
+
KritaClient,
|
|
14
|
+
KritaCommandError,
|
|
15
|
+
KritaConnectionError,
|
|
16
|
+
KritaError,
|
|
17
|
+
KritaValidationError,
|
|
18
|
+
)
|
|
19
|
+
from krita_client.config import ClientConfig
|
|
20
|
+
from krita_client.models import (
|
|
21
|
+
COMMAND_MODELS,
|
|
22
|
+
BatchCommand,
|
|
23
|
+
BatchParams,
|
|
24
|
+
ClearParams,
|
|
25
|
+
DrawShapeParams,
|
|
26
|
+
ErrorCode,
|
|
27
|
+
FillParams,
|
|
28
|
+
GetCanvasParams,
|
|
29
|
+
GetColorAtParams,
|
|
30
|
+
ListBrushesParams,
|
|
31
|
+
NewCanvasParams,
|
|
32
|
+
OpenFileParams,
|
|
33
|
+
RedoParams,
|
|
34
|
+
SaveParams,
|
|
35
|
+
SetBrushParams,
|
|
36
|
+
SetColorParams,
|
|
37
|
+
StrokeParams,
|
|
38
|
+
UndoParams,
|
|
39
|
+
)
|
|
40
|
+
from krita_client.schema import generate_openapi_schema
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
"COMMAND_MODELS",
|
|
44
|
+
"BatchCommand",
|
|
45
|
+
"BatchParams",
|
|
46
|
+
"ClearParams",
|
|
47
|
+
"ClientConfig",
|
|
48
|
+
"DrawShapeParams",
|
|
49
|
+
"ErrorCode",
|
|
50
|
+
"FillParams",
|
|
51
|
+
"GetCanvasParams",
|
|
52
|
+
"GetColorAtParams",
|
|
53
|
+
"KritaClient",
|
|
54
|
+
"KritaCommandError",
|
|
55
|
+
"KritaConnectionError",
|
|
56
|
+
"KritaError",
|
|
57
|
+
"KritaValidationError",
|
|
58
|
+
"ListBrushesParams",
|
|
59
|
+
"NewCanvasParams",
|
|
60
|
+
"OpenFileParams",
|
|
61
|
+
"RedoParams",
|
|
62
|
+
"SaveParams",
|
|
63
|
+
"SetBrushParams",
|
|
64
|
+
"SetColorParams",
|
|
65
|
+
"StrokeParams",
|
|
66
|
+
"UndoParams",
|
|
67
|
+
"generate_openapi_schema",
|
|
68
|
+
]
|