Commit Graph
236 Commits
Author SHA1 Message Date
Aska 285e1e9911 feat(db): 新增 0002_memory 迁移;迁移测试改用嵌入式迁移集合(数量无关,避免卡死后续迁移) 2026-09-06 05:12:42 +08:00
Aska 0a936a3202 feat(multimodal): 视觉分层路由(多模态检测→主/视觉/OCR 工具)+ 语音 STT→TTS 降级链(异步) 2026-09-06 05:12:36 +08:00
Aska 02aae2bbb4 feat(guardrail): 输入/输出护栏(关键词/敏感信息/长度,pipeline fail-fast) 2026-09-06 05:07:13 +08:00
Aska e33b005612 feat(trace): 深追踪(Span 生命周期/父子链/JSONL recorder,支持 llm/tool/state 等类别) 2026-09-06 05:06:41 +08:00
Aska 011d25a53d feat(persist): durable checkpoint(SQLite upsert/LoadLatest/List/Delete,ErrNotFound) 2026-09-06 05:05:24 +08:00
Aska ecd3cdf28c docs(persona): 游戏身份(昔涟/翁法罗斯/开拓者设定)与亲昵称呼(小女友/亲爱的)统一共存,清除残留「姐姐」 2026-09-06 04:58:09 +08:00
Aska 95e058094a docs(persona): 默认人格表述对齐「全能小女友」、称呼用户「亲爱的」 2026-09-06 04:55:18 +08:00
Aska b9253a4980 feat(user): 主人档案/白名单(OwnerProfile+loader)+ 给 LLM 的身份说明书(owner_identity.md) 2026-09-06 04:55:18 +08:00
Aska c647d33a00 feat(persona): 迁移默认人格「昔涟」并适配新 schema(configs/personas/cyrene.yaml) 2026-09-06 04:41:04 +08:00
Aska 8317f370cd chore(deps): go mod tidy 整理依赖图(yaml.v3 转正为直接依赖) 2026-09-06 04:38:21 +08:00
Aska d09ccc7570 feat(model): LLM 多供应商适配(Adapter/OpenAI 非流式+SSE 流式/per-role 路由/主备降级/多模态检测/调用记录) 2026-09-06 04:37:27 +08:00
Aska 51b2bdfba2 feat(embedding): 嵌入(n-gram 哈希向量 + 关键词 FTS + OpenAI 兼容 API 钩子 + Manager 选择) 2026-09-06 04:37:10 +08:00
Aska 70fd915242 feat(persona): 人格系统(YAML loader / 角色人格注册+记忆隔离 / 情绪状态机+好感度) 2026-09-06 04:36:31 +08:00
Aska 653c2489bf feat(capability): 能力注册中心(类型化注册/按类查询/并发安全) 2026-09-06 04:35:31 +08:00
Aska 7b8cfc664a feat(sdk): 插件 SDK(Tool/Skill/Channel 接口 + 注册辅助 + 配置 hook) 2026-09-06 04:35:31 +08:00
Aska c52ddfd9c7 feat(channel): 跨平台 IM 接入抽象契约(UnifiedMessage/PlatformAdapter/Capabilities/Actor 身份) 2026-09-06 04:33:59 +08:00
Aska a21176ec0a chore(deps): 添加 gopkg.in/yaml.v3(人格 YAML 加载) 2026-09-06 04:33:59 +08:00
Aska c730b05621 chore(deps): 添加 modernc.org/sqlite 纯 Go SQLite 驱动(无 CGO、跨平台) 2026-09-06 04:27:45 +08:00
Aska 34cac241c1 feat(db): SQLite 连接与迁移框架(embed 迁移/事务校验/PG 预留 M4) 2026-09-06 04:26:02 +08:00
Aska dd16176bb7 feat(bus): 进程内事件总线(通配订阅/非阻塞扇出/Close 幂等) 2026-09-06 04:26:02 +08:00
Aska c1fb20bd6b docs(config): 更新 .env.example 对齐新架构 schema 2026-09-06 04:19:20 +08:00
Aska 1defd46d14 docs(AGENTS): 补充「可并行项交后台子代理、主会话当监工」的上下文保护铁律 2026-09-06 04:17:54 +08:00
Aska 1d4bed415f feat(platform): 多平台检测/路径/信号/系统信息(含跨平台构建验证) 2026-09-06 04:17:20 +08:00
Aska efed5f05b1 feat(config): 配置加载与 schema 校验(.env/env 注入 + 反射解码 + 校验) 2026-09-06 04:15:31 +08:00
Aska 0236010136 feat(logger): slog 结构化日志封装(text/json + 级别解析) 2026-09-06 04:13:19 +08:00
Aska 62c7a2aa12 docs: 新增项目级开发铁律 AGENTS.md 2026-09-06 04:12:37 +08:00
Aska 4506f639dd chore: 清理 v2 过时残留(旧 API 文档/人格配置/部署目录/compose/启动脚本/密钥备份/旧CI),更新 gitignore 2026-09-06 03:52:27 +08:00
Aska 8b310feceb docs: 更新 README 为新架构(人格化通用 Agent 运行时) 2026-09-05 23:13:27 +08:00
Aska 4be3826af7 chore: 清空 v2 实现,重建新架构骨架(人格化通用 Agent 运行时) 2026-09-05 23:09:26 +08:00
Aska 9c8d5a9e8d feat(rag): pgvector knowledge base with API and LLM tools
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- services/rag: knowledge_docs store — vector search via the shared
  embedder (HNSW index, graceful ILIKE fallback), list/delete scoped to
  the user, search intentionally global for the single-user deployment
