-
Notifications
You must be signed in to change notification settings - Fork 61
🤖 feat: seamless fork semantics #2295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b5afd6282
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
d41c35d to
219caa0
Compare
…ation
- Schema: add autoName flag to WorkspaceMetadata and WorkspaceConfig
- Backend: auto-generate fork branch names ({parent}-fork-N pattern)
when /fork is used without an explicit name
- Backend: clear autoName flag on any title update (manual rename or
auto-generated) to exit the provisional naming state
- Frontend: simplify /fork command - bare /fork works, everything after
is treated as a start message
- Frontend: auto-name on first message via nameGeneration IPC
(fire-and-forget, reuses existing LLM title generation pipeline)
- Frontend: italic styling in sidebar for auto-name workspaces
- Remove fork-help toast (no longer needed since bare /fork works)
- Tests: update fork command tests, add generateForkBranchName unit tests
Move the auto-naming trigger from ChatInput (frontend) to WorkspaceService.sendMessage (backend), fixing three issues: 1. Eliminates duplicate candidate-building logic that was missing gateway model transforms (bug) 2. Includes prior assistant message from forked history for richer title generation context 3. Colocates the trigger with existing fire-and-forget side effects (updateRecencyTimestamp pattern) Changes: - Add autoGenerateTitle() private method to WorkspaceService - Trigger from sendMessage after recency timestamp update - Add assistantContext param to generateWorkspaceIdentity prompt - Remove auto-naming block, refs, and imports from ChatInput - Un-export NAME_GEN_PREFERRED_MODELS (now module-private)
- Add RENAME_WORKSPACE and REGENERATE_WORKSPACE_NAME to keybinds registry - Add workspace.regenerateTitle backend endpoint (reads first user message + assistant reply from history, calls generateWorkspaceIdentity, persists via updateTitle) - Add SidebarRenameKeybinds component inside RenameProvider for F2/Shift+F2 (F2 enters inline edit mode, Shift+F2 calls regenerateTitle API) - Update WorkspaceListItem context menu: F2 hint on 'Edit chat title', new 'Generate new title' item with Shift+F2 hint and Sparkles icon - Add command palette entries with shortcut hints - Add keybind labels + navigation group entries in KeybindsSection
All rename/name terminology updated to reflect that this feature is about workspace *titles*, not workspace names/branches: Keybinds: - RENAME_WORKSPACE → EDIT_WORKSPACE_TITLE - REGENERATE_WORKSPACE_NAME → GENERATE_WORKSPACE_TITLE Commands: - ws:rename → ws:edit-title (+ ws:rename-any → ws:edit-title-any) - ws:regenerate-name → ws:generate-title Context: - WorkspaceRenameContext.tsx → WorkspaceTitleEditContext.tsx (git mv) - RenameProvider → TitleEditProvider, useRename → useTitleEdit - requestRename/confirmRename/cancelRename → requestEdit/confirmEdit/cancelEdit WorkspaceContext: - renameWorkspace → updateWorkspaceTitle - onRenameWorkspace → onUpdateTitle (command palette sources + App.tsx) Schema: - autoName → autoTitle (project + workspace schemas, workspaceService) UI strings updated: 'Rename Workspace' → 'Edit Workspace Title', field labels from 'name' to 'title', initial values from .name to .title
f46c527 to
90aac9c
Compare
When Shift+F2 or 'Generate new title' triggers regenerateTitle, the sidebar title now shimmers (using the existing Shimmer component) and renders in italic — matching the autoTitle placeholder style. TitleEditContext gains generatingTitleWorkspaceId state and a wrapGenerateTitle(workspaceId, asyncFn) helper that manages the loading lifecycle. Both call sites (keybind handler in ProjectSidebar, context menu in WorkspaceListItem) use the wrapper so the loading state is consistent regardless of entry point.
Replace the lazy AI title generation on fork with a simple numbered suffix: forking "Fix sidebar" produces "Fix sidebar (1)", then "Fix sidebar (2)", etc. The suffix logic strips any existing "(N)" from the parent title before incrementing, so forking "Fix sidebar (2)" yields "Fix sidebar (3)" — not "Fix sidebar (2) (1)". Removed: - autoTitle field from project + workspace schemas - autoGenerateTitle() method in WorkspaceService - sendMessage trigger that called autoGenerateTitle on first message - autoTitle clearing in updateTitle - Italic styling for autoTitle in WorkspaceListItem Users can still manually generate a new AI title any time via Shift+F2 or the context menu "Generate new title" action. Added: - generateForkTitle() helper (+ 5 unit tests)
Move gateway resolution from scattered call sites into ProviderModelFactory.createModel(), so every model instantiation automatically routes through the gateway when configured. Changes: - createModel now calls resolveGatewayModelString (idempotent) - Remove manual gateway resolution from system1ToolWrapper - Remove resolveGatewayModelString from AIService public API - Simplify frontend buildNameGenCandidates (no gateway transform needed) - Extract NAME_GEN_PREFERRED_MODELS to shared constant - Update schema/router comments to reflect new behavior
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1c8e91ffbe
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| .get(props.selectedWorkspace.projectPath) | ||
| ?.find((m) => m.id === wsId); | ||
| const displayTitle = meta?.title ?? meta?.name ?? ""; | ||
| requestEdit(wsId, displayTitle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefill title when entering edit mode from keyboard shortcut
The F2 handler only calls requestEdit, but the inline input value is initialized in WorkspaceListItem.startEditing() and that path is bypassed here. As a result, pressing F2 opens edit mode with an empty input instead of the current title, and the subsequent blur/Enter path immediately trips the "Title cannot be empty" validation unless the user retypes the whole title manually. This breaks the advertised keyboard edit flow for selected workspaces.
Useful? React with 👍 / 👎.
| await this.updateTitle(workspaceId, result.data.title); | ||
| return Ok({ title: result.data.title }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check updateTitle result before reporting regeneration success
regenerateTitle awaits updateTitle but ignores its Result, then always returns Ok with the generated title. If persistence fails (for example workspace lookup/config write failure), callers still get a success response even though no title was saved, which can leave UI and stored metadata out of sync and hide real errors.
Useful? React with 👍 / 👎.
Summary
Seamless forking with workspace title management and centralized gateway routing. Forking now auto-generates deterministic numbered titles (
Fix Bug (1)), with F2/Shift+F2 keybinds for manual rename and AI title regeneration. Gateway model routing is centralized increateModelso all callers get correct behavior automatically.Background
Previously
/fork <name>required a user-supplied branch name, adding friction. Additionally, gateway model routing was scattered across multiple call sites — the frontend had to pre-transform model IDs withformatAsGatewayModelto compensate for the backend'screateModelnot handling it, and the backend'sregenerateTitlepath was broken for gateway users entirely.Implementation
Fork semantics
(N)suffix pattern: fork of "Fix Bug" → "Fix Bug (1)"generateForkTitle(parent, existing)handles deduplication and suffix strippingWorkspace title management
workspace.regenerateTitleIPC reads history and callsgenerateWorkspaceIdentityrename→titleacross UI and backendCentralized gateway routing (addresses Codex review comment)
ProviderModelFactory.createModel()now callsresolveGatewayModelStringinternally (idempotent — already-resolved strings pass through unchanged)system1ToolWrapperandAIServicepublic APIbuildNameGenCandidates— no longer needs gateway transformationNAME_GEN_PREFERRED_MODELSto shared constant atsrc/common/constants/nameGeneration.tsValidation
make typecheck— passesmake static-check— passesmake test— 3790 pass, 16 skip (1 pre-existing flaky failure unrelated to changes)Generated with
mux• Model:anthropic:claude-opus-4-6• Thinking:xhigh• Cost:$51.40