@agentikos/omega-os 0.19.44 → 0.19.46

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.
@@ -1037,7 +1037,50 @@ PY
1037
1037
  # Selection comes from the manifest's `claude_plugins:` list (headless) or a
1038
1038
  # whiptail checklist (interactive). Failures on individual plugins are
1039
1039
  # recorded but do not abort the step — Claude plugins are nice-to-have.
1040
+ _disable_broken_claude_plugins() {
1041
+ # v0.19.46 — detect + neutralize known-broken Claude Code plugins
1042
+ # before any `claude` session is spawned (AISB-chat, Hermès-chat,
1043
+ # auto-launch menu, etc.). Without this, broken plugins fire their
1044
+ # SessionStart hook on every claude invocation and pollute the TUI
1045
+ # with ugly stack traces.
1046
+ #
1047
+ # Currently neutralized:
1048
+ # * thedotmack/claude-mem@13.x — imports `zod/v3` which zod 4
1049
+ # removed; the SessionStart hook crashes on every claude start.
1050
+ # Upstream issue (no fix as of 2026-05-26).
1051
+ local cache_dir="${HOME}/.claude/plugins/cache"
1052
+ [ -d "$cache_dir" ] || return 0
1053
+ local found=0
1054
+ # claude-mem: look for the broken worker-service.cjs path.
1055
+ local cm
1056
+ for cm in "$cache_dir"/thedotmack/claude-mem/*/; do
1057
+ [ -d "$cm" ] || continue
1058
+ if [ -f "$cm/scripts/worker-service.cjs" ]; then
1059
+ # Probe the broken `zod/v3` require — if grep finds it, plugin is
1060
+ # the broken upstream version.
1061
+ if grep -q "require.*zod/v3\|require.*['\"]zod/v3['\"]" \
1062
+ "$cm/scripts/worker-service.cjs" 2>/dev/null; then
1063
+ local disabled="${cm%/}.disabled-by-omegaos"
1064
+ if [ ! -d "$disabled" ]; then
1065
+ mv "$cm" "$disabled" 2>/dev/null \
1066
+ && info " neutralized broken claude-mem at $(basename "$cm") (zod/v3 import bug)" \
1067
+ && found=1
1068
+ fi
1069
+ fi
1070
+ fi
1071
+ done
1072
+ if [ "$found" = "1" ]; then
1073
+ info " → re-enable later: \`mv ${cache_dir}/thedotmack/claude-mem.*.disabled-by-omegaos ${cache_dir}/thedotmack/claude-mem/\`"
1074
+ fi
1075
+ return 0
1076
+ }
1077
+
1040
1078
  step_claude_plugins() {
1079
+ # v0.19.46 — preflight: kill any known-broken plugins so the claude
1080
+ # commands we spawn later (and the user's interactive `claude` runs)
1081
+ # don't crash on hook startup.
1082
+ _disable_broken_claude_plugins
1083
+
1041
1084
  local catalog="$OMEGA_HOME/Agentik_SSOT/claude-plugins/claude-plugins.yaml"
1042
1085
  if [ ! -f "$catalog" ]; then
1043
1086
  info "no Claude plugin catalog — skipping (step 20 should have deployed it)"
package/install.sh CHANGED
@@ -290,11 +290,14 @@ post_install_card
290
290
  # * an `omega` binary exists at the canonical path
291
291
  #
292
292
  # Otherwise we just print the instruction so the user knows what to do.
293
- if [ -t 0 ] && [ "${NONINTERACTIVE:-0}" != "1" ] \
294
- && [ -x "$OMEGA_HOME/Agentik_Tools/bin/omega" ]; then
293
+ if [ -t 0 ] && [ -x "$OMEGA_HOME/Agentik_Tools/bin/omega" ]; then
295
294
  log ""
296
- log "${C_DIM}::${C_RST} reloading your shell so \`omega\` is on PATH…"
297
- log "${C_DIM}::${C_RST} type ${C_BOLD}omega${C_RST} to open the session manager"
295
+ log "${C_ORANGE}::${C_RST} ${C_BOLD}Installation complete launching Omega menu…${C_RST}"
296
+ log "${C_DIM}::${C_RST} press Esc or pick ${C_BOLD}Quit${C_RST} to exit the menu"
298
297
  log ""
299
- exec "${SHELL:-/bin/bash}" -l
298
+ # v0.19.45 — auto-launch the Omega menu RIGHT NOW so the user sees the
299
+ # interactive surface immediately. No "type `omega` to open" prompt —
300
+ # just open it. exec replaces the install process so the menu owns
301
+ # the terminal cleanly.
302
+ exec "$OMEGA_HOME/Agentik_Tools/bin/omega"
300
303
  fi
@@ -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.44"
191
+ __version__ = "0.19.46"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -2981,91 +2981,23 @@ def _session_age(unix_ts: int) -> str:
2981
2981
 
2982
2982
 
2983
2983
  def cmd_menu(_args: argparse.Namespace) -> int:
2984
- """`omega` (no args) — attach to the persistent Omega master tmux session.
2985
-
2986
- v0.19.25 redesign per the user's spec: bare `omega` should feel like
2987
- typing `claude` (opens the Claude Code TUI) or `hermes` (opens
2988
- Hermès). It should TAKE OVER your terminal as the OmegaOS home.
2989
-
2990
- Mechanism (tmux-based, since OmegaOS is multi-session by design):
2991
- 1. Ensure the `Omega` tmux session exists (spawn if missing).
2992
- The session's window 0 runs `omega menu-tui` — the fzf-driven
2993
- action picker.
2994
- 2. `os.execvp("tmux attach -t Omega")` your terminal now IS
2995
- the Omega session. Detach with Ctrl-b d, attach again with
2996
- `omega`.
2997
-
2998
- Inside the Omega session you have:
2999
- * window 0 (menu) — the action picker
3000
- * spawned on demand: AISB-chat, Hermes-chat, projects, scratch shells
3001
- * Ctrl-b w — tmux's own window picker
3002
- * Ctrl-b z — tmux-claude session manager (if installed)
3003
-
3004
- If you're already inside tmux (e.g. iTerm tmux integration), we
3005
- don't take over the current session — we tell you how to switch
3006
- to the Omega session manually.
2984
+ """`omega` (no args) — render the Omega menu DIRECTLY in the current
2985
+ terminal. No tmux switch, no session attach, no message: just the menu.
2986
+
2987
+ v0.19.45 RADICAL simplification. Previously we tried to be clever:
2988
+ detect $TMUX, switch-client to the persistent Omega session, attach,
2989
+ etc. Result: a brittle pipeline that printed "Switch to it with: ..."
2990
+ when the cleverness failed, leaving the user staring at a useless
2991
+ message. The user (correctly) called this "insupportable".
2992
+
2993
+ New behavior: `omega` = `omega menu-tui` = fzf TUI right here, right
2994
+ now. Works inside tmux, outside tmux, in iTerm, in Termius, anywhere.
2995
+ The menu's actions (open AISB chat, etc.) still use tmux for chat
2996
+ persistence — but the menu itself is just a fzf prompt in your
2997
+ current terminal, no indirection.
3007
2998
  """
3008
- import os
3009
- import shutil
3010
- from omega_engine import tmux
3011
-
3012
- OMEGA_SESSION = "Omega"
3013
-
3014
- if not shutil.which("tmux"):
3015
- print(" tmux not installed — `brew install tmux` (macOS) or "
3016
- "`apt-get install tmux` (Linux)")
3017
- return 2
3018
-
3019
- if os.environ.get("TMUX"):
3020
- # We're already inside a tmux client. Nested `tmux attach` is
3021
- # rejected by tmux, but `tmux switch-client` works fine — and is
3022
- # what the user wants when they type `omega` from inside tmux.
3023
- # v0.19.41 — actually DO the switch instead of just printing
3024
- # instructions. Print is the v0.19.40 bug ("ça lance rien du tout").
3025
- import subprocess
3026
- if not tmux.is_alive(OMEGA_SESSION):
3027
- tmux.spawn_omega_master(_omega_home())
3028
- # Are we already INSIDE the Omega session?
3029
- proc = subprocess.run(
3030
- ["tmux", "display-message", "-p", "#S"],
3031
- capture_output=True, text=True,
3032
- )
3033
- current = (proc.stdout or "").strip()
3034
- if current == OMEGA_SESSION:
3035
- # Already in Omega — just jump to the menu window. If the
3036
- # menu window was killed, recreate it.
3037
- wins = subprocess.run(
3038
- ["tmux", "list-windows", "-t", OMEGA_SESSION, "-F", "#W"],
3039
- capture_output=True, text=True,
3040
- )
3041
- if "menu" not in (wins.stdout or "").split():
3042
- subprocess.run(
3043
- ["tmux", "new-window", "-t", OMEGA_SESSION, "-n",
3044
- "menu", "omega menu-tui"],
3045
- capture_output=True,
3046
- )
3047
- subprocess.run(
3048
- ["tmux", "select-window", "-t", f"{OMEGA_SESSION}:menu"],
3049
- capture_output=True,
3050
- )
3051
- else:
3052
- # Different session — switch the client to Omega.
3053
- subprocess.run(
3054
- ["tmux", "switch-client", "-t", OMEGA_SESSION],
3055
- capture_output=True,
3056
- )
3057
- return 0
3058
-
3059
- if not tmux.is_alive(OMEGA_SESSION):
3060
- tmux.spawn_omega_master(_omega_home())
3061
-
3062
- try:
3063
- os.execvp("tmux", ["tmux", "attach", "-t", OMEGA_SESSION])
3064
- except FileNotFoundError:
3065
- print(" tmux not on PATH")
3066
- return 2
3067
- return 0
3068
-
2999
+ from omega_engine.tui import run_tui
3000
+ return run_tui()
3069
3001
 
3070
3002
  def cmd_menu_tui(args: argparse.Namespace) -> int:
3071
3003
  """`omega menu-tui` — fzf arrow-key menu (default) / REPL / Textual.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.44"
3
+ version = "0.19.46"
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"
@@ -219,98 +219,69 @@ class TestAisbChat(unittest.TestCase):
219
219
  self.assertEqual(history[1].text, "ok, will look into it")
220
220
 
221
221
 
222
- class TestBareOmegaAttachesNotPrints(unittest.TestCase):
223
- """v0.19.41bug fix. `omega` (no args) used to PRINT instructions
224
- instead of doing the switch when invoked from inside tmux. Lock in
225
- that cmd_menu calls tmux switch-client / select-window directly."""
226
-
227
- def test_cmd_menu_when_in_tmux_calls_switch_client(self):
228
- """When $TMUX is set AND we're in a DIFFERENT session than Omega,
229
- cmd_menu must run `tmux switch-client -t Omega` itself not
230
- print a hint and exit."""
231
- import argparse
232
- with mock.patch.dict("os.environ", {"TMUX": "/tmp/tmux-fake,1,0"}):
233
- calls = []
234
- class _FakeProc:
235
- stdout = "some-other-session\n"
236
- returncode = 0
237
- def _fake_run(cmd, **kw):
238
- calls.append(cmd)
239
- return _FakeProc()
240
- with mock.patch("subprocess.run", side_effect=_fake_run), \
241
- mock.patch("shutil.which", return_value="/usr/bin/tmux"), \
242
- mock.patch("omega_engine.tmux.is_alive", return_value=True):
243
- from omega_engine.cli import cmd_menu
244
- rc = cmd_menu(argparse.Namespace())
245
- self.assertEqual(rc, 0)
246
- switch_calls = [c for c in calls
247
- if isinstance(c, list)
248
- and len(c) >= 4
249
- and c[:2] == ["tmux", "switch-client"]]
250
- self.assertTrue(switch_calls,
251
- f"cmd_menu must call `tmux switch-client -t Omega` when "
252
- f"invoked from inside a different tmux session. "
253
- f"Captured calls: {calls}")
254
-
255
- def test_cmd_menu_when_already_in_omega_selects_menu_window(self):
256
- """If the user is ALREADY in the Omega session, cmd_menu must
257
- select the :menu window (not switch-client — that'd be a no-op)."""
258
- import argparse
259
- with mock.patch.dict("os.environ", {"TMUX": "/tmp/tmux-fake,1,0"}):
260
- calls = []
261
- class _ProcS:
262
- stdout = "Omega\n"; returncode = 0
263
- class _ProcWins:
264
- stdout = "menu\naisb\nhermes\n"; returncode = 0
265
- def _fake_run(cmd, **kw):
266
- calls.append(cmd)
267
- if cmd[:3] == ["tmux", "display-message", "-p"]:
268
- return _ProcS()
269
- if cmd[:3] == ["tmux", "list-windows", "-t"]:
270
- return _ProcWins()
271
- class R: returncode = 0; stdout = ""
272
- return R()
273
- with mock.patch("subprocess.run", side_effect=_fake_run), \
274
- mock.patch("shutil.which", return_value="/usr/bin/tmux"), \
275
- mock.patch("omega_engine.tmux.is_alive", return_value=True):
276
- from omega_engine.cli import cmd_menu
277
- rc = cmd_menu(argparse.Namespace())
278
- self.assertEqual(rc, 0)
279
- select_calls = [c for c in calls
280
- if isinstance(c, list)
281
- and len(c) >= 4
282
- and c[:2] == ["tmux", "select-window"]
283
- and "Omega:menu" in c]
284
- self.assertTrue(select_calls,
285
- f"cmd_menu must call `tmux select-window -t Omega:menu` "
286
- f"when already inside Omega. Captured: {calls}")
287
- switch_calls = [c for c in calls
288
- if isinstance(c, list)
289
- and len(c) >= 2
290
- and c[:2] == ["tmux", "switch-client"]]
291
- self.assertEqual(switch_calls, [],
292
- f"cmd_menu must NOT switch-client when already in Omega.")
293
-
294
- def test_cmd_menu_does_not_print_hint_when_in_tmux(self):
295
- """REGRESSION — the v0.19.40 bug: cmd_menu printed
296
- 'Omega session is running. Switch to it with: ...' instead of
297
- actually switching."""
298
- import argparse, io, sys as _sys
299
- with mock.patch.dict("os.environ", {"TMUX": "/tmp/tmux-fake,1,0"}):
300
- class _Proc:
301
- stdout = "Other\n"; returncode = 0
302
- with mock.patch("subprocess.run", return_value=_Proc()), \
303
- mock.patch("shutil.which", return_value="/usr/bin/tmux"), \
304
- mock.patch("omega_engine.tmux.is_alive", return_value=True), \
305
- mock.patch.object(_sys, "stdout", new_callable=io.StringIO) as captured:
306
- from omega_engine.cli import cmd_menu
307
- cmd_menu(argparse.Namespace())
308
- out = captured.getvalue()
309
- self.assertNotIn("Switch to it with", out,
310
- f"v0.19.40 regression: cmd_menu printed switch instructions "
311
- f"instead of switching. Output: {out!r}")
312
- self.assertNotIn("tmux switch-client -t Omega", out,
313
- "cmd_menu must DO the switch, not print the command")
222
+ class TestBareOmegaRendersMenuDirectly(unittest.TestCase):
223
+ """v0.19.45RADICAL simplification. Previously cmd_menu tried to
224
+ be clever (switch-client / select-window / attach). It was brittle
225
+ and printed "Switch to it with..." when the cleverness failed —
226
+ the user (correctly) called it "insupportable" through 3+ ships.
227
+
228
+ New contract: bare `omega` = run_tui() right in the current pane.
229
+ No tmux switch, no session attach, no print. The fzf menu just
230
+ renders inline."""
231
+
232
+ def test_cmd_menu_calls_run_tui_directly(self):
233
+ """The new cmd_menu must delegate to omega_engine.tui.run_tui —
234
+ nothing else. No tmux switch, no session attach."""
235
+ import argparse, inspect
236
+ from omega_engine.cli import cmd_menu
237
+ src = inspect.getsource(cmd_menu)
238
+ self.assertIn("from omega_engine.tui import run_tui", src,
239
+ "cmd_menu must import run_tui directly")
240
+ self.assertIn("return run_tui()", src,
241
+ "cmd_menu must return run_tui() — direct menu render")
242
+
243
+ def test_cmd_menu_body_only_calls_run_tui(self):
244
+ """REGRESSION the user hit this through v0.19.40, .41, .42,
245
+ .43, .44: cmd_menu kept printing 'Omega session is running.
246
+ Switch to it with: tmux switch-client -t Omega' instead of just
247
+ showing a menu.
248
+
249
+ v0.19.45 ENFORCES the direct-render contract. We strip the
250
+ docstring + comments and verify the EXECUTABLE body is exactly:
251
+ from omega_engine.tui import run_tui
252
+ return run_tui()
253
+ Anything else (subprocess, switch-client, execvp, print of switch
254
+ instructions) is a regression.
255
+ """
256
+ import inspect, ast
257
+ from omega_engine.cli import cmd_menu
258
+ src = inspect.getsource(cmd_menu)
259
+ # Parse the function body and inspect the AST nodes.
260
+ tree = ast.parse(src.strip())
261
+ fn = tree.body[0]
262
+ # Strip leading Expr-of-string-Constant (docstring).
263
+ body = [n for n in fn.body
264
+ if not (isinstance(n, ast.Expr)
265
+ and isinstance(n.value, ast.Constant)
266
+ and isinstance(n.value.value, str))]
267
+ # Expected: ImportFrom omega_engine.tui import run_tui ; Return.
268
+ kinds = [type(n).__name__ for n in body]
269
+ self.assertEqual(kinds, ["ImportFrom", "Return"],
270
+ f"cmd_menu body must be exactly [ImportFrom, Return]. "
271
+ f"Got: {kinds}. v0.19.40-.44 regression somebody re-added "
272
+ f"tmux switch logic.")
273
+ # Confirm the ImportFrom is `from omega_engine.tui import run_tui`
274
+ imp = body[0]
275
+ self.assertEqual(imp.module, "omega_engine.tui",
276
+ "import must be from omega_engine.tui")
277
+ self.assertIn("run_tui", [n.name for n in imp.names],
278
+ "must import run_tui")
279
+ # Confirm the Return calls run_tui()
280
+ ret = body[1]
281
+ self.assertIsInstance(ret.value, ast.Call,
282
+ "return must be a function call")
283
+ self.assertEqual(ret.value.func.id, "run_tui",
284
+ "must return run_tui()")
314
285
 
315
286
 
316
287
  if __name__ == "__main__":
@@ -1 +1 @@
1
- 0.19.44
1
+ 0.19.46
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentikos/omega-os",
3
- "version": "0.19.44",
3
+ "version": "0.19.46",
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"