@agentikos/omega-os 0.19.12 → 0.19.13
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__/aisb_chat.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/aisb_chat.py +43 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/telegram.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/telegram.py +27 -14
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/stack.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/stack.py +30 -0
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/test_telegram_history.py +63 -15
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/docs/references/README.md +17 -0
- package/omega/Agentik_SSOT/skills/desktop-architecture/SKILL.md +61 -0
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -60,6 +60,49 @@ def _clear_history(home: Path) -> int:
|
|
|
60
60
|
conn.close()
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def chat_once(home: Path, text: str, *,
|
|
64
|
+
topic_id: int = None,
|
|
65
|
+
record_history: bool = True) -> str:
|
|
66
|
+
"""Run ONE conversation turn against the AISB envelope and return the
|
|
67
|
+
reply. Stateless from the caller's POV — history is persisted via
|
|
68
|
+
``telegram_history`` keyed on ``topic_id`` (a single global default
|
|
69
|
+
for the tmux REPL; chat_id for Telegram DMs to keep per-user threads).
|
|
70
|
+
|
|
71
|
+
Extracted so the Telegram DM path can talk to the same agent the
|
|
72
|
+
tmux REPL talks to, without duplicating env+envelope+provider plumbing.
|
|
73
|
+
"""
|
|
74
|
+
import time
|
|
75
|
+
from omega_engine.envelope import EnvelopeContext, build_envelope
|
|
76
|
+
from omega_engine.provider import AgentRequest
|
|
77
|
+
from omega_engine.router import ModelRouter
|
|
78
|
+
from omega_engine.telegram_history import (
|
|
79
|
+
build_context_prompt, record_inbound, record_outbound,
|
|
80
|
+
)
|
|
81
|
+
if topic_id is None:
|
|
82
|
+
topic_id = CHAT_TOPIC
|
|
83
|
+
if record_history:
|
|
84
|
+
record_inbound(home, topic_id=topic_id, text=text)
|
|
85
|
+
enriched = build_context_prompt(
|
|
86
|
+
home, topic_id=topic_id, new_intent=text, limit=10,
|
|
87
|
+
)
|
|
88
|
+
ctx = EnvelopeContext(
|
|
89
|
+
role="aisb",
|
|
90
|
+
intent=enriched,
|
|
91
|
+
task_id=f"chat-{int(time.time())}",
|
|
92
|
+
)
|
|
93
|
+
env = build_envelope(home, ctx)
|
|
94
|
+
router = ModelRouter.auto()
|
|
95
|
+
provider = router.resolve("aisb")
|
|
96
|
+
result = provider.run(AgentRequest(
|
|
97
|
+
role="aisb", prompt=env["user"], context={},
|
|
98
|
+
system=env["system"],
|
|
99
|
+
))
|
|
100
|
+
reply = (result.text or "").strip() or "(empty reply)"
|
|
101
|
+
if record_history:
|
|
102
|
+
record_outbound(home, topic_id=topic_id, text=reply)
|
|
103
|
+
return reply
|
|
104
|
+
|
|
105
|
+
|
|
63
106
|
def run_chat_loop() -> int:
|
|
64
107
|
"""Block until /quit. Returns 0 on clean exit."""
|
|
65
108
|
home = _omega_home()
|
|
Binary file
|
|
@@ -153,33 +153,46 @@ def _route_one(
|
|
|
153
153
|
"""
|
|
154
154
|
from omega_engine import telegram_history
|
|
155
155
|
|
|
156
|
-
# DM (no topic) —
|
|
157
|
-
#
|
|
158
|
-
#
|
|
156
|
+
# DM (no topic) — route to the AISB conversational agent (same one
|
|
157
|
+
# the tmux REPL talks to). This used to refuse with "Missions only
|
|
158
|
+
# run from a project topic" which broke the most basic UX (a fresh
|
|
159
|
+
# install has no group topic yet, so the bot was effectively dead).
|
|
160
|
+
#
|
|
161
|
+
# Per-chat conversation history is namespaced by chat_id (encoded
|
|
162
|
+
# as a negative topic_id to avoid collisions with real Telegram
|
|
163
|
+
# forum topics, which are always positive small integers).
|
|
159
164
|
if topic_id is None:
|
|
160
|
-
|
|
161
|
-
# bot's eventual reply (handled elsewhere) are linked.
|
|
165
|
+
dm_topic = -abs(int(chat_id)) if chat_id is not None else 0
|
|
162
166
|
telegram_history.record_inbound(
|
|
163
|
-
home, topic_id=
|
|
167
|
+
home, topic_id=dm_topic, text=text, message_id=message_id,
|
|
164
168
|
)
|
|
165
169
|
logger.info(
|
|
166
|
-
"telegram in: DM (chat=%s) text=%r —
|
|
167
|
-
"mission from the DM; ask in a project topic instead",
|
|
170
|
+
"telegram in: DM (chat=%s) text=%r — routing to AISB chat",
|
|
168
171
|
chat_id, text[:80],
|
|
169
172
|
)
|
|
173
|
+
try:
|
|
174
|
+
from omega_engine.aisb_chat import chat_once
|
|
175
|
+
reply = chat_once(home, text, topic_id=dm_topic,
|
|
176
|
+
record_history=False)
|
|
177
|
+
except Exception as exc: # noqa: BLE001
|
|
178
|
+
logger.warning("telegram DM: chat_once failed",
|
|
179
|
+
exc_info=True)
|
|
180
|
+
reply = (
|
|
181
|
+
f"I hit an error talking to the AISB agent: {exc}\n"
|
|
182
|
+
"Check `omega doctor` for provider/account status."
|
|
183
|
+
)
|
|
184
|
+
telegram_history.record_outbound(
|
|
185
|
+
home, topic_id=dm_topic, text=reply,
|
|
186
|
+
)
|
|
170
187
|
if telegram_bridge is not None and chat_id is not None:
|
|
171
188
|
try:
|
|
172
189
|
telegram_bridge._call("sendMessage", { # noqa: SLF001
|
|
173
190
|
"chat_id": str(chat_id),
|
|
174
|
-
"text":
|
|
175
|
-
"Missions only run from a project topic in the "
|
|
176
|
-
"OmegaOS group — not the DM. Open the topic for "
|
|
177
|
-
"the project and re-send your request there."
|
|
178
|
-
),
|
|
191
|
+
"text": reply[:3900],
|
|
179
192
|
})
|
|
180
193
|
except Exception: # noqa: BLE001
|
|
181
194
|
logger.warning("telegram daemon: DM reply failed", exc_info=True)
|
|
182
|
-
return "dm:
|
|
195
|
+
return "dm:aisb-chat"
|
|
183
196
|
|
|
184
197
|
# Topic message — record + route.
|
|
185
198
|
telegram_history.record_inbound(
|
|
Binary file
|
|
@@ -176,6 +176,35 @@ def _backend_supabase_stack() -> Stack:
|
|
|
176
176
|
)
|
|
177
177
|
|
|
178
178
|
|
|
179
|
+
def _claude_dashboard_stack() -> Stack:
|
|
180
|
+
"""The Claude Code-grade premium dashboard stack.
|
|
181
|
+
|
|
182
|
+
Picks up the architecture contract from
|
|
183
|
+
``Agentik_SSOT/docs/references/CLAUDE-DESKTOP-FRONTEND-ARCHITECTURE.md``
|
|
184
|
+
during PRD + branding + design-system phases. Worker prompts include
|
|
185
|
+
the `/desktop-architecture` skill so every generated component traces
|
|
186
|
+
back to the same reference doc.
|
|
187
|
+
"""
|
|
188
|
+
return Stack(
|
|
189
|
+
id="claude-dashboard",
|
|
190
|
+
title="Claude-grade premium dashboard (Next.js + Convex + shadcn + Motion + references doc)",
|
|
191
|
+
config=StackConfig(
|
|
192
|
+
type="web",
|
|
193
|
+
frontend="nextjs",
|
|
194
|
+
backend="convex",
|
|
195
|
+
deploy="vercel",
|
|
196
|
+
payments="stripe",
|
|
197
|
+
ui_kit="shadcn",
|
|
198
|
+
auth="clerk",
|
|
199
|
+
extras=["desktop-architecture-reference"],
|
|
200
|
+
),
|
|
201
|
+
why="When the operator wants the Claude / Linear / Vercel / Stripe / "
|
|
202
|
+
"Elevenlabs dashboard look. Genesis phases pull from "
|
|
203
|
+
"Agentik_SSOT/docs/references/CLAUDE-DESKTOP-FRONTEND-ARCHITECTURE.md "
|
|
204
|
+
"as the single source of design truth.",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
179
208
|
CANONICAL_STACKS: dict[str, Stack] = {
|
|
180
209
|
s.id: s for s in (
|
|
181
210
|
default_stack(),
|
|
@@ -183,6 +212,7 @@ CANONICAL_STACKS: dict[str, Stack] = {
|
|
|
183
212
|
_mobile_cross_stack(),
|
|
184
213
|
_desktop_tauri_stack(),
|
|
185
214
|
_backend_supabase_stack(),
|
|
215
|
+
_claude_dashboard_stack(),
|
|
186
216
|
)
|
|
187
217
|
}
|
|
188
218
|
|
package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313-pytest-8.4.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -142,10 +142,15 @@ class TestTopicStats(unittest.TestCase):
|
|
|
142
142
|
self.assertEqual(by_topic[2]["messages"], 1)
|
|
143
143
|
|
|
144
144
|
|
|
145
|
-
class
|
|
146
|
-
"""The daemon
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
class TestDaemonDMRoutesToAISBChat(unittest.TestCase):
|
|
146
|
+
"""The daemon now routes DMs to the AISB conversational agent
|
|
147
|
+
(v0.19.13 change). Previously it refused with "project topic only",
|
|
148
|
+
which made the bot mute on a fresh install with no group yet."""
|
|
149
|
+
|
|
150
|
+
def test_dm_message_routes_to_aisb_chat(self):
|
|
151
|
+
from omega_engine.daemons import telegram as T
|
|
152
|
+
from omega_engine import aisb_chat
|
|
153
|
+
from unittest import mock
|
|
149
154
|
|
|
150
155
|
class _FakeBridge:
|
|
151
156
|
def __init__(self):
|
|
@@ -161,22 +166,65 @@ class TestDaemonDMRefusal(unittest.TestCase):
|
|
|
161
166
|
with tempfile.TemporaryDirectory() as td:
|
|
162
167
|
home = Path(td)
|
|
163
168
|
bridge = _FakeBridge()
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
169
|
+
with mock.patch.object(aisb_chat, "chat_once",
|
|
170
|
+
return_value="hello from AISB"):
|
|
171
|
+
tag = T._route_one(
|
|
172
|
+
topic_id=None, text="hi from DM",
|
|
173
|
+
message_id=5, chat_id=12345,
|
|
174
|
+
supervisor=_FakeSupervisor(),
|
|
175
|
+
project_map={},
|
|
176
|
+
home=home,
|
|
177
|
+
telegram_bridge=bridge,
|
|
178
|
+
)
|
|
179
|
+
self.assertEqual(tag, "dm:aisb-chat",
|
|
180
|
+
"DM must now be tagged as routed to AISB, not refused")
|
|
181
|
+
# We sent the AISB reply back via sendMessage.
|
|
174
182
|
self.assertEqual(len(bridge.calls), 1)
|
|
175
183
|
self.assertEqual(bridge.calls[0]["method"], "sendMessage")
|
|
176
184
|
self.assertEqual(
|
|
177
185
|
str(bridge.calls[0]["fields"]["chat_id"]), "12345",
|
|
178
186
|
)
|
|
179
|
-
self.
|
|
187
|
+
self.assertEqual(
|
|
188
|
+
bridge.calls[0]["fields"]["text"], "hello from AISB",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def test_dm_history_is_namespaced_by_chat_id(self):
|
|
192
|
+
"""Two DMs from different chats must NOT cross-contaminate history.
|
|
193
|
+
We use negative topic_ids derived from chat_id (real topics are
|
|
194
|
+
always positive Telegram forum thread IDs)."""
|
|
195
|
+
from omega_engine.daemons import telegram as T
|
|
196
|
+
from omega_engine import aisb_chat
|
|
197
|
+
from unittest import mock
|
|
198
|
+
|
|
199
|
+
class _FakeBridge:
|
|
200
|
+
def __init__(self): self.calls = []
|
|
201
|
+
def _call(self, method, fields, **_kw):
|
|
202
|
+
self.calls.append({"method": method, "fields": fields})
|
|
203
|
+
return {"message_id": 1}
|
|
204
|
+
|
|
205
|
+
class _FakeSupervisor:
|
|
206
|
+
def on_channel_message(self, t, x): return []
|
|
207
|
+
|
|
208
|
+
with tempfile.TemporaryDirectory() as td:
|
|
209
|
+
home = Path(td)
|
|
210
|
+
(home / "Agentik_Runtime").mkdir(parents=True)
|
|
211
|
+
captured: list[int] = []
|
|
212
|
+
def _fake_chat(home_arg, text, *, topic_id, record_history):
|
|
213
|
+
captured.append(topic_id)
|
|
214
|
+
return "ok"
|
|
215
|
+
with mock.patch.object(aisb_chat, "chat_once",
|
|
216
|
+
side_effect=_fake_chat):
|
|
217
|
+
T._route_one(topic_id=None, text="hi", message_id=1,
|
|
218
|
+
chat_id=42, supervisor=_FakeSupervisor(),
|
|
219
|
+
project_map={}, home=home,
|
|
220
|
+
telegram_bridge=_FakeBridge())
|
|
221
|
+
T._route_one(topic_id=None, text="hi", message_id=2,
|
|
222
|
+
chat_id=99, supervisor=_FakeSupervisor(),
|
|
223
|
+
project_map={}, home=home,
|
|
224
|
+
telegram_bridge=_FakeBridge())
|
|
225
|
+
self.assertEqual(captured, [-42, -99],
|
|
226
|
+
"DM history must be namespaced by chat_id "
|
|
227
|
+
"(encoded as negative topic_id)")
|
|
180
228
|
|
|
181
229
|
def test_topic_message_records_history(self):
|
|
182
230
|
from omega_engine.daemons.telegram import _route_one
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.19.
|
|
1
|
+
0.19.13
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# References
|
|
2
|
+
|
|
3
|
+
Operator-curated source-of-truth documents that OmegaOS skills + Genesis
|
|
4
|
+
consume by name. Drop a new version of any file here and it propagates
|
|
5
|
+
to every project at the next `omega sync`.
|
|
6
|
+
|
|
7
|
+
## Active references
|
|
8
|
+
|
|
9
|
+
| File | Consumed by | Topic |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `CLAUDE-DESKTOP-FRONTEND-ARCHITECTURE.md` | `/desktop-architecture`, Genesis stack `claude-dashboard`, refonte audit | Premium desktop / dashboard UI architecture, the "Claude / Linear / Vercel / Stripe / Elevenlabs" canon |
|
|
12
|
+
|
|
13
|
+
## Format
|
|
14
|
+
|
|
15
|
+
Plain Markdown. No frontmatter needed — these are reference docs, not
|
|
16
|
+
SKILL.md. Headings should be self-describing so skills can extract
|
|
17
|
+
sub-sections by regex if needed.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: desktop-architecture
|
|
3
|
+
description: >
|
|
4
|
+
Reference skill — pull the canonical Claude Code-grade desktop/dashboard
|
|
5
|
+
architecture (`Agentik_SSOT/docs/references/CLAUDE-DESKTOP-FRONTEND-ARCHITECTURE.md`)
|
|
6
|
+
and apply it to a project. Triggers on "desktop architecture", "Claude
|
|
7
|
+
dashboard", "Claude desktop", "premium dashboard", "comme Linear / Vercel
|
|
8
|
+
/ Stripe / Elevenlabs", "dashboard senior", "claude stack". Use whenever
|
|
9
|
+
the user asks for a dashboard refonte or a new project that needs the
|
|
10
|
+
Claude-grade desktop look.
|
|
11
|
+
when_to_use: >
|
|
12
|
+
User mentions "desktop architecture", "Claude dashboard", "Claude desktop
|
|
13
|
+
stack", or asks for a dashboard rebuild "comme Claude / Linear / Vercel /
|
|
14
|
+
Stripe / Elevenlabs". Also triggers automatically when the Genesis stack
|
|
15
|
+
picker selects the `claude-dashboard` preset.
|
|
16
|
+
allowed-tools: Read Grep Glob
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# /desktop-architecture — pull the canonical Claude dashboard reference
|
|
20
|
+
|
|
21
|
+
This skill loads the **Claude Desktop Frontend Architecture** reference
|
|
22
|
+
document from the SSOT and applies its principles to the current task.
|
|
23
|
+
|
|
24
|
+
## What it does
|
|
25
|
+
|
|
26
|
+
1. Reads `$OMEGA_HOME/Agentik_SSOT/docs/references/CLAUDE-DESKTOP-FRONTEND-ARCHITECTURE.md`
|
|
27
|
+
2. Extracts the relevant section (components, layout, motion, palette,
|
|
28
|
+
typography, density, navigation, command palette, etc.)
|
|
29
|
+
3. Applies it as the design contract for the requested task:
|
|
30
|
+
- **Refonte audit** — score the current UI against this contract
|
|
31
|
+
- **Genesis** — when stack = `claude-dashboard`, the PRD, branding and
|
|
32
|
+
design-system phases derive their tokens from this doc
|
|
33
|
+
- **Component builder** — when a worker generates a new dashboard
|
|
34
|
+
screen, it references the layout primitives from this doc first
|
|
35
|
+
|
|
36
|
+
## Triggers (any of these in a user prompt invoke me)
|
|
37
|
+
|
|
38
|
+
- `desktop architecture`
|
|
39
|
+
- `Claude desktop` / `Claude dashboard` / `Claude stack`
|
|
40
|
+
- `premium dashboard` / `dashboard senior`
|
|
41
|
+
- `comme Linear` / `comme Vercel` / `comme Stripe` / `comme Elevenlabs`
|
|
42
|
+
- `refais le dashboard` / `redesign dashboard` (combined with project name)
|
|
43
|
+
|
|
44
|
+
## Where it lives
|
|
45
|
+
|
|
46
|
+
The reference doc itself lives at:
|
|
47
|
+
`$OMEGA_HOME/Agentik_SSOT/docs/references/CLAUDE-DESKTOP-FRONTEND-ARCHITECTURE.md`
|
|
48
|
+
|
|
49
|
+
It's the single source of truth — when Gareth refreshes the document
|
|
50
|
+
(e.g. new components, new motion language), every project re-reads it
|
|
51
|
+
on next `/desktop-architecture` invocation. No fork, no drift.
|
|
52
|
+
|
|
53
|
+
## How to refresh the reference
|
|
54
|
+
|
|
55
|
+
The operator drops a new version into the SSOT path above, then runs:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
omega sync # projects to ~/.claude/skills/<id>/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Workers spawned after the sync pick up the new content automatically.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentikos/omega-os",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.13",
|
|
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"
|