- store: new chat_sessions/chat_messages tables with CRUD, ILIKE message
search, and auto-titling from the first user message
- context: optional Persister on the sliding-window store — messages are
saved asynchronously on Add, sessions not in memory are restored from
the database on Get
- orchestrator: ProcessInput/FinishRound now carry userID so persisted
messages have an owner
- api: real session handlers (list/create/delete), message history and
clear endpoints, working message search and three-format export
(markdown/txt/json), fixing the short-ID panic in export
- main: migration, store wiring, ctxStore persister adapter
Tests: chat store handler lifecycle (fake store), context persister
save/restore, stub auth login flow updated.
The bare 'cyrene' .gitignore pattern matched the cmd/cyrene directory,
so trace_adapter.go was never committed and a fresh clone failed to
build (undefined: traceAdapter). Scope the pattern to the root binary
and add the missing file.
The WS hub and platform bridge now call Pipeline.FinishRound when the
response stream completes, recording the assistant reply and invoking
the LLM memory extractor asynchronously.
- llm: ChatStreamWithTools sends OpenAI-format tools; streamed tool_call
deltas are reassembled by index into complete ToolCalls on the Done token
- model: LLMMessage gains ToolCallID/ToolCalls; StreamToken gains ToolCalls
- orchestrator: new ToolExecutor interface and streamWithTools loop —
execute requested tools, feed results back, up to 3 rounds, final round
forces a plain text answer; normal chats still stream token by token.
Also adds Pipeline.FinishRound (assistant reply recording + post-round
hook), wired to transports in the next commit.
- main: inject the plugin registry via toolExecAdapter
Includes an httptest-based test covering delta reassembly, tool
execution, and result feedback.
Frontend sent remote_url/bot_token/webhook_url while the backend reads
ws_url/token/listen_addr, so QQ adapters could never connect. Also add
the missing bot_qq field and wire the webhook adapter's APIKey.
- POST /api/v1/admin/restart: admin-only restart (forks new process)
- Fix: MemUserStore now uses cfg.AdminUsername instead of hardcoded 'admin'
- RestartFunc injected by main.go for clean process fork + exit
- llm.Adapter: SetCallLogger hook for recording every API call
- llm.CallLogger: ring-buffer with Recent+Stats for admin API
- main.go: wire DeepSeek adapter to CallLogger
- Fix: single CallLogger instance for both recording and display
- Metrics: model name, duration, success/fail, tokens
- All 16 packages pass
- memory/extractor: async LLM-based memory extraction from chat history
- Parses JSON lines from LLM response as memory entries
- Wire into orchestrator pipeline via PostProcess hook
- Non-blocking: runs in goroutine with 30s timeout
- Automatic dedup via existing keyword overlap logic
- BridgeConfigStore: file-backed JSON config (configs/bridge.json)
- Auto-creates config file only when user saves via admin panel
- Hot-reload: watches config file every 5s, reloads adapters live
- Admin API: GET/PUT/DELETE /api/v1/admin/bridge/config/:name
- Frontend: full CRUD page with platform type selector + toggle
- Removed bridge env vars from .env.example
- Backend: trace.Logger ring-buffer for request chain events
- Backend: perf.Monitor with runtime.MemStats sampling every 10s
- Backend: /api/v1/admin/trace and /api/v1/admin/perf endpoints
- Frontend: TracePage — timeline with hop icons and status dots
- Frontend: PerformancePage — memory/GC bar charts + live stats
- Admin nav expanded to 11 items