@agentikos/omega-os 0.19.42 → 0.19.43
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.
- package/bootstrap/lib/__pycache__/llm-clis.cpython-313.pyc +0 -0
- package/bootstrap/lib/common.sh +6 -0
- package/bootstrap/lib/llm-clis.py +6 -0
- package/bootstrap/lib/manifest-helpers.py +110 -0
- package/bootstrap/lib/steps.sh +230 -26
- package/bootstrap/templates/aisb/CLAUDE.md +13 -0
- package/install.sh +8 -2
- package/omega/Agentik_Engine/omega_engine/__init__.py +1 -1
- package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cli.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/hermes.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/paperclip_bridge.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/personas.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/provider.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tmux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tui.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/cli.py +44 -7
- package/omega/Agentik_Engine/omega_engine/hermes.py +43 -1
- package/omega/Agentik_Engine/omega_engine/paperclip_bridge.py +22 -0
- package/omega/Agentik_Engine/omega_engine/personas.py +11 -3
- package/omega/Agentik_Engine/omega_engine/provider.py +18 -3
- package/omega/Agentik_Engine/omega_engine/tmux.py +41 -21
- package/omega/Agentik_Engine/omega_engine/tui.py +8 -7
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_install_steps_v0_19_43.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_steps_v0_19_43.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_palette.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_palette.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_v19_43_fixes.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_v19_43_fixes.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/test_install_steps_v0_19_43.py +242 -0
- package/omega/Agentik_Engine/tests/test_installer_wiring.py +128 -1
- package/omega/Agentik_Engine/tests/test_tmux_palette.py +51 -0
- package/omega/Agentik_Engine/tests/test_v19_43_fixes.py +265 -0
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/docs/AUDIT-V0.19.43.md +92 -0
- package/omega/Agentik_SSOT/rules/audit-gates.md +2 -2
- package/omega/Agentik_SSOT/rules/constitution.md +18 -0
- package/omega/Agentik_SSOT/rules/three-laws.md +2 -0
- package/package.json +1 -1
|
@@ -271,6 +271,31 @@ def cmd_doctor(args: argparse.Namespace) -> int:
|
|
|
271
271
|
except Exception as exc: # noqa: BLE001
|
|
272
272
|
line("warn", f"provider auth check failed: {exc}")
|
|
273
273
|
|
|
274
|
+
# v0.19.43 — Hermès budget-isolation check. Hermès SHOULD use its own
|
|
275
|
+
# paid Anthropic key (ANTHROPIC_API_KEY_HERMES) so its calls don't
|
|
276
|
+
# share the AISB Max OAuth pool. See omega_engine/hermes.py::build_env
|
|
277
|
+
# for the 3-tier fallback. When path (3) — Max OAuth — is the live
|
|
278
|
+
# path, surface it here so the operator knows isolation is OFF.
|
|
279
|
+
try:
|
|
280
|
+
from omega_engine.vault import vault_read as _vread
|
|
281
|
+
_hermes_vault_key = (_vread(home, "ANTHROPIC_API_KEY_HERMES") or "").strip()
|
|
282
|
+
_hermes_env_key = (_os.environ.get("ANTHROPIC_API_KEY") or "").strip()
|
|
283
|
+
if _hermes_vault_key:
|
|
284
|
+
line("ok", "Hermès budget isolation: vault key present "
|
|
285
|
+
"(ANTHROPIC_API_KEY_HERMES)")
|
|
286
|
+
elif _hermes_env_key:
|
|
287
|
+
line("warn", "Hermès budget isolation: shell env key only "
|
|
288
|
+
"(ANTHROPIC_API_KEY) — works but couples Hermès to "
|
|
289
|
+
"whatever the env points at. Consider wiring the "
|
|
290
|
+
"vault key for permanent isolation.")
|
|
291
|
+
else:
|
|
292
|
+
line("warn", "Hermès budget isolation OFF — no vault key, no env "
|
|
293
|
+
"key. Hermès will fall back to Max OAuth (charges "
|
|
294
|
+
"your Max sub). Wire with: "
|
|
295
|
+
"`omega vault write ANTHROPIC_API_KEY_HERMES sk-ant-...`")
|
|
296
|
+
except Exception as exc: # noqa: BLE001
|
|
297
|
+
line("warn", f"Hermès isolation check failed: {exc}")
|
|
298
|
+
|
|
274
299
|
# 6c1. LLM CLIs installed on the host
|
|
275
300
|
section("llm clis")
|
|
276
301
|
import shutil as _shu
|
|
@@ -2885,8 +2910,11 @@ def cmd_aisb(args: argparse.Namespace) -> int:
|
|
|
2885
2910
|
from omega_engine import tmux
|
|
2886
2911
|
sub = getattr(args, "aisb_cmd", None) or "chat"
|
|
2887
2912
|
if sub in ("chat", None):
|
|
2913
|
+
# v0.19.43 — AISB-chat is now a WINDOW inside the Omega master
|
|
2914
|
+
# session (Omega:aisb), not a standalone session. spawn_aisb_chat
|
|
2915
|
+
# returns "Omega:aisb" so we pass that as the switch target.
|
|
2888
2916
|
return _attach_or_spawn_chat(
|
|
2889
|
-
"
|
|
2917
|
+
"Omega:aisb",
|
|
2890
2918
|
spawn_fn=tmux.spawn_aisb_chat,
|
|
2891
2919
|
label="AISB master (Claude Code on Max OAuth)",
|
|
2892
2920
|
)
|
|
@@ -3175,14 +3203,14 @@ def _legacy_fzf_menu(_args: argparse.Namespace) -> int:
|
|
|
3175
3203
|
subprocess.run(["tmux", "kill-session", "-t", "Omega"])
|
|
3176
3204
|
return 0
|
|
3177
3205
|
|
|
3178
|
-
# Chat sessions —
|
|
3206
|
+
# Chat sessions — windows inside Omega master (v0.19.43).
|
|
3179
3207
|
if action == "open:aisb":
|
|
3180
|
-
tmux.spawn_aisb_chat(HOME, force_replace=False)
|
|
3181
|
-
subprocess.run(["tmux", "switch-client", "-t",
|
|
3208
|
+
target = tmux.spawn_aisb_chat(HOME, force_replace=False)
|
|
3209
|
+
subprocess.run(["tmux", "switch-client", "-t", target])
|
|
3182
3210
|
continue
|
|
3183
3211
|
if action == "open:hermes":
|
|
3184
|
-
tmux.spawn_hermes_chat(HOME, force_replace=False)
|
|
3185
|
-
subprocess.run(["tmux", "switch-client", "-t",
|
|
3212
|
+
target = tmux.spawn_hermes_chat(HOME, force_replace=False)
|
|
3213
|
+
subprocess.run(["tmux", "switch-client", "-t", target])
|
|
3186
3214
|
continue
|
|
3187
3215
|
|
|
3188
3216
|
# Inline actions — run in the menu pane, prompt to return.
|
|
@@ -3494,6 +3522,13 @@ def cmd_switch(args: argparse.Namespace) -> int:
|
|
|
3494
3522
|
"qwen_code": "qwen",
|
|
3495
3523
|
"continue_dev": "cn",
|
|
3496
3524
|
"aider": "aider",
|
|
3525
|
+
# v0.19.43 — providers installable via the CLI catalog that were
|
|
3526
|
+
# missing from `omega switch`. Each maps to its bin_name from
|
|
3527
|
+
# bootstrap/lib/llm-clis.py::_CATALOG.
|
|
3528
|
+
"glm_sdk": "zhipuai", # Python SDK — no binary, kept for completeness
|
|
3529
|
+
"ollama": "ollama",
|
|
3530
|
+
"lm_studio": "lms",
|
|
3531
|
+
"gh_copilot": "gh", # extension on top of gh
|
|
3497
3532
|
}
|
|
3498
3533
|
if not getattr(args, "provider", None):
|
|
3499
3534
|
print(f" active provider: {_active_provider()}")
|
|
@@ -3598,10 +3633,12 @@ def cmd_hermes(args: argparse.Namespace) -> int:
|
|
|
3598
3633
|
|
|
3599
3634
|
# v0.19.15 — `omega hermes` with no subcommand opens the Hermès chat
|
|
3600
3635
|
# tmux session. Same UX as bare `omega` → AISB chat, but for L2.
|
|
3636
|
+
# v0.19.43 — Hermes-chat is now a WINDOW inside the Omega master
|
|
3637
|
+
# session (Omega:hermes); spawn_hermes_chat returns that ref.
|
|
3601
3638
|
if sub is None or sub == "chat":
|
|
3602
3639
|
from omega_engine import tmux as _tx
|
|
3603
3640
|
return _attach_or_spawn_chat(
|
|
3604
|
-
"
|
|
3641
|
+
"Omega:hermes",
|
|
3605
3642
|
spawn_fn=_tx.spawn_hermes_chat,
|
|
3606
3643
|
label="Hermès meta-companion chat",
|
|
3607
3644
|
)
|
|
@@ -262,6 +262,39 @@ def build_env(
|
|
|
262
262
|
calls through your Max sub.
|
|
263
263
|
|
|
264
264
|
Caller env wins via ``extra``.
|
|
265
|
+
|
|
266
|
+
──────────────────────────────────────────────────────────────────
|
|
267
|
+
IMPORTANT — Hermès credential resolution (v0.19.43 clarification)
|
|
268
|
+
──────────────────────────────────────────────────────────────────
|
|
269
|
+
|
|
270
|
+
Hermès SHOULD use ANTHROPIC_API_KEY_HERMES from the vault for budget
|
|
271
|
+
isolation from the AISB Max OAuth. The 3-tier fallback below is a
|
|
272
|
+
SAFETY NET for the edge case where the vault key is missing but the
|
|
273
|
+
operator still wants Hermès to work (during initial setup, debugging,
|
|
274
|
+
or a one-off command before they have wired the paid key).
|
|
275
|
+
|
|
276
|
+
Fallback order (first non-empty wins):
|
|
277
|
+
|
|
278
|
+
1. ANTHROPIC_API_KEY_HERMES (vault) ← preferred, isolated budget
|
|
279
|
+
2. ANTHROPIC_API_KEY (shell env) ← shared env, semi-isolated
|
|
280
|
+
3. CLAUDE_CODE_OAUTH_TOKEN (Max OAuth) ← LAST RESORT, breaks isolation
|
|
281
|
+
|
|
282
|
+
Hierarchy intent:
|
|
283
|
+
* Path (1) is the contract Hermès was designed to honor.
|
|
284
|
+
* Path (2) lets a developer ``ANTHROPIC_API_KEY=sk-... omega hermes``
|
|
285
|
+
without writing to the vault.
|
|
286
|
+
* Path (3) preserves "Hermès still works on a fresh install before
|
|
287
|
+
the user has wired their key" — at the cost of charging the user's
|
|
288
|
+
Max sub for what should be a paid-API call.
|
|
289
|
+
|
|
290
|
+
``omega doctor`` warns when Hermès would fall through to path (3) in
|
|
291
|
+
practice (vault empty AND ``ANTHROPIC_API_KEY`` unset). The persistent
|
|
292
|
+
Hermès chat (``step_hermes_session`` in bootstrap/lib/steps.sh) SKIPS
|
|
293
|
+
its spawn entirely on missing vault key — it does NOT fall through to
|
|
294
|
+
Max OAuth for 24/7 runtime use, because an always-on Max-billed Hermès
|
|
295
|
+
is rarely what the operator wants. Only the interactive on-demand
|
|
296
|
+
``omega hermes`` path uses this fallback chain.
|
|
297
|
+
──────────────────────────────────────────────────────────────────
|
|
265
298
|
"""
|
|
266
299
|
env = {**os.environ}
|
|
267
300
|
# 1. Vault first.
|
|
@@ -279,10 +312,19 @@ def build_env(
|
|
|
279
312
|
if not key:
|
|
280
313
|
key = (os.environ.get("ANTHROPIC_API_KEY") or "").strip()
|
|
281
314
|
# 3. Last-resort OAuth (preserves the old behaviour without making
|
|
282
|
-
# Hermès depend on it).
|
|
315
|
+
# Hermès depend on it). When this branch fires, log a warning to
|
|
316
|
+
# stderr so the operator knows budget isolation is OFF — Hermès is
|
|
317
|
+
# now sharing the Max OAuth pool with AISB+Oracle+Workers. The
|
|
318
|
+
# `omega doctor` `personas` / `providers` section will also surface
|
|
319
|
+
# this drift.
|
|
283
320
|
if not key:
|
|
284
321
|
try:
|
|
285
322
|
env["CLAUDE_CODE_OAUTH_TOKEN"] = claude_oauth_token(creds_path)
|
|
323
|
+
import sys as _sys
|
|
324
|
+
print(" ⚠️ Hermès budget isolation OFF — falling back to "
|
|
325
|
+
"Max OAuth. Run `omega vault write "
|
|
326
|
+
"ANTHROPIC_API_KEY_HERMES sk-ant-...` to restore.",
|
|
327
|
+
file=_sys.stderr)
|
|
286
328
|
except Exception: # noqa: BLE001
|
|
287
329
|
pass
|
|
288
330
|
if key:
|
|
@@ -292,6 +292,28 @@ def send_heartbeat(
|
|
|
292
292
|
return True
|
|
293
293
|
|
|
294
294
|
|
|
295
|
+
def heartbeat_on_spawn(agent_id: str, project: str | None = None) -> None:
|
|
296
|
+
"""v0.19.43 — call this from spawn_worker / spawn_oracle right after
|
|
297
|
+
the tmux session is created. Drops a one-shot heartbeat to Paperclip
|
|
298
|
+
so the dashboard's live-agent indicator wakes up immediately instead
|
|
299
|
+
of waiting for the agent's first explicit heartbeat call.
|
|
300
|
+
|
|
301
|
+
Never raises — if Paperclip is not installed or not running, this is
|
|
302
|
+
a no-op. Safe to call from any spawn path.
|
|
303
|
+
"""
|
|
304
|
+
try:
|
|
305
|
+
hb = Heartbeat(
|
|
306
|
+
agent_id=agent_id,
|
|
307
|
+
project=project or "",
|
|
308
|
+
session=os.environ.get("TMUX_SESSION", ""),
|
|
309
|
+
status="alive",
|
|
310
|
+
summary="spawned",
|
|
311
|
+
)
|
|
312
|
+
send_heartbeat(hb)
|
|
313
|
+
except Exception:
|
|
314
|
+
pass # silent fallback — bridge is optional infrastructure
|
|
315
|
+
|
|
316
|
+
|
|
295
317
|
# ---------------------------------------------------------------------------
|
|
296
318
|
# Registration — write Paperclip's agent + company config from OmegaOS
|
|
297
319
|
# ---------------------------------------------------------------------------
|
|
@@ -55,6 +55,14 @@ _LLM_PERSONA_PATHS: dict[str, list[str]] = {
|
|
|
55
55
|
"continue_dev": [".continue/CONTEXT.md"],
|
|
56
56
|
"aider": ["CONVENTIONS.md"],
|
|
57
57
|
"hermes": ["HERMES.md"],
|
|
58
|
+
# v0.19.43 — 4 CLIs were installable but had no persona file. Without
|
|
59
|
+
# this mapping, write_all_personas() silently skipped them and the
|
|
60
|
+
# CLI would launch with no Omega context. Each maps to the closest
|
|
61
|
+
# convention for that CLI.
|
|
62
|
+
"glm_sdk": ["GLM.md"], # Zhipu GLM SDK — bespoke marker
|
|
63
|
+
"ollama": ["OLLAMA.md"], # Ollama local runtime
|
|
64
|
+
"lm_studio": ["LM_STUDIO.md"], # LM Studio local
|
|
65
|
+
"gh_copilot": ["CLAUDE.md"], # gh copilot piggy-backs on CLAUDE.md
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
|
|
@@ -98,7 +106,7 @@ You sit at L4 or L5 depending on context.
|
|
|
98
106
|
$OMEGA_HOME = ~/Omega
|
|
99
107
|
├── Agentik_Engine/ ← Python engine (omega CLI)
|
|
100
108
|
├── Agentik_SSOT/ ← source of truth
|
|
101
|
-
│ ├── skills/ ←
|
|
109
|
+
│ ├── skills/ ← 18 audits + orchestrators + /newcmd
|
|
102
110
|
│ ├── agents/aisb/ ← 13 AISB persona files
|
|
103
111
|
│ ├── personas/OMEGAOS-CONTEXT.md ← THIS FILE
|
|
104
112
|
│ ├── docs/LAYERS.md ← formal L1-L5 architecture
|
|
@@ -122,11 +130,11 @@ $OMEGA_HOME = ~/Omega
|
|
|
122
130
|
| Status / health | `omega doctor` / `omega status` |
|
|
123
131
|
| Session manager (tmux) | `omega` (no args) |
|
|
124
132
|
|
|
125
|
-
## Quality Arsenal (
|
|
133
|
+
## Quality Arsenal (18 forensic audits)
|
|
126
134
|
|
|
127
135
|
`/codeaudit /flowaudit /uiuxaudit /debugaudit /featureaudit /perfaudit
|
|
128
136
|
/secaudit /a11yaudit /seoaudit /dataaudit /apiaudit /copyaudit /dxaudit
|
|
129
|
-
/motionaudit /automationaudit /logicaudit /retentionaudit`
|
|
137
|
+
/motionaudit /automationaudit /logicaudit /retentionaudit /refontaudit`
|
|
130
138
|
|
|
131
139
|
Each: Gestalt clarity gate, Popper falsification, hinge point 10x
|
|
132
140
|
scrutiny, auto-fix, auto-re-audit, scored /100.
|
|
@@ -440,13 +440,28 @@ class _OpenAICompatProvider:
|
|
|
440
440
|
self._base_url = base_url or self._default_base_url
|
|
441
441
|
|
|
442
442
|
def _resolve_key(self) -> str:
|
|
443
|
-
|
|
444
|
-
if
|
|
443
|
+
# Constructor-injected key always wins.
|
|
444
|
+
if self._api_key:
|
|
445
|
+
return self._api_key
|
|
446
|
+
# v0.19.43 — try the encrypted vault first, then fall back to env.
|
|
447
|
+
# The vault is where step_providers stores api keys provided via
|
|
448
|
+
# the install manifest; env is the legacy / fallback path.
|
|
449
|
+
try:
|
|
450
|
+
from omega_engine.vault import vault_read
|
|
451
|
+
from pathlib import Path
|
|
452
|
+
home = Path(os.environ.get("OMEGA_HOME", str(Path.home() / "Omega")))
|
|
453
|
+
v = vault_read(home, self._env_var)
|
|
454
|
+
if v and v.strip():
|
|
455
|
+
return v.strip()
|
|
456
|
+
except Exception:
|
|
457
|
+
pass
|
|
458
|
+
key = os.environ.get(self._env_var)
|
|
459
|
+
if not key or not key.strip():
|
|
445
460
|
raise RuntimeError(
|
|
446
461
|
f"{type(self).__name__} requires an API key. "
|
|
447
462
|
f"Pass api_key=... or set {self._env_var} in the environment."
|
|
448
463
|
)
|
|
449
|
-
return key
|
|
464
|
+
return key.strip()
|
|
450
465
|
|
|
451
466
|
def _build_messages(self, req: AgentRequest) -> list[dict[str, str]]:
|
|
452
467
|
prompt = req.prompt
|
|
@@ -385,30 +385,37 @@ def spawn_chat_in_omega(
|
|
|
385
385
|
|
|
386
386
|
def spawn_aisb_chat(omega_home: str | Path | None = None,
|
|
387
387
|
force_replace: bool = False) -> str:
|
|
388
|
-
"""Spawn the AISB master chat
|
|
388
|
+
"""Spawn the AISB master chat as a WINDOW inside the Omega master session.
|
|
389
389
|
|
|
390
|
-
v0.19.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
390
|
+
v0.19.43 — refactored to use the window-based pattern via
|
|
391
|
+
:func:`spawn_chat_in_omega` so AISB-chat lives UNDER the persistent
|
|
392
|
+
Omega master session (single tmux lifecycle, detach returns to the
|
|
393
|
+
Omega menu) instead of as a standalone tmux session. This honors the
|
|
394
|
+
v0.19.31+ design promise: "everything under Omega".
|
|
395
|
+
|
|
396
|
+
Returns the full tmux ref ``"Omega:aisb"`` — callers can use it
|
|
397
|
+
directly with ``tmux switch-client -t`` / ``tmux attach -t``.
|
|
395
398
|
|
|
396
399
|
Auth: Claude Max OAuth (inherited from the user's shell env, no env
|
|
397
400
|
override needed — `claude` reads `~/.claude/.credentials.json`).
|
|
398
401
|
|
|
399
|
-
``force_replace=True`` kills any existing
|
|
400
|
-
the
|
|
401
|
-
|
|
402
|
+
``force_replace=True`` kills any existing aisb window first — used
|
|
403
|
+
by the menu's "+ New" action so the user gets a fresh window each
|
|
404
|
+
time.
|
|
402
405
|
"""
|
|
403
|
-
name = "AISB-chat"
|
|
404
406
|
home = Path(omega_home or os.environ.get("OMEGA_HOME")
|
|
405
407
|
or Path.home() / "Omega")
|
|
408
|
+
# Ensure the Omega master session exists — spawn_chat_in_omega tries
|
|
409
|
+
# to do this too, but its fallback uses ctx_dir.parent.parent.parent
|
|
410
|
+
# which doesn't always resolve to OMEGA_HOME. Be explicit.
|
|
411
|
+
spawn_omega_master(home)
|
|
406
412
|
persona = home / "Agentik_SSOT" / "agents" / "aisb" / "CLAUDE.md"
|
|
407
413
|
ctx_dir = _ensure_chat_context_dir(home, "aisb-master", persona)
|
|
408
|
-
|
|
409
|
-
|
|
414
|
+
spawn_chat_in_omega(
|
|
415
|
+
"aisb", ctx_dir=ctx_dir, run_command="claude",
|
|
410
416
|
force_replace=force_replace,
|
|
411
417
|
)
|
|
418
|
+
return "Omega:aisb"
|
|
412
419
|
|
|
413
420
|
|
|
414
421
|
def spawn_omega_master(omega_home: str | Path | None = None) -> str:
|
|
@@ -448,19 +455,31 @@ def spawn_omega_master(omega_home: str | Path | None = None) -> str:
|
|
|
448
455
|
|
|
449
456
|
def spawn_hermes_chat(omega_home: str | Path | None = None,
|
|
450
457
|
force_replace: bool = False) -> str:
|
|
451
|
-
"""Spawn the Hermès chat
|
|
452
|
-
|
|
458
|
+
"""Spawn the Hermès chat as a WINDOW inside the Omega master session.
|
|
459
|
+
|
|
460
|
+
v0.19.43 — refactored to use the window-based pattern via
|
|
461
|
+
:func:`spawn_chat_in_omega` to match :func:`spawn_aisb_chat` and the
|
|
462
|
+
menu TUI (single tmux lifecycle, detach returns to the Omega menu).
|
|
463
|
+
|
|
464
|
+
Credential isolation is PRESERVED — Hermès reads
|
|
465
|
+
``ANTHROPIC_API_KEY_HERMES`` from the vault to keep its budget
|
|
466
|
+
isolated from the AISB Max OAuth. If the vault key is missing we
|
|
467
|
+
fall back to ``ANTHROPIC_API_KEY`` in the shell env, and finally to
|
|
468
|
+
plain ``claude`` (Max OAuth) with a marker file dropped in the
|
|
469
|
+
context dir so the operator sees the message after attaching.
|
|
453
470
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
``ANTHROPIC_API_KEY`` (from vault) before launching `claude`. Same
|
|
457
|
-
shell-stays-alive pattern.
|
|
471
|
+
Returns ``"Omega:hermes"`` so callers can use it with
|
|
472
|
+
``tmux switch-client -t`` / ``tmux attach -t`` directly.
|
|
458
473
|
"""
|
|
459
|
-
name = "Hermes-chat"
|
|
460
474
|
home = Path(omega_home or os.environ.get("OMEGA_HOME")
|
|
461
475
|
or Path.home() / "Omega")
|
|
476
|
+
# Ensure the Omega master session exists — see spawn_aisb_chat.
|
|
477
|
+
spawn_omega_master(home)
|
|
462
478
|
persona = home / "Agentik_SSOT" / "docs" / "LAYERS.md"
|
|
463
479
|
ctx_dir = _ensure_chat_context_dir(home, "hermes", persona)
|
|
480
|
+
# Credential isolation — vault key first, env fallback, Max OAuth
|
|
481
|
+
# last-resort. MUST stay in this function: the budget-isolation
|
|
482
|
+
# contract belongs to Hermès, not to the generic spawn helper.
|
|
464
483
|
try:
|
|
465
484
|
from omega_engine.vault import vault_read
|
|
466
485
|
api_key = (vault_read(home, "ANTHROPIC_API_KEY_HERMES") or "").strip()
|
|
@@ -479,10 +498,11 @@ def spawn_hermes_chat(omega_home: str | Path | None = None,
|
|
|
479
498
|
else:
|
|
480
499
|
# Single-line shell statement; send-keys passes it as-is.
|
|
481
500
|
run_cmd = f"ANTHROPIC_API_KEY={api_key} claude"
|
|
482
|
-
|
|
483
|
-
|
|
501
|
+
spawn_chat_in_omega(
|
|
502
|
+
"hermes", ctx_dir=ctx_dir, run_command=run_cmd,
|
|
484
503
|
force_replace=force_replace,
|
|
485
504
|
)
|
|
505
|
+
return "Omega:hermes"
|
|
486
506
|
|
|
487
507
|
|
|
488
508
|
# ---------------------------------------------------------------------------
|
|
@@ -67,7 +67,7 @@ except ImportError:
|
|
|
67
67
|
CATEGORIES: list[tuple[str, str]] = [
|
|
68
68
|
("chat", "Chat — AISB & Hermès"),
|
|
69
69
|
("projects", "Projects — Genesis & shells"),
|
|
70
|
-
("audits", "Audits — Quality Arsenal (
|
|
70
|
+
("audits", "Audits — Quality Arsenal (18 forensic)"),
|
|
71
71
|
("missions", "Missions — run with verified completion"),
|
|
72
72
|
("sessions", "Sessions — live tmux sessions"),
|
|
73
73
|
("accounts", "Accounts — Claude Max + provider auth"),
|
|
@@ -135,22 +135,23 @@ def dispatch_slash(line: str) -> CommandResult:
|
|
|
135
135
|
if cmd in ("detach", "d"):
|
|
136
136
|
return CommandResult(detach=True)
|
|
137
137
|
|
|
138
|
-
# Chat sessions
|
|
138
|
+
# Chat sessions — v0.19.43 are now WINDOWS inside the Omega master
|
|
139
|
+
# session (Omega:aisb, Omega:hermes), not standalone sessions.
|
|
139
140
|
if cmd == "aisb" or (cmd == "chat" and rest and rest[0] == "aisb"):
|
|
140
141
|
from omega_engine import tmux as _tx
|
|
141
|
-
_tx.spawn_aisb_chat(Path(os.environ.get(
|
|
142
|
+
target = _tx.spawn_aisb_chat(Path(os.environ.get(
|
|
142
143
|
"OMEGA_HOME", str(Path.home() / "Omega"))))
|
|
143
144
|
return CommandResult(
|
|
144
145
|
text=" AISB-chat spawned — switching client…",
|
|
145
|
-
session_jump=
|
|
146
|
+
session_jump=target,
|
|
146
147
|
)
|
|
147
148
|
if cmd == "hermes" or (cmd == "chat" and rest and rest[0] == "hermes"):
|
|
148
149
|
from omega_engine import tmux as _tx
|
|
149
|
-
_tx.spawn_hermes_chat(Path(os.environ.get(
|
|
150
|
+
target = _tx.spawn_hermes_chat(Path(os.environ.get(
|
|
150
151
|
"OMEGA_HOME", str(Path.home() / "Omega"))))
|
|
151
152
|
return CommandResult(
|
|
152
153
|
text=" Hermes-chat spawned — switching client…",
|
|
153
|
-
session_jump=
|
|
154
|
+
session_jump=target,
|
|
154
155
|
)
|
|
155
156
|
|
|
156
157
|
# Provider hot-swap
|
|
@@ -164,7 +165,7 @@ def dispatch_slash(line: str) -> CommandResult:
|
|
|
164
165
|
if rest:
|
|
165
166
|
return CommandResult(text=_run_omega("audit", *rest))
|
|
166
167
|
return CommandResult(text=(
|
|
167
|
-
" Quality Arsenal —
|
|
168
|
+
" Quality Arsenal — 18 forensic audits:\n"
|
|
168
169
|
" /codeaudit /uiuxaudit /flowaudit /debugaudit\n"
|
|
169
170
|
" /featureaudit /perfaudit /secaudit /a11yaudit\n"
|
|
170
171
|
" /seoaudit /dataaudit /apiaudit /copyaudit\n"
|
|
Binary file
|
|
Binary file
|
package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313-pytest-8.4.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
package/omega/Agentik_Engine/tests/__pycache__/test_tmux_palette.cpython-313-pytest-8.4.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|