- gateway: GET/POST /knowledge/docs, DELETE /knowledge/docs/:id,
  POST /knowledge/search
- plugins/knowledge: knowledge_search and knowledge_ingest tools so the
  persona can save and recall information mid-conversation
- main: migrations, store wiring, plugin registration
2026-08-21 18:40:01 +08:00
Aska ac0c2b2c73 feat(ai-core): real vision image analysis
- 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
2026-08-21 18:33:44 +08:00
Aska 2104fc0c6c feat(frontend): voice input and read-aloud UI
- assistant messages get a 🔊 button that fetches TTS audio and plays
  it, toggling to stop
- ChatInput gains a mic button: MediaRecorder capture, base64 upload to
  /voice/stt, recognized text fills the input
- api client: voice.tts (blob) and voice.stt helpers
2026-08-21 18:31:24 +08:00
Aska a0357a7bbd feat(voice): real TTS fallback chain and whisper-compatible STT
- TTS providers: cloud (OpenAI-compatible /audio/speech, e.g. Bailian
  compatible mode with cosyvoice), local self-hosted HTTP server,
  edge-tts CLI, espeak CLI, silent — ordered by TTS_PROVIDER list,
  skipping providers whose binary/config is missing
- STT: whisper-compatible /audio/transcriptions endpoint (cloud or
  self-hosted faster-whisper), replacing the empty dashscope stub
- config: TTS_CLOUD_URL/KEY/MODEL/VOICE, TTS_LOCAL_URL, STT_API_URL/
  KEY/MODEL; cloud keys fall back to DASHSCOPE_API_KEY
- gateway /voice/tts now returns real audio/mpeg bytes instead of a
  byte count
- tests: cloud/local/whisper round-trips via httptest, chain skip
  behavior, fallback order; kept and adapted prior service tests
2026-08-21 18:28:39 +08:00
Aska b8fb7feb86 feat(ai-core): mood state machine and affection level
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- 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
2026-08-21 18:13:23 +08:00
Aska 26d65dd6bb feat(frontend): message search and session export entry points
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- SearchModal queries GET /messages/search and jumps to the matching
  session; opened from the sidebar button or Ctrl+K
