v0.3.0 — HTTP+SSE API, structured answers, registry pricing, silas:doctor
The second half of the pre-1.0 push. Chaos-gated: 235 kill/deploy cycles across worker/supervisor/SIGTERM/parked on SQLite and Postgres — 100% completion, byte-identical replay, zero duplicate side effects.
- A public HTTP + SSE session API at
/silas/api/v1— sessions (create/show,?trace=1for the full transcript), turns (create — 409 while one is active — and cancel), and approvals (list/approve/decline, the exact sameapprove!/decline!as the inbox, Slack, and email, stamped withconfig.api_actor). Deny-by-default viaconfig.api_auth.GET .../sessions/:id/streamis server-sent events at row granularity withLast-Event-IDresume — at-least-once, epoch-ms watermark ids,?poll=1for a curl-friendly backlog-and-close, self-closing afterapi_stream_max_duration. - Structured final answers — declare a JSON schema under
final_answer:in agent.yml and read the parsed Hash fromTurn#answer_data(APIanswer_data, inbox trace, REPL, and a newassert_answer_dataeval assertion). Schema-less agents keep a byte-identical definitions digest, so turns parked across the upgrade never tripNondeterminismError. - Cost accounting prices itself from RubyLLM's model registry (1,100+ models) per (model, provider) — steps stamp the provider at persist time;
config.model_pricesis now an override map; unknown models stayunpriced, never a lying $0.00. Default model is nowclaude-sonnet-4-5. - Inbox at scale — the budget "raise & resume" top-up card the 0.1.5 changelog promised, keyset pagination (
?before=), and a 2-query session index. bin/rails silas:doctor— provider key, queue adapter, model resolution, migrations, tool validation, rescuer entry, cable adapter, auth wiring. Exits non-zero on failures.- The 0.2
agent_sdkconfig shims are hard-removed (NoMethodErrornow); workflows onactions/checkout@v5.
Upgrade: bin/rails silas:install:migrations db:migrate (adds silas_steps.provider, drops the write-only silas_turns.cost_microcents). Full details in CHANGELOG.md.