emdash-cli 0.1.46__py3-none-any.whl → 0.1.70__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 +12 -28
- emdash_cli/commands/__init__.py +2 -2
- emdash_cli/commands/agent/constants.py +78 -0
- emdash_cli/commands/agent/handlers/__init__.py +10 -0
- emdash_cli/commands/agent/handlers/agents.py +67 -39
- emdash_cli/commands/agent/handlers/index.py +183 -0
- emdash_cli/commands/agent/handlers/misc.py +119 -0
- emdash_cli/commands/agent/handlers/registry.py +72 -0
- emdash_cli/commands/agent/handlers/rules.py +48 -31
- emdash_cli/commands/agent/handlers/sessions.py +1 -1
- emdash_cli/commands/agent/handlers/setup.py +187 -54
- emdash_cli/commands/agent/handlers/skills.py +42 -4
- emdash_cli/commands/agent/handlers/telegram.py +523 -0
- emdash_cli/commands/agent/handlers/todos.py +55 -34
- emdash_cli/commands/agent/handlers/verify.py +10 -5
- emdash_cli/commands/agent/help.py +236 -0
- emdash_cli/commands/agent/interactive.py +278 -47
- emdash_cli/commands/agent/menus.py +116 -84
- emdash_cli/commands/agent/onboarding.py +619 -0
- emdash_cli/commands/agent/session_restore.py +210 -0
- emdash_cli/commands/index.py +111 -13
- emdash_cli/commands/registry.py +635 -0
- emdash_cli/commands/skills.py +72 -6
- emdash_cli/design.py +328 -0
- emdash_cli/diff_renderer.py +438 -0
- emdash_cli/integrations/__init__.py +1 -0
- emdash_cli/integrations/telegram/__init__.py +15 -0
- emdash_cli/integrations/telegram/bot.py +402 -0
- emdash_cli/integrations/telegram/bridge.py +980 -0
- emdash_cli/integrations/telegram/config.py +155 -0
- emdash_cli/integrations/telegram/formatter.py +392 -0
- emdash_cli/main.py +52 -2
- emdash_cli/sse_renderer.py +632 -171
- {emdash_cli-0.1.46.dist-info → emdash_cli-0.1.70.dist-info}/METADATA +2 -2
- emdash_cli-0.1.70.dist-info/RECORD +63 -0
- emdash_cli/commands/swarm.py +0 -86
- emdash_cli-0.1.46.dist-info/RECORD +0 -49
- {emdash_cli-0.1.46.dist-info → emdash_cli-0.1.70.dist-info}/WHEEL +0 -0
- {emdash_cli-0.1.46.dist-info → emdash_cli-0.1.70.dist-info}/entry_points.txt +0 -0
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
"""Interactive menus for the agent CLI.
|
|
2
2
|
|
|
3
|
-
Contains all prompt_toolkit-based interactive menus.
|
|
3
|
+
Contains all prompt_toolkit-based interactive menus with zen design language.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
|
|
10
|
+
from ...design import (
|
|
11
|
+
Colors,
|
|
12
|
+
STATUS_ACTIVE,
|
|
13
|
+
STATUS_INACTIVE,
|
|
14
|
+
STATUS_ERROR,
|
|
15
|
+
DOT_BULLET,
|
|
16
|
+
ARROW_PROMPT,
|
|
17
|
+
header,
|
|
18
|
+
footer,
|
|
19
|
+
menu_hint,
|
|
20
|
+
)
|
|
21
|
+
|
|
10
22
|
console = Console()
|
|
11
23
|
|
|
12
24
|
|
|
@@ -77,17 +89,19 @@ def get_clarification_response(clarification: dict) -> str | None:
|
|
|
77
89
|
lines = []
|
|
78
90
|
for i, opt in enumerate(options):
|
|
79
91
|
if i == selected_index[0]:
|
|
80
|
-
lines.append(("class:selected", f"
|
|
92
|
+
lines.append(("class:selected", f" {STATUS_ACTIVE} "))
|
|
93
|
+
lines.append(("class:selected", f"{i+1}. {opt}\n"))
|
|
81
94
|
else:
|
|
82
|
-
lines.append(("class:option", f"
|
|
83
|
-
|
|
95
|
+
lines.append(("class:option", f" {STATUS_INACTIVE} "))
|
|
96
|
+
lines.append(("class:option", f"{i+1}. {opt}\n"))
|
|
97
|
+
lines.append(("class:hint", f"\n{ARROW_PROMPT} ↑↓ move Enter select 1-9 quick o other"))
|
|
84
98
|
return lines
|
|
85
99
|
|
|
86
|
-
# Style
|
|
100
|
+
# Style (zen palette)
|
|
87
101
|
style = Style.from_dict({
|
|
88
|
-
"selected": "
|
|
89
|
-
"option":
|
|
90
|
-
"hint": "
|
|
102
|
+
"selected": f"{Colors.SUCCESS} bold",
|
|
103
|
+
"option": Colors.MUTED,
|
|
104
|
+
"hint": f"{Colors.DIM} italic",
|
|
91
105
|
})
|
|
92
106
|
|
|
93
107
|
# Calculate height based on options
|
|
@@ -213,22 +227,22 @@ def show_plan_approval_menu() -> tuple[str, str]:
|
|
|
213
227
|
lines = [("class:title", "Approve this plan?\n\n")]
|
|
214
228
|
for i, (key, desc) in enumerate(options):
|
|
215
229
|
if i == selected_index[0]:
|
|
216
|
-
lines.append(("class:selected", f"
|
|
217
|
-
lines.append(("class:selected-desc", f"
|
|
230
|
+
lines.append(("class:selected", f" {STATUS_ACTIVE} {key}\n"))
|
|
231
|
+
lines.append(("class:selected-desc", f" {desc}\n"))
|
|
218
232
|
else:
|
|
219
|
-
lines.append(("class:option", f"
|
|
220
|
-
lines.append(("class:desc", f"
|
|
221
|
-
lines.append(("class:hint", "\n
|
|
233
|
+
lines.append(("class:option", f" {STATUS_INACTIVE} {key}\n"))
|
|
234
|
+
lines.append(("class:desc", f" {desc}\n"))
|
|
235
|
+
lines.append(("class:hint", f"\n{ARROW_PROMPT} y approve n feedback Esc cancel"))
|
|
222
236
|
return lines
|
|
223
237
|
|
|
224
|
-
# Style
|
|
238
|
+
# Style (zen palette)
|
|
225
239
|
style = Style.from_dict({
|
|
226
|
-
"title": "
|
|
227
|
-
"selected": "
|
|
228
|
-
"selected-desc":
|
|
229
|
-
"option":
|
|
230
|
-
"desc":
|
|
231
|
-
"hint": "
|
|
240
|
+
"title": f"{Colors.PRIMARY} bold",
|
|
241
|
+
"selected": f"{Colors.SUCCESS} bold",
|
|
242
|
+
"selected-desc": Colors.SUCCESS,
|
|
243
|
+
"option": Colors.MUTED,
|
|
244
|
+
"desc": Colors.DIM,
|
|
245
|
+
"hint": f"{Colors.DIM} italic",
|
|
232
246
|
})
|
|
233
247
|
|
|
234
248
|
# Layout
|
|
@@ -369,45 +383,46 @@ def show_agents_interactive_menu() -> tuple[str, str]:
|
|
|
369
383
|
|
|
370
384
|
for i, (name, desc, is_builtin, is_action) in enumerate(menu_items):
|
|
371
385
|
is_selected = i == selected_index[0]
|
|
372
|
-
|
|
386
|
+
indicator = STATUS_ACTIVE if is_selected else STATUS_INACTIVE
|
|
373
387
|
|
|
374
388
|
if is_action:
|
|
375
389
|
# Action item (like Create New)
|
|
376
390
|
if is_selected:
|
|
377
|
-
lines.append(("class:action-selected", f"{
|
|
391
|
+
lines.append(("class:action-selected", f" {indicator} {name}\n"))
|
|
378
392
|
else:
|
|
379
|
-
lines.append(("class:action", f"{
|
|
393
|
+
lines.append(("class:action", f" {indicator} {name}\n"))
|
|
380
394
|
elif is_builtin:
|
|
381
395
|
# Built-in agent
|
|
382
396
|
if is_selected:
|
|
383
|
-
lines.append(("class:builtin-selected", f"{
|
|
384
|
-
lines.append(("class:desc-selected", f"
|
|
397
|
+
lines.append(("class:builtin-selected", f" {indicator} {name}\n"))
|
|
398
|
+
lines.append(("class:desc-selected", f" {desc}\n"))
|
|
385
399
|
else:
|
|
386
|
-
lines.append(("class:builtin", f"{
|
|
387
|
-
lines.append(("class:desc", f"
|
|
400
|
+
lines.append(("class:builtin", f" {indicator} {name}\n"))
|
|
401
|
+
lines.append(("class:desc", f" {desc}\n"))
|
|
388
402
|
else:
|
|
389
403
|
# Custom agent
|
|
390
404
|
if is_selected:
|
|
391
|
-
lines.append(("class:custom-selected", f"{
|
|
392
|
-
lines.append(("class:desc-selected", f"
|
|
405
|
+
lines.append(("class:custom-selected", f" {indicator} {name}\n"))
|
|
406
|
+
lines.append(("class:desc-selected", f" {desc}\n"))
|
|
393
407
|
else:
|
|
394
|
-
lines.append(("class:custom", f"{
|
|
395
|
-
lines.append(("class:desc", f"
|
|
408
|
+
lines.append(("class:custom", f" {indicator} {name}\n"))
|
|
409
|
+
lines.append(("class:desc", f" {desc}\n"))
|
|
396
410
|
|
|
397
|
-
lines.append(("class:hint", "\n
|
|
411
|
+
lines.append(("class:hint", f"\n{ARROW_PROMPT} ↑↓ navigate Enter view n new e edit d delete q quit"))
|
|
398
412
|
return lines
|
|
399
413
|
|
|
414
|
+
# Style (zen palette)
|
|
400
415
|
style = Style.from_dict({
|
|
401
|
-
"title": "
|
|
402
|
-
"builtin":
|
|
403
|
-
"builtin-selected": "
|
|
404
|
-
"custom":
|
|
405
|
-
"custom-selected": "
|
|
406
|
-
"action":
|
|
407
|
-
"action-selected": "
|
|
408
|
-
"desc":
|
|
409
|
-
"desc-selected":
|
|
410
|
-
"hint": "
|
|
416
|
+
"title": f"{Colors.PRIMARY} bold",
|
|
417
|
+
"builtin": Colors.MUTED,
|
|
418
|
+
"builtin-selected": f"{Colors.SUCCESS} bold",
|
|
419
|
+
"custom": Colors.PRIMARY,
|
|
420
|
+
"custom-selected": f"{Colors.SUCCESS} bold",
|
|
421
|
+
"action": Colors.WARNING,
|
|
422
|
+
"action-selected": f"{Colors.WARNING} bold",
|
|
423
|
+
"desc": Colors.DIM,
|
|
424
|
+
"desc-selected": Colors.SUCCESS,
|
|
425
|
+
"hint": f"{Colors.DIM} italic",
|
|
411
426
|
})
|
|
412
427
|
|
|
413
428
|
height = len(menu_items) + 4 # items + title + hint + padding
|
|
@@ -439,33 +454,42 @@ def show_agents_interactive_menu() -> tuple[str, str]:
|
|
|
439
454
|
|
|
440
455
|
|
|
441
456
|
def prompt_agent_name() -> str:
|
|
442
|
-
"""Prompt user for new agent name."""
|
|
457
|
+
"""Prompt user for new agent name with zen styling."""
|
|
443
458
|
from prompt_toolkit import PromptSession
|
|
444
459
|
|
|
445
460
|
console.print()
|
|
446
|
-
console.print("[
|
|
447
|
-
console.print(
|
|
461
|
+
console.print(f"[{Colors.MUTED}]{header('Create Agent', 35)}[/{Colors.MUTED}]")
|
|
462
|
+
console.print()
|
|
463
|
+
console.print(f" [{Colors.DIM}]Enter a name for your agent[/{Colors.DIM}]")
|
|
464
|
+
console.print(f" [{Colors.DIM}](e.g., code-reviewer, bug-finder)[/{Colors.DIM}]")
|
|
465
|
+
console.print()
|
|
448
466
|
|
|
449
467
|
try:
|
|
450
468
|
session = PromptSession()
|
|
451
|
-
name = session.prompt("
|
|
469
|
+
name = session.prompt(f" {ARROW_PROMPT} ").strip()
|
|
452
470
|
return name.lower().replace(" ", "-") if name else ""
|
|
453
471
|
except (KeyboardInterrupt, EOFError):
|
|
454
472
|
return ""
|
|
455
473
|
|
|
456
474
|
|
|
457
475
|
def confirm_delete(agent_name: str) -> bool:
|
|
458
|
-
"""Confirm agent deletion."""
|
|
476
|
+
"""Confirm agent deletion with zen styling."""
|
|
459
477
|
from prompt_toolkit import PromptSession
|
|
460
478
|
|
|
461
479
|
console.print()
|
|
462
|
-
console.print(f"[
|
|
463
|
-
console.print(
|
|
480
|
+
console.print(f"[{Colors.MUTED}]{header('Delete Agent', 35)}[/{Colors.MUTED}]")
|
|
481
|
+
console.print()
|
|
482
|
+
console.print(f" [{Colors.ERROR}]{STATUS_ERROR}[/{Colors.ERROR}] This will permanently delete:")
|
|
483
|
+
console.print()
|
|
484
|
+
console.print(f" [{Colors.WARNING}]{agent_name}[/{Colors.WARNING}]")
|
|
485
|
+
console.print()
|
|
486
|
+
console.print(f" [{Colors.DIM}]Type 'delete' to confirm[/{Colors.DIM}]")
|
|
487
|
+
console.print()
|
|
464
488
|
|
|
465
489
|
try:
|
|
466
490
|
session = PromptSession()
|
|
467
|
-
response = session.prompt("
|
|
468
|
-
return response
|
|
491
|
+
response = session.prompt(f" {ARROW_PROMPT} ").strip().lower()
|
|
492
|
+
return response == "delete"
|
|
469
493
|
except (KeyboardInterrupt, EOFError):
|
|
470
494
|
return False
|
|
471
495
|
|
|
@@ -536,38 +560,39 @@ def show_sessions_interactive_menu(sessions: list, active_session: str | None) -
|
|
|
536
560
|
|
|
537
561
|
for i, (name, summary, mode, msg_count, updated, is_active) in enumerate(menu_items):
|
|
538
562
|
is_selected = i == selected_index[0]
|
|
539
|
-
|
|
540
|
-
active_marker = "
|
|
563
|
+
indicator = STATUS_ACTIVE if is_selected else STATUS_INACTIVE
|
|
564
|
+
active_marker = f" {DOT_BULLET}" if is_active else ""
|
|
541
565
|
|
|
542
566
|
if is_selected:
|
|
543
|
-
lines.append(("class:name-selected", f"{
|
|
567
|
+
lines.append(("class:name-selected", f" {indicator} {name}{active_marker}"))
|
|
544
568
|
lines.append(("class:mode-selected", f" [{mode}]"))
|
|
545
569
|
lines.append(("class:info-selected", f" {msg_count} msgs\n"))
|
|
546
570
|
if summary:
|
|
547
571
|
truncated = summary[:50] + "..." if len(summary) > 50 else summary
|
|
548
|
-
lines.append(("class:summary-selected", f"
|
|
572
|
+
lines.append(("class:summary-selected", f" {truncated}\n"))
|
|
549
573
|
else:
|
|
550
|
-
lines.append(("class:name", f"{
|
|
574
|
+
lines.append(("class:name", f" {indicator} {name}{active_marker}"))
|
|
551
575
|
lines.append(("class:mode", f" [{mode}]"))
|
|
552
576
|
lines.append(("class:info", f" {msg_count} msgs\n"))
|
|
553
577
|
if summary:
|
|
554
578
|
truncated = summary[:50] + "..." if len(summary) > 50 else summary
|
|
555
|
-
lines.append(("class:summary", f"
|
|
579
|
+
lines.append(("class:summary", f" {truncated}\n"))
|
|
556
580
|
|
|
557
|
-
lines.append(("class:hint", "\n
|
|
581
|
+
lines.append(("class:hint", f"\n{ARROW_PROMPT} ↑↓ navigate Enter load d delete q quit"))
|
|
558
582
|
return lines
|
|
559
583
|
|
|
584
|
+
# Style (zen palette)
|
|
560
585
|
style = Style.from_dict({
|
|
561
|
-
"title": "
|
|
562
|
-
"name":
|
|
563
|
-
"name-selected": "
|
|
564
|
-
"mode":
|
|
565
|
-
"mode-selected":
|
|
566
|
-
"info":
|
|
567
|
-
"info-selected":
|
|
568
|
-
"summary": "
|
|
569
|
-
"summary-selected": "
|
|
570
|
-
"hint": "
|
|
586
|
+
"title": f"{Colors.PRIMARY} bold",
|
|
587
|
+
"name": Colors.PRIMARY,
|
|
588
|
+
"name-selected": f"{Colors.SUCCESS} bold",
|
|
589
|
+
"mode": Colors.MUTED,
|
|
590
|
+
"mode-selected": Colors.SUCCESS,
|
|
591
|
+
"info": Colors.DIM,
|
|
592
|
+
"info-selected": Colors.SUCCESS,
|
|
593
|
+
"summary": f"{Colors.DIM} italic",
|
|
594
|
+
"summary-selected": f"{Colors.SUCCESS} italic",
|
|
595
|
+
"hint": f"{Colors.DIM} italic",
|
|
571
596
|
})
|
|
572
597
|
|
|
573
598
|
height = len(menu_items) * 2 + 4 # items (with summaries) + title + hint + padding
|
|
@@ -599,17 +624,23 @@ def show_sessions_interactive_menu(sessions: list, active_session: str | None) -
|
|
|
599
624
|
|
|
600
625
|
|
|
601
626
|
def confirm_session_delete(session_name: str) -> bool:
|
|
602
|
-
"""Confirm session deletion."""
|
|
627
|
+
"""Confirm session deletion with zen styling."""
|
|
603
628
|
from prompt_toolkit import PromptSession
|
|
604
629
|
|
|
605
630
|
console.print()
|
|
606
|
-
console.print(f"[
|
|
607
|
-
console.print(
|
|
631
|
+
console.print(f"[{Colors.MUTED}]{header('Delete Session', 35)}[/{Colors.MUTED}]")
|
|
632
|
+
console.print()
|
|
633
|
+
console.print(f" [{Colors.ERROR}]{STATUS_ERROR}[/{Colors.ERROR}] This will permanently delete:")
|
|
634
|
+
console.print()
|
|
635
|
+
console.print(f" [{Colors.WARNING}]{session_name}[/{Colors.WARNING}]")
|
|
636
|
+
console.print()
|
|
637
|
+
console.print(f" [{Colors.DIM}]Type 'delete' to confirm[/{Colors.DIM}]")
|
|
638
|
+
console.print()
|
|
608
639
|
|
|
609
640
|
try:
|
|
610
641
|
session = PromptSession()
|
|
611
|
-
response = session.prompt("
|
|
612
|
-
return response
|
|
642
|
+
response = session.prompt(f" {ARROW_PROMPT} ").strip().lower()
|
|
643
|
+
return response == "delete"
|
|
613
644
|
except (KeyboardInterrupt, EOFError):
|
|
614
645
|
return False
|
|
615
646
|
|
|
@@ -673,21 +704,22 @@ def show_plan_mode_approval_menu() -> tuple[str, str]:
|
|
|
673
704
|
lines = [("class:title", "Enter plan mode?\n\n")]
|
|
674
705
|
for i, (key, desc) in enumerate(options):
|
|
675
706
|
if i == selected_index[0]:
|
|
676
|
-
lines.append(("class:selected", f"
|
|
677
|
-
lines.append(("class:selected-desc", f"
|
|
707
|
+
lines.append(("class:selected", f" {STATUS_ACTIVE} {key}\n"))
|
|
708
|
+
lines.append(("class:selected-desc", f" {desc}\n"))
|
|
678
709
|
else:
|
|
679
|
-
lines.append(("class:option", f"
|
|
680
|
-
lines.append(("class:desc", f"
|
|
681
|
-
lines.append(("class:hint", "\n
|
|
710
|
+
lines.append(("class:option", f" {STATUS_INACTIVE} {key}\n"))
|
|
711
|
+
lines.append(("class:desc", f" {desc}\n"))
|
|
712
|
+
lines.append(("class:hint", f"\n{ARROW_PROMPT} y approve n skip Esc cancel"))
|
|
682
713
|
return lines
|
|
683
714
|
|
|
715
|
+
# Style (zen palette)
|
|
684
716
|
style = Style.from_dict({
|
|
685
|
-
"title": "
|
|
686
|
-
"selected": "
|
|
687
|
-
"selected-desc":
|
|
688
|
-
"option":
|
|
689
|
-
"desc":
|
|
690
|
-
"hint": "
|
|
717
|
+
"title": f"{Colors.WARNING} bold",
|
|
718
|
+
"selected": f"{Colors.SUCCESS} bold",
|
|
719
|
+
"selected-desc": Colors.SUCCESS,
|
|
720
|
+
"option": Colors.MUTED,
|
|
721
|
+
"desc": Colors.DIM,
|
|
722
|
+
"hint": f"{Colors.DIM} italic",
|
|
691
723
|
})
|
|
692
724
|
|
|
693
725
|
layout = Layout(
|