- Fix regex pattern in semantic-validator.js that was truncating domain names (google.com -> google) - Remove unnecessary 'info' type error reporting to bug tracker - Only add bug tracker activity when errorId is valid - Add terminal approval UI design document Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
8.3 KiB
Terminal Mode Approval UI Design
Date: 2025-01-21 Status: Design Approved, Ready for Implementation
Overview
Redesign terminal mode command approval flow to use interactive UI buttons instead of conversational text responses. This eliminates ambiguity, prevents accidental mode switches, and provides clear visual feedback for command approvals.
Problem Statement
Current Issues:
- Terminal commands go to AI agent instead of executing directly via shell
- When AI asks for approval, typing "APPROVED" is not recognized as approval
- System treats "APPROVED" as conversational message and switches to Chat mode
- No clear UI for approving/rejecting commands
User Impact:
- Confusing approval flow
- Inadvertent mode switching
- Commands not executing when expected
Design Solution
1. Approval Request UI Component
Visual Design:
┌─────────────────────────────────────────┐
│ 🤖 Executing: ping google.com │
│ │
│ Network operation - will send ICMP │
│ packets to google.com │
│ │
│ [Approve] [Custom Instructions] [Reject] │
└─────────────────────────────────────────┘
Custom Instructions Mode: When clicked, expands to show input field:
┌─────────────────────────────────────────┐
│ 🤖 Executing: ping google.com │
│ │
│ [Input: __ping google.com -c 5___] │
│ │
│ [Execute Custom] [Cancel] │
└─────────────────────────────────────────┘
Key Features:
- Inline with chat messages (like tool output)
- Shows command and explanation
- Three clear buttons (no ambiguity)
- Custom instructions option for command modification
- Auto-highlights pending request
2. Data Flow
Approval Request Flow:
1. AI decides to execute command requiring approval
2. AI sends WebSocket message:
{
"type": "approval-request",
"id": "approval-123456",
"command": "ping google.com",
"explanation": "Network operation...",
"sessionId": "session-abc"
}
3. Frontend renders approval card
4. User sees buttons
Approve Response:
{
"type": "approval-response",
"id": "approval-123456",
"approved": true,
"sessionId": "session-abc"
}
Custom Instructions Response:
{
"type": "approval-response",
"id": "approval-123456",
"approved": true,
"customCommand": "ping google.com -c 3",
"sessionId": "session-abc"
}
Reject Response:
{
"type": "approval-response",
"id": "approval-123456",
"approved": false,
"sessionId": "session-abc"
}
3. State Management
Pending Approvals Manager (Server-side):
class PendingApprovalsManager {
constructor() {
this.approvals = new Map();
}
createApproval(sessionId, command, explanation) {
const id = `approval-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
this.approvals.set(id, {
sessionId, command, explanation,
createdAt: Date.now()
});
// Auto-expire after 5 minutes
setTimeout(() => this.expire(id), 5 * 60 * 1000);
return id;
}
getApproval(id) { /* ... */ }
removeApproval(id) { /* ... */ }
expire(id) { /* ... */ }
}
Why This Works:
- Server tracks pending approvals
- Approval sent to AI as conversational message: "[APPROVED: ping google.com]"
- AI sees approval in conversation context
- AI proceeds with command
- No complex state needed in AI itself
Auto-Cleanup:
- Pending approvals expire after 5 minutes
- Cleared on session disconnect
- Expired approvals show: "This approval request has expired"
4. Component Architecture
Frontend Components:
approval-card.js
class ApprovalCard {
render(approvalData) { /* Returns HTML */ }
handleApprove() { sendApprovalResponse(this.id, true); }
handleCustom() { this.expandInput(); }
handleReject() { sendApprovalResponse(this.id, false); }
executeCustom(customCommand) { sendApprovalResponse(this.id, true, customCommand); }
}
chat-functions.js (Enhancements)
// In handleWebSocketMessage():
if (data.type === 'approval-request') {
renderApprovalCard(data);
return;
}
Backend Components:
server.js
class PendingApprovalsManager {
// Manages pending approval state
}
// WebSocket handlers for approval-request and approval-response
services/claude-service.js
async requestApproval(sessionId, command, explanation) {
const approvalId = approvalManager.createApproval(...);
this.emit('approval-request', {id, sessionId, command, explanation});
}
5. Error Handling & Edge Cases
Error Scenarios:
-
Approval Request Times Out
- 5-minute auto-expire
- Buttons disabled, shows "Expired"
- AI informed of timeout
-
User Tries New Command During Approval
- Show: "You have a pending approval. Please approve or reject first."
- New command queued until approval resolved
-
Custom Command Significantly Different
- Original:
ping google.com - Custom:
rm -rf / - AI reviews custom command
- If more dangerous, requests NEW approval
- Shows: "Modified command requires additional approval"
- Original:
-
Session Disconnected During Approval
- Pending approvals auto-expire
- Fresh state on reconnect
- No stale approvals
-
Duplicate Approval Requests
- Server checks for existing approval for same command/session
- Reuses existing ID
- Prevents duplicate cards
-
Custom Command Validation
- Empty input: "Please enter a command or use Approve/Reject"
- Dangerous commands: AI still reviews, can re-request approval
6. Implementation Plan
Phase 1: Backend Approval Tracking
- Create
PendingApprovalsManagerclass inserver.js - Add approval request/response WebSocket handlers
- Integrate with
claude-service.jsfor approval requests - Test: Server can track and expire approvals
Phase 2: Frontend Approval Card
- Create
approval-card.jscomponent - Add CSS styling for three-button layout
- Add expandable input for custom instructions
- Integrate into
handleWebSocketMessage() - Test: Card renders correctly, buttons work
Phase 3: Approval Flow
- Wire Approve button → server
- Wire Custom Instructions → expand → send custom command
- Wire Reject → server
- Test: Full round-trip approval
Phase 4: AI Integration
- Modify AI to detect when approval needed
- Send approval request instead of direct execution
- Receive approval response and proceed
- Test: AI properly requests and handles approvals
Files to Modify:
server.js- Add approval manager, WebSocket handlersservices/claude-service.js- AddrequestApproval()methodpublic/claude-ide/chat-functions.js- Handle approval messagespublic/claude-ide/components/approval-card.js- New componentpublic/claude-ide/components/approval-card.css- New styles
Testing Strategy:
- Unit test approval manager
- Integration test full approval flow
- UI test card interactions
- Test edge cases (timeout, custom commands, disconnects)
Success Criteria
- Approval requests show interactive card with three buttons
- Custom instructions option allows command modification
- No accidental mode switching when responding to approvals
- Pending approvals auto-expire after 5 minutes
- AI maintains context through approval flow
- Clear visual feedback throughout process
Future Enhancements
- Approval history log
- Bulk approval for batch operations
- Approval templates for common command patterns
- User preferences (auto-approve safe commands)
- Approval notifications across multiple sessions