P2c: in-app choir agent with proposals and approval

This commit is contained in:
Emil
2026-11-01 02:27:44 +03:00
parent 0df07577a1
commit 2ecb8822de
20 changed files with 2236 additions and 30 deletions
+20 -2
View File
@@ -28,6 +28,24 @@ Verification: `cargo test -p zhila-engine` (non-silent 16.5 s buffer, correct fr
Limits: WAV only, stereo float, fixed 48 kHz and 1.5 s tail; no stems, normalisation or section ranges.
## P2c · agent (next)
## P2c · the choir
An in-app LLM agent on the same verbs, with state/sound context and approval for project edits.
`crates/zhila-daemon/src/agent.rs` is the performer. It receives the project state and live meter as text, a system prompt with the ZHILA rules, and an OpenAI-compatible tool list. Safe verbs (play, stop, strike, strike_face, render) execute immediately; project verbs (tempo, gains, pattern, faces, sections, cuts, undo/redo) are collected into one proposal stored with an id. The hand approves or rejects; approval applies every command with `Actor::Agent`, saves the project, and emits the normal events plus an agent confirmation.
Wire: `agent_ask { text }`, `agent_approve { id }`, `agent_reject { id }`, `agent_reset`; events `agent_message { role, text }`, `agent_proposal { id, description, commands }`, `agent_resolved { id, applied }`; `agent_history { messages }` on hello. The host keeps the conversation and pending proposals in memory.
Config: `ZHILA_AGENT_KEY` or `DEEPSEEK_API_KEY` enables the live provider (`ZHILA_AGENT_URL`, default `https://api.deepseek.com`; `ZHILA_AGENT_MODEL`, default `deepseek-chat`). No key, or `ZHILA_AGENT_MOCK=1`, uses the deterministic mock: "tempo" proposes 132 bpm, "listen" strikes the bass, "play"/"stop"/"render" perform, "bass" proposes a gain.
Surface: the `choir` room (top rail) with the conversation, proposals (commands labelled, approve/reject), a listen button, an input, and a readout of sections, levels, bpm and cores. The agent's voice is Cormorant; the commands are mono.
Verification: `node scripts/agent-smoke.mjs` (mock: ask → proposal → approve → tempo 132, resolved, history); `npm --prefix ui run agent-ui-smoke` (choir ask/approve, readout 132, screenshot `preview-p2-agent.png`); `cargo test -p zhila-daemon` (mock turn, tool mapping).
Limits: in-app only, no MCP; one tool round per ask; the conversation is daemon memory; the mock is the default without a key; the host restart clears the chat (the project keeps the approved edits).
## P2 acceptance
- Arrangement: four 2-bar sections, 8-bar playback, per-section editing, persisted and undoable.
- Render: a valid 48 kHz stereo float WAV of the arrangement (16.5 s, non-silent, peak 0.442).
- Agent: ask → proposal → approve → a project edit applied with `Actor::Agent`, on the same wire.
- The native Tauri app hosts all of it in-process; the browser path uses the standalone daemon.
- `./scripts/check.sh`, the persistence smoke and the three P2 smokes pass.
+1 -1
View File
@@ -1,7 +1,7 @@
# ZHILA — план проекта
Черновик v1.1 · 1 ноября 2026
Статус: **P2 в работе** (P0, P1a–P1f, P2a, P2b; см. `P0.md`, `P1.md`, `P2.md`). Демо `reference/demo/` — референс, не кодовая база. Осталось: агент.
Статус: **P2 полностью выполнен** (P0, P1a–P1f, P2a–P2c; см. `P0.md`, `P1.md`, `P2.md`). Демо `reference/demo/` — референс, не кодовая база. Следующая фаза — P3.
**Зафиксировано 1 ноября:** descent — основной вид; камень = паттерн; климат — на жилу (концепт погоды остаётся); платформа v1 — Linux; UI — Svelte 5. Журнал — §9.
+4
View File
@@ -176,3 +176,7 @@ The Tauri app starts the same host in-process, so the wire contract is unchanged
## P2b additions
`Command::render` (no arguments). The host renders the current arrangement to a WAV in the project, answers with the unchanged state, and broadcasts `rendered { path, duration_sec }`. The render is not journaled and does not push undo. The file is 48 kHz stereo 32-bit float.
## P2c additions
Agent commands: `agent_ask { text }`, `agent_approve { id }`, `agent_reject { id }`, `agent_reset`. Events: `agent_message { message: { role, text } }` (roles `user`/`agent`/`system`), `agent_proposal { id, description, commands }`, `agent_resolved { id, applied }`. On hello the host sends `agent_history { messages }`. Agent-approved project edits journal as `Actor::agent`; safe performance verbs execute immediately. The provider stays server-side; the key is never in the surface.