@agentikos/omega-os 0.19.30 → 0.19.32

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.30"
191
+ __version__ = "0.19.32"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -2606,6 +2606,88 @@ def cmd_tmux(args: argparse.Namespace) -> int:
2606
2606
  print(f"no such session: {args.name}")
2607
2607
  return 1
2608
2608
 
2609
+ if sub == "switcher":
2610
+ # v0.19.32 — fzf-based tmux session picker.
2611
+ # Bound to Option+/ in the pro tmux config. Lists ALL live
2612
+ # tmux sessions (Omega, AISB-chat, Hermes-chat, per-project
2613
+ # oracles, workers, ...) with metadata, lets the user pick
2614
+ # one, and switches the client to it.
2615
+ import shlex, shutil, subprocess
2616
+ from omega_engine import __version__
2617
+ if not shutil.which("fzf"):
2618
+ print(" fzf not on PATH — install `brew install fzf` "
2619
+ "or `apt install fzf`")
2620
+ return 2
2621
+ sessions = tmux.list_sessions(home)
2622
+ if not sessions:
2623
+ print(" no tmux sessions yet — type `omega` to spawn the master")
2624
+ return 0
2625
+ sessions.sort(key=lambda s: -int(s.created))
2626
+
2627
+ def _age(ts: int) -> str:
2628
+ import time as _t
2629
+ delta = max(0, int(_t.time()) - int(ts))
2630
+ if delta < 60: return "now"
2631
+ if delta < 3600: return f"{delta // 60}m"
2632
+ if delta < 86400: return f"{delta // 3600}h"
2633
+ return f"{delta // 86400}d"
2634
+
2635
+ ORANGE = "\033[38;2;217;119;87m"
2636
+ MUTED = "\033[38;2;136;131;122m"
2637
+ BOLD = "\033[1m"
2638
+ DIM = "\033[2m"
2639
+ RST = "\033[0m"
2640
+
2641
+ lines = []
2642
+ keys = []
2643
+ for s in sessions:
2644
+ mark = f"{ORANGE}▶{RST}" if s.attached else " "
2645
+ project = f"[{s.project}]" if s.project else ""
2646
+ line = (
2647
+ f" {mark} {BOLD}{s.name:<32}{RST} "
2648
+ f"{DIM}{s.category:<10}{RST} "
2649
+ f"{MUTED}{s.windows}w {_age(s.created):<5}{RST} "
2650
+ f"{DIM}{project}{RST}"
2651
+ )
2652
+ lines.append(line)
2653
+ keys.append(s.name)
2654
+
2655
+ header = (
2656
+ f"{ORANGE}{BOLD}Ω Sessions{RST} "
2657
+ f"{MUTED}• ↑↓ navigate • ↵ switch-client • Esc cancel{RST}"
2658
+ )
2659
+ try:
2660
+ proc = subprocess.run(
2661
+ ["fzf", "--ansi", "--no-multi",
2662
+ "--prompt=session › ",
2663
+ f"--header={header}",
2664
+ "--header-first",
2665
+ "--layout=reverse",
2666
+ "--height=60%",
2667
+ "--border=rounded",
2668
+ "--padding=1,2",
2669
+ "--info=hidden",
2670
+ "--pointer=▶",
2671
+ "--color="
2672
+ "bg:#FAFAF7,fg:#3D3929,"
2673
+ "bg+:#E5E2DD,fg+:#D97757,"
2674
+ "hl:#D97757,hl+:#D97757,"
2675
+ "prompt:#D97757,pointer:#D97757,"
2676
+ "header:#88837A,border:#A8A29E,info:#88837A,"
2677
+ "gutter:#FAFAF7"],
2678
+ input="\n".join(lines), capture_output=True, text=True,
2679
+ )
2680
+ except (KeyboardInterrupt, subprocess.SubprocessError):
2681
+ return 0
2682
+ if proc.returncode != 0:
2683
+ return 0
2684
+ pick = proc.stdout.rstrip("\n")
2685
+ for line, name in zip(lines, keys):
2686
+ if line == pick:
2687
+ subprocess.run(["tmux", "switch-client", "-t", name])
2688
+ return 0
2689
+ return 0
2690
+
2609
2691
  if sub == "spawn":
