k-cli-for-devs 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.
Files changed (75) hide show
  1. k_cli/__init__.py +77 -0
  2. k_cli/agents/__init__.py +0 -0
  3. k_cli/agents/adversarial_swarm.py +338 -0
  4. k_cli/agents/agent_core.py +255 -0
  5. k_cli/agents/background_daemon.py +141 -0
  6. k_cli/agents/orchestrator.py +376 -0
  7. k_cli/agents/persona.py +649 -0
  8. k_cli/agents/scaffold_engine.py +121 -0
  9. k_cli/agents/strands_agent.py +832 -0
  10. k_cli/agents/subagents.py +1496 -0
  11. k_cli/cli.py +3297 -0
  12. k_cli/core/__init__.py +0 -0
  13. k_cli/core/airgap.py +95 -0
  14. k_cli/core/credentials.py +548 -0
  15. k_cli/core/intent_sensor.py +177 -0
  16. k_cli/core/llm_driver.py +1028 -0
  17. k_cli/core/model_manager.py +1109 -0
  18. k_cli/core/models_hub.py +913 -0
  19. k_cli/core/prompting.py +41 -0
  20. k_cli/core/sdk.py +322 -0
  21. k_cli/core/session.py +826 -0
  22. k_cli/core/smart_router.py +230 -0
  23. k_cli/core/storage_manager.py +176 -0
  24. k_cli/core/viewport_engine.py +117 -0
  25. k_cli/demo/demo_runner.py +579 -0
  26. k_cli/git/__init__.py +0 -0
  27. k_cli/git/ai_bisect.py +208 -0
  28. k_cli/git/conflict_resolver.py +1039 -0
  29. k_cli/git/git_guard.py +417 -0
  30. k_cli/git/patcher.py +1175 -0
  31. k_cli/git/repo_map.py +1780 -0
  32. k_cli/git/smart_git.py +928 -0
  33. k_cli/git/verifier.py +969 -0
  34. k_cli/github/__init__.py +0 -0
  35. k_cli/github/dedup_engine.py +787 -0
  36. k_cli/github/github_client.py +1702 -0
  37. k_cli/github/github_engine.py +641 -0
  38. k_cli/github/local_hub.py +209 -0
  39. k_cli/github/pr_watcher.py +129 -0
  40. k_cli/github/trending.py +205 -0
  41. k_cli/tools/__init__.py +0 -0
  42. k_cli/tools/audit.py +79 -0
  43. k_cli/tools/chaos_immunity.py +377 -0
  44. k_cli/tools/codebase_qa.py +106 -0
  45. k_cli/tools/command_runner.py +256 -0
  46. k_cli/tools/diagram_generator.py +547 -0
  47. k_cli/tools/doc_retriever.py +1332 -0
  48. k_cli/tools/feature.py +105 -0
  49. k_cli/tools/ghost_daemon.py +122 -0
  50. k_cli/tools/incident_triage.py +1365 -0
  51. k_cli/tools/mcp_client.py +1846 -0
  52. k_cli/tools/repo_gardener.py +142 -0
  53. k_cli/tools/rules.py +109 -0
  54. k_cli/tools/security.py +52 -0
  55. k_cli/tools/security_healer.py +999 -0
  56. k_cli/tools/synapse_graph.py +155 -0
  57. k_cli/tui/__init__.py +0 -0
  58. k_cli/tui/diff_viewer.py +223 -0
  59. k_cli/tui/tui.py +1145 -0
  60. k_cli/tui/tui_animations.py +648 -0
  61. k_cli/tui/tui_app.py +2788 -0
  62. k_cli/ui/__init__.py +10 -0
  63. k_cli/ui/simple_repl.py +315 -0
  64. k_cli/web/__init__.py +7 -0
  65. k_cli/web/server.py +624 -0
  66. k_cli/web/static/app.js +830 -0
  67. k_cli/web/static/index.html +495 -0
  68. k_cli/web/static/monitor.html +189 -0
  69. k_cli/web/static/style.css +838 -0
  70. k_cli_for_devs-1.0.0.dist-info/METADATA +461 -0
  71. k_cli_for_devs-1.0.0.dist-info/RECORD +75 -0
  72. k_cli_for_devs-1.0.0.dist-info/WHEEL +5 -0
  73. k_cli_for_devs-1.0.0.dist-info/entry_points.txt +2 -0
  74. k_cli_for_devs-1.0.0.dist-info/licenses/LICENSE +21 -0
  75. k_cli_for_devs-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,256 @@
