kiwimatecoder 0.1.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.
Files changed (104) hide show
  1. kiwimatecoder/__init__.py +8 -0
  2. kiwimatecoder/__main__.py +12 -0
  3. kiwimatecoder/acp/__init__.py +13 -0
  4. kiwimatecoder/acp/protocol.py +115 -0
  5. kiwimatecoder/acp/server.py +823 -0
  6. kiwimatecoder/acp/stdio.py +32 -0
  7. kiwimatecoder/agent.py +1162 -0
  8. kiwimatecoder/ai.py +68 -0
  9. kiwimatecoder/audit.py +65 -0
  10. kiwimatecoder/browser.py +261 -0
  11. kiwimatecoder/catalog.py +445 -0
  12. kiwimatecoder/checkpoints.py +103 -0
  13. kiwimatecoder/client.py +820 -0
  14. kiwimatecoder/clipboard.py +99 -0
  15. kiwimatecoder/commands.py +6757 -0
  16. kiwimatecoder/config.py +5335 -0
  17. kiwimatecoder/diagnostics.py +295 -0
  18. kiwimatecoder/documents.py +299 -0
  19. kiwimatecoder/evals/__init__.py +39 -0
  20. kiwimatecoder/evals/cases.py +230 -0
  21. kiwimatecoder/evals/render.py +46 -0
  22. kiwimatecoder/evals/runner.py +319 -0
  23. kiwimatecoder/events.py +95 -0
  24. kiwimatecoder/forge.py +172 -0
  25. kiwimatecoder/git.py +164 -0
  26. kiwimatecoder/headless.py +255 -0
  27. kiwimatecoder/hooks.py +170 -0
  28. kiwimatecoder/hunks.py +260 -0
  29. kiwimatecoder/i18n.py +368 -0
  30. kiwimatecoder/images.py +195 -0
  31. kiwimatecoder/index/__init__.py +14 -0
  32. kiwimatecoder/index/builder.py +376 -0
  33. kiwimatecoder/index/embeddings.py +151 -0
  34. kiwimatecoder/index/search.py +247 -0
  35. kiwimatecoder/index/store.py +251 -0
  36. kiwimatecoder/instructions.py +83 -0
  37. kiwimatecoder/jobs.py +594 -0
  38. kiwimatecoder/lsp/__init__.py +56 -0
  39. kiwimatecoder/lsp/client.py +548 -0
  40. kiwimatecoder/lsp/manager.py +353 -0
  41. kiwimatecoder/lsp/protocol.py +79 -0
  42. kiwimatecoder/main.py +4258 -0
  43. kiwimatecoder/mcp/__init__.py +45 -0
  44. kiwimatecoder/mcp/client.py +385 -0
  45. kiwimatecoder/mcp/errors.py +7 -0
  46. kiwimatecoder/mcp/manager.py +253 -0
  47. kiwimatecoder/mcp/protocol.py +132 -0
  48. kiwimatecoder/media.py +904 -0
  49. kiwimatecoder/memory.py +141 -0
  50. kiwimatecoder/network.py +112 -0
  51. kiwimatecoder/notify.py +139 -0
  52. kiwimatecoder/permissions.py +171 -0
  53. kiwimatecoder/pickers.py +417 -0
  54. kiwimatecoder/plugins.py +245 -0
  55. kiwimatecoder/pricing.py +167 -0
  56. kiwimatecoder/prompts.py +213 -0
  57. kiwimatecoder/providers.py +342 -0
  58. kiwimatecoder/redaction.py +66 -0
  59. kiwimatecoder/remote.py +294 -0
  60. kiwimatecoder/repl.py +1388 -0
  61. kiwimatecoder/routing.py +65 -0
  62. kiwimatecoder/sandbox.py +169 -0
  63. kiwimatecoder/sdk.py +146 -0
  64. kiwimatecoder/session.py +574 -0
  65. kiwimatecoder/share.py +386 -0
  66. kiwimatecoder/shell.py +660 -0
  67. kiwimatecoder/skills.py +138 -0
  68. kiwimatecoder/sync.py +513 -0
  69. kiwimatecoder/team.py +249 -0
  70. kiwimatecoder/telemetry.py +392 -0
  71. kiwimatecoder/templates.py +108 -0
  72. kiwimatecoder/tools/__init__.py +190 -0
  73. kiwimatecoder/tools/ask.py +62 -0
  74. kiwimatecoder/tools/base.py +69 -0
  75. kiwimatecoder/tools/browser.py +261 -0
  76. kiwimatecoder/tools/edit_file.py +143 -0
  77. kiwimatecoder/tools/forge.py +207 -0
  78. kiwimatecoder/tools/git.py +158 -0
  79. kiwimatecoder/tools/image.py +300 -0
  80. kiwimatecoder/tools/io.py +346 -0
  81. kiwimatecoder/tools/list_dir.py +67 -0
  82. kiwimatecoder/tools/lsp.py +254 -0
  83. kiwimatecoder/tools/memory.py +115 -0
  84. kiwimatecoder/tools/paths.py +234 -0
  85. kiwimatecoder/tools/read_file.py +113 -0
  86. kiwimatecoder/tools/registry.py +91 -0
  87. kiwimatecoder/tools/run_bash.py +189 -0
  88. kiwimatecoder/tools/search.py +224 -0
  89. kiwimatecoder/tools/selection.py +108 -0
  90. kiwimatecoder/tools/shell.py +158 -0
  91. kiwimatecoder/tools/skill.py +46 -0
  92. kiwimatecoder/tools/task.py +61 -0
  93. kiwimatecoder/tools/todo.py +77 -0
  94. kiwimatecoder/tools/web.py +146 -0
  95. kiwimatecoder/tools/write_file.py +83 -0
  96. kiwimatecoder/ui.py +189 -0
  97. kiwimatecoder/updater.py +502 -0
  98. kiwimatecoder/web.py +499 -0
  99. kiwimatecoder-0.1.0.dist-info/METADATA +2016 -0
  100. kiwimatecoder-0.1.0.dist-info/RECORD +104 -0
  101. kiwimatecoder-0.1.0.dist-info/WHEEL +5 -0
  102. kiwimatecoder-0.1.0.dist-info/entry_points.txt +2 -0
  103. kiwimatecoder-0.1.0.dist-info/licenses/LICENSE +21 -0
  104. kiwimatecoder-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,132 @@
