From 868ab54be6575ea6bd170d2ece7b7c8d4f6c0007 Mon Sep 17 00:00:00 2001 From: brother7 <7brother7@gmail.com> Date: Tue, 15 Sep 2026 14:50:06 +0800 Subject: [PATCH] fix(agents): make editor settings peer tabs --- .../20260915-agent-editor-tabs-8c46f6f5.md | 51 +++++++++++++++++ README.md | 2 +- src/pages/CloudAgents/DraftEditor.tsx | 31 ++++++---- tests/e2e/cloud-agents.spec.ts | 41 +++++++++++++- tests/unit/cloud-agents-page.test.tsx | 56 +++++++++++++++++-- 5 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 .project-docs/30-worklog/tasks/20260915-agent-editor-tabs-8c46f6f5.md diff --git a/.project-docs/30-worklog/tasks/20260915-agent-editor-tabs-8c46f6f5.md b/.project-docs/30-worklog/tasks/20260915-agent-editor-tabs-8c46f6f5.md new file mode 100644 index 0000000..02e53cb --- /dev/null +++ b/.project-docs/30-worklog/tasks/20260915-agent-editor-tabs-8c46f6f5.md @@ -0,0 +1,51 @@ +# Task: 核对我的要求与高级设置的切换逻辑 + +## Identity + +- Task ID: 20260915-agent-editor-tabs-8c46f6f5 +- Mode: Feature +- Branch: codex/20260915-agent-editor-tabs-8c46f6f5-agent-editor-tabs +- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260915-agent-editor-tabs-8c46f6f5 +- Base commit: 80e52496d2696c3b579c911ee7c07f9588b368a6 +- Owner: codex +- Status: Ready for Integration + +## Scope + +- Implement the user-approved peer “我的要求” / “高级设置” tabs in the personal cloud Agent editor. +- Own DraftEditor, focused unit/Electron regressions, README and this task record. No Main, API, persistence or billing changes. + +## Intent And Constraints + +- Source inspection established that the former advanced control only revealed category navigation and reset the content to instructions. The user accepted replacing it with a peer tab. +- Concurrent Task Gate passed through bundled check/start/status, first isolating from occupied main, then resuming this same task. Feature identity, absolute worktree, branch and recorded base match the ownership registry. No subagents were created. +- Planning Gate passed. Read the entry instructions, active record, memory index, positioning, integrated current state, decision index, system overview, planning gate, business rules, success criteria, personal cloud Agent ADR and guided UX source record. +- Project Context Loaded: Main-owned Electron product; integrated focus includes guided Agent requirements and knowledge processing. This task changes only local editor presentation. Relevant files are DraftEditor.tsx, cloud-agents-page.test.tsx, cloud-agents.spec.ts and README.md. No additional evidence, reflection or commitment dependency applies. +- Peer inspection used registered task records only. Guided UX and knowledge changes overlap in domain but are integrated; remaining channel diagnosis and historical reviews do not own this tab decision. Historical placeholder records and template positioning remain unknown coordination state, with no concrete dependency on this implementation. +- Preserve basic requirements as the default, saved/preview/published separation, unfinished requirements/resources/knowledge/budget input, independent budget saving and current preview. Use the existing light-system Tabs component. +- The user's approval supersedes the prior advanced-disclosure interaction for this scope; accepted canonical memory remains read-only in feature mode. + +## Outcome + +- Existing Radix-based Tabs provide peer selection, associated panel semantics, keyboard navigation and a grouped, clearly highlighted selection. Advanced settings initially opens capabilities; capability/knowledge/limit selection is remembered across top-level tab switches. Selecting the active tab does not collapse or reset it. +- One shared panel and ConfigurationFields instance remain mounted. Switching changes the visible category without discarding resource search, knowledge creation, independent budget edits, basic requirements or preview input; switching itself does not save or send. +- Changing the top-level tab resets the shared form scroll to the top so the previous category's scroll offset does not hide the new form heading. Category selection and entered values still remain. +- README describes the final peer-tab behavior. Focused unit and Electron specs cover selection, defaults, repeated selection, remembered categories, hidden navigation, keyboard movement, scroll reset, preserved inputs and existing save/preview flows. + +## Verification + +- pnpm 10.33.4 matches packageManager; frozen-lockfile install passed without dependency changes. +- Typecheck and scoped ESLint passed; production build:vite passed for Renderer, Main, Preload and utility. Repeated these checks after adding the scroll reset; the final Electron run also passed (1 test, 24.7 seconds), including the explicit real-scroll reset assertions. +- Four focused unit files: 46/47 initially passed; the new test used a string expectation for a numeric input, corrected to numeric 12.5. The affected page file then passed all 19 tests. Combined final focused coverage: 47 tests (19 page + 28 unchanged guidance/workflows/management). +- First Electron cloud-agents.spec.ts run passed with the real desktop shell and test-owned Host API fixture, including arrow-key switching, category memory and preservation of knowledge/budget input. Existing wide/narrow windows, 125%/150% zoom, save/retrial and independent costs/schedules paths passed. +- Visually inspected the advanced and requirements tab screenshots. Both use the existing light palette and grouped selection; the advanced view hides the requirements form. +- Working and committed changes were inspected from the recorded base; only the four intended product/document/test paths and this task record changed. Bundled documentation drift and whitespace checks passed. +- No full repository suite or live cloud/provider requests were needed for this local navigation change. Production deployment, installation and main integration are outside this task's result. + +## Follow-ups + +- Integrate this task branch through the normal Integration Gate; rebuild/install the client for the currently installed application to receive the change. + +## Promotion Candidates + +- Target: ADR-2026-09-11-personal-cloud-agents.md Desktop Workspace / Guided First Helper and canonical Agent UI description. Proposal: replace “advanced configuration expands below requirements” with two peer editor tabs; preserve basic-default guidance, advanced category memory, unsaved input and preview separation. Evidence: explicit user acceptance, source implementation, focused unit and Electron regressions. Future impact: later UI work should preserve this navigation model. Semantic conflict: replaces the earlier disclosure description only; Main/cloud/data semantics stay unchanged. Human confirmation: interaction change already approved, no additional product decision needed during normal integration. diff --git a/README.md b/README.md index 0857386..58eac40 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Makelore 是一个面向软件、视觉创作、智能机器人与个人云智能体的 AI 桌面工作台。当前版本为 `2.0.0`,源码提供四个模块入口;云智能体需配套配置 WS/Yuxi 服务。模块入口页按 Agents、Code、Canvas、Robot 排列,统一采用横向插画卡片;Agents 标语为“打造你想象中的AI助手”。工作区左上角入口点击后返回模块入口页: - `Makelore Code|AI 编程`:管理本地项目、项目智能体、对话、文件上下文、代码变更和运行时。 -- `Makelore Agents|AI 智能体`:配置个人云智能体并试聊,发布后正式对话、按账号分享或创建应用 API Key。支持流式回复、审批、排队请求、附件与产物、自动任务和活动历史;重新进入时恢复最近智能体与对话,未确认操作可按原输入重试。聊天可提出日程建议,由创建者核对能力、时间和费用后启用。知识库上传、替换及导入本人会话附件后自动解析并建立索引;文档卡片区分排队、解析、索引、可用和失败,持续刷新已加载文档,失败可原地重试;零文本内容不会显示为可用,新文档可用后才移除被替换的旧文档。支持删除知识内容;个人 MCP 凭据、Skills、子智能体可自助管理。支持智能体和会话归档、发布版本比较及恢复为草稿。除知识库 embedding 向量化外,模型调用(包括知识处理触发的对话模型调用)仍按原规则由创建者个人词元点数支付,可按智能体设置每次任务和每日上限,费用按时间、来源、应用分页统计;embedding 向量化由平台承担,不计入用户用量、词元点数或智能体费用上限;分享/API 调用者保有自己的内容空间。Main 管理云会话和本机文件,Renderer 通过 Host API 操作。配套服务接入见 [Yuxi MakeLore 说明](https://xerrors.github.io/Yuxi/advanced/makelore-agents.html)。 编辑采用全高桌面分栏,支持拖动调整与展开、独立滚动、小窗口配置/试用切换。首次创建按选用途、说要求、试一试引导,提供科学问答、故事、英语和笔记整理起点;回答方式可多选,特别要求直接编辑,仍以草稿的 system_prompt 保存。新助手预选云端目录的第一个可用模型并明确显示,可自行更换;已有助手不自动换模型。能力、知识与限制折叠到高级设置。草稿明确保存(Ctrl/⌘+S),保存与切换页面保留当前试用及未发送文字;“保存并重新试用”使用最新保存的要求,保留上次试用供对比,并可复用上次问题,不自动发送。示例问题仅填入输入框;有运行、排队、审批或未确认操作时先处理当前试用。工具确认先展示实际操作说明与参数,完整技术详情可展开。确认“开始使用”会创建仅自己可用的发布版本并进入独立对话,分享与应用仍单独开启。费用上限在限制中独立保存。Enter 发送、Shift+Enter 换行,F6 切换面板焦点、Esc 恢复分栏。 +- `Makelore Agents|AI 智能体`:配置个人云智能体并试聊,发布后正式对话、按账号分享或创建应用 API Key。支持流式回复、审批、排队请求、附件与产物、自动任务和活动历史;重新进入时恢复最近智能体与对话,未确认操作可按原输入重试。聊天可提出日程建议,由创建者核对能力、时间和费用后启用。知识库上传、替换及导入本人会话附件后自动解析并建立索引;文档卡片区分排队、解析、索引、可用和失败,持续刷新已加载文档,失败可原地重试;零文本内容不会显示为可用,新文档可用后才移除被替换的旧文档。支持删除知识内容;个人 MCP 凭据、Skills、子智能体可自助管理。支持智能体和会话归档、发布版本比较及恢复为草稿。除知识库 embedding 向量化外,模型调用(包括知识处理触发的对话模型调用)仍按原规则由创建者个人词元点数支付,可按智能体设置每次任务和每日上限,费用按时间、来源、应用分页统计;embedding 向量化由平台承担,不计入用户用量、词元点数或智能体费用上限;分享/API 调用者保有自己的内容空间。Main 管理云会话和本机文件,Renderer 通过 Host API 操作。配套服务接入见 [Yuxi MakeLore 说明](https://xerrors.github.io/Yuxi/advanced/makelore-agents.html)。 编辑采用全高桌面分栏,支持拖动调整与展开、独立滚动、小窗口配置/试用切换。首次创建按选用途、说要求、试一试引导,提供科学问答、故事、英语和笔记整理起点;回答方式可多选,特别要求直接编辑,仍以草稿的 system_prompt 保存。新助手预选云端目录的第一个可用模型并明确显示,可自行更换;已有助手不自动换模型。编辑区以“我的要求”和“高级设置”两个 Tab 切换,默认显示基础要求;高级设置包含能力、知识与限制,返回时保留上次分类,切换保留未保存的输入及当前试用。草稿明确保存(Ctrl/⌘+S),保存与切换页面保留当前试用及未发送文字;“保存并重新试用”使用最新保存的要求,保留上次试用供对比,并可复用上次问题,不自动发送。示例问题仅填入输入框;有运行、排队、审批或未确认操作时先处理当前试用。工具确认先展示实际操作说明与参数,完整技术详情可展开。确认“开始使用”会创建仅自己可用的发布版本并进入独立对话,分享与应用仍单独开启。费用上限在限制中独立保存。Enter 发送、Shift+Enter 换行,F6 切换面板焦点、Esc 恢复分栏。 云知识库的 embedding 模型只由平台管理员在 Yuxi 后台维护:在「智能体管理 → 模型供应商」启用供应商,按供应商要求填写有效的服务地址和 API Key,添加并启用 embedding 模型并填写实际向量维度;embedding 向量化费用由平台承担,不计入用户用量、词元点数或智能体费用上限;one-api 不参与 embedding 配置,Works Square 只负责其他应计费模型调用的创建者词元点数账本。客户端区分目录加载中、加载失败与无可用模型,空状态提供管理员配置说明;「刷新知识库与模型」保留未提交名称,未确认的创建请求沿用原操作身份。 diff --git a/src/pages/CloudAgents/DraftEditor.tsx b/src/pages/CloudAgents/DraftEditor.tsx index 5ccaf33..74fb43c 100644 --- a/src/pages/CloudAgents/DraftEditor.tsx +++ b/src/pages/CloudAgents/DraftEditor.tsx @@ -4,6 +4,7 @@ import { ArrowLeft, Check, Loader2, Save } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@/components/ui/dialog'; import { cloudAgentsApi } from '@/lib/cloud-agents-api'; import { EMPTY_CLOUD_CONFIGURATION, type CloudAgentDraft, type CloudRecent, type CloudThread, type CloudScheduleProposal } from '../../../shared/cloud-agents'; @@ -18,7 +19,7 @@ import { AgentRequirements } from './AgentRequirements'; import { agentExamples } from './agent-guidance'; type Tab = 'configuration' | 'chat' | 'tasks' | 'access'; -type Category = 'instructions' | 'capabilities' | 'knowledge' | 'limits'; +type AdvancedCategory = 'capabilities' | 'knowledge' | 'limits'; const hasDraftChanges = (draft: CloudAgentDraft, saved: CloudAgentDraft) => draft.name !== saved.name || draft.purpose !== saved.purpose || draft.system_prompt !== saved.system_prompt || JSON.stringify(draft.configuration) !== JSON.stringify(saved.configuration); const errorMessage = (error: unknown) => error instanceof Error ? error.message : '暂时无法完成操作'; @@ -29,7 +30,8 @@ export function DraftEditor({ initial, recent, onBack, onSaved, startingPrompt } }) { const [saved, setSaved] = useState(initial); const [draft, setDraft] = useState(() => startingPrompt === undefined ? initial : { ...initial, system_prompt: startingPrompt }); - const [advanced, setAdvanced] = useState(false); + const [editorTab, setEditorTab] = useState('instructions'); + const [advancedCategory, setAdvancedCategory] = useState('capabilities'); const [previewActivation, setPreviewActivation] = useState(0); const [previewCreated, setPreviewCreated] = useState(Boolean(initial.configuration?.model)); const [remote, setRemote] = useState(null); @@ -39,7 +41,7 @@ export function DraftEditor({ initial, recent, onBack, onSaved, startingPrompt } const initialTab = recent?.mode === 'preview' ? 'configuration' : initial.published_version ? 'chat' : 'configuration'; const [tab, setTab] = useState(initialTab); const [visited, setVisited] = useState>(() => new Set([initialTab])); - const [category, setCategory] = useState('instructions'); + const category = editorTab === 'instructions' ? 'instructions' : advancedCategory; const [openedThread, setOpenedThread] = useState(); const [conversationSource, setConversationSource] = useState<'desktop' | 'wechat'>('desktop'); const [wechatVisited, setWechatVisited] = useState(false); @@ -49,6 +51,7 @@ export function DraftEditor({ initial, recent, onBack, onSaved, startingPrompt } const hasPending = pending.hasPending || formalPending.hasPending; const alive = useRef(true); const saving = useRef(false); + const configurationScroll = useRef(null); const dirty = hasDraftChanges(draft, saved); const canSave = dirty && !busy && !remote && Boolean(draft.name.trim() && draft.purpose.trim()); const navigate = (next: Tab) => { setVisited(current => new Set([...current, next])); setTab(next); }; @@ -128,14 +131,21 @@ export function DraftEditor({ initial, recent, onBack, onSaved, startingPrompt } }