- session items in the sidebar gain a hover export button that
  downloads the markdown export via an authenticated fetch + blob
  (plain links cannot send the JWT)
2026-08-21 12:59:30 +08:00
Aska 9d040fde0b feat(plugins): implement web-search, web-fetch, http and file tools
- web-search: real SearXNG /search?format=json query, top-5 formatted
  results (was a 'not configured' stub)
- web-fetch: fetch page, strip scripts/styles/tags, truncate to 4000
  runes for the LLM context
- http: generic request tool (GET/POST/PUT/DELETE/PATCH) with scheme
  and method validation, status + truncated body
- file: sandboxed read/write/list inside the data directory with path
  escape rejection; split into file_read/file_write/file_list
- all tool schemas converted to proper JSON Schema; httptest/tempdir
  tests for each plugin
2026-08-21 12:57:19 +08:00
Aska d80710d85a feat(gateway): automation rule engine and reminder scheduler
- 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
2026-08-21 12:54:11 +08:00
Aska 9f30cdd086 feat(bridge): QQ adapter reconnect and send rate limiting
- 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
2026-08-21 12:48:04 +08:00
Aska 8603839711 feat(ai-core): trace instrumentation, LLM thinker, decay scheduler
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- 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)
2026-08-20 20:57:27 +08:00
Aska 8495a4b055 feat(memory): hybrid vector search via embedder
- 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
2026-08-20 20:57:13 +08:00
Aska 8190007865 feat(frontend): session list sidebar and persisted history loading
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- Sidebar lists sessions with title/relative time, click to switch,
  hover-to-delete; refreshes after each round so new titles appear
- ChatPage loads message history from GET /sessions/:id/messages when
  entering a session
- WS connect now passes user_id so persisted messages have an owner
2026-08-20 20:34:08 +08:00
Aska f8196c111c feat(gateway): persist chat sessions and messages in PostgreSQL
- 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.
2026-08-20 20:34:08 +08:00
Aska f44bf26050 fix(build): stop ignoring cmd/cyrene sources
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
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.
2026-08-20 19:42:32 +08:00
Aska cc040b861d feat(ai-core): trigger memory extraction after each conversation round
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.
2026-08-20 19:40:58 +08:00
Aska 7c02d31194 feat(ai-core): wire function calling into the LLM pipeline
- 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.
2026-08-20 19:40:58 +08:00
Aska 9a3c77dbd3 fix(bridge): align admin panel field keys with backend adapter settings
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.
2026-08-20 19:40:32 +08:00
Aska a58ec7325d refactor(logging): replace all print/log with structured slog logger
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- main.go: 30+ log.Printf → logger.Infof
- plugin/registry: 12 log.Printf → logger.Infof
- db/db.go, ws/hub.go: log → logger
- platform-bridge: fmt.Printf/println → logger.Info
- Logs now: time=... level=INFO msg=...
- 16 packages pass, vet clean
2026-08-12 21:31:06 +08:00
Aska 628d416dcd feat(admin): add authenticated restart endpoint + fix admin username
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- 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
2026-08-12 21:26:58 +08:00
Aska dee48b6766 feat: add automation, reminders, notifications, msg search, session export, image analysis, host exec, PWA, Docker, E2E, CI/CD
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled
- Automation: rules CRUD (in-memory store + API)
- Reminders: CRUD (in-memory store + API)
- Notifications: push interface for future push server
- Message search: API endpoint with DB-backed query
- Session export: /sessions/:id/export → Markdown
- Image analysis: API stub for multimodal LLM
- Host exec: API stub for Docker sandbox
- PWA: manifest.json + service worker
- Docker: Dockerfile + docker-compose.yml
- E2E: Playwright test scaffold
- CI/CD: GitHub Actions workflow (go test + tsc)
2026-08-12 19:43:46 +08:00
Aska 3f9c4ca3c3 fix(prompt): prevent LLM from confusing context with user input
- 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
2026-08-12 19:28:32 +08:00