1
+ """Minimal JSON-RPC 2.0 and MCP content helpers.
2
+
3
+ Only the subset the client needs is implemented: request/notification
4
+ construction, response validation, SSE framing, and flattening MCP content
5
+ blocks into the plain text the agent consumes. The JSON-RPC method names and
6
+ result shapes follow the Model Context Protocol revision named in
7
+ :data:`MCP_PROTOCOL_VERSION`.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ from typing import Any
14
+
15
+ from kiwimatecoder import __version__
16
+ from kiwimatecoder.mcp.errors import McpError
17
+
18
+ MCP_PROTOCOL_VERSION = "2025-06-18"
19
+
20
+ CLIENT_INFO = {"name": "kiwimatecoder", "version": __version__}
21
+
22
+
23
+ def request_message(
24
+ request_id: int, method: str, params: dict[str, Any] | None = None
25
+ ) -> dict[str, Any]:
26
+ """Build a JSON-RPC request object."""
27
+ message: dict[str, Any] = {
28
+ "jsonrpc": "2.0",
29
+ "id": request_id,
30
+ "method": method,
31
+ "params": params if params is not None else {},
32
+ }
33
+ return message
34
+
35
+
36
+ def notification_message(
37
+ method: str, params: dict[str, Any] | None = None
38
+ ) -> dict[str, Any]:
39
+ """Build a JSON-RPC notification (no ``id``, no response expected)."""
40
+ message: dict[str, Any] = {"jsonrpc": "2.0", "method": method}
41
+ if params is not None:
42
+ message["params"] = params
43
+ return message
44
+
45
+
46
+ def parse_response(message: dict[str, Any], method: str) -> Any:
47
+ """Return a JSON-RPC result or raise :class:`McpError` for its error."""
48
+ error = message.get("error")
49
+ if isinstance(error, dict):
50
+ detail = str(error.get("message") or error)
51
+ code = error.get("code")
52
+ suffix = f" (code {code})" if code is not None else ""
53
+ raise McpError(f"{method} failed: {detail}{suffix}")
54
+ if "result" not in message:
55
+ raise McpError(f"{method}: malformed JSON-RPC response")
56
+ return message["result"]
57
+
58
+
59
+ def parse_sse_messages(text: str) -> list[dict[str, Any]]:
60
+ """Extract JSON-RPC objects from an SSE body's ``data:`` lines."""
61
+ messages: list[dict[str, Any]] = []
62
+ data_lines: list[str] = []
63
+
64
+ def flush() -> None:
65
+ if not data_lines:
66
+ return
67
+ payload = "\n".join(data_lines)
68
+ data_lines.clear()
69
+ try:
70
+ decoded = json.loads(payload)
71
+ except json.JSONDecodeError:
72
+ return
73
+ if isinstance(decoded, dict):
74
+ messages.append(decoded)
75
+
76
+ for line in text.splitlines():
77
+ if line.startswith("data:"):
78
+ data_lines.append(line[5:].lstrip())
79
+ elif not line.strip():
80
+ flush()
81
+ flush()
82
+ return messages
83
+
84
+
85
+ def _flatten_block(block: Any) -> str:
86
+ if not isinstance(block, dict):
87
+ return str(block)
88
+ kind = str(block.get("type") or "")
89
+ if kind == "text":
90
+ return str(block.get("text") or "")
91
+ if kind == "image":
92
+ return "[image content]"
93
+ if kind == "audio":
94
+ return "[audio content]"
95
+ if kind == "resource":
96
+ resource = block.get("resource")
97
+ if isinstance(resource, dict) and resource.get("text") is not None:
98
+ return str(resource["text"])
99
+ return "[resource content]"
100
+ if kind == "resource_link":
101
+ return str(block.get("uri") or "[resource link]")
102
+ return f"[{kind} content]" if kind else "[content]"
103
+
104
+
105
+ def flatten_content(content: Any) -> str:
106
+ """Render an MCP ``content`` list as plain text for the agent."""
107
+ if content is None:
108
+ return ""
109
+ if isinstance(content, str):
110
+ return content
111
+ if not isinstance(content, list):
112
+ return str(content)
113
+ return "\n".join(part for part in (_flatten_block(item) for item in content) if part)
114
+
115
+
116
+ def flatten_resource_contents(contents: Any) -> str:
117
+ """Render an MCP ``resources/read`` contents list as plain text."""
118
+ if contents is None:
119
+ return ""
120
+ if not isinstance(contents, list):
121
+ return flatten_content(contents)
122
+ parts: list[str] = []
123
+ for item in contents:
124
+ if not isinstance(item, dict):
125
+ parts.append(str(item))
126
+ elif item.get("text") is not None:
127
+ parts.append(str(item["text"]))
128
+ elif item.get("blob") is not None:
129
+ parts.append("[binary resource]")
130
+ else:
131
+ parts.append("[resource content]")
132
+ return "\n".join(part for part in parts if part)