Skip to content

Conversation

@vinci-grape
Copy link
Collaborator

Change Summary

upload index.html

Related issue number

Checklist

  • The pull request title is a good summary of the changes - it will be used in the changelog
  • Unit tests for the changes exist
  • Run pre-commit install and pre-commit run --all-files before git commit, and passed lint check.
  • Documentation reflects the changes where applicable

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @vinci-grape, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a comprehensive web user interface for the MS-Agent framework, significantly improving user interaction and manageability. It establishes a FastAPI-powered backend for core functionalities like project and session management, coupled with a dynamic React frontend for an engaging user experience. The system supports real-time communication with agents via WebSockets, providing live updates on execution, logs, and progress, and offers flexible configuration options for LLMs and external services.

Highlights

  • New Web User Interface: Introduced a complete web-based user interface for the MS-Agent framework, enabling interactive control and monitoring of agents.
  • FastAPI Backend: Implemented a FastAPI backend to provide REST APIs for managing projects, sessions, and configurations, and WebSocket endpoints for real-time agent interaction.
  • React Frontend: Developed a React-based frontend with Material-UI components, offering an intuitive and interactive user experience for agent selection, conversation, and progress visualization.
  • Real-time Agent Interaction: Enabled real-time streaming of agent output, logs, and workflow progress through WebSockets, enhancing user feedback during agent execution.
  • Configuration Management: Integrated robust configuration management for Large Language Models (LLMs) and Model Context Protocol (MCP) servers, allowing users to customize agent behavior and capabilities.
  • Automated Setup Script: Provided a start.sh script to automate the setup of the Python virtual environment, dependencies, and the launch of both the backend and frontend servers for ease of use.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive Web UI for the ms-agent project, featuring a FastAPI backend and a React frontend. The implementation is extensive and well-structured, providing a rich user experience for interacting with agents. My review focuses on enhancing the backend's robustness, security, and maintainability. Key recommendations include strengthening security in file handling, improving exception handling and logging, ensuring configuration consistency, and completing support for all frontend options in the backend logic. The frontend code is well-organized and effectively uses modern React practices.

Comment on lines +321 to +331
full_path = os.path.normpath(full_path)

# Security check: ensure file is within allowed directories
allowed_dirs = [output_dir, projects_dir]
is_allowed = any(
full_path.startswith(os.path.normpath(d)) for d in allowed_dirs)

if not is_allowed:
raise HTTPException(
status_code=403,
detail='Access denied: file outside allowed directories')
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The security check to prevent path traversal is insufficient. Using os.path.normpath does not resolve symbolic links, which could allow an attacker to create a symlink within an allowed directory to read arbitrary files on the system. To mitigate this, you should use os.path.realpath() to resolve the absolute canonical path of both the requested path and the allowed directories before performing the check.

Suggested change
full_path = os.path.normpath(full_path)
# Security check: ensure file is within allowed directories
allowed_dirs = [output_dir, projects_dir]
is_allowed = any(
full_path.startswith(os.path.normpath(d)) for d in allowed_dirs)
if not is_allowed:
raise HTTPException(
status_code=403,
detail='Access denied: file outside allowed directories')
# Normalize path and resolve symlinks to prevent path traversal.
full_path = os.path.realpath(full_path)
# Security check: ensure file is within allowed directories
allowed_dirs = [os.path.realpath(d) for d in [output_dir, projects_dir]]
is_allowed = any(full_path.startswith(d) for d in allowed_dirs)
if not is_allowed:
raise HTTPException(
status_code=403,
detail='Access denied: file outside allowed directories')

Comment on lines +88 to +121
async def stop(self):
"""Stop the agent"""
self._stop_requested = True
self.is_running = False
if not self.process:
return

try:
# If already exited, nothing to do
if self.process.returncode is not None:
return

# Prefer terminating the whole process group to stop child processes too
try:
os.killpg(self.process.pid, signal.SIGTERM)
except Exception:
# Fallback to terminating only the parent
try:
self.process.terminate()
except Exception:
pass

try:
await asyncio.wait_for(self.process.wait(), timeout=5.0)
except asyncio.TimeoutError:
try:
os.killpg(self.process.pid, signal.SIGKILL)
except Exception:
try:
self.process.kill()
except Exception:
pass
except Exception:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The stop method uses except Exception: pass in multiple places to handle errors during process termination. Silently ignoring all exceptions can hide underlying issues and make debugging difficult. It's better to at least log any exceptions that occur during the termination and kill process.

Comment on lines +166 to +167
else:
cmd = [python, '-m', 'ms_agent', 'run', '--config', project_path]
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The else block provides a fallback command for unknown project types. This could lead to unexpected behavior if a new, unsupported project type is added. It would be safer to raise an exception for unhandled project types to make the system's behavior more predictable and prevent misconfiguration.

Suggested change
else:
cmd = [python, '-m', 'ms_agent', 'run', '--config', project_path]
else:
raise ValueError(f"Unsupported project type: {project_type}")

Comment on lines +51 to +52
except Exception:
self._config = self.DEFAULT_CONFIG.copy()
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Catching a broad Exception can mask various issues, such as permission errors or malformed JSON that isn't a JSONDecodeError. It's better to catch more specific exceptions (e.g., json.JSONDecodeError, IOError) and log the error for easier debugging.

Suggested change
except Exception:
self._config = self.DEFAULT_CONFIG.copy()
except (json.JSONDecodeError, IOError) as e:
print(f"Error loading config file: {e}")

Comment on lines +150 to +156
provider = llm.get('provider', 'modelscope')
if provider == 'modelscope':
env_vars['MODELSCOPE_API_KEY'] = llm['api_key']
elif provider == 'openai':
env_vars['OPENAI_API_KEY'] = llm['api_key']
elif provider == 'anthropic':
env_vars['ANTHROPIC_API_KEY'] = llm['api_key']
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The get_env_vars method only sets API key environment variables for modelscope, openai, and anthropic providers. The frontend settings dialog also allows for deepseek and custom providers. This function should be updated to handle these providers to ensure their API keys are correctly passed to the agent's environment.

Suggested change
provider = llm.get('provider', 'modelscope')
if provider == 'modelscope':
env_vars['MODELSCOPE_API_KEY'] = llm['api_key']
elif provider == 'openai':
env_vars['OPENAI_API_KEY'] = llm['api_key']
elif provider == 'anthropic':
env_vars['ANTHROPIC_API_KEY'] = llm['api_key']
provider = llm.get('provider', 'modelscope')
if provider == 'modelscope':
env_vars['MODELSCOPE_API_KEY'] = llm['api_key']
elif provider == 'openai':
env_vars['OPENAI_API_KEY'] = llm['api_key']
elif provider == 'anthropic':
env_vars['ANTHROPIC_API_KEY'] = llm['api_key']
elif provider == 'deepseek':
env_vars['DEEPSEEK_API_KEY'] = llm['api_key']

# CORS configuration
app.add_middleware(
CORSMiddleware,
allow_origins=['*'],
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using allow_origins=['*'] is insecure for production as it allows any website to make requests to your API. This should be restricted to the specific origin(s) of your frontend application to prevent security vulnerabilities like Cross-Site Request Forgery (CSRF). Consider loading the allowed origins from an environment variable for flexibility.

Suggested change
allow_origins=['*'],
allow_origins=os.getenv('CORS_ALLOWED_ORIGINS', 'http://localhost:5173').split(','),

return None

try:
import yaml
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The import yaml statement is located inside the get_project_config method. According to PEP 8, imports should be at the top of the file. This improves readability and avoids the overhead of re-importing the module on every function call. If PyYAML is an optional dependency, this should be documented, and the ImportError should be caught specifically.

# Initialize paths
BASE_DIR = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
PROJECTS_DIR = os.path.join(BASE_DIR, 'projects')
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There is an inconsistency in the definition of the projects directory. Here, PROJECTS_DIR is os.path.join(BASE_DIR, 'projects'), but webui/backend/api.py uses os.path.join(base_dir, 'ms-agent', 'projects'). This can lead to incorrect behavior and potential security issues. These paths should be consolidated to a single source of truth.

Suggested change
PROJECTS_DIR = os.path.join(BASE_DIR, 'projects')
PROJECTS_DIR = os.path.join(BASE_DIR, 'ms-agent', 'projects')

@tastelikefeet tastelikefeet merged commit d9ab2c8 into main Jan 19, 2026
2 of 3 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.

3 participants