- llm: Adapter.Vision sends multimodal chat requests (text + image_url,
data URLs supported) and logs the call as purpose 'vision'
- gateway /images/analyze now accepts image_url or image_base64 and
returns real analysis instead of a placeholder message
- main wires the default LLM adapter as the vision analyzer
- httptest coverage for the vision request/response shape
- new emotion package: rule-based sentiment (positive/negative lexicon)
drives mood transitions (开心/平静/难过) with 30min inactivity decay;
affection 0-100 grows with positive interaction, with 初识→熟悉→信赖→
羁绊 tiers
- pipeline records each user message and injects a mood line into the
system prompt so the persona's tone follows her mood
- mood changes broadcast over WS; frontend shows a mood badge with
affection tooltip; also handles the 'reminder' message type from the
reminder scheduler
- tests: sentiment scoring, mood shift, affection bounds, prompt line,
onChange callback
- engine: 5-field cron parser (*/n, ranges, lists) firing at most once
per minute; device-state triggers with edge detection; manual trigger
via POST /automation/rules/:id/trigger; actions run through the AI
pipeline so rules can call any tool (IoT control, search, ...)
- reminders: due-scan scheduler delivering via WebSocket broadcast,
optional LLM-polished reminder text with plain-title fallback;
Reminder gains Done flag with ListDue/MarkDone
- tests: cron matching and validation, once-per-minute dedup, device
edge triggering, manual trigger, reminder delivery
- supervisor loop keeps the OBv11 WebSocket alive, reconnecting with
exponential backoff (1s→30s) when the connection drops; Start no
longer fails permanently when NapCat is temporarily unreachable
- Send enforces MinGap between messages (from SendOptions or the
adapter's send_interval_ms setting, now wired from the admin panel)
- parseMessage no longer panics on events missing sender/time fields
- tests: reconnect after drop, rate limit enforcement, malformed events,
send while disconnected
- orchestrator: Tracer interface with spans for intent analysis, persona,
subsession dispatch, context build, LLM streaming and each tool call;
traces finish when the stream completes — the admin Trace waterfall
finally receives data
- background: Thinker generates real LLM thoughts (post-chat + silence
triggers, recent history as context, empty/overlong outputs discarded);
thoughts broadcast to web clients as 'thinking' WS messages; pipeline
postChatHook triggers post-chat thinking after each round
- memory: ApplyDecayAll + ListUserIDs with a 6h decay/purge cron in main
(was implemented but never scheduled)
- repository: optional pgvector embedding column (migration with
CREATE EXTENSION guarded by main), SearchByVector cosine search,
vector-enabled insert path
- service: SetEmbedder — memories are embedded on Add; Search merges
vector hits with n-gram keyword matches (vector first, deduped)
- embedder was already implemented (OpenAI-compatible API + n-gram FNV
fallback) but never instantiated; main now wires it from
EMBEDDING_API_URL/EMBEDDING_MODEL config
- 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 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.
- 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
- Context merged into single system message with clear delimiters
- Prefix: 「以下是系统上下文,不是用户说的话」
- Memory → 【相关记忆】, IoT → 【设备状态】
- Filter empty memories, skip raw intent data
- Persona rule: context markers are internal data, not user input
- Persona injector: concise natural language rules, not raw YAML
- Context builder: skip empty memory, skip raw intent data
- Prompt reduced from 2000+ tokens to ~500 tokens
- LLM response quality improved (natural tone, no confusion)
- 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