AskaEth
|
2c56bc9704
|
fix(search): 「上游没给链接」不再被当成「没有结果」(真机 no results 的根因)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
真机现象:她自主思考的 4 次 web-search 全部报
`search: no results (provider=zhipu)`,而同一查询直连上游返回 10 条。
根因:`Finalize` 把「link 为空」当成「不是一条结果」整条丢弃。而智谱
`search_std` 的 `search_result[].link` 在真机上**经常整批是空串**(实测同一
payload 连打 6 次:10 条全空 link,title/content 齐全;换查询也见过 6/10 空)。
⇒ 10 条被整批丢光 ⇒ 工具层如实报「一家都没查到」——**那是谎报**。
为什么面板探针是 ok:探针走 `search.Probe → p.Search`,**不过 Finalize**;
工具走 `Execute → p.Search → Finalize`。同一份上游、同一份解析代码,两条路
给出相反结论 —— 探针对这一类缺陷**结构性失明**,以后不能拿探针通不通推断
工具通不通。
修法:无链接条目**照原样保留**(title/content 对模型仍有用,链接空着就空着,
**绝不编一个出来**);判据改为「link/title/content/snippet **全空**的空壳行才
不算结果」;无链接条目不参与按 link 的去重(没有链接就没有判同身份,宁可重复
也不静默吞)。「空结果 ≠ 成功」**未放宽**:真·空 search_result 仍报 ErrNoResults。
验收(主会话复跑 + 亲自变异):go build ./... + vet 绿;io 与 search 两包绿;
我用 -overlay 把判据退回缺陷形态 ⇒ TestWebSearch_ZhipuLinklessResultsAreNotNoResults
变红,报错串与真机逐字相同。子代理另用真 key 走 in-process 工具路径实测:
三条当时失败的查询现在各回 10 条。
⚠️ 本修复要等下次 build + restart 才真机生效(现在跑的还是老产物)。
⚠️ 其他四家是否也有空 link 形态未验(无 key);修复是通用的。
|
2026-10-07 10:28:36 +08:00 |
|
AskaEth
|
bc1dee3f56
|
refactor(search): provider 配置面去 env 化 —— 加新家不再需要动 .env
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
动因:`.env` 已冻结(基础键不加/不改/不删),而「加一家 provider」原本会逼出
新的 env 键(一家一个 struct 字段 + searchProviderVector 逐家读 + 逐家写死的
switch)⇒ 想接腾讯云元宝/秘塔就只能破红线。面板本来就该是插件配置的一等来源
($DATA_DIR/config/plugins/web-search.json),故让**文件成为权威**。
- plugins/tools/io/search/registry.go:接入位表加 defaultBaseURL(「没配 baseUrl
回落代码默认值」从此只有一个出处);新增 Descriptor(s)/DefaultBaseURL。
- cmd/cyrene/websearch_providers.go(新):按接入位表逐家算出生效投影 ——
加一家时这里**零改动**,这正是本片的核心;顺手把 wire_io_tools.go 从 430 行
降到 342(它逼近 §10 的 500 行上限)。
- cmd/cyrene/wire_plugin_actions.go / websearch_action_data.go /
websearch_selection.go:基地址判定统一走「文件值 → 接入位默认值」的进位链;
checkPrimaryUsable 判据不放松(真没配齐仍 400 primary_not_configured)。
🔴 **一处对我任务书的纠正(子代理提出、我采纳)**:我要求「既有 6 家在文件里
没有该条目时仍回落 .env」。仓库现状**没有**这层回落,且有回归用例把它钉死
(TestWireIOTools_PanelConfigClearedProviderDoesNotReviveFromEnv:「文件里没有
的家不得从 .env 复活」)。本片按「不改变既有行为」实现 —— 我的要求才是错的:
文件一旦存在就是权威,env 只在文件缺失/为空时播种。
验收(主会话复跑 + 亲自变异):go build ./... + 两包 vet 绿;search 包与
cmd/cyrene 全绿;我用 -overlay 让文件里的 apiKey 被忽略 ⇒ 4 条用例变红
(含「无 env 字段的家只认文件也能进注册表」这条核心判据)。
⚠️ 新家仍未接:腾讯云元宝(tencent_wsa)/ 秘塔(metaso)两片随后串行落地。
|
2026-10-07 10:18:58 +08:00 |
|
AskaEth
|
e5e5207c94
|
test(channelbridge): 补跨「渠道桥 → 网关」的 IM 附件整链回归
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
安卓端的 P0(「IM 入站的文件要挂到消息的 documents 上」)其实早已修复
(679cee0):附件引用在落库那一刻写进 chat_messages.document 列,DTO 的
documents 由该列解出。但既有两个用例各据一半(渠道桥侧只验落库、网关侧只验
投影),**没有一条真正跨过这条边界** —— 于是「哪一段断了」只能靠人读代码。
本片补一条真跨边界的端到端:同一个真实 history.Store(:memory: SQLite)
同时喂真渠道桥与真网关,走完整 IM 入站回合(真抽取器 + 真循环 + 假模型),
最后从 HTTP 原始 JSON 逐字断言该消息带 documents。
验收(主会话复跑 + 亲自变异):channelbridge 包测试绿;我把
inboundDocumentColumn 变异成恒回空串(模拟 P0 根因)⇒ 该用例变红,报错文案
正是「带附件的用户消息缺少 documents 键(这正是安卓报的 P0)」;还原后绿。
⚠️ 真渠道/真设备未跑:要主人发一条新的真文件消息才能做设备级复验。
|
2026-10-07 10:11:19 +08:00 |
|
AskaEth
|
c46053e276
|
feat(admin): 搜索提供商下拉/多选/表格显示中文名(值仍是 ASCII id)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
主人报障:「为什么中文搜索接口……下拉菜单里全给的英文名?你甚至不愿意带个括号
把中文名写上去」。根因不是漏写文案,而是整条链路没有「显示名」的位置:字段
声明只有 optionsFrom,候选动作回的就是 KnownNames() 的纯 id 数组。
- 后端:候选改为对象数组 {value,label};label 表与接入位表同源(键用
NameSearXNG 等常量),未知 id 原样回。value 逐字等于 KnownNames()。
- 前端:下拉/多选「显示 label、写 value」;表格单元格按 value→label 索引显示,
查不到回落显示原值。多选从裸输入框改成「候选开关 + 落盘值输入框」。
解码器本就兼容裸字符串/{value,label}/{id} 三形状 ⇒ 其他插件零影响。
中文名逐字:SearXNG 本地兜底(searxng)/ 智谱 BigModel(zhipu)/
阿里云 IQS 信息查询(aliyun_iqs)/ 博查 Bocha(bocha)/
火山引擎·豆包搜索(volcengine)/ 百度千帆 AI 搜索(baidu_qianfan)。
验收(主会话复跑 + 亲自变异):go build ./... + vet 绿;search 包测试绿;
tsc --noEmit 0 错;新渲染测试 26 checks + 既有 plugin panel 55 / data 90 /
schema values 40 / channel config 70 全绿。我用 sed 把 values.ts 的
option.value 全换成 option.label ⇒ 渲染测试红(「点选把候选项的 id 追加到
降级链末尾」got="bocha, 智谱 BigModel(zhipu)")—— 这正是会把配置文件写坏的
错法;还原后 md5 一致且绿。
⚠️ 契约面变更(我在 Docs/api-client.md 登记):plugin.providers 候选响应形状
字符串数组 → 对象数组;label 仅供显示、value 才是落盘值。
⚠️ 已知边界:viewer 角色看不到 form 区块 ⇒ 表格对 viewer 仍显示裸 id(未做)。
⚠️ 真机浏览器点击未跑(项目无 jsdom)⇒ 建议刷新管理页点一次确认观感。
|
2026-10-07 10:08:19 +08:00 |
|
AskaEth
|
8051906afa
|
fix(turnreply): 产出侧不再产出未配对的段落标签(安卓报障的回执)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
安卓客户端登记(他们文档 02 末节):一条助手消息的 content 是
`<p><p>正文</p>`,按他们的解析契约(非贪婪)必然把 `<p>正文` 当内容 ⇒ 用户
直接看到字面 `<p>`。任何按该契约定实现的消费方都会踩。
根因(两半都证实,都在同一处):
- (a) 规整器**原样放过**模型吐出的 `<p><p>X</p>`:段块正则非贪婪,把它当成
一个"已完整包裹"的块逐字保留(旧的覆盖检查用同一个正则 ⇒ 护栏本身是盲的);
- (b) 规整器**亲手制造**该形状:末段漏 `</p>` 时无条件套一层 ⇒ `<p><p>X</p>`。
实证:模型吐 `<p>那现在…?`(无闭标签)经旧代码规整后与上报串**逐字节相同**;
- (c) 顺带修一个幂等漏洞:落单 `</p>` 旧行为会越跑越多(`<p></p></p>`)。
修法(新增 paragraph_repair.go:配对修复 + 接线):
`<p><p>X</p>`⇒`<p>X</p>`;`<p>X`⇒补 `</p>`;`<p>正文<p>`⇒合并;`<p>A</p><p>`⇒
丢空开标签;`<p></p>`⇒整对丢;落单 `</p>`⇒丢标签正文不动。不吞正文护栏:
`<p`(无 `>`)/`<p2>`/`1 < 2`/`a<b>`/代码围栏/`<action>` 内 `<p>`/自闭合
`<p/>` 一律原样(每条都有用例)。`normalizePiece` 改为"补闭不补开"——在造出
畸形的那一点上根治。
验收(主会话复跑 + 亲自变异):go build ./... + vet 绿;turnreply /
gateway 全量 / channelbridge 三包绿;我用 -overlay 摘掉配对修复接线 ⇒
TestNormalizeParagraphs_* 变红。生产库只读核查:177 行 assistant 里**仅 1 行**
畸形(各消费方已容错)⇒ 不做一次性修复脚本。
⚠️ 未部署:跑着的 :10942 仍是旧产物 ⇒ 畸形仍会产出,安卓端的容错请继续保留。
|
2026-10-07 10:07:13 +08:00 |
|
AskaEth
|
378faf212e
|
feat(browser): 取正文能力 + web-fetch 浏览器降级档接线(解封 Z5/B5)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
Z5(c2e413e)把 web-fetch 的降级链与注入点做完了,但「取正文」入口缺失 ⇒
组合根拿不到 BodyRenderer、这一档实际关着(当时如实登记)。本片补上:
- internal/capability/browser/render.go:新增 Manager.RenderText(ctx,url)
(导出的进程内能力)—— 先过 GuardURL(与全仓同一份 SSRF 判定源)、复用
withSession/session、等 readyState=complete 之后才取 body.innerText;
渲染失败 = 分类错误,渲染成功但正文为空 = 空串+无错(不冒充成功/失败)。
- cmd/cyrene/wire_body_fallback.go:适配器 + 挂载点,把 Manager 适配成
io.BodyRenderer 并用 WithBrowserFallback 挂上;web_runtime 里把浏览器
接线**上移到 io 工具集之前**(顺序颠倒会静默关死这一档)。
- plugins/tools/browser/tool.go:新增 Tool.Manager(),供组合根取驱动句柄。
开关口径(裁决,依据 design/28 §1 M5 / §7 判据 4 / §8 B5):**有可用浏览器
就挂,没有就不挂**,不新增开关 ——
① 设计把 M5/B5 写成要落地生效的降级档,不是永远关着的空壳;
② 设计 §8 的可调项清单里没有这条降级档的开关,`.env` 已冻结 ⇒ 自造开关属
「自行发挥」;
③ io 库层「不传 = 默认关」的语义一字未改,本片只把组合根从「永远关」改成
「没来源就关」,并留带来源的 WARN(reason=no-usable-browser)。
⚠️ 若日后要「有浏览器也需显式开启」,得先给设计定开关落点,代码侧一行改回。
验收(主会话复跑 + 亲自变异):go build ./... + 三包 vet 绿;browser/io 两包
测试绿(cmd/cyrene 由子代理跑过全绿);我用 -overlay 把 GuardURL 的判定对象
换成常量 URL(绕过被拒目标)⇒ TestManager_RenderTextBlockedURLRejectedBeforeAnyProcess
变红,证明判定确实**在起任何进程之前**跑。
⚠️ 生产端到端未验:按红线没重启后端、没起真 Chrome ⇒「真页面 → browser 取到
正文」这条链只有假 CDP + 组合根接线级证据。
⚠️ design/28 有 6 处表述与代码现状冲突(归属 web-fetch vs web-search、extract
动作归属、B5 排期、状态过期等),已登记待我同步文档。
|
2026-10-07 09:59:56 +08:00 |
|
AskaEth
|
25aa50e532
|
feat(search): 智谱 provider 按官方 schema 加固(请求补确证字段 + 错误码分档)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
官方文档逐页确证后落地的四件(分册 11 的「官方 schema 确证(2026-10-07)」):
- 请求补 search_intent:false(官方标 required,缺发可能触发 1213)与
content_size:medium;count 仅 1–50 透传,越界不发该字段;
search_query >70 rune 直接报错且**不发请求**;
- 响应按官方收窄:摘要只认 snippet/summary/abstract 候选(官方响应**没有**
snippet),publish_date 入 Published;
- 错误码分档:1000/1001/1003⇒unauthorized、1113⇒quota_exceeded、
1302/1305⇒rate_limited。🔴 1113 与 1302/1305 **同为 HTTP 429** ⇒ 只看状态码
分不开「该充值」与「该退避」,必须读 error.code(码同时进日志文案);
- media/icon/refer 当前一律不投影(Result 没有「来源站点」位;要投影应给
Result 加字段 + 同步契约,不许塞进 Snippet —— 否则摘要位会被站点名恒填满)。
另修两处过期注释(providers_test.go 仍写「只发 search_engine/search_query」)。
验收(主会话复跑 + 亲自变异):go vet 绿;search 包与调用方 io 包全绿;
我用 -overlay 删掉 1113⇒quota_exceeded 映射 ⇒ TestZhipuErrorCodeMapping 变红
(欠费被误报成限流、探针码 rate_limited)。
⚠️ 候选键容错暂未删除:官方已排除的键保留到**真机实测通过后**再收窄(现无 key)。
⚠️ 真机未跑:仍只打 httptest,官方真实响应形态未实测。
|
2026-10-07 09:59:24 +08:00 |
|
AskaEth
|
c512609c63
|
feat(admin): 记忆整理候选的应用/回滚操作面(切片 TIDY-FE)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
主人报障「面板上点不到『应用』」→ 后端 TIDY-1 的五条端点(契约 v0.83 B20–B24)
此前只能 curl 驱动。本片补齐界面:候选表(动作/状态/摘要/理由/时间 + 行内
应用/回滚,回滚仅在 status=applied 时可点)、status 筛选、批量应用全部待定、
手动真跑一轮(两个写动作都走二次确认)。
三条契约硬口径落到界面:
- 幂等不是错误:skipped 用中性色,绝不渲染成失败;
- 超限必须如实:truncated=true 时黄牌「还有 N 条待定未处理」,且该分支绝不
渲染「已全部处理」;未处理量只由后端权威字段算得(total - 已处理三项);
- 权威键只读:状态与计数全部取自响应,不做「应该成功了」的推断。
一个刻意的偏离(有测试钉住):截断提示不用共用 Notice tone=warn —— 那个组件
的固定前缀是「待实现」,贴在「还有 N 条未处理」上会被读成「功能还没做」。
验收(主会话复跑 + 亲自变异):tsc --noEmit 0 错;vite build 通过;
渲染测试 43 checks、传输层测试 28 checks 全绿;我把 truncated 判断取反 ⇒
渲染测试红在「截断时必须显式点明命中数大于本轮处理数」,还原后 md5 一致且绿。
⚠️ 未跑真机浏览器交互(需 owner 凭据 + 真后端),证据止于渲染层与传输层。
|
2026-10-07 09:58:21 +08:00 |
|
AskaEth
|
aa0bf8b5a0
|
fix(websearch): 面板「填 key + 同一次选它当主 provider」不再被自己的校验回滚
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
真机报障(2026-10-07 09:50):面板上给 zhipu 填了 API Key,保存却一直回
400 primary_not_configured;盘上配置文件 mtime 一动不动 —— 连刚填的 key
一起被回滚,界面表现为「怎么填都存不进去」。
根因(顺序错误):saveProvider 先 applySelectionPatch(内含「主 provider 必须
已配齐」的校验),后 UpsertProviderEntry。校验看的是**盘上的旧文件**,而这次
提交里的 key 还没落盘 ⇒ 校验判它没配齐,整笔拒绝。
修法:把校验从 applySelectionPatch 里摘出来,改名 mergeSelectionPatch(只合并
文件级字段 + 回报有没有给 primary),由 saveProvider 在 UpsertProviderEntry
**之后**对最终文件校验,再写盘。判据本身一字未改 —— 「真的没配齐的主家照样拒」。
验证:cmd/cyrene 整包测试绿;新增回归 TestWebSearchSaveProviderAndPrimaryInOneSubmit
(同一次提交填 key + 选主家 ⇒ 200 且盘上 key 与 primary 都在;反向:真没配齐仍 400
且文件字节不变);用 -overlay 把校验改回「拿旧文件校验」⇒ 该用例变红且报错文案
与主人看到的逐字相同。
|
2026-10-07 09:56:37 +08:00 |
|
AskaEth
|
ef8fc66e54
|
docs(contract): v0.83 —— 记忆整理应用面五条端点 + 读侧 status 闸 + 两处过时口径改正
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
新增 §2.2 B20–B24(候选列表 / 单条应用 / 批量应用 / 单条回滚 / 手动真跑)、
§4.15 详解(三条硬约束:幂等不是错误 / 超限必须如实 / 软动作永不物理删除)、
错误码表补 404 tidy_run_not_found、409 tidy_disabled、500 六个 tidy_*、503 tidy_timeout;
计数 writeAuth 19 → 24、总数 73 → 78(按 routes.go 核:writeAuth 挂载 admin 26 条,
减去历史口径的 channels/events 与 counters ⇒ 24)。
改正两处已成假话的 §7.2 条目:
- 「整理候选 apply/revert/列表/运行均未实现」→ 已实现五条,仍缺 reject / 运行历史读口 / 按 run 筛候选
- 「面板记忆页无法过滤」→ 补一句:v0.83 起服务端已按 status 过闸,字段面仍未补齐
诚实边界写进契约:生产库零动作 / 面板真机未跑 / 旧候选 run_id 为空串 /
run_id 列只在存储包前滚 / 语义召回不可复现。
|
2026-10-07 09:51:57 +08:00 |
|
AskaEth
|
f847769698
|
test(gateway): 面板记忆列表过 status 闸的端到端回归(TIDY-1 补证)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
真实 sql.DB + 真实 memory.Store + 真实 HTTP handler:两条在册 ⇒ 面板 2 条;
软合并一条 ⇒ 只剩被保留那条;再归档另一条 ⇒ 200 + 非 null 空数组。
复核(主会话亲自):目标测试绿;用 overlay 把 store.List 的 status 闸
变异成恒真 ⇒ 该用例变红(证明它真的在测那条闸,而不是在测夹具)。
顺带确证一件口径:GET /admin/memories/reviews(审查留痕)**不该**过 status 闸
—— 留痕表本身无 status 概念(preinsert_schema.go:29-46),且它是软删行的
查看与撤销入口,加闸等于审计自我抹除。
|
2026-10-07 09:49:57 +08:00 |
|
AskaEth
|
9126d653e5
|
fix(memory): 读侧过 status 闸 —— 软删行不再被检索、不再进面板
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
整理(tidy)与入库前审查(D3)都只做软动作:status 改 merged/archived,
正文一个字不改、行一行不删。因此只要有一条「能看到什么记忆」的读路径
漏了 status 闸,清理就等于白清 —— 生产库上那 10 条 merged 行就是反例。
- store.go:ListByPersona / List 加 status='active'
- rules.go:ListScope / ListProject 加 status='active'
- Get 刻意不过闸(撤销软合并要先读得到被吸收的行),并在注释里写明
- gateway/admin.go collectMemories 只加注释:口径只有一处,不重复过滤
验证:go build ./... + go vet 绿;memory 包全量测试绿;
新增 status_gate_test.go(4 条读路径逐条断言 + Retriever 端到端
「内容逐字相同的两条,软合并后只召回一条」+ Get 反向护栏);
用 -overlay 把闸门变异成恒真 ⇒ 5 个读路径用例与检索端到端用例全红。
|
2026-10-07 09:48:37 +08:00 |
|
AskaEth
|
c2e413ec38
|
feat(io): web-fetch 直连→浏览器渲染降级档 + fetchedBy 如实标注(Z5 机制)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 降级链:直连失败 / 判定为动态页 ⇒ 浏览器渲染取正文;返回体带 fetchedBy=direct|browser,
两条档的失败各自留痕(directError/browserError/browserSource/dynamicSuspect),**绝不静默替换**
- 被 SSRF 拒绝的目标**不换路**(红线);渲染器缺位时如实报双失败
- 3 个变异自检(去掉动态页判据 / 去掉 SSRF 短路 / 掩盖双失败)
⚠️ **生产接不通**:internal/capability/browser 没有「取正文」入口(不在本片文件面)⇒
开关默认关、不假装可用;解封形状已在报告里给出(加 RenderText ≈40 行)
|
2026-10-07 09:34:47 +08:00 |
|
AskaEth
|
20f82c9679
|
docs(contract): v0.82 —— resultSummary(失败也带)+ 自排成本可见面 + browser 面板(Z4)
- tool_execution.end 的 resultSummary(含失败口径、≤500 rune、空 ⇒ 缺席)
- GET /admin/backthink 加 ?trigger=(闭集 + 未知/空 400 invalid_trigger + 下推 SQL)+ 新端点
GET /api/v1/admin/backthink/self-wake(writeAuth、三态、gate 快照、*IsDefault 语义)
- GET /admin/panels 新增 browser/settings + 六个动作(3 读 3 写)+ 错误码 + turnAttachment
- request_think 可达性改正(已上线);计数 72→73(writeAuth 18→19)
|
2026-10-07 09:34:46 +08:00 |
|
AskaEth
|
9fa7e65278
|
feat(loop): tool_execution.end 失败也带 resultSummary(Z3,主会话裁定)
与回看面对齐:失败调用给该次错误文本的脱敏渲染(仍 ≤500 rune、仍走 trace.RedactText),
缺席只剩「真的没有结果」(空结果 / 空错误文本)。2 变异(失败仍缺席 / 绕过脱敏)
|
2026-10-07 09:34:45 +08:00 |
|
AskaEth
|
8e2441c183
|
feat(browser): 补上 B3/B4 的两行接线(Z2)—— 面板页与截图进上下文真生效
- wire_runtime.go 加 TransformContext: a.browserShotTransform(visionResolver)(只改本轮所见)
- wire_frontend.go 在 declareBuiltinPanels 之后接 wireBrowserPanel(带 a.cfg != nil 守卫,
否则 6 处既有夹具 panic;生产路径 cfg 恒非 nil ⇒ 行为与字面写法一致)
- 3 条盯梢用例(1 条 Skip→转正 + 2 条新增),2 变异打红
- 真机(隔离实例):panels 出现 browser/settings、三个只读动作真回执、**真回合内联 image 部件
61,410 字符** ⇒ design/28 判据 2 在真产物里成立
|
2026-10-07 09:34:44 +08:00 |
|
AskaEth
|
93fc24cade
|
docs(readme): 用户侧文档按代码重写(Z1)
修正 6 条「本该 ✅ 却标 ⚠️/❌」的能力(checkpoint 恢复/DashScope ASR/异步记忆提取/知识库删除/
全链路 P2/面板 18 模块)+ 快速开始与 .env 冻结口径 + 目录结构 + **新增「已知缺口与路线图」如实列未做**
|
2026-10-07 09:34:44 +08:00 |
|
AskaEth
|
454ddb0b70
|
feat(memory): 记忆整理**应用路径 + 调度修复 + 手动真跑**(TIDY-1,主人投诉的根因)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
主人实测:memory_items 1191 行、候选 77 条全 pending、memory_tidy_runs 仅 1 行、两晚定时没跑。
根因两条(都在这片里修掉):
① **以前根本没有执行面** —— 只有只读试算,候选永远 pending
② **调度被重启饿死** —— interval=24h 的 ticker 从进程启动算起,两天重启十几次 ⇒ 24h 永远走不完
- 应用路径:逐条 / 按 run 批量(默认 100、硬顶 500、超限 truncated)/ revert;**软合并**
(status + merged_into/merged_from/merge_count,**绝不改 content、行不删**)+ 审计
(memory.tidy.apply / memory.tidy.revert)+ **幂等**(候选状态条件更新 + 行 status 闸两道)
- 调度:改成**到点即跑**(catchUp:无历史+窗口内 / 距上次 run ≥ interval / 窗口起点晚于上次 run),
「上次 run」以 memory_tidy_runs 为**持久事实**;注入时钟用例证明**重启不饿死**
- 手动真跑端点 POST /admin/memories/tidy/run(同档鉴权 + 审计 + 回执:新增/合并/软删/耗时)
- 候选表加 run_id 列 + 索引(前滚;顺序=建表→补列→建索引,否则既有库会 no such column)
- 3 个变异自检(删 catchUp / 去掉两道 status 闸 / truncated 恒 false)
⚠️ 生产库零动作:1191 行真跑与 77 条候选应用**未执行**(按红线由主人确认后主会话执行)
⚠️ 契约段在报告里(candidates 列表/apply/revert/tidy.run),Docs/ 待登记
|
2026-10-06 22:39:35 +08:00 |
|
AskaEth
|
57d0e8c543
|
feat(admin): 时间轴只读权威键 + 自排筛选轴 + browser 面板图标(Y2+Y3+Y4 前端一并落)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 时间轴:页首「已过保留期」的**唯一**判据改为 retentionBoundaryReached === true(truncated 只出
「未显示」);缺席(老后端)一句话都不说;删掉旧的 truncated+retentionEnabled+翻到底 启发式
- Backthink:筛选轴接上服务端 ?trigger=(客户端筛选保留作兜底)+ 自排闸用量行(三态文案)
- plugin/nav.ts 加 browser 图标
- 真机(隔离实例,46/46):翻页不重不漏、三种「必须 false」的权威键语义、**重启后 round 不重复**
⚠️ 未验:真机上没构造出权威键 true(需真有更早轮次被清扫)——别读成「真机验过 true」
|
2026-10-06 21:48:52 +08:00 |
|
AskaEth
|
e0a6bca501
|
feat(browser): B3 截图→上下文闭环 + B4 面板声明页(Y4)
- B3:截图落盘后**自动**并入本轮视图(能收图 ⇒ 真 image 部件挂 user 消息;收不了 ⇒ vision/OCR 文字;
大图先经 image-crop 裁切;取走即消费、每会话 ≤4 张、TTL 10min、跨会话隔离)
- B4:browser 面板**声明**(配置表单 + 运行状态/指纹自检/最近截图三张只读表 + 拍一张/重新自检)
+ 六个动作走 PLG-2 的通用动作端点(**不开新路由**)+ 保存事务(不可用则回滚 409)+ 热重载
- 读面**不启动浏览器**(计数型假 dialer 证明 0 次拨号);行数据不含路径/URL/内容
- 3 个变异(短路主路/行与列 key 脱钩/保存不回滚)
⚠️ **两行接线未落**(不在我文件面):wire_runtime.go 的 TransformContext + wire_frontend.go 的
wireBrowserPanel —— 落地前 B3/B4 只是「组件就绪」,跑着的后端里不存在(Y4 已写盯梢用例)
|
2026-10-06 21:48:50 +08:00 |
|
AskaEth
|
4213b268fe
|
feat(backthink): 自排的成本可见面(C2 读侧,Y3)
- GET /api/v1/admin/backthink 加可选 ?trigger=(闭集=内建触发标签 + 本服务订阅的事件主题;
未知/空 ⇒ 400 invalid_trigger,不静默忽略;合法值下推到 SQL ⇒ limit 是匹配条数)
- 新端点 GET /api/v1/admin/backthink/self-wake(writeAuth):闸的只读镜像
{available,running,reason?,configFile?,gate{pending,used,limit,windowSec,default*,*IsDefault}}
三态分开(未接线 / 有配置未运行 / 运行中),读它**不消耗额度**
- 零新 env 键;旋钮源 = $DATA_DIR/config/backthink.json(**写面未做**,前置=组合根接线,已登记)
- 键名沿用设计与现有代码的 selfWakePerWindow(派工书写错成 selfWakeLimit,未改键名以免废掉主人已写的配置)
- 5 个变异(未知值静默忽略/关掉下推/恒报运行中/白名单摘键/前端把看不到画成 0/0)
⚠️ 本片改了 4 个文件面外文件(admin_query.go/routes.go/api.ts/adminSystem.ts)——已逐条说明理由
|
2026-10-06 21:48:49 +08:00 |
|
AskaEth
|
215eedf8e9
|
feat(ws): tool_execution.end 带可选 resultSummary(Y1,答应安卓端的那条)
- 形状:data.resultSummary(可选)。与回看面 toolCalls[].resultSummary 代码级同源:同一个常量
(500 rune)与同一个截断函数,摘要由 **loop 侧**生成(trace.RedactText + renderToolResultSummary)
再随 StreamEvent 下发,gateway 只搬运不加工(与回看面同口径)
- 缺席语义:结果真拿到才带;失败/取消/超时/未落图 ⇒ 整键缺席(绝不用空串顶位)
- 线上帧证据:真 WS + 真 JWT + 真 loop ⇒ 客户端收到 resultSummary;同源钉用真图快照反读逐字比对
- 3 个变异(空摘要也写键/去掉脱敏/失败当结果)
⚠️ 待裁:失败路径现按派工书「整键缺席」,但回看面对失败给的是 error 摘要 ⇒ 实时无结果区、事后有;
若要实时也显示失败原因,一行可改(toolEndFrameSummary 的 return "")
|
2026-10-06 21:48:48 +08:00 |
|
AskaEth
|
a820d9968e
|
docs(contract): v0.81 —— 时间轴 retentionBoundaryReached + round 跨重启单调 + 自排可见面登记(X5)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 新增响应键 retentionBoundaryReached(与 truncated 分意,判据三条 + 三个盲区如实登记)
- round 跨重启不再重复(行为修复,客户端可放心按 round 分组)
- 登记 trigger=self_wake 与 4 条 backthink.self_wake.* 审计动词,并标明入口工具 request_think
**未接线 ⇒ 生产里目前不会出现**
- §7.1 两行状态;计数不变(无新端点 ⇒ 14+18+40=72)
⚠️ 该键取自 X1 工作树实现 ⇒ 已在文档 4 处标明「提交后按 git show 逐字复核」(本提交即该实现)
|
2026-10-06 21:16:25 +08:00 |
|
AskaEth
|
2d211c2d16
|
feat(backthink,browser): 自排工具面 C1-3 + 浏览器两处偏离收口(X2+X3 同文件一并落)
X2 C1-3(自排工具面与提示词):
- request_think(thinktool.go,照 transcode/tool.go 范式)+ reason 必填/urgency 闭集 + 双守门
(安全闸 + owner 判定:群聊/陌生人一律拒)
- **成对**进两张唤醒态允许集(quiet + awake;CAPACITY_TOOL_SETS 是整体替换)
- 提示词抽共用段落 + 自排前缀优先(不枚举工具清单);面板加 self_wake 标签与筛选轴
- 4 个变异自检(拿掉 owner 判定/只加一张表/放宽 urgency/前端标签恒等)
X3 收口(与 X2 共用 wire_services.go ⇒ 一并落):
- 删掉第三份 SSRF 实现(guard.go),改由 io.ValidateRequestURL 唯一判定 + 薄门面(保两个错误身份)
- 浏览器会话挂进 a.close(真机:真 Chrome 被关、无残留、生产未扰动)
- a.wireBrowser() 归位到 wire_runtime.go,删掉 ioToolOptions 的临时挂点
- 5 个变异自检
顺带补提交 C1-2 漏掉的 internal/config/runtimeconfig/backthink_test.go(ed50053 漏 add)。
|
2026-10-06 21:16:23 +08:00 |
|
AskaEth
|
2bf3b536dd
|
fix(flow): 时间轴两处诚实性缺陷(X1)
① round 号跨重启被复用 ⇒ 时间轴把多个真实轮次并成一块(真机实测 web 的 r:1 挤了 4 路、
startedAt 跨 13:52→21:05)。修法:发号前从落盘播种(MaxRound,json_extract + json_valid 挡坏行),
每会话每进程只播一次、失败只 WARN 且不重试、并发首轮共享一次读;接口形状零变化
② truncated 一个字段兼两个意思 ⇒ 一页没拉完时前端会说「更早的轮次已过保留期」(假话)。
新增 retentionBoundaryReached(= 保留期启用 且 已翻到底 且 现存最早一轮 round>1 ⇒ 确有轮次被清扫),
truncated 语义一字未改;盲区如实登记(整段被清扫会说少、最早一轮落盘失败可能多说)
3 个变异自检(不落账/floor>0/去掉 hasMore 守卫)
|
2026-10-06 21:16:21 +08:00 |
|
AskaEth
|
b36798265a
|
docs(comments): proactive 判据键在 data 内、不在帧壳顶层(安卓核对指出)
4 处注释写「帧顶」而代码放在 data[proactive](+ 测试文件 6 处同源表述)。
安卓端两层都读所以不受影响,但注释与代码相反会误导下一个按注释写的人。
零行为改动(仅注释)。
|
2026-10-06 21:16:20 +08:00 |
|
AskaEth
|
f1fbc249fd
|
feat(browser): B1 接线 + B2 薄层工具面(V5)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- browsercfg 接进组合根:配置读 $DATA_DIR/config/plugins/browser.json(零 env)→ 探测(本机
Chromium → 已在跑的 CDP)→ 不可用就不注册(原因码入日志)
- 自研最小出站 CDP 客户端(不 Enabled Runtime、隔离世界求值、不发 --enable-automation)+
导航 + 截图 0600 落盘 + 指纹自检;工具 browser(open/screenshot/info,owner-only)
- 3 个变异自检(启动恢复 --enable-automation/无视可用性/空闲回收失效)
- 真机对照(两站各 1 次,**如实结论**):两侧都 pass ⇒ 「headless 被拦 / headful 通过」**未被证明**;
但测到两处硬差异:无头 UA 带 HeadlessChrome、screen 800 vs 2632;两模式 webdriver 均 false
(把 L6 的推断变成实测)。跑完 0 残留 Chrome、无对外监听端口
⚠️ 未做:MCP 自动接入(口径委派未落地)/自动注入上下文/面板页/搜索降级/docker 配方/Windows 用
pipe(Go ExtraFiles 不支持);SSRF 落了第三份同策实现待收口;浏览器会话未挂进程关闭链
|
2026-10-06 20:25:16 +08:00 |
|
AskaEth
|
ea150ceea9
|
docs(contract): §2.0 端点计数回补(14+18+40=72)+ S6 未确证项收口(V4)
- writeAuth 17→18、总数 71→72(并写明自 v0.76 起 −1 的滞后已修正;历史版本条目保留原写法)
- S6 的未确证项逐条核对:能验的给代码级证据,验不了的写明「为什么验不了」(无凭据/禁重启)
- 契约版本仍 v0.80(同版内记账回补,零形状变更)
|
2026-10-06 20:25:14 +08:00 |
|
AskaEth
|
4a04ad43fe
|
feat(skills): 示例技能 + 端到端验收(V3)
- configs/skills/daily-brief/skill.yaml:真能跑的工作流(4 步依赖图 + 2 条 guardrail + allowed-tools)
- example_skill_e2e_test.go:真 Loader + 真 registry + 真 loop 三轮断言 —— 第1轮只有清单、
第2轮命中展开正文且工具面只剩 allowed(B 工具不可见)、第3轮正文保留而工具面恢复、BodyRenders==1
- 3 个变异自检(triggers 清空/关掉收缩/正文漏进清单)
⚠️ 生产未验:当前后端启动早于技能落盘 ⇒ 需一次 restart 才会出现 skills registered;
隔离实例(临时端口/临时 DATA_DIR)已 GREEN,含面板链四条真实回执
|
2026-10-06 20:25:14 +08:00 |
|
AskaEth
|
745365c7df
|
fix(admin): 时间轴分页与保留期文案按契约收紧(V2)
- 类型补上后端真在返回的 source/nextBefore/hasMore/retentionEnabled(此前类型里没有)
- 新增纯函数 pageHasOlder(hasMore 权威,老后端退满页启发式)/timelineCursorOf/retentionClaimable/
timelineHints;取数体抽成可执行导出函数 ⇒ effect 本体首次被真跑(真 fetch + 真状态机 + 真 SSR)
- 🔴 修一处成对契约缺陷:后端 truncated = hasMore || !storeWired,而契约/设计要求 truncated ⇒
「已过保留期」⇒ 旧前端会对主人说假话。现改为:只有「已翻到底 + 保留期启用 + 非 live-only」
才说「已过保留期」,其余说「更早的轮次未显示」
- 3 个变异自检(去掉 canLoadMore 短路/恒可翻页/忽略 hasMore)
⚠️ 未验(如实):鉴权后的真机 HTTP 往返拿不到 owner 凭据;前端产物未部署(面板仍是旧文案)
|
2026-10-06 20:25:06 +08:00 |
|
AskaEth
|
ed5005307a
|
feat(backthink): 自排 C1-2 本体 + TriggerUnknown 修 fail-open(V1)
- selfwake.go:WakeNow + 待跑槽容量 1(先探槽合并不过闸、槽空才过闸、同锁)+ 闸 4 轮/小时
($DATA_DIR/config/backthink.json,零新 env 键)+ 审计四条 what + 启动日志两键 + 组合根接线
- G-A(主人已批):TriggerUnknown 作零值、既有两值编号后移(语义不动),未知触发走**最紧分支**
- 5 个变异自检(拆闸/≤0 未回落/过闸挪到探槽前=G1 失效形态/槽无界/零值挪走)
⚠️ 服务侧已就绪但**她仍调不到**(自排工具面属 C1-3)⇒ 不得写「C 已完成」
|
2026-10-06 20:25:04 +08:00 |
|
AskaEth
|
301f8b4276
|
docs(comments): 清掉两处已过期的状态注释(ErrRunPending 早已不存在)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
S1/S3 大扫除点名的代码侧残留:
- cmd/cyrene/skills.go 注释仍称 Runner.Run 返回 ErrRunPending(哨兵已删,f75e7a9 起真执行)
- internal/services/gateway/admin_plugins_skill.go 注释仍称执行后置到 M12
零行为改动(仅注释)。
|
2026-10-06 18:46:58 +08:00 |
|
AskaEth
|
94da6bcd6d
|
feat(backthink): 静默期自排 C 的判定侧(C1-1,切片三之一)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 追加 TriggerSelfWake(不动既有编号)+ SelfWakeRequest(走既有 urgency 声明通道,不新造第二条)
- escalateImport 折算收成唯一 foldDeclared(事件轮与自排轮共用、只上抬取较高档)
- DecisionInput.Heartbeat bool → Kind TriggerKind;心跳仍免检、**自排不享心跳豁免**(要求声明 ≥ warning)
- push 与档位分离:push.go 零改动即自动正确(eventDriven 对 self_wake 为 false ⇒ 照旧过 PushGate)
- 4 个变异自检(折算空操作/删自排分支/常量传心跳/非事件一律豁免)
⚠️ 本片只是判定侧:WakeNow/worker/闸属 C1-2,工具面与提示词属 C1-3 ⇒ **不得写『C 已完成』**
⚠️ 遗留 G-A(建议登记进 design/12 C.4):TriggerKind 零值=TriggerHeartbeat ⇒ 漏填=最宽豁免(fail-open);
本片已在字段注释与单测里显式化,但规格侧应补一句或引入 TriggerUnknown
|
2026-10-06 18:46:27 +08:00 |
|
AskaEth
|
ea43f07bce
|
docs(contract): v0.80 —— 时间轴出口 + provider 热重载 + AMR 落副本
三批登记(S6 按代码逐条核对,30 条 文件:行 证据;我复核版本行与唯一当前版本):
① W1 GET /api/v1/admin/flow/timeline(时间正序/游标/retentionHours/truncated,计数 16→17、70→71)
② W3 热重载 + primary/fallback:新增错误码 primary_not_configured(400)/config_unstartable(409),
并改正 3 处已变假话的旧口径(『不热替换、需重启』『无主 provider 字段』)
③ W4 VoiceTranscoder 已注入 ⇒ AMR 落 wav 副本;6 处已变假话处改正
(S6 主动纠正一处口径:微信 iLink 语音刻意不下载字节,不算进『已修』)
⚠️ S6 发现既有记账错误:§2.0 条数自 v0.76(cb232e7) 起少 1(实测应为 14+18+40=72),
已在文档内如实标注请裁决,未擅自回补。
|
2026-10-06 18:46:26 +08:00 |
|
AskaEth
|
9c9a6d26c9
|
docs(env): .env 冻结最终口径 —— 基础键已定、以后不准改(不加/不改/不删)
主人 2026-10-06 二次收口:只求『统一不新增』且『基础键已定好、以后不准改』。
- AGENTS §10 与 design/13 §2.1 同步改写:新配置一律走 $DATA_DIR/config/** + 代码默认值;
既有基础键与 env: tag 保持现状(不迁移/不改默认值/不删键);E6 作废
- 新增一条判据:模板与代码若出现差异 ⇒ 那是**事故**(有人动了被冻结的东西),要回退而不是同步文档
|
2026-10-06 18:46:25 +08:00 |
|
AskaEth
|
ffe2518bf4
|
feat(memory): 留痕表正式迁移 0025 + 保留期清扫(W5)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 迁移 0025_memory_ingest_reviews(幂等,既有部署重跑不炸/不丢行)
- GC:保留期 720h + 条数上限 10 万行,挂进审查服务生命周期(Start 起 / Stop 停 / 启动先扫)
- 过期即硬删(RevertMerged 只读 memory_items,删留痕不损失回滚能力)
- 偏离一处并给理由:表只留 created_at(先例 0017;append-only;加 updated_at 需三份 DDL 真源)
- 3 个变异自检(边界 <=/元组比较方向/Retention=0)
|
2026-10-06 15:59:16 +08:00 |
|
AskaEth
|
ddd3d00d09
|
fix: 修「假话但绿」的用例 + 补 VoiceTranscoder 注入(W4)
- history_toolcalls_gap_test.go 改成正向断言:单路回合经 StartRoundWithTurnID 带权威 turnId
⇒ 落库行按该标识查得到 ⇒ HTTP 出口 toolCalls 在场;并保留「无权威标识 ⇒ 整体缺席」边界用例
- 组合根补 VoiceTranscoder: a.transcoder ⇒ 微信/QQ 的 AMR 语音在落盘前先转 wav 再落副本
- 4 个变异自检(删注入/摘 ctx 标识/清 turn_id/调换 wiring 顺序,均红)
|
2026-10-06 15:59:14 +08:00 |
|
AskaEth
|
a30f4a49ff
|
feat(search): provider 热重载 + primary/fallback(W3)
- 保存被包成事务:快照 → 落盘 → 按新配置重建工具 → 原子替换注册表条目(registry.ReplaceTool
窄方法,保留运行期 Policy);下一轮即生效,不要求重启
- 若新配置会让后端下次起不来(主家未配齐 fail-fast)⇒ 文件按字节回滚 + 409 config_unstartable
- 声明面补 primary + fallback[](可配可生效);否决「另开 form」方案(会破坏既有 reauth 回填)
- 主 provider 解析口径核查结论:没被 PLG-4 改坏(顺手修了一处日志缺陷)
- 4 个变异自检(丢 Policy/不换条目/回滚 no-op/忽略 fallback)
|
2026-10-06 15:59:12 +08:00 |
|
AskaEth
|
5ee5f9126f
|
feat(admin): Flow 页时间轴视图(W2)
- 视图切换:最近一轮(既有 DOM 逐字节未变,7/7 SSR 对照 IDENTICAL)| 时间轴(新)
- 时间轴:竖轴=时间(默认最新在上)、每回合一个可折叠块、块内复用 LaneTracks 泳道、
块间不画任何连线(不臆造因果);before 游标分页;truncated ⇒ 显式「更早的轮次已过保留期」
- 降级诚实:只拿到最近一轮(老后端)⇒ 明确提示「当前只支持最近一轮」
- 4 个变异自检(排序方向/块间插线/truncated 静默/游标方向);老视图等价性实测
|
2026-10-06 15:59:11 +08:00 |
|
AskaEth
|
1efe3a6a79
|
feat(flow): 链路图时间轴出口(W1)—— 所有轮次按时间正序
- 新增 GET /api/v1/admin/flow/timeline?sessionId=&limit=&before=:时间正序多轮,
每轮 {turnId,round,startedAt,endedAt,lanes[]};limit 缺省 50/上限 200 + before 游标
- 数据源=落盘 flow_graphs + 内存最近一轮(同图 id 去重);保留期 168h 外的轮次不返回,
但响应给 retentionHours/retentionEnabled/truncated ⇒ 前端如实标注,不悄悄少一块
- 老出口 GET /admin/flow/graph 零 diff;角色门 writeAuth(owner|admin)
- 4 个变异自检(游标 <= 重复、分组降级、去重缺失、truncated 静默)
|
2026-10-06 15:59:09 +08:00 |
|
AskaEth
|
78e99d9f4c
|
docs(contract): v0.79 —— 面板动作真可用 + 记忆审查/语音可见面 + 回合标识全覆盖
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
四批一并登记(DOC-3 按代码逐条核对,含 文件:行 证据;我复核版本行/唯一当前版本/端点面):
① PLG-2 动作真可用:SetExecutor 已删、生产执行器接线(wire_frontend.go:205 →
wire_plugin_actions.go:61-89);错误码按代码重写 —— action_not_implemented(501) 只剩
「已声明未登记处理器」,兜底是 502 action_failed;并纠正一处输入说法:网关层非法 JSON
回 bad_request(非 invalid_payload),两个码都登记
② CODE-TC-2 回合标识全覆盖:StartRoundWithTurnID 是唯一生产建图点;graph.id 对单路也追加
#{回合标识} ⇒ 契约明写「一律用响应里的 id,不要自拼」
③ L45:新增 B16 GET /admin/memories/reviews + B17 POST /admin/memories/{id}/revert(writeAuth)
+ U19 GET /api/v1/media/{name} 与消息 DTO voice(覆盖率按实际填充面写,帧/握手回放标注不带)
④ L2/SK-5 零契约变更(已在报告说明)
计数:writeAuth 14→16、总数 68→70。
⚠️ DOC-3 指出的易误用点(已在文档区分):turns[].turnId(=graph.id) 与 lanes[].turnId(=权威 turn-N) 不同源。
未确证:documents.SaveAudio / UpdateMessageVoice / RevertMerged 本体未逐行核(标「转述自 L45」);真机未跑。
|
2026-10-06 14:20:08 +08:00 |
|
AskaEth
|
1420e8aaa6
|
feat(gateway): D3 审查读侧/revert 端点 + 语音用户可见面(L45)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
(a) 记忆入库前审查的两条 admin 端点(主人判「有必要就做」):
GET /api/v1/admin/memories/reviews?limit= (留痕读侧,不含记忆正文)
POST /api/v1/admin/memories/{id}/revert (回滚软合并,落审计 memory.review.revert)
两条 writeAuth(裁定 DECISIONS #10:留痕属私有面,不给 viewer)
(b) 语音用户可见面:DTO voice(含服务端派生 url)+ GET /api/v1/media/{name}
(200/206/304/416/HEAD、Accept-Ranges、非法名/穿越统一 404 media_not_found)
+ documents.Store.SaveAudio(内容寻址、$DATA_DIR 0600)+ history voice 列读写与引用计数差动
缺口(如实):message_persisted/握手回放仍不带 voice(文件面外,需给 history.Message 加字段);
AMR 需一行 VoiceTranscoder 注入(DECISIONS #11 已排)。4 个变异自检(含一条自认的等价变异)。
|
2026-10-06 14:12:27 +08:00 |
|
AskaEth
|
4a937bd269
|
feat(flow): toolCalls 覆盖率追到全部编排回合(L3)—— 图带权威回合标识
- 新增 StartRoundWithTurnID(ctx, owner, text):从 ctx 取权威回合标识(与 chat_messages.turn_id
同值);Run 的唯一生产建图入口切到它;原 StartRound 语义逐字不变(1 行包装)
- 归属桶(并行按路分图)保持不变;落盘查询键 lane_turn_id 对单路也有值 ⇒ 消息面按等值查得到图
- 无权威标识时**保持缺席**(不拿桶里的路标识顶上:不许臆造)
- 不需要迁移 0024(0023 的列+索引已在位;老单路行标识根本没存过,回填=编造)
形状变化(已登记契约):graph.id 对单路也追加 #{回合标识}(web-7 → web-7#turn-…),
顺带修掉「重启后单路轮次 upsert 掉旧行」的隐患。3 个变异自检(退回老入口/无视 ctx/臆造回退)。
|
2026-10-06 14:12:25 +08:00 |
|
AskaEth
|
6475eb875d
|
feat(skills): 渐进披露接线(L2)—— 清单投影 + 命中才展开 + 工具面只收不放
- 清单只给 name+description(+when-to-use),单条 ≤1536 字符 + 全局条数上限,超限如实标 truncated
- 命中才把正文作为一条消息注入:跨回合保留、按内容指纹缓存不重复读盘、注入 ≤16 KiB 标 .truncated
- invocation 三态与清单逐格对齐(model-only 清单不含 description;user-only 清单有但模型不可调)
- 激活轮的工具面 = allowed-tools ∩ 安全闸 ∩ 注册表 再减 disallowed-tools(owner 也看不见未允许的工具)
- 激活状态进程内按会话(不落库);注入量已界化(压缩器估值未含,超我文件面)
裁定(DECISIONS #3/#4/#5):删掉 paths 启发式(只认显式挂载);多技能并集;收缩作用域=激活的那个回合。
|
2026-10-06 14:12:24 +08:00 |
|
AskaEth
|
2e1c3ed3fd
|
feat(plugins): 面板动作执行器接线 —— 动作真可用,不再 501 兜底(L1)
- 插件管理器加生产动作处理器登记面(RegisterActions);未登记处理器/未声明动作仍 404
- web-search 四个动作真读写真源 + 真发 HTTP 探针:plugin.listProviders/saveProvider/
testProvider/reauthProvider(配置落 $DATA_DIR/config/plugins/web-search.json,0600)
- 失败回结构化错误码(不含上游原文)+ 审计带 code 字段;501 文案改为「未登记处理器」
- 拆出 panelactions.go(动作索引推导/OptionsActionName/三闸门分发),panels.go 519→347 行
缺口(如实):面板保存后运行中的工具**不热重载**(下一片做);声明面缺 primary/fallback
(按 DECISIONS-2026-10-06 #1/#2 补)。
|
2026-10-06 14:12:23 +08:00 |
|
AskaEth
|
a150211468
|
docs(contract): v0.78 登记 16 路已落地的六批形状(含 5 处如实的覆盖率/未实现标注)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
六批:① 消息读取面 toolCalls[] 已实现(迁移 0023 按路键;**覆盖率只到真并行路**)
② 管理面 panels + 动作端点 + panels_changed 帧(**动作执行器无生产实现 ⇒ 现全回 501**)
③ 搜索 provider 可变源(config/plugins/web-search.json;不新增 env 键)
④ 账号上下线落事件 + channel_event 帧(**只覆盖账号状态这一路**)
⑤ iLink 账号三态(-14=被拒非过期;**accounts[] 每账号三态未做**)
⑥ 语音:**只登记落库面已实现**,用户可见面(DTO voice + /media/{name})仍标未实现
我复核并改掉一处 overclaim:v0.78 总述原写「六条全部已实现」与 ⑥ 自述矛盾 ⇒
改为「①~⑤ 已实现;⑥ 只到落库面」。
值得记的一笔:DOC-2 拒绝照抄我任务书里「把语音改成已实现」的要求,回代码核到三条机器证据
(无 /media/ 路由、DTO 无 voice 字段、转码器无注入点)⇒ 没实现的没写成可用。这是对的。
未确证(文档内已标):六批都没在运行中的 :10942 上验过(本批禁换产物/重启);
lane_turn_id == chat_messages.turn_id 仍是代码级推论。
|
2026-10-06 09:11:48 +08:00 |
|
AskaEth
|
9e63af9063
|
feat(admin): 前端可接入点 —— 折叠分组 + 动态插件页 + schema 渲染(PLG-3)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- sections.tsx 的分组升级为可折叠(CollapsibleGroup);新增 plugins 分组由
GET /api/v1/admin/panels 动态填充(navModel.ts 纯函数可单测)
- 插件页走动态段 /admin/plugin/<pluginId>/<panelId>,不进 router.ts 的静态白名单
- 把既有三段式(字段声明表 + 纯函数规则 + 渲染器,含「留空=不改」掩码语义)泛化成
schema → 控件(src/admin/schema/),复用它渲染插件表单/表格/事实面/日志
- 可测判据:新增插件页不得改动 sections.tsx / router.ts / AdminApp.tsx 的静态清单
- when 不满足 ⇒ 入口不出现;viewer 只看到只读区块
我的复跑:npx tsc --noEmit 通过;npx vite build 通过(3.67s);50 个前端脚本式测试全部
打印 checks passed(含本片新增 pluginData 90 / PluginPanel.render 55 / navModel 62 / schema values 40)。
|
2026-10-06 09:04:51 +08:00 |
|
AskaEth
|
ede00d9928
|
feat(voice): 语音消息落库 + 转码接入(切片 0020)
- 迁移 0020_chat_message_voice:按 design/24 §10 与契约 §7.2 已登记的 voice 形状建列/索引
- 语音回合进编排并落库;voice 引用与统计如实回填(转码/转写没成功就如实标未成功,不假装)
- 复用既有 internal/capability/transcode:非 wav(微信 AMR 等)先转码再送 ASR;失败可分类且不丢消息
⚠️ 部分完成(如实登记):生产端到端未成立(本片只到落库与转码接入),且**未经验真机**。
|
2026-10-06 09:04:06 +08:00 |
|
AskaEth
|
120d926cf8
|
feat(search): 搜索 provider 可变源 + 插件声明面板(PLG-4)
- 新增 $DATA_DIR/config/plugins/web-search.json(0600 + temp+rename,文件名 = 插件 id)
- 组合根改「先读可变源、缺失回落 .env 播种」;**不新增任何 env 键**(.env 已冻结)
- 多实例:每家 provider 独立 key/baseURL/启用态 + 「测试连通」探针
- 用 PLG-1 的声明库给出该面板的 adminPanels 声明;动作名交给 PLG-2 的通用动作端点分发
(本片自己不开路由)
⚠️ 本片自认越界:改了 cmd/cyrene/wire_web_search_test.go(既有测试,为适配 DataDir);
另有 design/28 的相关注册留给主会话。
|
2026-10-06 09:04:04 +08:00 |
|
AskaEth
|
2d21aa553e
|
feat(plugins): 插件管理器接线 —— 面板接入点快照 + 动作分发(PLG-2)
- GET /api/v1/admin/panels:按调用者角色过滤后的接入点快照(PLG-1 的 catalog 挂进插件管理器)
- POST /api/v1/admin/plugins/{id}/actions/{action}:**只接受该插件声明过的动作名**
(未声明 ⇒ 404);写动作 writeAuth + 落审计;插件只给动作名不给 URL ⇒ 不给插件开任意请求面
- 生命周期:install/uninstall/enable/disable 变化后**重算面板集合**并经进程内 bus 推 panels_changed
(前端可热更新;不新开端口)
契约 v0.78 登记由主会话随后统一落(本片报告给了可直接粘贴的契约段)。
|
2026-10-06 09:03:57 +08:00 |
|