From 5f4754718f28230418b23c8f1c689c762b8e7270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=A4=95?= Date: Sun, 26 Apr 2026 11:34:46 +0800 Subject: [PATCH] Jules refactor backend and frontend 3736339600030847383 (#33) * fix: correct actorlist handle in supervisory node and ui form reset (#30) - Fixed `AttributeError` for `workflow_template_manager` in `SupervisoryNode` by properly unpacking the `.global_state_machine` handle from `ray_actor_hook`. - Removed overly broad blanket `Exception` swallowing for WebSocket cancellation that caused closed loops in Uvicorn handlers to leak and dump HTTP errors. - UI: Reset `model_id` to blank whenever a user alters the `Provider Title` to prevent stale incompatible models from breaking submission. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com> * Fix provider manager and skill settings 17493544742337088454 (#31) * fix: correct actorlist handle in supervisory node and ui form reset - Fixed `AttributeError` for `workflow_template_manager` in `SupervisoryNode` by properly unpacking the `.global_state_machine` handle from `ray_actor_hook`. - Removed overly broad blanket `Exception` swallowing for WebSocket cancellation that caused closed loops in Uvicorn handlers to leak and dump HTTP errors. - UI: Reset `model_id` to blank whenever a user alters the `Provider Title` to prevent stale incompatible models from breaking submission. Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com> * fix: dynamically resolve backend urls based on browser window location - Updated `apiClient.ts` to use a relative base URL (`''`) if `VITE_API_BASE_URL` is omitted, allowing axios to infer the current domain in reverse-proxied environments. - Updated WebSocket URL generation in `RightPanel.tsx` and `useClusterState.ts` to dynamically calculate protocol (`ws:` vs `wss:`) and host from `window.location`. Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com> * Refactor GlobalStateMachine/PostgresDatabase reflection, error retry mechanisms, and frontend worker individual UI. - Replaced dynamic getattr reflection in GlobalStateMachine and PostgresDatabase with explicit wrapper methods to improve stability and avoid Missing Method AttributeErrors. - Add `get_tool_list` explicit wrapper method resolving runtime crashes. - Implemented `RetryableError` and `NonRetryableError` base exceptions, wrapping network errors and utilizing custom `@retry_on_retryable_error` decorator on Provider requests instead of Ray actor's unsupported `retry_exceptions`. - Added exponential backoff algorithms for WebSocket reconnections in the frontend. - Added strict TypeScript-based schema validation for WorkflowTemplate creation payloads. - Redesigned the Worker Individual configuration UI into a unified list containing both System Nodes and Custom Workers, supporting Add, Edit, and Delete workflows, and resolving the provider-switching bug. - Updated unit tests to align with architectural changes. - Cleaned up temp scripts. Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com> --- frontend/src/api/client.ts | 6 +- .../Agent/WorkerIndividualSettings.tsx | 552 ++++++++++-------- frontend/src/components/Chat/RightPanel.tsx | 64 +- .../src/components/Resource/SkillSettings.tsx | 9 +- .../Resource/WorkflowTemplateSettings.tsx | 29 +- frontend/src/hooks/useClusterState.ts | 65 ++- frontend/src/types/index.ts | 16 + pretor/adapter/model_adapter/agent_factory.py | 2 +- pretor/api/agent.py | 51 +- pretor/api/auth.py | 10 +- pretor/api/cluster.py | 7 +- pretor/api/platform/frontend.py | 2 +- pretor/api/provider.py | 5 +- pretor/api/resource.py | 12 +- pretor/api/workflow.py | 7 +- pretor/core/database/postgres.py | 79 ++- .../global_state_machine.py | 80 ++- .../individual_manager.py | 2 +- .../model_provider/claude_provider.py | 2 + .../model_provider/gemini_provider.py | 6 + .../model_provider/openai_provider.py | 5 +- .../global_state_machine/provider_manager.py | 13 +- .../consciousness_node/consciousness_node.py | 5 +- .../individual/control_node/control_node.py | 5 +- .../supervisory_node/supervisory_node.py | 7 +- pretor/core/workflow/workflow_runner.py | 1 + pretor/utils/check_user/role_check.py | 3 +- pretor/utils/error.py | 10 +- pretor/utils/get_tool.py | 2 +- pretor/utils/retry.py | 31 + pretor/worker_individual/worker_cluster.py | 3 +- pretor/worker_individual/worker_individual.py | 2 +- .../model_adapter/agent_factory_test.py | 8 +- tests/core/database/postgres_test.py | 11 +- .../global_state_machine_test.py | 33 +- .../model_provider/claude_provider_test.py | 2 +- .../model_provider/gemini_provider_test.py | 2 +- .../model_provider/openai_provider_test.py | 10 +- .../provider_manager_test.py | 3 +- tests/core/workflow/workflow_runner_test.py | 8 +- 40 files changed, 741 insertions(+), 429 deletions(-) create mode 100644 pretor/utils/retry.py diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 7c13b50..b82b652 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1,9 +1,9 @@ import axios from 'axios'; -// The base URL should typically come from an environment variable in a real app, -// but for development we can default to localhost. +// The base URL should typically come from an environment variable in a real app. +// If missing, defaulting to '' means requests will be relative to the current browser origin. export const apiClient = axios.create({ - baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000', + baseURL: import.meta.env.VITE_API_BASE_URL || '', timeout: 10000, headers: { 'Content-Type': 'application/json', diff --git a/frontend/src/components/Agent/WorkerIndividualSettings.tsx b/frontend/src/components/Agent/WorkerIndividualSettings.tsx index c394e07..f6ed75c 100644 --- a/frontend/src/components/Agent/WorkerIndividualSettings.tsx +++ b/frontend/src/components/Agent/WorkerIndividualSettings.tsx @@ -1,285 +1,331 @@ import { useState, useEffect } from 'react'; import apiClient from '../../api/client'; -import { Bot, Save } from 'lucide-react'; +import { Save, Plus, Edit2, Trash2, X } from 'lucide-react'; import type { Provider } from '../../types'; -function WorkerIndividualForm({ providers }: { providers: Provider[] }) { - const [formData, setFormData] = useState({ - agent_name: '', - agent_type: 'OrdinaryIndividual', - description: '', - provider_title: providers.length > 0 ? providers[0].provider_title : '', - model_id: '', - system_prompt: '', - output_template: '{}', - bound_skill: '{}', - workspace: '[]' - }); - const [loading, setLoading] = useState(false); - const [message, setMessage] = useState(''); - - // Update initial provider_title when providers load - useEffect(() => { - if (providers.length > 0 && !formData.provider_title) { - setFormData(prev => ({ ...prev, provider_title: providers[0].provider_title })); - } - }, [providers, formData.provider_title]); - - const handleChange = (e: React.ChangeEvent) => { - setFormData({ ...formData, [e.target.name]: e.target.value }); - }; - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setLoading(true); - setMessage(''); - try { - const payload = { - ...formData, - output_template: JSON.parse(formData.output_template), - bound_skill: JSON.parse(formData.bound_skill), - workspace: JSON.parse(formData.workspace) - }; - await apiClient.post('/api/v1/agent/worker', payload); - setMessage('Successfully created worker individual'); - setFormData({ - agent_name: '', - agent_type: 'OrdinaryIndividual', - description: '', - provider_title: '', - model_id: '', - system_prompt: '', - output_template: '{}', - bound_skill: '{}', - workspace: '[]' - }); - } catch (err: any) { - console.error(err); - setMessage(err.response?.data?.detail || 'Failed to create worker individual. Ensure JSON fields are valid.'); - } finally { - setLoading(false); - } - }; - - return ( -
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -