Skip to content

Add unified new chat project setup modal#157

Open
friuns2 wants to merge 3 commits into
mainfrom
codex/new-chat-project-clone-modal
Open

Add unified new chat project setup modal#157
friuns2 wants to merge 3 commits into
mainfrom
codex/new-chat-project-clone-modal

Conversation

@friuns2
Copy link
Copy Markdown
Owner

@friuns2 friuns2 commented May 11, 2026

Summary

  • add GitHub clone support to the new chat project setup flow
  • replace separate create/clone prompts with a unified Create Project modal
  • add dark-theme modal styling and update manual test docs

Verification

  • pnpm run build:frontend
  • focused Playwright DOM check for light/dark modal surfaces
  • PROFILE_BASE_URL=http://127.0.0.1:4173 PROFILE_WAIT_MS=7000 pnpm run profile:browser

Performance profile: output/playwright/browser-runtime-profile-home-2026-05-11T04-50-25-588Z.json. Existing warning remains: threadRead=3; no new startup fanout from this modal change.

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

Add unified project setup modal with GitHub clone support

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add GitHub repository cloning support to new chat project setup
• Replace separate create/clone prompts with unified modal interface
• Implement tab-based mode switching between create and clone operations
• Add comprehensive dark theme styling for modal and form elements
Diagram
flowchart LR
  A["User clicks Create Project"] --> B["Project Setup Modal Opens"]
  B --> C{"Select Mode"}
  C -->|"New project"| D["Enter project name"]
  C -->|"Clone from GitHub"| E["Enter repository URL"]
  D --> F["Create project in destination"]
  E --> G["Clone repository to destination"]
  F --> H["Register and select project"]
  G --> H
Loading

Grey Divider

File Changes

1. src/api/codexGateway.ts ✨ Enhancement +22/-0

Add GitHub clone API gateway function

• Add cloneGithubRepository() function to handle GitHub clone API calls
• Implement error handling and response parsing for clone operations
• Follow existing pattern for path normalization and error messages

src/api/codexGateway.ts


2. src/composables/useUiLanguage.ts 📝 Documentation +12/-0

Add Chinese translations for project setup modal

• Add Chinese translations for new modal UI strings
• Include labels for create/clone modes, form fields, and action buttons
• Add loading state messages for both create and clone operations

src/composables/useUiLanguage.ts


3. src/server/codexAppServerBridge.ts ✨ Enhancement +64/-0

Implement GitHub clone server-side logic and endpoint

• Implement normalizeGithubCloneUrl() to validate and normalize GitHub URLs
• Support both SSH and HTTPS GitHub repository URL formats
• Add cloneGithubRepositoryIntoBase() to execute git clone with validation
• Add POST endpoint /codex-api/github-clone to handle clone requests
• Include comprehensive error handling for invalid URLs and paths

src/server/codexAppServerBridge.ts


View more (3)
4. src/App.vue ✨ Enhancement +184/-14

Replace project creation prompt with unified modal

• Replace onCreateProject() prompt-based flow with modal-based onOpenProjectSetupModal()
• Add modal state management for create/clone mode, form inputs, and errors
• Implement tab-based UI for switching between create and clone modes
• Add form validation for project names and GitHub URLs
• Add computed properties for submit button labels and form validation
• Implement createProjectFromSetupModal() and cloneGithubRepositoryFromSetupModal() handlers

src/App.vue


5. src/style.css ✨ Enhancement +48/-0

Add dark theme styling for project setup modal

• Add dark theme styles for project setup modal and form elements
• Style tab buttons with active state and hover effects
• Add dark theme styling for inputs, error messages, and action buttons
• Ensure consistent contrast and spacing across light and dark themes

src/style.css


6. tests.md 📝 Documentation +30/-0

Add manual test documentation for project setup modal

• Add comprehensive manual test documentation for unified project setup modal
• Include prerequisites, step-by-step test procedures, and expected results
• Cover both light and dark theme verification
• Document cleanup procedures for test artifacts

tests.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented May 11, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0)

Grey Divider


Action required

1. Workspace roots cache stale 🐞 Bug ≡ Correctness
Description
After a successful GitHub clone, the server persists the cloned folder as a workspace root, but the
client-side getWorkspaceRootsState() cache is not invalidated, so the UI can reload/persist an
out-of-date roots list and omit (or overwrite) the new root. This can make the newly-cloned project
not show up in the folder selector or have incorrect ordering until a full refresh.
Code

src/api/codexGateway.ts[R2810-2830]

+export async function cloneGithubRepository(url: string, basePath: string): Promise<string> {
+  const response = await fetch('/codex-api/github-clone', {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/json' },
+    body: JSON.stringify({ url, basePath }),
+  })
+  const payload = await readJsonResponse(response)
+  if (!response.ok) {
+    const message = getErrorMessageFromPayload(payload, 'Failed to clone GitHub repository')
+    throw new Error(message)
+  }
+  const record =
+    payload && typeof payload === 'object' && !Array.isArray(payload)
+      ? (payload as Record<string, unknown>)
+      : {}
+  const data =
+    record.data && typeof record.data === 'object' && !Array.isArray(record.data)
+      ? (record.data as Record<string, unknown>)
+      : {}
+  return typeof data.path === 'string' ? normalizePathForUi(data.path) : ''
+}
Evidence
getWorkspaceRootsState() is cached and only cleared by invalidateWorkspaceRootsStateCache(),
which is called by openProjectRoot() but not by the newly-added cloneGithubRepository(). The new
modal flow calls pinProjectToTop() and loadWorkspaceRootOptionsState() immediately after
cloning; both depend on getWorkspaceRootsState(), and pinProjectToTop() ultimately persists
workspace-roots state back via setWorkspaceRootsState(), risking writing back stale state that
doesn’t include the newly persisted cloned root.

