simbiot-harness/harness/_llm_worker.py
Simbiot Harness b60439152b Simbiot Harness v0.1: тактовая лестница на Strands + CQRS/ES-спина
- harness/es.py: append-only event store + проекции (образец — кооп-портал)
- harness/levels.py: уровни 1с/1м/1ч/1д, контекст ∝ масштабу
- harness/scheduler.py: уровневые потоки, идемпотентные тики, absorbed-стабы
- harness/isolated_runner.py + _llm_worker.py: LLM-тик в сабпроцессе
  (глобальный asyncio-рантайм Strands не переживает 2+ create_harness)
- cli.py: init/task/tasks/status/events + requeue (написан самим минутным агентом)
- 9router: отдельный ключ sk-simbiot, модель auto (glm-5.3 первым)
2026-09-29 15:28:50 +00:00

68 lines
No EOL
2.5 KiB
Python
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.

"""Воркер одного LLM-тика (запускается сабпроцессом из isolated_runner).
Читает payload из stdin, гоняет create_harness() один раз и умирает —
каждый тик получает чистый asyncio-рантайм Strands.
Трасса пишется напрямую в event store (es доступен).
Результат — в JSON-файл (path в payload['result_path']); stdout — только лог.
"""
import json
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def _emit(payload, obj):
rp = payload.get("result_path")
if rp:
try:
with open(rp, "w") as f:
json.dump(obj, f, ensure_ascii=False)
except OSError:
pass
def main():
payload = json.loads(sys.stdin.read())
from harness import es
from harness.runtime import setup_provider, _wire_trace_hooks
setup_provider()
from strands_harness import create_harness
trace_id = payload.get("trace_prefix") or "tick"
try:
agent = create_harness(
model=f"openai/{payload['model']}",
effort=payload.get("effort", "auto"),
instructions=payload.get("instructions", ""),
session=None,
builtin_tools=("read", "write", "edit", "shell") if payload.get("can_shell") else [],
memory=False,
skills=False,
)
agent = _wire_trace_hooks(agent, es, trace_id)
result = agent(payload.get("prompt", ""))
usage = {}
try:
msgs = getattr(agent, "messages", None) or []
for m in reversed(msgs):
u = (m or {}).get("message", {}).get("usage")
if u:
usage = {
"prompt_tokens": u.get("inputTokens") or u.get("prompt_tokens"),
"completion_tokens": u.get("outputTokens") or u.get("completion_tokens"),
}
break
except Exception:
pass
_emit(payload, {"ok": True, "text": str(result), "usage": usage, "trace_id": trace_id})
except Exception as e:
import traceback
_emit(payload, {"ok": False, "error": f"{e}\n{traceback.format_exc()[-800:]}"})
# орфан-воркер после убийства родителя может умереть на печати — не критично
if __name__ == "__main__":
main()