emdash-cli 0.1.35__py3-none-any.whl → 0.1.46__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.
- emdash_cli/client.py +35 -0
- emdash_cli/clipboard.py +30 -61
- emdash_cli/commands/agent/__init__.py +14 -0
- emdash_cli/commands/agent/cli.py +100 -0
- emdash_cli/commands/agent/constants.py +53 -0
- emdash_cli/commands/agent/file_utils.py +178 -0
- emdash_cli/commands/agent/handlers/__init__.py +41 -0
- emdash_cli/commands/agent/handlers/agents.py +421 -0
- emdash_cli/commands/agent/handlers/auth.py +69 -0
- emdash_cli/commands/agent/handlers/doctor.py +319 -0
- emdash_cli/commands/agent/handlers/hooks.py +121 -0
- emdash_cli/commands/agent/handlers/mcp.py +183 -0
- emdash_cli/commands/agent/handlers/misc.py +200 -0
- emdash_cli/commands/agent/handlers/rules.py +394 -0
- emdash_cli/commands/agent/handlers/sessions.py +168 -0
- emdash_cli/commands/agent/handlers/setup.py +582 -0
- emdash_cli/commands/agent/handlers/skills.py +440 -0
- emdash_cli/commands/agent/handlers/todos.py +98 -0
- emdash_cli/commands/agent/handlers/verify.py +648 -0
- emdash_cli/commands/agent/interactive.py +657 -0
- emdash_cli/commands/agent/menus.py +728 -0
- emdash_cli/commands/agent.py +7 -1321
- emdash_cli/commands/server.py +99 -40
- emdash_cli/server_manager.py +70 -10
- emdash_cli/sse_renderer.py +36 -5
- {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.46.dist-info}/METADATA +2 -4
- emdash_cli-0.1.46.dist-info/RECORD +49 -0
- emdash_cli-0.1.35.dist-info/RECORD +0 -30
- {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.46.dist-info}/WHEEL +0 -0
- {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.46.dist-info}/entry_points.txt +0 -0
emdash_cli/commands/server.py
CHANGED
|
@@ -10,6 +10,9 @@ from rich.console import Console
|
|
|
10
10
|
|
|
11
11
|
console = Console()
|
|
12
12
|
|
|
13
|
+
# Per-repo servers directory
|
|
14
|
+
SERVERS_DIR = Path.home() / ".emdash" / "servers"
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
@click.group()
|
|
15
18
|
def server():
|
|
@@ -26,23 +29,41 @@ def server_killall():
|
|
|
26
29
|
"""
|
|
27
30
|
killed = 0
|
|
28
31
|
|
|
29
|
-
# Kill by PID
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
# Kill servers by PID files in servers directory
|
|
33
|
+
if SERVERS_DIR.exists():
|
|
34
|
+
for pid_file in SERVERS_DIR.glob("*.pid"):
|
|
35
|
+
try:
|
|
36
|
+
pid = int(pid_file.read_text().strip())
|
|
37
|
+
os.kill(pid, signal.SIGTERM)
|
|
38
|
+
console.print(f"[green]Killed server process {pid}[/green]")
|
|
39
|
+
killed += 1
|
|
40
|
+
except (ValueError, ProcessLookupError, PermissionError):
|
|
41
|
+
pass
|
|
42
|
+
finally:
|
|
43
|
+
# Clean up all files for this server
|
|
44
|
+
hash_prefix = pid_file.stem
|
|
45
|
+
for ext in [".port", ".pid", ".repo"]:
|
|
46
|
+
server_file = SERVERS_DIR / f"{hash_prefix}{ext}"
|
|
47
|
+
if server_file.exists():
|
|
48
|
+
server_file.unlink(missing_ok=True)
|
|
49
|
+
|
|
50
|
+
# Also check legacy location
|
|
51
|
+
legacy_pid_file = Path.home() / ".emdash" / "server.pid"
|
|
52
|
+
if legacy_pid_file.exists():
|
|
32
53
|
try:
|
|
33
|
-
pid = int(
|
|
54
|
+
pid = int(legacy_pid_file.read_text().strip())
|
|
34
55
|
os.kill(pid, signal.SIGTERM)
|
|
35
|
-
console.print(f"[green]Killed server process {pid}[/green]")
|
|
56
|
+
console.print(f"[green]Killed legacy server process {pid}[/green]")
|
|
36
57
|
killed += 1
|
|
37
58
|
except (ValueError, ProcessLookupError, PermissionError):
|
|
38
59
|
pass
|
|
39
60
|
finally:
|
|
40
|
-
|
|
61
|
+
legacy_pid_file.unlink(missing_ok=True)
|
|
41
62
|
|
|
42
|
-
# Clean up port file
|
|
43
|
-
|
|
44
|
-
if
|
|
45
|
-
|
|
63
|
+
# Clean up legacy port file
|
|
64
|
+
legacy_port_file = Path.home() / ".emdash" / "server.port"
|
|
65
|
+
if legacy_port_file.exists():
|
|
66
|
+
legacy_port_file.unlink(missing_ok=True)
|
|
46
67
|
|
|
47
68
|
# Kill any remaining emdash_core.server processes
|
|
48
69
|
try:
|
|
@@ -77,41 +98,79 @@ def server_killall():
|
|
|
77
98
|
|
|
78
99
|
@server.command("status")
|
|
79
100
|
def server_status():
|
|
80
|
-
"""Show
|
|
101
|
+
"""Show status of all running servers.
|
|
81
102
|
|
|
82
103
|
Example:
|
|
83
104
|
emdash server status
|
|
84
105
|
"""
|
|
85
|
-
|
|
86
|
-
pid_file = Path.home() / ".emdash" / "server.pid"
|
|
106
|
+
import httpx
|
|
87
107
|
|
|
88
|
-
|
|
89
|
-
console.print("[yellow]No server running[/yellow]")
|
|
90
|
-
return
|
|
108
|
+
servers_found = []
|
|
91
109
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
# Check per-repo servers directory
|
|
111
|
+
if SERVERS_DIR.exists():
|
|
112
|
+
for port_file in SERVERS_DIR.glob("*.port"):
|
|
113
|
+
try:
|
|
114
|
+
port = int(port_file.read_text().strip())
|
|
115
|
+
hash_prefix = port_file.stem
|
|
97
116
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
117
|
+
# Get repo path if available
|
|
118
|
+
repo_file = SERVERS_DIR / f"{hash_prefix}.repo"
|
|
119
|
+
repo_path = repo_file.read_text().strip() if repo_file.exists() else "unknown"
|
|
120
|
+
|
|
121
|
+
# Get PID if available
|
|
122
|
+
pid_file = SERVERS_DIR / f"{hash_prefix}.pid"
|
|
123
|
+
pid = pid_file.read_text().strip() if pid_file.exists() else "unknown"
|
|
124
|
+
|
|
125
|
+
# Check health
|
|
105
126
|
try:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
response = httpx.get(f"http://localhost:{port}/api/health", timeout=2.0)
|
|
128
|
+
healthy = response.status_code == 200
|
|
129
|
+
except (httpx.RequestError, httpx.TimeoutException):
|
|
130
|
+
healthy = False
|
|
131
|
+
|
|
132
|
+
servers_found.append({
|
|
133
|
+
"port": port,
|
|
134
|
+
"pid": pid,
|
|
135
|
+
"repo": repo_path,
|
|
136
|
+
"healthy": healthy,
|
|
137
|
+
})
|
|
138
|
+
except (ValueError, IOError):
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
# Check legacy location
|
|
142
|
+
legacy_port_file = Path.home() / ".emdash" / "server.port"
|
|
143
|
+
if legacy_port_file.exists():
|
|
144
|
+
try:
|
|
145
|
+
port = int(legacy_port_file.read_text().strip())
|
|
146
|
+
legacy_pid_file = Path.home() / ".emdash" / "server.pid"
|
|
147
|
+
pid = legacy_pid_file.read_text().strip() if legacy_pid_file.exists() else "unknown"
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
response = httpx.get(f"http://localhost:{port}/api/health", timeout=2.0)
|
|
151
|
+
healthy = response.status_code == 200
|
|
152
|
+
except (httpx.RequestError, httpx.TimeoutException):
|
|
153
|
+
healthy = False
|
|
154
|
+
|
|
155
|
+
servers_found.append({
|
|
156
|
+
"port": port,
|
|
157
|
+
"pid": pid,
|
|
158
|
+
"repo": "(legacy)",
|
|
159
|
+
"healthy": healthy,
|
|
160
|
+
})
|
|
161
|
+
except (ValueError, IOError):
|
|
162
|
+
pass
|
|
163
|
+
|
|
164
|
+
if not servers_found:
|
|
165
|
+
console.print("[yellow]No servers running[/yellow]")
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
console.print(f"[bold]Found {len(servers_found)} server(s):[/bold]\n")
|
|
169
|
+
for srv in servers_found:
|
|
170
|
+
status = "[green]healthy[/green]" if srv["healthy"] else "[red]unhealthy[/red]"
|
|
171
|
+
console.print(f" {status}")
|
|
172
|
+
console.print(f" Port: {srv['port']}")
|
|
173
|
+
console.print(f" PID: {srv['pid']}")
|
|
174
|
+
console.print(f" Repo: {srv['repo']}")
|
|
175
|
+
console.print(f" URL: http://localhost:{srv['port']}")
|
|
176
|
+
console.print()
|
emdash_cli/server_manager.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Server lifecycle management for emdash-core."""
|
|
2
2
|
|
|
3
3
|
import atexit
|
|
4
|
+
import hashlib
|
|
4
5
|
import os
|
|
5
6
|
import signal
|
|
6
7
|
import socket
|
|
@@ -17,15 +18,15 @@ class ServerManager:
|
|
|
17
18
|
"""Manages FastAPI server lifecycle for CLI.
|
|
18
19
|
|
|
19
20
|
The ServerManager handles:
|
|
21
|
+
- Per-repo server instances (each repo gets its own server)
|
|
20
22
|
- Discovering running servers via port file
|
|
21
23
|
- Starting new servers when needed
|
|
22
24
|
- Health checking servers
|
|
23
25
|
- Graceful shutdown on CLI exit
|
|
26
|
+
- Cleanup of stale servers
|
|
24
27
|
"""
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
PORT_FILE = Path.home() / ".emdash" / "server.port"
|
|
28
|
-
PID_FILE = Path.home() / ".emdash" / "server.pid"
|
|
29
|
+
SERVERS_DIR = Path.home() / ".emdash" / "servers"
|
|
29
30
|
STARTUP_TIMEOUT = 30.0 # seconds
|
|
30
31
|
HEALTH_TIMEOUT = 2.0 # seconds
|
|
31
32
|
|
|
@@ -40,8 +41,35 @@ class ServerManager:
|
|
|
40
41
|
self.port: Optional[int] = None
|
|
41
42
|
self._started_by_us = False
|
|
42
43
|
|
|
44
|
+
# Create servers directory
|
|
45
|
+
self.SERVERS_DIR.mkdir(parents=True, exist_ok=True)
|
|
46
|
+
|
|
47
|
+
# Cleanup stale servers on init
|
|
48
|
+
self._cleanup_stale_servers()
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def _repo_hash(self) -> str:
|
|
52
|
+
"""Get a short hash of the repo root path for unique file naming."""
|
|
53
|
+
path_str = str(self.repo_root.resolve())
|
|
54
|
+
return hashlib.sha256(path_str.encode()).hexdigest()[:12]
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def _port_file(self) -> Path:
|
|
58
|
+
"""Get the port file path for this repo."""
|
|
59
|
+
return self.SERVERS_DIR / f"{self._repo_hash}.port"
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def _pid_file(self) -> Path:
|
|
63
|
+
"""Get the PID file path for this repo."""
|
|
64
|
+
return self.SERVERS_DIR / f"{self._repo_hash}.pid"
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def _repo_file(self) -> Path:
|
|
68
|
+
"""Get the repo path file for this repo (for debugging)."""
|
|
69
|
+
return self.SERVERS_DIR / f"{self._repo_hash}.repo"
|
|
70
|
+
|
|
43
71
|
def get_server_url(self) -> str:
|
|
44
|
-
"""Get URL of running server, starting one if needed.
|
|
72
|
+
"""Get URL of running server for this repo, starting one if needed.
|
|
45
73
|
|
|
46
74
|
Returns:
|
|
47
75
|
Base URL of the running server (e.g., "http://localhost:8765")
|
|
@@ -49,17 +77,19 @@ class ServerManager:
|
|
|
49
77
|
Raises:
|
|
50
78
|
RuntimeError: If server fails to start
|
|
51
79
|
"""
|
|
52
|
-
# Check if server already running
|
|
53
|
-
if self.
|
|
80
|
+
# Check if server already running for THIS repo
|
|
81
|
+
if self._port_file.exists():
|
|
54
82
|
try:
|
|
55
|
-
port = int(self.
|
|
83
|
+
port = int(self._port_file.read_text().strip())
|
|
56
84
|
if self._check_health(port):
|
|
57
85
|
self.port = port
|
|
58
86
|
return f"http://localhost:{port}"
|
|
59
87
|
except (ValueError, IOError):
|
|
60
88
|
pass
|
|
89
|
+
# Server not healthy, clean up stale files
|
|
90
|
+
self._cleanup_files()
|
|
61
91
|
|
|
62
|
-
# Start new server
|
|
92
|
+
# Start new server for this repo
|
|
63
93
|
self.port = self._find_free_port()
|
|
64
94
|
self._spawn_server()
|
|
65
95
|
return f"http://localhost:{self.port}"
|
|
@@ -133,6 +163,11 @@ class ServerManager:
|
|
|
133
163
|
|
|
134
164
|
self._started_by_us = True
|
|
135
165
|
|
|
166
|
+
# Write port, PID, and repo files
|
|
167
|
+
self._port_file.write_text(str(self.port))
|
|
168
|
+
self._pid_file.write_text(str(self.process.pid))
|
|
169
|
+
self._repo_file.write_text(str(self.repo_root))
|
|
170
|
+
|
|
136
171
|
# Register cleanup for normal exit
|
|
137
172
|
atexit.register(self.shutdown)
|
|
138
173
|
|
|
@@ -203,14 +238,39 @@ class ServerManager:
|
|
|
203
238
|
)
|
|
204
239
|
|
|
205
240
|
def _cleanup_files(self) -> None:
|
|
206
|
-
"""Clean up port and
|
|
207
|
-
for file in [self.
|
|
241
|
+
"""Clean up port, PID, and repo files for this repo."""
|
|
242
|
+
for file in [self._port_file, self._pid_file, self._repo_file]:
|
|
208
243
|
try:
|
|
209
244
|
if file.exists():
|
|
210
245
|
file.unlink()
|
|
211
246
|
except IOError:
|
|
212
247
|
pass
|
|
213
248
|
|
|
249
|
+
def _cleanup_stale_servers(self) -> None:
|
|
250
|
+
"""Clean up stale server files where process no longer exists."""
|
|
251
|
+
if not self.SERVERS_DIR.exists():
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
for pid_file in self.SERVERS_DIR.glob("*.pid"):
|
|
255
|
+
try:
|
|
256
|
+
pid = int(pid_file.read_text().strip())
|
|
257
|
+
# Check if process exists
|
|
258
|
+
try:
|
|
259
|
+
os.kill(pid, 0) # Signal 0 checks if process exists
|
|
260
|
+
except OSError:
|
|
261
|
+
# Process doesn't exist, clean up files
|
|
262
|
+
hash_prefix = pid_file.stem
|
|
263
|
+
for ext in [".port", ".pid", ".repo"]:
|
|
264
|
+
stale_file = self.SERVERS_DIR / f"{hash_prefix}{ext}"
|
|
265
|
+
if stale_file.exists():
|
|
266
|
+
stale_file.unlink()
|
|
267
|
+
except (ValueError, IOError):
|
|
268
|
+
# Invalid PID file, remove it
|
|
269
|
+
try:
|
|
270
|
+
pid_file.unlink()
|
|
271
|
+
except IOError:
|
|
272
|
+
pass
|
|
273
|
+
|
|
214
274
|
|
|
215
275
|
# Global singleton for CLI commands
|
|
216
276
|
_server_manager: Optional[ServerManager] = None
|
emdash_cli/sse_renderer.py
CHANGED
|
@@ -68,6 +68,9 @@ class SSERenderer:
|
|
|
68
68
|
# Extended thinking storage
|
|
69
69
|
self._last_thinking: Optional[str] = None
|
|
70
70
|
|
|
71
|
+
# Context frame storage (rendered at end of stream)
|
|
72
|
+
self._last_context_frame: Optional[dict] = None
|
|
73
|
+
|
|
71
74
|
def render_stream(
|
|
72
75
|
self,
|
|
73
76
|
lines: Iterator[str],
|
|
@@ -127,6 +130,11 @@ class SSERenderer:
|
|
|
127
130
|
# Always stop spinner when stream ends
|
|
128
131
|
self._stop_spinner()
|
|
129
132
|
|
|
133
|
+
# Render context frame at the end (only once)
|
|
134
|
+
if self.verbose:
|
|
135
|
+
self._render_final_context_frame()
|
|
136
|
+
# Keep _last_context_frame for /context command access
|
|
137
|
+
|
|
130
138
|
return {
|
|
131
139
|
"content": final_response,
|
|
132
140
|
"session_id": self._session_id,
|
|
@@ -311,12 +319,12 @@ class SSERenderer:
|
|
|
311
319
|
if "path" in args:
|
|
312
320
|
path = str(args["path"])
|
|
313
321
|
# Shorten long paths
|
|
314
|
-
if len(path) >
|
|
315
|
-
summary = "..." + path[-
|
|
322
|
+
if len(path) > 50:
|
|
323
|
+
summary = "..." + path[-47:]
|
|
316
324
|
else:
|
|
317
325
|
summary = path
|
|
318
326
|
elif "pattern" in args:
|
|
319
|
-
summary = str(args["pattern"])[:
|
|
327
|
+
summary = str(args["pattern"])[:50]
|
|
320
328
|
|
|
321
329
|
# Build compact progress line
|
|
322
330
|
line = f" │ {spinner} ({agent_type}) {self._subagent_tool_count} tools... {tool_name} {summary}"
|
|
@@ -455,7 +463,7 @@ class SSERenderer:
|
|
|
455
463
|
self._stop_spinner()
|
|
456
464
|
|
|
457
465
|
# Truncate prompt for display
|
|
458
|
-
prompt_display = prompt[:
|
|
466
|
+
prompt_display = prompt[:150] + "..." if len(prompt) > 150 else prompt
|
|
459
467
|
|
|
460
468
|
self.console.print()
|
|
461
469
|
# Use different colors for different agent types
|
|
@@ -717,7 +725,16 @@ class SSERenderer:
|
|
|
717
725
|
self.console.print(f"\n[red]Session ended with error: {error}[/red]")
|
|
718
726
|
|
|
719
727
|
def _render_context_frame(self, data: dict) -> None:
|
|
720
|
-
"""
|
|
728
|
+
"""Store context frame data to render at end of stream."""
|
|
729
|
+
# Just store the latest context frame, will render at end
|
|
730
|
+
self._last_context_frame = data
|
|
731
|
+
|
|
732
|
+
def _render_final_context_frame(self) -> None:
|
|
733
|
+
"""Render the final context frame at end of agent loop."""
|
|
734
|
+
if not self._last_context_frame:
|
|
735
|
+
return
|
|
736
|
+
|
|
737
|
+
data = self._last_context_frame
|
|
721
738
|
adding = data.get("adding") or {}
|
|
722
739
|
reading = data.get("reading") or {}
|
|
723
740
|
|
|
@@ -761,3 +778,17 @@ class SSERenderer:
|
|
|
761
778
|
|
|
762
779
|
if stats:
|
|
763
780
|
self.console.print(f" [dim]{' · '.join(stats)}[/dim]")
|
|
781
|
+
|
|
782
|
+
# Show reranked items (for testing)
|
|
783
|
+
items = reading.get("items", [])
|
|
784
|
+
if items:
|
|
785
|
+
self.console.print(f"\n [bold]Reranked Items ({len(items)}):[/bold]")
|
|
786
|
+
for item in items[:10]: # Show top 10
|
|
787
|
+
name = item.get("name", "?")
|
|
788
|
+
item_type = item.get("type", "?")
|
|
789
|
+
score = item.get("score")
|
|
790
|
+
file_path = item.get("file", "")
|
|
791
|
+
score_str = f" [cyan]({score:.3f})[/cyan]" if score is not None else ""
|
|
792
|
+
self.console.print(f" [dim]{item_type}[/dim] [bold]{name}[/bold]{score_str}")
|
|
793
|
+
if file_path:
|
|
794
|
+
self.console.print(f" [dim]{file_path}[/dim]")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emdash-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.46
|
|
4
4
|
Summary: EmDash CLI - Command-line interface for code intelligence
|
|
5
5
|
Author: Em Dash Team
|
|
6
6
|
Requires-Python: >=3.10,<4.0
|
|
@@ -10,10 +10,8 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
-
Provides-Extra: images
|
|
14
13
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
15
|
-
Requires-Dist: emdash-core (>=0.1.
|
|
14
|
+
Requires-Dist: emdash-core (>=0.1.46)
|
|
16
15
|
Requires-Dist: httpx (>=0.25.0)
|
|
17
|
-
Requires-Dist: pillow (>=10.0.0) ; extra == "images"
|
|
18
16
|
Requires-Dist: prompt_toolkit (>=3.0.43,<4.0.0)
|
|
19
17
|
Requires-Dist: rich (>=13.7.0)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
emdash_cli/__init__.py,sha256=21JmQcWge3QOM4hLjtBdu-7AoxJonJuIwMeobWIjr2w,690
|
|
2
|
+
emdash_cli/client.py,sha256=00RTy6yAr1j2P0XIJGOhcjP5C16-5EGJLXBUKFUcxAU,22054
|
|
3
|
+
emdash_cli/clipboard.py,sha256=3iwkfj4Od1gPSsMbIBc6sx9XH2XCNgvc5Uu2pPRGcpw,2371
|
|
4
|
+
emdash_cli/commands/__init__.py,sha256=D9edXBHm69tueUtE4DggTA1_Yjsl9YZaKjBVDY2D_gQ,712
|
|
5
|
+
emdash_cli/commands/agent/__init__.py,sha256=Q02HtlODcid-YS_HDqBjbW6V8Xg9pYy0gWvrxn1EB9E,410
|
|
6
|
+
emdash_cli/commands/agent/cli.py,sha256=bfRSRAo6exy3llBoHS81AgGKP36xJ3MyL9eoLBtnJW4,2975
|
|
7
|
+
emdash_cli/commands/agent/constants.py,sha256=1H9fEObjsMeFzXVz0kQdB6HamSmvYqeMQLnX0ozStYU,1915
|
|
8
|
+
emdash_cli/commands/agent/file_utils.py,sha256=2YOKybPVGyjmImbqLHQOIL7zDKeVjQMWssAh9ZX1_Vc,5257
|
|
9
|
+
emdash_cli/commands/agent/handlers/__init__.py,sha256=70VjCycodve_zhQN_kuuYFY2Fi2vpvI8uawJqxXpCY8,958
|
|
10
|
+
emdash_cli/commands/agent/handlers/agents.py,sha256=5k_1lp_lynTrzqyYAPz9UXFt9esFzy6v0hOoyfeZCHI,14329
|
|
11
|
+
emdash_cli/commands/agent/handlers/auth.py,sha256=L2CrWdHg7Xb8e1l3UEGaYPmLubIx1r-e__qkzy5mQZ0,2401
|
|
12
|
+
emdash_cli/commands/agent/handlers/doctor.py,sha256=yECBNFgHzHS2m-P2xmXkZ4AKpTMhT2IYS-Dz4NcoM94,10019
|
|
13
|
+
emdash_cli/commands/agent/handlers/hooks.py,sha256=vZUdzppD6ztw8S757Rb6FMmWhU7n3SIayHHIIry41yU,5176
|
|
14
|
+
emdash_cli/commands/agent/handlers/mcp.py,sha256=ei76RZQ6bniaxxMX8yh9aIkKJET5aKFT7oj4GiPQ2wM,6255
|
|
15
|
+
emdash_cli/commands/agent/handlers/misc.py,sha256=q6zvqd0WzsZgUjVbXuxZVlFrLxi9Tq8Ll3ljhpQeWhY,7951
|
|
16
|
+
emdash_cli/commands/agent/handlers/rules.py,sha256=lvpBGmcSO0vfRCn052QMyH50GXMGhYlEFeJF6fNoZPg,12510
|
|
17
|
+
emdash_cli/commands/agent/handlers/sessions.py,sha256=GGDP9AsVYhbKT7HtDrGu-y2FsEyos39UqgOceebJLXs,6609
|
|
18
|
+
emdash_cli/commands/agent/handlers/setup.py,sha256=5EAXXb3aku86I1X8_eskn-5tTzxmlyyzljsDkVKlyEQ,17246
|
|
19
|
+
emdash_cli/commands/agent/handlers/skills.py,sha256=3a3ZW51WesfGd_V7JJwmW80gJhFiDVONJA6Yr8jRaQI,14538
|
|
20
|
+
emdash_cli/commands/agent/handlers/todos.py,sha256=N3BTxvOxRpVpgQGezE66kKWYKeYFrF9l-pKAE2V_4z4,3931
|
|
21
|
+
emdash_cli/commands/agent/handlers/verify.py,sha256=9F_pzRZyqUr9MvFQx7IxsajrKIrBwoRjXL5RWxi9OTo,20717
|
|
22
|
+
emdash_cli/commands/agent/interactive.py,sha256=6ItB_HnZteHN-5E-bfa0dMgRw2pyyKDtinT530qxe54,24597
|
|
23
|
+
emdash_cli/commands/agent/menus.py,sha256=Kvw142-pbv9pLRAzd1E3XvsjRRUhgNozCeBex9uavN0,21269
|
|
24
|
+
emdash_cli/commands/agent.py,sha256=fJmiBecmnjdaeNwHIpexC4O6sISIqVD8SKiySBoBWvY,321
|
|
25
|
+
emdash_cli/commands/analyze.py,sha256=c9ztbv0Ra7g2AlDmMOy-9L51fDVuoqbuzxnRfomoFIQ,4403
|
|
26
|
+
emdash_cli/commands/auth.py,sha256=SpWdqO1bJCgt4x1B4Pr7hNOucwTuBFJ1oGPOzXtvwZM,3816
|
|
27
|
+
emdash_cli/commands/db.py,sha256=nZK7gLDVE2lAQVYrMx6Swscml5OAtkbg-EcSNSvRIlA,2922
|
|
28
|
+
emdash_cli/commands/embed.py,sha256=kqP5jtYCsZ2_s_I1DjzIUgaod1VUvPiRO0jIIY0HtCs,3244
|
|
29
|
+
emdash_cli/commands/index.py,sha256=uFNC5whhU9JdF_59FeM99OPdzKLBTJLkLO6vp9pt944,6959
|
|
30
|
+
emdash_cli/commands/plan.py,sha256=BRiyIhfy_zz2PYy4Qo3a0t77GwHhdssZk6NImOkPi-w,2189
|
|
31
|
+
emdash_cli/commands/projectmd.py,sha256=4y4cn_yFw85jMUm52nGjpqnd-YWvs6ZNEMWJGeJC17Q,1605
|
|
32
|
+
emdash_cli/commands/research.py,sha256=xtI9_9emY7-rGQD5xJALTxtgTFmI4dplYW148dtTaTs,1553
|
|
33
|
+
emdash_cli/commands/rules.py,sha256=n85CCG0WNIBEsUK9STJetPmZxoypQtest5BGPsXl0ac,2712
|
|
34
|
+
emdash_cli/commands/search.py,sha256=DrSv_oN2xF1NaKCBICdyII7eupVRsDQ2ysW-TPSU0X0,1661
|
|
35
|
+
emdash_cli/commands/server.py,sha256=uqgp0DH7bJhu8E3k8PM1IaPLAogTtjCXu6iaZyfiOOw,5868
|
|
36
|
+
emdash_cli/commands/skills.py,sha256=8N4279Hr8u2L8AgVjSTRVBLJBcXhN5DN7dn5fME62bs,9989
|
|
37
|
+
emdash_cli/commands/spec.py,sha256=qafDmzKyRH035p3xTm_VTUsQLDZblIzIg-dxjEPv6tM,1494
|
|
38
|
+
emdash_cli/commands/swarm.py,sha256=s_cntuorNdtNNTD2Qs1p2IcHghMrBMOQuturPS3y9mM,2661
|
|
39
|
+
emdash_cli/commands/tasks.py,sha256=TdyunjSV5w7jpNFwv0fTL-_No5Fyvdm7Z2nXqxWSJec,1635
|
|
40
|
+
emdash_cli/commands/team.py,sha256=K1-IJg6iG-9HMF_3JmpNDlNs1PYbb-ThFHU9KU_jKRo,1430
|
|
41
|
+
emdash_cli/keyboard.py,sha256=haYYAuhYGtdjomzhIFy_3Z3eN3BXfMdb4uRQjwB0tbk,4593
|
|
42
|
+
emdash_cli/main.py,sha256=c-faWp-jzf9a0BbXhVoPvPQfGWSryXpYfswehqZCYPM,2593
|
|
43
|
+
emdash_cli/server_manager.py,sha256=saSxTaCu-b2n2-cIA3VzUe-Tj8ABpeZ39TPOdqjBzVI,9397
|
|
44
|
+
emdash_cli/session_store.py,sha256=GjS73GLSZ3oTNtrFHMcyiP6GnH0Dvfvs6r4s3-bfEaM,9424
|
|
45
|
+
emdash_cli/sse_renderer.py,sha256=kP_MygMQqW06kmPsD2BRMOdvXJTC4NG6_8_2IfioL4I,29092
|
|
46
|
+
emdash_cli-0.1.46.dist-info/METADATA,sha256=0-d6wf19RzND2n9QHDqQUPgROpQRglX0z7tTF4SvUw0,662
|
|
47
|
+
emdash_cli-0.1.46.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
48
|
+
emdash_cli-0.1.46.dist-info/entry_points.txt,sha256=31CuYD0k-tM8csFWDunc-JoZTxXaifj3oIXz4V0p6F0,122
|
|
49
|
+
emdash_cli-0.1.46.dist-info/RECORD,,
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
emdash_cli/__init__.py,sha256=21JmQcWge3QOM4hLjtBdu-7AoxJonJuIwMeobWIjr2w,690
|
|
2
|
-
emdash_cli/client.py,sha256=MZCyajCM7UghFVv_lKoPAaX0lUUDTe4FI4qlIPCYvcc,21008
|
|
3
|
-
emdash_cli/clipboard.py,sha256=hcg5sbIhbixqzpJdonoFLGBlSo2AKjplNrWy5PGnqaY,3564
|
|
4
|
-
emdash_cli/commands/__init__.py,sha256=D9edXBHm69tueUtE4DggTA1_Yjsl9YZaKjBVDY2D_gQ,712
|
|
5
|
-
emdash_cli/commands/agent.py,sha256=ZBCJWxX-Ze6UlmU3POO3EMjCdOc6D_akxlr6T4U-p74,48445
|
|
6
|
-
emdash_cli/commands/analyze.py,sha256=c9ztbv0Ra7g2AlDmMOy-9L51fDVuoqbuzxnRfomoFIQ,4403
|
|
7
|
-
emdash_cli/commands/auth.py,sha256=SpWdqO1bJCgt4x1B4Pr7hNOucwTuBFJ1oGPOzXtvwZM,3816
|
|
8
|
-
emdash_cli/commands/db.py,sha256=nZK7gLDVE2lAQVYrMx6Swscml5OAtkbg-EcSNSvRIlA,2922
|
|
9
|
-
emdash_cli/commands/embed.py,sha256=kqP5jtYCsZ2_s_I1DjzIUgaod1VUvPiRO0jIIY0HtCs,3244
|
|
10
|
-
emdash_cli/commands/index.py,sha256=uFNC5whhU9JdF_59FeM99OPdzKLBTJLkLO6vp9pt944,6959
|
|
11
|
-
emdash_cli/commands/plan.py,sha256=BRiyIhfy_zz2PYy4Qo3a0t77GwHhdssZk6NImOkPi-w,2189
|
|
12
|
-
emdash_cli/commands/projectmd.py,sha256=4y4cn_yFw85jMUm52nGjpqnd-YWvs6ZNEMWJGeJC17Q,1605
|
|
13
|
-
emdash_cli/commands/research.py,sha256=xtI9_9emY7-rGQD5xJALTxtgTFmI4dplYW148dtTaTs,1553
|
|
14
|
-
emdash_cli/commands/rules.py,sha256=n85CCG0WNIBEsUK9STJetPmZxoypQtest5BGPsXl0ac,2712
|
|
15
|
-
emdash_cli/commands/search.py,sha256=DrSv_oN2xF1NaKCBICdyII7eupVRsDQ2ysW-TPSU0X0,1661
|
|
16
|
-
emdash_cli/commands/server.py,sha256=UTmLAVolT0krN9xCtMcCSvmQZ9k1QwpFFmXGg9BulRY,3459
|
|
17
|
-
emdash_cli/commands/skills.py,sha256=8N4279Hr8u2L8AgVjSTRVBLJBcXhN5DN7dn5fME62bs,9989
|
|
18
|
-
emdash_cli/commands/spec.py,sha256=qafDmzKyRH035p3xTm_VTUsQLDZblIzIg-dxjEPv6tM,1494
|
|
19
|
-
emdash_cli/commands/swarm.py,sha256=s_cntuorNdtNNTD2Qs1p2IcHghMrBMOQuturPS3y9mM,2661
|
|
20
|
-
emdash_cli/commands/tasks.py,sha256=TdyunjSV5w7jpNFwv0fTL-_No5Fyvdm7Z2nXqxWSJec,1635
|
|
21
|
-
emdash_cli/commands/team.py,sha256=K1-IJg6iG-9HMF_3JmpNDlNs1PYbb-ThFHU9KU_jKRo,1430
|
|
22
|
-
emdash_cli/keyboard.py,sha256=haYYAuhYGtdjomzhIFy_3Z3eN3BXfMdb4uRQjwB0tbk,4593
|
|
23
|
-
emdash_cli/main.py,sha256=c-faWp-jzf9a0BbXhVoPvPQfGWSryXpYfswehqZCYPM,2593
|
|
24
|
-
emdash_cli/server_manager.py,sha256=RrLteSHUmcFV4cyHJAEmgM9qHru2mJS08QNLWno6Y3Y,7051
|
|
25
|
-
emdash_cli/session_store.py,sha256=GjS73GLSZ3oTNtrFHMcyiP6GnH0Dvfvs6r4s3-bfEaM,9424
|
|
26
|
-
emdash_cli/sse_renderer.py,sha256=QRykGh1BirtRC_2_3X48zJ0gctDEF7OV5VgiM0QUwtQ,27750
|
|
27
|
-
emdash_cli-0.1.35.dist-info/METADATA,sha256=Imi3rtfGyvWLC_ddLV8GiPPeSQlavqcB78XgowoJufg,738
|
|
28
|
-
emdash_cli-0.1.35.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
29
|
-
emdash_cli-0.1.35.dist-info/entry_points.txt,sha256=31CuYD0k-tM8csFWDunc-JoZTxXaifj3oIXz4V0p6F0,122
|
|
30
|
-
emdash_cli-0.1.35.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|