Backend:
- Add WS event "thinking" (start/stream/done) with
throttled 150ms streaming, replacing system messages
- Fix inter-persona relay: [RELAI INTER-PERSONA] block
+ [PROTOCOLE CANAL 3615] directive prevents personas
from rejecting relay as injection
- Fix resolveRuntimeModel fallback to LLM_MODEL
- Switch from mascarade to direct local vLLM streaming
- Fix llmHeaders: read API key at call time (ESM order)
- Add shouldThink: disable qwen3 thinking for short msgs
via chat_template_kwargs.enable_thinking
- Increase THINKING_HEADROOM to 2048
- Remove double-strip: onDone passes raw text, caller
strips via cleanPersonaResponse
- stripThinking handles unclosed <think> tags
Frontend:
- ThinkingPanel: collapsible right drawer with live
thinking stream per persona + progress bar
- useChatState: thinkingByPersona state + WS handler
- styles.css: panel styles, responsive hide <800px
- Fix TimelineView meta type error (pre-existing)
Extract shared extractFirstJsonObject() into json-utils.ts and
replace the 4 identical copies in composition-store, context-store,
ws-chat, and media-store with imports.
Remove unused SENTENCE_END regex and extractSentences() from
ws-conversation-router.ts (TTS sentence splitting, no longer called)
and shouldThink() from ws-ollama.ts (adaptive thinking, never called).
Offline scripts for maintaining the persona and RAG subsystems.
- ingest_spectacle_corpus.py: bulk-load texts into LightRAG
- camoufox_server.py: headless browser proxy for scraping
- audit_personas.py: validate persona configs against store
- generate-persona-dialogues.js: synthetic dialogue generator
Show real-time thinking/reasoning progress in the chat UI with
persona-specific flavour texts for a more engaging experience.
- Extend ws-conversation-router with thinking state machine
- Stream thinking tokens to frontend via useChatState hook
- Add persona flavour text display in Chat component
- Simplify ws-commands-info and ws-commands-compose routing
- Update ComposePage with server status panel
- Add integration and router tests for thinking flow
Switch from Ollama API format to OpenAI-compatible llama-server
with reasoning token support.
- Refactor ws-ollama to emit OpenAI chat completions format
- Update llm-client endpoint configuration
- Add reasoning/thinking token extraction to web-search
- Update smoke tests for new response shape
- Add llama-server deployment to k8s manifests
- Update README with new architecture notes
Prevent data loss from truncated JSON files caused by crashes or
concurrent writes.
- Add extractFirstJsonObject helper for recovering partial JSON
- Switch composition-store and media-store to atomic writes (tmp+rename)
- Harden chat-history and media routes with graceful error handling
- Improve ws-chat resilience against malformed stored state
- Add tests for corruption recovery and atomic save paths
Persona memories are now scoped per-nick, preventing cross-user
contamination in shared channels.
- Add auto/explicit memory modes to persona-memory-store
- Extend chat-types with memory-related message fields
- Refactor ws-commands-chat to route through memory layer
- Expand personas-default with richer persona definitions
- Update persona-memory-policy for mode selection
- Add tests for nick-scoped storage and retrieval
Chunk messages from the same persona were displayed as separate lines
instead of being concatenated into a single streaming message. The root
cause: audio (TTS) and system (typing indicator) messages interleaved
between chunks, and the accumulator only checked the very last array
element. Now uses findLastChunkIndex to search backward through the
full message array, matching the logic already used for final message
replacement.
- LLM_API_KEY support across all LLM calls
- TEI embedding server (bge-m3, :9500)
- Hierarchical AGENTS.md documentation
- CLAUDE.md updated for new architecture
- lot-203: LOT203_MEMORY_BENCHMARK.md — Mem0 vs local store (verdict: keep local; 300-2000ms vs <5ms, 3 extra services vs 0)
- ComposePage: "☁ Serveur" button + panel listing server-side compositions from /api/v2/media/compositions
- lot-28-rag-config: confirmed done (RAG_CHUNK_SIZE/MIN_SIMILARITY/MAX_RESULTS/EMBEDDING_MODEL in rag.ts)
- lot-29-systemd: scripts/journald-monitor.sh (TUI status, --watch mode, CI exit code) + ops/v2/journald-alerts.conf
- scripts/cleanup-test-compositions.js: dry-run cleanup tool for stale test compositions on disk
- PLAN.md lot-28 [planned] → [done]
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Instrument ws-persona-router with attempt/write/skip/failure recording
- Expose persona_memory stats in GET /api/v2/perf endpoint
- Export Prometheus series for persona memory in /metrics
- Add app.test.ts cases for perf and Prometheus persona memory endpoints
- Clean up obsolete composition and ws-commands test stubs
- Update AGENTS.md/PLAN.md/TODO.md: session 2026-03-25 personas V2 runtime hardening
- Remove DAW e2e test skip
- Add COMPOSE_ADVANCED_COMMANDS set + createComposeAdvancedCommandHandler to ws-commands-compose.ts
- Route all 9 advanced composition cmds before generate switch in ws-commands-generate.ts
- -695 LOC in ws-commands-generate.ts
- Add /delete + /marker regression tests in ws-commands.test.ts
- Sync PLAN.md, TODO.md, AGENTS.md, docs/AGENTS.md
- useMemo for wordCount (was inline .reduce on every render across 500+ msgs)
- useMemo for searchMatches (was creating new Set on every render)
- Both now only recompute when messages/searchQuery actually change
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- index.ts reduced from 583 LOC to 155 LOC (thin orchestrator)
- All logic delegated to worker-runtime.ts exports:
createShutdownController, createNodeExecutor, runPollCycle, waitForNextPollTick
- Removed duplicated executeRun, executeNodeStub, syncQueuedRuns, etc.
- Single source of truth for poll/dequeue/execute cycle
- 6/6 worker-runtime tests pass
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace all execFileSync("ffmpeg") with await execFileAsync("ffmpeg")
across ws-commands-generate.ts (~35 calls)
- Remove stale execFileSync dynamic imports (2 occurrences)
- Remove unused execFileSync import from ws-commands-info.ts
- Event loop stays free during /mix, /master, /bounce, /fx, /noise, etc.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix: "\s*" in string literal was "s*" not whitespace — changed to "\\s*"
- Extract detectGenerationIntent as exported standalone function (testable)
- 13 new tests: FR image (4), EN image (2), FR music (3), EN music (1), negative (3)
- All 21 conversation-router tests pass
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>