git clone -b rev2026 https://github.com/stipot-com/adaos.git
cd adaos
# 1. mac/linux:
bash tools/bootstrap.sh
source ./.venv/bin/activate
adaos --help
# 2. windows (PowerShell):
# 2.1. using astrav uv https://github.com/astral-sh/uv
powershell -ExecutionPolicy Bypass -File tools/bootstrap_uv.ps1
./.venv/Scripts/Activate.ps1
adaos --help
# 2.2. using pip
powershell -ExecutionPolicy Bypass -File ./tools/bootstrap.ps1
./.venv/Scripts/Activate.ps1
adaos --help
# При необходимости обновления пакетов uv
uv lock; uv sync
- Публичные точки входа. Высокоуровневые фасады доступны через
adaos.sdk.manage(инструменты управления),adaos.sdk.data(датаплейн утилиты) и функциюadaos.sdk.validate_self(валидация текущего навыка). - Модель способностей. Каждый инструмент проверяет разрешения через
ctx.caps; названия способностей совпадают с именами инструментов (например,manage.self,skills.manage,scenarios.manage,resources.manage). При отсутствии прав возбуждаетсяadaos.sdk.core.CapabilityError. - Контракт идемпотентности. Все операции, изменяющие состояние, принимают параметры
request_idиdry_run. Первый запуск фиксирует результат в KV-хранилище, повторный с тем жеrequest_idвозвращает сохранённый ответ без повторного исполнения. - Модель ошибок. При отсутствии инициализированного контекста поднимается
SdkRuntimeNotInitialized; превышение квот отображается какQuotaExceeded; конфликты состояния — черезConflictError. - Метаданные инструментов. Декоратор
@toolизadaos.sdk.decoratorsприкрепляет к каждой функции JSON-схемы входа/выхода и вспомогательные сведения (summary, stability). Экспортерadaos.sdk.exporter.exportагрегирует эти описания для систем LLM.
adaos --help
adaos skill install weather_skill
adaos skill list
adaos skill run weather_skill
adaos skill run weather_skill --topic nlp.intent.weather.get --payload '{"city": "Berlin"}'
adaos api serve --host 127.0.0.1 --port 8777
curl -i http://127.0.0.1:8777/health/live
curl -i http://127.0.0.1:8777/health/ready
# Windows запустить альтернативную ноду в той-же кодовой базе
$env:ADAOS_BASE_DIR_SUFFIX="_1"; adaos api serve --host 127.0.0.1 --port 8778
# Мониотринг
adaos api serve --host 127.0.0.1 --port 8777
$env:ADAOS_BASE_DIR_SUFFIX="_1"; adaos api serve --host 127.0.0.1 --port 8778
adaos monitor sse http://127.0.0.1:8777/api/observe/stream
curl -H "X-AdaOS-Token: dev-local-token" -X POST http://127.0.0.1:8778/api/observe/test
# Вариант 2
# 1) Узнай node_id member-ноды:
curl -H "X-AdaOS-Token: dev-local-token" http://127.0.0.1:8777/api/subnet/nodes
# 2) Подними SSE со строгим фильтром:
adaos monitor sse http://127.0.0.1:8777/api/observe/stream --topic net.subnet.
# 3) Попроси хаб дерегистрировать эту ноду (сразу прилетит net.subnet.node.down):
curl -H "X-AdaOS-Token: dev-local-token" -H "Content-Type: application/json" \
-X POST http://127.0.0.1:8777/api/subnet/deregister \
-d '{"node_id":"<member-node-id>"}'
# С хвостом
adaos monitor sse http://127.0.0.1:8777/api/observe/stream?replay_lines=50 --topic net.subnet.from adaos.services.skill.runtime import run_skill_handler_sync
print(
run_skill_handler_sync(
"weather_skill",
"nlp.intent.weather.get",
{"city": "Berlin"},
)
)headers = {"X-AdaOS-Token": "dev-local-token"}
# 1) проверить статус
print(requests.get("http://127.0.0.1:8778/api/node/status", headers=headers).json())
# 2) сменить роль на member или hub (и задать hub_url)
payload = {"role": "member", "hub_url": "http://127.0.0.1:8777"}
print(requests.post("http://127.0.0.1:8778/api/node/role", json=payload, headers=headers).json())
# 3) снова статус — должен быть role=member, ready=true
print(requests.get("http://127.0.0.1:8778/api/node/status", headers=headers).json())AdaOS CLI дополнен встроенным HTTP API (по умолчанию на http://127.0.0.1:8777).
Аутентификация — через заголовок X-AdaOS-Token. Токен задаётся переменной окружения ADAOS_API_TOKEN (по умолчанию: dev-local-token).
Озвучивание текста через выбранный TTS-бэкенд (native / OVOS / Rhasspy).
Запрос:
{
"text": "Hello from AdaOS",
"provider": "auto", // необязательный параметр ("auto"|"ovos"|"rhasspy")
"voice": "default" // необязательный параметр (в зависимости от бэкенда)
}Ответ:
{
"status": "ok",
"provider": "ovos",
"text": "Hello from AdaOS"
}curl -X POST http://127.0.0.1:8777/api/say \
-H "X-AdaOS-Token: dev-local-token" \
-H "Content-Type: application/json" \
-d '{"text":"Hello from AdaOS"}'Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8777/api/say `
-Headers @{ "X-AdaOS-Token" = "dev-local-token" } `
-ContentType "application/json" `
-Body (@{ text = "Hello from AdaOS" } | ConvertTo-Json)-
/api/say— озвучивание текста -
/api/listen— захват аудио и STT (планируется) -
/api/skills— управление навыками -
/api/runtime— управление окружением
AdaOS CLI позволяет управлять навыками, тестами и Runtime через удобный интерфейс командной строки.
Все команды поддерживают локализацию (ru/en).
adaos [OPTIONS] COMMAND [ARGS]...OPTIONS– глобальные опции CLI (например,--help).COMMAND– раздел команд:skill,runtime,test,db.ARGS– аргументы для конкретной команды.
adaos skill [SUBCOMMAND]Управление навыками: установка, удаление, обновление и отправка изменений в монорепозиторий.
adaos skill listОписание: Показывает все навыки, установленные у пользователя.
Пример:
adaos skill listВывод:
- AlarmSkill (активная версия: 1.0)
- WeatherSkill (активная версия: 0.3.2)
adaos skill create <skill_name> [--template <template_name>]Параметры:
<skill_name>– имя нового навыка.--template, -t– шаблон для инициализации навыка (по умолчаниюbasic).
Пример:
adaos skill create alarm_skill -t AlarmSkillСтатические проверки (без импорта кода):
skill.yaml существует и валиден по схеме.
обязательные файлы: handlers/main.py.
dependencies: корректные строки; requirements.txt при желании.
tools[].name уникальны, схемы валидны (draft 2020-12).
events.subscribe[]/publish[] — строки, без дубликатов.
Динамические проверки (с импорта handler): 6) @tool("") реально экспортирован для каждого tools[].name. 7) Есть подписчик @subscribe(topic) для каждого events.subscribe[]. 8) (опц.) «сухой вызов» каждого инструмента с пустыми/моком аргументов — только если --probe-tools, иначе пропускаем.
adaos skill validate weather_skill
adaos skill validate weather_skill --json
adaos skill validate weather_skill --strictadaos skill install <skill_name>Описание:
Добавляет навык из монорепозитория и помечает его как installed=1.
Обновляет sparse-checkout, чтобы навык появился в рабочей директории.
Пример:
adaos skill install weather_skilladaos skill uninstall <skill_name>Описание:
Удаляет навык из рабочей директории пользователя (флаг installed=0) и пересобирает sparse-checkout.
Пример:
adaos skill uninstall alarm_skilladaos skill update <skill_name>Описание: Подтягивает последнюю версию навыка из монорепозитория и обновляет версию в БД.
Пример:
adaos skill update weather_skilladaos skill push <skill_name> [-m <message>]Параметры:
<skill_name>– имя навыка.-m, --message– комментарий к коммиту (по умолчаниюОбновление навыка).
Пример:
adaos skill push alarm_skill -m "Исправлены ошибки логики будильника"adaos skill pull <skill_name>Описание: Принудительно загружает навык из монорепозитория. Используется при первой установке или восстановлении навыка.
adaos skill versions <skill_name>Описание: Показывает текущую активную версию навыка.
Пример:
adaos skill versions alarm_skillВывод:
alarm_skill — активная версия: 1.0.0
В разработке. Команды
adaos runtime,adaos testиadaos dbбудут добавлены в следующих версиях.
adaos skill create weather_skill -t AlarmSkill
adaos skill push weather_skill -m "Добавлен навык прогноза погоды"adaos skill list
adaos skill update alarm_skill
adaos skill update weather_skillproject_root/ ├── .env # Конфигурация окружения (SKILLS_REPO_URL и т.д.) ├── docker-compose.yml ├── requirements.txt ├── setup.py ├── README.md │ ├── src/adaos/ ├── agent/ # Runtime │ ├── core/ # State machine, skill_loader │ ├── db/ # SQLite persistence │ ├── i18n/ # TTS / UI strings │ └── audio/ # asr, tts, wake_word (если используется) │ ├── sdk/ # CLI и DevTools │ ├── cli/ # Typer CLI │ ├── skills/ # Компиляторы / шаблоны / генерация │ ├── llm/ # Подключение и промпты │ ├── locales/ # Локализация CLI │ └── utils/ # Общие утилиты (git, env) │ ├── common/ # Опционально: конфиг, логгер, схемы └── skills_templates/ # YAML/intent-шаблоны │ └── .adaos/ # Рабочая среда пользователя (динамическая) ├── workspace/ # Редактируемые копии │ ├── skills/ # Локальные исходники навыков │ └── scenarios/ # Локальные исходники сценариев ├── skills/ # Кэш реестра навыков (read-only sparse checkout) ├── scenarios/ # Кэш реестра сценариев (read-only sparse checkout) ├── skill_db.sqlite # База данных навыков (версии, установленные навыки) ├── models/ # Локальные модели (ASR и др.) │ └── vosk-model-small-ru-0.22/ ├── runtime/ # Логи и тесты │ ├── logs/ │ └── tests/
Сервер Root принимает обращения от CLI через REST API. По умолчанию используются dev-настройки:
ROOT_TOKEN— токен дляPOST /v1/*(значение по умолчанию:dev-root-token).ROOT_BASE(root_baseв~/.adaos/root-cli.json) — базовый URL Root (http://127.0.0.1:3030).ADAOS_BASEиADAOS_TOKEN— адрес и токен локального AdaOS моста, передаются в заголовках приGET /adaos/healthz.
CLI автоматически выполняет preflight-проверки, регистрирует subnet/node и отправляет архив черновика:
adaos skill install weather_skill
adaos skill create demo --template python-minimal
adaos skill push demo
adaos scenario create morning
adaos scenario push morningДля сброса кэша реестра используйте adaos repo reset skills или adaos repo reset scenarios — команда выполнит git fetch/reset --hard/clean -fdx внутри .adaos/skills или .adaos/scenarios.
@startuml Local_AdaOS_MVP
!includeurl https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
Container(user, "Пользователь", "Голос или текст", "Формулирует запросы")
Container(llm, "LLM Client", "OpenAI / litellm", "Генерация тестов и навыков по запросу")
Container(testrunner, "Test Runner", "PyYAML + pytest", "Прогоняет тесты BDD для навыков")
Container(git, "Git Repo", "GitPython", "Версионирование навыков")
Container(sqlite, "Skill DB", "SQLite + SQLAlchemy", "Метаданные навыков и версий")
Container(runtime, "Skill Runtime", "importlib + watchdog", "Запуск навыков и проверка прав")
Container(logs, "Логирование", "logging + rich", "Хранение логов и ошибок")
Rel(user, llm, "Говорит/пишет запрос")
Rel(llm, testrunner, "Создает тест")
Rel(testrunner, runtime, "Проверяет в песочнице")
Rel(testrunner, git, "Сохраняет успешный навык")
Rel(testrunner, sqlite, "Записывает метаданные")
Rel(runtime, sqlite, "Читает активные версии навыков")
Rel(runtime, logs, "Пишет логи работы и ошибок")
@enduml-
LLM (OpenAI / Ollama через
openaiилиlitellm)- Генерирует тест (YAML) и код навыка.
-
TestRunner (
PyYAML,pytest)- Прогоняет тест на существующих навыках.
- Если провал – генерирует и тестирует новый навык в песочнице.
-
GitPython
- Хранит каждую версию навыка в
skills_repo/. - Теги:
AlarmSkill_v1.0.
- Хранит каждую версию навыка в
-
SQLite + SQLAlchemy
- Записывает: версия, путь к активной директории навыка, дата создания.
-
Runtime (
importlib,watchdog)- Подхватывает активные навыки из
skills/active/. - Обрабатывает intent → вызывает handler.py → проверяет права.
- Подхватывает активные навыки из
-
Логирование (
logging + rich)- Все ошибки тестов и Runtime пишутся в
runtime.log. - Возможна интеграция с CLI для просмотра.
- Все ошибки тестов и Runtime пишутся в
- Каждый навык — это модуль на Python:
manifest.yaml + handler.py. - SDK максимально минималистичный (10–15 функций) и похож на известные фреймворки (Flask, FastAPI, Alexa Skills Kit).
- Навык выполняется в общем рантайме без тяжёлого sandbox, но с системой прав как в Android.
Пример:
# manifest.yaml
name: AlarmSkill
version: 1.0
permissions:
- audio.playback
- time.schedule
intents:
- set_alarm
- cancel_alarm# handler.py
from skill_sdk import speak, set_alarm, cancel_alarm
def handle(intent, entities):
if intent == "set_alarm":
set_alarm(entities["time"])
speak("Будильник установлен")
else:
cancel_alarm()
speak("Будильник отменён")- Навык при установке получает фиксированный набор прав на ресурсы (микрофон, TTS, сетевые вызовы и т.д.).
- Магазин проверяет права и код (статический анализ).
- В случае критической ошибки возможен быстрый откат навыка через CI/CD.
-
LLM выступает главным создателем навыков, получая только компактную документацию по SDK и несколько примеров.
-
Для пользователей без навыков программирования на сервере AdaOS делаем UI-конструктор:
- Пользователь описывает навык голосом или текстом.
- LLM генерирует код и манифест.
- Код проверяется и устанавливается через магазин.
Таким образом:
- LLM генерирует 90% навыков без человека.
- Разработчики могут писать сложные навыки руками.
-
Все навыки проходят через автоматизированный пайплайн:
- Проверка прав и зависимостей.
- Прогон в тестовом окружении / эмуляторе.
- Подпись и публикация в магазине.
-
Магазин управляет версиями SDK и навыков, как App Store.
- Навык может вызвать другой навык через SDK (
invoke_skill(skill_id, params)). - Это позволяет строить иерархию без сложного DSL-графа.
- Визуальный редактор на сервере может отображать эти связи как граф, но это всего лишь UI-надстройка.
@startuml Skill_Lifecycle
!includeurl https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
LAYOUT_WITH_LEGEND()
Container(skillMgr, "SkillManager", "Python", "Управляет жизненным циклом навыков")
Component(store, "Local Skill Store", "Filesystem", "Хранилище навыков")
Component(registry, "Skill Registry", "Git / AdaOS Server", "Централизованный каталог")
Component(executor, "SkillExecutor", "Python Sandbox", "Изолированное исполнение навыков")
Rel(skillMgr, registry, "Запрашивает метаинформацию / навык")
Rel(skillMgr, store, "Сохраняет/удаляет/обновляет")
Rel(skillMgr, executor, "Передаёт навык на запуск")
Rel(executor, store, "Читает код / настройки")
Rel(executor, skillMgr, "Сообщает результат")
@enduml
| Этап | Запрос от Reutilizer | Ответ от AdaOS Server |
|---|---|---|
| 📡 Регистрация | POST /register + ID |
200 OK + config, skill_list |
| 🔁 Синхронизация | GET /skills/update |
Список доступных обновлений |
| ⬇️ Установка навыка | GET /skills/{id} |
Архив с кодом + манифест |
| 📥 Отправка логов | POST /logs |
200 OK или retry |
| 📤 Загрузка данных | POST /data (sensors) |
200 OK или rules to trigger |
| 🔃 Обновление состояния | PATCH /status |
Могут быть переданы команды или сценарии |
@startuml Hybrid_Approach
!includeurl https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
!includeurl https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
LAYOUT_WITH_LEGEND()
Person(user, "Пользователь", "Создаёт или использует навыки")
System_Boundary(s1, "AdaOS Server") {
Container(ui, "Web UI / Voice UI", "React / Ionic", "Интерфейс для управления навыками и устройствами")
Container(api, "API Gateway", "FastAPI / GraphQL", "Единая точка входа для UI и LLM")
Container(store, "Skill Store", "PostgreSQL + S3", "Хранилище навыков, версий и прав доступа")
Container(ci, "CI/CD Pipeline", "GitHub Actions / Drone CI", "Проверка и подписание навыков")
Container(llm, "LLM Engine", "ChatGPT / Ollama", "Генерация и модификация навыков")
Container(deviceReg, "Device Registry", "Redis + PostgreSQL", "Регистрация и статус устройств")
Container(mqtt, "Messaging Broker", "MQTT / WebSocket", "Команды и обновления для устройств")
}
System_Boundary(s2, "Устройство с AdaOS") {
Container(runtime, "Skill Runtime", "Python + Skill SDK", "Исполнение навыков с системой прав")
Container(updater, "Updater", "Git / HTTPS", "Обновление навыков и ядра системы")
}
Rel(user, ui, "Управляет навыками и устройствами")
Rel(ui, api, "Вызывает")
Rel(api, llm, "Запрос на генерацию навыка")
Rel(api, store, "Чтение / запись навыков")
Rel(api, ci, "Инициирует проверку и подписание навыка")
Rel(api, deviceReg, "Обновляет статусы устройств")
Rel(api, mqtt, "Отправляет команды")
Rel(store, ci, "Отдаёт исходники для проверки")
Rel(mqtt, runtime, "Доставляет команды и обновления")
Rel(updater, store, "Скачивает обновлённые навыки")
Rel(runtime, store, "Устанавливает навыки через SDK")
@enduml
- Сбор словарей из lang_res и генерация локализации
- Перенос prep request в папку навыка
- Постобработка папки навыка для его улучшения. Например, можно обратить внимание, что логи не достаточно информативны и скорректировать prepare.py. Или регулярная ошибка может говорить о необходимости найти причины и отладиться.
# Создать навык weather_skill на основе шаблона AlarmSkill
adaos skill create weather_skill -t AlarmSkill
# Сформировать запрос для LLM на генерацию кода prepare.py подготовительной работы
adaos llm build-prep weather_skill "Научись узнавать погоду на сегодня"
# Запрос используем для генерации prepare.py
# Исполнение подготовительной работы prepare.py и сохранение логов
adaos skill prep weather_skill
# Сформировать запрос для LLM на генерации кода навыка
adaos llm build-skill weather_skill "Научись узнавать погоду на сегодня"
# Запрос используем для генерации handlers/main.py, skill.yaml
# Запустить навык
adaos skill run weather_skill get_weather
# Обновить навык из репозитория
adaos skill update weather_skillpython cli.py skill listpython cli.py skill versions AlarmSkillpython cli.py test run src/skills/AlarmSkill/tests/test_alarm.yamlpython cli.py skill rollbackpython cli.py runtime logs# Сборка
docker-compose build
# Запуск
docker-compose up -d
# Войти внутрь контейнера и запустить CLI
docker exec -it adaos bash
python cli.py skill list
/build /docs /src /adaos /core/ # чистые функции: планирование, валидаторы, преобразования /scenario_engine /domain/ # dataclass DTO/VO, типы событий, конфиги /ports/ # Protocol/ABC: GitClient, PathProvider, *Repository, Runtime, EventBus /adapters/ # реализации портов (весь I/O) /fs /db # sqlite и т.п. /git /audio /stt /tts /ovos /rhasspy /android /inimatic /services/ # объектные «оболочки» поверх core и портов /skill /scenario /runtime /orchestrator /apps/ # исполняемые приложения (входные точки) /cli # Typer /api # FastAPI/Flask /launcher /linux /windows /sdk/ # публичные типы/интерфейсы для внешних навыков/сценариев /llm /locales /skills /utils /abi # если это публичные форматы — сюда /templates/ /skills /scenarios /tests /tools