gb/VIBE.md
Rodrigo Rodriguez (Pragmatismo) f3bad05e76
Some checks failed
BotServer CI / build (push) Failing after 13s
Fix LXD socket handling in container mode
2026-03-15 18:19:22 -03:00

523 lines
15 KiB
Markdown

# Vibe App Improvement Specification
## Realistic Enhancements Based on Existing Architecture
## Current State Analysis
Vibe is an AI-powered app builder with:
-**Mantis Farm**: Multi-agent system (Mantis #1-4 with EVOLVED/BRED/WILD states)
-**Pipeline Stages**: PLAN → BUILD → REVIEW → DEPLOY → MONITOR
-**Canvas**: Task node visualization with drag-and-drop
-**Integrated Tools**: Code editor, database schema, git, browser, terminal (via modals)
-**Chat Interface**: Real-time WebSocket with Mantis #1
-**Deployment**: Internal (GB Platform) and External (Forgejo ALM)
-**MCP Panel**: Model Context Protocol servers
-**Backend**: `/api/autotask/classify` endpoint for intent processing
## 🎯 Critical Improvements (Fix What's Broken)
### 1. Fix Task Node Rendering
**Problem:** Nodes don't persist after page refresh
**Fix:**
```javascript
// Save nodes to localStorage
function saveCanvasState() {
localStorage.setItem('vibe_canvas_state', JSON.stringify({
nodes: taskNodes,
project: currentProject,
timestamp: Date.now()
}));
}
// Restore on load
function restoreCanvasState() {
const saved = localStorage.getItem('vibe_canvas_state');
if (!saved) return;
const state = JSON.parse(saved);
currentProject = state.project;
state.nodes.forEach((node, i) => {
setTimeout(() => {
addTaskNode(node.title, node.description, node.meta);
}, i * 200);
});
}
// Call on init
document.addEventListener('DOMContentLoaded', restoreCanvasState);
```
### 2. Make Editor Actually Editable
**Problem:** Editor modal loads but can't edit files
**Fix:**
```html
<!-- Replace basic editor with Monaco -->
<div id="vibeEditorModal" class="vibe-editor-modal">
<div class="editor-header">
<span id="currentFileName">untitled.txt</span>
<div class="editor-actions">
<button onclick="saveFile()">💾 Save</button>
<button onclick="closeEditor()"></button>
</div>
</div>
<div id="monacoEditor" style="height: calc(100% - 50px);"></div>
</div>
<script src="/suite/js/vendor/monaco-editor/min/vs/loader.js"></script>
<script>
let editor;
function initMonaco() {
require.config({ paths: { vs: '/suite/js/vendor/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function() {
editor = monaco.editor.create(document.getElementById('monacoEditor'), {
value: '',
language: 'javascript',
theme: 'vs-dark',
automaticLayout: true
});
});
}
async function saveFile() {
const content = editor.getValue();
const filename = document.getElementById('currentFileName').textContent;
await fetch('/api/vibe/file', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ filename, content })
});
vibeAddMsg('system', `✅ Saved ${filename}`);
}
</script>
```
### 3. Connect Database Schema Tool
**Problem:** Database modal shows but doesn't interact with actual DB
**Fix:**
```javascript
async function loadDatabaseSchema() {
const response = await fetch('/api/vibe/schema');
const { tables } = await response.json();
const schemaView = document.getElementById('databaseSchemaView');
schemaView.innerHTML = tables.map(table => `
<div class="table-card">
<h4>${table.name}</h4>
<div class="columns">
${table.columns.map(col => `
<div class="column">
<span class="col-name">${col.name}</span>
<span class="col-type">${col.type}</span>
</div>
`).join('')}
</div>
</div>
`).join('');
}
async function createTable() {
const tableName = prompt('Table name:');
if (!tableName) return;
const response = await fetch('/api/vibe/schema/table', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: tableName,
columns: [
{ name: 'id', type: 'UUID PRIMARY KEY' },
{ name: 'created_at', type: 'TIMESTAMP DEFAULT NOW()' }
]
})
});
if (response.ok) {
vibeAddMsg('system', `✅ Created table ${tableName}`);
loadDatabaseSchema();
}
}
```
### 4. Fix Terminal Integration
**Problem:** Terminal doesn't execute commands
**Fix:**
```javascript
// WebSocket for terminal
const terminalWs = new WebSocket(`ws://${location.host}/ws/terminal`);
const terminalOutput = document.getElementById('terminalOutput');
terminalWs.onmessage = (event) => {
const line = document.createElement('div');
line.textContent = event.data;
terminalOutput.appendChild(line);
terminalOutput.scrollTop = terminalOutput.scrollHeight;
};
function executeCommand(cmd) {
terminalWs.send(JSON.stringify({ command: cmd }));
}
document.getElementById('terminalInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
const cmd = e.target.value;
executeCommand(cmd);
e.target.value = '';
}
});
```
### 5. Make Git Status Actually Work
**Problem:** Git panel shows but doesn't show real status
**Fix:**
```javascript
async function loadGitStatus() {
const response = await fetch('/api/vibe/git/status');
const { branch, changes } = await response.json();
document.getElementById('gitBranch').textContent = branch;
const changesList = document.getElementById('gitChanges');
changesList.innerHTML = changes.map(change => `
<div class="git-change ${change.status}">
<span class="change-status">${change.status}</span>
<span class="change-file">${change.file}</span>
</div>
`).join('');
}
async function gitCommit() {
const message = prompt('Commit message:');
if (!message) return;
await fetch('/api/vibe/git/commit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
});
vibeAddMsg('system', `✅ Committed: ${message}`);
loadGitStatus();
}
```
## 🚀 High-Value Additions
### 6. File Tree in Editor
**What:** Show project structure, click to open files
**Implementation:**
```html
<div class="editor-sidebar">
<div class="file-tree" id="fileTree">
<!-- Populated dynamically -->
</div>
</div>
<script>
async function loadFileTree() {
const response = await fetch('/api/vibe/files');
const { files } = await response.json();
const tree = buildTree(files);
document.getElementById('fileTree').innerHTML = renderTree(tree);
}
function renderTree(node, level = 0) {
if (node.type === 'file') {
return `
<div class="tree-item file" style="padding-left: ${level * 16}px"
onclick="openFile('${node.path}')">
📄 ${node.name}
</div>
`;
}
return `
<div class="tree-item folder" style="padding-left: ${level * 16}px">
📁 ${node.name}
${node.children.map(child => renderTree(child, level + 1)).join('')}
</div>
`;
}
async function openFile(path) {
const response = await fetch(`/api/vibe/file?path=${encodeURIComponent(path)}`);
const content = await response.text();
editor.setValue(content);
document.getElementById('currentFileName').textContent = path.split('/').pop();
}
</script>
```
### 7. Keyboard Shortcuts
**What:** Cmd+S to save, Cmd+K for command palette
**Implementation:**
```javascript
document.addEventListener('keydown', (e) => {
// Cmd/Ctrl + S: Save
if ((e.metaKey || e.ctrlKey) && e.key === 's') {
e.preventDefault();
saveFile();
}
// Cmd/Ctrl + K: Command palette
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
openCommandPalette();
}
// Cmd/Ctrl + B: Toggle sidebar
if ((e.metaKey || e.ctrlKey) && e.key === 'b') {
e.preventDefault();
toggleSidebar();
}
// Escape: Close modals
if (e.key === 'Escape') {
closeAllModals();
}
});
```
### 8. Quick Command Palette
**What:** Fuzzy search for all actions
**Implementation:**
```html
<div id="commandPalette" class="command-palette" style="display: none;">
<input type="text" id="commandInput" placeholder="Type a command...">
<div class="command-results" id="commandResults"></div>
</div>
<script>
const commands = [
{ label: 'Save File', action: saveFile, shortcut: 'Cmd+S' },
{ label: 'New File', action: newFile, shortcut: 'Cmd+N' },
{ label: 'Open Terminal', action: () => openModal('terminal') },
{ label: 'Git Status', action: () => openModal('git') },
{ label: 'Database Schema', action: () => openModal('database') },
{ label: 'Deploy App', action: showDeploymentModal }
];
function openCommandPalette() {
document.getElementById('commandPalette').style.display = 'flex';
document.getElementById('commandInput').focus();
}
document.getElementById('commandInput').addEventListener('input', (e) => {
const query = e.target.value.toLowerCase();
const filtered = commands.filter(cmd =>
cmd.label.toLowerCase().includes(query)
);
document.getElementById('commandResults').innerHTML = filtered.map(cmd => `
<div class="command-item" onclick="executeCommand('${cmd.label}')">
<span>${cmd.label}</span>
<span class="shortcut">${cmd.shortcut || ''}</span>
</div>
`).join('');
});
</script>
```
### 9. Task Node Actions
**What:** Click node to see details, edit, or delete
**Implementation:**
```javascript
function addTaskNode(title, description, meta) {
// ... existing code ...
node.onclick = () => showNodeDetails(nodeIdCounter);
return node;
}
function showNodeDetails(nodeId) {
const node = taskNodes.find(n => n.id === nodeId);
if (!node) return;
const modal = document.createElement('div');
modal.className = 'node-details-modal';
modal.innerHTML = `
<div class="modal-content">
<h3>${node.title}</h3>
<p>${node.description}</p>
<div class="node-files">
<h4>Files</h4>
${(node.meta.fileList || []).map(f => `<div>📄 ${f}</div>`).join('')}
</div>
<div class="node-actions">
<button onclick="editNode(${nodeId})">✏️ Edit</button>
<button onclick="deleteNode(${nodeId})">🗑️ Delete</button>
<button onclick="closeModal()">Close</button>
</div>
</div>
`;
document.body.appendChild(modal);
}
```
### 10. Deployment Status Tracking
**What:** Show real-time deployment progress
**Implementation:**
```javascript
async function executeDeployment() {
const deployButton = document.getElementById('deployButton');
deployButton.textContent = 'Deploying...';
deployButton.disabled = true;
// Create progress tracker
const progressDiv = document.createElement('div');
progressDiv.className = 'deployment-progress';
progressDiv.innerHTML = `
<div class="progress-step active">📦 Building...</div>
<div class="progress-step">🚀 Deploying...</div>
<div class="progress-step">✅ Complete</div>
`;
document.querySelector('.vibe-deployment-panel').appendChild(progressDiv);
// WebSocket for deployment events
const deployWs = new WebSocket(`ws://${location.host}/ws/deployment`);
deployWs.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.step === 'building') {
updateProgressStep(0, 'active');
} else if (data.step === 'deploying') {
updateProgressStep(0, 'complete');
updateProgressStep(1, 'active');
} else if (data.step === 'complete') {
updateProgressStep(1, 'complete');
updateProgressStep(2, 'complete');
vibeAddMsg('bot', `✅ Deployed to: ${data.url}`);
deployButton.textContent = 'Deploy Now';
deployButton.disabled = false;
}
};
// Start deployment
const response = await fetch('/api/deployment/deploy', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(getDeploymentConfig())
});
}
```
## 🔧 Backend API Requirements
```
# File Operations
GET /api/vibe/files - List project files
GET /api/vibe/file?path=... - Get file content
POST /api/vibe/file - Save file
DELETE /api/vibe/file?path=... - Delete file
# Database
GET /api/vibe/schema - Get database schema
POST /api/vibe/schema/table - Create table
POST /api/vibe/schema/query - Execute SQL query
# Git
GET /api/vibe/git/status - Get git status
POST /api/vibe/git/commit - Commit changes
POST /api/vibe/git/push - Push to remote
# Terminal
WS /ws/terminal - Terminal WebSocket
# Deployment
POST /api/deployment/deploy - Deploy app
WS /ws/deployment - Deployment progress
```
## 📊 Database Schema
```sql
-- Store canvas state
CREATE TABLE vibe_projects (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
name VARCHAR(255),
canvas_state JSONB, -- nodes, connections
files JSONB, -- file tree
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- Track deployments
CREATE TABLE vibe_deployments (
id UUID PRIMARY KEY,
project_id UUID REFERENCES vibe_projects(id),
target VARCHAR(50), -- internal, external
status VARCHAR(50), -- building, deploying, complete, failed
url TEXT,
logs TEXT,
deployed_at TIMESTAMP
);
```
## ✅ Implementation Priority
### Phase 1: Fix Broken Features (Week 1)
1. ✅ Task node persistence
2. ✅ Monaco editor integration
3. ✅ Database schema viewer
4. ✅ Terminal execution
5. ✅ Git status display
### Phase 2: Essential Features (Week 2)
6. ✅ File tree navigation
7. ✅ Keyboard shortcuts
8. ✅ Command palette
9. ✅ Node detail view
10. ✅ Deployment tracking
### Phase 3: Polish (Week 3)
- Error handling
- Loading states
- Empty states
- Responsive design
- Performance optimization
## 🧪 Testing Checklist
- [ ] Create new project
- [ ] Add task nodes to canvas
- [ ] Refresh page - nodes persist
- [ ] Open file in editor
- [ ] Edit and save file
- [ ] View database schema
- [ ] Execute terminal command
- [ ] Check git status
- [ ] Commit changes
- [ ] Deploy app (internal)
- [ ] Deploy app (external)
- [ ] Use keyboard shortcuts
- [ ] Search command palette
## 🎯 Success Metrics
- Canvas state persists across sessions
- Editor can open/edit/save files
- All tool modals are functional
- Deployment completes successfully
- No console errors
- Fast load time (< 2s)