@getvision/core 0.0.0 → 0.0.2-ae8b128-develop

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/core.d.ts +98 -0
  2. package/dist/core.d.ts.map +1 -0
  3. package/dist/core.js +266 -0
  4. package/dist/index.d.ts +8 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +5 -14
  7. package/dist/logs/index.d.ts +3 -0
  8. package/dist/logs/index.d.ts.map +1 -0
  9. package/dist/logs/index.js +2 -0
  10. package/dist/logs/interceptor.d.ts +21 -0
  11. package/dist/logs/interceptor.d.ts.map +1 -0
  12. package/dist/logs/interceptor.js +72 -0
  13. package/dist/logs/store.d.ts +36 -0
  14. package/dist/logs/store.d.ts.map +1 -0
  15. package/dist/logs/store.js +72 -0
  16. package/dist/server/index.d.ts +3 -0
  17. package/dist/server/index.d.ts.map +1 -0
  18. package/dist/server/index.js +2 -0
  19. package/dist/server/jsonrpc.d.ts +21 -0
  20. package/dist/server/jsonrpc.d.ts.map +1 -0
  21. package/dist/server/jsonrpc.js +73 -0
  22. package/dist/server/static.d.ts +10 -0
  23. package/dist/server/static.d.ts.map +1 -0
  24. package/dist/server/static.js +54 -0
  25. package/dist/server/websocket.d.ts +36 -0
  26. package/dist/server/websocket.d.ts.map +1 -0
  27. package/dist/server/websocket.js +153 -0
  28. package/dist/tracing/index.d.ts +3 -0
  29. package/dist/tracing/index.d.ts.map +1 -0
  30. package/dist/tracing/index.js +2 -0
  31. package/dist/tracing/store.d.ts +52 -0
  32. package/dist/tracing/store.d.ts.map +1 -0
  33. package/dist/tracing/store.js +101 -0
  34. package/dist/tracing/tracer.d.ts +28 -0
  35. package/dist/tracing/tracer.d.ts.map +1 -0
  36. package/dist/tracing/tracer.js +64 -0
  37. package/dist/types/adapter-options.d.ts +69 -0
  38. package/dist/types/adapter-options.d.ts.map +1 -0
  39. package/dist/types/adapter-options.js +4 -0
  40. package/dist/types/index.d.ts +193 -0
  41. package/dist/types/index.d.ts.map +1 -0
  42. package/dist/types/index.js +5 -0
  43. package/dist/types/logs.d.ts +14 -0
  44. package/dist/types/logs.d.ts.map +1 -0
  45. package/dist/types/logs.js +1 -0
  46. package/dist/utils/service-detection.d.ts +43 -0
  47. package/dist/utils/service-detection.d.ts.map +1 -0
  48. package/dist/utils/service-detection.js +103 -0
  49. package/dist/utils/zod-utils.d.ts +7 -0
  50. package/dist/utils/zod-utils.d.ts.map +1 -0
  51. package/dist/utils/zod-utils.js +145 -0
  52. package/package.json +20 -8
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Console interceptor to capture logs
3
+ * Preserves original console behavior while storing logs
4
+ */
5
+ export class ConsoleInterceptor {
6
+ originalConsole = {
7
+ log: console.log,
8
+ info: console.info,
9
+ warn: console.warn,
10
+ error: console.error,
11
+ debug: console.debug,
12
+ };
13
+ logStore;
14
+ onLog;
15
+ constructor(logStore, onLog) {
16
+ this.logStore = logStore;
17
+ this.onLog = onLog;
18
+ }
19
+ /**
20
+ * Start intercepting console methods
21
+ */
22
+ start() {
23
+ const intercept = (level, original) => {
24
+ return (...args) => {
25
+ // Call original console method first
26
+ original.apply(console, args);
27
+ // Format message
28
+ const message = args
29
+ .map((arg) => {
30
+ if (typeof arg === 'string')
31
+ return arg;
32
+ if (arg instanceof Error)
33
+ return arg.message;
34
+ try {
35
+ return JSON.stringify(arg);
36
+ }
37
+ catch {
38
+ return String(arg);
39
+ }
40
+ })
41
+ .join(' ');
42
+ // Capture stack trace for errors
43
+ let stack;
44
+ if (level === 'error') {
45
+ const err = args.find((arg) => arg instanceof Error);
46
+ if (err) {
47
+ stack = err.stack;
48
+ }
49
+ }
50
+ // Store log
51
+ this.logStore.addLog(level, message, args, stack);
52
+ // Notify listener
53
+ this.onLog?.(level, message, args, stack);
54
+ };
55
+ };
56
+ console.log = intercept('log', this.originalConsole.log);
57
+ console.info = intercept('info', this.originalConsole.info);
58
+ console.warn = intercept('warn', this.originalConsole.warn);
59
+ console.error = intercept('error', this.originalConsole.error);
60
+ console.debug = intercept('debug', this.originalConsole.debug);
61
+ }
62
+ /**
63
+ * Stop intercepting and restore original console
64
+ */
65
+ stop() {
66
+ console.log = this.originalConsole.log;
67
+ console.info = this.originalConsole.info;
68
+ console.warn = this.originalConsole.warn;
69
+ console.error = this.originalConsole.error;
70
+ console.debug = this.originalConsole.debug;
71
+ }
72
+ }
@@ -0,0 +1,36 @@
1
+ import type { LogEntry, LogLevel } from '../types/logs';
2
+ /**
3
+ * Circular buffer for storing logs
4
+ * Automatically removes oldest entries when limit is reached
5
+ */
6
+ export declare class LogStore {
7
+ private logs;
8
+ private maxLogs;
9
+ constructor(maxLogs?: number);
10
+ /**
11
+ * Add a log entry
12
+ */
13
+ addLog(level: LogLevel, message: string, args?: any[], stack?: string): LogEntry;
14
+ /**
15
+ * Get all logs (newest first)
16
+ */
17
+ getAllLogs(): LogEntry[];
18
+ /**
19
+ * Get logs with filters
20
+ */
21
+ getLogs(filter?: {
22
+ level?: LogLevel;
23
+ search?: string;
24
+ limit?: number;
25
+ since?: number;
26
+ }): LogEntry[];
27
+ /**
28
+ * Clear all logs
29
+ */
30
+ clear(): void;
31
+ /**
32
+ * Get log count
33
+ */
34
+ count(): number;
35
+ }
36
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/logs/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAEvD;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,OAAO,CAAQ;gBAEX,OAAO,SAAS;IAI5B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ;IAoBhF;;OAEG;IACH,UAAU,IAAI,QAAQ,EAAE;IAIxB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,EAAE;QACf,KAAK,CAAC,EAAE,QAAQ,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,GAAG,QAAQ,EAAE;IAgCd;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,KAAK,IAAI,MAAM;CAGhB"}
@@ -0,0 +1,72 @@
1
+ import { nanoid } from 'nanoid';
2
+ /**
3
+ * Circular buffer for storing logs
4
+ * Automatically removes oldest entries when limit is reached
5
+ */
6
+ export class LogStore {
7
+ logs = [];
8
+ maxLogs;
9
+ constructor(maxLogs = 10_000) {
10
+ this.maxLogs = maxLogs;
11
+ }
12
+ /**
13
+ * Add a log entry
14
+ */
15
+ addLog(level, message, args, stack) {
16
+ const entry = {
17
+ id: nanoid(),
18
+ timestamp: Date.now(),
19
+ level,
20
+ message,
21
+ args,
22
+ stack,
23
+ };
24
+ this.logs.push(entry);
25
+ // Remove oldest if we've hit the limit
26
+ if (this.logs.length > this.maxLogs) {
27
+ this.logs.shift();
28
+ }
29
+ return entry;
30
+ }
31
+ /**
32
+ * Get all logs (newest first)
33
+ */
34
+ getAllLogs() {
35
+ return [...this.logs].reverse();
36
+ }
37
+ /**
38
+ * Get logs with filters
39
+ */
40
+ getLogs(filter) {
41
+ let filtered = this.logs;
42
+ if (filter?.level) {
43
+ filtered = filtered.filter((log) => log.level === filter.level);
44
+ }
45
+ if (filter?.search) {
46
+ const searchLower = filter.search.toLowerCase();
47
+ filtered = filtered.filter((log) => log.message.toLowerCase().includes(searchLower) ||
48
+ log.args?.some((arg) => String(arg).toLowerCase().includes(searchLower)));
49
+ }
50
+ if (filter?.since) {
51
+ filtered = filtered.filter((log) => log.timestamp >= (filter.since ?? 0));
52
+ }
53
+ // Newest first
54
+ const reversed = [...filtered].reverse();
55
+ if (filter?.limit) {
56
+ return reversed.slice(0, filter.limit);
57
+ }
58
+ return reversed;
59
+ }
60
+ /**
61
+ * Clear all logs
62
+ */
63
+ clear() {
64
+ this.logs = [];
65
+ }
66
+ /**
67
+ * Get log count
68
+ */
69
+ count() {
70
+ return this.logs.length;
71
+ }
72
+ }
@@ -0,0 +1,3 @@
1
+ export { VisionWebSocketServer } from './websocket';
2
+ export { JsonRpcHandler } from './jsonrpc';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { VisionWebSocketServer } from './websocket';
2
+ export { JsonRpcHandler } from './jsonrpc';
@@ -0,0 +1,21 @@
1
+ /**
2
+ * JSON-RPC 2.0 Handler
3
+ */
4
+ export declare class JsonRpcHandler {
5
+ private methods;
6
+ /**
7
+ * Register a JSON-RPC method
8
+ */
9
+ register(method: string, handler: (params: unknown) => Promise<unknown>): void;
10
+ /**
11
+ * Handle incoming JSON-RPC request
12
+ */
13
+ handle(message: string): Promise<string | null>;
14
+ /**
15
+ * Create a notification (server -> client)
16
+ */
17
+ createNotification(method: string, params?: unknown): string;
18
+ private createSuccessResponse;
19
+ private createErrorResponse;
20
+ }
21
+ //# sourceMappingURL=jsonrpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../../src/server/jsonrpc.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA2D;IAE1E;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAI9E;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAkCrD;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM;IAS5D,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,mBAAmB;CAc5B"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * JSON-RPC 2.0 Handler
3
+ */
4
+ export class JsonRpcHandler {
5
+ methods = new Map();
6
+ /**
7
+ * Register a JSON-RPC method
8
+ */
9
+ register(method, handler) {
10
+ this.methods.set(method, handler);
11
+ }
12
+ /**
13
+ * Handle incoming JSON-RPC request
14
+ */
15
+ async handle(message) {
16
+ let request;
17
+ try {
18
+ request = JSON.parse(message);
19
+ }
20
+ catch (error) {
21
+ return this.createErrorResponse(null, -32700, 'Parse error');
22
+ }
23
+ // Validate JSON-RPC request
24
+ if (request.jsonrpc !== '2.0') {
25
+ return this.createErrorResponse(request.id ?? null, -32600, 'Invalid Request');
26
+ }
27
+ // Handle notification (no response needed)
28
+ if (request.id === undefined) {
29
+ return null;
30
+ }
31
+ // Find and execute method
32
+ const handler = this.methods.get(request.method);
33
+ if (!handler) {
34
+ return this.createErrorResponse(request.id, -32601, `Method not found: ${request.method}`);
35
+ }
36
+ try {
37
+ const result = await handler(request.params);
38
+ return this.createSuccessResponse(request.id, result);
39
+ }
40
+ catch (error) {
41
+ const message = error instanceof Error ? error.message : 'Internal error';
42
+ return this.createErrorResponse(request.id, -32603, message);
43
+ }
44
+ }
45
+ /**
46
+ * Create a notification (server -> client)
47
+ */
48
+ createNotification(method, params) {
49
+ const notification = {
50
+ jsonrpc: '2.0',
51
+ method,
52
+ params,
53
+ };
54
+ return JSON.stringify(notification);
55
+ }
56
+ createSuccessResponse(id, result) {
57
+ const response = {
58
+ jsonrpc: '2.0',
59
+ result,
60
+ id,
61
+ };
62
+ return JSON.stringify(response);
63
+ }
64
+ createErrorResponse(id, code, message, data) {
65
+ const error = { code, message, data };
66
+ const response = {
67
+ jsonrpc: '2.0',
68
+ error,
69
+ id,
70
+ };
71
+ return JSON.stringify(response);
72
+ }
73
+ }
@@ -0,0 +1,10 @@
1
+ import type { IncomingMessage, ServerResponse } from 'http';
2
+ /**
3
+ * Serve static files from the built UI directory
4
+ */
5
+ export declare function serveStatic(req: IncomingMessage, res: ServerResponse, uiPath: string): Promise<boolean>;
6
+ /**
7
+ * Get the path to the UI dist directory
8
+ */
9
+ export declare function getUIPath(): string;
10
+ //# sourceMappingURL=static.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAI3D;;GAEG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAuClB;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAQlC"}
@@ -0,0 +1,54 @@
1
+ import { readFile } from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import { join, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { lookup } from 'mime-types';
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ /**
8
+ * Serve static files from the built UI directory
9
+ */
10
+ export async function serveStatic(req, res, uiPath) {
11
+ let filePath = req.url || '/';
12
+ // Remove query string
13
+ const queryIndex = filePath.indexOf('?');
14
+ if (queryIndex !== -1) {
15
+ filePath = filePath.substring(0, queryIndex);
16
+ }
17
+ // Default to index.html for root and SPA routes
18
+ if (filePath === '/' || !filePath.includes('.')) {
19
+ filePath = '/index.html';
20
+ }
21
+ const fullPath = join(uiPath, filePath);
22
+ // Security: prevent directory traversal
23
+ if (!fullPath.startsWith(uiPath)) {
24
+ return false;
25
+ }
26
+ if (!existsSync(fullPath)) {
27
+ return false;
28
+ }
29
+ try {
30
+ const content = await readFile(fullPath);
31
+ const mimeType = lookup(fullPath) || 'application/octet-stream';
32
+ res.writeHead(200, {
33
+ 'Content-Type': mimeType,
34
+ 'Cache-Control': 'public, max-age=3600',
35
+ });
36
+ res.end(content);
37
+ return true;
38
+ }
39
+ catch (error) {
40
+ console.error('Error serving static file:', error);
41
+ return false;
42
+ }
43
+ }
44
+ /**
45
+ * Get the path to the UI dist directory
46
+ */
47
+ export function getUIPath() {
48
+ // Get the core package root directory
49
+ // __dirname in dev: /Users/.../packages/core/src/server
50
+ // __dirname in prod: /Users/.../packages/core/dist/server
51
+ const coreRoot = join(__dirname, '../..');
52
+ const uiPath = join(coreRoot, 'dist/ui');
53
+ return uiPath;
54
+ }
@@ -0,0 +1,36 @@
1
+ import type { VisionServerOptions, DashboardEvent } from '../types/index';
2
+ /**
3
+ * Vision WebSocket Server
4
+ * Handles real-time communication with the dashboard UI
5
+ * Also serves static UI files on the same port
6
+ */
7
+ export declare class VisionWebSocketServer {
8
+ private httpServer;
9
+ private wss;
10
+ private clients;
11
+ private rpc;
12
+ private options;
13
+ constructor(options?: VisionServerOptions);
14
+ /**
15
+ * Handle HTTP requests (for serving UI)
16
+ */
17
+ private handleHttp;
18
+ private setupServer;
19
+ /**
20
+ * Register a JSON-RPC method handler
21
+ */
22
+ registerMethod(method: string, handler: (params: unknown) => Promise<unknown>): void;
23
+ /**
24
+ * Broadcast an event to all connected clients
25
+ */
26
+ broadcast(event: DashboardEvent): void;
27
+ /**
28
+ * Get number of connected clients
29
+ */
30
+ getClientCount(): number;
31
+ /**
32
+ * Close the server
33
+ */
34
+ close(): Promise<void>;
35
+ }
36
+ //# sourceMappingURL=websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/server/websocket.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEzE;;;;GAIG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,GAAG,CAAgB;IAC3B,OAAO,CAAC,OAAO,CAA+B;gBAElC,OAAO,GAAE,mBAAwB;IA8B7C;;OAEG;YACW,UAAU;IAgCxB,OAAO,CAAC,WAAW;IAkDnB;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAIpF;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAUtC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAiB7B"}
@@ -0,0 +1,153 @@
1
+ import { WebSocketServer, WebSocket } from 'ws';
2
+ import { createServer } from 'http';
3
+ import { JsonRpcHandler } from './jsonrpc';
4
+ import { serveStatic, getUIPath } from './static';
5
+ /**
6
+ * Vision WebSocket Server
7
+ * Handles real-time communication with the dashboard UI
8
+ * Also serves static UI files on the same port
9
+ */
10
+ export class VisionWebSocketServer {
11
+ httpServer;
12
+ wss;
13
+ clients = new Set();
14
+ rpc;
15
+ options;
16
+ constructor(options = {}) {
17
+ this.options = {
18
+ port: options.port ?? 9500,
19
+ host: options.host ?? 'localhost',
20
+ maxTraces: options.maxTraces ?? 1000,
21
+ maxLogs: options.maxLogs ?? 10_000,
22
+ captureConsole: options.captureConsole ?? true,
23
+ enableCors: options.enableCors ?? true,
24
+ };
25
+ this.rpc = new JsonRpcHandler();
26
+ // Create HTTP server first
27
+ this.httpServer = createServer((req, res) => {
28
+ this.handleHttp(req, res).catch(err => {
29
+ console.error('HTTP handler error:', err);
30
+ res.writeHead(500);
31
+ res.end('Internal Server Error');
32
+ });
33
+ });
34
+ // Attach WebSocket server to HTTP server on /ws path
35
+ this.wss = new WebSocketServer({
36
+ server: this.httpServer,
37
+ path: '/ws',
38
+ });
39
+ this.setupServer();
40
+ }
41
+ /**
42
+ * Handle HTTP requests (for serving UI)
43
+ */
44
+ async handleHttp(req, res) {
45
+ // Enable CORS
46
+ if (this.options.enableCors) {
47
+ res.setHeader('Access-Control-Allow-Origin', '*');
48
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
49
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
50
+ }
51
+ if (req.method === 'OPTIONS') {
52
+ res.writeHead(200);
53
+ res.end();
54
+ return;
55
+ }
56
+ // Health check
57
+ if (req.url === '/health') {
58
+ res.writeHead(200, { 'Content-Type': 'application/json' });
59
+ res.end(JSON.stringify({ status: 'ok', clients: this.clients.size }));
60
+ return;
61
+ }
62
+ // Try to serve static files from built UI
63
+ const uiPath = getUIPath();
64
+ const served = await serveStatic(req, res, uiPath);
65
+ if (!served) {
66
+ // No static UI available — return 404 (no legacy HTML fallback)
67
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
68
+ res.end('Vision Dashboard UI not found. Build the UI or ensure adapters are running.');
69
+ }
70
+ }
71
+ setupServer() {
72
+ // Start HTTP server
73
+ this.httpServer.listen(this.options.port, this.options.host, () => {
74
+ console.log(`🚀 Vision Dashboard running at http://${this.options.host}:${this.options.port}`);
75
+ console.log(` WebSocket: ws://${this.options.host}:${this.options.port}/ws`);
76
+ });
77
+ // Handle WebSocket connections
78
+ this.wss.on('connection', (ws) => {
79
+ console.log('🔌 Dashboard client connected');
80
+ this.clients.add(ws);
81
+ ws.on('message', async (data) => {
82
+ const message = data.toString();
83
+ const response = await this.rpc.handle(message);
84
+ if (response) {
85
+ ws.send(response);
86
+ }
87
+ });
88
+ ws.on('close', () => {
89
+ console.log('🔌 Dashboard client disconnected');
90
+ this.clients.delete(ws);
91
+ });
92
+ ws.on('error', (error) => {
93
+ console.error('WebSocket error:', error);
94
+ this.clients.delete(ws);
95
+ });
96
+ // Send initial connection success
97
+ ws.send(JSON.stringify({
98
+ jsonrpc: '2.0',
99
+ method: 'connection.established',
100
+ params: { timestamp: Date.now() },
101
+ }));
102
+ });
103
+ this.wss.on('error', (error) => {
104
+ console.error('WebSocket server error:', error);
105
+ });
106
+ this.httpServer.on('error', (error) => {
107
+ console.error('HTTP server error:', error);
108
+ });
109
+ }
110
+ /**
111
+ * Register a JSON-RPC method handler
112
+ */
113
+ registerMethod(method, handler) {
114
+ this.rpc.register(method, handler);
115
+ }
116
+ /**
117
+ * Broadcast an event to all connected clients
118
+ */
119
+ broadcast(event) {
120
+ const notification = this.rpc.createNotification(event.type, event.data);
121
+ this.clients.forEach((client) => {
122
+ if (client.readyState === WebSocket.OPEN) {
123
+ client.send(notification);
124
+ }
125
+ });
126
+ }
127
+ /**
128
+ * Get number of connected clients
129
+ */
130
+ getClientCount() {
131
+ return this.clients.size;
132
+ }
133
+ /**
134
+ * Close the server
135
+ */
136
+ async close() {
137
+ return new Promise((resolve, reject) => {
138
+ this.clients.forEach((client) => client.close());
139
+ this.clients.clear();
140
+ this.wss.close((wsError) => {
141
+ this.httpServer.close((httpError) => {
142
+ if (wsError || httpError) {
143
+ reject(wsError || httpError);
144
+ }
145
+ else {
146
+ console.log('✅ Vision Dashboard server closed');
147
+ resolve();
148
+ }
149
+ });
150
+ });
151
+ });
152
+ }
153
+ }
@@ -0,0 +1,3 @@
1
+ export { TraceStore } from './store';
2
+ export { Tracer } from './tracer';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tracing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { TraceStore } from './store';
2
+ export { Tracer } from './tracer';
@@ -0,0 +1,52 @@
1
+ import type { Trace, Span } from '../types/index';
2
+ /**
3
+ * In-memory trace store
4
+ * Stores traces with automatic cleanup when max limit is reached
5
+ */
6
+ export declare class TraceStore {
7
+ private traces;
8
+ private maxTraces;
9
+ constructor(maxTraces?: number);
10
+ /**
11
+ * Create a new trace
12
+ */
13
+ createTrace(method: string, path: string): Trace;
14
+ /**
15
+ * Add a trace to the store
16
+ */
17
+ addTrace(trace: Trace): void;
18
+ /**
19
+ * Add a span to a trace
20
+ */
21
+ addSpan(traceId: string, span: Span): void;
22
+ /**
23
+ * Complete a trace with final data
24
+ */
25
+ completeTrace(traceId: string, statusCode: number, duration: number): void;
26
+ /**
27
+ * Get a trace by ID
28
+ */
29
+ getTrace(id: string): Trace | undefined;
30
+ /**
31
+ * Get all traces (newest first)
32
+ */
33
+ getAllTraces(): Trace[];
34
+ /**
35
+ * Get traces with filters
36
+ */
37
+ getTraces(filter?: {
38
+ method?: string;
39
+ statusCode?: number;
40
+ minDuration?: number;
41
+ limit?: number;
42
+ }): Trace[];
43
+ /**
44
+ * Clear all traces
45
+ */
46
+ clear(): void;
47
+ /**
48
+ * Get trace count
49
+ */
50
+ count(): number;
51
+ }
52
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/tracing/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAEjD;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,SAAS,CAAQ;gBAEb,SAAS,SAAO;IAI5B;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK;IAahD;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAY5B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAO1C;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ1E;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIvC;;OAEG;IACH,YAAY,IAAI,KAAK,EAAE;IAIvB;;OAEG;IACH,SAAS,CAAC,MAAM,CAAC,EAAE;QACjB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,GAAG,KAAK,EAAE;IAsBX;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,KAAK,IAAI,MAAM;CAGhB"}