Skip to content

feat(web): add personal Agent configuration and model entry - #103

Merged
EricWvi merged 12 commits into
ora-space:mainfrom
wanglongan587:feat/337-personal-agent-ui
Oct 21, 2026
Merged

EricWvi merged 12 commits into
ora-space:mainfrom
wanglongan587:feat/337-personal-agent-ui

Conversation

@wanglongan587

@wanglongan587 wanglongan587 commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

selected Agent -> My Configuration (members, lazy load)
  typed options + compatible personal model
  shared connection library -> inline metadata / write-only API key
  conflict -> retain draft -> explicit reconciliation / repair

OpenCode reuses the global default. Clearing options never deletes connections. Selected release kind comes from the frozen selection, not the newest catalog. Independent forms avoid nested HTML forms.

Base: #101 is merged. Merged with main a9c5f20fcbe9a1ff5f3c51218230a189a418c551 (after #81); the diff contains only the selected-release kind and personal configuration UI changes and adds no migration.

ADR: personal-agent-configurations remains approved. This PR implements its web editing portion; runtime adapter delivery and final ADR implementation remain separate.

Refs ora-space/circus#337

Evidence

  • Before: the plugin screen had no personal options/model entry.
    After: member entry, typed writes, CAS conflicts, explicit repair, clearing, inline connection creation and credential cache isolation are exercised through production clients and MSW.
  • npm run check: 142 files / 1160 tests passed; types, lint, coverage, module docs, documented exports, dead code, duplication and production build passed.
  • npm run check:modules -- --base upstream/main: module hygiene OK for the 4 modules changed against upstream main; both READMEs of agent-configurations and model-connections are updated with this change.
  • Changed-module gate passed against the P3 base. PostgreSQL catalog/selection integration test passed, including selected release kind.
  • Review follow-up (360cf30): the option baseline now advances in place from the write result plus a refetch instead of remounting the editor, so an unsaved default-model draft keeps its connection, model and CAS version across an option save or clear. OpenCode's credential controls follow the connection chosen in the global default draft (including one created inline) instead of the absent plugin connectionId, and cover an existing configured connection and a connection without a key. agent-configurations/dialog.test.tsx drives the production dialog for the save and clear scenarios; editor.test.tsx covers the default-connection, missing-key and follow-the-draft cases. Both new dialog tests and all three credential tests fail against 725f550 and pass on this head.
  • Review follow-up (1c74995, 2c76a57): a save adopts the follow-up read in place only when it is the revision that write confirmed, in the same selection and declaration context. A read showing another editor's later revision keeps the draft on the confirmed revision and opens the explicit comparison with saving disabled, so a retained draft can no longer be sent with a revision it was never compared against. dialog.test.tsx drives the production dialog through the reviewer's sequence (save → concurrent revision 3 → comparison → adopt server → save with revision 3); the later commits only format the change and keep useAgentEditor within the function-size limit.

Merge Danger

Door: two-way

No migration beyond the prerequisite P3 stack. Backend still enforces ownership, revisions, declaration identity and runtime readiness.

Blast Radius: personal-configuration

The editor advances its baseline only after successful writes that a follow-up read confirms, or after explicit user reconciliation, and only the option baseline moves: the independent default-model editing session and its CAS version survive. API keys use the existing write-only boundary and never enter configuration payloads or query/mutation variables.

Numeric Settings and declaration defaults retain their original JSON literals through controls, request serialization and the reconciliation view, including large integers and precise decimals. The P3 replay fix is inherited from main.

New head CI provides the post-merge frontend/backend gates.

Refs ora-space/circus#354

@HappyAuratus HappyAuratus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查版本:725f550a77a8f45cb482d5f065a700a513ffbed7;新增网页切片相对已审 P3 2d8e497 核对。发现两项可复现的 P2 问题,需修复后复审。

已检查成员入口的延迟读取、个人 API 与统一连接库、选项 revision/selectionVersion/fingerprint、显式修复和清除、数字原文序列化及凭据的 write-only 通路。当前 head 后端/前端 CI 均通过;本地运行 agent-configurations、model-connections 和 plugins 相关 6 文件 / 41 测试通过,git diff --check 通过。额外通过生产 AgentConfigurationDialog、完整 provider 和 MSW HTTP 边界运行两项复现,均确认失败:已有 OpenCode 默认连接没有 API Key 控件;修改默认连接草稿后保存插件选项,草稿回到服务器原选择。现有测试主要直接挂载 Editor,未覆盖该对话框的保存后重建与 OpenCode 全局默认分支。

