mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-13 02:41:50 +08:00
Add comprehensive tests for vector/semantic search functionality
- Implement full coverage tests for Embedder model loading and embedding generation - Add CRUD operations and caching tests for VectorStore - Include cosine similarity computation tests - Validate semantic search accuracy and relevance through various queries - Establish performance benchmarks for embedding and search operations - Ensure edge cases and error handling are covered - Test thread safety and concurrent access scenarios - Verify availability of semantic search dependencies
This commit is contained in:
190
ccw/src/core/websocket.ts
Normal file
190
ccw/src/core/websocket.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
// @ts-nocheck
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
// WebSocket clients for real-time notifications
|
||||
export const wsClients = new Set();
|
||||
|
||||
export function handleWebSocketUpgrade(req, socket, head) {
|
||||
const key = req.headers['sec-websocket-key'];
|
||||
const acceptKey = createHash('sha1')
|
||||
.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
|
||||
.digest('base64');
|
||||
|
||||
const responseHeaders = [
|
||||
'HTTP/1.1 101 Switching Protocols',
|
||||
'Upgrade: websocket',
|
||||
'Connection: Upgrade',
|
||||
`Sec-WebSocket-Accept: ${acceptKey}`,
|
||||
'',
|
||||
''
|
||||
].join('\r\n');
|
||||
|
||||
socket.write(responseHeaders);
|
||||
|
||||
// Add to clients set
|
||||
wsClients.add(socket);
|
||||
console.log(`[WS] Client connected (${wsClients.size} total)`);
|
||||
|
||||
// Handle incoming messages
|
||||
socket.on('data', (buffer) => {
|
||||
try {
|
||||
const frame = parseWebSocketFrame(buffer);
|
||||
if (!frame) return;
|
||||
|
||||
const { opcode, payload } = frame;
|
||||
|
||||
switch (opcode) {
|
||||
case 0x1: // Text frame
|
||||
if (payload) {
|
||||
console.log('[WS] Received:', payload);
|
||||
}
|
||||
break;
|
||||
case 0x8: // Close frame
|
||||
socket.end();
|
||||
break;
|
||||
case 0x9: // Ping frame - respond with Pong
|
||||
const pongFrame = Buffer.alloc(2);
|
||||
pongFrame[0] = 0x8A; // Pong opcode with FIN bit
|
||||
pongFrame[1] = 0x00; // No payload
|
||||
socket.write(pongFrame);
|
||||
break;
|
||||
case 0xA: // Pong frame - ignore
|
||||
break;
|
||||
default:
|
||||
// Ignore other frame types (binary, continuation)
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore parse errors
|
||||
}
|
||||
});
|
||||
|
||||
// Handle disconnect
|
||||
socket.on('close', () => {
|
||||
wsClients.delete(socket);
|
||||
console.log(`[WS] Client disconnected (${wsClients.size} remaining)`);
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
wsClients.delete(socket);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse WebSocket frame (simplified)
|
||||
* Returns { opcode, payload } or null
|
||||
*/
|
||||
export function parseWebSocketFrame(buffer) {
|
||||
if (buffer.length < 2) return null;
|
||||
|
||||
const firstByte = buffer[0];
|
||||
const opcode = firstByte & 0x0f; // Extract opcode (bits 0-3)
|
||||
|
||||
// Opcode types:
|
||||
// 0x0 = continuation, 0x1 = text, 0x2 = binary
|
||||
// 0x8 = close, 0x9 = ping, 0xA = pong
|
||||
|
||||
const secondByte = buffer[1];
|
||||
const isMasked = (secondByte & 0x80) !== 0;
|
||||
let payloadLength = secondByte & 0x7f;
|
||||
|
||||
let offset = 2;
|
||||
if (payloadLength === 126) {
|
||||
payloadLength = buffer.readUInt16BE(2);
|
||||
offset = 4;
|
||||
} else if (payloadLength === 127) {
|
||||
payloadLength = Number(buffer.readBigUInt64BE(2));
|
||||
offset = 10;
|
||||
}
|
||||
|
||||
let mask = null;
|
||||
if (isMasked) {
|
||||
mask = buffer.slice(offset, offset + 4);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
const payload = buffer.slice(offset, offset + payloadLength);
|
||||
|
||||
if (isMasked && mask) {
|
||||
for (let i = 0; i < payload.length; i++) {
|
||||
payload[i] ^= mask[i % 4];
|
||||
}
|
||||
}
|
||||
|
||||
return { opcode, payload: payload.toString('utf8') };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create WebSocket frame
|
||||
*/
|
||||
export function createWebSocketFrame(data) {
|
||||
const payload = Buffer.from(JSON.stringify(data), 'utf8');
|
||||
const length = payload.length;
|
||||
|
||||
let frame;
|
||||
if (length <= 125) {
|
||||
frame = Buffer.alloc(2 + length);
|
||||
frame[0] = 0x81; // Text frame, FIN
|
||||
frame[1] = length;
|
||||
payload.copy(frame, 2);
|
||||
} else if (length <= 65535) {
|
||||
frame = Buffer.alloc(4 + length);
|
||||
frame[0] = 0x81;
|
||||
frame[1] = 126;
|
||||
frame.writeUInt16BE(length, 2);
|
||||
payload.copy(frame, 4);
|
||||
} else {
|
||||
frame = Buffer.alloc(10 + length);
|
||||
frame[0] = 0x81;
|
||||
frame[1] = 127;
|
||||
frame.writeBigUInt64BE(BigInt(length), 2);
|
||||
payload.copy(frame, 10);
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast message to all connected WebSocket clients
|
||||
*/
|
||||
export function broadcastToClients(data) {
|
||||
const frame = createWebSocketFrame(data);
|
||||
|
||||
for (const client of wsClients) {
|
||||
try {
|
||||
client.write(frame);
|
||||
} catch (e) {
|
||||
wsClients.delete(client);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[WS] Broadcast to ${wsClients.size} clients:`, data.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract session ID from file path
|
||||
*/
|
||||
export function extractSessionIdFromPath(filePath) {
|
||||
// Normalize path
|
||||
const normalized = filePath.replace(/\\/g, '/');
|
||||
|
||||
// Look for session pattern: WFS-xxx, WRS-xxx, etc.
|
||||
const sessionMatch = normalized.match(/\/(W[A-Z]S-[^/]+)\//);
|
||||
if (sessionMatch) {
|
||||
return sessionMatch[1];
|
||||
}
|
||||
|
||||
// Look for .workflow/.sessions/xxx pattern
|
||||
const sessionsMatch = normalized.match(/\.workflow\/\.sessions\/([^/]+)/);
|
||||
if (sessionsMatch) {
|
||||
return sessionsMatch[1];
|
||||
}
|
||||
|
||||
// Look for lite-plan/lite-fix pattern
|
||||
const liteMatch = normalized.match(/\.(lite-plan|lite-fix)\/([^/]+)/);
|
||||
if (liteMatch) {
|
||||
return liteMatch[2];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user