feat(agent): hierarchical executor with path resolve, runtime probe, quiet UI
CI / build-gateway (push) Failing after 16s
CI / sync-config (push) Failing after 0s

Make Zed Agent closer to Cursor: deterministic DevOps path index, live Traefik
port probe before blind edits, stop-after-edit, and quieter Russian progress.
This commit is contained in:
2026-08-13 11:41:27 +03:00
parent 6fd2f0e689
commit a2d238d92e
71 changed files with 10617 additions and 449 deletions
+37
View File
@@ -0,0 +1,37 @@
# Static LiteLLM settings — model_list generated by scripts/gen-litellm-config.py
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
store_model_in_db: false
max_budget: 50
budget_duration: 30d
litellm_settings:
drop_params: true
set_verbose: false
request_timeout: 300
num_retries: 2
cache: true
cache_params:
type: redis
host: redis
port: 6379
ttl: 3600
callbacks: ["prometheus"]
require_auth_for_metrics_endpoint: false
environment_variables:
NOVITA_API_KEY: os.environ/NOVITA_API_KEY
GROQ_API_KEY: os.environ/GROQ_API_KEY
XAI_API_KEY: os.environ/XAI_API_KEY
GEMINI_API_KEY: os.environ/GEMINI_API_KEY
GIGACHAT_CREDENTIALS: os.environ/GIGACHAT_CREDENTIALS
TOGETHER_API_KEY: os.environ/TOGETHER_API_KEY
OPENROUTER_API_KEY: os.environ/OPENROUTER_API_KEY
router_settings:
routing_strategy: simple-shuffle
num_retries: 2
timeout: 300
allowed_fails: 5
cooldown_time: 15
+22 -50
View File
@@ -1,104 +1,76 @@
# tier × lane (A/B/C) → Novita model id + LiteLLM fallbacks
# Tier × lane orchestration metadata (model IDs → config/providers.yaml)
lanes:
A: economy
B: balanced
C: max
# LiteLLM per-lane RPM (proxy-side). Zed agent bursts tool calls — keep high for personal IFT.
# OpenRouter :free upstream may still 429; router fallbacks + cooldown_time apply separately.
models:
a-simple:
novita: novita/qwen/qwen3-4b-fp8
fallbacks: [b-simple, groq-llama-8b]
rpm: 60
rpm: 300
b-simple:
novita: novita/meta-llama/llama-3.1-8b-instruct
fallbacks: [a-simple, groq-llama-8b]
rpm: 60
rpm: 300
c-simple:
novita: novita/qwen/qwen3-8b-fp8
fallbacks: [b-simple]
rpm: 60
rpm: 300
a-medium-ops:
novita: novita/qwen/qwen3-8b-fp8
fallbacks: [a-medium-code, b-medium-ops]
rpm: 40
rpm: 240
b-medium-ops:
novita: novita/deepseek/deepseek-v3.2
fallbacks: [a-medium-code, c-medium-ops]
rpm: 40
rpm: 240
c-medium-ops:
novita: novita/deepseek/deepseek-v3.2
fallbacks: [b-medium-ops]
rpm: 40
rpm: 240
a-medium-code:
novita: novita/qwen/qwen3-coder-30b-a3b-instruct
fallbacks: [a-medium-ops, groq-qwen-coder]
rpm: 40
rpm: 240
b-medium-code:
novita: novita/qwen/qwen3-coder-30b-a3b-instruct
fallbacks: [b-medium-ops, c-medium-code]
rpm: 40
rpm: 240
c-medium-code:
novita: novita/qwen/qwen3-coder-30b-a3b-instruct
fallbacks: [b-medium-code, c-medium-ops]
rpm: 30
rpm: 180
a-complex:
novita: novita/deepseek/deepseek-v3.2
fallbacks: [b-complex, a-reasoning]
rpm: 30
rpm: 180
b-complex:
novita: novita/deepseek/deepseek-r1-0528
fallbacks: [a-complex, c-complex]
rpm: 20
rpm: 120
c-complex:
novita: novita/deepseek/deepseek-r1-turbo
fallbacks: [b-complex]
rpm: 15
rpm: 120
a-reasoning:
novita: novita/deepseek/deepseek-r1-0528-qwen3-8b
fallbacks: [b-reasoning, gemini-flash]
rpm: 30
rpm: 120
b-reasoning:
novita: novita/deepseek/deepseek-r1-0528
fallbacks: [a-reasoning, c-reasoning]
rpm: 20
rpm: 120
c-reasoning:
novita: novita/deepseek/deepseek-r1-turbo
fallbacks: [b-reasoning, gemini-flash]
rpm: 15
rpm: 120
a-vision-ocr:
novita: novita/paddlepaddle/paddleocr-vl
fallbacks: [a-vision]
rpm: 30
rpm: 120
no_escalation: true
a-vision:
novita: novita/qwen/qwen3-vl-30b-a3b-instruct
fallbacks: [a-vision-ocr]
rpm: 20
rpm: 120
b-vision:
novita: novita/qwen/qwen2.5-vl-72b-instruct
fallbacks: [a-vision, c-vision]
rpm: 15
rpm: 90
c-vision:
novita: novita/qwen/qwen3-vl-235b-a22b-instruct
fallbacks: [b-vision]
rpm: 10
optional_providers:
groq-llama-8b:
model: groq/llama-3.1-8b-instant
api_key: os.environ/GROQ_API_KEY
groq-qwen-coder:
model: groq/qwen-qwen-2.5-coder-32b
api_key: os.environ/GROQ_API_KEY
gemini-flash:
model: gemini/gemini-2.0-flash
api_key: os.environ/GEMINI_API_KEY
rpm: 90
audit:
price_drift_threshold_pct: 10
+81 -1
View File
@@ -32,9 +32,89 @@ redis:
ttl_sec: 1800
classifier:
# heuristic | hybrid (default) | llm
mode: hybrid
llm_model: gigachat-classifier
low_confidence_threshold: 0.6
timeout_sec: 15
max_tokens: 64
# Strong Max plan → cheap coder workers/executor → conditional DeepSeek verify
hierarchical:
enabled: true
trigger_tiers: [COMPLEX, REASONING]
header: X-AI-Orchestrate # off | auto | force
planner_model: novita-planner
verifier_model: novita-verifier
planner_fallback: b-complex
verifier_fallback: b-complex
verify_policy: on_fail_or_hard
verify_input: digests
synthesize_model: a-medium-code
plan_confirm: true
agent_executor_model: a-medium-code
agent_escalate_model: b-complex
agent_escalate_after_edit_failures: 2
skip_synthesize_if_single: true
max_subtasks: 3
max_verify_retries: 1
plan_max_tokens: 1024
verify_max_tokens: 384
synthesize_max_tokens: 1024
worker_max_tokens: 768
wall_clock_sec: 600
digest_chars: 300
call_timeout_sec: 300
# First turn (kickstart read) can stay longer; after read_file body Coder hangs —
# tool_loop uses short timeout + escalate_after_read → DeepSeek.
executor_timeout_sec: 90
executor_num_retries: 0
executor_input_chars: 16000
executor_tool_loop_chars: 12000
executor_tool_loop_timeout_sec: 45
executor_newest_tool_chars: 3500
executor_minimal_context: true
executor_max_tools: 6
executor_tool_desc_chars: 120
executor_tools_full_chars: 8000
executor_max_tokens: 1024
executor_use_stream: false
executor_synthetic_on_timeout: true
# First turn only: synthetic read_file on plan path if model returns prose.
# Mid-loop still stops (no fake edits).
executor_synthetic_mode: kickstart_only
executor_max_synthetic_continues: 1
executor_max_edit_failures: 4
executor_midloop_model_retry: true
executor_midloop_escalate: true
# After successful read_file skip DeepSeek (was 408→400 loop) → edit_file
executor_force_edit_after_read: true
# After a successful read_file, skip cheap coder — it stalls on fat tool results
executor_escalate_after_read: true
# Rewrite read_file on already-read paths → edit (breaks re-read loops)
executor_rewrite_reread: true
# When model returns 200 without tool_calls: one escalate retry before kickstart
executor_no_tools_escalate: true
# After plan approve: 1) deterministic path index 2) if gaps → cheap find_* model
path_resolve_enabled: true
path_resolve_model: a-simple
path_resolve_timeout_sec: 45
path_resolve_max_tools: 3
# DevOps (*.calentiq.com / Bad Gateway): probe live ports before edit
runtime_probe_enabled: true
runtime_probe_timeout_sec: 8
# Optional: ssh host for docker inspect (empty = TCP probe from gateway only)
runtime_probe_ssh_host: ""
# Quiet Zed: milestones only (no ctx bars / LiteLLM waits / subtask dumps)
progress_verbose: false
show_context_fill: false
progress_in_content: true
stream_progress: true
context_window_tokens: 32768
plan_input_chars: 48000
llm_cache_ttl_sec: 3600
worker_map:
simple: a-simple
medium_code: a-medium-code
hard: b-complex
worker_map_max:
hard: c-complex
+133
View File
@@ -0,0 +1,133 @@
# Provider profiles — active: PRIMARY_PROVIDER env (default: hybrid)
# Regenerate: bash scripts/gen-litellm-config.py
profiles:
hybrid:
label: "Hybrid: Novita workers + Novita plan/verify (no Claude geo-billing)"
welcome_credit: false
requires: [NOVITA_API_KEY]
smart_router:
model: novita/meta-llama/llama-3.1-8b-instruct
api_key: NOVITA_API_KEY
fallbacks:
# No groq/gemini here — VPN off on IFT; those hang until client timeout.
a-simple: [b-simple, a-medium-ops]
a-medium-code: [b-medium-code, a-complex]
a-complex: [b-complex, a-reasoning]
b-complex: [a-complex, c-complex]
a-reasoning: [b-reasoning, a-complex]
a-vision: [a-vision-ocr]
smart-router-internal: [a-medium-ops, a-medium-code, a-complex]
# Planner is Max — fallback to DeepSeek then coder (never Llama)
novita-planner: [b-complex, a-medium-code]
novita-verifier: [b-complex, a-medium-code]
default_fallbacks: [a-medium-code, a-complex, a-medium-ops]
lanes:
# Prefer Llama for fast lanes — Qwen3 puts answers in reasoning_content
a-simple: { model: novita/meta-llama/llama-3.1-8b-instruct, api_key: NOVITA_API_KEY }
b-simple: { model: novita/meta-llama/llama-3.1-8b-instruct, api_key: NOVITA_API_KEY }
c-simple: { model: novita/meta-llama/llama-3.1-8b-instruct, api_key: NOVITA_API_KEY }
a-medium-ops: { model: novita/meta-llama/llama-3.1-8b-instruct, api_key: NOVITA_API_KEY }
b-medium-ops: { model: novita/meta-llama/llama-3.1-8b-instruct, api_key: NOVITA_API_KEY }
c-medium-ops: { model: novita/meta-llama/llama-3.1-8b-instruct, api_key: NOVITA_API_KEY }
# medium_code → coder / Plus-class (disable thinking — else stream hangs)
a-medium-code: { model: novita/qwen/qwen3-coder-30b-a3b-instruct, api_key: NOVITA_API_KEY, disable_thinking: true }
b-medium-code: { model: novita/qwen/qwen3-coder-30b-a3b-instruct, api_key: NOVITA_API_KEY, disable_thinking: true }
c-medium-code: { model: novita/qwen/qwen3-coder-30b-a3b-instruct, api_key: NOVITA_API_KEY, disable_thinking: true }
# complex/reasoning A/B → coder/deepseek; C (hard) → Qwen3.8-Max only
a-complex: { model: novita/qwen/qwen3-coder-30b-a3b-instruct, api_key: NOVITA_API_KEY, disable_thinking: true }
b-complex: { model: novita/deepseek/deepseek-v3.2, api_key: NOVITA_API_KEY }
c-complex: { model: novita/qwen/qwen3.8-max, api_key: NOVITA_API_KEY, disable_thinking: true }
a-reasoning: { model: novita/qwen/qwen3-coder-30b-a3b-instruct, api_key: NOVITA_API_KEY, disable_thinking: true }
b-reasoning: { model: novita/deepseek/deepseek-v3.2, api_key: NOVITA_API_KEY }
c-reasoning: { model: novita/qwen/qwen3.8-max, api_key: NOVITA_API_KEY, disable_thinking: true }
a-vision-ocr: { model: novita/paddlepaddle/paddleocr-vl, api_key: NOVITA_API_KEY }
a-vision: { model: novita/qwen/qwen3-vl-30b-a3b-instruct, api_key: NOVITA_API_KEY }
b-vision: { model: novita/qwen/qwen2.5-vl-72b-instruct, api_key: NOVITA_API_KEY }
c-vision: { model: novita/qwen/qwen3-vl-235b-a22b-instruct, api_key: NOVITA_API_KEY }
openrouter:
label: OpenRouter reserve (VPN; free :free + pay-as-you-go)
welcome_credit: true
requires: [OPENROUTER_API_KEY]
requires_vpn: true
smart_router:
model: openrouter/openrouter/free
api_key: OPENROUTER_API_KEY
fallbacks:
a-simple: [b-simple, c-simple]
a-medium-code: [b-medium-code, c-medium-code]
a-complex: [b-complex, c-complex]
smart-router-internal: [a-medium-ops, a-medium-code]
default_fallbacks: [a-medium-code, a-medium-ops]
lanes:
a-simple: { model: openrouter/openai/gpt-oss-20b:free, api_key: OPENROUTER_API_KEY }
b-simple: { model: openrouter/openai/gpt-oss-20b:free, api_key: OPENROUTER_API_KEY }
c-simple: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
a-medium-ops: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
b-medium-ops: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
c-medium-ops: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
a-medium-code: { model: openrouter/cohere/north-mini-code:free, api_key: OPENROUTER_API_KEY }
b-medium-code: { model: openrouter/cohere/north-mini-code:free, api_key: OPENROUTER_API_KEY }
c-medium-code: { model: openrouter/cohere/north-mini-code:free, api_key: OPENROUTER_API_KEY }
a-complex: { model: openrouter/google/gemma-4-26b-a4b-it:free, api_key: OPENROUTER_API_KEY }
b-complex: { model: openrouter/nvidia/nemotron-3-nano-30b-a3b:free, api_key: OPENROUTER_API_KEY }
c-complex: { model: openrouter/nvidia/nemotron-3-nano-30b-a3b:free, api_key: OPENROUTER_API_KEY }
a-reasoning: { model: openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free, api_key: OPENROUTER_API_KEY }
b-reasoning: { model: openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free, api_key: OPENROUTER_API_KEY }
c-reasoning: { model: openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free, api_key: OPENROUTER_API_KEY }
a-vision-ocr: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
a-vision: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
b-vision: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
c-vision: { model: openrouter/openrouter/free, api_key: OPENROUTER_API_KEY }
# Always registered when keys present (all profiles)
fixed_models:
# Hierarchical: strong Max plan (rare); DeepSeek verify (conditional)
novita-planner:
model: novita/qwen/qwen3.8-max
api_key: NOVITA_API_KEY
max_tokens: 1024
temperature: 0
disable_thinking: true
novita-verifier:
model: novita/deepseek/deepseek-v3.2
api_key: NOVITA_API_KEY
max_tokens: 1024
temperature: 0
# Optional Claude — only if ANTHROPIC_API_KEY works later (VPN + billing)
claude-haiku-planner:
model: anthropic/claude-haiku-4-5-20251001
api_key: ANTHROPIC_API_KEY
requires_vpn: true
max_tokens: 1024
temperature: 0
claude-sonnet-verifier:
model: anthropic/claude-sonnet-5
api_key: ANTHROPIC_API_KEY
requires_vpn: true
max_tokens: 2048
temperature: 0
grok-3:
model: xai/grok-3
api_key: XAI_API_KEY
requires_vpn: true
groq-llama-8b:
model: groq/llama-3.1-8b-instant
api_key: GROQ_API_KEY
groq-qwen-coder:
model: groq/qwen-qwen-2.5-coder-32b
api_key: GROQ_API_KEY
gemini-flash:
model: gemini/gemini-2.0-flash
api_key: GEMINI_API_KEY
gigachat-classifier:
model: gigachat/GigaChat-2-Lite
api_key: GIGACHAT_CREDENTIALS
ssl_verify: false
max_tokens: 64
temperature: 0
gigachat-pro:
model: gigachat/GigaChat-2-Pro
api_key: GIGACHAT_CREDENTIALS
ssl_verify: false
+14
View File
@@ -38,6 +38,18 @@ gateway:
- novita
- traefik
- mnesia
medium_code_keywords:
- поправь
- исправь
- fix
- edit
- patch
- bugfix
- typo
- rename
- add test
- unit test
- lint
ocr_keywords:
- ocr
- прочитай текст
@@ -64,6 +76,8 @@ litellm:
tier: SIMPLE
- keywords: ["bash", "docker", "swarm", "ci/cd", "gitea", "rebar", "erlang", "devops", "kubectl", "terraform", "playwright", "npm", "wsl"]
tier: MEDIUM
- keywords: ["поправь", "исправь", "fix", "edit", "patch", "bugfix", "typo", "rename", "add test", "lint"]
tier: MEDIUM
- keywords: ["рефакторинг", "refactor", "архитектура", "architecture", "спроектируй", "design system", "microservice", "distributed", "migration plan"]
tier: COMPLEX
- keywords: ["step by step", "reasoning", "prove", "analyze deeply", "think through"]