Merge pull request #17 from southseact-3d/cto-task-ok-so-for-the-plan-messages-when-the-proceed-with-build-butt
Add model selector to plan messages proceed button
This commit is contained in:
57
IMPLEMENTATION_SUMMARY.txt
Normal file
57
IMPLEMENTATION_SUMMARY.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
# Model Selector for Plan Messages - Implementation Complete
|
||||
|
||||
## What Was Implemented
|
||||
|
||||
When the "Proceed with Build" button appears in plan messages, a model selector dropdown is now displayed above it, allowing users to choose which AI model to use for the build process.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. New Function: `createInlineModelSelector()`
|
||||
Location: chat/public/builder.js (line 1900-1975)
|
||||
|
||||
This helper function:
|
||||
- Creates a container div with the class 'inline-model-selector'
|
||||
- Adds a label "Select Model for Build:" above the dropdown
|
||||
- Creates a styled select dropdown element
|
||||
- Populates it with all available models from state.models
|
||||
- Shows model labels, names, and multipliers (e.g., "2x")
|
||||
- Pre-selects the currently chosen model
|
||||
- Handles user selection changes and syncs with the main model selector
|
||||
- Updates state.selectedModelId and calls markUserModelChange()
|
||||
|
||||
### 2. Modified "Proceed with Build" Button Section
|
||||
Location: chat/public/builder.js (line 2174-2193)
|
||||
|
||||
The proceed button section now:
|
||||
- Creates a container div (buildActionsContainer) using flexbox layout
|
||||
- Adds the inline model selector above the button
|
||||
- Adds the "Proceed with Build" button below the selector
|
||||
- Appends the entire container to the message body
|
||||
|
||||
## Key Features
|
||||
|
||||
Model selector appears inline in plan messages
|
||||
User can change model before proceeding with build
|
||||
Selection syncs with main model selector in composer
|
||||
State is properly managed and protected from server overwrites
|
||||
Handles edge cases (no models available)
|
||||
Matches existing UI styling and design system
|
||||
JavaScript syntax validation passed
|
||||
No breaking changes to existing functionality
|
||||
|
||||
## How It Works
|
||||
|
||||
1. User receives a plan message from AI
|
||||
2. The renderMessages function detects it's a plan message ready for building
|
||||
3. A buildActionsContainer is created with the inline model selector and proceed button
|
||||
4. User can select a different model from the dropdown if desired
|
||||
5. Selection changes update state and sync with main selector
|
||||
6. When user clicks "Proceed with Build", the selected model is used for the build
|
||||
|
||||
## Technical Details
|
||||
|
||||
- Uses flexbox for layout (gap: 12px, margin-top: 16px)
|
||||
- Select element styled with custom SVG dropdown arrow
|
||||
- Full-width design for easy selection on all devices
|
||||
- Integrates with existing state management functions
|
||||
- No backend changes required
|
||||
72
MODEL_SELECTOR_FOR_PLAN_MESSAGES.md
Normal file
72
MODEL_SELECTOR_FOR_PLAN_MESSAGES.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Model Selector for Plan Messages Implementation
|
||||
|
||||
## Summary
|
||||
When the "Proceed with Build" button appears in plan messages, a model selector dropdown is now displayed above it, allowing users to choose the AI model they want to use for the build process.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. New Helper Function: `createInlineModelSelector()`
|
||||
**Location:** `chat/public/builder.js` (lines ~1899-1975)
|
||||
|
||||
Created a new helper function that generates an inline model selector specifically for plan messages:
|
||||
- Creates a labeled select dropdown with the title "Select Model for Build:"
|
||||
- Populates the dropdown with all available models from `state.models`
|
||||
- Shows model labels, names, and multiplier indicators (e.g., "2x")
|
||||
- Pre-selects the currently selected model from `state.selectedModelId`
|
||||
- Handles model selection changes and updates:
|
||||
- The inline selector's value
|
||||
- The main model selector in the composer area
|
||||
- The state's selectedModelId
|
||||
- Marks the change as user-initiated to prevent server overwrites
|
||||
|
||||
### 2. Modified "Proceed with Build" Button Section
|
||||
**Location:** `chat/public/builder.js` (lines ~2174-2193)
|
||||
|
||||
Updated the code where the "Proceed with Build" button is created:
|
||||
- Creates a container div (`buildActionsContainer`) to hold both the model selector and the button
|
||||
- Adds the inline model selector above the button
|
||||
- Maintains the existing "Proceed with Build" button functionality
|
||||
- Uses flexbox layout with proper spacing (gap: 12px, margin-top: 16px)
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Plan Message Displayed**: When an AI plan message is received and ready for building
|
||||
2. **Model Selector Created**: The `createInlineModelSelector()` function is called to generate the dropdown
|
||||
3. **User Selection**: User can select a different model for the build if desired
|
||||
4. **State Sync**: Selection changes are synchronized with the main model selector
|
||||
5. **Build Process**: When "Proceed with Build" is clicked, the selected model is used for the build
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Better UX**: Users can now choose their model right where they need it (in the plan message)
|
||||
- **Flexibility**: No need to go back to the composer area to change models before proceeding
|
||||
- **Clear Context**: Model selector is clearly labeled as "Select Model for Build:"
|
||||
- **State Consistency**: Model selection is synchronized across all UI elements
|
||||
- **Prevents Conflicts**: User model selections are protected from server overwrites
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Styling
|
||||
The inline model selector uses:
|
||||
- Consistent styling with the rest of the UI
|
||||
- Custom SVG dropdown arrow
|
||||
- Proper padding and borders matching the design system
|
||||
- Full-width layout for easy selection on all devices
|
||||
|
||||
### State Management
|
||||
- Updates `state.selectedModelId` when changed
|
||||
- Calls `markUserModelChange()` to prevent server overwrites
|
||||
- Syncs with the main model selector in the composer
|
||||
- Preserves existing state management patterns
|
||||
|
||||
### Integration
|
||||
- Works with the existing `updateModelSelectDisplay()` function
|
||||
- Compatible with `markUserModelChange()` for state protection
|
||||
- Integrates seamlessly with the current build flow
|
||||
- No changes to backend or API required
|
||||
|
||||
## Testing
|
||||
- JavaScript syntax check: ✓ Passed
|
||||
- Function definition: ✓ Present at line 1900
|
||||
- Function call: ✓ Present at line 2181
|
||||
- No breaking changes to existing functionality
|
||||
@@ -1895,6 +1895,85 @@ function hideLoadingIndicator() {
|
||||
}
|
||||
|
||||
// Expose for builder.html
|
||||
|
||||
// Helper function to create inline model selector for plan messages
|
||||
function createInlineModelSelector() {
|
||||
const container = document.createElement('div');
|
||||
container.className = 'inline-model-selector';
|
||||
container.style.cssText = 'display: flex; flex-direction: column; gap: 8px;';
|
||||
|
||||
// Label
|
||||
const label = document.createElement('label');
|
||||
label.textContent = 'Select Model for Build:';
|
||||
label.style.cssText = 'font-weight: 600; font-size: 13px; color: var(--ink);';
|
||||
|
||||
// Create a select element (simple and reliable)
|
||||
const select = document.createElement('select');
|
||||
select.className = 'inline-model-select';
|
||||
select.style.cssText = `
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 12px center;
|
||||
background-size: 14px;
|
||||
padding-right: 40px;
|
||||
`;
|
||||
|
||||
// Populate with available models
|
||||
if (state.models && state.models.length > 0) {
|
||||
state.models.forEach(model => {
|
||||
const option = document.createElement('option');
|
||||
option.value = model.id || model.name || model;
|
||||
option.textContent = model.label || model.name || model.id || model;
|
||||
if (model.multiplier && model.multiplier !== 1) {
|
||||
option.textContent += ` (${model.multiplier}x)`;
|
||||
}
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
// Set current selection
|
||||
const currentSelection = state.selectedModelId || el.modelSelect?.value;
|
||||
if (currentSelection) {
|
||||
select.value = currentSelection;
|
||||
}
|
||||
} else {
|
||||
const option = document.createElement('option');
|
||||
option.value = '';
|
||||
option.textContent = 'No models available';
|
||||
option.disabled = true;
|
||||
select.appendChild(option);
|
||||
}
|
||||
|
||||
// Handle selection change
|
||||
select.addEventListener('change', (e) => {
|
||||
const selectedModel = e.target.value;
|
||||
console.log('[Inline Model Selector] Model selected:', selectedModel);
|
||||
// Update state
|
||||
state.selectedModelId = selectedModel;
|
||||
// Also update the main model selector if it exists
|
||||
if (el.modelSelect) {
|
||||
el.modelSelect.value = selectedModel;
|
||||
updateModelSelectDisplay(selectedModel);
|
||||
}
|
||||
// Mark that user changed model (prevent server from overwriting)
|
||||
markUserModelChange();
|
||||
});
|
||||
|
||||
container.appendChild(label);
|
||||
container.appendChild(select);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
window.hideLoadingIndicator = hideLoadingIndicator;
|
||||
|
||||
function renderMessages(session) {
|
||||
@@ -2093,13 +2172,24 @@ function renderMessages(session) {
|
||||
const needsClarification = clarificationPatterns.some(pattern => pattern.test(replyContent));
|
||||
|
||||
if (isOpenRouterMessage && hasReply && (isPlanPhase || isBuildPhase) && !needsClarification) {
|
||||
// Create a container for model selector and proceed button
|
||||
const buildActionsContainer = document.createElement('div');
|
||||
buildActionsContainer.className = 'build-actions-container';
|
||||
buildActionsContainer.style.cssText = 'display: flex; flex-direction: column; gap: 12px; margin-top: 16px;';
|
||||
|
||||
// Create inline model selector for plan messages
|
||||
const inlineModelSelector = createInlineModelSelector();
|
||||
buildActionsContainer.appendChild(inlineModelSelector);
|
||||
|
||||
// Create proceed button
|
||||
const proceedBtn = document.createElement('button');
|
||||
proceedBtn.className = 'primary';
|
||||
proceedBtn.style.marginTop = '12px';
|
||||
proceedBtn.style.width = '100%';
|
||||
proceedBtn.textContent = 'Proceed with Build';
|
||||
proceedBtn.onclick = () => proceedWithBuild(replyContent);
|
||||
assistantBody.appendChild(proceedBtn);
|
||||
buildActionsContainer.appendChild(proceedBtn);
|
||||
|
||||
assistantBody.appendChild(buildActionsContainer);
|
||||
}
|
||||
|
||||
// Add Download ZIP button for OpenCode messages that are finished and are the latest message
|
||||
|
||||
Reference in New Issue
Block a user