@agentikos/omega-os 0.19.28 → 0.19.30

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.
@@ -188,7 +188,7 @@ from omega_engine.genesis import (
188
188
  )
189
189
  from omega_engine import plan as plan_v7
190
190
 
191
- __version__ = "0.19.28"
191
+ __version__ = "0.19.30"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -2855,19 +2855,23 @@ def cmd_menu(_args: argparse.Namespace) -> int:
2855
2855
  return 0
2856
2856
 
2857
2857
 
2858
- def cmd_menu_tui(_args: argparse.Namespace) -> int:
2859
- """`omega menu-tui` — the OmegaOS Textual TUI (v0.19.27+).
2858
+ def cmd_menu_tui(args: argparse.Namespace) -> int:
2859
+ """`omega menu-tui` — fzf arrow-key menu (default) / REPL / Textual.
2860
2860
 
2861
- Modern boxed-layout TUI with slash commands (Hermès-style), sidebar
2862
- categories, scrollable content log, footer keybindings. Falls back
2863
- to a plain slash REPL if `textual` isn't installed (e.g. headless
2864
- or before the engine venv finishes installing deps).
2861
+ v0.19.30 default = fzf arrow-key menu. Arrow keys + search-as-you-type
2862
+ + mouse + Enter, with clean grouped layout (CHAT / PROJECTS / AUDITS
2863
+ / INFRASTRUCTURE / HEALTH / SCRAPE / EXIT). Color-themed to Claude
2864
+ (orange #D97757 accents on dark backdrop).
2865
2865
 
2866
- Delegates to `omega_engine.tui.run_tui()` which encapsulates both
2867
- the Textual app and the plain REPL fallback.
2866
+ Flags:
2867
+ --repl → plain slash REPL (input() loop, type /commands)
2868
+ --textual → Textual app (opt-in, may break under tmux send-keys)
2868
2869
  """
2869
2870
  from omega_engine.tui import run_tui
2870
- return run_tui()
2871
+ return run_tui(
2872
+ prefer_textual=getattr(args, "textual", False),
2873
+ force_repl=getattr(args, "repl", False),
2874
+ )
2871
2875
 
2872
2876
 
2873
2877
  def _legacy_fzf_menu(_args: argparse.Namespace) -> int:
@@ -4343,10 +4347,14 @@ def _build_parser() -> argparse.ArgumentParser:
4343
4347
  sub.add_parser("menu",
4344
4348
  help="open the interactive whiptail menu (legacy)"
4345
4349
  ).set_defaults(fn=cmd_menu_whiptail)
4346
- sub.add_parser("menu-tui",
4347
- help="the Textual TUI inside the Omega tmux session "
4348
- "(don't call directly bare `omega` lands you here)"
4349
- ).set_defaults(fn=cmd_menu_tui)
4350
+ p_mt = sub.add_parser("menu-tui",
4351
+ help="fzf arrow-key menu (default), --repl for slash REPL, "
4352
+ "--textual for the Textual app")
4353
+ p_mt.add_argument("--textual", action="store_true",
4354
+ help="try the Textual app (fragile under tmux)")
4355
+ p_mt.add_argument("--repl", action="store_true",
4356
+ help="force slash REPL instead of the arrow menu")
4357
+ p_mt.set_defaults(fn=cmd_menu_tui)
4350
4358
  sub.add_parser("menu-fzf",
4351
4359
  help="legacy v0.19.26 fzf menu fallback"
4352
4360
  ).set_defaults(fn=_legacy_fzf_menu)
@@ -409,17 +409,242 @@ if TEXTUAL_AVAILABLE:
409
409
  _switch_client(res.session_jump)
410
410
 
411
411
 
412
- def run_tui() -> int:
413
- """Entry point `omega menu-tui` calls this."""
414
- if not TEXTUAL_AVAILABLE:
415
- print(" textual not installed `omega upgrade` or run:")
416
- print(" pip install textual")
412
+ def _arrow_menu() -> int:
413
+ """v0.19.30fzf-driven arrow-key menu (the default `omega` UX).
414
+
415
+ Clean grouped layout, arrow-key navigation, search-as-you-type,
416
+ Enter to pick, Esc to refresh. After each action runs INLINE in
417
+ the same pane, "press Enter to return" then re-render the menu.
418
+
419
+ Why fzf and not Textual? Textual's focus model is fragile under
420
+ tmux + send-keys (v0.19.27 bug). fzf has been arrow-key + mouse
421
+ capable since 2014; it's lightweight, single-binary, and behaves
422
+ consistently in every terminal.
423
+
424
+ Why fzf and not whiptail? whiptail is fine but visually 1995. fzf
425
+ gives us a Linear-style search filter and clean ANSI color groups.
426
+ """
427
+ import os
428
+ import shlex
429
+ import shutil
430
+ import subprocess
431
+ from pathlib import Path
432
+ from omega_engine import __version__
433
+ from omega_engine import tmux
434
+
435
+ if not shutil.which("fzf"):
436
+ print(" fzf not on PATH — falling back to slash REPL.")
437
+ print(" install: brew install fzf (or apt install fzf)")
438
+ return _plain_repl()
439
+
440
+ HOME = Path(os.environ.get("OMEGA_HOME", str(Path.home() / "Omega")))
441
+ OMEGA_BIN = str(HOME / "Agentik_Tools" / "bin" / "omega")
442
+
443
+ # ANSI escapes — used via fzf --ansi.
444
+ ORANGE = "\033[38;2;217;119;87m"
445
+ MUTED = "\033[38;2;136;131;122m"
446
+ BOLD = "\033[1m"
447
+ DIM = "\033[2m"
448
+ RST = "\033[0m"
449
+
450
+ def _label(name: str, hint: str = "") -> str:
451
+ """Two-column label: name on the left, hint dimmed on the right."""
452
+ if hint:
453
+ return f" {name:<36}{DIM}{hint}{RST}"
454
+ return f" {name}"
455
+
456
+ def _section(name: str) -> str:
457
+ return f"{ORANGE}{BOLD}── {name} ──{RST}"
458
+
459
+ def _build_items() -> list[tuple[str, str]]:
460
+ """Return (display, action_key) — section headers have key '__sep__'."""
461
+ provider = _active_provider()
462
+ sessions = tmux.list_sessions(HOME)
463
+ return [
464
+ (_section("CHAT"), "__sep__"),
465
+ (_label("AISB master chat", "→ claude (Max OAuth)"), "open:aisb"),
466
+ (_label("Hermès companion", "→ claude (Anthropic API)"), "open:hermes"),
467
+ (_label("Switch LLM", f"current: {provider}"), "switch:provider"),
468
+ ("", "__sep__"),
469
+ (_section("PROJECTS"), "__sep__"),
470
+ (_label("New project", "Genesis pipeline"), "genesis:new"),
471
+ (_label("Open project shell"), "project:open"),
472
+ ("", "__sep__"),
473
+ (_section("AUDITS & MISSIONS"), "__sep__"),
474
+ (_label("Run a mission", "verified completion"), "run:mission"),
475
+ (_label("Quality Arsenal", "17 forensic audits"), "audit:menu"),
476
+ ("", "__sep__"),
477
+ (_section("INFRASTRUCTURE"), "__sep__"),
478
+ (_label("Sessions", f"{len(sessions)} active"), "sessions:list"),
479
+ (_label("Accounts", "Claude Max pool"), "accounts:menu"),
480
+ (_label("Vault", "encrypted secrets"), "vault:menu"),
481
+ ("", "__sep__"),
482
+ (_section("HEALTH"), "__sep__"),
483
+ (_label("omega doctor", "full health check"), "cmd:doctor"),
484
+ (_label("omega status", "task state"), "cmd:status"),
485
+ ("", "__sep__"),
486
+ (_section("SCRAPE"), "__sep__"),
487
+ (_label("Stealth scrape", "CloakBrowser"), "scrape:cloak"),
488
+ (_label("Fast scrape", "Scrapling"), "scrape:scrapling"),
489
+ ("", "__sep__"),
490
+ (_section("EXIT"), "__sep__"),
491
+ (_label("Detach", "session keeps running"), "detach"),
492
+ (_label("Quit Omega", "kills the tmux session"), "quit:kill"),
493
+ ]
494
+
495
+ def _run_inline(cmd_argv, *, shell: bool = False) -> None:
496
+ os.system("clear")
497
+ header = " ".join(cmd_argv) if isinstance(cmd_argv, list) else cmd_argv
498
+ print(f" {ORANGE}{BOLD}Ω ›{RST} {header}")
499
+ print(f" {MUTED}{'─' * 60}{RST}")
500
+ if shell:
501
+ subprocess.run(cmd_argv, shell=True)
502
+ else:
503
+ subprocess.run(cmd_argv)
417
504
  print()
418
- print(" Falling back to plain prompt mode.")
505
+ print(f" {MUTED}{'─' * 60}{RST}")
506
+ try:
507
+ input(f" {DIM}press Enter to return to Omega menu… {RST}")
508
+ except (EOFError, KeyboardInterrupt):
509
+ pass
510
+
511
+ def _prompt(label: str) -> str:
512
+ try:
513
+ return input(f" {ORANGE}{label}:{RST} ").strip()
514
+ except (EOFError, KeyboardInterrupt):
515
+ return ""
516
+
517
+ while True:
518
+ items = _build_items()
519
+ lines = [disp for disp, _ in items]
520
+ header = (
521
+ f"{ORANGE}{BOLD}Ω Omega OS v{__version__}{RST} "
522
+ f"{MUTED}• ↑↓ navigate • ↵ pick • / search • Esc refresh{RST}"
523
+ )
524
+ try:
525
+ proc = subprocess.run(
526
+ ["fzf",
527
+ "--ansi",
528
+ "--prompt=Ω › ",
529
+ f"--header={header}",
530
+ "--header-first",
531
+ "--layout=reverse",
532
+ "--height=100%",
533
+ "--border=rounded",
534
+ "--padding=1,2",
535
+ "--no-multi",
536
+ "--info=hidden",
537
+ "--pointer=▶",
538
+ "--marker=●",
539
+ "--color=bg+:#1a1a2e,fg+:#D97757,hl+:#D97757,"
540
+ "hl:#D97757,prompt:#D97757,pointer:#D97757,"
541
+ "header:#88837A,border:#A8A29E,info:#88837A"],
542
+ input="\n".join(lines), capture_output=True, text=True,
543
+ )
544
+ except (KeyboardInterrupt, subprocess.SubprocessError):
545
+ return 0
546
+ if proc.returncode != 0:
547
+ # Esc → refresh.
548
+ continue
549
+ pick = proc.stdout.rstrip("\n")
550
+ action = None
551
+ for disp, key in items:
552
+ if disp == pick and key != "__sep__":
553
+ action = key
554
+ break
555
+ if action is None:
556
+ continue
557
+
558
+ # === Dispatch ===
559
+ if action == "detach":
560
+ subprocess.run(["tmux", "detach-client"])
561
+ return 0
562
+ if action == "quit:kill":
563
+ subprocess.run(["tmux", "kill-session", "-t", "Omega"])
564
+ return 0
565
+ if action == "open:aisb":
566
+ tmux.spawn_aisb_chat(HOME, force_replace=False)
567
+ subprocess.run(["tmux", "switch-client", "-t", "AISB-chat"])
568
+ continue
569
+ if action == "open:hermes":
570
+ tmux.spawn_hermes_chat(HOME, force_replace=False)
571
+ subprocess.run(["tmux", "switch-client", "-t", "Hermes-chat"])
572
+ continue
573
+ if action == "switch:provider":
574
+ _run_inline([OMEGA_BIN, "switch"]); continue
575
+ if action == "genesis:new":
576
+ slug = _prompt("project slug (a-z0-9_-)")
577
+ if slug:
578
+ _run_inline([OMEGA_BIN, "genesis", "new", slug])
579
+ continue
580
+ if action == "project:open":
581
+ _run_inline("ls -la ~/Omega/Agentik_Coding/projects/ 2>/dev/null "
582
+ "&& echo && echo '(cd into one to start working)'",
583
+ shell=True)
584
+ continue
585
+ if action == "run:mission":
586
+ intent = _prompt("mission intent")
587
+ if intent:
588
+ _run_inline([OMEGA_BIN, "run", intent])
589
+ continue
590
+ if action == "audit:menu":
591
+ _run_inline(
592
+ "echo ' Quality Arsenal — 17 forensic audits:' && "
593
+ "echo ' /codeaudit /uiuxaudit /flowaudit /debugaudit' && "
594
+ "echo ' /featureaudit /perfaudit /secaudit /a11yaudit' && "
595
+ "echo ' /seoaudit /dataaudit /apiaudit /copyaudit' && "
596
+ "echo ' /dxaudit /motionaudit /automationaudit' && "
597
+ "echo ' /logicaudit /retentionaudit /refontaudit' && "
598
+ "echo && echo ' invoke from any claude session, or:' && "
599
+ f"echo ' {OMEGA_BIN} audit <id>'",
600
+ shell=True)
601
+ continue
602
+ if action == "sessions:list":
603
+ _run_inline("tmux ls", shell=True); continue
604
+ if action == "accounts:menu":
605
+ _run_inline([OMEGA_BIN, "account", "list"]); continue
606
+ if action == "vault:menu":
607
+ _run_inline([OMEGA_BIN, "vault", "status"]); continue
608
+ if action == "cmd:doctor":
609
+ _run_inline([OMEGA_BIN, "doctor"]); continue
610
+ if action == "cmd:status":
611
+ _run_inline([OMEGA_BIN, "status"]); continue
612
+ if action == "scrape:cloak":
613
+ url = _prompt("URL")
614
+ if url:
615
+ _run_inline([OMEGA_BIN, "scrape", url])
616
+ continue
617
+ if action == "scrape:scrapling":
618
+ url = _prompt("URL")
619
+ if url:
620
+ _run_inline([OMEGA_BIN, "scrape", url, "--engine", "scrapling"])
621
+ continue
622
+
623
+
624
+ def run_tui(prefer_textual: bool = False,
625
+ force_repl: bool = False) -> int:
626
+ """Entry point — `omega menu-tui` calls this.
627
+
628
+ v0.19.30 — default is the arrow-key fzf menu (clean grouped layout,
629
+ arrow keys + search-as-you-type + mouse, color theme matched to
630
+ Claude). Falls back to plain slash REPL if fzf is missing.
631
+
632
+ Modes:
633
+ - default → `_arrow_menu()` (fzf, arrow keys + search)
634
+ - `--repl` → `_plain_repl()` (input() loop, slash commands)
635
+ - `--textual` → Textual TUI (opt-in, may break under tmux)
636
+ """
637
+ if prefer_textual and TEXTUAL_AVAILABLE:
638
+ try:
639
+ app = OmegaTUI()
640
+ app.run()
641
+ return 0
642
+ except Exception as exc: # noqa: BLE001
643
+ print(f" Textual TUI failed: {exc}")
644
+ print(" Falling back to arrow-key menu.")
645
+ if force_repl:
419
646
  return _plain_repl()
420
- app = OmegaTUI()
421
- app.run()
422
- return 0
647
+ return _arrow_menu()
423
648
 
424
649
 
425
650
  # ---------------------------------------------------------------------------
@@ -428,15 +653,73 @@ def run_tui() -> int:
428
653
 
429
654
 
430
655
  def _plain_repl() -> int:
431
- """Slash-command REPL with no textual TUI same command set."""
656
+ """Slash-command REPL the v0.19.29 default for `omega menu-tui`.
657
+
658
+ Rock-solid input via Python's stdlib `input()` — works in any
659
+ terminal, any tmux setup, any TERM value. Same slash command set
660
+ as the Textual app. readline gives history (↑/↓), basic line
661
+ editing, Ctrl-r reverse search.
662
+ """
663
+ import os
432
664
  from omega_engine import __version__
433
- print(f"\n Ω Omega OS v{__version__} — plain REPL mode")
434
- print(" Type /help for commands, /quit to exit.\n")
665
+
666
+ # readline gives line editing + history. Persist history under $OMEGA_HOME.
667
+ try:
668
+ import readline
669
+ hist_path = os.path.join(
670
+ os.environ.get("OMEGA_HOME", os.path.expanduser("~/Omega")),
671
+ "Agentik_Extra", "var", "omega-repl-history",
672
+ )
673
+ try:
674
+ os.makedirs(os.path.dirname(hist_path), exist_ok=True)
675
+ if os.path.exists(hist_path):
676
+ readline.read_history_file(hist_path)
677
+ except OSError:
678
+ hist_path = None
679
+ readline.set_history_length(500)
680
+ # Tab-completion over known slash commands.
681
+ _COMMANDS = [
682
+ "/help", "/aisb", "/hermes", "/switch", "/mission", "/audit",
683
+ "/genesis", "/scrape", "/sessions", "/accounts", "/vault",
684
+ "/doctor", "/status", "/detach", "/quit",
685
+ ]
686
+ def _completer(text: str, state: int) -> str | None:
687
+ matches = [c for c in _COMMANDS if c.startswith(text)]
688
+ return matches[state] if state < len(matches) else None
689
+ readline.set_completer(_completer)
690
+ readline.parse_and_bind("tab: complete")
691
+ except ImportError:
692
+ hist_path = None
693
+
694
+ # Banner — boxed, orange Ω like Hermès's launch screen.
695
+ print()
696
+ print(" ┌─────────────────────────────────────────────────────────┐")
697
+ print(f" │ \033[38;2;217;119;87m\033[1mΩ\033[0m \033[1mOmega OS\033[0m v{__version__:<10} │")
698
+ print( " │ type \033[1m/help\033[0m for slash commands • \033[1m/quit\033[0m to exit │")
699
+ print( " ├─────────────────────────────────────────────────────────┤")
700
+ print( " │ quick start: │")
701
+ print( " │ \033[1m/aisb\033[0m chat with AISB (Max OAuth) │")
702
+ print( " │ \033[1m/hermes\033[0m chat with Hermès (Anthropic API) │")
703
+ print( " │ \033[1m/switch\033[0m see + hot-swap LLM provider │")
704
+ print( " │ \033[1m/mission \"...\"\033[0m run verified-completion mission │")
705
+ print( " │ \033[1m/scrape <url>\033[0m stealth scrape (CloakBrowser) │")
706
+ print( " │ \033[1m/audit <id>\033[0m run a Quality Arsenal audit │")
707
+ print( " │ \033[1m/doctor\033[0m full health check │")
708
+ print( " └─────────────────────────────────────────────────────────┘")
709
+ print()
710
+ print(" TAB completes slash commands • ↑/↓ for history\n")
711
+
712
+ PROMPT = " \033[38;2;217;119;87mΩ\033[0m › "
435
713
  while True:
436
714
  try:
437
- line = input(" Ω › ").strip()
715
+ line = input(PROMPT).strip()
438
716
  except (EOFError, KeyboardInterrupt):
439
717
  print()
718
+ if hist_path:
719
+ try:
720
+ readline.write_history_file(hist_path)
721
+ except OSError:
722
+ pass
440
723
  return 0
441
724
  if not line:
442
725
  continue
@@ -455,3 +738,8 @@ def _plain_repl() -> int:
455
738
  print()
456
739
  if res.session_jump:
457
740
  _switch_client(res.session_jump)
741
+ if hist_path:
742
+ try:
743
+ readline.write_history_file(hist_path)
744
+ except OSError:
745
+ pass
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.28"
3
+ version = "0.19.30"
4
4
  description = "The Omega OS orchestration engine — event-sourced, verified-completion agent graphs."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1 +1 @@
1
- 0.19.28
1
+ 0.19.30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentikos/omega-os",
3
- "version": "0.19.28",
3
+ "version": "0.19.30",
4
4
  "description": "Omega OS — installable agentic operating system with verified-completion orchestration. Event-sourced engine, 8-block rack, autonomous agents, MCP.",
5
5
  "bin": {
6
6
  "omega-os": "bin/omega-os.js"