2610
2692
  kind = args.kind
2611
2693
  name = args.name
@@ -4510,6 +4592,9 @@ def _build_parser() -> argparse.ArgumentParser:
4510
4592
  p_tcl.add_argument("--yes", action="store_true",
4511
4593
  help="apply (default is dry-run)")
4512
4594
  tx_sub.add_parser("menu", help="interactive whiptail picker (use under tmux for prefix+Z)")
4595
+ tx_sub.add_parser("switcher",
4596
+ help="fzf session switcher — list all live tmux sessions and "
4597
+ "switch-client to one (bound to Option+/ in the pro config)")
4513
4598
  p_tcfg = tx_sub.add_parser("config",
4514
4599
  help="write the recommended tmux.conf to Agentik_Tools/")
4515
4600
  p_tcfg.add_argument("--profile", choices=["minimal", "pro"],
@@ -325,6 +325,48 @@ def _spawn_with_shell_then_run(
325
325
  return name
326
326
 
327
327
 
328
+ def spawn_chat_in_omega(
329
+ window_name: str,
330
+ *,
331
+ ctx_dir: Path,
332
+ run_command: str,
333
+ force_replace: bool = False,
334
+ ) -> bool:
335
+ """v0.19.31 — spawn a chat as a WINDOW inside the Omega master session.
336
+
337
+ Returns True when the window exists after the call. The user can
338
+ then `tmux select-window -t Omega:<name>` (or pick from the menu).
339
+ Detach (Ctrl-b d) detaches the whole Omega session — user comes
340
+ back to their shell with Omega still alive, and `omega` re-attaches
341
+ them straight back to the menu.
342
+
343
+ Why windows instead of separate sessions: the user wants `omega`
344
+ to STAY OMEGA. With separate AISB-chat / Hermes-chat sessions,
345
+ detaching from one of those landed them in the shell, not back
346
+ in the Omega menu. Windows under Omega solve that — everything
347
+ lives under the same session lifecycle.
348
+ """
349
+ if not is_alive("Omega"):
350
+ # Omega master must already be alive — bare `omega` ensures this.
351
+ spawn_omega_master(ctx_dir.parent.parent.parent)
352
+ # Probe existing windows.
353
+ _, list_out = _tmux("list-windows", "-t", "Omega", "-F", "#W")
354
+ existing = list_out.splitlines() if list_out else []
355
+ if window_name in existing:
356
+ if force_replace:
357
+ _tmux("kill-window", "-t", f"Omega:{window_name}")
358
+ else:
359
+ return True
360
+ # Create the window with the user's interactive shell at ctx_dir, then
361
+ # send the launch command. Shell stays alive even if the command exits.
362
+ rc, _ = _tmux("new-window", "-t", "Omega", "-n", window_name,
363
+ "-c", str(ctx_dir))
364
+ if rc != 0:
365
+ return False
366
+ _tmux("send-keys", "-t", f"Omega:{window_name}", run_command, "Enter")
367
+ return True
368
+
369
+
328
370
  def spawn_aisb_chat(omega_home: str | Path | None = None,
329
371
  force_replace: bool = False) -> str:
330
372
  """Spawn the AISB master chat tmux session — REAL Claude Code TUI.
@@ -530,12 +572,21 @@ bind-key Z display-popup -E -w 80% -h 80% "omega tmux menu"
530
572
  # Prefix+S — native session list (tmux's built-in choose-tree)
531
573
  bind-key S choose-tree -Zs
532
574
 
575
+ # Option+/ → session switcher (fzf popup, pick any live tmux session)
576
+ # Option+z → Omega action menu (spawn Omega if missing + switch-client)
577
+ # macOS Option key → enable "Use Option as Meta" in your terminal.
578
+ bind-key -n M-/ display-popup -E -h 80% -w 90% "omega tmux switcher"
579
+ bind-key -n M-z run-shell -b "tmux has-session -t Omega 2>/dev/null || tmux new-session -d -s Omega -n menu -c $HOME 'omega menu-tui'; tmux switch-client -t Omega"
580
+
533
581
  # ════════════════════════════════════════════════════════════════════
534
- # Visual cues per session category
582
+ # Claude Code LIGHT theme (white-paper)
535
583
  # ════════════════════════════════════════════════════════════════════
536
- set -g status-style "bg=#1a1a2e,fg=#eeeeee"
537
- set -g status-left "#[fg=#7aa2f7,bold]#S #[fg=default]│ "
538
- set -g status-right "#[fg=#888888]%H:%M │ #(omega tmux count 2>/dev/null) sessions"
584
+ set -g status-style "bg=#FAFAF7,fg=#3D3929"
585
+ set -g status-left "#[fg=#D97757,bold]Ω #S #[fg=#A8A29E]│ "
586
+ set -g status-right "#[fg=#88837A]%H:%M │ #(omega tmux count 2>/dev/null) sessions"
587
+ set -g pane-border-style "fg=#A8A29E"
588
+ set -g pane-active-border-style "fg=#D97757"
589
+ set -g message-style "bg=#E5E2DD,fg=#3D3929"
539
590
  """
540
591
 
541
592
 
@@ -623,18 +674,49 @@ bind-key S choose-tree -Zs
623
674
  bind-key r source-file ~/.tmux.conf \\; display-message "tmux.conf reloaded"
624
675
 
625
676
  # ════════════════════════════════════════════════════════════════════
626
- # Visual cues per session category — colour the status bar by name.
677
+ # Global Omega menu keybindings (v0.19.31)
678
+ # ════════════════════════════════════════════════════════════════════
679
+ # Open the Omega menu from ANYWHERE in tmux — no prefix needed.
680
+ #
681
+ # Option+/ or Option+z → opens the Omega menu
682
+ #
683
+ # How: spawn the Omega session if missing, then switch the current
684
+ # client to it. Detach (Ctrl-b d) brings you back to your shell with
685
+ # Omega still alive.
686
+ #
687
+ # IMPORTANT — for Option key to work on macOS terminals, enable
688
+ # "Use Option as Meta key" (iTerm2: Profile → Keys → Left/Right Option
689
+ # Key → Esc+). Otherwise the binding stays inactive.
690
+ # ────────────────────────────────────────────────────────────────────
691
+ # Option+/ → SESSION SWITCHER (fzf — pick any live tmux session)
692
+ # Option+z → OMEGA ACTION MENU (the v0.19.30 fzf menu of actions)
693
+ # ────────────────────────────────────────────────────────────────────
694
+ # popup -E runs the command in a tmux popup overlay (modal). The popup
695
+ # closes when the command exits, returning the user to their previous
696
+ # pane. -h 80% / -w 90% sizes the popup.
697
+ bind-key -n M-/ display-popup -E -h 80% -w 90% "omega tmux switcher"
698
+ bind-key -n M-z run-shell -b "tmux has-session -t Omega 2>/dev/null || tmux new-session -d -s Omega -n menu -c $HOME 'omega menu-tui'; tmux switch-client -t Omega"
699
+
700
+ # ════════════════════════════════════════════════════════════════════
701
+ # Claude Code LIGHT theme (white-paper) — status bar + borders
627
702
  # ════════════════════════════════════════════════════════════════════
628
- set -g status-style "bg=#1a1a2e,fg=#eeeeee"
629
- set -g status-left "#[fg=#7aa2f7,bold]#S #[fg=default]│ "
630
- set -g status-right "#[fg=#888888]%H:%M │ #(omega tmux count 2>/dev/null) sessions"
703
+ # Colours derived from tweakcn.com/r/themes/claude.json:
704
+ # bg #FAFAF7 (cream) fg #3D3929 (slate) accent #D97757 (orange)
705
+ # muted #88837A (warm gray) border #A8A29E (soft)
706
+ set -g status-style "bg=#FAFAF7,fg=#3D3929"
707
+ set -g status-left "#[fg=#D97757,bold]Ω #S #[fg=#A8A29E]│ "
708
+ set -g status-right "#[fg=#88837A]%H:%M │ #(omega tmux count 2>/dev/null) sessions"
631
709
  set -g status-interval 5
632
710
  set -g status-left-length 40
633
711
  set -g status-right-length 60
634
712
 
635
- # Pane border colour softer than default red
636
- set -g pane-border-style "fg=#333333"
637
- set -g pane-active-border-style "fg=#7aa2f7"
713
+ # Pane borderssoft warm gray, accent orange on the active pane.
714
+ set -g pane-border-style "fg=#A8A29E"
715
+ set -g pane-active-border-style "fg=#D97757"
716
+
717
+ # Message + copy-mode prompts — same palette.
718
+ set -g message-style "bg=#E5E2DD,fg=#3D3929"
719
+ set -g mode-style "bg=#D97757,fg=#FAFAF7"
638
720
  """
639
721
 
640
722
 
@@ -522,6 +522,11 @@ def _arrow_menu() -> int:
522
522
  f"{MUTED}• ↑↓ navigate • ↵ pick • / search • Esc refresh{RST}"
523
523
  )
524
524
  try:
525
+ # Claude Code LIGHT theme (white-paper) — bg cream #FAFAF7,
526
+ # fg dark slate #3D3929, accent orange #D97757, muted warm
527
+ # gray #88837A, soft border #A8A29E. Reads cleanly under
528
+ # both light and dark terminal backgrounds (we override
529
+ # fzf's bg explicitly).
525
530
  proc = subprocess.run(
526
531
  ["fzf",
527
532
  "--ansi",
@@ -536,9 +541,21 @@ def _arrow_menu() -> int:
536
541
  "--info=hidden",
537
542
  "--pointer=▶",
538
543
  "--marker=●",
539
- "--color=bg+:#1a1a2e,fg+:#D97757,hl+:#D97757,"
540
- "hl:#D97757,prompt:#D97757,pointer:#D97757,"
541
- "header:#88837A,border:#A8A29E,info:#88837A"],
544
+ "--color="
545
+ "bg:#FAFAF7,"
546
+ "fg:#3D3929,"
547
+ "bg+:#E5E2DD,"
548
+ "fg+:#D97757,"
549
+ "hl:#D97757,"
550
+ "hl+:#D97757,"
551
+ "prompt:#D97757,"
552
+ "pointer:#D97757,"
553
+ "marker:#D97757,"
554
+ "header:#88837A,"
555
+ "border:#A8A29E,"
556
+ "info:#88837A,"
557
+ "spinner:#D97757,"
558
+ "gutter:#FAFAF7"],
542
559
  input="\n".join(lines), capture_output=True, text=True,
543
560
  )
544
561
  except (KeyboardInterrupt, subprocess.SubprocessError):
@@ -563,12 +580,34 @@ def _arrow_menu() -> int:
563
580
  subprocess.run(["tmux", "kill-session", "-t", "Omega"])
564
581
  return 0
565
582
  if action == "open:aisb":
566
- tmux.spawn_aisb_chat(HOME, force_replace=False)
567
- subprocess.run(["tmux", "switch-client", "-t", "AISB-chat"])
583
+ # v0.19.31 — open as a WINDOW in Omega, not a separate session.
584
+ # User stays in Omega; Ctrl-b 0 returns to menu, Ctrl-b d
585
+ # detaches the whole Omega (and `omega` brings them back).
586
+ persona = HOME / "Agentik_SSOT" / "agents" / "aisb" / "CLAUDE.md"
587
+ ctx_dir = tmux._ensure_chat_context_dir(HOME, "aisb-master", persona)
588
+ tmux.spawn_chat_in_omega(
589
+ "aisb", ctx_dir=ctx_dir, run_command="claude",
590
+ force_replace=False,
591
+ )
592
+ subprocess.run(["tmux", "select-window", "-t", "Omega:aisb"])
568
593
  continue
569
594
  if action == "open:hermes":
570
- tmux.spawn_hermes_chat(HOME, force_replace=False)
571
- subprocess.run(["tmux", "switch-client", "-t", "Hermes-chat"])
595
+ persona = HOME / "Agentik_SSOT" / "docs" / "LAYERS.md"
596
+ ctx_dir = tmux._ensure_chat_context_dir(HOME, "hermes", persona)
597
+ try:
598
+ from omega_engine.vault import vault_read
599
+ api_key = (vault_read(HOME, "ANTHROPIC_API_KEY_HERMES") or "").strip()
600
+ except Exception: # noqa: BLE001
601
+ api_key = ""
602
+ if not api_key:
603
+ api_key = (os.environ.get("ANTHROPIC_API_KEY") or "").strip()
604
+ run_cmd = (f"ANTHROPIC_API_KEY={api_key} claude"
605
+ if api_key else "claude")
606
+ tmux.spawn_chat_in_omega(
607
+ "hermes", ctx_dir=ctx_dir, run_command=run_cmd,
608
+ force_replace=False,
609
+ )
610
+ subprocess.run(["tmux", "select-window", "-t", "Omega:hermes"])
572
611
  continue
573
612
  if action == "switch:provider":
574
613
  _run_inline([OMEGA_BIN, "switch"]); continue
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.30"
3
+ version = "0.19.32"
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.30
1
+ 0.19.32
@@ -53,11 +53,18 @@ catalog:
53
53
 
54
54
  - id: claude-mem
55
55
  name: claude-mem
56
- description: "Long-term memory + observation system across sessions"
56
+ description: |
57
+ Long-term memory + observation system across sessions.
58
+ KNOWN ISSUE (2026-05-25): claude-mem 13.3.0 ships a stop-hook
59
+ worker-service.cjs that imports `zod/v3` (doesn't exist in zod 4+).
60
+ Under Bun the hook crashes with "Cannot find module 'zod/v3'". The
61
+ plugin still installs — only the stop hook breaks.
62
+ Marked opt-in until upstream fixes. Install manually with:
63
+ claude plugin install claude-mem@thedotmack
57
64
  category: memory
58
65
  marketplace: thedotmack
59
66
  scope: user
60
- recommended: true
67
+ recommended: false
61
68
 
62
69
  - id: frontend-design
63
70
  name: frontend-design
@@ -74,6 +74,29 @@ native:
74
74
  secrets: []
75
75
  recommended: true
76
76
 
77
+ - id: paperclipai
78
+ name: Paperclip (orchestration UI — agent teams, org charts, governance)
79
+ # Node.js + React app from paperclipai/paperclip.
80
+ #
81
+ # STATUS (v0.19.32) — honest disclosure:
82
+ # - The binary installs cleanly (`npx -y paperclipai onboard --yes`).
83
+ # - There is NO native OmegaOS↔Paperclip bridge yet. Paperclip's
84
+ # own docs list Claude Code, Codex, Cursor, OpenClaw — Hermès is
85
+ # NOT in their supported-agents list, and OmegaOS isn't either.
86
+ # - To make Paperclip "understand" our agents I'd need to:
87
+ # a) Write a Paperclip agent profile pointing at omega's
88
+ # claude/hermes subprocess invocations
89
+ # b) Add a heartbeat sender from our tmux sessions
90
+ # c) Map Paperclip's org-chart concepts to our 4-level model
91
+ # That's real work, scheduled for v0.20.x — not done yet.
92
+ # For now: install it if you want the standalone Paperclip UI, but
93
+ # treat it as a parallel system, not an OmegaOS bridge.
94
+ install: { npm_global: "paperclipai" }
95
+ binary: paperclip
96
+ secrets: []
97
+ recommended: false
98
+ post_install: ["paperclip", "--version"]
99
+
77
100
  - id: scrapling
78
101
  name: Scrapling (optional fast scraper — HTTP-first, adaptive elements)
79
102
  # Complementary to CloakBrowser. Scrapling shines for non-protected
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentikos/omega-os",
3
- "version": "0.19.30",
3
+ "version": "0.19.32",
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"