VIBN Frontend for Coolify deployment
This commit is contained in:
414
EXTENSION_INTEGRATION.md
Normal file
414
EXTENSION_INTEGRATION.md
Normal file
@@ -0,0 +1,414 @@
|
||||
# Cursor Extension → Vibn Integration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide explains how to connect your Cursor extension to send session data to Vibn's Firebase backend.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Flow
|
||||
|
||||
```
|
||||
Cursor Extension
|
||||
↓
|
||||
User codes & uses AI
|
||||
↓
|
||||
Extension captures:
|
||||
- Model used
|
||||
- Tokens consumed
|
||||
- Files modified
|
||||
- Time elapsed
|
||||
↓
|
||||
Extension sends POST request to Vibn API
|
||||
↓
|
||||
Vibn verifies API key
|
||||
↓
|
||||
Stores session in Firebase
|
||||
↓
|
||||
User sees data in Vibn dashboard
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Extension Configuration
|
||||
|
||||
### Add Settings to Extension
|
||||
|
||||
Users need to configure two settings in your Cursor extension:
|
||||
|
||||
```typescript
|
||||
// extension settings (package.json or settings UI)
|
||||
{
|
||||
"vibn.apiKey": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "Your Vibn API key (get it from vibnai.com/connections)"
|
||||
},
|
||||
"vibn.apiUrl": {
|
||||
"type": "string",
|
||||
"default": "https://vibnai.com/api",
|
||||
"description": "Vibn API endpoint"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Extension Code Changes
|
||||
|
||||
### A. Get User's API Key
|
||||
|
||||
```typescript
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
function getVibnApiKey(): string | undefined {
|
||||
const config = vscode.workspace.getConfiguration('vibn');
|
||||
return config.get<string>('apiKey');
|
||||
}
|
||||
|
||||
function getVibnApiUrl(): string {
|
||||
const config = vscode.workspace.getConfiguration('vibn');
|
||||
return config.get<string>('apiUrl') || 'https://vibnai.com/api';
|
||||
}
|
||||
```
|
||||
|
||||
### B. Send Session Data to Vibn
|
||||
|
||||
```typescript
|
||||
interface SessionData {
|
||||
projectId?: string; // Optional: link to a specific project
|
||||
startTime: string; // ISO 8601 timestamp
|
||||
endTime?: string; // ISO 8601 timestamp (if session ended)
|
||||
duration?: number; // seconds
|
||||
model: string; // e.g., "claude-sonnet-4", "gpt-4", etc.
|
||||
tokensUsed: number;
|
||||
cost: number; // USD
|
||||
filesModified: string[]; // Array of file paths
|
||||
conversationSummary?: string; // Optional: summary of what was done
|
||||
}
|
||||
|
||||
async function sendSessionToVibn(sessionData: SessionData): Promise<boolean> {
|
||||
const apiKey = getVibnApiKey();
|
||||
const apiUrl = getVibnApiUrl();
|
||||
|
||||
if (!apiKey) {
|
||||
console.warn('Vibn API key not configured');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiUrl}/sessions/track`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
apiKey,
|
||||
sessionData,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
console.error('Failed to send session to Vibn:', error);
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log('Session tracked:', result.sessionId);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error sending session to Vibn:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### C. Example Usage
|
||||
|
||||
```typescript
|
||||
// When a session starts
|
||||
const sessionStart = {
|
||||
startTime: new Date().toISOString(),
|
||||
model: 'claude-sonnet-4',
|
||||
tokensUsed: 0,
|
||||
cost: 0,
|
||||
filesModified: [],
|
||||
};
|
||||
|
||||
// When a session ends or periodically
|
||||
const sessionEnd = {
|
||||
...sessionStart,
|
||||
endTime: new Date().toISOString(),
|
||||
duration: 1800, // 30 minutes
|
||||
tokensUsed: 45000,
|
||||
cost: 1.35, // $1.35
|
||||
filesModified: [
|
||||
'/src/components/Button.tsx',
|
||||
'/src/utils/helpers.ts',
|
||||
],
|
||||
conversationSummary: 'Updated Button component styling and added helper functions',
|
||||
};
|
||||
|
||||
await sendSessionToVibn(sessionEnd);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Dual Database Support (Transition Period)
|
||||
|
||||
During migration, send data to both PostgreSQL (current) and Vibn (new):
|
||||
|
||||
```typescript
|
||||
async function trackSession(sessionData: SessionData) {
|
||||
// Send to PostgreSQL (existing)
|
||||
await sendToPostgreSQL(sessionData);
|
||||
|
||||
// Send to Vibn (new)
|
||||
await sendSessionToVibn(sessionData);
|
||||
}
|
||||
```
|
||||
|
||||
This allows:
|
||||
- Existing users to continue working
|
||||
- New Vibn users to get data immediately
|
||||
- Gradual migration path
|
||||
|
||||
---
|
||||
|
||||
## 4. API Endpoint Details
|
||||
|
||||
### Endpoint
|
||||
```
|
||||
POST https://vibnai.com/api/sessions/track
|
||||
```
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"apiKey": "vibn_abc123def456...",
|
||||
"sessionData": {
|
||||
"projectId": "optional-project-id",
|
||||
"startTime": "2025-01-15T10:30:00.000Z",
|
||||
"endTime": "2025-01-15T11:00:00.000Z",
|
||||
"duration": 1800,
|
||||
"model": "claude-sonnet-4",
|
||||
"tokensUsed": 45000,
|
||||
"cost": 1.35,
|
||||
"filesModified": [
|
||||
"/src/components/Button.tsx",
|
||||
"/src/utils/helpers.ts"
|
||||
],
|
||||
"conversationSummary": "Updated Button component styling"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response (Success - 200)
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"sessionId": "abc123def456",
|
||||
"message": "Session tracked successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### Response (Error - 401)
|
||||
```json
|
||||
{
|
||||
"error": "Invalid or inactive API key"
|
||||
}
|
||||
```
|
||||
|
||||
### Response (Error - 500)
|
||||
```json
|
||||
{
|
||||
"error": "Failed to track session",
|
||||
"details": "Error message here"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Testing
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Use localhost for testing
|
||||
POST http://localhost:3000/api/sessions/track
|
||||
```
|
||||
|
||||
### Production
|
||||
```bash
|
||||
# Use production URL
|
||||
POST https://vibnai.com/api/sessions/track
|
||||
```
|
||||
|
||||
### Test API Key
|
||||
For development, users can get their API key from:
|
||||
```
|
||||
http://localhost:3000/marks-account/connections
|
||||
```
|
||||
|
||||
or in production:
|
||||
```
|
||||
https://vibnai.com/[workspace]/connections
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Error Handling
|
||||
|
||||
### Invalid API Key
|
||||
- User sees: "Vibn API key is invalid. Please check your settings."
|
||||
- Extension: Disable Vibn integration silently, fall back to PostgreSQL only
|
||||
|
||||
### Network Error
|
||||
- User sees: Nothing (don't interrupt their work)
|
||||
- Extension: Queue sessions locally, retry later
|
||||
|
||||
### Rate Limiting
|
||||
- If we add rate limiting later, queue and retry with exponential backoff
|
||||
|
||||
---
|
||||
|
||||
## 7. User Experience
|
||||
|
||||
### Good UX:
|
||||
- ✅ Silent background syncing
|
||||
- ✅ No interruptions to coding
|
||||
- ✅ Optional notification when first session is tracked
|
||||
- ✅ Status indicator in extension (optional)
|
||||
|
||||
### Bad UX:
|
||||
- ❌ Blocking user while sending data
|
||||
- ❌ Showing errors for every failed request
|
||||
- ❌ Requiring manual sync
|
||||
|
||||
---
|
||||
|
||||
## 8. Security Best Practices
|
||||
|
||||
### DO:
|
||||
- ✅ Store API key in VSCode settings (encrypted by VS Code)
|
||||
- ✅ Use HTTPS for all requests
|
||||
- ✅ Validate API key before each request
|
||||
- ✅ Include timeout on requests (5-10 seconds)
|
||||
|
||||
### DON'T:
|
||||
- ❌ Log API keys to console
|
||||
- ❌ Store API keys in plaintext files
|
||||
- ❌ Send API keys in URL parameters
|
||||
- ❌ Retry forever on failure
|
||||
|
||||
---
|
||||
|
||||
## 9. Migration Strategy
|
||||
|
||||
### Phase 1: Dual Write (Now)
|
||||
- Send to both PostgreSQL and Vibn
|
||||
- No user impact
|
||||
- Validate Vibn is receiving data correctly
|
||||
|
||||
### Phase 2: Gradual Rollout
|
||||
- New users only use Vibn
|
||||
- Existing users continue with PostgreSQL
|
||||
- Migration tool for old data (optional)
|
||||
|
||||
### Phase 3: Vibn Only
|
||||
- Deprecate PostgreSQL
|
||||
- All users on Vibn
|
||||
- Extension only sends to Vibn
|
||||
|
||||
---
|
||||
|
||||
## 10. Example: Complete Integration
|
||||
|
||||
```typescript
|
||||
// vibn-integration.ts
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class VibnIntegration {
|
||||
private apiKey: string | undefined;
|
||||
private apiUrl: string;
|
||||
private queuedSessions: SessionData[] = [];
|
||||
|
||||
constructor() {
|
||||
this.loadConfig();
|
||||
this.startPeriodicSync();
|
||||
}
|
||||
|
||||
private loadConfig() {
|
||||
const config = vscode.workspace.getConfiguration('vibn');
|
||||
this.apiKey = config.get<string>('apiKey');
|
||||
this.apiUrl = config.get<string>('apiUrl') || 'https://vibnai.com/api';
|
||||
}
|
||||
|
||||
async trackSession(sessionData: SessionData): Promise<void> {
|
||||
if (!this.apiKey) {
|
||||
console.log('Vibn not configured, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiUrl}/sessions/track`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
apiKey: this.apiKey,
|
||||
sessionData,
|
||||
}),
|
||||
signal: AbortSignal.timeout(10000), // 10 second timeout
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log('Session tracked:', result.sessionId);
|
||||
} catch (error) {
|
||||
console.warn('Failed to send to Vibn, queuing:', error);
|
||||
this.queuedSessions.push(sessionData);
|
||||
}
|
||||
}
|
||||
|
||||
private startPeriodicSync() {
|
||||
setInterval(() => this.retryQueuedSessions(), 60000); // Every minute
|
||||
}
|
||||
|
||||
private async retryQueuedSessions() {
|
||||
if (this.queuedSessions.length === 0) return;
|
||||
|
||||
const session = this.queuedSessions.shift();
|
||||
if (session) {
|
||||
await this.trackSession(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton
|
||||
export const vibnIntegration = new VibnIntegration();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check Vibn Dashboard: `https://vibnai.com/[workspace]/connections`
|
||||
- API Docs: `https://vibnai.com/docs/api`
|
||||
- Support: `support@vibnai.com`
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
1. ✅ User gets API key from Vibn connections page
|
||||
2. ✅ User adds API key to Cursor extension settings
|
||||
3. ✅ Extension sends session data to Vibn API
|
||||
4. ✅ Vibn validates API key and stores data in Firebase
|
||||
5. ✅ User sees real-time data in Vibn dashboard
|
||||
|
||||
Simple, secure, and non-intrusive! 🚀
|
||||
|
||||
Reference in New Issue
Block a user