Repository navigation
Commit 25c6447
authored
* docs(spark): session 模型/强度对持久化设计(#879)
设计定稿(v2,2026-09-02):(模型,effort)成对单值;显式选择即记忆——来源为
用户/记忆的对才随消息携带并持久化,默认来源不携带不记忆(没选过的人继续跟随
bot 默认);welcome=草稿+种子链;多 tab 同浏览器共享 view 同步、跨浏览器最后发送者赢;
渠道 /model//reasoning 清空 session 对;ACP 对存 runtime_metadata。
附录 A 含 v1→v2 修订记录与代码证据。
* feat(agent): session 模型/强度对持久化后端(#879)
- 迁移 0146:bot_sessions 加 preferred_chat_model_id/preferred_reasoning_effort
(成对写、成对清,NULL=无记忆;写不碰 updated_at)
- 解析链:请求 > session 记忆 > subagent pin > bot 默认 > 历史;schedule 轮跳过记忆;
effort 记忆 shadow stored(不进 ReasoningRequestedEffort,不串子代理)
- 写点(全经 reconcile,DB 不存非法对):picker PATCH;首发 createSession body 随 INSERT;
每轮 resolve() 内请求携带且与记忆不同才写(门=数据,渠道结构不携带);
渠道 /model//reasoning 成功后将 session 对清空(P11')
- welcome 种子端点:该 bot 该用户最近一条有记忆的 native session
- ACP:对存 runtime_metadata(acp_model_id/acp_reasoning_effort),PATCH 双写 agent
自报值,spawn 后回放覆盖 profile 默认(治 effort 回退)
- fork 继承源对;sqlc/swagger/sdk 重生;机制测试:解析链顺序/记忆级/写回门/渠道清空
* feat(web): session 模型/强度对持久化前端(#879)
- composer 对搬入 ChatViewEntry(pairModelId/pairEffort/pairSource):
同 session 多 tab 共享同步;ref 改 computed 桥接;promoteDraft 迁移(首发不闪回)
- 来源状态机:user/session 才随 send/retry/edit/createSession 携带;
default/unset 省略——服务端据此区分'没选过'(跟随 bot 默认)与'选过'(记忆)
- 播种:repoint 重播种不覆盖 user;welcome=本机草稿>种子端点>bot 默认;
pin/运行时切换按转移表标来源;换模型落新模型默认档(P6')
- picker 纯乐观,PATCH best-effort 失败静默;删 store 层 override 死代码
未经人工 QA:spec §1.4 九幕走查待做
* fix(web): composer 加载 spinner 改为 3 秒后才显示 + spec P8′ 措辞
- 触发器 spinner 延迟:加载 3 秒内不出 spinner(用户反馈:快速加载不该闪);
popover 菜单内等待行保持即时(用户开着菜单主动等)
- spec:P8′ 同步范围明确为 dockview 面板级;两个浏览器标签页=跨设备语义
(最后发送者赢,刷新收敛),消除'同一浏览器内'歧义
* fix(db): 0146 外键改为团队期复合形式,修 lint CI
- 0146 迁移的 preferred_chat_model_id 外键改用团队期后的复合写法:
(team_id, col) REFERENCES models(team_id, id) ON DELETE SET NULL (col)。
裸 SET NULL 会让 confdelsetcols 为 NULL,被 TestTeamChainReversible
守卫判为"可清 team_id 的不安全 FK"(CI Migrations 红)。0001 无需改:
其团队期通用块会把单列 FK 重写成同一形状,全新/增量两条路径收敛。
- golangci 三处:contract.go 与 service_model_preference_test.go 的
gofmt 对齐(rebase 合入遗留),service_model_selection_test.go 的
unused-receiver。
- 另两个 CI 失败与本分支无关(分支不碰 native/docker):
TestSpawnAdapterGenerateWithWatchdog* 为预存竞态(本地 -race x20 全过),
server-entrypoint 的 alpine:3.23 拉取失败为 runner 网络问题。
* fix(web): rebase 后修复 chat-pane 编译——可空 botId 守卫、收窄绕过、补导入
rebase 到 94d468e 后四处适配(main 侧变化引入,非行为变更):
- currentBotId 变为 string|null(#1131),persistComposerPair/seedWelcomePair
补 botId 空守卫;
- vue-tsc 对 pairSource.value 链收窄到新不含 'user',post-await 重查改走
paneView 链(该重查是防种子竞速的必要逻辑,不是冗余);
- useDelayedTrue 补 type Ref 导入,onUnmounted 改用文件已导入的
onBeforeUnmount。
chat-pane 剩余两处 TS6133(textareaEl/composerEl)为 main 自带基线,
与本分支无关。
* fix(agent): #879 review 修复——半对读侧守卫、WS 首发 reconcile、preference SQL 补 team_id
- sessionModelPreference:模型列为 NULL 时 effort 一并置空(半对只可能由
ON DELETE SET NULL 单列清出;否则强度会被贴到回落模型上,spec §3.7 禁止)
- createWSChatSession:携带的对先经 ReconcileSessionModelPreference 再 INSERT,
与 REST 首发一致(此前已删模型 UUID=FK 违反 500、slug 退化成半对、非法 effort
原样入库)
- UpdateSessionModelPreference/GetLatestSessionModelPreference 补
team_id = memoh_current_team_id()(sessions.sql 全文惯例,FORCE RLS 之下的
纵深防御),Update 加 deleted_at IS NULL 守卫
* fix(web): #879 review 修复——草稿仅首发成功时清除、种子跨 bot 守卫、对携带门入测试
- clearPairDraft 从通用 repoint watcher 挪到 handleSend 成功路径:
此前 welcome 未发草稿仅因点开历史会话/硬刷新就被清掉,直接违反 spec
P2′;现在草稿只在 welcome 首发成功(对已落库)时消费,发送失败保留
- seedWelcomePair await 后补 bot/view 同一性守卫:切 bot 后迟到的种子
不再写进另一个 bot 的 welcome(此前会跨 bot 串染并随首发携带)
- 携带/省略门与草稿助手提取进 chat-pane-send.ts(carriedPairForSource/
*ComposerPairDraft/welcomeSendConsumedDraft),补 6 组机制测试——此前
该状态机零测试
* fix: 区分命令成功与消息提交并隔离跨模型推理强度
* fix(chat): 捕获发送快照时立即保护偏好读取
* fix(claudecode): 保留完整模型名与别名的兼容性
* refactor(web): #879 composer pair 状态收拢到 useComposerPair
- 5 个分散的重置/刷新 watcher 合并为一个:以 runtime 身份为键,同 view 身份变化即重置并重载,view 切换不重置
- 修复已有空会话切换 Agent/runtime 后残留旧模型对(旧 watcher 遇 sessionId 直接返回)
- 修复 welcome seed 在默认外部 Agent stage 期间返回,把 native UUID 塞进 direct 草稿的竞态
- pair-sync 新增 invalidate(),重置时作废在途读写
- chat-pane.vue 净删约 190 行;新增 5 个状态转换测试
* perf(agent): #879 direct runtime 重复发送相同模型对时跳过目录探测
Claude Code 的 ModelCatalog 每次新起 CLI 等 initialize,Codex 调 model/list;
已记忆的 Web 会话每次发送都携带同一对,只在与已存对不同时才重新校验。
revision 仍每次推进,旧 picker PATCH 依旧被拦。
* test(db): #879 integration 测试改走真实迁移链;PATCH revision 必填
- 删除手写假表 + 字符串切 sqlc 源码的夹具,改用 freshMigratedDB/migrateTo/
applyCanonicalInitOnly:链可逆、0146 幂等、fence/换 runtime 清空/FK SET NULL
在真 schema 上验证
- PatchSessionModelPreference 的 expected revision 改为必填,删掉无调用方的
无条件写分支;picker 写永远是 CAS
- 0146 up 注释精简并指向 0141,down 合并为一条 ALTER
* fix(web): 保护发送准备期间的模型选择与 welcome seed
* fix(chat): 偏好写入结束后立即保存后续模型选择
* fix(chat): #879 review 收尾——发送失败不再卡死 pair 重校验等四处
- composer-pair-sync: dirty 布尔改为 pending 在途计数 + unsaved 未保存
标记。任何失败(发送或写入)都归还计数,普通消息发送失败不再永久
关闭该 view 的服务器重校验;离线失败的 pick 仍受保护到下一次确认
发送;invalidate 只清 unsaved,计数由 settle 自然归还(避免双重计数)。
- picker PATCH 409 冲突不再被静默吞掉:write 新增 onError 出口,冲突时
dropUnsavedChoice + 立即刷新采纳服务端值,pane 显示已有三语言文案。
- retry/edit 接通 model_preference_settled:RetryLatestMessageInput /
EditLatestMessageInput 透传回调,local_channel 两个 WS 处理器在拿到
runRef 处发事件,前端 send.ts 透传、pane 接 finish(false)。生成期间
的改选不再等整条回复结束才落库。
- direct runtime 写回失败降级为 warn(与 native best-effort 契约一致),
不再让一次 DB 抖动杀死用户消息。
- persist 的 PATCH 响应回写按 usesDirectRuntime 取列,与 applySessionPair
对称,native 会话不会吃到残留 external id。
测试:sync 原语 +2(失败发送恢复/冲突出口)、useComposerPair +3(失败
发送恢复/未保存保护/冲突回退/direct 双列回写)、chat-list +2(retry/edit
settled 透传与错配不放行)、Go direct 写回失败回归 +1。
1 parent 8d5dfae commit 25c6447
71 files changed
Lines changed: 4921 additions & 481 deletions
File tree
- apps/web/src
- composables/api
- i18n/locales
- pages/home
- components
- composables
- store
- chat
- cmd/agent
- db/postgres
- migrations
- queries
- docs/spark
- internal
- agent
- adapter/agentsession
- application
- runtime
- acp
- claudecode
- external
- apperror
- channel/inbound
- chat/thread
- command
- db
- postgres/sqlc
- store
- handlers
- packages/sdk/src
- @pinia
- spec
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
38 | 47 | | |
39 | 48 | | |
40 | 49 | | |
| |||
117 | 126 | | |
118 | 127 | | |
119 | 128 | | |
| 129 | + | |
| 130 | + | |
120 | 131 | | |
121 | 132 | | |
122 | 133 | | |
| |||
158 | 169 | | |
159 | 170 | | |
160 | 171 | | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
161 | 204 | | |
162 | 205 | | |
163 | 206 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
24 | 29 | | |
25 | 30 | | |
26 | 31 | | |
| |||
520 | 525 | | |
521 | 526 | | |
522 | 527 | | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
523 | 535 | | |
| 536 | + | |
524 | 537 | | |
525 | 538 | | |
526 | 539 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
222 | 222 | | |
223 | 223 | | |
224 | 224 | | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
225 | 235 | | |
226 | 236 | | |
227 | 237 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
234 | 234 | | |
235 | 235 | | |
236 | 236 | | |
| 237 | + | |
237 | 238 | | |
238 | 239 | | |
239 | 240 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
230 | 230 | | |
231 | 231 | | |
232 | 232 | | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
233 | 236 | | |
234 | 237 | | |
235 | 238 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
227 | 227 | | |
228 | 228 | | |
229 | 229 | | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
230 | 233 | | |
231 | 234 | | |
232 | 235 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
230 | 230 | | |
231 | 231 | | |
232 | 232 | | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
233 | 236 | | |
234 | 237 | | |
235 | 238 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
1 | 13 | | |
2 | 14 | | |
3 | 15 | | |
| 16 | + | |
| 17 | + | |
4 | 18 | | |
| 19 | + | |
5 | 20 | | |
6 | 21 | | |
| 22 | + | |
7 | 23 | | |
| 24 | + | |
| 25 | + | |
8 | 26 | | |
9 | 27 | | |
10 | 28 | | |
| |||
108 | 126 | | |
109 | 127 | | |
110 | 128 | | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
77 | 77 | | |
78 | 78 | | |
79 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
0 commit comments