@agentikos/omega-os 0.19.26 → 0.19.27
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/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__/tui.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/cli.py +24 -10
- package/omega/Agentik_Engine/omega_engine/tui.py +457 -0
- package/omega/Agentik_Engine/pyproject.toml +2 -1
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -2856,16 +2856,27 @@ def cmd_menu(_args: argparse.Namespace) -> int:
|
|
|
2856
2856
|
|
|
2857
2857
|
|
|
2858
2858
|
def cmd_menu_tui(_args: argparse.Namespace) -> int:
|
|
2859
|
-
"""`omega menu-tui` — the
|
|
2859
|
+
"""`omega menu-tui` — the OmegaOS Textual TUI (v0.19.27+).
|
|
2860
2860
|
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2861
|
+
Modern boxed-layout TUI with slash commands (Hermès-style), sidebar
|
|
2862
|
+
categories, scrollable content log, footer keybindings. Falls back
|
|
2863
|
+
to a plain slash REPL if `textual` isn't installed (e.g. headless
|
|
2864
|
+
or before the engine venv finishes installing deps).
|
|
2865
2865
|
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2866
|
+
Delegates to `omega_engine.tui.run_tui()` which encapsulates both
|
|
2867
|
+
the Textual app and the plain REPL fallback.
|
|
2868
|
+
"""
|
|
2869
|
+
from omega_engine.tui import run_tui
|
|
2870
|
+
return run_tui()
|
|
2871
|
+
|
|
2872
|
+
|
|
2873
|
+
def _legacy_fzf_menu(_args: argparse.Namespace) -> int:
|
|
2874
|
+
"""v0.19.26 fzf menu — kept as fallback. Reachable via `omega menu-fzf`.
|
|
2875
|
+
|
|
2876
|
+
Actions run INLINE in the menu pane (not in dead background tmux
|
|
2877
|
+
windows). After every action, "press Enter to return to menu".
|
|
2878
|
+
Sessions (AISB/Hermes) still spawn as separate tmux sessions because
|
|
2879
|
+
they're meant to be talked to long-running.
|
|
2869
2880
|
"""
|
|
2870
2881
|
import os
|
|
2871
2882
|
import shlex
|
|
@@ -4333,9 +4344,12 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
4333
4344
|
help="open the interactive whiptail menu (legacy)"
|
|
4334
4345
|
).set_defaults(fn=cmd_menu_whiptail)
|
|
4335
4346
|
sub.add_parser("menu-tui",
|
|
4336
|
-
help="the
|
|
4337
|
-
"
|
|
4347
|
+
help="the Textual TUI inside the Omega tmux session "
|
|
4348
|
+
"(don't call directly — bare `omega` lands you here)"
|
|
4338
4349
|
).set_defaults(fn=cmd_menu_tui)
|
|
4350
|
+
sub.add_parser("menu-fzf",
|
|
4351
|
+
help="legacy v0.19.26 fzf menu fallback"
|
|
4352
|
+
).set_defaults(fn=_legacy_fzf_menu)
|
|
4339
4353
|
sub.add_parser("version", help="print the engine version").set_defaults(fn=cmd_version)
|
|
4340
4354
|
|
|
4341
4355
|
# `omega switch <provider>` — hot-swap the LLM CLI used for new chats.
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"""OmegaOS interactive Textual TUI — the v0.19.27 redesign.
|
|
2
|
+
|
|
3
|
+
User: "l'objectif c'est que ça fonctionne comme
|
|
4
|
+
https://www.agentik-os.com/services/agentik-coding-workflow ! avec notre
|
|
5
|
+
nouveau system omegaOS qui est noramlement une refont de tout ca ! et
|
|
6
|
+
aussi pour ta reponse - le TUI mets tout en place pour OmegaOS"
|
|
7
|
+
|
|
8
|
+
Architecture mirror of the Agentik Coding Workflow v2.5.1 doc:
|
|
9
|
+
|
|
10
|
+
- 4-level hierarchy visible (Human → AISB → Oracle → Worker)
|
|
11
|
+
- Telegram + terminal-native (no web dashboard)
|
|
12
|
+
- Terminal entry = this TUI
|
|
13
|
+
- Sessions exposed via tmux; TUI is the OmegaOS control surface
|
|
14
|
+
|
|
15
|
+
Layout (Textual, mouse + keyboard, slash-command driven like Hermès):
|
|
16
|
+
|
|
17
|
+
┌── Ω Omega OS v0.19.27 • provider: claude_code • sessions: 3 ──┐
|
|
18
|
+
│ CATEGORY │ CONTENT │
|
|
19
|
+
│ ──────── │ ─────── │
|
|
20
|
+
│ ▶ Chat │ (selected category's content here │
|
|
21
|
+
│ Projects │ — sessions list, audit menu, │
|
|
22
|
+
│ Audits │ doctor output, etc.) │
|
|
23
|
+
│ Sessions │ │
|
|
24
|
+
│ Accounts │ │
|
|
25
|
+
│ Vault │ │
|
|
26
|
+
│ Health │ │
|
|
27
|
+
│ Scrape │ │
|
|
28
|
+
│ │ │
|
|
29
|
+
├────────────────────────────┴─────────────────────────────────────┤
|
|
30
|
+
│ Ω › /<slash command> │
|
|
31
|
+
├──────────────────────────────────────────────────────────────────┤
|
|
32
|
+
│ q quit • d detach • ? help • / focus slash input │
|
|
33
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
34
|
+
|
|
35
|
+
Slash commands (Hermès-style):
|
|
36
|
+
/chat aisb /chat hermes /aisb /hermes
|
|
37
|
+
/switch <provider> /switch (show current)
|
|
38
|
+
/audit <id> /mission "<intent>" /scrape <url>
|
|
39
|
+
/genesis <slug> /doctor /status
|
|
40
|
+
/vault [<key>] /accounts /sessions
|
|
41
|
+
/quit /detach /help
|
|
42
|
+
"""
|
|
43
|
+
from __future__ import annotations
|
|
44
|
+
|
|
45
|
+
import os
|
|
46
|
+
import subprocess
|
|
47
|
+
import shlex
|
|
48
|
+
from pathlib import Path
|
|
49
|
+
from typing import Any
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
from textual.app import App, ComposeResult
|
|
53
|
+
from textual.widgets import (
|
|
54
|
+
Header, Footer, Input, RichLog, ListView, ListItem, Label,
|
|
55
|
+
)
|
|
56
|
+
from textual.containers import Horizontal, Vertical
|
|
57
|
+
from textual.binding import Binding
|
|
58
|
+
TEXTUAL_AVAILABLE = True
|
|
59
|
+
except ImportError:
|
|
60
|
+
TEXTUAL_AVAILABLE = False
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# ---------------------------------------------------------------------------
|
|
64
|
+
# Sidebar category map
|
|
65
|
+
# ---------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
CATEGORIES: list[tuple[str, str]] = [
|
|
68
|
+
("chat", "Chat — AISB & Hermès"),
|
|
69
|
+
("projects", "Projects — Genesis & shells"),
|
|
70
|
+
("audits", "Audits — Quality Arsenal (17 forensic)"),
|
|
71
|
+
("missions", "Missions — run with verified completion"),
|
|
72
|
+
("sessions", "Sessions — live tmux sessions"),
|
|
73
|
+
("accounts", "Accounts — Claude Max + provider auth"),
|
|
74
|
+
("vault", "Vault — encrypted secrets"),
|
|
75
|
+
("health", "Health — doctor + status"),
|
|
76
|
+
("scrape", "Scrape — CloakBrowser + Scrapling"),
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
# Slash command dispatcher
|
|
82
|
+
# ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class CommandResult:
|
|
86
|
+
"""A command's effect — text to display + optional side-effects."""
|
|
87
|
+
|
|
88
|
+
def __init__(self, *, text: str = "", session_jump: str = "",
|
|
89
|
+
exit_tui: bool = False, detach: bool = False) -> None:
|
|
90
|
+
self.text = text
|
|
91
|
+
self.session_jump = session_jump
|
|
92
|
+
self.exit_tui = exit_tui
|
|
93
|
+
self.detach = detach
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _omega_bin() -> str:
|
|
97
|
+
home = Path(os.environ.get("OMEGA_HOME", str(Path.home() / "Omega")))
|
|
98
|
+
return str(home / "Agentik_Tools" / "bin" / "omega")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _run_omega(*args: str) -> str:
|
|
102
|
+
"""Shell out to the omega CLI and capture its stdout/stderr."""
|
|
103
|
+
try:
|
|
104
|
+
proc = subprocess.run([_omega_bin(), *args],
|
|
105
|
+
capture_output=True, text=True, timeout=120)
|
|
106
|
+
return (proc.stdout + proc.stderr).rstrip()
|
|
107
|
+
except subprocess.SubprocessError as exc:
|
|
108
|
+
return f" error: {exc}"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _switch_client(target: str) -> None:
|
|
112
|
+
subprocess.run(["tmux", "switch-client", "-t", target],
|
|
113
|
+
capture_output=True)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def dispatch_slash(line: str) -> CommandResult:
|
|
117
|
+
"""Parse a slash command and return the effect to apply."""
|
|
118
|
+
line = line.strip()
|
|
119
|
+
if not line:
|
|
120
|
+
return CommandResult(text="(empty)")
|
|
121
|
+
# Allow both "/foo bar" and "foo bar" inputs.
|
|
122
|
+
if line.startswith("/"):
|
|
123
|
+
line = line[1:]
|
|
124
|
+
try:
|
|
125
|
+
argv = shlex.split(line)
|
|
126
|
+
except ValueError as exc:
|
|
127
|
+
return CommandResult(text=f" parse error: {exc}")
|
|
128
|
+
if not argv:
|
|
129
|
+
return CommandResult(text="(empty)")
|
|
130
|
+
cmd, *rest = argv
|
|
131
|
+
|
|
132
|
+
# Quit / detach
|
|
133
|
+
if cmd in ("quit", "q", "exit"):
|
|
134
|
+
return CommandResult(exit_tui=True)
|
|
135
|
+
if cmd in ("detach", "d"):
|
|
136
|
+
return CommandResult(detach=True)
|
|
137
|
+
|
|
138
|
+
# Chat sessions
|
|
139
|
+
if cmd == "aisb" or (cmd == "chat" and rest and rest[0] == "aisb"):
|
|
140
|
+
from omega_engine import tmux as _tx
|
|
141
|
+
_tx.spawn_aisb_chat(Path(os.environ.get(
|
|
142
|
+
"OMEGA_HOME", str(Path.home() / "Omega"))))
|
|
143
|
+
return CommandResult(
|
|
144
|
+
text=" AISB-chat spawned — switching client…",
|
|
145
|
+
session_jump="AISB-chat",
|
|
146
|
+
)
|
|
147
|
+
if cmd == "hermes" or (cmd == "chat" and rest and rest[0] == "hermes"):
|
|
148
|
+
from omega_engine import tmux as _tx
|
|
149
|
+
_tx.spawn_hermes_chat(Path(os.environ.get(
|
|
150
|
+
"OMEGA_HOME", str(Path.home() / "Omega"))))
|
|
151
|
+
return CommandResult(
|
|
152
|
+
text=" Hermes-chat spawned — switching client…",
|
|
153
|
+
session_jump="Hermes-chat",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Provider hot-swap
|
|
157
|
+
if cmd == "switch":
|
|
158
|
+
if rest:
|
|
159
|
+
return CommandResult(text=_run_omega("switch", rest[0]))
|
|
160
|
+
return CommandResult(text=_run_omega("switch"))
|
|
161
|
+
|
|
162
|
+
# Audits + missions
|
|
163
|
+
if cmd == "audit":
|
|
164
|
+
if rest:
|
|
165
|
+
return CommandResult(text=_run_omega("audit", *rest))
|
|
166
|
+
return CommandResult(text=(
|
|
167
|
+
" Quality Arsenal — 17 forensic audits:\n"
|
|
168
|
+
" /codeaudit /uiuxaudit /flowaudit /debugaudit\n"
|
|
169
|
+
" /featureaudit /perfaudit /secaudit /a11yaudit\n"
|
|
170
|
+
" /seoaudit /dataaudit /apiaudit /copyaudit\n"
|
|
171
|
+
" /dxaudit /motionaudit /automationaudit\n"
|
|
172
|
+
" /logicaudit /retentionaudit /refontaudit\n"
|
|
173
|
+
" invoke from any claude session, or:\n"
|
|
174
|
+
f" omega audit <id>"
|
|
175
|
+
))
|
|
176
|
+
if cmd in ("mission", "run"):
|
|
177
|
+
if not rest:
|
|
178
|
+
return CommandResult(text=" usage: /mission \"<intent>\"")
|
|
179
|
+
return CommandResult(text=_run_omega("run", " ".join(rest)))
|
|
180
|
+
|
|
181
|
+
# Genesis (new project)
|
|
182
|
+
if cmd == "genesis":
|
|
183
|
+
if not rest:
|
|
184
|
+
return CommandResult(text=_run_omega("genesis", "questions"))
|
|
185
|
+
return CommandResult(text=_run_omega("genesis", "new", rest[0]))
|
|
186
|
+
|
|
187
|
+
# Vault
|
|
188
|
+
if cmd == "vault":
|
|
189
|
+
if not rest:
|
|
190
|
+
return CommandResult(text=_run_omega("vault", "status"))
|
|
191
|
+
return CommandResult(text=_run_omega("vault", *rest))
|
|
192
|
+
|
|
193
|
+
# Accounts + sessions
|
|
194
|
+
if cmd == "accounts":
|
|
195
|
+
return CommandResult(text=_run_omega("account", "list"))
|
|
196
|
+
if cmd == "sessions":
|
|
197
|
+
try:
|
|
198
|
+
proc = subprocess.run(["tmux", "ls"],
|
|
199
|
+
capture_output=True, text=True, timeout=10)
|
|
200
|
+
return CommandResult(text=proc.stdout + proc.stderr)
|
|
201
|
+
except subprocess.SubprocessError as exc:
|
|
202
|
+
return CommandResult(text=f" error: {exc}")
|
|
203
|
+
|
|
204
|
+
# Health
|
|
205
|
+
if cmd == "doctor":
|
|
206
|
+
return CommandResult(text=_run_omega("doctor"))
|
|
207
|
+
if cmd == "status":
|
|
208
|
+
return CommandResult(text=_run_omega("status"))
|
|
209
|
+
|
|
210
|
+
# Scrape
|
|
211
|
+
if cmd == "scrape":
|
|
212
|
+
if not rest:
|
|
213
|
+
return CommandResult(text=" usage: /scrape <url> [--engine scrapling]")
|
|
214
|
+
return CommandResult(text=_run_omega("scrape", *rest))
|
|
215
|
+
|
|
216
|
+
# Help
|
|
217
|
+
if cmd in ("help", "?"):
|
|
218
|
+
return CommandResult(text=(
|
|
219
|
+
" SLASH COMMANDS\n"
|
|
220
|
+
" ──────────────\n"
|
|
221
|
+
" /aisb switch to AISB master chat (Max OAuth)\n"
|
|
222
|
+
" /hermes switch to Hermès chat (Anthropic API)\n"
|
|
223
|
+
" /switch <provider> hot-swap LLM provider (Hermes-style)\n"
|
|
224
|
+
" /mission \"<intent>\" run a verified-completion mission\n"
|
|
225
|
+
" /audit <id> run a forensic audit (codeaudit, …)\n"
|
|
226
|
+
" /genesis <slug> start a new project via Genesis pipeline\n"
|
|
227
|
+
" /scrape <url> stealth scrape (CloakBrowser default)\n"
|
|
228
|
+
" /scrape <url> --engine scrapling fast scrape (Scrapling)\n"
|
|
229
|
+
" /sessions list active tmux sessions\n"
|
|
230
|
+
" /accounts list Claude Max account pool\n"
|
|
231
|
+
" /vault [key] vault status or read key\n"
|
|
232
|
+
" /doctor full health check (omega doctor)\n"
|
|
233
|
+
" /status task state (omega status)\n"
|
|
234
|
+
" /detach detach from Omega tmux session\n"
|
|
235
|
+
" /quit quit the TUI (kill Omega session)\n"
|
|
236
|
+
" /help show this help\n"
|
|
237
|
+
"\n"
|
|
238
|
+
" KEYBINDINGS\n"
|
|
239
|
+
" ───────────\n"
|
|
240
|
+
" / focus the slash input\n"
|
|
241
|
+
" ? this help\n"
|
|
242
|
+
" d detach\n"
|
|
243
|
+
" q quit\n"
|
|
244
|
+
" Tab navigate categories"
|
|
245
|
+
))
|
|
246
|
+
|
|
247
|
+
return CommandResult(text=(
|
|
248
|
+
f" unknown command: /{cmd}\n"
|
|
249
|
+
f" type /help for the list of commands"
|
|
250
|
+
))
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# ---------------------------------------------------------------------------
|
|
254
|
+
# The Textual app
|
|
255
|
+
# ---------------------------------------------------------------------------
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
if TEXTUAL_AVAILABLE:
|
|
259
|
+
|
|
260
|
+
class OmegaTUI(App):
|
|
261
|
+
"""OmegaOS Textual TUI — the v0.19.27 control surface."""
|
|
262
|
+
|
|
263
|
+
CSS = """
|
|
264
|
+
Screen {
|
|
265
|
+
background: $background;
|
|
266
|
+
}
|
|
267
|
+
#sidebar {
|
|
268
|
+
width: 32;
|
|
269
|
+
border-right: tall $primary;
|
|
270
|
+
padding: 1 1;
|
|
271
|
+
}
|
|
272
|
+
#content {
|
|
273
|
+
padding: 1 2;
|
|
274
|
+
}
|
|
275
|
+
#slash {
|
|
276
|
+
border-top: tall $primary;
|
|
277
|
+
background: $surface;
|
|
278
|
+
}
|
|
279
|
+
Header {
|
|
280
|
+
background: $primary;
|
|
281
|
+
color: $text;
|
|
282
|
+
}
|
|
283
|
+
ListView > ListItem.--highlight {
|
|
284
|
+
background: $primary;
|
|
285
|
+
color: $text;
|
|
286
|
+
}
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
BINDINGS = [
|
|
290
|
+
Binding("q", "quit_omega", "Quit"),
|
|
291
|
+
Binding("d", "detach_omega", "Detach"),
|
|
292
|
+
Binding("question_mark", "help_omega", "Help"),
|
|
293
|
+
Binding("slash", "focus_slash", "Slash"),
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
297
|
+
super().__init__(*args, **kwargs)
|
|
298
|
+
self._content: RichLog | None = None
|
|
299
|
+
self._slash: Input | None = None
|
|
300
|
+
|
|
301
|
+
def compose(self) -> ComposeResult:
|
|
302
|
+
from omega_engine import __version__
|
|
303
|
+
yield Header(name=f"Ω Omega OS v{__version__}", show_clock=True)
|
|
304
|
+
with Horizontal():
|
|
305
|
+
with Vertical(id="sidebar"):
|
|
306
|
+
yield Label("Categories", id="sidebar-title")
|
|
307
|
+
items = [ListItem(Label(name)) for _id, name in CATEGORIES]
|
|
308
|
+
yield ListView(*items, id="cats")
|
|
309
|
+
with Vertical(id="content-wrap"):
|
|
310
|
+
log = RichLog(id="content", highlight=True, markup=True,
|
|
311
|
+
wrap=True)
|
|
312
|
+
self._content = log
|
|
313
|
+
yield log
|
|
314
|
+
self._slash = Input(placeholder="Ω › type a slash command "
|
|
315
|
+
"(/help for list, /quit to exit)",
|
|
316
|
+
id="slash")
|
|
317
|
+
yield self._slash
|
|
318
|
+
yield Footer()
|
|
319
|
+
|
|
320
|
+
def on_mount(self) -> None:
|
|
321
|
+
self._write_welcome()
|
|
322
|
+
if self._slash:
|
|
323
|
+
self._slash.focus()
|
|
324
|
+
|
|
325
|
+
def _write_welcome(self) -> None:
|
|
326
|
+
if not self._content:
|
|
327
|
+
return
|
|
328
|
+
from omega_engine import __version__
|
|
329
|
+
self._content.write(
|
|
330
|
+
f"[bold #D97757]Ω Omega OS v{__version__}[/]\n"
|
|
331
|
+
"Type /help to see all slash commands.\n"
|
|
332
|
+
"\n"
|
|
333
|
+
"Quick start:\n"
|
|
334
|
+
" [bold]/aisb[/] chat with the AISB master agent\n"
|
|
335
|
+
" [bold]/hermes[/] chat with Hermès (Anthropic API)\n"
|
|
336
|
+
" [bold]/switch[/] see + hot-swap LLM provider\n"
|
|
337
|
+
" [bold]/mission \"...\"[/] run a verified-completion mission\n"
|
|
338
|
+
" [bold]/scrape <url>[/] stealth scrape via CloakBrowser\n"
|
|
339
|
+
" [bold]/audit <id>[/] run a Quality Arsenal audit\n"
|
|
340
|
+
" [bold]/doctor[/] full health check\n"
|
|
341
|
+
"\n"
|
|
342
|
+
"Click a category in the sidebar, or type a / command.\n"
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
def action_quit_omega(self) -> None:
|
|
346
|
+
subprocess.run(["tmux", "kill-session", "-t", "Omega"],
|
|
347
|
+
capture_output=True)
|
|
348
|
+
self.exit()
|
|
349
|
+
|
|
350
|
+
def action_detach_omega(self) -> None:
|
|
351
|
+
subprocess.run(["tmux", "detach-client"], capture_output=True)
|
|
352
|
+
self.exit()
|
|
353
|
+
|
|
354
|
+
def action_help_omega(self) -> None:
|
|
355
|
+
res = dispatch_slash("/help")
|
|
356
|
+
if self._content:
|
|
357
|
+
self._content.write(res.text)
|
|
358
|
+
|
|
359
|
+
def action_focus_slash(self) -> None:
|
|
360
|
+
if self._slash:
|
|
361
|
+
self._slash.focus()
|
|
362
|
+
|
|
363
|
+
def on_list_view_selected(self, event: Any) -> None:
|
|
364
|
+
"""User clicked a sidebar category — render that category's content."""
|
|
365
|
+
idx = event.list_view.index or 0
|
|
366
|
+
if idx >= len(CATEGORIES):
|
|
367
|
+
return
|
|
368
|
+
cat_id = CATEGORIES[idx][0]
|
|
369
|
+
self._render_category(cat_id)
|
|
370
|
+
|
|
371
|
+
def _render_category(self, cat_id: str) -> None:
|
|
372
|
+
if not self._content:
|
|
373
|
+
return
|
|
374
|
+
mapping = {
|
|
375
|
+
"chat": "/help", # show overall help — chat actions in help
|
|
376
|
+
"projects": "/genesis",
|
|
377
|
+
"audits": "/audit",
|
|
378
|
+
"missions": "/help",
|
|
379
|
+
"sessions": "/sessions",
|
|
380
|
+
"accounts": "/accounts",
|
|
381
|
+
"vault": "/vault",
|
|
382
|
+
"health": "/doctor",
|
|
383
|
+
"scrape": "/help",
|
|
384
|
+
}
|
|
385
|
+
cmd = mapping.get(cat_id, "/help")
|
|
386
|
+
res = dispatch_slash(cmd)
|
|
387
|
+
self._content.write(f"\n[bold #D97757]── {cat_id} ──[/]\n")
|
|
388
|
+
self._content.write(res.text)
|
|
389
|
+
|
|
390
|
+
def on_input_submitted(self, event: Any) -> None:
|
|
391
|
+
"""User typed a slash command."""
|
|
392
|
+
value = event.value
|
|
393
|
+
if not value:
|
|
394
|
+
return
|
|
395
|
+
if self._content:
|
|
396
|
+
self._content.write(f"\n[bold #D97757]Ω ›[/] {value}\n")
|
|
397
|
+
res = dispatch_slash(value)
|
|
398
|
+
if event.input:
|
|
399
|
+
event.input.value = ""
|
|
400
|
+
if res.exit_tui:
|
|
401
|
+
self.action_quit_omega()
|
|
402
|
+
return
|
|
403
|
+
if res.detach:
|
|
404
|
+
self.action_detach_omega()
|
|
405
|
+
return
|
|
406
|
+
if res.text and self._content:
|
|
407
|
+
self._content.write(res.text)
|
|
408
|
+
if res.session_jump:
|
|
409
|
+
_switch_client(res.session_jump)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def run_tui() -> int:
|
|
413
|
+
"""Entry point — `omega menu-tui` calls this."""
|
|
414
|
+
if not TEXTUAL_AVAILABLE:
|
|
415
|
+
print(" textual not installed — `omega upgrade` or run:")
|
|
416
|
+
print(" pip install textual")
|
|
417
|
+
print()
|
|
418
|
+
print(" Falling back to plain prompt mode.")
|
|
419
|
+
return _plain_repl()
|
|
420
|
+
app = OmegaTUI()
|
|
421
|
+
app.run()
|
|
422
|
+
return 0
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
# ---------------------------------------------------------------------------
|
|
426
|
+
# Plain REPL fallback (when textual isn't installed)
|
|
427
|
+
# ---------------------------------------------------------------------------
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def _plain_repl() -> int:
|
|
431
|
+
"""Slash-command REPL with no textual TUI — same command set."""
|
|
432
|
+
from omega_engine import __version__
|
|
433
|
+
print(f"\n Ω Omega OS v{__version__} — plain REPL mode")
|
|
434
|
+
print(" Type /help for commands, /quit to exit.\n")
|
|
435
|
+
while True:
|
|
436
|
+
try:
|
|
437
|
+
line = input(" Ω › ").strip()
|
|
438
|
+
except (EOFError, KeyboardInterrupt):
|
|
439
|
+
print()
|
|
440
|
+
return 0
|
|
441
|
+
if not line:
|
|
442
|
+
continue
|
|
443
|
+
res = dispatch_slash(line)
|
|
444
|
+
if res.exit_tui:
|
|
445
|
+
subprocess.run(["tmux", "kill-session", "-t", "Omega"],
|
|
446
|
+
capture_output=True)
|
|
447
|
+
return 0
|
|
448
|
+
if res.detach:
|
|
449
|
+
subprocess.run(["tmux", "detach-client"], capture_output=True)
|
|
450
|
+
return 0
|
|
451
|
+
if res.text:
|
|
452
|
+
print()
|
|
453
|
+
for ln in res.text.splitlines():
|
|
454
|
+
print(f" {ln}")
|
|
455
|
+
print()
|
|
456
|
+
if res.session_jump:
|
|
457
|
+
_switch_client(res.session_jump)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "omega-engine"
|
|
3
|
-
version = "0.19.
|
|
3
|
+
version = "0.19.27"
|
|
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"
|
|
7
7
|
license = { text = "MIT" }
|
|
8
8
|
dependencies = [
|
|
9
9
|
"pyyaml>=6.0",
|
|
10
|
+
"textual>=1.0",
|
|
10
11
|
]
|
|
11
12
|
|
|
12
13
|
[project.optional-dependencies]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.19.
|
|
1
|
+
0.19.27
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentikos/omega-os",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.27",
|
|
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"
|