Commit Graph
7 Commits
Author SHA1 Message Date
AskaEth 074ffc4ebf docs(gateway): gateway 剩余文件注释改中文(逐行 1:1,代码零字节改动)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批:
已推库 16 个文件 + 本批剩余文件)。
校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0);
全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
2026-10-03 22:28:25 +08:00
AskaEth 0624d9ee36 feat(session,runtime): 多角色并存—按会话选角(迁移0011 + 按回合解析 + agent池 + 提取器修正)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
按 DevDocs/design/22 批次 1 后端(§2/§3/§4.1-4.5/§4.7/§5 验收 1-6)。
- 迁移 0011:chat_sessions.persona_id + chat_messages.persona_id(均 DEFAULT '',无回填 → 升级零风险);同步包内幂等 DDL;**真实库升级验证**(拷贝 data/cyrene.db 到临时目录跑 MigrateUp:既有 1 会话/109 消息 persona 仍为 '',原库未被触碰)
- history:SessionMeta/Message 加 PersonaID + SetSessionPersona;ListSessions/List/scan/Append 带上
- runtime:SessionEnv.PersonaID + loop.personaFor(ctx) 替换固定 l.personaID(memory/request/turn)+ **agent 池**(Options.Agents,按角色取 instructions,未命中回落)+ **提取器不再把 persona 烤死在构造期**(多角色下记忆不再永远记在 cyrene 名下)+ **thinking 旋钮改为按会话角色解析**(否则角色 Y 会用角色 X 的预算/展示)
- gateway:会话 DTO/POST/PATCH 支持 personaId;ws/rest/voice 的 OwnerEnv 硬编改为**按会话解析角色**(actor 元数据语义不变);admin memories 搜索去掉硬编 cyrene
- Docs/api-client v0.42;**两处有意的行为收紧**已写明:POST /sessions body 非法 JSON → 400(原先完全忽略 body;空/null/{} 仍 201);POST /admin/memories/search 省略 personaId 且无默认角色 → 400(原先默认查 cyrene)
- 测试:design/22 §5 验收 1-6(记忆隔离/提示词首条 system/情绪按角色/提取 persona 归属/迁移兼容)+ 进程内 e2e(断言 adapter 收到的 model.Request.Messages[0] 即该角色的 systemPrompt)
- **已知未做(留批次 2 / 待确认)**:① IM 与渠道级未做 → **§7-3「owner 私聊镜像随主会话角色」尚未生效**;② 请求级覆盖未实现(本批只做会话级);③ **§7-5 的「上下文发送角色标记」只完成存储+DTO 半边**——消息 persona 已落库且 DTO 已带,但模型上下文不从 chat_messages 重建,「第 N 条是谁说的」尚未进上下文(需确认是否属批次 2);④「切角色重建摘要」当前是空操作(压缩未接线);⑤ thinking 旋钮仅在流式路径生效(非流式 agent.RunStep 不带,A 批次既有性质)
- 验收:go build/vet/test 全绿 + linux/amd64 与 darwin/arm64 交叉编译(既有 flake 本轮未触发;同批 session_orchestrator.go 一度 501 行 → 抽出 session_tail.go)
2026-10-03 20:12:29 +08:00
AskaEth 99f222761e feat(voice): 语音silent降级信号(C2) — provider仅在结果为空时出现
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- voice/Chain+Service: STTWithProvider/TTSWithProvider(真实档位cloud/local/edge-tts/espeak/silent), 旧方法改薄包装
- gateway: transcribe空文本带{text,provider} / voice_output空音频带provider / speech空音频tts_empty+X-Voice-Provider头
- middleware: CORS Access-Control-Expose-Headers: X-Voice-Provider
- 可选接口 voiceProviderReporter(type断言透传), 自定义实现回退silent
- 新增测试10个(provider_signal/voice_signal), build/vet/test全绿+交叉编译
- Docs/api-client v0.23 + api-reference CORS 同步
2026-09-08 21:23:12 +08:00
Aska 03d7050e1e feat(voice): 百炼声音复刻create_voice + TTS instruction情绪驱动(主TTS-昔涟复刻音色)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
2026-09-08 06:48:15 +08:00
Aska 73dabb9dde feat(voice): 阿里百炼 STT/TTS 主链路接通(base64 STT + cosyvoice TTS按voice_id + REST /audio/* + voice_input.deviceId)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- voice/dashscope.go 新建:DashscopeSTT(qwen-audio-3.0-asr-flash, base64 data URI→text) + DashscopeTTS(cosyvoice 按 voice_id, 取非流式 24h URL 下载字节)
- cloud.go newDashboardSTT/TTS 由空 endpoint stub 改为真实百炼 adapter
- chain.go gating 从 DashscopeAPIKey!="" 改为 voiceConfigured(cfg); silent 兜底保留
- config.VoiceConfig 扩展 DASHSCOPE_BASE_URL/VOICE_STT_*/VOICE_TTS_* 字段(必填 DASHSCOPE_API_KEY)
- gateway: POST /api/v1/audio/{transcribe,speech} (owner+审计+MaxBytesReader); voiceInputRequest 增 deviceId 并透传 runner.Run
- 实测: cosyvoice-v3.5-plus+longxiaochun 回 418(引擎拒绝), 改用 cosyvoice-v3-flash+longxiaochun_v3; TTS 你好我是昔涟->106124B wav -> STT 回 你好我是西联, 链返回真实字节/文本
- 单测: dashscope_test/config voice defaults/gateway audio_test; go build/vet/test 全绿
- 声音复刻(响昔涟音色)待公网参考音频; 不做 create_voice
2026-09-08 06:06:02 +08:00
Aska adad4e1f62 fix(session): 群聊/陌生人记忆隔离——MemWritable 贯穿 loop(AGENTS.md 红线)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
群聊/陌生人查记忆只读不写、不泄露主人敏感;owner 默认行为完全不变。

- loop/sessionenv.go:SessionEnv 类型 + WithSessionEnv/sessionEnvFrom/OwnerEnv——每次 Run 携带会话
  隔离上下文,经 context.Context 传递(不改 Run 签名、不存 Loop/Options 字段,避免 16 并发渠道
  消息共享 Loop 的数据竞争;Chatter 接口与测试桩签名不变)。
- loop/memory.go 门控:injectMemory 读——MemWritable=true(owner)走原 Retriever.Inject 全量不变;
  false(群聊/陌生人)改 Retrieve 后只留 ScopeProject(人人可读)、剔除 ScopeUser(owner习惯私有)与
  ScopePersona(角色日常=owner敏感),块首加「群聊隔离」标记,无项目记忆不注入;extractMemory 写
  false 直接 return 跳过(不调用 extractor 不落库)。
- 渠道入站(Channelbridge)传真实会话 MemWritable/Env;Web/REST/WS/voice chat 绑 OwnerEnv(JWT=owner
  行为不变);backthink/automations/orchestration 默认 owner 全量。
- 测试:memory_gating_test 6 用例(owner/群聊只读不写/陌生人受限/无项目记忆不注入/默认owner全量)全绿;
  loop/session/gateway 既有测试无回归。go build/vet/test 47 包全绿。

遗留:ScopeProject 过滤在 loop 内后处理实现(未改 memory 包),若后续允许可在 Retriever 加 scope
过滤选项消除与 Inject 模板的重复(2处)。
2026-09-06 20:34:06 +08:00
Aska 518bd0a230 feat: admin 端点补齐 + 视觉真推理 + 语音链路 + wire.go 收口(A+B+第3步)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
批次A admin 端点(原本 404 变 200 真实数据):
- GET /admin/llm:读 s.cfg.LLM 组 openai+anthropic 两 provider(enabled=当前 Provider、multimodal=配 VisionModel),APIKey 不进 wire 零泄露。
- GET /admin/automations:*automations.Service.List()(reminders+event rules+cron schedules,cron 加只读登记)。
- GET /admin/users:cfg.AdminUser + *auth.APIKey.List()(密钥掩码);无用户存储,恒先返回当前 admin 账号。
- GET /admin/backthink:*backthink.Backthink.List(ctx,50)。均只读、owner/admin RBAC、{data} 信封。

批次B 视觉真推理 + 语音:
- rest.go chatRequest 加 Image?;流式 publishChatStream 带 image;userChatMessages 构造 ImageMessage(model.go:71)。
- loop/vision.go:ImageResolver 可注入(MVP 先看图再对话);run.go Run 开头 resolveImages,无 resolver 透传直交主模型。
- vision/resolver.go:MessageResolver 调 vision.Router.Route——KindMain 保留图片交主模型多模态、KindVisionTool/OCRTool 经 dispatcher.Invoke 折叠成 [图片内容] 文本、KindUnsupported 记日志保留原图不崩。
- gateway/voice.go:VoiceService 接口 + SetVoice 注入点 + handleVoiceInput(未注入回 error 不崩)+ runVoiceTurn 异步 STT→loop chat→TTS→定向 voice_output 帧。
- ws_hub/ws_route:voice_input 接 handleVoiceInput;前端 ws.ts decodeBase64/playVoiceAudio/case voice_output。

第3步 wire.go 收口(唯一碰 wire.go 的一步):
- Deps 补传 Automations:a.automation / Backthink:a.backthink / Users:auth.NewAPIKey(a.cfg.Auth)(*auth.APIKey 原生满足 UserStore,避免 admin 重复的复合类型)。
- gw.SetVoice(a.voice);loop.Options.Vision = vision.NewMessageResolver(router, info, dispatcher.Invoke)(router=NewRouter(WithVisionTool/WithOCRTool)、info=cfg.LLM.VisionModel)。

实机验证:四 admin 端点 200 真实数据(llm 双 provider 脱敏、users=admin,yeij0942,owner);WS 握手正常。go build/vet/test 全绿 + 前端 tsc。wire.go 557 行。
2026-09-06 18:54:05 +08:00