Wmc/dev 0518#3294
Conversation
Develop
Enhance A2A protocol support and fix various bugs
…nd improve agent execution flow (#2839) * 修复调用多模态工具导致502Bad Gateway问题 * Bugfix: Add tooltip to tab labels in ToolManagement and SkillManagement Made-with: Cursor * Feat: Add presigned URL support for external MCP tool file access and improve agent execution flow * 使用已有的types,而非重复定义 * 针对用户上传的文件进行去重处理,限制文件最大个数 * Update frontend/types/chat.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update frontend/types/chat.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * 新增测试用例 * 修复单元测试 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* openspec初始化 * oauth spec开发结果 * oauth 单元测试 * oauth 重定向修复 * oauth 重定向修复 * oauth 重定向修复 * oauth 抽象实现 * gde provider * gde provider * enhance unlink_account logic to check for password authentication before unlinking * refactor OAuthAccountsSection to load enabled providers and improve account unlinking logic * add OAuth linking functionality with state management and error handling * refactor OAuth account deletion logic to use direct deletion and update related tests * update GDE OAuth configuration to use environment variables for URLs and client IDs * add SSL verification configuration for OAuth requests and update context handling * remove hardcoded OAuth credentials from const.py and update .env.example * remove avatar_url references from user info handling and update email fallback logic * refactor user identity handling in OAuth account unlinking logic * update OAuthAccountsSection to simplify display logic for linked accounts * refactor OAuth user binding logic to check for existing accounts before creating new users * 删除冗余文件 * 删除冗余文件 * add user OAuth account table and update trigger for third-party logins * 修复单元测试 * 删除冗余代码 * k8s同步oauth配置 * 软删除时需添加delete_flag="Y"的筛选条件 * 用户删除的时候将oauth表中delete_flag设置为Y * 优化import * 移除无用的rebind_oauth_account函数调用,并在用户已绑定其他账户时抛出OAuthLinkError * clean code * 补充ut * 补充单元测试
…w of unsuploaded files (#2840) * Implementing virtual scrolling with react-virtuoso and support automatic line wrapping * merge unuploaded file preview logic * bug fix
* 修复调用多模态工具导致502Bad Gateway问题 * Bugfix: Add tooltip to tab labels in ToolManagement and SkillManagement Made-with: Cursor * Bugfix: fix excessive execution time of test_a2a_client_servic
…aming handler (#2842) - Introduced a local variable to manage title generation state, preventing duplicate calls during new conversations. - Updated the title generation process to use a captured user message directly, enhancing reliability and performance.
…rchTool (#2781) * ✨ Add display name to index name mapping for KnowledgeBaseSearchTool - Introduced `get_knowledge_name_map_by_index_names` function to retrieve a mapping of index names to their corresponding display names. - Updated `create_agent_config` and `create_tool_config_list` to utilize the new mapping for generating user-friendly summaries. - Enhanced `KnowledgeBaseSearchTool` to support conversion from display names to index names during queries. - Added tests to verify the functionality of the new mapping and its integration within the tool configuration process. * ✨ Add display name to index name mapping for KnowledgeBaseSearchTool
* ✨ Feat: Implement max steps reached handling in chat system - Added support for processing and displaying max steps reached events in the chat stream. - Introduced new message type `MAX_STEPS_REACHED` in chatConfig. - Enhanced chatStreamHandler and taskWindow to manage max steps notifications and content. - Updated localization files for English and Chinese to include relevant messages. - Modified chat message extraction logic to handle historical max steps data. * ✨ Feat: Implement max steps reached handling in chat system - Added support for processing and displaying max steps reached events in the chat stream. - Introduced new message type `MAX_STEPS_REACHED` in chatConfig. - Enhanced chatStreamHandler and taskWindow to manage max steps notifications and content. - Updated localization files for English and Chinese to include relevant messages. - Modified chat message extraction logic to handle historical max steps data. * 🐛 Bugfix: Implement max steps reached handling in chat system * 🐛 Bugfix: Implement max steps reached handling in chat system * 🐛 Bugfix: Implement max steps reached handling in chat system
* feat:add model-monitoring * fix: mask base_url in connectivity logs to resolve CodeQL clear-text secret alert * fix: resolve CI test failures, remove dead code, and fix permission case mismatch - Remove _filter_by_rbac function and unused imports from monitoring_app - Fix OpenAIModel.__call__ to accept injected _token_tracker - Fix LLMTokenTracker to no-op when monitoring is disabled - Fix OpenAIModel.__init__ to handle missing model_id attribute - Fix monitor_llm_call decorator IndexError on bare functions - Fix permission case mismatch (MODEL:CREATE -> model:create) - Mask base_url in model health connectivity logs (CodeQL) - Update test assertions for display_name parameter - Merge SQL migrations into single file - Add time range selector (24h/7d/30d) to monitoring UI Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: resolve SonarCloud quality gate failures and CI test errors - Add missing record_model_call import in embedding_model.py (NameError fix) - Update test assertions to include display_name parameter - Use Annotated type hints for FastAPI DI, replace unused variables - Remove unused error variable in _MonitoredClient.create - Extract renderTextModelMetric helper in ModelList.tsx to eliminate negated conditions and nested ternaries - Replace unused loop index and empty pass blocks in tests * fix: remove explicit return False in __exit__ to resolve SonarCloud R635 * fix: use relative import for record_model_call to fix CI ModuleNotFoundError * fix: use absolute import in embedding_model and fix test import method - Revert embedding_model.py to absolute import (compatible with installed package) - Replace importlib.util direct file loading in test with normal package import * fix: use absolute import for record_model_call in embedding_model.py * fix: update test patch targets from embedding_model_under_test to nexent.core.models.embedding_model * fix: use relative import for record_model_call (consistent with openai_llm.py) * test: add monitoring integration tests to improve Codecov diff coverage Covers _MonitoredClient wrapping, display_name context var, token tracker, set_monitoring_context/operation calls, copy_context propagation, and monitoring_app error handling paths. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * test: add monitoring integration tests for embedding, agent, conversation and tool services Add 8 tests covering record_model_call and set_monitoring_context/operation instrumentation in 4 production files to meet Codecov diff coverage target. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: replace deprecated codecov Python uploader with official GitHub Action The old pip install codecov CLI is deprecated and silently fails on ARM runners. Replace the architecture-conditional dual-uploader approach with a single codecov/codecov-action@v4 step that works on all platforms. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… part2 (#2813) * ✨ Add display name to index name mapping for KnowledgeBaseSearchTool - Introduced `get_knowledge_name_map_by_index_names` function to retrieve a mapping of index names to their corresponding display names. - Updated `create_agent_config` and `create_tool_config_list` to utilize the new mapping for generating user-friendly summaries. - Enhanced `KnowledgeBaseSearchTool` to support conversion from display names to index names during queries. - Added tests to verify the functionality of the new mapping and its integration within the tool configuration process. * ✨ Enhance prompt generation with knowledge base display names - Added `knowledge_base_display_names` to the `GeneratePromptRequest` model to allow frontend-configured names for knowledge bases. - Updated backend functions to utilize these display names, improving few-shot example generation without requiring database lookups. - Modified frontend components to capture and pass knowledge base display names during prompt generation. - Enhanced tests to cover the new functionality and ensure proper integration of knowledge base display names in the prompt generation process. * ✨ Enhance prompt generation with knowledge base display names part2 * ✨ Add display name to index name mapping for KnowledgeBaseSearchTool * 🐛 Bugfix: Enhance prompt generation with knowledge base display names part2
…ype (#2868) * Introduced kbSelectionConfig to manage knowledge base selection parameters. * Updated logic to determine parameter names for different tool types. * Merged KB selection configuration into final tool parameters to streamline processing.
* 🐛 Bugfix: skill deletion failed occasionally * ♻️ Simplify how run_skill_script() receives additional parameters * 🧪 Add test files * 🧪 Fix test files * ♻️ Update system prompt to better support models with lower parameters * ♻️ Update system prompt to better support models with lower parameters * ♻️ Remove unnecessary rely on re to reduce the risk of DoS * ♻️ Remove unnecessary rely on re to reduce the risk of DoS * ✨ Support multi-turn NL2Skill * ✨ Support complicated skill generation * ✨ Support complicated skill generation * ✨ Support official skills pre-installation * ✨ Support official skills pre-installation * 🧪 Add test files * 🧪 Add test files * ♻️ Refactor skill_app, skillService and content_classifier_utils according to sonar
…s logging (#2875) * docs: Add design spec for doc-qa-agent MVP Defines architecture, data flow, file layout, and acceptance criteria for a standalone document Q&A agent built on the Nexent SDK. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * agent context * context management for agent * agent context * Added get_or_create_context_manager, clear_conversation_context_manager, reference counting in register_agent_run/unregister_agent_run * Modified prepare_agent_run to mount CM, and stop_agent_tasks analysis (though we didn't modify it, we analyzed it) * Added cleanup in delete_conversation_service * Added context_manager field to AgentRunInfo * Modified agent_run_thread to reuse CM * add compress_if_needed and quantitative collection * reuse context_manager; extract and log token usage per step * add TokenUsage for message to facilitate displaying token usage * main code for context compression * add test multi run to understand previous run and current run * token usage metrics log * using sdk to conduct end-to-end test for anget_context.py * reusable functions for testing agent_context * fix bug: reuse cache and calc effective tokens * from utils.token_estimation import msg_token_count * estimate token * Add test_agent_context unit tests * update agent_context * ♻️ Refactor agent_context module for code quality compliance - Split agent_context.py into smaller modules: summary_cache.py, summary_config.py - Convert all Chinese comments/docstrings to English (per .cursor/rules/english_comments.mdc) - Add module-level docstrings for public API documentation - Update __init__.py exports to include new module classes - Convert test files' Chinese comments to English for compliance - Default summary prompts to English with proper documentation * 🔄 Merge feature/agent_context improvements into refactored codebase - Add context_manager_config field to AgentConfig - Create ContextManagerConfig in create_agent_info - Enhanced step metrics with compression ratio and cache hit tracking - Add _render_steps_with_truncation for fallback truncation - Add cache hit logging (previous_cache_hit, current_cache_hit, stable_bypass) - Add cache_types to compression stats output - Simplify estimate_tokens to flat message list approach - Remove auto-clear ContextManager logic (keeps cache valid) - Stop tracking test scripts (keep locally) * 🧪 Fix test assertions to align with feature branch standards - Fix TestM13StepLocalLogCleared: cache hit is recorded in _step_local_log (count_after_second should be 1, not 0) - Update summary_json_schema: chars -> words for clearer units * 🔄 Merge feature/token_indicator: Add token usage indicator with real-time context metrics - Add TokenUsageIndicator component with circular progress visualization - Emit TOKEN_COUNT messages via observer for real-time frontend updates - Include step_number, input/output tokens, estimated context, and threshold - Preserve context manager and metrics logging from refactor/agent_context Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Enhance agent context management with token compression logging and dynamic token threshold * fix: improve token usage tracking with stream_options and fallback estimation - Add stream_options to request usage info from streaming API - Handle empty choices in streaming chunks (usage-only chunks) - Add fallback token estimation when API doesn't return usage - Add None handling in msg_token_count and _extract_text_from_chat_message * chore: add *.log to gitignore to exclude runtime log files * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: make ContextManagerConfig.enabled configurable per agent and refactor for cognitive complexity - Add enable_context_manager field to AgentInfo database model (default False) - Update create_agent_config to read setting from agent_info instead of hardcoded True - Add field to API request models (backend and frontend) - Add database migration for new column - Refactor _trim_actions_to_budget to reduce cognitive complexity (19 -> 15) - Refactor _render_steps_with_truncation to reduce cognitive complexity (23 -> 15) * fix: pin greenlet<3.5.0 for aarch64 Linux compatibility greenlet 3.5.0 lacks wheels for ARM64 Linux (aarch64), causing CI failures. Pin to <3.5.0 to ensure compatible version (3.4.0) is resolved. * fix: update test mocks to support agent_context refactor - Add enable_context_manager attribute to MockAgent in test_agent_db.py - Add AgentRunInfo, agent_context, and agent_run_manager stubs in test_conversation_management_service.py - Add nexent.core.agents.agent_context stub in test_create_agent_info.py - Add smolagents.memory stub with AgentMemory/MemoryStep in SDK model tests - Update TokenCountTransformer tests to match new passthrough behavior - Update test_create_agent_config assertions to include context_manager_config parameter - Fix TaskStep/ActionStep mocks to use real classes for dataclass inheritance - Add proper package stubs for sdk.nexent.core.agents and utils modules * fix: update test_nexent_agent mocks for agent_run_with_observer - Add timing.duration attribute to mock action steps (implementation expects step_log.timing.duration) - Add step_number attribute to mock action steps - Import ANY from unittest.mock for flexible assertions - Update TOKEN_COUNT assertions to use ANY (implementation now sends JSON token data) - Fix test_agent_run_with_observer_with_none_duration: implementation now handles None gracefully (0.0) * fix: add context_manager and step_metrics to CoreAgent test mocks Implementation now accesses context_manager and step_metrics in _collect_step_metrics method. Tests need these attributes initialized to avoid AttributeError. --------- Co-authored-by: liudongfei <744532452@qq.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Jinglong Wang <wangjinglong8@huawei.com> Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* ✨ Feat: Enhance final answer generation with streaming support - Introduced a new method to build messages for final answer generation, incorporating task prompts and memory messages. - Updated the max steps handling to utilize streaming for real-time answer generation, improving user experience. - Enhanced error handling during final answer generation to provide fallback messages in case of failures. * 🔧 Update max steps warning logic in chat stream final message component - Modified the condition for displaying the max steps warning to trigger when the message is complete and contains maxStepsInfo. - Improved clarity in the code comments to better reflect the updated logic. * ✨ Add unit tests for _build_final_answer_messages function - Introduced a new test suite for the _build_final_answer_messages function, covering various scenarios including basic message structure, skipping the first memory message, handling empty memory, and template rendering with task variables. - Enhanced the test setup by mocking necessary modules to ensure isolated testing of the function's behavior.
…text (#2880) - Updated prompt generation logic to always include knowledge_base_names in the template context, defaulting to an empty string when not available. This change prevents errors related to undefined variables in Jinja2 templates. - Modified YAML files for English and Chinese prompts to reflect the updated syntax for knowledge_base_names, ensuring consistency in few-shot example generation.
- Add enable_context_manager BOOLEAN column to ag_tenant_agent_t table - Add column comment for enable_context_manager - Sync docker/init.sql and k8s init.sql with migration v2.0.4_0427 Co-authored-by: Jinglong Wang <wangjinglong8@huawei.com>
- Added validation for API response types to raise ValueError for unexpected string or dictionary responses. - Implemented safety checks to skip non-standard chunks that lack expected attributes, logging warnings for such cases. - Introduced unit tests to cover new error handling scenarios and ensure robust processing of API responses.
…tools to access MinIO files (#2885) * feat: Expose URL via the northbound api to allow third-party MCP tools to access MinIO files * Add relevant configuration instructions * Update backend/prompts/managed_system_prompt_template_zh.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update backend/consts/const.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update backend/prompts/managed_system_prompt_template_en.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update backend/database/attachment_db.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * 新增测试用例,修改测试用例 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…MCP services under Kubernetes deployment. (#2890)
| const handleSubmit = async () => { | ||
| try { | ||
| const values = await editorForm.validateFields(); | ||
| const payload = buildPayload(values); | ||
| setSubmitting(true); | ||
|
|
||
| const savedTemplate = editingTemplate | ||
| ? await promptTemplateService.update(editingTemplate.template_id, payload) | ||
| : await promptTemplateService.create(payload); | ||
|
|
||
| if (savedTemplate) { | ||
| onTemplatesChanged(); | ||
| onSelectTemplate(savedTemplate); | ||
| message.success(t("businessLogic.config.template.saveSuccess")); | ||
| closeEditor(); | ||
| } | ||
| } catch (error) { | ||
| if ((error as any)?.errorFields) { | ||
| return; | ||
| } | ||
| log.error("Failed to save prompt template:", error); | ||
| message.error(t("businessLogic.config.template.saveError")); | ||
| } finally { | ||
| setSubmitting(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
表单验证与提交逻辑耦合,handleSubmit 函数中混合了表单验证和提交逻辑,难以测试
| const renderLanguagePanel = (language: "zh" | "en") => { | ||
| const isChinese = language === "zh"; | ||
| const contentName = isChinese ? "template_content_zh" : "template_content_en"; | ||
|
|
||
| return ( | ||
| <Flex vertical gap={16}> | ||
| <Flex vertical gap={4}> | ||
| <Text strong>{t("businessLogic.config.template.basicSection")}</Text> | ||
| <Text type="secondary"> | ||
| {t("businessLogic.config.template.basicDescription")} | ||
| </Text> | ||
| {!isChinese ? ( | ||
| <Text type="secondary"> | ||
| {t("businessLogic.config.template.englishOptionalDescription")} | ||
| </Text> | ||
| ) : null} | ||
| </Flex> | ||
|
|
||
| {renderTemplateFields(contentName, BASIC_PROMPT_TEMPLATE_FIELDS, isChinese)} |
There was a problem hiding this comment.
不必要的重新渲染,每次父组件更新都会重新创建整个语言面板
| <List | ||
| dataSource={templates} | ||
| locale={{ | ||
| emptyText: t("businessLogic.config.template.empty"), | ||
| }} | ||
| split={false} | ||
| renderItem={(template) => { | ||
| const isSelected = selectedTemplateId === template.template_id; | ||
| const isSystemDefault = template.is_system_default; | ||
| return ( | ||
| <List.Item style={{ padding: 0, marginBottom: 12 }}> |
|
|
||
| const openCreateEditor = async () => { | ||
| try { | ||
| const systemDefault = await promptTemplateService.detail(0); |
There was a problem hiding this comment.
硬编码的字符串,0 是系统默认模板的ID,应该使用常量
| closeEditor(); | ||
| } | ||
| } catch (error) { | ||
| if ((error as any)?.errorFields) { |
There was a problem hiding this comment.
类型断言使用不当,使用 any 类型断言,绕过了类型检查
| title={editingTemplate | ||
| ? editorReadOnly | ||
| ? t("common.preview") | ||
| : t("businessLogic.config.template.editTitle") | ||
| : t("businessLogic.config.template.createTitle")} |
| } | ||
| }; | ||
|
|
||
| const handleDelete = (template: PromptTemplate) => { |
There was a problem hiding this comment.
缺少加载状态,删除操作没有加载状态,用户可能重复点击。
| const handleContentSelect = useCallback(() => { | ||
| if (!contentTextAreaRef.current) return; | ||
| const textarea = contentTextAreaRef.current.resizableTextArea?.textArea; | ||
| if (!textarea) return; | ||
|
|
||
| const { selectionStart, selectionEnd } = textarea; |
There was a problem hiding this comment.
文本选择功能不完善,用户选择文本时,模式会自动切换,可能覆盖用户手动选择的模式。onClick、onKeyUp 和 onSelect 都触发了 handleContentSelect,可能导致意外的状态变化。没有考虑用户在 general 模式下选择文本的场景
| if (mode === "insert") { | ||
| const pos = parseInt(startPos, 10); | ||
| if (isNaN(pos) || pos < 0) { | ||
| message.error(t("systemPrompt.finetune.positionError")); | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
没有验证 pos 是否在内容长度范围内,没有验证 startPos 是否为有效数字字符串
| const mapHeadersToChinese = (text: string) => { | ||
| let result = text; | ||
| for (const [en, zh] of Object.entries(headerMap)) { | ||
| result = result.split(en).join(zh); | ||
| } | ||
| return result; | ||
| }; |
There was a problem hiding this comment.
文本映射可能导致内容损坏,使用 split().join() 替换可能导致部分匹配问题,没有考虑大小写敏感性,如果内容中包含 "# Duty" 作为普通文本也会被替换
| const modeOptions: Array<{ value: OptimizeMode; label: string; desc: string }> = [ | ||
| { | ||
| value: "general", | ||
| label: t("systemPrompt.finetune.modeGeneral"), | ||
| desc: t("systemPrompt.finetune.modeGeneralDesc"), | ||
| }, |
| <Card title={t("systemPrompt.optimize.optimized")}> | ||
| {isOptimizing ? ( | ||
| <div className="flex flex-col items-center justify-center py-8 gap-3 min-h-[200px]"> | ||
| <Spin size="medium" /> | ||
| <span className="text-gray-500 text-sm"> | ||
| {t("systemPrompt.optimize.generating")} | ||
| </span> | ||
| </div> | ||
| ) : ( | ||
| <Paragraph | ||
| style={{ whiteSpace: "pre-wrap", minHeight: 200, marginBottom: 0 }} | ||
| className="font-mono text-sm" | ||
| > | ||
| {optimizedContent || t("systemPrompt.optimize.empty")} | ||
| </Paragraph> | ||
| )} | ||
| </Card> |
There was a problem hiding this comment.
当 optimizedContent 更新时,文本区域会重新渲染,滚动位置可能丢失
| if (!open) { | ||
| setFeedback(""); | ||
| setOptimizedContent(""); | ||
| setIsOptimizing(false); | ||
| setMode("general"); | ||
| setStartPos(""); | ||
| setEndPos(""); | ||
| setIsContentSelected(false); | ||
| return; | ||
| } |
| <Card title={t("systemPrompt.optimize.optimized")}> | ||
| {isOptimizing ? ( | ||
| <div className="flex flex-col items-center justify-center py-8 gap-3 min-h-[200px]"> | ||
| <Spin size="medium" /> |
There was a problem hiding this comment.
优化过程可能较长,但只有 Spin 组件,没有显示进度。
| const handleReplace = () => { | ||
| if (!optimizedContent.trim() || isOptimizing) return; | ||
| onReplace(optimizedContent.trim(), sectionType); | ||
| }; |
| useEffect(() => { | ||
| if (!visible || !draft) return; | ||
| form.setFieldsValue({ | ||
| name: draft.name, | ||
| description: draft.description, | ||
| transportType: draft.transportType, | ||
| serverUrl: draft.serverUrl, | ||
| authorizationToken: draft.authorizationToken, | ||
| customHeaders: draft.customHeaders, | ||
| containerConfigJson: draft.containerConfigJson, | ||
| containerPort: draft.containerPort, | ||
| }); | ||
| }, [visible, draft, form]); |
There was a problem hiding this comment.
表单状态与Draft状态不同步,
- 表单字段使用 value 和 onChange 双向绑定,同时使用 form.setFieldValue
- 当用户输入时,更新了 draft 状态,但表单值可能不同步
- 存在多个数据源(draft 状态和表单状态),容易产生不一致
| <McpCommunityCardList | ||
| loading={browser.loading} | ||
| services={browser.services} | ||
| hasPrevPage={browser.hasPrevPage} | ||
| hasNextPage={browser.hasNextPage} | ||
| onPrevPage={browser.prevPage} | ||
| onNextPage={browser.nextPage} | ||
| onSelect={setSelected} | ||
| onQuickAdd={quickAdd.open} | ||
| /> | ||
| </div> |
There was a problem hiding this comment.
props传递路径过长,quickAdd.open 需要接收 service 参数,但类型定义不清晰。
| <McpCommunityToolbar | ||
| search={browser.filters.search} | ||
| transport={browser.filters.transport} | ||
| tag={browser.filters.tag} | ||
| tagStats={browser.tagStats} | ||
| page={browser.page} | ||
| resultCount={browser.services.length} | ||
| onSearchChange={(value) => browser.updateFilter("search", value)} | ||
| onTransportChange={(value) => | ||
| browser.updateFilter("transport", value) | ||
| } | ||
| onTagChange={(value) => browser.updateFilter("tag", value)} | ||
| /> |
There was a problem hiding this comment.
不必要的重新渲染,每次渲染都创建新onSearchChange函数
| <McpCommunityDetailModal | ||
| service={selected} | ||
| onClose={() => setSelected(null)} | ||
| onQuickAdd={quickAdd.open} | ||
| /> |
There was a problem hiding this comment.
每次 selected 变化时,McpCommunityDetailModal 都会重新创建。
| interface CommunityQuickAddModalProps { | ||
| controller: ReturnType<typeof useMcpCommunityQuickAdd>; | ||
| } |
There was a problem hiding this comment.
类型定义不完整,使用 ReturnType 推断类型,但 useMcpCommunityQuickAdd 的返回类型可能变化。
| const handleOk = async () => { | ||
| try { | ||
| await form.validateFields(); | ||
| } catch { | ||
| return; | ||
| } | ||
| await controller.confirm(); | ||
| }; |
There was a problem hiding this comment.
错误处理不完善,如果 controller.confirm() 失败,没有错误处理。
| {draft.transportType !== McpTransportType.CONTAINER ? ( | ||
| <div className="space-y-4"> | ||
| <Form.Item | ||
| label={t("mcpTools.addModal.serverUrl")} | ||
| name="serverUrl" | ||
| className="mb-0 text-sm text-slate-500" | ||
| rules={rules.httpUrl} | ||
| > |
There was a problem hiding this comment.
复杂的条件渲染逻辑,两种配置模式的渲染逻辑应该提取为独立组件。
| <Form | ||
| form={form} | ||
| layout="vertical" | ||
| requiredMark={false} | ||
| className="space-y-4 pt-2" | ||
| > |
There was a problem hiding this comment.
表单验证反馈不及时,只在提交时验证,用户输入时没有实时反馈。
|
|
||
| useEffect(() => { | ||
| if (!visible || !draft) return; | ||
| form.setFieldsValue({ |
| const [versionMode, setVersionMode] = useState<McpVersionFilterMode>( | ||
| McpVersionFilterMode.LATEST | ||
| ); |
There was a problem hiding this comment.
状态管理混乱 - versionMode 与 version props不同步:
- versionMode 是本地状态,但 version 来自props,两者可能不同步
- useEffect中的逻辑有重复:else if 和 else 都设置为 LATEST
- 当 version 值不是 "latest" 或空字符串时,应该如何处理?
| const marketMenuItems: MenuProps["items"] = [ | ||
| { | ||
| key: "modelscope", | ||
| label: ( | ||
| <a | ||
| href="https://www.modelscope.cn/mcp" | ||
| target="_blank" | ||
| rel="noreferrer" | ||
| className="text-[#1677ff] hover:underline" | ||
| > | ||
| {t("mcpTools.registry.market.modelscope")} | ||
| </a> | ||
| ), | ||
| }, |
| const updatedSinceDateValue = useMemo(() => { | ||
| if (!updatedSince) return null; | ||
| const parsed = dayjs(updatedSince); | ||
| return parsed.isValid() ? parsed : null; | ||
| }, [updatedSince]); |
There was a problem hiding this comment.
日期选择器重新计算,这个 useMemo 是合理的,但 dayjs 的导入和使用可以优化。
| interface McpRegistryToolbarProps { | ||
| search: string; | ||
| version: string; | ||
| updatedSince: string; | ||
| includeDeleted: boolean; | ||
| page: number; | ||
| resultCount: number; | ||
| onSearchChange: (value: string) => void; | ||
| onVersionChange: (value: string) => void; | ||
| onUpdatedSinceChange: (value: string) => void; | ||
| onIncludeDeletedChange: (value: boolean) => void; | ||
| } |
There was a problem hiding this comment.
缺少类型定义,回调函数的类型应该更具体,比如 onSearchChange: (value: string) => void 已经足够,但可以考虑使用 ChangeEventHandler
| <div className="flex flex-col gap-2 lg:flex-row lg:items-center"> | ||
| <Input | ||
| value={search} | ||
| onChange={(event) => onSearchChange(event.target.value)} |
There was a problem hiding this comment.
缺少防抖功能,输入搜索时,每次按键都会触发搜索请求。
| <DatePicker | ||
| value={updatedSinceDateValue} | ||
| onChange={(value) => | ||
| onUpdatedSinceChange(value ? value.toISOString() : "") | ||
| } | ||
| allowClear | ||
| className="h-9 min-w-[160px] flex-1 rounded-md border border-slate-200 text-sm lg:flex-none lg:w-44" | ||
| placeholder={t("mcpTools.registry.updatedSincePlaceholder")} | ||
| /> |
There was a problem hiding this comment.
日期选择器交互不够友好,日期选择器没有预设的快捷选项(如"最近7天"、"最近30天")。
No description provided.