@agentikos/omega-os 0.19.13 → 0.19.15
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/common.sh +12 -6
- package/bootstrap/lib/steps.sh +84 -21
- 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__/tmux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/cli.py +124 -3
- package/omega/Agentik_Engine/omega_engine/hermes.py +34 -8
- package/omega/Agentik_Engine/omega_engine/tmux.py +19 -4
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.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/test_hermes_and_ua.py +56 -8
- package/omega/Agentik_Engine/tests/test_install_ux.py +6 -1
- package/omega/Agentik_Engine/tests/test_installer_wiring.py +16 -11
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/docs/LAYERS.md +130 -73
- package/package.json +1 -1
package/bootstrap/lib/common.sh
CHANGED
|
@@ -550,13 +550,19 @@ except Exception: print("unknown")' 2>/dev/null)" || readiness="unknown"
|
|
|
550
550
|
printf ' %s elapsed %s\n' "$bar" "$(printf '%02d:%02d' "$mm" "$ss")"
|
|
551
551
|
printf ' %s\n' "$bar"
|
|
552
552
|
printf ' %s %snext steps%s\n' "$bar" "$C_BOLD" "$C_RST"
|
|
553
|
-
printf " %s 1.
|
|
553
|
+
printf " %s 1. ${C_BOLD}source ~/.zshrc${C_RST} ${C_DIM}or open a new shell${C_RST}\n" "$bar"
|
|
554
|
+
printf ' %s 2. %somega%s %stalk to AISB (master agent, Max OAuth)%s\n' \
|
|
555
|
+
"$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
|
|
556
|
+
printf ' %s 3. %somega hermes%s %stalk to Hermès (meta-companion, Anthropic API)%s\n' \
|
|
557
|
+
"$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
|
|
558
|
+
printf ' %s 4. %somega account login%s %swire your Claude Max OAuth%s\n' \
|
|
559
|
+
"$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
|
|
560
|
+
printf ' %s 5. %somega run "hello"%s %sfirst verified mission%s\n' \
|
|
561
|
+
"$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
|
|
562
|
+
printf ' %s 6. %somega menu%s %sinteractive whiptail picker%s\n' \
|
|
563
|
+
"$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
|
|
564
|
+
printf ' %s 7. %somega doctor%s %sfull health check%s\n' \
|
|
554
565
|
"$bar" "$C_BOLD" "$C_RST" "$C_DIM" "$C_RST"
|
|
555
|
-
printf " %s 2. open a new shell ${C_DIM}(or \`source ~/.zshrc\`)${C_RST}\n" "$bar"
|
|
556
|
-
printf ' %s 3. %somega status%s every task + derived state\n' "$bar" "$C_BOLD" "$C_RST"
|
|
557
|
-
printf ' %s 4. %somega account list%s wire your Claude Max OAuth\n' "$bar" "$C_BOLD" "$C_RST"
|
|
558
|
-
printf ' %s 5. %somega run "hello"%s first verified mission\n' "$bar" "$C_BOLD" "$C_RST"
|
|
559
|
-
printf ' %s 6. %somega%s interactive menu (whiptail)\n' "$bar" "$C_BOLD" "$C_RST"
|
|
560
566
|
printf ' %s\n' "$bar"
|
|
561
567
|
printf ' %s %ssessions%s all Omega/Claude/LLM sessions run inside tmux\n' \
|
|
562
568
|
"$bar" "$C_BOLD" "$C_RST"
|
package/bootstrap/lib/steps.sh
CHANGED
|
@@ -448,10 +448,11 @@ PY
|
|
|
448
448
|
step_mcp() {
|
|
449
449
|
local catalog="$OMEGA_HOME/Agentik_SSOT/mcp/mcp-catalog.yaml"
|
|
450
450
|
[ -f "$catalog" ] || { err "MCP catalog missing: $catalog"; return 1; }
|
|
451
|
-
#
|
|
452
|
-
#
|
|
451
|
+
# The catalog YAML uses ``catalog:`` then `` - id: <name>`` (2-space
|
|
452
|
+
# indent). The old pattern ``^- id:`` matched at column 0 and counted
|
|
453
|
+
# zero. Allow leading whitespace.
|
|
453
454
|
local _mcp_count
|
|
454
|
-
_mcp_count="$(grep -
|
|
455
|
+
_mcp_count="$(grep -cE '^[[:space:]]*- id:' "$catalog" 2>/dev/null || true)"
|
|
455
456
|
_mcp_count="$(printf '%s' "$_mcp_count" | tr -d '\n ' )"
|
|
456
457
|
info "MCP catalog present (${_mcp_count:-?} entries)"
|
|
457
458
|
|
|
@@ -865,37 +866,55 @@ _claude_plugins_prompt_checklist() {
|
|
|
865
866
|
|
|
866
867
|
# --- 50 -----------------------------------------------------------------------
|
|
867
868
|
step_telegram() {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
869
|
+
# Two distinct bots in the corrected v0.19.14 model:
|
|
870
|
+
# * AISB bot (token A) — REQUIRED. Runs missions on Max OAuth.
|
|
871
|
+
# * Hermès bot (token H) — OPTIONAL. Meta-companion on Anthropic API.
|
|
872
|
+
# And one optional API key (ANTHROPIC_API_KEY_HERMES) gating Hermès AI.
|
|
873
|
+
# Old `TELEGRAM_TOKEN` is treated as the AISB token (back-compat).
|
|
874
|
+
local aisb_token hermes_token anthropic_key chat_id
|
|
875
|
+
|
|
876
|
+
# 1. AISB bot — required.
|
|
877
|
+
info "AISB bot — required. Talks to OmegaOS on Claude Max OAuth."
|
|
878
|
+
ask aisb_token "AISB Telegram bot token (from @BotFather)" "${TELEGRAM_TOKEN_AISB:-${TELEGRAM_TOKEN:-}}"
|
|
879
|
+
if [ -z "$aisb_token" ]; then
|
|
880
|
+
err "an AISB bot token is required (or install with --profile minimal)"
|
|
872
881
|
return 1
|
|
873
882
|
fi
|
|
874
883
|
if have curl; then
|
|
875
|
-
if ! curl -s "https://api.telegram.org/bot${
|
|
876
|
-
err "Telegram token rejected by the API"
|
|
884
|
+
if ! curl -s "https://api.telegram.org/bot${aisb_token}/getMe" | grep -q '"ok":true'; then
|
|
885
|
+
err "AISB Telegram token rejected by the API"
|
|
877
886
|
return 1
|
|
878
887
|
fi
|
|
879
888
|
fi
|
|
889
|
+
|
|
880
890
|
local sec="$OMEGA_HOME/Agentik_Extra/etc/secrets"
|
|
881
891
|
mkdir -p "$sec"
|
|
882
|
-
|
|
892
|
+
# Write a single .env file consumed by both daemons; vault still holds
|
|
893
|
+
# the canonical encrypted copy.
|
|
894
|
+
{
|
|
895
|
+
echo "# Generated by OmegaOS install — do not edit by hand."
|
|
896
|
+
echo "# AISB bot (OmegaOS-native, Claude Max OAuth)"
|
|
897
|
+
printf 'TELEGRAM_TOKEN_AISB=%s\n' "$aisb_token"
|
|
898
|
+
printf 'TELEGRAM_TOKEN=%s\n' "$aisb_token" # back-compat alias
|
|
899
|
+
} > "$sec/telegram.env"
|
|
883
900
|
chmod 600 "$sec/telegram.env"
|
|
884
|
-
|
|
885
|
-
python3 - "$OMEGA_HOME" "$token" <<'PY' || true
|
|
901
|
+
python3 - "$OMEGA_HOME" "$aisb_token" <<'PY' || true
|
|
886
902
|
import sys
|
|
887
903
|
from pathlib import Path
|
|
888
904
|
home = Path(sys.argv[1])
|
|
889
905
|
sys.path.insert(0, str(home / "Agentik_Engine"))
|
|
890
906
|
try:
|
|
891
907
|
from omega_engine.vault import vault_write
|
|
908
|
+
# Write under BOTH names so old code paths reading TELEGRAM_TOKEN keep
|
|
909
|
+
# working without a separate migration step.
|
|
910
|
+
vault_write(home, "TELEGRAM_TOKEN_AISB", sys.argv[2])
|
|
892
911
|
vault_write(home, "TELEGRAM_TOKEN", sys.argv[2])
|
|
893
912
|
except Exception as exc:
|
|
894
913
|
print(f"(vault write skipped: {exc})")
|
|
895
914
|
PY
|
|
896
|
-
ok "Telegram bot validated and wired"
|
|
915
|
+
ok "AISB Telegram bot validated and wired"
|
|
897
916
|
|
|
898
|
-
#
|
|
917
|
+
# 2. AISB group chat id — same as before (scopes missions to a group).
|
|
899
918
|
chat_id="$(python3 - "$MANIFEST" <<'PY' 2>/dev/null || true
|
|
900
919
|
import sys, yaml
|
|
901
920
|
try:
|
|
@@ -906,14 +925,11 @@ except Exception:
|
|
|
906
925
|
print('')
|
|
907
926
|
PY
|
|
908
927
|
)"
|
|
909
|
-
chat_id="$
|
|
928
|
+
chat_id="$(printf '%s' "$chat_id" | tr -d '\n ')"
|
|
910
929
|
if [ -z "$chat_id" ]; then
|
|
911
|
-
ask chat_id "
|
|
930
|
+
ask chat_id "AISB forum group chat id (e.g. -1001234567890; blank to set later)" ""
|
|
912
931
|
fi
|
|
913
932
|
if [ -n "$chat_id" ]; then
|
|
914
|
-
python3 "$OMEGA_REPO/bootstrap/lib/manifest-helpers.py" telegram-chat-id \
|
|
915
|
-
"$MANIFEST" "$OMEGA_HOME" 2>/dev/null | sed 's/^/ /' || true
|
|
916
|
-
# When chat_id came from the prompt (not the manifest), persist directly.
|
|
917
933
|
python3 - "$OMEGA_HOME" "$chat_id" <<'PY' || true
|
|
918
934
|
import sys
|
|
919
935
|
from pathlib import Path
|
|
@@ -922,12 +938,59 @@ sys.path.insert(0, str(home / "Agentik_Engine"))
|
|
|
922
938
|
try:
|
|
923
939
|
from omega_engine.vault import vault_write
|
|
924
940
|
vault_write(home, "TELEGRAM_GROUP_ID", sys.argv[2])
|
|
925
|
-
print(f"
|
|
941
|
+
print(f"AISB group chat_id stored: {sys.argv[2]}")
|
|
926
942
|
except Exception as exc:
|
|
927
943
|
print(f"(vault write skipped: {exc})")
|
|
928
944
|
PY
|
|
929
945
|
else
|
|
930
|
-
info "no
|
|
946
|
+
info "no AISB group_chat_id captured — set later with \`omega telegram set-group <id>\`"
|
|
947
|
+
fi
|
|
948
|
+
|
|
949
|
+
# 3. Hermès bot — OPTIONAL. Skip cleanly if the operator just hits Enter.
|
|
950
|
+
echo
|
|
951
|
+
info "Hermès bot — OPTIONAL. Meta-companion on Anthropic API (you pay per call)."
|
|
952
|
+
info " Skip both prompts if you don't want Hermès yet — OmegaOS works fully without it."
|
|
953
|
+
ask hermes_token "Hermès Telegram bot token (blank = skip Hermès)" "${TELEGRAM_TOKEN_HERMES:-}"
|
|
954
|
+
if [ -n "$hermes_token" ]; then
|
|
955
|
+
if have curl; then
|
|
956
|
+
if ! curl -s "https://api.telegram.org/bot${hermes_token}/getMe" | grep -q '"ok":true'; then
|
|
957
|
+
err "Hermès Telegram token rejected by the API — continuing without Hermès"
|
|
958
|
+
hermes_token=""
|
|
959
|
+
fi
|
|
960
|
+
fi
|
|
961
|
+
fi
|
|
962
|
+
if [ -n "$hermes_token" ]; then
|
|
963
|
+
ask anthropic_key "Anthropic API key for Hermès (sk-ant-...; blank = set later)" \
|
|
964
|
+
"${ANTHROPIC_API_KEY_HERMES:-${ANTHROPIC_API_KEY:-}}"
|
|
965
|
+
{
|
|
966
|
+
echo "# Hermès bot (Layer 2 meta-companion, Anthropic API)"
|
|
967
|
+
printf 'TELEGRAM_TOKEN_HERMES=%s\n' "$hermes_token"
|
|
968
|
+
} >> "$sec/telegram.env"
|
|
969
|
+
if [ -n "$anthropic_key" ]; then
|
|
970
|
+
printf 'ANTHROPIC_API_KEY_HERMES=%s\n' "$anthropic_key" >> "$sec/telegram.env"
|
|
971
|
+
fi
|
|
972
|
+
chmod 600 "$sec/telegram.env"
|
|
973
|
+
python3 - "$OMEGA_HOME" "$hermes_token" "$anthropic_key" <<'PY' || true
|
|
974
|
+
import sys
|
|
975
|
+
from pathlib import Path
|
|
976
|
+
home = Path(sys.argv[1])
|
|
977
|
+
sys.path.insert(0, str(home / "Agentik_Engine"))
|
|
978
|
+
try:
|
|
979
|
+
from omega_engine.vault import vault_write
|
|
980
|
+
vault_write(home, "TELEGRAM_TOKEN_HERMES", sys.argv[2])
|
|
981
|
+
if sys.argv[3]:
|
|
982
|
+
vault_write(home, "ANTHROPIC_API_KEY_HERMES", sys.argv[3])
|
|
983
|
+
except Exception as exc:
|
|
984
|
+
print(f"(vault write skipped: {exc})")
|
|
985
|
+
PY
|
|
986
|
+
if [ -n "$anthropic_key" ]; then
|
|
987
|
+
ok "Hermès Telegram bot + Anthropic key wired"
|
|
988
|
+
else
|
|
989
|
+
info "Hermès Telegram bot wired (no Anthropic key yet — set with"
|
|
990
|
+
info " omega vault write ANTHROPIC_API_KEY_HERMES <sk-ant-...>)"
|
|
991
|
+
fi
|
|
992
|
+
else
|
|
993
|
+
info "Hermès skipped — wire later with \`omega telegram setup-hermes\`"
|
|
931
994
|
fi
|
|
932
995
|
return 0
|
|
933
996
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -2741,8 +2741,70 @@ def cmd_aisb(args: argparse.Namespace) -> int:
|
|
|
2741
2741
|
return 2
|
|
2742
2742
|
|
|
2743
2743
|
|
|
2744
|
+
def _attach_or_spawn_chat(session_name: str, *,
|
|
2745
|
+
spawn_fn,
|
|
2746
|
+
label: str) -> int:
|
|
2747
|
+
"""Attach to ``session_name`` tmux session, spawning it first if absent.
|
|
2748
|
+
|
|
2749
|
+
- Outside tmux : `os.execvp("tmux", ["tmux", "attach", "-t", session])`
|
|
2750
|
+
- Inside tmux : prints the switch command (we can't switch from a
|
|
2751
|
+
subprocess; the user needs to do it in their shell).
|
|
2752
|
+
Returns the exit code of execvp or 0 when we printed instructions.
|
|
2753
|
+
|
|
2754
|
+
This is the v0.19.15 UX: bare `omega` puts you in the master chat,
|
|
2755
|
+
bare `omega hermes` puts you in the Hermès chat. No whiptail menu
|
|
2756
|
+
by default — that's `omega menu` now.
|
|
2757
|
+
"""
|
|
2758
|
+
import os
|
|
2759
|
+
from omega_engine import tmux
|
|
2760
|
+
home = _omega_home()
|
|
2761
|
+
if not tmux.is_alive(session_name):
|
|
2762
|
+
try:
|
|
2763
|
+
spawn_fn(home)
|
|
2764
|
+
except Exception as exc: # noqa: BLE001
|
|
2765
|
+
print(f" could not spawn {label}: {exc}")
|
|
2766
|
+
print(f" try manually: tmux new -d -s {session_name}")
|
|
2767
|
+
return 2
|
|
2768
|
+
# Inside tmux already? Tell the user to switch (we can't from here).
|
|
2769
|
+
if os.environ.get("TMUX"):
|
|
2770
|
+
print(f" already inside tmux — switch with:")
|
|
2771
|
+
print(f" tmux switch-client -t {session_name}")
|
|
2772
|
+
print(f" or detach (Ctrl-b d) then `omega` again.")
|
|
2773
|
+
return 0
|
|
2774
|
+
# Outside tmux — replace this process with `tmux attach`.
|
|
2775
|
+
print(f" attaching to {label} ({session_name})…")
|
|
2776
|
+
print(f" detach: Ctrl-b d (session keeps running)")
|
|
2777
|
+
try:
|
|
2778
|
+
os.execvp("tmux", ["tmux", "attach", "-t", session_name])
|
|
2779
|
+
except FileNotFoundError:
|
|
2780
|
+
print(" tmux not on PATH — install with `brew install tmux` "
|
|
2781
|
+
"or `apt-get install tmux`")
|
|
2782
|
+
return 2
|
|
2783
|
+
return 0 # unreachable (execvp replaced the process)
|
|
2784
|
+
|
|
2785
|
+
|
|
2744
2786
|
def cmd_menu(_args: argparse.Namespace) -> int:
|
|
2745
|
-
"""`omega`
|
|
2787
|
+
"""`omega` (no args) — open the AISB master chat session in tmux.
|
|
2788
|
+
|
|
2789
|
+
v0.19.15 changed the default: typing `omega` used to open the whiptail
|
|
2790
|
+
menu, which Gareth correctly called bad UX ("type `omega`, talk to my
|
|
2791
|
+
master agent"). Now bare `omega` attaches to the always-on `AISB-chat`
|
|
2792
|
+
tmux session, spawning it on demand. The whiptail menu lives at
|
|
2793
|
+
`omega menu`.
|
|
2794
|
+
"""
|
|
2795
|
+
from omega_engine import tmux
|
|
2796
|
+
return _attach_or_spawn_chat(
|
|
2797
|
+
"AISB-chat",
|
|
2798
|
+
spawn_fn=tmux.spawn_aisb_chat,
|
|
2799
|
+
label="AISB master chat",
|
|
2800
|
+
)
|
|
2801
|
+
|
|
2802
|
+
|
|
2803
|
+
def cmd_menu_whiptail(_args: argparse.Namespace) -> int:
|
|
2804
|
+
"""`omega menu` — the explicit whiptail picker.
|
|
2805
|
+
|
|
2806
|
+
The old bare-omega behaviour, moved behind an explicit subcommand
|
|
2807
|
+
because the default is now the AISB chat (v0.19.15)."""
|
|
2746
2808
|
from omega_engine.menu import run_menu
|
|
2747
2809
|
return run_menu()
|
|
2748
2810
|
|
|
@@ -2825,6 +2887,53 @@ def cmd_hermes(args: argparse.Namespace) -> int:
|
|
|
2825
2887
|
import json as _json
|
|
2826
2888
|
sub = getattr(args, "hermes_cmd", None)
|
|
2827
2889
|
|
|
2890
|
+
# v0.19.15 — `omega hermes` with no subcommand opens the Hermès chat
|
|
2891
|
+
# tmux session. Same UX as bare `omega` → AISB chat, but for L2.
|
|
2892
|
+
if sub is None or sub == "chat":
|
|
2893
|
+
from omega_engine import tmux as _tx
|
|
2894
|
+
return _attach_or_spawn_chat(
|
|
2895
|
+
"Hermes-chat",
|
|
2896
|
+
spawn_fn=_tx.spawn_hermes_chat,
|
|
2897
|
+
label="Hermès meta-companion chat",
|
|
2898
|
+
)
|
|
2899
|
+
if sub == "chat-loop":
|
|
2900
|
+
# REPL that runs inside the Hermes-chat tmux session.
|
|
2901
|
+
# Uses Anthropic API directly (separate from AISB's Max OAuth).
|
|
2902
|
+
from omega_engine.aisb_chat import chat_once
|
|
2903
|
+
from omega_engine.vault import vault_read
|
|
2904
|
+
import os, sys
|
|
2905
|
+
home = _omega_home()
|
|
2906
|
+
api_key = (vault_read(home, "ANTHROPIC_API_KEY_HERMES") or "").strip()
|
|
2907
|
+
if not api_key:
|
|
2908
|
+
api_key = (os.environ.get("ANTHROPIC_API_KEY") or "").strip()
|
|
2909
|
+
if not api_key:
|
|
2910
|
+
print(" Hermès has no Anthropic API key — set one with:")
|
|
2911
|
+
print(" omega vault write ANTHROPIC_API_KEY_HERMES sk-ant-...")
|
|
2912
|
+
print(" (Hermès uses its OWN paid Anthropic budget, separate")
|
|
2913
|
+
print(" from OmegaOS's Claude Max OAuth — see LAYERS.md)")
|
|
2914
|
+
return 2
|
|
2915
|
+
os.environ["ANTHROPIC_API_KEY"] = api_key
|
|
2916
|
+
print(f" Hermès chat (Anthropic API) — /quit to exit")
|
|
2917
|
+
# We re-use chat_once but namespace history to a Hermès topic so
|
|
2918
|
+
# AISB's chat history doesn't bleed into Hermès's.
|
|
2919
|
+
HERMES_TOPIC = -999999
|
|
2920
|
+
while True:
|
|
2921
|
+
try:
|
|
2922
|
+
line = input("\nyou > ").strip()
|
|
2923
|
+
except (EOFError, KeyboardInterrupt):
|
|
2924
|
+
print("\n(exit)")
|
|
2925
|
+
return 0
|
|
2926
|
+
if not line:
|
|
2927
|
+
continue
|
|
2928
|
+
if line in ("/quit", "/exit"):
|
|
2929
|
+
return 0
|
|
2930
|
+
try:
|
|
2931
|
+
reply = chat_once(home, line, topic_id=HERMES_TOPIC)
|
|
2932
|
+
except Exception as exc: # noqa: BLE001
|
|
2933
|
+
print(f"hermes (error): {exc}")
|
|
2934
|
+
continue
|
|
2935
|
+
print(f"\nhermes > {reply}")
|
|
2936
|
+
|
|
2828
2937
|
if sub == "status":
|
|
2829
2938
|
st = H.status()
|
|
2830
2939
|
if getattr(args, "json", False):
|
|
@@ -3774,10 +3883,14 @@ def cmd_cleanup(args: argparse.Namespace) -> int:
|
|
|
3774
3883
|
|
|
3775
3884
|
def _build_parser() -> argparse.ArgumentParser:
|
|
3776
3885
|
parser = argparse.ArgumentParser(prog="omega", description="Omega OS control CLI")
|
|
3777
|
-
#
|
|
3778
|
-
#
|
|
3886
|
+
# v0.19.15 — bare `omega` now drops into the AISB master chat tmux
|
|
3887
|
+
# session (attach or spawn). `omega menu` keeps the legacy whiptail
|
|
3888
|
+
# picker for power users.
|
|
3779
3889
|
parser.set_defaults(fn=cmd_menu)
|
|
3780
3890
|
sub = parser.add_subparsers(dest="cmd")
|
|
3891
|
+
sub.add_parser("menu",
|
|
3892
|
+
help="open the interactive whiptail menu (the old `omega` behaviour)"
|
|
3893
|
+
).set_defaults(fn=cmd_menu_whiptail)
|
|
3781
3894
|
sub.add_parser("version", help="print the engine version").set_defaults(fn=cmd_version)
|
|
3782
3895
|
p_doc = sub.add_parser("doctor", help="validate the deployment")
|
|
3783
3896
|
p_doc.add_argument("--json", action="store_true",
|
|
@@ -4018,6 +4131,14 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
4018
4131
|
help="(observe) project slug")
|
|
4019
4132
|
p_hebr.add_argument("task_id", nargs="?", default=None,
|
|
4020
4133
|
help="(observe) task id whose .done.json to ingest")
|
|
4134
|
+
# v0.19.15 — `omega hermes chat` and `omega hermes chat-loop`: the
|
|
4135
|
+
# Hermès counterpart to `omega aisb chat`. `chat` spawns/attaches
|
|
4136
|
+
# the persistent Hermes-chat tmux session; `chat-loop` is the REPL
|
|
4137
|
+
# itself that runs inside that session (Anthropic API).
|
|
4138
|
+
he_sub.add_parser("chat",
|
|
4139
|
+
help="spawn (or attach to) the Hermes-chat tmux session")
|
|
4140
|
+
he_sub.add_parser("chat-loop",
|
|
4141
|
+
help="the Hermès REPL itself (called by the tmux session)")
|
|
4021
4142
|
|
|
4022
4143
|
# `omega hermes-desktop` — Hermes Desktop remote backend
|
|
4023
4144
|
p_hd = sub.add_parser(
|
|
@@ -248,19 +248,45 @@ def build_env(
|
|
|
248
248
|
*,
|
|
249
249
|
extra: dict[str, str] | None = None,
|
|
250
250
|
creds_path: str | Path | None = None,
|
|
251
|
+
omega_home: str | Path | None = None,
|
|
251
252
|
) -> dict[str, str]:
|
|
252
253
|
"""Build the env dict for every Hermes invocation.
|
|
253
254
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
255
|
+
v0.19.14 — Hermès now defaults to its OWN Anthropic API key (budget
|
|
256
|
+
isolation from the OmegaOS Claude Max OAuth):
|
|
257
|
+
|
|
258
|
+
1. ``ANTHROPIC_API_KEY_HERMES`` from the encrypted vault → primary.
|
|
259
|
+
2. ``ANTHROPIC_API_KEY`` already in the shell env → fallback.
|
|
260
|
+
3. ``CLAUDE_CODE_OAUTH_TOKEN`` from ``~/.claude/.credentials.json``
|
|
261
|
+
→ LAST RESORT only, with a clear warning that this routes Hermès
|
|
262
|
+
calls through your Max sub.
|
|
263
|
+
|
|
264
|
+
Caller env wins via ``extra``.
|
|
257
265
|
"""
|
|
258
|
-
token = claude_oauth_token(creds_path)
|
|
259
266
|
env = {**os.environ}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
# 1. Vault first.
|
|
268
|
+
key = ""
|
|
269
|
+
try:
|
|
270
|
+
from omega_engine.vault import vault_read
|
|
271
|
+
from pathlib import Path as _P
|
|
272
|
+
home = _P(omega_home) if omega_home else _P(
|
|
273
|
+
os.environ.get("OMEGA_HOME", str(_P.home() / "Omega"))
|
|
274
|
+
)
|
|
275
|
+
key = (vault_read(home, "ANTHROPIC_API_KEY_HERMES") or "").strip()
|
|
276
|
+
except Exception: # noqa: BLE001
|
|
277
|
+
key = ""
|
|
278
|
+
# 2. Shell env fallback.
|
|
279
|
+
if not key:
|
|
280
|
+
key = (os.environ.get("ANTHROPIC_API_KEY") or "").strip()
|
|
281
|
+
# 3. Last-resort OAuth (preserves the old behaviour without making
|
|
282
|
+
# Hermès depend on it).
|
|
283
|
+
if not key:
|
|
284
|
+
try:
|
|
285
|
+
env["CLAUDE_CODE_OAUTH_TOKEN"] = claude_oauth_token(creds_path)
|
|
286
|
+
except Exception: # noqa: BLE001
|
|
287
|
+
pass
|
|
288
|
+
if key:
|
|
289
|
+
env["ANTHROPIC_API_KEY"] = key
|
|
264
290
|
env.setdefault("HERMES_PROVIDER", "anthropic")
|
|
265
291
|
env.setdefault("HERMES_MODEL", "claude-opus-4-7")
|
|
266
292
|
if extra:
|
|
@@ -232,11 +232,11 @@ def spawn_worker(project: str, task: str, *,
|
|
|
232
232
|
|
|
233
233
|
|
|
234
234
|
def spawn_aisb_chat(omega_home: str | Path | None = None) -> str:
|
|
235
|
-
"""Spawn
|
|
235
|
+
"""Spawn the AISB master chat tmux session.
|
|
236
236
|
|
|
237
|
-
Runs ``omega aisb chat-loop`` inside
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
Runs ``omega aisb chat-loop`` inside — REPL conversation with the
|
|
238
|
+
AISB master agent on Claude Max OAuth. This is what bare `omega`
|
|
239
|
+
attaches to (v0.19.15+).
|
|
240
240
|
"""
|
|
241
241
|
name = "AISB-chat"
|
|
242
242
|
home = Path(omega_home or os.environ.get("OMEGA_HOME")
|
|
@@ -246,6 +246,21 @@ def spawn_aisb_chat(omega_home: str | Path | None = None) -> str:
|
|
|
246
246
|
return name
|
|
247
247
|
|
|
248
248
|
|
|
249
|
+
def spawn_hermes_chat(omega_home: str | Path | None = None) -> str:
|
|
250
|
+
"""Spawn the Hermès meta-companion chat tmux session.
|
|
251
|
+
|
|
252
|
+
Runs ``omega hermes chat-loop`` — REPL conversation with Hermès on
|
|
253
|
+
Anthropic API (separate budget from AISB's Max OAuth). This is what
|
|
254
|
+
`omega hermes` attaches to (v0.19.15+).
|
|
255
|
+
"""
|
|
256
|
+
name = "Hermes-chat"
|
|
257
|
+
home = Path(omega_home or os.environ.get("OMEGA_HOME")
|
|
258
|
+
or Path.home() / "Omega")
|
|
259
|
+
omega_bin = home / "Agentik_Tools" / "bin" / "omega"
|
|
260
|
+
spawn(name, command=f"{omega_bin} hermes chat-loop")
|
|
261
|
+
return name
|
|
262
|
+
|
|
263
|
+
|
|
249
264
|
# ---------------------------------------------------------------------------
|
|
250
265
|
# Categorised view + health
|
|
251
266
|
# ---------------------------------------------------------------------------
|
package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313-pytest-8.4.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
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
|
|
@@ -95,13 +95,43 @@ class TestClaudeOAuthRead(unittest.TestCase):
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
class TestBuildEnv(unittest.TestCase):
|
|
98
|
-
|
|
98
|
+
"""v0.19.14 — Hermès prefers ANTHROPIC_API_KEY_HERMES from the vault,
|
|
99
|
+
falls back to ANTHROPIC_API_KEY env, then last-resort to the Max
|
|
100
|
+
OAuth at ``~/.claude/.credentials.json``."""
|
|
101
|
+
|
|
102
|
+
def test_env_uses_anthropic_key_env_when_set(self):
|
|
103
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
104
|
+
p = _fake_creds(Path(tmp) / "c.json", token="tk-Z")
|
|
105
|
+
old = os.environ.get("ANTHROPIC_API_KEY")
|
|
106
|
+
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-test"
|
|
107
|
+
os.environ.pop("OMEGA_HOME", None)
|
|
108
|
+
try:
|
|
109
|
+
env = H.build_env(creds_path=p)
|
|
110
|
+
self.assertEqual(env.get("ANTHROPIC_API_KEY"), "sk-ant-test",
|
|
111
|
+
"Hermès must prefer ANTHROPIC_API_KEY over OAuth")
|
|
112
|
+
# OAuth NOT exposed when an Anthropic key is available.
|
|
113
|
+
self.assertNotIn("CLAUDE_CODE_OAUTH_TOKEN", env)
|
|
114
|
+
finally:
|
|
115
|
+
if old is None:
|
|
116
|
+
os.environ.pop("ANTHROPIC_API_KEY", None)
|
|
117
|
+
else:
|
|
118
|
+
os.environ["ANTHROPIC_API_KEY"] = old
|
|
119
|
+
|
|
120
|
+
def test_env_falls_back_to_oauth_when_no_anthropic_key(self):
|
|
99
121
|
with tempfile.TemporaryDirectory() as tmp:
|
|
100
122
|
p = _fake_creds(Path(tmp) / "c.json", token="tk-Z")
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
123
|
+
old = os.environ.get("ANTHROPIC_API_KEY")
|
|
124
|
+
os.environ.pop("ANTHROPIC_API_KEY", None)
|
|
125
|
+
os.environ["OMEGA_HOME"] = tmp # no vault key here
|
|
126
|
+
try:
|
|
127
|
+
env = H.build_env(creds_path=p)
|
|
128
|
+
self.assertEqual(env.get("CLAUDE_CODE_OAUTH_TOKEN"), "tk-Z")
|
|
129
|
+
self.assertEqual(env["HERMES_PROVIDER"], "anthropic")
|
|
130
|
+
self.assertEqual(env["HERMES_MODEL"], "claude-opus-4-7")
|
|
131
|
+
finally:
|
|
132
|
+
os.environ.pop("OMEGA_HOME", None)
|
|
133
|
+
if old is not None:
|
|
134
|
+
os.environ["ANTHROPIC_API_KEY"] = old
|
|
105
135
|
|
|
106
136
|
def test_env_extra_overrides_default(self):
|
|
107
137
|
with tempfile.TemporaryDirectory() as tmp:
|
|
@@ -110,9 +140,27 @@ class TestBuildEnv(unittest.TestCase):
|
|
|
110
140
|
extra={"HERMES_MODEL": "claude-sonnet-4-7"})
|
|
111
141
|
self.assertEqual(env["HERMES_MODEL"], "claude-sonnet-4-7")
|
|
112
142
|
|
|
113
|
-
def
|
|
114
|
-
|
|
115
|
-
|
|
143
|
+
def test_env_no_creds_no_anthropic_returns_env_without_token(self):
|
|
144
|
+
"""When neither an Anthropic key nor Claude OAuth is available,
|
|
145
|
+
build_env returns a usable env WITHOUT either token. The caller
|
|
146
|
+
(or Hermès itself) decides whether to error or skip; build_env
|
|
147
|
+
no longer raises — that was the v0.18 strict behaviour."""
|
|
148
|
+
old_anth = os.environ.get("ANTHROPIC_API_KEY")
|
|
149
|
+
old_home = os.environ.get("OMEGA_HOME")
|
|
150
|
+
os.environ.pop("ANTHROPIC_API_KEY", None)
|
|
151
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
152
|
+
os.environ["OMEGA_HOME"] = tmp
|
|
153
|
+
try:
|
|
154
|
+
env = H.build_env(creds_path=Path("/no/such/file"))
|
|
155
|
+
self.assertNotIn("ANTHROPIC_API_KEY", env)
|
|
156
|
+
self.assertNotIn("CLAUDE_CODE_OAUTH_TOKEN", env)
|
|
157
|
+
self.assertEqual(env["HERMES_PROVIDER"], "anthropic")
|
|
158
|
+
finally:
|
|
159
|
+
os.environ.pop("OMEGA_HOME", None)
|
|
160
|
+
if old_home is not None:
|
|
161
|
+
os.environ["OMEGA_HOME"] = old_home
|
|
162
|
+
if old_anth is not None:
|
|
163
|
+
os.environ["ANTHROPIC_API_KEY"] = old_anth
|
|
116
164
|
|
|
117
165
|
|
|
118
166
|
# ---------------------------------------------------------------------------
|
|
@@ -140,7 +140,12 @@ class TestPostInstallCard(unittest.TestCase):
|
|
|
140
140
|
self.assertIn("install complete", out)
|
|
141
141
|
self.assertIn("status", out)
|
|
142
142
|
self.assertIn("next steps", out)
|
|
143
|
-
|
|
143
|
+
# v0.19.15 — bare `omega` is the AISB master chat, `omega hermes`
|
|
144
|
+
# is the L2 companion. Old card pointed at `omega status` as the
|
|
145
|
+
# entry; new card points at `omega` itself.
|
|
146
|
+
self.assertIn("omega", out)
|
|
147
|
+
self.assertIn("AISB", out)
|
|
148
|
+
self.assertIn("Hermès", out)
|
|
144
149
|
self.assertIn("omega run", out)
|
|
145
150
|
# No literal $C_DIM / $C_RST tokens
|
|
146
151
|
self.assertNotIn("${C_DIM}", out)
|
|
@@ -475,20 +475,25 @@ class TestBrandColourIsOrange(unittest.TestCase):
|
|
|
475
475
|
f"banner should use C_ORANGE on each of 8 rows (got {n})")
|
|
476
476
|
|
|
477
477
|
|
|
478
|
-
class
|
|
479
|
-
"""
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
478
|
+
class TestPostInstallCardSurfacesEntryPoints(unittest.TestCase):
|
|
479
|
+
"""v0.19.15 — bare `omega` is now the AISB chat attach (no longer needs
|
|
480
|
+
the explicit `tmux attach -t AISB-chat` in the card). The card must
|
|
481
|
+
still surface BOTH master entry points: `omega` for AISB and
|
|
482
|
+
`omega hermes` for the L2 companion. Plus the "every session in tmux"
|
|
483
|
+
discipline."""
|
|
484
|
+
|
|
485
|
+
def test_card_surfaces_aisb_and_hermes_entries(self):
|
|
484
486
|
if not COMMON_SH.is_file():
|
|
485
487
|
self.skipTest("common.sh not in repo")
|
|
486
488
|
text = COMMON_SH.read_text()
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
"
|
|
490
|
-
|
|
491
|
-
|
|
489
|
+
# Bare omega = AISB master.
|
|
490
|
+
self.assertIn("AISB", text,
|
|
491
|
+
"post_install_card must mention AISB as the master agent entry")
|
|
492
|
+
# `omega hermes` = L2.
|
|
493
|
+
self.assertIn("omega hermes", text,
|
|
494
|
+
"post_install_card must mention `omega hermes` as the L2 "
|
|
495
|
+
"companion entry — without it the user can't discover it")
|
|
496
|
+
# The "every session in tmux" expectation.
|
|
492
497
|
self.assertIn("tmux", text)
|
|
493
498
|
|
|
494
499
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.19.
|
|
1
|
+
0.19.15
|
|
@@ -1,90 +1,147 @@
|
|
|
1
1
|
# OmegaOS Layered Architecture
|
|
2
2
|
|
|
3
|
-
> Five layers.
|
|
4
|
-
>
|
|
3
|
+
> Five layers. **Two independent credential domains.** **Two Telegram bots
|
|
4
|
+
> with separate tokens.** Hermès sits above; AISB+Oracle+Workers stay below.
|
|
5
|
+
> Each layer is independently usable.
|
|
6
|
+
|
|
7
|
+
## The corrected model (v0.19.14)
|
|
5
8
|
|
|
6
9
|
```
|
|
7
10
|
┌──────────────────────────────────────────────────────────────────────┐
|
|
8
|
-
│ Layer 1 ─ Human
|
|
9
|
-
│
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
│
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
│
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
│
|
|
22
|
-
│
|
|
23
|
-
│
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
│
|
|
28
|
-
│
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
│
|
|
34
|
-
│
|
|
35
|
-
│
|
|
36
|
-
│
|
|
37
|
-
|
|
38
|
-
|
|
11
|
+
│ Layer 1 ─ Human (you) │
|
|
12
|
+
│ Three doors: │
|
|
13
|
+
│ 1. Telegram → Hermès bot (meta-companion, Anthropic API) │
|
|
14
|
+
│ 2. Telegram → AISB bot (OmegaOS native, Claude Max OAuth) │
|
|
15
|
+
│ 3. CLI / tmux (omega …, AISB-chat session) │
|
|
16
|
+
└────────┬───────────────────────────────────┬─────────────────────────┘
|
|
17
|
+
│ │
|
|
18
|
+
▼ ▼
|
|
19
|
+
┌──────────────────────┐ ┌────────────────────────────────────┐
|
|
20
|
+
│ Layer 2 ─ HERMÈS │ │ Layer 3 ─ AISB │
|
|
21
|
+
│ Meta-companion, │ ───────►│ OmegaOS intake / orchestrator │
|
|
22
|
+
│ scheduler, learner. │ dispatch│ Classifies, picks a topology, │
|
|
23
|
+
│ │ missions│ runs the mission. │
|
|
24
|
+
│ Auth: ANTHROPIC_API_ │ │ │
|
|
25
|
+
│ KEY_HERMES │ │ Auth: Claude Max OAuth │
|
|
26
|
+
│ Bot: TELEGRAM_TOKEN_│ │ (~/.claude/.credentials.json)│
|
|
27
|
+
│ HERMES │ │ Bot: TELEGRAM_TOKEN_AISB │
|
|
28
|
+
│ │ │ │
|
|
29
|
+
│ OPT-IN (skip if you │ │ Required for missions. │
|
|
30
|
+
│ don't want a paid │ │ Telegram bot is optional too — │
|
|
31
|
+
│ Anthropic key) │ │ tmux AISB-chat is the fallback. │
|
|
32
|
+
└──────────────────────┘ └─────────────┬──────────────────────┘
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
┌────────────────────────────────────┐
|
|
36
|
+
│ Layer 4 ─ Oracle (planner) │
|
|
37
|
+
│ Persistent tmux. Reads mission, │
|
|
38
|
+
│ plans N workers with verify_cmd. │
|
|
39
|
+
│ Auth: Claude Max OAuth │
|
|
40
|
+
└─────────────┬──────────────────────┘
|
|
41
|
+
│
|
|
42
|
+
▼
|
|
43
|
+
┌────────────────────────────────────┐
|
|
44
|
+
│ Layer 5 ─ Workers (executors) │
|
|
45
|
+
│ One per subtask. Persistent tmux. │
|
|
46
|
+
│ Writes .done.json. Audit-gated. │
|
|
47
|
+
│ Auth: Claude Max OAuth │
|
|
48
|
+
└────────────────────────────────────┘
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Why TWO bots, TWO auth domains
|
|
52
|
+
|
|
53
|
+
| Concern | Hermès (L2) | AISB+Oracle+Workers (L3-L5) |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| **Telegram token** | `TELEGRAM_TOKEN_HERMES` | `TELEGRAM_TOKEN_AISB` |
|
|
56
|
+
| **LLM credential** | `ANTHROPIC_API_KEY_HERMES` (you pay per call) | Claude Max OAuth from `~/.claude/.credentials.json` (covered by your Max sub) |
|
|
57
|
+
| **What it does** | Meta-reasoning: schedules, suggestions, learning, dispatches missions DOWN to AISB | Executes verified-completion missions inside projects |
|
|
58
|
+
| **Budget risk** | You pay → bounded by your Anthropic spend limit | Claude Max — never charged per call |
|
|
59
|
+
| **Failure mode if absent** | Skip Hermès → OmegaOS still works (CLI + AISB bot) | If absent, no missions → not optional |
|
|
60
|
+
|
|
61
|
+
This split is intentional:
|
|
62
|
+
|
|
63
|
+
1. **Budget isolation.** Hermès can run a tight schedule loop, learn from
|
|
64
|
+
observations, propose missions — without ever touching your Max quota.
|
|
65
|
+
AISB+Workers can crank through 50-step missions on Max OAuth — without
|
|
66
|
+
ever burning your Anthropic API budget.
|
|
67
|
+
2. **Independent identity.** Hermès has its own Telegram username, its
|
|
68
|
+
own bot personality, its own conversation history. AISB stays
|
|
69
|
+
project-focused (one bot per OmegaOS install, topics per project).
|
|
70
|
+
3. **Authority gradient.** Hermès is *above* OmegaOS — it can issue
|
|
71
|
+
commands to AISB but doesn't run inside it. AISB is *the* runtime
|
|
72
|
+
for OmegaOS missions.
|
|
73
|
+
|
|
74
|
+
## Per-project Telegram structure
|
|
75
|
+
|
|
76
|
+
OmegaOS treats Telegram as the operator's command surface:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
AISB Group (Telegram supergroup with topics enabled)
|
|
80
|
+
│
|
|
81
|
+
├── Topic "general" — chat with AISB, status questions
|
|
82
|
+
├── Topic "project: dentistry" — dispatch missions for the Dentistry project
|
|
83
|
+
├── Topic "project: kommu" — dispatch missions for the Kommu project
|
|
84
|
+
├── Topic "project: causio" — dispatch missions for the Causio project
|
|
85
|
+
└── … (one topic per project, mapped in
|
|
86
|
+
Agentik_SSOT/projects/<slug>/registry.yaml)
|
|
39
87
|
```
|
|
40
88
|
|
|
41
|
-
|
|
89
|
+
A message posted in a project topic = a mission for THAT project. AISB
|
|
90
|
+
reads `message_thread_id` (the topic_id), looks up the slug, runs the
|
|
91
|
+
mission in the project's context (cwd = project root, env =
|
|
92
|
+
project-scoped secrets).
|
|
93
|
+
|
|
94
|
+
Hermès operates ABOVE the group. It can:
|
|
95
|
+
|
|
96
|
+
* Receive a DM in **its own** Telegram bot from you.
|
|
97
|
+
* Decide: "this is a mission for project X" → send a message INTO
|
|
98
|
+
the AISB group's topic-X (Hermès posts as a member of the group).
|
|
99
|
+
* Or: "this is a meta-question" → answer directly via Anthropic API.
|
|
100
|
+
* Or: "this is an autonomous trigger" (cron, observation) → dispatch
|
|
101
|
+
a fresh mission into a project topic.
|
|
42
102
|
|
|
43
|
-
|
|
44
|
-
|---|---|---|---|
|
|
45
|
-
| 1 | Intent | Human | n/a |
|
|
46
|
-
| 2 | Autonomous companion | Hermes (Python, ~/.hermes) | Claude Max OAuth |
|
|
47
|
-
| 3 | Mission intake | OmegaOS engine | Claude Max OAuth |
|
|
48
|
-
| 4 | Planning | Persistent tmux + `claude -p` | Claude Max OAuth |
|
|
49
|
-
| 5 | Execution | Persistent tmux + `claude -p` | Claude Max OAuth |
|
|
103
|
+
## Install / secrets layout (corrected)
|
|
50
104
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
token
|
|
54
|
-
|
|
55
|
-
|
|
105
|
+
| Vault key | Holds | Who reads it |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `TELEGRAM_TOKEN_AISB` | AISB bot token (from BotFather, bot A) | `omega telegram bridge` + AISB daemon |
|
|
108
|
+
| `TELEGRAM_TOKEN_HERMES` | Hermès bot token (from BotFather, bot B) | Hermès daemon only |
|
|
109
|
+
| `ANTHROPIC_API_KEY_HERMES` | Hermès's own paid Anthropic key | Hermès daemon only |
|
|
110
|
+
| `TELEGRAM_GROUP_ID` | AISB supergroup chat_id | AISB daemon (to scope missions) |
|
|
111
|
+
| `TELEGRAM_TOKEN` | **back-compat alias** for `TELEGRAM_TOKEN_AISB` | Old install paths |
|
|
112
|
+
| Claude Max OAuth | The OAuth at `~/.claude/.credentials.json` | AISB, Oracle, all Workers |
|
|
113
|
+
|
|
114
|
+
Claude Max OAuth is **never duplicated in the vault** — it lives in
|
|
115
|
+
`~/.claude/.credentials.json` and every layer below Hermès reads it live
|
|
116
|
+
on every call so refresh rotations propagate naturally.
|
|
56
117
|
|
|
57
118
|
## Layer choice cheat-sheet
|
|
58
119
|
|
|
59
120
|
| You want to | Use |
|
|
60
121
|
|---|---|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
69
|
-
## Bridges
|
|
70
|
-
|
|
71
|
-
* `omega hermes` — Layer 2 ↔ rest of stack. Hermes can call OmegaOS via
|
|
72
|
-
the `omega` CLI (any of layers 3-5). OmegaOS can call Hermes via
|
|
73
|
-
`omega hermes ask "..."`.
|
|
74
|
-
* `omega ua` — Understand-Anything sidecar. Builds an interactive
|
|
75
|
-
knowledge graph of any project; `omega ua consume` lands the graph
|
|
76
|
-
into the Engine's GraphRetriever so Oracle/workers can answer
|
|
77
|
-
"where in the code is X?" via Graph RAG.
|
|
78
|
-
* `omega ma` — Anthropic Managed Agents (opt-in, API-key-only). NOT
|
|
79
|
-
part of the OAuth stack; only used when explicitly opted into per
|
|
80
|
-
topology entry.
|
|
122
|
+
| Quick chat with the meta-companion | Hermès bot (DM) — Anthropic API |
|
|
123
|
+
| Run a mission on a project | AISB project topic OR `omega run` from project dir |
|
|
124
|
+
| One-shot CLI question (no orchestration) | `claude -p "..."` directly |
|
|
125
|
+
| Verified-completion multi-worker mission | `omega run` / AISB topic — engages Oracle + Workers |
|
|
126
|
+
| Recurring scheduled mission | `omega cadence schedule …` — wakes through AISB |
|
|
127
|
+
| Cross-platform autonomous loop | Hermès (Anthropic API key, scheduled tasks) |
|
|
128
|
+
| Audit a project | `/codeaudit` etc. from project — Quality Arsenal |
|
|
81
129
|
|
|
82
130
|
## What this is NOT
|
|
83
131
|
|
|
84
|
-
*
|
|
85
|
-
|
|
86
|
-
ability to delegate to each other.
|
|
87
|
-
*
|
|
88
|
-
OS
|
|
89
|
-
|
|
90
|
-
|
|
132
|
+
* Hermès is NOT a wrapper around AISB — they're separate runtimes with
|
|
133
|
+
separate credentials and separate Telegram identities. The bridge gives
|
|
134
|
+
both the ability to delegate to each other.
|
|
135
|
+
* AISB does NOT need Hermès to function. Skip Hermès install → OmegaOS
|
|
136
|
+
is a complete agentic OS with verified completion. Add Hermès when you
|
|
137
|
+
want meta-reasoning + autonomous loops above your projects.
|
|
138
|
+
* The Anthropic API key Hermès uses is NOT shared with anything else.
|
|
139
|
+
AISB+Oracle+Workers stay on Max OAuth, always.
|
|
140
|
+
|
|
141
|
+
## v0.19.x evolution
|
|
142
|
+
|
|
143
|
+
| Version | Change |
|
|
144
|
+
|---|---|
|
|
145
|
+
| v0.18 | Single OAuth model (Hermès on Claude Max) |
|
|
146
|
+
| **v0.19.14** | **Split: Hermès on `ANTHROPIC_API_KEY_HERMES`; AISB on Max OAuth; two Telegram bots** |
|
|
147
|
+
| (planned v0.19.15+) | Dedicated Hermès daemon (its own poll loop), Hermès→AISB dispatch verbs |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentikos/omega-os",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.15",
|
|
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"
|