emdash-cli 0.1.4__py3-none-any.whl → 0.1.17__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/__init__.py +6 -1
- emdash_cli/client.py +1 -1
- emdash_cli/commands/agent.py +19 -0
- emdash_cli/commands/index.py +76 -8
- emdash_cli/sse_renderer.py +137 -44
- {emdash_cli-0.1.4.dist-info → emdash_cli-0.1.17.dist-info}/METADATA +2 -2
- {emdash_cli-0.1.4.dist-info → emdash_cli-0.1.17.dist-info}/RECORD +9 -9
- {emdash_cli-0.1.4.dist-info → emdash_cli-0.1.17.dist-info}/WHEEL +0 -0
- {emdash_cli-0.1.4.dist-info → emdash_cli-0.1.17.dist-info}/entry_points.txt +0 -0
emdash_cli/__init__.py
CHANGED
emdash_cli/client.py
CHANGED
emdash_cli/commands/agent.py
CHANGED
|
@@ -459,6 +459,7 @@ def _run_interactive(
|
|
|
459
459
|
from prompt_toolkit.history import FileHistory
|
|
460
460
|
from prompt_toolkit.completion import Completer, Completion
|
|
461
461
|
from prompt_toolkit.styles import Style
|
|
462
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
462
463
|
from pathlib import Path
|
|
463
464
|
|
|
464
465
|
# Current mode
|
|
@@ -503,11 +504,29 @@ def _run_interactive(
|
|
|
503
504
|
history_file.parent.mkdir(parents=True, exist_ok=True)
|
|
504
505
|
history = FileHistory(str(history_file))
|
|
505
506
|
|
|
507
|
+
# Key bindings: Enter submits, Alt+Enter inserts newline
|
|
508
|
+
# Note: Shift+Enter is indistinguishable from Enter in most terminals
|
|
509
|
+
kb = KeyBindings()
|
|
510
|
+
|
|
511
|
+
@kb.add("enter")
|
|
512
|
+
def submit_on_enter(event):
|
|
513
|
+
"""Submit on Enter."""
|
|
514
|
+
event.current_buffer.validate_and_handle()
|
|
515
|
+
|
|
516
|
+
@kb.add("escape", "enter") # Alt+Enter (Escape then Enter)
|
|
517
|
+
@kb.add("c-j") # Ctrl+J as alternative for newline
|
|
518
|
+
def insert_newline_alt(event):
|
|
519
|
+
"""Insert a newline character with Alt+Enter or Ctrl+J."""
|
|
520
|
+
event.current_buffer.insert_text("\n")
|
|
521
|
+
|
|
506
522
|
session = PromptSession(
|
|
507
523
|
history=history,
|
|
508
524
|
completer=SlashCommandCompleter(),
|
|
509
525
|
style=PROMPT_STYLE,
|
|
510
526
|
complete_while_typing=True,
|
|
527
|
+
multiline=True,
|
|
528
|
+
prompt_continuation="... ",
|
|
529
|
+
key_bindings=kb,
|
|
511
530
|
)
|
|
512
531
|
|
|
513
532
|
def get_prompt():
|
emdash_cli/commands/index.py
CHANGED
|
@@ -5,7 +5,9 @@ import os
|
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
from rich.console import Console
|
|
8
|
-
from rich.
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn
|
|
10
|
+
from rich.table import Table
|
|
9
11
|
|
|
10
12
|
from ..client import EmdashClient
|
|
11
13
|
from ..server_manager import get_server_manager
|
|
@@ -68,30 +70,96 @@ def index_start(
|
|
|
68
70
|
options["model"] = model
|
|
69
71
|
|
|
70
72
|
try:
|
|
71
|
-
# Stream indexing progress with
|
|
72
|
-
|
|
73
|
+
# Stream indexing progress with progress bar
|
|
74
|
+
final_stats = {}
|
|
75
|
+
|
|
76
|
+
with Progress(
|
|
77
|
+
TextColumn("[bold cyan]{task.description}[/bold cyan]"),
|
|
78
|
+
BarColumn(bar_width=40, complete_style="cyan", finished_style="green"),
|
|
79
|
+
TaskProgressColumn(),
|
|
80
|
+
console=console,
|
|
81
|
+
transient=True,
|
|
82
|
+
) as progress:
|
|
83
|
+
task = progress.add_task("Starting...", total=100)
|
|
84
|
+
|
|
73
85
|
for line in client.index_start_stream(repo_path, changed_only):
|
|
74
86
|
line = line.strip()
|
|
87
|
+
if line.startswith("event: "):
|
|
88
|
+
continue
|
|
75
89
|
if line.startswith("data: "):
|
|
76
90
|
try:
|
|
77
91
|
data = json.loads(line[6:])
|
|
78
92
|
step = data.get("step") or data.get("message", "")
|
|
79
93
|
percent = data.get("percent")
|
|
94
|
+
|
|
95
|
+
# Capture final stats from response event
|
|
96
|
+
if data.get("success") and data.get("stats"):
|
|
97
|
+
final_stats = data.get("stats", {})
|
|
98
|
+
|
|
80
99
|
if step:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
status.update(f"[bold cyan]{step}[/bold cyan]")
|
|
100
|
+
progress.update(task, description=step)
|
|
101
|
+
if percent is not None:
|
|
102
|
+
progress.update(task, completed=percent)
|
|
85
103
|
except json.JSONDecodeError:
|
|
86
104
|
pass
|
|
87
105
|
|
|
88
|
-
|
|
106
|
+
# Complete the progress bar
|
|
107
|
+
progress.update(task, completed=100, description="Complete")
|
|
108
|
+
|
|
109
|
+
# Show completion with sense of accomplishment
|
|
110
|
+
_show_completion(repo_path, final_stats, client)
|
|
89
111
|
|
|
90
112
|
except Exception as e:
|
|
91
113
|
console.print(f"\n[red]Error:[/red] {e}")
|
|
92
114
|
raise click.Abort()
|
|
93
115
|
|
|
94
116
|
|
|
117
|
+
def _show_completion(repo_path: str, stats: dict, client: EmdashClient) -> None:
|
|
118
|
+
"""Show a nice completion message with stats."""
|
|
119
|
+
# If we don't have stats from the stream, fetch from status endpoint
|
|
120
|
+
if not stats:
|
|
121
|
+
try:
|
|
122
|
+
status_data = client.index_status(repo_path)
|
|
123
|
+
stats = {
|
|
124
|
+
"files": status_data.get("file_count", 0),
|
|
125
|
+
"functions": status_data.get("function_count", 0),
|
|
126
|
+
"classes": status_data.get("class_count", 0),
|
|
127
|
+
"communities": status_data.get("community_count", 0),
|
|
128
|
+
}
|
|
129
|
+
except Exception:
|
|
130
|
+
stats = {}
|
|
131
|
+
|
|
132
|
+
# Build completion message
|
|
133
|
+
console.print()
|
|
134
|
+
|
|
135
|
+
if stats:
|
|
136
|
+
# Create a summary table
|
|
137
|
+
table = Table(show_header=False, box=None, padding=(0, 2))
|
|
138
|
+
table.add_column("Label", style="dim")
|
|
139
|
+
table.add_column("Value", style="bold")
|
|
140
|
+
|
|
141
|
+
if stats.get("files"):
|
|
142
|
+
table.add_row("Files", str(stats["files"]))
|
|
143
|
+
if stats.get("functions"):
|
|
144
|
+
table.add_row("Functions", str(stats["functions"]))
|
|
145
|
+
if stats.get("classes"):
|
|
146
|
+
table.add_row("Classes", str(stats["classes"]))
|
|
147
|
+
if stats.get("communities"):
|
|
148
|
+
table.add_row("Communities", str(stats["communities"]))
|
|
149
|
+
|
|
150
|
+
panel = Panel(
|
|
151
|
+
table,
|
|
152
|
+
title="[bold green]Indexing Complete[/bold green]",
|
|
153
|
+
border_style="green",
|
|
154
|
+
padding=(1, 2),
|
|
155
|
+
)
|
|
156
|
+
console.print(panel)
|
|
157
|
+
else:
|
|
158
|
+
console.print("[bold green]Indexing complete![/bold green]")
|
|
159
|
+
|
|
160
|
+
console.print()
|
|
161
|
+
|
|
162
|
+
|
|
95
163
|
@index.command("status")
|
|
96
164
|
@click.argument("repo_path", required=False)
|
|
97
165
|
def index_status(repo_path: str | None):
|
emdash_cli/sse_renderer.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import sys
|
|
5
5
|
import time
|
|
6
|
+
import threading
|
|
6
7
|
from typing import Iterator, Optional
|
|
7
8
|
|
|
8
9
|
from rich.console import Console
|
|
@@ -54,6 +55,12 @@ class SSERenderer:
|
|
|
54
55
|
self._subagent_tool_count = 0
|
|
55
56
|
self._subagent_current_tool = None
|
|
56
57
|
|
|
58
|
+
# Spinner animation thread
|
|
59
|
+
self._spinner_thread: Optional[threading.Thread] = None
|
|
60
|
+
self._spinner_running = False
|
|
61
|
+
self._spinner_message = "thinking"
|
|
62
|
+
self._spinner_lock = threading.Lock()
|
|
63
|
+
|
|
57
64
|
def render_stream(self, lines: Iterator[str]) -> dict:
|
|
58
65
|
"""Render SSE stream to terminal.
|
|
59
66
|
|
|
@@ -66,27 +73,35 @@ class SSERenderer:
|
|
|
66
73
|
current_event = None
|
|
67
74
|
final_response = ""
|
|
68
75
|
|
|
69
|
-
for
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
76
|
+
# Start spinner while waiting for first event
|
|
77
|
+
if self.verbose:
|
|
78
|
+
self._start_spinner("thinking")
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
for line in lines:
|
|
82
|
+
line = line.strip()
|
|
83
|
+
|
|
84
|
+
if line.startswith("event: "):
|
|
85
|
+
current_event = line[7:]
|
|
86
|
+
elif line.startswith("data: "):
|
|
87
|
+
try:
|
|
88
|
+
data = json.loads(line[6:])
|
|
89
|
+
# Ensure data is a dict (could be null/None from JSON)
|
|
90
|
+
if data is None:
|
|
91
|
+
data = {}
|
|
92
|
+
if current_event:
|
|
93
|
+
result = self._handle_event(current_event, data)
|
|
94
|
+
if result:
|
|
95
|
+
final_response = result
|
|
96
|
+
except json.JSONDecodeError:
|
|
97
|
+
pass
|
|
98
|
+
elif line == ": ping":
|
|
99
|
+
# SSE keep-alive - ensure spinner is running
|
|
100
|
+
if self.verbose and not self._spinner_running:
|
|
101
|
+
self._start_spinner("waiting")
|
|
102
|
+
finally:
|
|
103
|
+
# Always stop spinner when stream ends
|
|
104
|
+
self._stop_spinner()
|
|
90
105
|
|
|
91
106
|
return {
|
|
92
107
|
"content": final_response,
|
|
@@ -96,20 +111,50 @@ class SSERenderer:
|
|
|
96
111
|
"clarification": self._pending_clarification,
|
|
97
112
|
}
|
|
98
113
|
|
|
114
|
+
def _start_spinner(self, message: str = "thinking") -> None:
|
|
115
|
+
"""Start the animated spinner in a background thread."""
|
|
116
|
+
if self._spinner_running:
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
self._spinner_message = message
|
|
120
|
+
self._spinner_running = True
|
|
121
|
+
self._spinner_thread = threading.Thread(target=self._spinner_loop, daemon=True)
|
|
122
|
+
self._spinner_thread.start()
|
|
123
|
+
|
|
124
|
+
def _stop_spinner(self) -> None:
|
|
125
|
+
"""Stop the spinner and clear the line."""
|
|
126
|
+
if not self._spinner_running:
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
self._spinner_running = False
|
|
130
|
+
if self._spinner_thread:
|
|
131
|
+
self._spinner_thread.join(timeout=0.2)
|
|
132
|
+
self._spinner_thread = None
|
|
133
|
+
|
|
134
|
+
# Clear the spinner line
|
|
135
|
+
with self._spinner_lock:
|
|
136
|
+
sys.stdout.write("\r" + " " * 60 + "\r")
|
|
137
|
+
sys.stdout.flush()
|
|
138
|
+
|
|
139
|
+
def _spinner_loop(self) -> None:
|
|
140
|
+
"""Background thread that animates the spinner."""
|
|
141
|
+
while self._spinner_running:
|
|
142
|
+
with self._spinner_lock:
|
|
143
|
+
self._spinner_idx = (self._spinner_idx + 1) % len(SPINNER_FRAMES)
|
|
144
|
+
spinner = SPINNER_FRAMES[self._spinner_idx]
|
|
145
|
+
sys.stdout.write(f"\r \033[33m{spinner}\033[0m \033[2m{self._spinner_message}...\033[0m")
|
|
146
|
+
sys.stdout.flush()
|
|
147
|
+
time.sleep(0.1)
|
|
148
|
+
|
|
99
149
|
def _show_waiting(self) -> None:
|
|
100
|
-
"""Show waiting animation."""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
# Use carriage return to update in place
|
|
104
|
-
sys.stdout.write(f"\r [dim]{spinner}[/dim] waiting...")
|
|
105
|
-
sys.stdout.flush()
|
|
150
|
+
"""Show waiting animation (starts spinner if not running)."""
|
|
151
|
+
if not self._spinner_running:
|
|
152
|
+
self._start_spinner("waiting")
|
|
106
153
|
|
|
107
154
|
def _clear_waiting(self) -> None:
|
|
108
|
-
"""Clear waiting line."""
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
sys.stdout.flush()
|
|
112
|
-
self._waiting_for_next = False
|
|
155
|
+
"""Clear waiting line (stops spinner)."""
|
|
156
|
+
self._stop_spinner()
|
|
157
|
+
self._waiting_for_next = False
|
|
113
158
|
|
|
114
159
|
def _handle_event(self, event_type: str, data: dict) -> Optional[str]:
|
|
115
160
|
"""Handle individual SSE event."""
|
|
@@ -126,8 +171,10 @@ class SSERenderer:
|
|
|
126
171
|
self._render_tool_start(data)
|
|
127
172
|
elif event_type == "tool_result":
|
|
128
173
|
self._render_tool_result(data)
|
|
129
|
-
#
|
|
174
|
+
# Start spinner while waiting for next tool/response
|
|
130
175
|
self._waiting_for_next = True
|
|
176
|
+
if self.verbose:
|
|
177
|
+
self._start_spinner("thinking")
|
|
131
178
|
elif event_type == "thinking":
|
|
132
179
|
self._render_thinking(data)
|
|
133
180
|
elif event_type == "progress":
|
|
@@ -144,6 +191,8 @@ class SSERenderer:
|
|
|
144
191
|
self._render_warning(data)
|
|
145
192
|
elif event_type == "session_end":
|
|
146
193
|
self._render_session_end(data)
|
|
194
|
+
elif event_type == "context_frame":
|
|
195
|
+
self._render_context_frame(data)
|
|
147
196
|
|
|
148
197
|
return None
|
|
149
198
|
|
|
@@ -231,6 +280,10 @@ class SSERenderer:
|
|
|
231
280
|
description = args.get("description", "")
|
|
232
281
|
prompt = args.get("prompt", "")
|
|
233
282
|
|
|
283
|
+
# Reset sub-agent tracking
|
|
284
|
+
self._subagent_tool_count = 0
|
|
285
|
+
self._subagent_current_tool = None
|
|
286
|
+
|
|
234
287
|
# Truncate prompt for display
|
|
235
288
|
prompt_display = prompt[:60] + "..." if len(prompt) > 60 else prompt
|
|
236
289
|
|
|
@@ -304,6 +357,10 @@ class SSERenderer:
|
|
|
304
357
|
success = data.get("success", True)
|
|
305
358
|
result_data = data.get("data") or {}
|
|
306
359
|
|
|
360
|
+
# Clear the progress line
|
|
361
|
+
sys.stdout.write(f"\r{' ' * 120}\r")
|
|
362
|
+
sys.stdout.flush()
|
|
363
|
+
|
|
307
364
|
# Calculate duration
|
|
308
365
|
duration = ""
|
|
309
366
|
if self._current_tool and self._current_tool.get("start_time"):
|
|
@@ -313,20 +370,20 @@ class SSERenderer:
|
|
|
313
370
|
if success:
|
|
314
371
|
agent_type = result_data.get("agent_type", "Agent")
|
|
315
372
|
iterations = result_data.get("iterations", 0)
|
|
316
|
-
tools_used = result_data.get("tools_used", [])
|
|
317
373
|
files_count = len(result_data.get("files_explored", []))
|
|
318
374
|
|
|
319
375
|
self.console.print(
|
|
320
376
|
f" [green]✓[/green] {agent_type} completed{duration}"
|
|
321
377
|
)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
378
|
+
# Show stats using our tracked tool count
|
|
379
|
+
stats = []
|
|
380
|
+
if iterations > 0:
|
|
381
|
+
stats.append(f"{iterations} turns")
|
|
382
|
+
if files_count > 0:
|
|
383
|
+
stats.append(f"{files_count} files")
|
|
384
|
+
if self._subagent_tool_count > 0:
|
|
385
|
+
stats.append(f"{self._subagent_tool_count} tools")
|
|
386
|
+
if stats:
|
|
330
387
|
self.console.print(f" [dim]{' · '.join(stats)}[/dim]")
|
|
331
388
|
else:
|
|
332
389
|
error = result_data.get("error", data.get("summary", "failed"))
|
|
@@ -334,6 +391,7 @@ class SSERenderer:
|
|
|
334
391
|
|
|
335
392
|
self.console.print()
|
|
336
393
|
self._current_tool = None
|
|
394
|
+
self._subagent_tool_count = 0
|
|
337
395
|
|
|
338
396
|
def _format_args_summary(self, args: dict) -> str:
|
|
339
397
|
"""Format args into a compact summary string."""
|
|
@@ -438,5 +496,40 @@ class SSERenderer:
|
|
|
438
496
|
if not success:
|
|
439
497
|
error = data.get("error", "Unknown error")
|
|
440
498
|
self.console.print(f"\n[red]Session ended with error: {error}[/red]")
|
|
441
|
-
|
|
442
|
-
|
|
499
|
+
|
|
500
|
+
def _render_context_frame(self, data: dict) -> None:
|
|
501
|
+
"""Render context frame update (post-agentic loop summary)."""
|
|
502
|
+
if not self.verbose:
|
|
503
|
+
return
|
|
504
|
+
|
|
505
|
+
adding = data.get("adding") or {}
|
|
506
|
+
reading = data.get("reading") or {}
|
|
507
|
+
|
|
508
|
+
# Get stats from the adding data
|
|
509
|
+
step_count = adding.get("step_count", 0)
|
|
510
|
+
entities_found = adding.get("entities_found", 0)
|
|
511
|
+
context_tokens = adding.get("context_tokens", 0)
|
|
512
|
+
|
|
513
|
+
# Get reading stats
|
|
514
|
+
item_count = reading.get("item_count", 0)
|
|
515
|
+
|
|
516
|
+
# Only show if there's something to report
|
|
517
|
+
if step_count == 0 and item_count == 0:
|
|
518
|
+
return
|
|
519
|
+
|
|
520
|
+
self.console.print()
|
|
521
|
+
self.console.print("[dim]───── Context Frame ─────[/dim]")
|
|
522
|
+
|
|
523
|
+
# Show stats line
|
|
524
|
+
stats = []
|
|
525
|
+
if step_count > 0:
|
|
526
|
+
stats.append(f"{step_count} steps")
|
|
527
|
+
if entities_found > 0:
|
|
528
|
+
stats.append(f"{entities_found} entities")
|
|
529
|
+
if item_count > 0:
|
|
530
|
+
stats.append(f"{item_count} context items")
|
|
531
|
+
if context_tokens > 0:
|
|
532
|
+
stats.append(f"{context_tokens:,} context tokens")
|
|
533
|
+
|
|
534
|
+
if stats:
|
|
535
|
+
self.console.print(f" [dim]{' · '.join(stats)}[/dim]")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emdash-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.17
|
|
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
|
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
13
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
14
|
-
Requires-Dist: emdash-core (>=0.1.
|
|
14
|
+
Requires-Dist: emdash-core (>=0.1.17)
|
|
15
15
|
Requires-Dist: httpx (>=0.25.0)
|
|
16
16
|
Requires-Dist: prompt_toolkit (>=3.0.43,<4.0.0)
|
|
17
17
|
Requires-Dist: rich (>=13.7.0)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
emdash_cli/__init__.py,sha256=
|
|
2
|
-
emdash_cli/client.py,sha256=
|
|
1
|
+
emdash_cli/__init__.py,sha256=Rnn2O7B8OCEKlVtNRbWOU2-GN75_KLmhEJgOZzY-KwE,232
|
|
2
|
+
emdash_cli/client.py,sha256=1Ri-BpZPfnZuXRhN8sCLna2SRhhr_AVDC_0CeTQPOhM,16275
|
|
3
3
|
emdash_cli/commands/__init__.py,sha256=zf0lQ6S1UgoIg6NS7Oehxnb3iGD0Wxai0QU1nobgi9U,671
|
|
4
|
-
emdash_cli/commands/agent.py,sha256=
|
|
4
|
+
emdash_cli/commands/agent.py,sha256=aYN9nLL30ETJKewo42d8U7QY9DGqCMTHCpIPiqJGlLA,30323
|
|
5
5
|
emdash_cli/commands/analyze.py,sha256=c9ztbv0Ra7g2AlDmMOy-9L51fDVuoqbuzxnRfomoFIQ,4403
|
|
6
6
|
emdash_cli/commands/auth.py,sha256=SpWdqO1bJCgt4x1B4Pr7hNOucwTuBFJ1oGPOzXtvwZM,3816
|
|
7
7
|
emdash_cli/commands/db.py,sha256=nZK7gLDVE2lAQVYrMx6Swscml5OAtkbg-EcSNSvRIlA,2922
|
|
8
8
|
emdash_cli/commands/embed.py,sha256=kqP5jtYCsZ2_s_I1DjzIUgaod1VUvPiRO0jIIY0HtCs,3244
|
|
9
|
-
emdash_cli/commands/index.py,sha256=
|
|
9
|
+
emdash_cli/commands/index.py,sha256=uFNC5whhU9JdF_59FeM99OPdzKLBTJLkLO6vp9pt944,6959
|
|
10
10
|
emdash_cli/commands/plan.py,sha256=BRiyIhfy_zz2PYy4Qo3a0t77GwHhdssZk6NImOkPi-w,2189
|
|
11
11
|
emdash_cli/commands/projectmd.py,sha256=4y4cn_yFw85jMUm52nGjpqnd-YWvs6ZNEMWJGeJC17Q,1605
|
|
12
12
|
emdash_cli/commands/research.py,sha256=xtI9_9emY7-rGQD5xJALTxtgTFmI4dplYW148dtTaTs,1553
|
|
@@ -19,8 +19,8 @@ emdash_cli/commands/tasks.py,sha256=TdyunjSV5w7jpNFwv0fTL-_No5Fyvdm7Z2nXqxWSJec,
|
|
|
19
19
|
emdash_cli/commands/team.py,sha256=K1-IJg6iG-9HMF_3JmpNDlNs1PYbb-ThFHU9KU_jKRo,1430
|
|
20
20
|
emdash_cli/main.py,sha256=pxUzyh01R-FDETMRf8nrBvP9QW3DVgeTJZ1Vsradw-E,2502
|
|
21
21
|
emdash_cli/server_manager.py,sha256=RrLteSHUmcFV4cyHJAEmgM9qHru2mJS08QNLWno6Y3Y,7051
|
|
22
|
-
emdash_cli/sse_renderer.py,sha256=
|
|
23
|
-
emdash_cli-0.1.
|
|
24
|
-
emdash_cli-0.1.
|
|
25
|
-
emdash_cli-0.1.
|
|
26
|
-
emdash_cli-0.1.
|
|
22
|
+
emdash_cli/sse_renderer.py,sha256=55lDLzYngrWmXstb7PNpQcWi2G4u47qWaYqRJjqMUYo,18587
|
|
23
|
+
emdash_cli-0.1.17.dist-info/METADATA,sha256=u7puOJ_vO_Nc_RU7RSCsQOoXV2rSTCd3zEfwpueg3o0,662
|
|
24
|
+
emdash_cli-0.1.17.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
25
|
+
emdash_cli-0.1.17.dist-info/entry_points.txt,sha256=31CuYD0k-tM8csFWDunc-JoZTxXaifj3oIXz4V0p6F0,122
|
|
26
|
+
emdash_cli-0.1.17.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|