@agentikos/omega-os 0.19.28 → 0.19.29

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.29"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -2855,19 +2855,20 @@ 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` — slash-command REPL (default) or Textual TUI.
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.29 default = plain REPL. Textual was unreliable under
2862
+ tmux + send-keys (focus didn't reach the input). The REPL uses
2863
+ synchronous input() which works EVERYWHERE, plus readline for
2864
+ history + tab completion of slash commands.
2865
2865
 
2866
- Delegates to `omega_engine.tui.run_tui()` which encapsulates both
2867
- the Textual app and the plain REPL fallback.
2866
+ Opt into Textual: `omega menu-tui --textual` (useful when running
2867
+ omega directly in iTerm/Wezterm/Kitty without tmux send-keys).
2868
2868
  """
2869
2869
  from omega_engine.tui import run_tui
2870
- return run_tui()
2870
+ prefer_textual = getattr(args, "textual", False)
2871
+ return run_tui(prefer_textual=prefer_textual)
2871
2872
 
2872
2873
 
2873
2874
  def _legacy_fzf_menu(_args: argparse.Namespace) -> int:
@@ -4343,10 +4344,12 @@ def _build_parser() -> argparse.ArgumentParser:
4343
4344
  sub.add_parser("menu",
4344
4345
  help="open the interactive whiptail menu (legacy)"
4345
4346
  ).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)
4347
+ p_mt = sub.add_parser("menu-tui",
4348
+ help="slash-command REPL (default) use --textual for the "
4349
+ "fancier (but tmux-fragile) Textual TUI")
4350
+ p_mt.add_argument("--textual", action="store_true",
4351
+ help="try the Textual app instead of the REPL")
4352
+ p_mt.set_defaults(fn=cmd_menu_tui)
4350
4353
  sub.add_parser("menu-fzf",
4351
4354
  help="legacy v0.19.26 fzf menu fallback"
4352
4355
  ).set_defaults(fn=_legacy_fzf_menu)
@@ -409,17 +409,34 @@ 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")
417
- print()
418
- print(" Falling back to plain prompt mode.")
419
- return _plain_repl()
420
- app = OmegaTUI()
421
- app.run()
422
- return 0
412
+ def run_tui(prefer_textual: bool = False) -> int:
413
+ """Entry point — `omega menu-tui` calls this.
414
+
415
+ v0.19.29 switched the DEFAULT to the plain slash REPL because the
416
+ Textual app, while pretty, has unreliable focus/keyboard delivery
417
+ inside tmux panes launched via send-keys. The user's bug report
418
+ ("je peux pas taper dans le keyboard ni sélectionner") was reproducible
419
+ on the VPS too — Textual's Input widget doesn't always claim focus
420
+ when the app starts under tmux + send-keys.
421
+
422
+ The plain REPL uses synchronous `input()` which is rock-solid in any
423
+ terminal, any tmux config, any TERM value. It accepts the SAME slash
424
+ commands (/aisb /hermes /switch /audit /mission /scrape /doctor …).
425
+
426
+ Opt back into Textual via `omega menu-tui --textual` (or pass
427
+ prefer_textual=True from code) — useful when iTerm/Wezterm/Kitty
428
+ runs the menu directly without tmux send-keys interference.
429
+ """
430
+ if prefer_textual and TEXTUAL_AVAILABLE:
431
+ try:
432
+ app = OmegaTUI()
433
+ app.run()
434
+ return 0
435
+ except Exception as exc: # noqa: BLE001
436
+ print(f" Textual TUI failed: {exc}")
437
+ print(" Falling back to plain REPL.")
438
+ return _plain_repl()
439
+ return _plain_repl()
423
440
 
424
441
 
425
442
  # ---------------------------------------------------------------------------
@@ -428,15 +445,73 @@ def run_tui() -> int:
428
445
 
429
446
 
430
447
  def _plain_repl() -> int:
431
- """Slash-command REPL with no textual TUI same command set."""
448
+ """Slash-command REPL the v0.19.29 default for `omega menu-tui`.
449
+
450
+ Rock-solid input via Python's stdlib `input()` — works in any
451
+ terminal, any tmux setup, any TERM value. Same slash command set
452
+ as the Textual app. readline gives history (↑/↓), basic line
453
+ editing, Ctrl-r reverse search.
454
+ """
455
+ import os
432
456
  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")
457
+
458
+ # readline gives line editing + history. Persist history under $OMEGA_HOME.
459
+ try:
460
+ import readline
461
+ hist_path = os.path.join(
462
+ os.environ.get("OMEGA_HOME", os.path.expanduser("~/Omega")),
463
+ "Agentik_Extra", "var", "omega-repl-history",
464
+ )
465
+ try:
466
+ os.makedirs(os.path.dirname(hist_path), exist_ok=True)
467
+ if os.path.exists(hist_path):
468
+ readline.read_history_file(hist_path)
469
+ except OSError:
470
+ hist_path = None
471
+ readline.set_history_length(500)
472
+ # Tab-completion over known slash commands.
473
+ _COMMANDS = [
474
+ "/help", "/aisb", "/hermes", "/switch", "/mission", "/audit",
475
+ "/genesis", "/scrape", "/sessions", "/accounts", "/vault",
476
+ "/doctor", "/status", "/detach", "/quit",
477
+ ]
478
+ def _completer(text: str, state: int) -> str | None:
479
+ matches = [c for c in _COMMANDS if c.startswith(text)]
480
+ return matches[state] if state < len(matches) else None
481
+ readline.set_completer(_completer)
482
+ readline.parse_and_bind("tab: complete")
483
+ except ImportError:
484
+ hist_path = None
485
+
486
+ # Banner — boxed, orange Ω like Hermès's launch screen.
487
+ print()
488
+ print(" ┌─────────────────────────────────────────────────────────┐")
489
+ print(f" │ \033[38;2;217;119;87m\033[1mΩ\033[0m \033[1mOmega OS\033[0m v{__version__:<10} │")
490
+ print( " │ type \033[1m/help\033[0m for slash commands • \033[1m/quit\033[0m to exit │")
491
+ print( " ├─────────────────────────────────────────────────────────┤")
492
+ print( " │ quick start: │")
493
+ print( " │ \033[1m/aisb\033[0m chat with AISB (Max OAuth) │")
494
+ print( " │ \033[1m/hermes\033[0m chat with Hermès (Anthropic API) │")
495
+ print( " │ \033[1m/switch\033[0m see + hot-swap LLM provider │")
496
+ print( " │ \033[1m/mission \"...\"\033[0m run verified-completion mission │")
497
+ print( " │ \033[1m/scrape <url>\033[0m stealth scrape (CloakBrowser) │")
498
+ print( " │ \033[1m/audit <id>\033[0m run a Quality Arsenal audit │")
499
+ print( " │ \033[1m/doctor\033[0m full health check │")
500
+ print( " └─────────────────────────────────────────────────────────┘")
501
+ print()
502
+ print(" TAB completes slash commands • ↑/↓ for history\n")
503
+
504
+ PROMPT = " \033[38;2;217;119;87mΩ\033[0m › "
435
505
  while True:
436
506
  try:
437
- line = input(" Ω › ").strip()
507
+ line = input(PROMPT).strip()
438
508
  except (EOFError, KeyboardInterrupt):
439
509
  print()
510
+ if hist_path:
511
+ try:
512
+ readline.write_history_file(hist_path)
513
+ except OSError:
514
+ pass
440
515
  return 0
441
516
  if not line:
442
517
  continue
@@ -455,3 +530,8 @@ def _plain_repl() -> int:
455
530
  print()
456
531
  if res.session_jump:
457
532
  _switch_client(res.session_jump)
533
+ if hist_path:
534
+ try:
535
+ readline.write_history_file(hist_path)
536
+ except OSError:
537
+ pass
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.28"
3
+ version = "0.19.29"
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.29
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.29",
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"