src/api/codexGateway.ts[2336-2351]
src/api/codexGateway.ts[2376-2378]
src/api/codexGateway.ts[2760-2785]
src/api/codexGateway.ts[2810-2830]
src/App.vue[3176-3192]
src/App.vue[3427-3437]
src/composables/useDesktopState.ts[5077-5102]
src/api/codexGateway.ts[2748-2758]
src/server/codexAppServerBridge.ts[3986-4004]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`cloneGithubRepository()` persists a new workspace root on the server, but the browser keeps using a cached `getWorkspaceRootsState()` result, so immediately after cloning the UI can operate on stale workspace-roots state (missing the new root) and even persist that stale state back.

### Issue Context
`openProjectRoot()` explicitly calls `invalidateWorkspaceRootsStateCache()`, but `cloneGithubRepository()` does not.

### Fix Focus Areas
- src/api/codexGateway.ts[2810-2830]
- src/api/codexGateway.ts[2760-2785]

### Suggested fix
- After a successful clone (once a valid `data.path` is returned), call `invalidateWorkspaceRootsStateCache()` (mirroring `openProjectRoot()`).
- Optionally, consider returning additional data from the clone endpoint (e.g., updated workspace-roots state) and updating the cache directly, but invalidation alone should fix the immediate correctness bug.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Clone can hang indefinitely 🐞 Bug ☼ Reliability
Description
The new /codex-api/github-clone endpoint runs git clone via runCommand() which has no
timeout/cancellation; a slow or stalled clone can keep the request open indefinitely and tie up the
bridge worker. This is a new risk introduced specifically by adding a long-running network operation
to an unbounded spawn wrapper.
Code

src/server/codexAppServerBridge.ts[R1029-1030]

+  await runCommand('git', ['clone', url, targetPath], { cwd: normalizedBasePath })
+  await persistWorkspaceRoot(targetPath, '')
Evidence
The clone endpoint calls runCommand('git', ['clone', ...]). The runCommand() implementation
wraps spawn() and waits for the process to close, but does not enforce any timeout, abort signal,
or kill-on-deadline behavior; therefore a hung git clone can block until it eventually exits (or
never).

src/server/codexAppServerBridge.ts[1014-1032]
src/server/codexAppServerBridge.ts[2717-2738]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`git clone` can take arbitrarily long or stall; the new clone endpoint uses `runCommand()` which has no timeout/cancellation, so the request can hang indefinitely.

### Issue Context
This becomes much more likely with cloning than with existing short git operations.

### Fix Focus Areas
- src/server/codexAppServerBridge.ts[1014-1032]
- src/server/codexAppServerBridge.ts[2717-2738]

### Suggested fix
- Extend `runCommand()` (or add a dedicated `runCommandWithTimeout()` variant) to accept a `timeoutMs` and kill the child process on expiry.
- Use that timeout-enabled command runner for `git clone` (and potentially other network-sensitive git operations).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread src/api/codexGateway.ts
Comment on lines +2810 to +2830
export async function cloneGithubRepository(url: string, basePath: string): Promise<string> {
const response = await fetch('/codex-api/github-clone', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url, basePath }),
})
const payload = await readJsonResponse(response)
if (!response.ok) {
const message = getErrorMessageFromPayload(payload, 'Failed to clone GitHub repository')
throw new Error(message)
}
const record =
payload && typeof payload === 'object' && !Array.isArray(payload)
? (payload as Record<string, unknown>)
: {}
const data =
record.data && typeof record.data === 'object' && !Array.isArray(record.data)
? (record.data as Record<string, unknown>)
: {}
return typeof data.path === 'string' ? normalizePathForUi(data.path) : ''
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Workspace roots cache stale 🐞 Bug ≡ Correctness

After a successful GitHub clone, the server persists the cloned folder as a workspace root, but the
client-side getWorkspaceRootsState() cache is not invalidated, so the UI can reload/persist an
out-of-date roots list and omit (or overwrite) the new root. This can make the newly-cloned project
not show up in the folder selector or have incorrect ordering until a full refresh.
Agent Prompt
### Issue description
`cloneGithubRepository()` persists a new workspace root on the server, but the browser keeps using a cached `getWorkspaceRootsState()` result, so immediately after cloning the UI can operate on stale workspace-roots state (missing the new root) and even persist that stale state back.

### Issue Context
`openProjectRoot()` explicitly calls `invalidateWorkspaceRootsStateCache()`, but `cloneGithubRepository()` does not.

### Fix Focus Areas
- src/api/codexGateway.ts[2810-2830]
- src/api/codexGateway.ts[2760-2785]

### Suggested fix
- After a successful clone (once a valid `data.path` is returned), call `invalidateWorkspaceRootsStateCache()` (mirroring `openProjectRoot()`).
- Optionally, consider returning additional data from the clone endpoint (e.g., updated workspace-roots state) and updating the cache directly, but invalidation alone should fix the immediate correctness bug.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

2 participants