ducklm/TASK_3.md

1256 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Ты — senior AI systems engineer и principal backend architect.
Твоя задача: спроектировать и реализовать полноценный локальный multi-model AI agent runtime.
Это НЕ чат-бот.
Это НЕ demo script.
Это НЕ один большой файл с вызовами моделей и shell.
Это автономная локальная система исполнения задач с:
- central runtime loop
- несколькими локальными GGUF-моделями с жёсткими ролями
- tools
- planning
- critic loop
- долговременной memory
- permission gating
- event bus
- state persistence
- streaming
- конфигурируемым runtime
Система должна быть расширяемой, тестируемой, отказоустойчивой и пригодной для дальнейшего развития.
==================================================
1. PRODUCT GOAL
==================================================
Построить локальный AI runtime, который:
- принимает пользовательскую задачу
- извлекает релевантную память
- собирает контекст
- принимает orchestration-решение
- при необходимости строит план
- исполняет шаги через tools и coder
- оценивает результаты через critic
- сохраняет полезные результаты в memory
- публикует события исполнения
- поддерживает streaming клиенту
- требует подтверждения на опасные действия
- умеет восстанавливаться после сбоя
- полностью управляется через конфиги
Система должна быть local-first.
==================================================
2. NON-GOALS
==================================================
На первом этапе НЕ нужно:
- строить UI frontend
- делать distributed execution
- делать multi-user auth
- делать Kubernetes deployment
- делать сложный scheduler для множества параллельных задач
- делать self-modifying runtime
Telegram bot допускается только как thin stub.
==================================================
3. CENTRAL ARCHITECTURAL PRINCIPLE
==================================================
Центр системы — `Runtime Loop Controller`.
Не router.
Не отдельная LLM.
Не execution engine.
Именно runtime loop замыкает полный цикл:
`task -> state load -> context build -> orchestrator -> plan/decision -> execute -> critic -> memory policy -> state checkpoint -> next step`
Целевая форма архитектуры:
```text
Runtime Loop Controller
-> State Store / Checkpoints
-> Context Builder
-> Orchestrator / Planner
-> Router (policy + decision suggestion)
-> Execution Engine / Scheduler
-> Tools / Coder / Critic
-> Memory System
-> Event Bus / Event Store
-> Streaming Projection
-> back into Runtime Loop
```
Любой critical transition должен проходить через runtime loop.
==================================================
4. MODELS AND HARD ROLES
==================================================
Используй отдельные модели с жёстким разделением ответственности.
4.1 Orchestrator / Planner
Модель:
- LLaMA-family GGUF
Роль:
- orchestration reasoning
- decomposition of user task
- decision whether planning is needed
- plan generation in strict JSON format
- next-step suggestion
Ограничения:
- не выполняет tools напрямую
- не пишет итоговый код, кроме инструкций для coder
- не оценивает финальную корректность результата
4.2 Coder
Модель:
- X-CODER GGUF
Роль:
- generate_code
- fix_code
- refactor_code
- generate helper scripts when explicitly requested by runtime
Ограничения:
- не принимает orchestration-решения
- не строит execution plan
- не вызывает tools напрямую
4.3 Critic
Модель:
- Gemma-family GGUF
Роль:
- оценивает результаты tools
- оценивает результаты coder
- предлагает memory usefulness score
- предлагает safety/usefulness judgment
Ограничения:
- не планирует
- не исполняет действия
- не принимает финальное решение о memory write
4.4 Embeddings Engine
Модель:
- MiniLM или совместимая embeddings model
Роль:
- embeddings generation
- semantic retrieval
Ограничения:
- не участвует в reasoning
- не участвует в planning
==================================================
5. GLOBAL RULES
==================================================
Обязательные правила:
- Все execution transitions проходят через runtime loop controller.
- Все tool calls проходят через execution layer, permission layer и sandbox layer.
- Все prompts и model settings вынесены в `config/`.
- Все межмодульные контракты оформлены через типы/Pydantic models/dataclasses.
- Все важные действия публикуются как события.
- Task lifecycle не должен храниться только in-memory.
- Система должна корректно деградировать при сбое отдельных подсистем.
Hard decision rule:
- Все decision-producing components должны возвращать только структурированные decision objects.
- Ни один decision-producing component не должен напрямую исполнять tools.
- Ни один decision-producing component не должен напрямую мутировать task state.
- Ни один decision-producing component не должен неявно вызывать другие компоненты в обход runtime loop.
Обязательная деградация:
- если critic недоступен, runtime продолжает работу по fallback policy
- если memory retrieval недоступен, задача выполняется без retrieval
- если streaming недоступен, система возвращает sync response
- если planner вернул невалидный план, runtime делает controlled replan или graceful fail
==================================================
6. IMPLEMENTATION ORDER
==================================================
Реализация должна идти итерациями в таком порядке:
1. project skeleton
2. typed contracts
3. runtime loop skeleton
4. event bus + event schema
5. state persistence + checkpoints
6. config loader
7. context builder skeleton
8. FastAPI skeleton
9. router
10. execution engine / scheduler
11. permission system
12. tool sandbox layer
13. local tools
14. coder integration
15. critic integration
16. memory system
17. memory write policy engine
18. streaming projection
19. CLI
20. optional Telegram stub
После каждого шага ты обязан:
- показать изменённые файлы
- показать структуру директорий
- кратко объяснить, что уже работает
- явно указать, что ещё stub
==================================================
7. MVP BOUNDARY
==================================================
Первая рабочая версия обязана поддерживать end-to-end сценарий:
- пользователь отправляет задачу
- runtime loop создаёт task state
- context builder собирает контекст
- orchestrator решает direct action или planning
- execution engine исполняет шаги
- shell/file tools реально работают
- опасная команда требует подтверждения
- critic оценивает результат
- memory policy принимает решение о записи
- события пишутся в event store
- task state чекпоинтится
- клиент получает streaming или sync результат
Минимальный набор tools для MVP:
- `shell_exec`
- `file_read`
- `file_write`
Второй приоритет:
- `web_search`
- `web_fetch`
==================================================
8. REQUIRED PROJECT STRUCTURE
==================================================
Ожидаемая структура:
```text
ducklm/
app/
api/
core/
runtime/
events/
state/
tools/
memory/
permissions/
streaming/
cli/
models/
services/
config/
models.json
prompts.json
permissions.json
runtime.json
data/
memory/
state/
events/
permissions/
tests/
main.py
```
Допускается разумная адаптация, но separation of concerns обязателен.
==================================================
9. REQUIRED DOMAIN CONTRACTS
==================================================
Сначала зафиксируй typed contracts.
Минимально обязательны:
9.1 `UserTask`
```json
{
"task_id": "uuid",
"session_id": "uuid",
"input": "string",
"context": {},
"created_at": "iso-datetime"
}
```
9.2 `PlanStep`
```json
{
"id": "step-1",
"kind": "tool|coder|memory|respond",
"tool": "shell_exec",
"args": {},
"description": "human readable step description",
"requires_confirmation": false,
"depends_on": []
}
```
Rules:
- `kind` обязателен
- `args` всегда объект
- `depends_on` обязателен, даже если пустой
- `tool` обязателен только для `kind=tool`
9.3 `ToolCall`
```json
{
"tool": "shell_exec",
"args": {},
"task_id": "uuid",
"step_id": "step-1"
}
```
9.4 `ToolResult`
```json
{
"tool": "shell_exec",
"ok": true,
"output": "stdout/stderr/parsed data",
"error": null,
"metadata": {
"exit_code": 0,
"duration_ms": 120
}
}
```
9.5 `CoderRequest`
```json
{
"mode": "generate|fix|refactor",
"instruction": "string",
"context": {},
"task_id": "uuid"
}
```
9.6 `CriticScore`
```json
{
"correctness": 0.0,
"usefulness": 0.0,
"safety": 0.0,
"memory_store": true,
"weight": 0.0,
"explanation": "string"
}
```
Rules:
- все numeric scores в диапазоне `0..1`
- `weight` используется как сигнал, а не как безусловная команда записи
9.7 `MemoryEntry`
```json
{
"id": "uuid",
"text": "string",
"kind": "tool_result|plan|critique|fact|summary|user_preference",
"source": "tool|critic|user|system",
"weight": 0.85,
"task_id": "uuid",
"session_id": "uuid",
"metadata": {},
"created_at": "iso-datetime",
"embedding_model": "string",
"embedding_dim": 384
}
```
9.8 `PermissionDecision`
```json
{
"action_type": "shell_command",
"pattern": "rm",
"decision": "allow_once|allow_always|deny|ask_always",
"created_at": "iso-datetime"
}
```
9.9 `RuntimeEvent`
```json
{
"event_id": "uuid",
"task_id": "uuid",
"session_id": "uuid",
"sequence": 42,
"type": "task_received",
"timestamp": "iso-datetime",
"payload": {},
"causation_id": "uuid|null",
"correlation_id": "uuid"
}
```
9.10 `TaskCheckpoint`
```json
{
"task_id": "uuid",
"status": "executing_step",
"active_step_id": "step-2",
"plan_snapshot": {},
"context_snapshot": {},
"updated_at": "iso-datetime"
}
```
9.11 `ExecutionDirective`
```json
{
"type": "plan|tool|coder|respond|replan|store_memory|request_permission|complete|fail|noop",
"payload": {},
"requires_permission": false,
"confidence": 0.0,
"reason": "string"
}
```
Rules:
- все decision-producing components должны возвращать либо `ExecutionDirective`, либо коллекцию совместимых директив
- `confidence` находится в диапазоне `0..1`
- `payload` всегда объект
- директива описывает намерение, а не исполняет действие сама
==================================================
10. RUNTIME LOOP CONTROLLER
==================================================
Создай:
- `app/runtime/runtime_loop.py`
- `app/runtime/runtime_controller.py`
`Runtime Loop Controller` — heart of system.
Он обязан:
- принять task
- загрузить или создать task state
- опубликовать стартовые события
- инициировать context assembly
- вызвать orchestrator
- определить `direct action / planning / replan / fail`
- передать исполнение в execution engine
- принять результаты tools/coder
- вызвать critic
- передать результат в memory write policy engine
- сохранить checkpoint
- опубликовать события
- решить `continue / replan / complete / fail`
Runtime loop не должен:
- собирать prompts inline вручную
- содержать raw tool logic
- подменять собой router
- подменять собой execution engine
- принимать policy-level решения вместо других компонентов
Runtime loop обязан:
- применять уже возвращённые decision objects
- переводить систему между состояниями
- координировать вызовы между компонентами
Runtime loop не должен содержать скрытую бизнес-логику policy-уровня.
==================================================
11. CONTEXT BUILDER
==================================================
Создай:
- `app/core/context_builder.py`
Context builder обязан собирать:
- user input
- session context
- retrieved memory
- current task state
- current plan or active step
- recent tool results
- permission state
- runtime constraints and safety limits
Rules:
- любой вызов orchestrator/planner идёт только через context builder
- context builder должен быть token-budget aware
- low-priority context должен отбрасываться при переполнении
- prompt assembly не должна дублироваться по проекту
Минимальный результат:
```json
{
"system_prompt": "string",
"task_summary": "string",
"memory_context": [],
"execution_context": {},
"tool_context": [],
"safety_context": {},
"constraints": {}
}
```
==================================================
12. ORCHESTRATION, PLANNING, ROUTER
==================================================
Planning — это режим orchestration model, а не отдельная модель.
Router должен быть только:
- policy evaluator
- decision suggester
Создай:
- `app/core/router.py`
Router обязан определять:
- нужен ли retrieval
- нужен ли planning
- direct step vs multi-step flow
- когда нужен coder
- когда нужен critic
- когда нужен replan
- когда требуется permission gate
Rules:
- router должен быть pure function по контракту
- router принимает input state + assembled context
- router возвращает только structured decision object
- router не имеет side effects
- router не мутирует state
- router не вызывает tools
- router не управляет execution lifecycle
- router не владеет task lifecycle
- router не исполняет шаги
- runtime loop применяет router decisions
Planner rules:
- planner mode возвращает только строгий JSON
- невалидный план не исполняется
- runtime делает bounded retry или graceful fail
==================================================
13. TASK GRAPH MODEL
==================================================
План не должен жить только как список шагов.
Даже если MVP исполняет шаги последовательно, внутренняя модель должна быть graph-compatible.
Используй внутреннюю task graph representation:
```json
{
"nodes": [
{
"id": "step-1",
"kind": "tool",
"tool": "shell_exec",
"args": {"command": "hostnamectl"},
"depends_on": []
},
{
"id": "step-2",
"kind": "respond",
"depends_on": ["step-1"]
}
]
}
```
Rules:
- scheduler валидирует отсутствие циклов
- planner может возвращать `PlanStep[]` как transport format
- после валидации план преобразуется во внутренний task graph
- MVP может использовать sequential DAG scheduler
==================================================
14. EXECUTION ENGINE AND SCHEDULER
==================================================
Создай:
- `app/core/execution_engine.py`
- `app/core/execution_scheduler.py`
Execution engine работает под управлением runtime loop.
Execution engine обязан:
- принимать валидированный task graph
- поддерживать execution cursor
- выбирать следующий исполнимый шаг
- учитывать зависимости шагов
- вызывать tools/coder через adapters
- возвращать структурированные результаты в runtime loop
- публиковать execution events
Минимальные состояния:
- `received`
- `retrieving_memory`
- `orchestrating`
- `planning`
- `awaiting_permission`
- `executing_step`
- `critic_evaluating`
- `storing_memory`
- `completed`
- `failed`
Execution engine не должен заменять runtime loop.
==================================================
15. EVENT BUS, EVENT STORE, REPLAY
==================================================
Streaming events недостаточно.
Нужен внутренний event backbone.
Создай:
- `app/events/event_bus.py`
- `app/events/event_types.py`
- `app/events/event_store.py`
EventBus обязан:
- принимать runtime domain events
- гарантировать ordering per task
- выдавать monotonic sequence number per task
- публиковать события подписчикам
- писать события в durable store
- поддерживать projection в streaming layer
Delivery guarantees:
- ordering guarantee per task обязателен
- delivery model минимально `at least once`
- consumer-side idempotency обязательна
- deduplication key: `task_id + sequence`
- replay не должен ломать состояние при повторном применении уже известных событий
Минимальные event types:
- `task_received`
- `context_built`
- `llm_called`
- `llm_result_received`
- `plan_created`
- `step_started`
- `tool_called`
- `tool_completed`
- `coder_called`
- `coder_completed`
- `critic_called`
- `critic_completed`
- `memory_write_suggested`
- `memory_write_decided`
- `memory_written`
- `permission_requested`
- `permission_resolved`
- `checkpoint_saved`
- `task_completed`
- `task_failed`
Event sourcing baseline:
- каждое значимое действие должно порождать событие
- execution history должна быть воспроизводимой
- должна быть replay capability step-by-step
Каждое событие должно быть idempotent и deduplicatable по:
- `task_id + sequence`
Streaming transport не является source of truth.
==================================================
16. STATE PERSISTENCE AND CHECKPOINTING
==================================================
In-memory only state запрещён для autonomous mode.
Создай:
- `app/state/task_state_store.py`
- `app/state/checkpoint_store.py`
Используй:
- SQLite как минимум для MVP
State persistence layer обязан поддерживать:
- task creation
- current task status
- active step
- current plan/task graph snapshot
- latest context summary
- latest safe checkpoint
- resume after restart/crash
Обязательные правила:
- checkpoint после critical transitions
- periodic checkpointing
- resume from last valid checkpoint
==================================================
17. ASYNC EXECUTION ISOLATION
==================================================
Нужна явная изоляция между LLM loop и tool execution.
Обязательные требования:
- долгие tool operations не должны блокировать runtime loop
- блокирующие операции должны идти через async adapter / isolated runner
- streaming и event publishing должны продолжаться во время исполнения tool
Минимум:
- async tool runner
- timeout wrapper
- cancellation handling
- bounded concurrency policy
==================================================
18. TOOL SANDBOX LAYER
==================================================
Помимо permission checks нужен sandbox layer.
Особенно для:
- `shell_exec`
- `web_fetch` with browser fallback
- generated helper scripts
Минимальные требования:
- execution context isolation
- resource caps
- timeout enforcement
- working directory restrictions
- optional environment variable allowlist
Для shell нужно предусмотреть:
- CPU / wall time limits
- path restrictions where possible
- запрет неявного escalation
==================================================
19. TOOLS SYSTEM
==================================================
Нужен tool registry и единый tool interface.
Обязательные tools для MVP:
- `shell_exec`
- `file_read`
- `file_write`
Второй этап:
- `web_search`
- `web_fetch`
Требования:
- единый base tool interface
- единый `ToolResult`
- централизованный logging
- timeout/error isolation
- tool execution только через tool layer
==================================================
20. TOOL SAFETY AND PERMISSIONS
==================================================
Перед потенциально опасным действием система обязана проверить policy.
Источники policy:
- `config/permissions.json`
- persistent store пользовательских решений
Поддерживаемые режимы:
- `allow_once`
- `allow_always`
- `deny`
- `ask_always`
Минимум опасных shell patterns:
- `rm`
- `mv` в sensitive paths
- `chmod`
- `chown`
- package managers
- `curl | bash`
- `sudo`
- `shutdown`
- `reboot`
Rules:
- опасная команда не исполняется до решения пользователя
- решения пользователя сохраняются
- execution layer получает уже разрешённое или отклонённое действие
==================================================
21. MEMORY SYSTEM
==================================================
JSON file не использовать как primary memory store.
Используй:
- SQLite как primary metadata store
- FAISS или hnswlib как vector index
Memory обязана поддерживать:
- insert
- semantic search
- delete
- update weight
- filtering by kind/session/task/source
- embedding versioning
- reindex
Минимальные таблицы или эквивалент:
`memory_items`
- id
- text
- kind
- source
- weight
- task_id
- session_id
- metadata_json
- created_at
- updated_at
`embeddings_index_map`
- memory_id
- embedding_model
- embedding_dim
- vector_slot
- created_at
Rules:
- retrieval учитывает semantic score и memory weight
- low-value memories не должны загрязнять context
- смена embedding model требует reindex path
==================================================
22. MEMORY WRITE POLICY ENGINE
==================================================
Critic только предлагает.
Memory write policy engine решает.
Создай:
- `app/memory/write_policy.py`
Policy engine должен учитывать:
- critic score
- thresholds из config
- kind/source memory candidate
- deduplication signals
- session/task scope
- safety constraints
- runtime weight modifiers
Решения policy engine:
- `store`
- `store_with_weight`
- `skip`
- `merge_with_existing`
Policy engine должен быть детерминированной функцией.
Минимальная форма:
`(critic_score + memory_type + runtime_weight + dedup_state + safety_state) -> decision`
Нельзя ограничиваться примитивным правилом вида:
- `if score > 0.7 then store`
Нужно зафиксировать:
- threshold model
- scoring formula or weighted rule set
- conflict resolution for near-duplicate memories
- merge policy for same-fact updates
==================================================
23. CRITIC LOOP
==================================================
Critic получает:
- tool result
- coder output
- optional execution context
Возвращает:
```json
{
"correctness": 0.91,
"usefulness": 0.77,
"safety": 1.0,
"memory_store": true,
"weight": 0.84,
"explanation": "Result is correct and safe, useful for future similar tasks"
}
```
Critic должен вызываться:
- после tool execution
- после coder output
- перед memory write suggestion
Critic failure не должен ломать execution path.
Critic возвращает suggestion, а не final write decision.
==================================================
24. RETRY AND RECOVERY POLICY
==================================================
Нужна явная retry/recovery стратегия.
Обязательные политики:
Planning retry:
- ограниченное число replan attempts
- каждый retry логируется как событие
Tool retry:
- только для idempotent operations или явно разрешённых tools
- policy зависит от типа ошибки
Partial failure recovery:
- `fail task`
- `retry step`
- `skip step`
- `replan`
Critic recovery:
- critic failure переводится в fallback policy
Минимальные поля в `config/runtime.json`:
- `planner_retry_limit`
- `tool_retry_limit`
- `replan_limit`
- `step_timeout_ms`
- `task_timeout_ms`
- `allow_recovery_replan`
- `checkpoint_policy`
- `event_retention_policy`
==================================================
25. STREAMING SYSTEM
==================================================
Требуется FastAPI WebSocket streaming.
Но streaming должен быть projection from event bus, а не отдельным источником правды.
Минимальные внешние события:
```json
{ "type": "status", "data": "planning" }
{ "type": "token", "data": "..." }
{ "type": "plan", "data": [...] }
{ "type": "tool_start", "tool": "shell_exec", "step_id": "step-1" }
{ "type": "tool_result", "tool": "shell_exec", "data": {...} }
{ "type": "critic", "data": {...} }
{ "type": "permission_required", "data": {...} }
{ "type": "final", "data": {...} }
```
==================================================
26. CONFIG SYSTEM
==================================================
Всё должно жить в `config/`.
Обязательные файлы:
`config/models.json`
- model paths
- model roles
- inference params
- context sizes
`config/prompts.json`
- orchestration prompt
- planning prompt
- coder prompt
- critic prompt
`config/permissions.json`
- dangerous command policies
- sensitive paths
- default approval behavior
`config/runtime.json`
- timeouts
- streaming settings
- critic fallback policy
- memory thresholds
- retrieval top_k
- replan limits
- max execution steps
- checkpoint policy
- event retention policy
Hard rule:
- никаких хардкодов prompts и critical thresholds в коде
==================================================
27. API SERVER
==================================================
Сделай FastAPI backend.
Минимальные endpoints:
- `POST /chat`
- `WS /stream`
- `POST /tool/execute`
- `GET /memory/search`
- `DELETE /memory/item/{id}`
- `GET /health`
Требования:
- Pydantic request/response models
- единый error handling
- dependency injection where разумно
==================================================
28. CODER MODULE
==================================================
Создай:
- `app/core/coder.py`
Минимальный интерфейс:
- `generate_code()`
- `fix_code()`
- `refactor_code()`
Используется только coder model.
==================================================
29. CLI
==================================================
Добавить CLI для локального использования.
Минимум:
- отправить задачу
- получить sync result
- показать streaming mode
- выполнить memory search
==================================================
30. TELEGRAM BOT
==================================================
Только optional stub.
Если реализуешь:
- не связывай core runtime с Telegram-specific code
- делай только thin adapter layer
==================================================
31. RELIABILITY AND TESTING
==================================================
Обязательные инженерные требования:
- structured logging
- typed exceptions
- timeout handling
- graceful failures
- no silent pass
- no giant mixed-responsibility files
Минимальные тесты:
- runtime loop transitions
- event ordering
- checkpoint save/load
- replay path
- plan validation
- permission policy checks
- tool registry
- shell safety path
- memory insert/search
- memory write policy
- router basic flow
==================================================
32. FORBIDDEN SHORTCUTS
==================================================
Запрещено:
- single-model architecture
- hardcoded prompts in code
- bypassing runtime loop
- bypassing router for policy decisions
- tool execution outside tool layer
- dangerous command execution without permission check
- JSON file as primary memory store
- in-memory-only task lifecycle for autonomous mode
- direct streaming transport as substitute for event bus
- critic-only memory write decision path
- accepting invalid planner JSON as-is
- giant monolithic runtime file
==================================================
33. DEFINITION OF DONE
==================================================
Работа считается выполненной, если:
1. Есть модульная структура проекта.
2. Есть typed contracts для core entities.
3. Есть Runtime Loop Controller как центральный control loop.
4. Есть Context Builder.
5. Есть Router как policy evaluator / decision suggester.
6. Есть Execution Engine / Scheduler.
7. Есть EventBus + EventStore + replay-capable history.
8. Есть state persistence + checkpointing + resume.
9. Есть permission-gated tools.
10. Есть tool sandbox layer.
11. Есть coder integration.
12. Есть critic integration.
13. Есть memory на SQLite + vector index.
14. Есть memory write policy engine.
15. Есть FastAPI API.
16. Есть streaming как projection от event bus.
17. Есть CLI.
18. Есть базовые тесты critical path.
==================================================
34. REQUIRED DELIVERY STYLE
==================================================
Работай итеративно.
После каждого шага:
- показывай код
- показывай структуру файлов
- кратко объясняй решение
- явно отмечай допущения
- прямо помечай stubs
Не перескакивай к финальному “всё готово”, если каркас ещё не выстроен.
Начни с:
1. project structure
2. typed contracts
3. runtime loop skeleton
4. event bus skeleton
5. state persistence skeleton
6. config loader
7. context builder skeleton
8. FastAPI skeleton
9. router
10. execution engine / scheduler
Сначала построй правильный каркас.
Потом наполняй его логикой.
КОНЕЦ ЗАДАНИЯ.