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.
Files changed (30) hide show
  1. emdash_cli/client.py +35 -0
  2. emdash_cli/clipboard.py +30 -61
  3. emdash_cli/commands/agent/__init__.py +14 -0
  4. emdash_cli/commands/agent/cli.py +100 -0
  5. emdash_cli/commands/agent/constants.py +53 -0
  6. emdash_cli/commands/agent/file_utils.py +178 -0
  7. emdash_cli/commands/agent/handlers/__init__.py +41 -0
  8. emdash_cli/commands/agent/handlers/agents.py +421 -0
  9. emdash_cli/commands/agent/handlers/auth.py +69 -0
  10. emdash_cli/commands/agent/handlers/doctor.py +319 -0
  11. emdash_cli/commands/agent/handlers/hooks.py +121 -0
  12. emdash_cli/commands/agent/handlers/mcp.py +183 -0
  13. emdash_cli/commands/agent/handlers/misc.py +200 -0
  14. emdash_cli/commands/agent/handlers/rules.py +394 -0
  15. emdash_cli/commands/agent/handlers/sessions.py +168 -0
  16. emdash_cli/commands/agent/handlers/setup.py +582 -0
  17. emdash_cli/commands/agent/handlers/skills.py +440 -0
  18. emdash_cli/commands/agent/handlers/todos.py +98 -0
  19. emdash_cli/commands/agent/handlers/verify.py +648 -0
  20. emdash_cli/commands/agent/interactive.py +657 -0
  21. emdash_cli/commands/agent/menus.py +728 -0
  22. emdash_cli/commands/agent.py +7 -1321
  23. emdash_cli/commands/server.py +99 -40
  24. emdash_cli/server_manager.py +70 -10
  25. emdash_cli/sse_renderer.py +36 -5
  26. {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.46.dist-info}/METADATA +2 -4
  27. emdash_cli-0.1.46.dist-info/RECORD +49 -0
  28. emdash_cli-0.1.35.dist-info/RECORD +0 -30
  29. {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.46.dist-info}/WHEEL +0 -0
  30. {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.46.dist-info}/entry_points.txt +0 -0
@@ -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 file first
30
- pid_file = Path.home() / ".emdash" / "server.pid"
31
- if pid_file.exists():
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(pid_file.read_text().strip())
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
- pid_file.unlink(missing_ok=True)
61
+ legacy_pid_file.unlink(missing_ok=True)
41
62
 
42
- # Clean up port file
43
- port_file = Path.home() / ".emdash" / "server.port"
44
- if port_file.exists():
45
- port_file.unlink(missing_ok=True)
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 server status.
101
+ """Show status of all running servers.
81
102
 
82
103
  Example:
83
104
  emdash server status
84
105
  """
85
- port_file = Path.home() / ".emdash" / "server.port"
86
- pid_file = Path.home() / ".emdash" / "server.pid"
106
+ import httpx
87
107
 
88
- if not port_file.exists():
89
- console.print("[yellow]No server running[/yellow]")
90
- return
108
+ servers_found = []
91
109
 
92
- try:
93
- port = int(port_file.read_text().strip())
94
- except (ValueError, IOError):
95
- console.print("[yellow]No server running (invalid port file)[/yellow]")
96
- return
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
- # Check if server is responsive
99
- import httpx
100
- try:
101
- response = httpx.get(f"http://localhost:{port}/api/health", timeout=2.0)
102
- if response.status_code == 200:
103
- pid = "unknown"
104
- if pid_file.exists():
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
- pid = pid_file.read_text().strip()
107
- except IOError:
108
- pass
109
-
110
- console.print(f"[bold green]Server running[/bold green]")
111
- console.print(f" Port: {port}")
112
- console.print(f" PID: {pid}")
113
- console.print(f" URL: http://localhost:{port}")
114
- else:
115
- console.print(f"[yellow]Server on port {port} not healthy[/yellow]")
116
- except (httpx.RequestError, httpx.TimeoutException):
117
- console.print(f"[yellow]Server on port {port} not responding[/yellow]")
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()
@@ -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
- DEFAULT_PORT = 8765
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.PORT_FILE.exists():
80
+ # Check if server already running for THIS repo
81
+ if self._port_file.exists():
54
82
  try:
55
- port = int(self.PORT_FILE.read_text().strip())
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 PID files."""
207
- for file in [self.PORT_FILE, self.PID_FILE]:
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
@@ -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) > 30:
315
- summary = "..." + path[-27:]
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"])[:25]
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[:80] + "..." if len(prompt) > 80 else 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
- """Render context frame update (post-agentic loop summary)."""
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.35
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.35)
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,,