本轮未重复完整后端 PostgreSQL/race gate,也未执行真实浏览器或模型运行验收;P3 沿用 cloud#101 同 SHA 已有独立审查及 CI 证据。P4 真实执行仍由后续事项承接。合并顺序仍需先 cloud#101。

{editor.confirmClear && <ClearAgentOptions editor={editor} />}
<AgentConnectionTools
context={props.context}
selected={connections.data?.find((connection) => connection.id === draft.connectionId)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 为 OpenCode 的全局默认连接接入凭据入口。OpenCode 配置只返回 modelDefault,不保存 connectionId,所以这里按 draft.connectionId 查找会得到 undefined,AgentConnectionTools 因而不渲染 CredentialForm。打开已有默认连接的 OpenCode「我的配置」即可复现 API Key 控件缺失,且默认模型表单内切换连接也不会更新此目标。请将凭据管理的目标显式关联到全局默认编辑选择,同时保持选项 payload 不复制全局模型引用;补已有连接、未配置 Key 和切换选择的对话框测试。

key={editor}
scope={scope}
context={query.data}
onSaved={() => setEditor((current) => current + 1)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 保存选项时保留独立的默认模型草稿。此处递增 key 会卸载整个 AgentConfigurationEditor,包括独立的 ModelDefaultForm。复现:打开 OpenCode,默认连接原为 A;在默认表单选 B 但尚未保存默认模型;点击「保存我的配置」,成功后默认连接无提示回到 A。清除插件选项也经过同一 onSaved 路径。请只重置已保存的选项基线,保留默认选择草稿及其原有 CAS version;补从生产 Dialog 进入的保存与清除回归。

@wanglongan587

Copy link
Copy Markdown
Collaborator Author

已按审查意见修复两项 P2,新 head 360cf30(在 725f550 之后追加 4 个 commit):

  1. OpenCode 全局默认连接接入凭据表单(65ebef2):ModelDefaultForm 新增 onConnectionChange,只回传默认草稿当前指向的连接,不复制全局默认资源;编辑会话用 useCredentialTarget 解析凭据目标,因此 OpenCode 不再按插件配置里不存在的 connectionId 查找,已有默认连接可以查看「API Key 已配置」并清除,缺 Key 时直接显示写入控件;在默认表单里更换连接会同步切换凭据目标,内联新建的连接也会成为凭据目标(配置 Key 后即可在默认连接中选择)。凭据区显示所属连接名,避免看不出改的是哪一条连接。
  2. 保存/清除只推进选项基线(0b19d02):对话框不再更换编辑器的 key,保存或清除成功后重新读取最新上下文并交回编辑会话;编辑会话先用写响应推进 revision,再以保留当前草稿值的方式采用最新基线(清除时回落到声明默认值)。ModelDefaultForm 保持挂载,未保存的默认连接/模型草稿与其 CAS version 一起保留,保存默认模型 仍按编辑开始时读到的 version 提交。

顺带(e0e17c8):核对面板按响应数值原文显示,避免高精度小数在比较视图里被截断;文档(360cf30)同步了两个模块的中英文 README。

验证:新增 5 个测试(editor.test.tsx 3 个凭据目标、dialog.test.tsx 2 个保存/清除对话框级回归)。相关模块 46 测试通过;完整 npm run check 142 文件 / 1160 测试通过,check:modules -- --base upstream/main 通过,git diff --check 通过。把 725f550 的源码临时还原后复跑新测试,5 个新增用例全部失败(默认草稿回到服务器原值、OpenCode 无凭据入口),确认覆盖的就是这两项问题;未将 jsdom 测试当作浏览器验收,也未重复完整后端 PG/race gate 或实际模型执行。

合并顺序仍需先 #101。P4 的真实运行能力与发布验收仍由 #336 承接,ADR 保持 approved。麻烦复审这个 head。

@HappyAuratus HappyAuratus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 commit 02eed4391da41e48e4947db5efbe9717c71a6de5。此前两项 P2(OpenCode 默认连接凭据入口、插件选项保存/清除卸载独立默认模型草稿)已有修复,新增后台刷新凭据基线的回归也通过。本轮发现一项新的 P2:保存后的 refetch 会把另一编辑器的 revision 静默应用到旧草稿,使下次保存覆盖未核对的并发修改,详见行内意见。

证据:当前 SHA 后端 check 和 frontend CI 均通过;本地 agent-configurations、model-connections、plugins 共 7 文件的原有 47 个测试全部通过。额外在生产 AgentConfigurationDialog / 生成客户端 / MSW 边界加入并发复现:第一次 PUT 返回 revision 2,随后 GET 返回另一编辑器的 revision 3;再次点击保存,实际请求为 revision 3、settings.style='initial my edit',而非保持写响应 revision 2 或要求显式核对。新增断言失败,原有用例仍全部通过。临时复现测试已移除,审查 worktree 干净,git diff --check 通过。

未执行真实浏览器、实际模型运行或重复完整后端 PG/race 门禁,不把 jsdom 当作浏览器验收。#337 已关闭并移交,后续结论按交接记录到 circus#354。

setDraft((current) => ({ ...current, revision: written.revision, requiresRepair: false }))
try {
const latest = await onSaved()
setDraft((current) => agentConfigurationDraft(latest, written.cleared ? undefined : current))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 不要把 refetch 读到的并发 revision 静默拼到旧草稿。agentConfigurationDraft(latest, current) 保留当前 values,却把 revision、selectionVersion 和声明基线改成 latest:本次写返回 r2 后,另一编辑器抢先写入 r3,随后的刷新读到 r3,本页面仍显示旧草稿,但下次 PUT 已带 r3,可直接覆盖对方修改,不再触发 revision_conflict。生产对话框/MSW 复现已确认第二次请求为 {revision:3, settings:{style:'initial my edit', ...}}。只可自动采纳本次写入确实确认的基线;读取结果若超出该写响应或发行/声明上下文已变,应保留草稿并要求显式核对。请补写入成功与后续读取之间发生并发修改的对话框级测试。

A save advanced the option baseline to whatever revision the follow-up read returned, so a retained draft could be paired with another editor's later revision and overwrite it on the next save. Adopt the read in place only when it is the confirmed revision in the same release context; otherwise keep the draft and require explicit reconciliation.
Lifting the write confirmation and setting update into module helpers keeps useAgentEditor within the 100-line function limit without changing behavior.

@HappyAuratus HappyAuratus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 commit 2c76a574735f2fc80345d0d4c9f709a5dfb0e864:上一轮 P2 并发覆盖已修复,本轮未发现新的阻塞问题,Approve。

adoptWrite 只在后续读取与写响应确认的 revision、编辑时 selectionVersion、声明 fingerprint 全部一致时原地采用;其他情况保留草稿并进入显式核对,不能自动给旧草稿配上新 revision。已回查此前 OpenCode 默认连接凭据入口、选项保存/清除保留独立默认模型草稿与 CAS version 的修复;本次 merge 后选定发行 kind 的后端、OpenAPI、生成客户端和入口保持一致。

本地证据:生产 AgentConfigurationDialog、生成客户端、MSW 边界的相关正式测试 6 文件 / 42 测试通过;另外临时加入“清除后读到并发写入”和“revision 与写响应相同但 selectionVersion 改变”两项对话框级验证,与正式测试合跑 7 文件 / 44 测试通过。临时还原修复前 83a398f 的 editor-state.ts 后,正式并发回归与上述两项验证均因未出现核对面板而失败,另外两个正式对话框测试通过;恢复当前 head 后 44 项全部通过。临时测试已移除,工作区干净,git diff --check 通过。

依据:cloud PR 当前 head(已重新 fetch 并在提交 review 前核对);specs upstream/main 5a608567b86c2ca1df38e9b15bafdc948692bf9f 的 personal-agent-configurations ADR 仍为 approved,本 PR 仅交付网页部分,其余运行时与真实验收由 circus#354 承接。

范围限制:本轮未执行真实浏览器、真实模型调用或完整 PostgreSQL/race 门禁;Code Review CI 连接要求重新连接 GitHub,本轮未独立读取 CI 状态,作者汇报的 CI 通过不作为本地复测结论。此 Approve 仅针对 cloud#103 当前 SHA,不代表 #354 的其他 PR 或发布验收已完成。

@EricWvi
EricWvi merged commit 4d35aad into ora-space:main Oct 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants