@agentikos/omega-os 0.19.15 → 0.19.17

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.
@@ -365,49 +365,74 @@ step_engine() {
365
365
 
366
366
  # --- 36 -----------------------------------------------------------------------
367
367
  #
368
- # step_tmux_config — install the "pro" tmux profile and wire ~/.tmux.conf.
368
+ # step_tmux_config — install the canonical `tmux-claude` setup.
369
369
  #
370
- # Writes two files:
371
- # 1. $OMEGA_HOME/Agentik_Tools/tmux.conf (bundled, single source of truth)
372
- # 2. ~/.tmux.conf (the user's live config)
370
+ # The canonical OmegaVPS tmux UX lives at github.com/agentik-os/tmux-claude:
371
+ # session manager popup (Ctrl+l, Ctrl+b z, Option+z), per-session metrics
372
+ # (RAM/age/git/Claude/AISB progress), project auto-discovery, dev-server
373
+ # port management, mobile-friendly scroll, theme-neutral status bar.
373
374
  #
374
- # (2) gets a timestamped .bak.<ts> sibling whenever the existing content
375
- # differs re-runs that produce identical content are silent no-ops, so the
376
- # step is fully idempotent without leaving piles of backups behind.
375
+ # We run the upstream installer (curl|bash). It writes ~/.tmux.conf plus
376
+ # ~/.tmux/scripts/ and ~/.config/tmux-claude/. Idempotent re-running is a
377
+ # safe no-op once the marker file is present.
377
378
  #
378
- # Why "pro" by default: Termius paste-fix, session-kill forensics log, smart
379
- # scroll in alt-screen panes (Claude Code TUI), extended keys, OSC 52
380
- # clipboard. This matches the live OmegaVPS UX the operator already uses.
379
+ # Fallback: when curl is unavailable or the network is down, we drop our
380
+ # bundled "pro" config so the user still has a sane tmux conf.
381
381
  step_tmux_config() {
382
382
  if ! have tmux; then
383
383
  err "tmux not installed — step_system_deps should have caught this"
384
384
  return 1
385
385
  fi
386
+ local marker="$HOME/.tmux/scripts/session-manager.sh"
387
+ local installer_url="https://raw.githubusercontent.com/agentik-os/tmux-claude/main/install.sh"
388
+
389
+ if [ -f "$marker" ]; then
390
+ info "tmux-claude already installed at $marker — skipping"
391
+ elif have curl; then
392
+ info "installing canonical tmux-claude setup (agentik-os/tmux-claude)…"
393
+ # We pipe through `bash -s -- --no-prompt` so the install doesn't ask
394
+ # for confirmation. If the upstream installer doesn't support that
395
+ # flag it just ignores it.
396
+ if curl -fsSL "$installer_url" 2>>"$LOG_FILE" \
397
+ | bash -s -- --no-prompt >>"$LOG_FILE" 2>&1; then
398
+ ok "tmux-claude installed (~/.tmux/scripts/, ~/.tmux.conf)"
399
+ else
400
+ err "tmux-claude install failed — falling back to bundled pro profile"
401
+ _tmux_fallback_pro_config
402
+ fi
403
+ else
404
+ info "curl missing — falling back to bundled pro profile"
405
+ _tmux_fallback_pro_config
406
+ fi
407
+
408
+ # Always also drop the bundled config under $OMEGA_HOME so `omega tmux
409
+ # install --profile pro` later remains a working manual recovery path.
410
+ PYTHONPATH="$OMEGA_HOME/Agentik_Engine" python3 - <<PY 2>>"$LOG_FILE"
411
+ import os
412
+ os.environ["OMEGA_HOME"] = "$OMEGA_HOME"
413
+ from omega_engine.tmux import write_default_config
414
+ bundled = write_default_config(profile="pro")
415
+ print(f" bundled fallback config also at: {bundled}")
416
+ PY
417
+ return 0
418
+ }
419
+
420
+ _tmux_fallback_pro_config() {
386
421
  PYTHONPATH="$OMEGA_HOME/Agentik_Engine" python3 - <<PY 2>>"$LOG_FILE"
387
422
  import os
388
423
  os.environ["OMEGA_HOME"] = "$OMEGA_HOME"
389
424
  from pathlib import Path
390
425
  from omega_engine.tmux import write_default_config, install_into_home_tmux_conf
391
-
392
- # 1. Always write the bundled "pro" config — single source of truth.
393
426
  bundled = write_default_config(profile="pro")
394
- print(f" tmux bundled config: {bundled} (pro profile)")
395
-
396
- # 2. Skip ~/.tmux.conf rewrite when it already matches the bundled content
397
- # (otherwise re-runs spam timestamped backups for no reason).
398
427
  home_conf = Path.home() / ".tmux.conf"
399
428
  bundled_content = Path(bundled).read_text()
400
429
  existing = home_conf.read_text() if home_conf.exists() else ""
401
- if existing == bundled_content:
402
- print(f" ~/.tmux.conf already matches pro profile — nothing to do")
403
- else:
430
+ if existing != bundled_content:
404
431
  res = install_into_home_tmux_conf(profile="pro", backup=True)
405
432
  if res["backup_path"]:
406
433
  print(f" backed up previous ~/.tmux.conf -> {res['backup_path']}")
407
434
  print(f" wrote pro profile to {res['written']}")
408
- print(f" reload in-session: tmux source-file ~/.tmux.conf")
409
435
  PY
410
- return $?
411
436
  }
412
437
 
413
438
  # --- 37 -----------------------------------------------------------------------
@@ -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.15"
191
+ __version__ = "0.19.17"
192
192
 
193
193
  __all__ = [
194
194
  "__version__",
@@ -194,13 +194,32 @@ class ClaudeCodeAdapter:
194
194
  cat = catalog_by_id.get(sid, {})
195
195
  install = cat.get("install") or {}
196
196
 
197
- # Prefer the locally installed binary; fall back to `npx <package>`.
198
- if tool and tool.invoke:
197
+ # Resolve the launch command. Three shapes:
198
+ # 1. uvx:<package> — Python MCP via Astral uvx (no
199
+ # local binary; Claude calls `uvx <package>` at runtime)
200
+ # 2. tool.invoke = relative path → resolved binary on disk
201
+ # 3. catalog install method → `npx -y <package>` or
202
+ # `uvx <package>` synthesized from the catalog alone
203
+ catalog_args = list(install.get("args") or [])
204
+ server_args = list(server.get("args") or [])
205
+ if tool and tool.invoke and tool.invoke.startswith("uvx:"):
206
+ # uvx-managed Python MCP server.
207
+ pkg = tool.invoke[len("uvx:"):]
208
+ entry["command"] = "uvx"
209
+ entry["args"] = [pkg, *catalog_args, *server_args]
210
+ elif tool and tool.invoke:
199
211
  entry["command"] = str(omega_home / tool.invoke)
200
- entry["args"] = list(server.get("args") or [])
212
+ entry["args"] = [*catalog_args, *server_args]
201
213
  elif install.get("method") == "npx" and install.get("package"):
202
214
  entry["command"] = "npx"
203
- entry["args"] = ["-y", str(install["package"]), *(server.get("args") or [])]
215
+ entry["args"] = ["-y", str(install["package"]),
216
+ *catalog_args, *server_args]
217
+ elif install.get("method") == "uvx" and install.get("package"):
218
+ # No local install (cold uvx call at runtime — slow first time
219
+ # but works without ever running `omega tool install`).
220
+ entry["command"] = "uvx"
221
+ entry["args"] = [str(install["package"]),
222
+ *catalog_args, *server_args]
204
223
  else:
205
224
  # nothing to invoke — skip rather than write a half-broken entry
206
225
  continue
@@ -237,12 +237,19 @@ def spawn_aisb_chat(omega_home: str | Path | None = None) -> str:
237
237
  Runs ``omega aisb chat-loop`` inside — REPL conversation with the
238
238
  AISB master agent on Claude Max OAuth. This is what bare `omega`
239
239
  attaches to (v0.19.15+).
240
+
241
+ v0.19.17 — explicitly cwd=$HOME. Without this the session inherited
242
+ the parent process's cwd, which could be the npm/_npx cache dir; if
243
+ that dir got cleaned (or `rm -rf ~/Omega` happened later), every
244
+ subprocess (including `claude -p`) crashed with
245
+ "The current working directory was deleted".
240
246
  """
241
247
  name = "AISB-chat"
242
248
  home = Path(omega_home or os.environ.get("OMEGA_HOME")
243
249
  or Path.home() / "Omega")
244
250
  omega_bin = home / "Agentik_Tools" / "bin" / "omega"
245
- spawn(name, command=f"{omega_bin} aisb chat-loop")
251
+ spawn(name, command=f"{omega_bin} aisb chat-loop",
252
+ cwd=str(Path.home()))
246
253
  return name
247
254
 
248
255
 
@@ -251,13 +258,15 @@ def spawn_hermes_chat(omega_home: str | Path | None = None) -> str:
251
258
 
252
259
  Runs ``omega hermes chat-loop`` — REPL conversation with Hermès on
253
260
  Anthropic API (separate budget from AISB's Max OAuth). This is what
254
- `omega hermes` attaches to (v0.19.15+).
261
+ `omega hermes` attaches to (v0.19.15+). Spawned with cwd=$HOME for
262
+ the same reason as ``spawn_aisb_chat`` (avoid deleted-cwd crash).
255
263
  """
256
264
  name = "Hermes-chat"
257
265
  home = Path(omega_home or os.environ.get("OMEGA_HOME")
258
266
  or Path.home() / "Omega")
259
267
  omega_bin = home / "Agentik_Tools" / "bin" / "omega"
260
- spawn(name, command=f"{omega_bin} hermes chat-loop")
268
+ spawn(name, command=f"{omega_bin} hermes chat-loop",
269
+ cwd=str(Path.home()))
261
270
  return name
262
271
 
263
272
 
@@ -215,6 +215,45 @@ def install_from_catalog(
215
215
  except (OSError, json.JSONDecodeError):
216
216
  version = ""
217
217
 
218
+ elif method == "uvx" and package:
219
+ # Python MCP servers (mcp-server-git, mcp-server-fetch, etc.) run
220
+ # via `uvx <package>` — Astral fetches + caches the package on
221
+ # first call. We don't install it locally; we just verify `uv`
222
+ # is on PATH and pre-warm the cache so the first `claude` call
223
+ # doesn't pay the cold-fetch latency.
224
+ uv = shutil.which("uv") or str(Path.home() / ".local" / "bin" / "uv")
225
+ if not Path(uv).exists():
226
+ raise RuntimeError(
227
+ "uv not found on PATH — install with "
228
+ "`curl -LsSf https://astral.sh/uv/install.sh | sh` to use uvx MCP servers"
229
+ )
230
+ # Pre-warm: `uv tool install` makes the package globally available
231
+ # as a uv tool (resolves once, ~5s) so subsequent `uvx <package>`
232
+ # invocations are instant. Failure here is non-fatal — `uvx` will
233
+ # still resolve at call time, just slower.
234
+ try:
235
+ res = subprocess.run(
236
+ [uv, "tool", "install", "--quiet", package],
237
+ check=False, capture_output=True, text=True, timeout=300,
238
+ )
239
+ # Best-effort version detect via `uv tool list`.
240
+ ls = subprocess.run(
241
+ [uv, "tool", "list"], capture_output=True, text=True, timeout=15,
242
+ )
243
+ for line in (ls.stdout or "").splitlines():
244
+ line = line.strip()
245
+ if line.startswith(package + " "):
246
+ # Format: "<package> v<version>"
247
+ parts = line.split()
248
+ if len(parts) >= 2:
249
+ version = parts[1].lstrip("v")
250
+ break
251
+ except subprocess.SubprocessError:
252
+ pass
253
+ # invoke is `uvx <package>` — sync.py renders it directly to the
254
+ # Claude .mcp.json (no local binary needed).
255
+ invoke = f"uvx:{package}"
256
+
218
257
  tool = Tool(
219
258
  name=mcp_id,
220
259
  version=version,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omega-engine"
3
- version = "0.19.15"
3
+ version = "0.19.17"
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.15
1
+ 0.19.17
@@ -18,7 +18,10 @@ catalog:
18
18
  name: Git
19
19
  description: Read/inspect git repositories
20
20
  category: core
21
- install: { method: npx, package: "@modelcontextprotocol/server-git" }
21
+ # Official MCP git server is Python — runs via uvx (Astral). The old
22
+ # npm package `@modelcontextprotocol/server-git` returns 404 — it was
23
+ # never published; only the Python `mcp-server-git` on PyPI exists.
24
+ install: { method: uvx, package: "mcp-server-git" }
22
25
  recommended: true
23
26
 
24
27
  - id: github
@@ -41,8 +44,10 @@ catalog:
41
44
  name: Higgsfield
42
45
  description: Image and video generation
43
46
  category: media
44
- install: { method: npx, package: "@higgsfield/mcp" }
45
- secrets: [HIGGSFIELD_API_KEY]
47
+ # Correct npm package name is `higgsfield-mcp` (no @ scope). The
48
+ # scoped `@higgsfield/mcp` returns 404 — was never published.
49
+ install: { method: npx, package: "higgsfield-mcp" }
50
+ secrets: [HF_API_KEY, HF_SECRET]
46
51
  recommended: false
47
52
 
48
53
  - id: playwright
@@ -63,7 +68,10 @@ catalog:
63
68
  name: Fetch
64
69
  description: Fetch and convert web content
65
70
  category: core
66
- install: { method: npx, package: "@modelcontextprotocol/server-fetch" }
71
+ # Official MCP fetch server is Python — runs via uvx. The npm
72
+ # package `@modelcontextprotocol/server-fetch` returns 404 — was
73
+ # never published. PyPI ships `mcp-server-fetch`.
74
+ install: { method: uvx, package: "mcp-server-fetch" }
67
75
  recommended: true
68
76
 
69
77
  - id: memory
@@ -98,10 +106,12 @@ catalog:
98
106
 
99
107
  - id: linear
100
108
  name: Linear
101
- description: Issues and project management
109
+ description: Issues and project management (Linear-hosted remote MCP)
102
110
  category: project
103
- install: { method: npx, package: "@linear/mcp" }
104
- secrets: [LINEAR_API_KEY]
111
+ # Linear ships an OFFICIAL remote MCP at https://mcp.linear.app/mcp,
112
+ # accessed via the `mcp-remote` npm proxy. No API key in env —
113
+ # OAuth happens in-browser the first time Claude connects.
114
+ install: { method: npx, package: "mcp-remote", args: ["https://mcp.linear.app/mcp"] }
105
115
  recommended: false
106
116
 
107
117
  - id: sentry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentikos/omega-os",
3
- "version": "0.19.15",
3
+ "version": "0.19.17",
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"