1
+ """
2
+ command_runner.py - Local Machine Command Execution Engine for K-CLI
3
+ Project Bankai v1.0.0 — Built for AWS "Agents for Humans" Hackathon
4
+ Empowers K-CLI with Google Antigravity-grade local shell execution capabilities.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import logging
11
+ import os
12
+ import shlex
13
+ import subprocess
14
+ import sys
15
+ import time
16
+ from dataclasses import dataclass, field
17
+ from pathlib import Path
18
+ from typing import Any, AsyncIterator, Dict, List, Optional
19
+
20
+ logger = logging.getLogger("k_cli.tools.command_runner")
21
+
22
+
23
+ @dataclass
24
+ class CommandExecutionResult:
25
+ """Represents the outcome of a locally executed command."""
26
+ command: str
27
+ exit_code: int
28
+ stdout: str
29
+ stderr: str
30
+ duration_sec: float
31
+ cwd: str
32
+ success: bool = field(init=False)
33
+
34
+ def __post_init__(self):
35
+ self.success = (self.exit_code == 0)
36
+
37
+ def to_dict(self) -> Dict[str, Any]:
38
+ return {
39
+ "command": self.command,
40
+ "success": self.success,
41
+ "exit_code": self.exit_code,
42
+ "stdout": self.stdout,
43
+ "stderr": self.stderr,
44
+ "duration_sec": round(self.duration_sec, 3),
45
+ "cwd": self.cwd,
46
+ }
47
+
48
+ def summary(self) -> str:
49
+ status_symbol = "✔" if self.success else "✖"
50
+ lines = [
51
+ f"{status_symbol} Command: `{self.command}` (Exit Code: {self.exit_code}, Duration: {self.duration_sec:.2f}s)",
52
+ ]
53
+ if self.stdout.strip():
54
+ lines.append(f"--- STDOUT ---\n{self.stdout.strip()}")
55
+ if self.stderr.strip():
56
+ lines.append(f"--- STDERR ---\n{self.stderr.strip()}")
57
+ return "\n".join(lines)
58
+
59
+
60
+ class LocalCommandExecutor:
61
+ """
62
+ Google Antigravity-grade local shell command executor.
63
+ Executes commands on the developer's local machine with working directory management,
64
+ stdout/stderr capture, and timeout safeguards.
65
+ """
66
+
67
+ def __init__(self, default_cwd: Optional[str] = None):
68
+ self.default_cwd = str(Path(default_cwd or os.getcwd()).resolve())
69
+
70
+ def _prepare_env(self, env: Optional[Dict[str, str]] = None) -> Dict[str, str]:
71
+ exec_env = os.environ.copy()
72
+ venv_bin = os.path.join(sys.prefix, "bin")
73
+ if os.path.exists(venv_bin):
74
+ current_path = exec_env.get("PATH", "")
75
+ if venv_bin not in current_path:
76
+ exec_env["PATH"] = f"{venv_bin}:{current_path}"
77
+ exec_env["PYTHONPATH"] = "/home/k/K-Cli-for-Devs"
78
+ if env:
79
+ exec_env.update(env)
80
+ return exec_env
81
+
82
+ def execute(
83
+ self,
84
+ command: str,
85
+ cwd: Optional[str] = None,
86
+ timeout: int = 60,
87
+ env: Optional[Dict[str, str]] = None,
88
+ ) -> CommandExecutionResult:
89
+ """
90
+ Executes a shell command synchronously on the local machine.
91
+
92
+ Args:
93
+ command: The command line string to execute.
94
+ cwd: Working directory (defaults to executor default_cwd).
95
+ timeout: Maximum execution time in seconds (default 60).
96
+ env: Custom environment variables dict.
97
+
98
+ Returns:
99
+ CommandExecutionResult containing exit code, stdout, stderr, and duration.
100
+ """
101
+ target_cwd = str(Path(cwd or self.default_cwd).resolve())
102
+ exec_env = self._prepare_env(env)
103
+
104
+ start_time = time.time()
105
+ logger.info(f"Executing local command: {command} in {target_cwd}")
106
+
107
+ try:
108
+ # Use bash on POSIX systems or cmd on Windows
109
+ shell_executable = "/bin/bash" if os.name == "posix" and os.path.exists("/bin/bash") else None
110
+ proc = subprocess.run(
111
+ command,
112
+ shell=True,
113
+ cwd=target_cwd,
114
+ env=exec_env,
115
+ executable=shell_executable,
116
+ stdout=subprocess.PIPE,
117
+ stderr=subprocess.PIPE,
118
+ text=True,
119
+ errors="replace",
120
+ timeout=timeout,
121
+ )
122
+ duration = time.time() - start_time
123
+ return CommandExecutionResult(
124
+ command=command,
125
+ exit_code=proc.returncode,
126
+ stdout=proc.stdout or "",
127
+ stderr=proc.stderr or "",
128
+ duration_sec=duration,
129
+ cwd=target_cwd,
130
+ )
131
+ except subprocess.TimeoutExpired as te:
132
+ duration = time.time() - start_time
133
+ stdout = te.stdout if isinstance(te.stdout, str) else (te.stdout.decode("utf-8", "replace") if te.stdout else "")
134
+ stderr = te.stderr if isinstance(te.stderr, str) else (te.stderr.decode("utf-8", "replace") if te.stderr else "")
135
+ return CommandExecutionResult(
136
+ command=command,
137
+ exit_code=-1,
138
+ stdout=stdout,
139
+ stderr=f"{stderr}\n[Error] Command timed out after {timeout} seconds.",
140
+ duration_sec=duration,
141
+ cwd=target_cwd,
142
+ )
143
+ except Exception as exc:
144
+ duration = time.time() - start_time
145
+ return CommandExecutionResult(
146
+ command=command,
147
+ exit_code=1,
148
+ stdout="",
149
+ stderr=f"[Error] Failed to launch command: {exc}",
150
+ duration_sec=duration,
151
+ cwd=target_cwd,
152
+ )
153
+
154
+ async def execute_async(
155
+ self,
156
+ command: str,
157
+ cwd: Optional[str] = None,
158
+ timeout: int = 60,
159
+ env: Optional[Dict[str, str]] = None,
160
+ ) -> CommandExecutionResult:
161
+ """
162
+ Asynchronously executes a shell command using asyncio.subprocess.
163
+ """
164
+ target_cwd = str(Path(cwd or self.default_cwd).resolve())
165
+ exec_env = self._prepare_env(env)
166
+
167
+ start_time = time.time()
168
+ logger.info(f"Executing async local command: {command} in {target_cwd}")
169
+
170
+ try:
171
+ proc = await asyncio.create_subprocess_shell(
172
+ command,
173
+ cwd=target_cwd,
174
+ env=exec_env,
175
+ stdout=asyncio.subprocess.PIPE,
176
+ stderr=asyncio.subprocess.PIPE,
177
+ executable="/bin/bash" if os.name == "posix" and os.path.exists("/bin/bash") else None,
178
+ )
179
+
180
+ try:
181
+ stdout_data, stderr_data = await asyncio.wait_for(
182
+ proc.communicate(),
183
+ timeout=float(timeout)
184
+ )
185
+ duration = time.time() - start_time
186
+ stdout_str = stdout_data.decode("utf-8", "replace") if stdout_data else ""
187
+ stderr_str = stderr_data.decode("utf-8", "replace") if stderr_data else ""
188
+ return CommandExecutionResult(
189
+ command=command,
190
+ exit_code=proc.returncode if proc.returncode is not None else 0,
191
+ stdout=stdout_str,
192
+ stderr=stderr_str,
193
+ duration_sec=duration,
194
+ cwd=target_cwd,
195
+ )
196
+ except asyncio.TimeoutError:
197
+ duration = time.time() - start_time
198
+ try:
199
+ proc.kill()
200
+ await proc.wait()
201
+ except Exception:
202
+ pass
203
+ return CommandExecutionResult(
204
+ command=command,
205
+ exit_code=-1,
206
+ stdout="",
207
+ stderr=f"[Error] Command timed out after {timeout} seconds.",
208
+ duration_sec=duration,
209
+ cwd=target_cwd,
210
+ )
211
+ except Exception as exc:
212
+ duration = time.time() - start_time
213
+ return CommandExecutionResult(
214
+ command=command,
215
+ exit_code=1,
216
+ stdout="",
217
+ stderr=f"[Error] Failed to execute async command: {exc}",
218
+ duration_sec=duration,
219
+ cwd=target_cwd,
220
+ )
221
+
222
+ async def stream_output(
223
+ self,
224
+ command: str,
225
+ cwd: Optional[str] = None,
226
+ env: Optional[Dict[str, str]] = None,
227
+ ) -> AsyncIterator[str]:
228
+ """
229
+ Streams command stdout/stderr line-by-line as it executes.
230
+ """
231
+ target_cwd = str(Path(cwd or self.default_cwd).resolve())
232
+ exec_env = os.environ.copy()
233
+ if env:
234
+ exec_env.update(env)
235
+
236
+ proc = await asyncio.create_subprocess_shell(
237
+ command,
238
+ cwd=target_cwd,
239
+ env=exec_env,
240
+ stdout=asyncio.subprocess.PIPE,
241
+ stderr=asyncio.subprocess.STDOUT,
242
+ executable="/bin/bash" if os.name == "posix" and os.path.exists("/bin/bash") else None,
243
+ )
244
+
245
+ if proc.stdout:
246
+ while True:
247
+ line = await proc.stdout.readline()
248
+ if not line:
249
+ break
250
+ yield line.decode("utf-8", "replace")
251
+
252
+ await proc.wait()
253
+
254
+
255
+ # Global default executor singleton
256
+ global_command_executor = LocalCommandExecutor()