@agentikos/omega-os 0.1.0 → 0.19.5
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/README.md +56 -14
- package/bootstrap/lib/__pycache__/claude-code-settings.cpython-313.pyc +0 -0
- package/bootstrap/lib/__pycache__/llm-clis.cpython-313.pyc +0 -0
- package/bootstrap/lib/__pycache__/manifest-helpers.cpython-313.pyc +0 -0
- package/bootstrap/lib/claude-code-settings.py +176 -0
- package/bootstrap/lib/common.sh +457 -1
- package/bootstrap/lib/llm-clis.py +341 -0
- package/bootstrap/lib/manifest-helpers.py +384 -0
- package/bootstrap/lib/steps.sh +1000 -26
- package/bootstrap/manifest.example.yaml +93 -2
- package/bootstrap/templates/aisb/CLAUDE.md +305 -0
- package/bootstrap/templates/aisb/architect.md +204 -0
- package/bootstrap/templates/aisb/checkers/CLAUDE.md +9 -0
- package/bootstrap/templates/aisb/checkers/checker-architect.md +151 -0
- package/bootstrap/templates/aisb/checkers/checker-common.md +171 -0
- package/bootstrap/templates/aisb/checkers/checker-construct.md +129 -0
- package/bootstrap/templates/aisb/checkers/checker-keymaker.md +204 -0
- package/bootstrap/templates/aisb/checkers/checker-link.md +205 -0
- package/bootstrap/templates/aisb/checkers/checker-merovingian.md +219 -0
- package/bootstrap/templates/aisb/checkers/checker-morpheus.md +211 -0
- package/bootstrap/templates/aisb/checkers/checker-neo.md +177 -0
- package/bootstrap/templates/aisb/checkers/checker-niobe.md +156 -0
- package/bootstrap/templates/aisb/checkers/checker-oracle.md +164 -0
- package/bootstrap/templates/aisb/checkers/checker-seraph.md +187 -0
- package/bootstrap/templates/aisb/checkers/checker-smith.md +195 -0
- package/bootstrap/templates/aisb/checkers/checker-zion.md +113 -0
- package/bootstrap/templates/aisb/construct.md +135 -0
- package/bootstrap/templates/aisb/keymaker.md +227 -0
- package/bootstrap/templates/aisb/link.md +170 -0
- package/bootstrap/templates/aisb/lmc-protocol.md +57 -0
- package/bootstrap/templates/aisb/merovingian.md +159 -0
- package/bootstrap/templates/aisb/morpheus.md +243 -0
- package/bootstrap/templates/aisb/neo.md +147 -0
- package/bootstrap/templates/aisb/niobe.md +197 -0
- package/bootstrap/templates/aisb/oracle.md +244 -0
- package/bootstrap/templates/aisb/protocols/handoff-templates.md +204 -0
- package/bootstrap/templates/aisb/protocols/shared-protocol.md +248 -0
- package/bootstrap/templates/aisb/pythia.md +153 -0
- package/bootstrap/templates/aisb/seraph.md +315 -0
- package/bootstrap/templates/aisb/smith.md +202 -0
- package/bootstrap/templates/aisb/zion.md +172 -0
- package/bootstrap/templates/autonomous/audit-patrol.yaml +41 -0
- package/bootstrap/templates/autonomous/smith-reflect.yaml +43 -0
- package/bootstrap/templates/autonomous/ssh-key-rotate.yaml +46 -0
- package/bootstrap/templates/autonomous/support-agent.yaml +38 -0
- package/docs/AUDITS.md +85 -0
- package/docs/COMPLETION-PLAN.md +48 -0
- package/docs/GAP-ANALYSIS.md +214 -0
- package/docs/INSTALL.md +47 -9
- package/docs/MCP-AND-PLUGINS.md +31 -4
- package/docs/SIMULATION.md +171 -0
- package/docs/simulate.sh +211 -0
- package/install.sh +164 -17
- package/omega/Agentik_Engine/README.md +27 -10
- package/omega/Agentik_Engine/omega_engine/__init__.py +212 -2
- package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/account.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/agent_messages.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/__pycache__/audit_diff.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/audit_gate.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/auto_update.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/autonomous.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/backup.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cadence.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/classifier.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cleanup.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__/completions.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/costs.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/done_signal.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/envelope.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/executor.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/handoff.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__/hermes_bootstrap.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_desktop.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/learning.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/managed_agent.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/memory.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/menu.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/mission.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/plan.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/project.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/prompts.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__/prune.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/pursue.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/reducer.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/router.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/skill_routing.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/smoke.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/store.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/sync.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/telegram_history.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__/tools.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/understand_anything.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/updater.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/validate.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/vault.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/webhooks.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/worker.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/account.py +502 -0
- package/omega/Agentik_Engine/omega_engine/agent_messages.py +167 -0
- package/omega/Agentik_Engine/omega_engine/aisb_chat.py +128 -0
- package/omega/Agentik_Engine/omega_engine/audit_diff.py +99 -0
- package/omega/Agentik_Engine/omega_engine/audit_gate.py +149 -0
- package/omega/Agentik_Engine/omega_engine/audits/__init__.py +60 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/batcher.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/dispatcher.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/generator.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/history.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/pipeline.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/batcher.py +218 -0
- package/omega/Agentik_Engine/omega_engine/audits/dispatcher.py +92 -0
- package/omega/Agentik_Engine/omega_engine/audits/generator.py +234 -0
- package/omega/Agentik_Engine/omega_engine/audits/history.py +168 -0
- package/omega/Agentik_Engine/omega_engine/audits/pipeline.py +198 -0
- package/omega/Agentik_Engine/omega_engine/auto_update.py +339 -0
- package/omega/Agentik_Engine/omega_engine/autonomous.py +538 -0
- package/omega/Agentik_Engine/omega_engine/backup.py +215 -0
- package/omega/Agentik_Engine/omega_engine/cadence.py +158 -0
- package/omega/Agentik_Engine/omega_engine/classifier.py +215 -0
- package/omega/Agentik_Engine/omega_engine/cleanup.py +673 -0
- package/omega/Agentik_Engine/omega_engine/cli.py +4564 -56
- package/omega/Agentik_Engine/omega_engine/completions.py +260 -0
- package/omega/Agentik_Engine/omega_engine/costs.py +100 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__init__.py +14 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/autonomous.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/engine.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/telegram.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/autonomous.py +56 -0
- package/omega/Agentik_Engine/omega_engine/daemons/engine.py +236 -0
- package/omega/Agentik_Engine/omega_engine/daemons/telegram.py +315 -0
- package/omega/Agentik_Engine/omega_engine/done_signal.py +154 -0
- package/omega/Agentik_Engine/omega_engine/educators/__init__.py +51 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/artifact.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/automation.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/base.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/claudecode.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/connection.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/coworker.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/loop.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/prompt.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/skill.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/artifact.py +65 -0
- package/omega/Agentik_Engine/omega_engine/educators/automation.py +76 -0
- package/omega/Agentik_Engine/omega_engine/educators/base.py +327 -0
- package/omega/Agentik_Engine/omega_engine/educators/claudecode.py +71 -0
- package/omega/Agentik_Engine/omega_engine/educators/connection.py +75 -0
- package/omega/Agentik_Engine/omega_engine/educators/coworker.py +68 -0
- package/omega/Agentik_Engine/omega_engine/educators/loop.py +82 -0
- package/omega/Agentik_Engine/omega_engine/educators/prompt.py +68 -0
- package/omega/Agentik_Engine/omega_engine/educators/skill.py +69 -0
- package/omega/Agentik_Engine/omega_engine/envelope.py +219 -0
- package/omega/Agentik_Engine/omega_engine/executor.py +195 -16
- package/omega/Agentik_Engine/omega_engine/genesis/__init__.py +134 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/orchestrator.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/phases.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/stack.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/state.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/orchestrator.py +262 -0
- package/omega/Agentik_Engine/omega_engine/genesis/phases.py +950 -0
- package/omega/Agentik_Engine/omega_engine/genesis/stack.py +324 -0
- package/omega/Agentik_Engine/omega_engine/genesis/state.py +353 -0
- package/omega/Agentik_Engine/omega_engine/handoff.py +459 -0
- package/omega/Agentik_Engine/omega_engine/hermes.py +426 -0
- package/omega/Agentik_Engine/omega_engine/hermes_bootstrap.py +382 -0
- package/omega/Agentik_Engine/omega_engine/hermes_desktop.py +469 -0
- package/omega/Agentik_Engine/omega_engine/integrations/__init__.py +30 -0
- package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/graphify.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/integrations/graphify.py +234 -0
- package/omega/Agentik_Engine/omega_engine/learning.py +268 -0
- package/omega/Agentik_Engine/omega_engine/managed_agent.py +467 -0
- package/omega/Agentik_Engine/omega_engine/memory.py +271 -0
- package/omega/Agentik_Engine/omega_engine/menu.py +1065 -0
- package/omega/Agentik_Engine/omega_engine/migrations/__init__.py +144 -0
- package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/v0_14_0.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/migrations/v0_14_0.py +29 -0
- package/omega/Agentik_Engine/omega_engine/mission.py +29 -14
- package/omega/Agentik_Engine/omega_engine/plan.py +846 -0
- package/omega/Agentik_Engine/omega_engine/prompts.py +158 -0
- package/omega/Agentik_Engine/omega_engine/provider.py +408 -13
- package/omega/Agentik_Engine/omega_engine/prune.py +151 -0
- package/omega/Agentik_Engine/omega_engine/pursue.py +205 -0
- package/omega/Agentik_Engine/omega_engine/rag/__init__.py +21 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/agentic.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/base.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/corrective.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/graph.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/hybrid.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/multimodal.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/router.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/agentic.py +83 -0
- package/omega/Agentik_Engine/omega_engine/rag/base.py +42 -0
- package/omega/Agentik_Engine/omega_engine/rag/corrective.py +119 -0
- package/omega/Agentik_Engine/omega_engine/rag/graph.py +169 -0
- package/omega/Agentik_Engine/omega_engine/rag/hybrid.py +205 -0
- package/omega/Agentik_Engine/omega_engine/rag/multimodal.py +136 -0
- package/omega/Agentik_Engine/omega_engine/rag/router.py +110 -0
- package/omega/Agentik_Engine/omega_engine/reducer.py +21 -3
- package/omega/Agentik_Engine/omega_engine/router.py +28 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__init__.py +48 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/auditor.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/finder.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/installer.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/marketplaces.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/auditor.py +232 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/finder.py +94 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/installer.py +129 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/marketplaces.py +80 -0
- package/omega/Agentik_Engine/omega_engine/skill_routing.py +388 -0
- package/omega/Agentik_Engine/omega_engine/smoke.py +81 -0
- package/omega/Agentik_Engine/omega_engine/store.py +132 -25
- package/omega/Agentik_Engine/omega_engine/sync.py +445 -0
- package/omega/Agentik_Engine/omega_engine/telegram_history.py +260 -0
- package/omega/Agentik_Engine/omega_engine/tmux.py +526 -0
- package/omega/Agentik_Engine/omega_engine/tools.py +272 -0
- package/omega/Agentik_Engine/omega_engine/understand_anything.py +275 -0
- package/omega/Agentik_Engine/omega_engine/updater.py +70 -0
- package/omega/Agentik_Engine/omega_engine/validate.py +186 -0
- package/omega/Agentik_Engine/omega_engine/vault.py +342 -0
- package/omega/Agentik_Engine/omega_engine/webhooks.py +262 -0
- package/omega/Agentik_Engine/omega_engine/worker.py +526 -0
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_audit_arsenal.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_executor.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313.pyc +0 -0
- 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_hermes_bootstrap_and_desktop.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.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/__pycache__/test_intelligence.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_mission.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_progress.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_project.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_reducer.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_report.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313.pyc +0 -0
- 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/__pycache__/test_tmux_and_aisb_chat.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/test_account.py +338 -0
- package/omega/Agentik_Engine/tests/test_adversarial.py +351 -0
- package/omega/Agentik_Engine/tests/test_agents_envelope.py +274 -0
- package/omega/Agentik_Engine/tests/test_audits_pipeline.py +348 -0
- package/omega/Agentik_Engine/tests/test_auto_update_and_migrations.py +394 -0
- package/omega/Agentik_Engine/tests/test_autonomous.py +361 -0
- package/omega/Agentik_Engine/tests/test_educators.py +233 -0
- package/omega/Agentik_Engine/tests/test_genesis_and_plan.py +573 -0
- package/omega/Agentik_Engine/tests/test_graphify.py +190 -0
- package/omega/Agentik_Engine/tests/test_handoff.py +311 -0
- package/omega/Agentik_Engine/tests/test_hermes_and_ua.py +387 -0
- package/omega/Agentik_Engine/tests/test_hermes_bootstrap_and_desktop.py +358 -0
- package/omega/Agentik_Engine/tests/test_install_steps.py +359 -0
- package/omega/Agentik_Engine/tests/test_install_ux.py +151 -0
- package/omega/Agentik_Engine/tests/test_installer_wiring.py +496 -0
- package/omega/Agentik_Engine/tests/test_intelligence.py +285 -0
- package/omega/Agentik_Engine/tests/test_llm_clis_and_uninstall.py +228 -0
- package/omega/Agentik_Engine/tests/test_managed_agent.py +363 -0
- package/omega/Agentik_Engine/tests/test_max_provider_and_menu.py +231 -0
- package/omega/Agentik_Engine/tests/test_menu_coverage.py +72 -0
- package/omega/Agentik_Engine/tests/test_pursue_cadence.py +217 -0
- package/omega/Agentik_Engine/tests/test_rag.py +287 -0
- package/omega/Agentik_Engine/tests/test_role_aliases_and_ssot.py +207 -0
- package/omega/Agentik_Engine/tests/test_skill_discovery_and_gate.py +337 -0
- package/omega/Agentik_Engine/tests/test_skill_power.py +259 -0
- package/omega/Agentik_Engine/tests/test_skill_routing.py +189 -0
- package/omega/Agentik_Engine/tests/test_snapshot_partial.py +172 -0
- package/omega/Agentik_Engine/tests/test_telegram_history.py +209 -0
- package/omega/Agentik_Engine/tests/test_tmux_and_aisb_chat.py +223 -0
- package/omega/Agentik_Engine/tests/test_tools_and_sync.py +312 -0
- package/omega/Agentik_Engine/tests/test_v06_features.py +370 -0
- package/omega/Agentik_Engine/tests/test_vault.py +173 -0
- package/omega/Agentik_Engine/tests/test_webhooks_and_readiness.py +277 -0
- package/omega/Agentik_Engine/tests/test_worker_and_cleanup.py +541 -0
- package/omega/Agentik_Extra/etc/secrets/.vault-key +3 -0
- package/omega/Agentik_Extra/etc/secrets/.vault-pub +1 -0
- package/omega/Agentik_Runtime/audits.db +0 -0
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/claude-plugins/claude-plugins.yaml +100 -0
- package/omega/Agentik_SSOT/docs/LAYERS.md +90 -0
- package/omega/Agentik_SSOT/docs/USER-JOURNEY.md +283 -0
- package/omega/Agentik_SSOT/marketplaces/design-discipline.yaml +86 -0
- package/omega/Agentik_SSOT/skills/a11yaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/apiaudit/SKILL.md +157 -0
- package/omega/Agentik_SSOT/skills/automationaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/cadence/SKILL.md +76 -0
- package/omega/Agentik_SSOT/skills/codeaudit/SKILL.md +153 -0
- package/omega/Agentik_SSOT/skills/copyaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/dataaudit/SKILL.md +157 -0
- package/omega/Agentik_SSOT/skills/debugaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/dispatch/SKILL.md +79 -0
- package/omega/Agentik_SSOT/skills/dxaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/featureaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/flowaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/genesis/SKILL.md +116 -0
- package/omega/Agentik_SSOT/skills/handoff/SKILL.md +117 -0
- package/omega/Agentik_SSOT/skills/logicaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/motionaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/perfaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/plan/SKILL.md +127 -0
- package/omega/Agentik_SSOT/skills/pursue/SKILL.md +68 -0
- package/omega/Agentik_SSOT/skills/rag-route.md +82 -0
- package/omega/Agentik_SSOT/skills/refontaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/retentionaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/secaudit/SKILL.md +157 -0
- package/omega/Agentik_SSOT/skills/seoaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/skill-auditor/SKILL.md +83 -0
- package/omega/Agentik_SSOT/skills/skill-finder/SKILL.md +116 -0
- package/omega/Agentik_SSOT/skills/uiuxaudit/SKILL.md +165 -0
- package/package.json +2 -2
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
"""Autonomous-agent supervisor — first-class persistent nodes of the engine.
|
|
2
|
+
|
|
3
|
+
An autonomous agent is a `Task` with `lifecycle: persistent` and a `Trigger`.
|
|
4
|
+
Charters live as YAML files in `Agentik_Orchestration/autonomous/`. The
|
|
5
|
+
supervisor loads every charter, schedules each agent, and — when a trigger
|
|
6
|
+
fires — opens a mission via the same `run_mission()` pipeline the rest of the
|
|
7
|
+
engine uses. The autonomous agent inherits verified completion and the deadman
|
|
8
|
+
for free; it is *our* architecture, configured.
|
|
9
|
+
|
|
10
|
+
Four trigger types are honoured:
|
|
11
|
+
|
|
12
|
+
* ``cron`` -- a 5-field schedule (`m h d M w`). Numeric, ``*``, ``*/N``,
|
|
13
|
+
comma lists. The supervisor's main loop polls due agents.
|
|
14
|
+
* ``event`` -- subscribed to the event bus; fires when an event matches the
|
|
15
|
+
configured ``event_type`` pattern.
|
|
16
|
+
* ``webhook`` -- the supervisor exposes :meth:`wake_webhook` — an external
|
|
17
|
+
HTTP shim invokes it when a request arrives at the agent's
|
|
18
|
+
webhook_path.
|
|
19
|
+
* ``channel`` -- the Telegram daemon calls :meth:`on_channel_message` for
|
|
20
|
+
messages on the agent's bound topic.
|
|
21
|
+
|
|
22
|
+
The supervisor is deliberately stdlib-only: it can run on a fresh VPS with no
|
|
23
|
+
extra Python deps beyond pyyaml (already an engine dep).
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import logging
|
|
28
|
+
import os
|
|
29
|
+
import signal
|
|
30
|
+
import threading
|
|
31
|
+
import time
|
|
32
|
+
from dataclasses import dataclass, field
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from typing import Any, Callable, Optional
|
|
35
|
+
|
|
36
|
+
import yaml
|
|
37
|
+
|
|
38
|
+
from omega_engine.events import Event
|
|
39
|
+
from omega_engine.task import Lifecycle
|
|
40
|
+
|
|
41
|
+
logger = logging.getLogger("omega.autonomous")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
45
|
+
# Charter
|
|
46
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class Charter:
|
|
50
|
+
"""A persistent agent's contract — one YAML file = one charter.
|
|
51
|
+
|
|
52
|
+
The dataclass mirrors the fields documented in
|
|
53
|
+
``docs/AUTONOMOUS-AGENTS.md`` §3. Missing optional fields fall back to the
|
|
54
|
+
same defaults the example charters use.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
id: str
|
|
58
|
+
role: str
|
|
59
|
+
trigger_type: str # "cron" | "event" | "webhook" | "channel"
|
|
60
|
+
trigger_config: dict[str, Any] = field(default_factory=dict)
|
|
61
|
+
charter: str = ""
|
|
62
|
+
lifecycle: str = Lifecycle.PERSISTENT.value
|
|
63
|
+
channel_topic: Optional[int] = None
|
|
64
|
+
max_iterations: int = 5
|
|
65
|
+
heartbeat_interval_s: int = 300
|
|
66
|
+
provider: Optional[str] = None
|
|
67
|
+
allowed_skills: list[str] = field(default_factory=list)
|
|
68
|
+
allowed_mcp: list[str] = field(default_factory=list)
|
|
69
|
+
allowed_topologies: list[str] = field(default_factory=list)
|
|
70
|
+
may_spawn_missions: bool = True
|
|
71
|
+
may_ship: bool = False
|
|
72
|
+
source_file: Optional[str] = None # filled by load_charters for diagnostics
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _is_charter_mapping(value: Any) -> bool:
|
|
76
|
+
"""A YAML top-level mapping is a charter iff it has id + role + trigger.
|
|
77
|
+
|
|
78
|
+
This is what lets a single file hold both worked examples and the template
|
|
79
|
+
block (which lacks an ``id``/``role`` — the template is a placeholder, not
|
|
80
|
+
a charter).
|
|
81
|
+
"""
|
|
82
|
+
if not isinstance(value, dict):
|
|
83
|
+
return False
|
|
84
|
+
if not value.get("id") or not value.get("role"):
|
|
85
|
+
return False
|
|
86
|
+
trig = value.get("trigger")
|
|
87
|
+
if not isinstance(trig, dict) or not trig.get("type"):
|
|
88
|
+
return False
|
|
89
|
+
return True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _charter_from_mapping(data: dict[str, Any], *,
|
|
93
|
+
source_file: str | None = None) -> Charter:
|
|
94
|
+
trig = data.get("trigger") or {}
|
|
95
|
+
chan = data.get("channel") or {}
|
|
96
|
+
budget = data.get("budget") or {}
|
|
97
|
+
allowed = data.get("allowed") or {}
|
|
98
|
+
guard = data.get("guardrails") or {}
|
|
99
|
+
return Charter(
|
|
100
|
+
id=str(data["id"]),
|
|
101
|
+
role=str(data["role"]),
|
|
102
|
+
trigger_type=str(trig.get("type", "")),
|
|
103
|
+
trigger_config=dict(trig.get("config") or {}),
|
|
104
|
+
charter=str(data.get("charter", "")).strip(),
|
|
105
|
+
lifecycle=str(data.get("lifecycle", Lifecycle.PERSISTENT.value)),
|
|
106
|
+
channel_topic=chan.get("telegram_topic"),
|
|
107
|
+
max_iterations=int(budget.get("max_iterations", 5)),
|
|
108
|
+
heartbeat_interval_s=int(budget.get("heartbeat_interval_s", 300)),
|
|
109
|
+
provider=data.get("provider"),
|
|
110
|
+
allowed_skills=list(allowed.get("skills") or []),
|
|
111
|
+
allowed_mcp=list(allowed.get("mcp") or []),
|
|
112
|
+
allowed_topologies=list(allowed.get("topologies") or []),
|
|
113
|
+
may_spawn_missions=bool(guard.get("may_spawn_missions", True)),
|
|
114
|
+
may_ship=bool(guard.get("may_ship", False)),
|
|
115
|
+
source_file=source_file,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def load_charters(directory: str | Path) -> list[Charter]:
|
|
120
|
+
"""Load every charter under ``directory`` — recursively scans ``*.yaml``.
|
|
121
|
+
|
|
122
|
+
A YAML file may hold ONE charter at top level OR a mapping-of-mappings where
|
|
123
|
+
each value is a charter (the example file uses the second form). Entries
|
|
124
|
+
that do not look like a charter (e.g. the ``template:`` placeholder block in
|
|
125
|
+
the example) are silently skipped — they're documentation, not agents.
|
|
126
|
+
"""
|
|
127
|
+
base = Path(directory)
|
|
128
|
+
out: list[Charter] = []
|
|
129
|
+
if not base.is_dir():
|
|
130
|
+
return out
|
|
131
|
+
|
|
132
|
+
for path in sorted(base.rglob("*.yaml")):
|
|
133
|
+
try:
|
|
134
|
+
data = yaml.safe_load(path.read_text()) or {}
|
|
135
|
+
except yaml.YAMLError as exc:
|
|
136
|
+
logger.warning("autonomous: cannot parse %s: %s", path, exc)
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
if not isinstance(data, dict):
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
# case 1: the whole file IS a single charter
|
|
143
|
+
if _is_charter_mapping(data):
|
|
144
|
+
out.append(_charter_from_mapping(data, source_file=str(path)))
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
# case 2: mapping of named charters (the example file). Each value that
|
|
148
|
+
# looks like a charter is loaded; everything else (template, comments)
|
|
149
|
+
# is skipped.
|
|
150
|
+
for key, value in data.items():
|
|
151
|
+
if key == "template":
|
|
152
|
+
# the template block is explicitly documentation
|
|
153
|
+
continue
|
|
154
|
+
if _is_charter_mapping(value):
|
|
155
|
+
out.append(_charter_from_mapping(value, source_file=str(path)))
|
|
156
|
+
|
|
157
|
+
return out
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
161
|
+
# Minimal cron parser
|
|
162
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
# Field order: minute hour day-of-month month day-of-week
|
|
165
|
+
# Ranges: m=0-59 h=0-23 dom=1-31 mo=1-12 dow=0-6 (Sun=0)
|
|
166
|
+
_FIELD_RANGES: list[tuple[int, int]] = [
|
|
167
|
+
(0, 59), (0, 23), (1, 31), (1, 12), (0, 6),
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _parse_field(spec: str, lo: int, hi: int) -> set[int]:
|
|
172
|
+
"""Parse one cron field into the set of integers it matches.
|
|
173
|
+
|
|
174
|
+
Supported forms (covers every form used by the example charters):
|
|
175
|
+
*
|
|
176
|
+
N
|
|
177
|
+
a,b,c
|
|
178
|
+
*/N
|
|
179
|
+
a-b (range — same syntax as standard cron)
|
|
180
|
+
"""
|
|
181
|
+
spec = spec.strip()
|
|
182
|
+
if spec == "*":
|
|
183
|
+
return set(range(lo, hi + 1))
|
|
184
|
+
|
|
185
|
+
if spec.startswith("*/"):
|
|
186
|
+
step = int(spec[2:])
|
|
187
|
+
if step <= 0:
|
|
188
|
+
raise ValueError(f"step must be positive: {spec}")
|
|
189
|
+
return {n for n in range(lo, hi + 1) if (n - lo) % step == 0}
|
|
190
|
+
|
|
191
|
+
out: set[int] = set()
|
|
192
|
+
for piece in spec.split(","):
|
|
193
|
+
piece = piece.strip()
|
|
194
|
+
if "-" in piece:
|
|
195
|
+
a, b = piece.split("-", 1)
|
|
196
|
+
ai, bi = int(a), int(b)
|
|
197
|
+
if ai > bi or ai < lo or bi > hi:
|
|
198
|
+
raise ValueError(f"bad range {piece} for field [{lo},{hi}]")
|
|
199
|
+
out.update(range(ai, bi + 1))
|
|
200
|
+
else:
|
|
201
|
+
n = int(piece)
|
|
202
|
+
if n < lo or n > hi:
|
|
203
|
+
raise ValueError(f"value {n} outside [{lo},{hi}]")
|
|
204
|
+
out.add(n)
|
|
205
|
+
return out
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def parse_cron(spec: str) -> tuple[set[int], ...]:
|
|
209
|
+
"""Parse a 5-field cron spec into 5 sets — one per field."""
|
|
210
|
+
parts = spec.split()
|
|
211
|
+
if len(parts) != 5:
|
|
212
|
+
raise ValueError(
|
|
213
|
+
f"cron spec must have 5 fields, got {len(parts)}: {spec!r}"
|
|
214
|
+
)
|
|
215
|
+
return tuple(
|
|
216
|
+
_parse_field(parts[i], *_FIELD_RANGES[i]) for i in range(5)
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def next_fire(spec: str, now: float) -> float:
|
|
221
|
+
"""Return the next epoch second at or after ``now`` when ``spec`` fires.
|
|
222
|
+
|
|
223
|
+
Naive but correct: walk forward minute-by-minute. The example charters fire
|
|
224
|
+
at most a handful of times a day; the search is always bounded by the
|
|
225
|
+
longest legal gap (year + 1 day for safety). For the spec ``*/5 * * * *``
|
|
226
|
+
this returns now+~5min.
|
|
227
|
+
"""
|
|
228
|
+
minute, hour, dom, month, dow = parse_cron(spec)
|
|
229
|
+
# round up to next minute boundary
|
|
230
|
+
t = time.localtime(now)
|
|
231
|
+
candidate = time.mktime((
|
|
232
|
+
t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0,
|
|
233
|
+
0, 0, -1,
|
|
234
|
+
)) + 60 # next minute (drop seconds)
|
|
235
|
+
|
|
236
|
+
# 5 years bounded search — way past any reasonable schedule
|
|
237
|
+
cutoff = candidate + 366 * 24 * 60 * 60 * 5
|
|
238
|
+
while candidate < cutoff:
|
|
239
|
+
ct = time.localtime(candidate)
|
|
240
|
+
# cron weekday: Sun=0..Sat=6; struct_tm tm_wday: Mon=0..Sun=6
|
|
241
|
+
c_dow = (ct.tm_wday + 1) % 7
|
|
242
|
+
if (ct.tm_min in minute
|
|
243
|
+
and ct.tm_hour in hour
|
|
244
|
+
and ct.tm_mday in dom
|
|
245
|
+
and ct.tm_mon in month
|
|
246
|
+
and c_dow in dow):
|
|
247
|
+
return candidate
|
|
248
|
+
candidate += 60
|
|
249
|
+
raise RuntimeError(f"no cron fire within 5 years for {spec!r}")
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
253
|
+
# Supervisor
|
|
254
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
@dataclass
|
|
257
|
+
class _Schedule:
|
|
258
|
+
"""Per-charter scheduler bookkeeping. Only used internally."""
|
|
259
|
+
|
|
260
|
+
charter: Charter
|
|
261
|
+
next_fire_at: Optional[float] = None # cron only
|
|
262
|
+
last_run_at: Optional[float] = None
|
|
263
|
+
runs: int = 0
|
|
264
|
+
errors: int = 0
|
|
265
|
+
last_error: Optional[str] = None
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
# default runner type — what fires when a trigger trips
|
|
269
|
+
MissionRunner = Callable[..., Any]
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _default_runner(*, intent: str,
|
|
273
|
+
omega_home: str | Path | None,
|
|
274
|
+
topic_id: int | None,
|
|
275
|
+
telegram: Any | None,
|
|
276
|
+
charter: Charter) -> Any:
|
|
277
|
+
"""The production runner — delegates to :func:`run_mission` lazily.
|
|
278
|
+
|
|
279
|
+
Imported lazily so unit tests can build a supervisor without dragging the
|
|
280
|
+
full executor stack into the test fixture.
|
|
281
|
+
"""
|
|
282
|
+
from omega_engine.mission import run_mission
|
|
283
|
+
|
|
284
|
+
return run_mission(
|
|
285
|
+
intent=intent,
|
|
286
|
+
omega_home=omega_home,
|
|
287
|
+
topic_id=topic_id,
|
|
288
|
+
telegram=telegram,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
class AutonomousSupervisor:
|
|
293
|
+
"""Loads charters, schedules them, runs forever.
|
|
294
|
+
|
|
295
|
+
The supervisor is deliberately single-threaded: it polls its schedule on a
|
|
296
|
+
tick, dispatches due missions synchronously, and surfaces any per-charter
|
|
297
|
+
failure as a logged error — never as a process exit. One bad charter cannot
|
|
298
|
+
take the whole supervisor down.
|
|
299
|
+
"""
|
|
300
|
+
|
|
301
|
+
def __init__(
|
|
302
|
+
self,
|
|
303
|
+
charters: list[Charter],
|
|
304
|
+
*,
|
|
305
|
+
omega_home: str | Path | None = None,
|
|
306
|
+
telegram: Any | None = None,
|
|
307
|
+
bus: Any | None = None,
|
|
308
|
+
runner: MissionRunner | None = None,
|
|
309
|
+
tick_seconds: float = 5.0,
|
|
310
|
+
) -> None:
|
|
311
|
+
self._omega_home = omega_home
|
|
312
|
+
self._telegram = telegram
|
|
313
|
+
self._bus = bus
|
|
314
|
+
self._runner: MissionRunner = runner or _default_runner
|
|
315
|
+
self._tick = max(0.5, float(tick_seconds))
|
|
316
|
+
self._schedules: dict[str, _Schedule] = {
|
|
317
|
+
c.id: _Schedule(c) for c in charters
|
|
318
|
+
}
|
|
319
|
+
self._stop = threading.Event()
|
|
320
|
+
self._lock = threading.Lock()
|
|
321
|
+
# event-triggered agents register a bus subscription on .run()
|
|
322
|
+
# webhook + channel triggers are awakened by external callers
|
|
323
|
+
self._init_cron_schedules()
|
|
324
|
+
if bus is not None:
|
|
325
|
+
self._wire_event_subscribers()
|
|
326
|
+
|
|
327
|
+
# -- public surface ------------------------------------------------------
|
|
328
|
+
|
|
329
|
+
def charters(self) -> list[Charter]:
|
|
330
|
+
with self._lock:
|
|
331
|
+
return [s.charter for s in self._schedules.values()]
|
|
332
|
+
|
|
333
|
+
def stats(self) -> dict[str, dict[str, Any]]:
|
|
334
|
+
"""For ``omega status`` / diagnostics."""
|
|
335
|
+
with self._lock:
|
|
336
|
+
return {
|
|
337
|
+
cid: {
|
|
338
|
+
"trigger": s.charter.trigger_type,
|
|
339
|
+
"next_fire_at": s.next_fire_at,
|
|
340
|
+
"last_run_at": s.last_run_at,
|
|
341
|
+
"runs": s.runs,
|
|
342
|
+
"errors": s.errors,
|
|
343
|
+
"last_error": s.last_error,
|
|
344
|
+
}
|
|
345
|
+
for cid, s in self._schedules.items()
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
def stop(self) -> None:
|
|
349
|
+
"""Request a graceful shutdown. ``run()`` returns on the next tick."""
|
|
350
|
+
self._stop.set()
|
|
351
|
+
|
|
352
|
+
def run(self) -> None:
|
|
353
|
+
"""Main loop. Returns only when :meth:`stop` is called or SIGTERM/SIGINT
|
|
354
|
+
is received. Crashes inside a single charter never escape this loop."""
|
|
355
|
+
# one-time SIGTERM/SIGINT wiring — only if we're on the main thread
|
|
356
|
+
# (so the daemon CLI installs them; tests can drive run() differently).
|
|
357
|
+
try:
|
|
358
|
+
signal.signal(signal.SIGTERM, lambda *_: self.stop())
|
|
359
|
+
signal.signal(signal.SIGINT, lambda *_: self.stop())
|
|
360
|
+
except ValueError:
|
|
361
|
+
# not on the main thread — caller handles signals
|
|
362
|
+
pass
|
|
363
|
+
|
|
364
|
+
logger.info("autonomous supervisor: %d charter(s) active",
|
|
365
|
+
len(self._schedules))
|
|
366
|
+
while not self._stop.is_set():
|
|
367
|
+
self._tick_once()
|
|
368
|
+
self._stop.wait(self._tick)
|
|
369
|
+
logger.info("autonomous supervisor: stopping cleanly")
|
|
370
|
+
|
|
371
|
+
# explicit single-tick variant — used by tests to step the loop
|
|
372
|
+
def tick(self, now: float | None = None) -> list[str]:
|
|
373
|
+
"""Run one schedule pass; return the charter ids that fired this tick."""
|
|
374
|
+
return self._tick_once(now=now)
|
|
375
|
+
|
|
376
|
+
# -- trigger entry points ------------------------------------------------
|
|
377
|
+
|
|
378
|
+
def on_channel_message(self, topic_id: int, text: str) -> list[str]:
|
|
379
|
+
"""Wake every charter bound to ``topic_id`` (channel trigger).
|
|
380
|
+
|
|
381
|
+
The Telegram daemon calls this for every inbound message it sees. The
|
|
382
|
+
text becomes the mission intent — the charter's role + channel binding
|
|
383
|
+
is what makes it an autonomous-agent action and not a one-shot call.
|
|
384
|
+
"""
|
|
385
|
+
fired: list[str] = []
|
|
386
|
+
for sched in self._schedules.values():
|
|
387
|
+
c = sched.charter
|
|
388
|
+
if c.trigger_type != "channel":
|
|
389
|
+
continue
|
|
390
|
+
cfg_topic = c.trigger_config.get("telegram_topic", c.channel_topic)
|
|
391
|
+
if cfg_topic is None or int(cfg_topic) != int(topic_id):
|
|
392
|
+
continue
|
|
393
|
+
self._fire(sched, intent=text)
|
|
394
|
+
fired.append(c.id)
|
|
395
|
+
return fired
|
|
396
|
+
|
|
397
|
+
def wake_webhook(self, path: str, payload: dict[str, Any] | None = None
|
|
398
|
+
) -> list[str]:
|
|
399
|
+
"""Wake every charter whose webhook trigger matches ``path``.
|
|
400
|
+
|
|
401
|
+
The supervisor does NOT itself bind a port — an external HTTP shim is
|
|
402
|
+
responsible for that. The shim calls this method on a hit; one charter
|
|
403
|
+
↔ one path (matched on ``webhook_path`` in its trigger config).
|
|
404
|
+
"""
|
|
405
|
+
payload = payload or {}
|
|
406
|
+
fired: list[str] = []
|
|
407
|
+
for sched in self._schedules.values():
|
|
408
|
+
c = sched.charter
|
|
409
|
+
if c.trigger_type != "webhook":
|
|
410
|
+
continue
|
|
411
|
+
wp = c.trigger_config.get("webhook_path")
|
|
412
|
+
if not wp or wp != path:
|
|
413
|
+
continue
|
|
414
|
+
intent = payload.get("intent") or f"{c.role}: webhook fired ({path})"
|
|
415
|
+
self._fire(sched, intent=intent, extra_context={"payload": payload})
|
|
416
|
+
fired.append(c.id)
|
|
417
|
+
return fired
|
|
418
|
+
|
|
419
|
+
# -- internals -----------------------------------------------------------
|
|
420
|
+
|
|
421
|
+
def _init_cron_schedules(self) -> None:
|
|
422
|
+
now = time.time()
|
|
423
|
+
for sched in self._schedules.values():
|
|
424
|
+
if sched.charter.trigger_type != "cron":
|
|
425
|
+
continue
|
|
426
|
+
spec = sched.charter.trigger_config.get("schedule")
|
|
427
|
+
if not spec:
|
|
428
|
+
logger.warning("autonomous: charter %s has cron trigger but no "
|
|
429
|
+
"schedule — skipping", sched.charter.id)
|
|
430
|
+
continue
|
|
431
|
+
try:
|
|
432
|
+
sched.next_fire_at = next_fire(spec, now)
|
|
433
|
+
except (ValueError, RuntimeError) as exc:
|
|
434
|
+
sched.last_error = f"cron parse: {exc}"
|
|
435
|
+
sched.errors += 1
|
|
436
|
+
logger.warning("autonomous: charter %s has bad cron %r: %s",
|
|
437
|
+
sched.charter.id, spec, exc)
|
|
438
|
+
|
|
439
|
+
def _wire_event_subscribers(self) -> None:
|
|
440
|
+
"""Hook the engine's event bus for charters with an event trigger."""
|
|
441
|
+
for sched in self._schedules.values():
|
|
442
|
+
c = sched.charter
|
|
443
|
+
if c.trigger_type != "event":
|
|
444
|
+
continue
|
|
445
|
+
pattern = c.trigger_config.get("event_type", "")
|
|
446
|
+
if not pattern:
|
|
447
|
+
continue
|
|
448
|
+
self._bus.subscribe(self._make_event_handler(sched, pattern))
|
|
449
|
+
|
|
450
|
+
def _make_event_handler(self, sched: _Schedule, pattern: str
|
|
451
|
+
) -> Callable[[Event], None]:
|
|
452
|
+
def handler(event: Event) -> None:
|
|
453
|
+
etype = event.type.value if hasattr(event.type, "value") else str(event.type)
|
|
454
|
+
# support exact match and a trailing wildcard (``task.*``)
|
|
455
|
+
if pattern.endswith("*"):
|
|
456
|
+
if not etype.startswith(pattern[:-1]):
|
|
457
|
+
return
|
|
458
|
+
elif etype != pattern:
|
|
459
|
+
return
|
|
460
|
+
intent = f"{sched.charter.role}: event {etype} on {event.task_id}"
|
|
461
|
+
self._fire(sched, intent=intent,
|
|
462
|
+
extra_context={"event_task_id": event.task_id,
|
|
463
|
+
"event_type": etype,
|
|
464
|
+
"event_payload": event.payload})
|
|
465
|
+
return handler
|
|
466
|
+
|
|
467
|
+
def _tick_once(self, now: float | None = None) -> list[str]:
|
|
468
|
+
now = now if now is not None else time.time()
|
|
469
|
+
fired: list[str] = []
|
|
470
|
+
with self._lock:
|
|
471
|
+
scheds = list(self._schedules.values())
|
|
472
|
+
for sched in scheds:
|
|
473
|
+
if sched.charter.trigger_type != "cron":
|
|
474
|
+
continue
|
|
475
|
+
if sched.next_fire_at is None:
|
|
476
|
+
continue
|
|
477
|
+
if now >= sched.next_fire_at:
|
|
478
|
+
spec = sched.charter.trigger_config.get("schedule", "")
|
|
479
|
+
intent = (f"{sched.charter.role}: cron tick "
|
|
480
|
+
f"({spec}) — {time.strftime('%Y-%m-%d %H:%M')}")
|
|
481
|
+
self._fire(sched, intent=intent,
|
|
482
|
+
extra_context={"cron_schedule": spec, "fired_at": now})
|
|
483
|
+
fired.append(sched.charter.id)
|
|
484
|
+
# reschedule for next fire
|
|
485
|
+
try:
|
|
486
|
+
sched.next_fire_at = next_fire(spec, now + 60)
|
|
487
|
+
except (ValueError, RuntimeError) as exc:
|
|
488
|
+
sched.last_error = f"reschedule: {exc}"
|
|
489
|
+
sched.errors += 1
|
|
490
|
+
sched.next_fire_at = None
|
|
491
|
+
return fired
|
|
492
|
+
|
|
493
|
+
def _fire(self, sched: _Schedule, *, intent: str,
|
|
494
|
+
extra_context: dict[str, Any] | None = None) -> None:
|
|
495
|
+
"""Invoke the runner once; absorb every exception per charter."""
|
|
496
|
+
c = sched.charter
|
|
497
|
+
sched.runs += 1
|
|
498
|
+
sched.last_run_at = time.time()
|
|
499
|
+
logger.info("autonomous: firing %s (%s) — intent=%r",
|
|
500
|
+
c.id, c.trigger_type, intent[:120])
|
|
501
|
+
try:
|
|
502
|
+
self._runner(
|
|
503
|
+
intent=intent,
|
|
504
|
+
omega_home=self._omega_home,
|
|
505
|
+
topic_id=c.channel_topic,
|
|
506
|
+
telegram=self._telegram,
|
|
507
|
+
charter=c,
|
|
508
|
+
)
|
|
509
|
+
except Exception as exc: # noqa: BLE001 — never let one bad charter kill us
|
|
510
|
+
sched.errors += 1
|
|
511
|
+
sched.last_error = f"{type(exc).__name__}: {exc}"
|
|
512
|
+
logger.exception("autonomous: charter %s crashed during fire", c.id)
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
516
|
+
# Convenience — build a supervisor straight from OMEGA_HOME
|
|
517
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
518
|
+
|
|
519
|
+
def build_supervisor_from_home(
|
|
520
|
+
omega_home: str | Path | None = None,
|
|
521
|
+
*,
|
|
522
|
+
telegram: Any | None = None,
|
|
523
|
+
bus: Any | None = None,
|
|
524
|
+
runner: MissionRunner | None = None,
|
|
525
|
+
) -> AutonomousSupervisor:
|
|
526
|
+
"""Discover charters in ``$OMEGA_HOME/Agentik_Orchestration/autonomous/`` and
|
|
527
|
+
return a ready-to-run supervisor."""
|
|
528
|
+
home = Path(omega_home or os.environ.get(
|
|
529
|
+
"OMEGA_HOME", str(Path.home() / "Omega")))
|
|
530
|
+
charter_dir = home / "Agentik_Orchestration" / "autonomous"
|
|
531
|
+
charters = load_charters(charter_dir)
|
|
532
|
+
return AutonomousSupervisor(
|
|
533
|
+
charters,
|
|
534
|
+
omega_home=home,
|
|
535
|
+
telegram=telegram,
|
|
536
|
+
bus=bus,
|
|
537
|
+
runner=runner,
|
|
538
|
+
)
|