@cnstra/devtools-server 1.1.2 → 1.2.0

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.
package/dist/index.cjs CHANGED
@@ -47,8 +47,8 @@ var CNSDevToolsServer = class {
47
47
  case "topology.query":
48
48
  await this.handleTopologyQuery(ws, msg.requestId, msg.cnsId, msg.appId);
49
49
  break;
50
- case "executions.query":
51
- await this.handleExecutionsQuery(ws, msg);
50
+ case "stimulations.query":
51
+ await this.handleStimulationsQuery(ws, msg);
52
52
  break;
53
53
  case "hops.query":
54
54
  await this.handleHopsQuery(ws, msg);
@@ -79,14 +79,14 @@ var CNSDevToolsServer = class {
79
79
  case "topology":
80
80
  await this.handleTopology(ws, item);
81
81
  break;
82
- case "execution.started":
83
- await this.handleExecutionStarted(ws, item.execution);
82
+ case "stimulation.started":
83
+ await this.handleStimulationStarted(ws, item.stimulation);
84
84
  break;
85
- case "execution.hop":
86
- await this.handleExecutionHop(item.hop);
85
+ case "stimulation.hop":
86
+ await this.handleStimulationHop(item.hop);
87
87
  break;
88
- case "execution.completed":
89
- await this.handleExecutionCompleted(item);
88
+ case "stimulation.completed":
89
+ await this.handleStimulationCompleted(item);
90
90
  break;
91
91
  }
92
92
  }
@@ -114,30 +114,30 @@ var CNSDevToolsServer = class {
114
114
  this.broadcast({ type: "app.connected", app, topology: { cnsId, neurons, collaterals, dendrites } });
115
115
  this.broadcastRaw(JSON.stringify(topologyBroadcast));
116
116
  }
117
- async handleExecutionStarted(ws, execution) {
117
+ async handleStimulationStarted(ws, stimulation) {
118
118
  const appId = this.appSockets.get(ws);
119
119
  if (appId) {
120
120
  const apps = await this.repository.listApps();
121
121
  const app = apps.find((a) => a.id === appId);
122
122
  if (app) await this.repository.upsertApp({ ...app, lastSeenAt: Date.now() });
123
123
  }
124
- await this.repository.saveExecution(execution);
125
- this.broadcast({ type: "execution.started", execution });
124
+ await this.repository.saveStimulation(stimulation);
125
+ this.broadcast({ type: "stimulation.started", stimulation });
126
126
  }
127
- async handleExecutionHop(hop) {
127
+ async handleStimulationHop(hop) {
128
128
  await this.repository.saveHop(hop);
129
- this.broadcast({ type: "execution.hop", hop });
129
+ this.broadcast({ type: "stimulation.hop", hop });
130
130
  }
131
- async handleExecutionCompleted(item) {
132
- await this.repository.completeExecution(
133
- item.executionId,
131
+ async handleStimulationCompleted(item) {
132
+ await this.repository.completeStimulation(
133
+ item.stimulationId,
134
134
  item.completedAt,
135
135
  item.hopCount,
136
136
  item.hasError
137
137
  );
138
138
  this.broadcast({
139
- type: "execution.completed",
140
- executionId: item.executionId,
139
+ type: "stimulation.completed",
140
+ stimulationId: item.stimulationId,
141
141
  completedAt: item.completedAt,
142
142
  hopCount: item.hopCount,
143
143
  hasError: item.hasError
@@ -162,15 +162,15 @@ var CNSDevToolsServer = class {
162
162
  if (appId) snapshots = snapshots.filter((s) => s.appId === appId);
163
163
  this.send(ws, { type: "topology.result", requestId, snapshots });
164
164
  }
165
- async handleExecutionsQuery(ws, msg) {
165
+ async handleStimulationsQuery(ws, msg) {
166
166
  const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : void 0);
167
167
  if (!appId) {
168
- this.send(ws, { type: "executions.result", requestId: msg.requestId, items: [], total: 0, offset: 0 });
168
+ this.send(ws, { type: "stimulations.result", requestId: msg.requestId, items: [], total: 0, offset: 0 });
169
169
  return;
170
170
  }
171
- const { items, total } = await this.repository.getExecutions(appId, msg.filter ?? {});
171
+ const { items, total } = await this.repository.getStimulations(appId, msg.filter ?? {});
172
172
  this.send(ws, {
173
- type: "executions.result",
173
+ type: "stimulations.result",
174
174
  requestId: msg.requestId,
175
175
  items,
176
176
  total,
@@ -178,7 +178,7 @@ var CNSDevToolsServer = class {
178
178
  });
179
179
  }
180
180
  async handleHopsQuery(ws, msg) {
181
- const items = await this.repository.getHops(msg.executionId);
181
+ const items = await this.repository.getHops(msg.stimulationId);
182
182
  this.send(ws, { type: "hops.result", requestId: msg.requestId, items });
183
183
  }
184
184
  async handleReplayStart(ws, msg) {
@@ -188,8 +188,8 @@ var CNSDevToolsServer = class {
188
188
  this.send(ws, { type: "replay.rejected", replayId: msg.replayId, reason: "App not connected" });
189
189
  return;
190
190
  }
191
- const newExecutionId = `${msg.executionId}-replay-${Date.now()}`;
192
- this.send(ws, { type: "replay.accepted", replayId: msg.replayId, newExecutionId });
191
+ const newStimulationId = `${msg.stimulationId}-replay-${Date.now()}`;
192
+ this.send(ws, { type: "replay.accepted", replayId: msg.replayId, newStimulationId });
193
193
  const payload = JSON.stringify(msg);
194
194
  for (const appWs of appSockets) {
195
195
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["CNSDTOAppBatchMessageSchema","CNSDTOClientMessageSchema"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n CNSDTOApp,\n CNSDTOAppBatchMessageSchema,\n CNSDTOClientMessageSchema,\n CNSDTOExecution,\n CNSDTOExecutionFilter,\n CNSDTOHop,\n CNSDTOTopologyMessage,\n} from '@cnstra/devtools-dto';\nimport { WebSocket } from 'ws';\n\n// ─── Repository interface ─────────────────────────────────────────────────────\n\nexport type CNSDTOTopologySnapshot = Omit<CNSDTOTopologyMessage, 'type'>;\n\nexport interface ICNSDevToolsServerRepository {\n // Apps\n upsertApp(app: CNSDTOApp): void | Promise<void>;\n listApps(): CNSDTOApp[] | Promise<CNSDTOApp[]>;\n\n // Topology\n saveTopology(snapshot: CNSDTOTopologySnapshot): void | Promise<void>;\n getTopology(cnsId?: string): CNSDTOTopologySnapshot[] | Promise<CNSDTOTopologySnapshot[]>;\n\n // Executions\n saveExecution(execution: CNSDTOExecution): void | Promise<void>;\n completeExecution(\n executionId: string,\n completedAt: number,\n hopCount: number,\n hasError: boolean\n ): void | Promise<void>;\n getExecutions(\n appId: string,\n filter: CNSDTOExecutionFilter\n ): { items: CNSDTOExecution[]; total: number } | Promise<{ items: CNSDTOExecution[]; total: number }>;\n\n // Hops\n saveHop(hop: CNSDTOHop): void | Promise<void>;\n getHops(executionId: string): CNSDTOHop[] | Promise<CNSDTOHop[]>;\n\n // CNS ↔ App mapping\n addCnsToApp(appId: string, cnsId: string): void | Promise<void>;\n getCnsByApp(appId: string): string[] | Promise<string[]>;\n findAppByCns(cnsId: string): string | undefined | Promise<string | undefined>;\n}\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport class CNSDevToolsServer {\n /** WebSocket → appId (for app clients) */\n private appSockets = new Map<WebSocket, string>();\n /** appId → WebSocket[] (one app may have multiple CNS instances) */\n private appWsByAppId = new Map<string, Set<WebSocket>>();\n /** WebSocket clients that registered as UI clients */\n private uiClients = new Set<WebSocket>();\n\n private metricsTimer?: NodeJS.Timeout;\n private lastCpuUsage = process.cpuUsage();\n private lastCpuTime = Date.now();\n\n constructor(private readonly repository: ICNSDevToolsServerRepository) {}\n\n // ─── Message entry point ─────────────────────────────────────────────────\n\n async handleMessage(\n ws: WebSocket,\n raw: unknown\n ): Promise<void> {\n if (typeof raw !== 'string' && typeof raw !== 'object') return;\n\n let data: unknown;\n try {\n data = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n return;\n }\n\n if (!data || typeof data !== 'object' || !('type' in data)) return;\n const type = (data as any).type as string;\n\n // App batch (topology + execution events)\n if (type === 'batch') {\n const result = CNSDTOAppBatchMessageSchema.safeParse(data);\n if (!result.success) return;\n for (const item of result.data.items) {\n await this.handleAppBatchItem(ws, item);\n }\n return;\n }\n\n // UI client message\n const clientResult = CNSDTOClientMessageSchema.safeParse(data);\n if (!clientResult.success) return;\n const msg = clientResult.data;\n\n switch (msg.type) {\n case 'client.connect':\n await this.handleClientConnect(ws);\n break;\n case 'apps.query':\n await this.handleAppsQuery(ws, msg.requestId);\n break;\n case 'topology.query':\n await this.handleTopologyQuery(ws, msg.requestId, msg.cnsId, msg.appId);\n break;\n case 'executions.query':\n await this.handleExecutionsQuery(ws, msg);\n break;\n case 'hops.query':\n await this.handleHopsQuery(ws, msg);\n break;\n case 'replay.start':\n await this.handleReplayStart(ws, msg);\n break;\n }\n }\n\n addClient(ws: WebSocket): void {\n this.uiClients.add(ws);\n if (this.uiClients.size === 1) this.startMetrics();\n }\n\n removeClient(ws: WebSocket): void {\n this.uiClients.delete(ws);\n this.appSockets.delete(ws);\n if (this.uiClients.size === 0) this.stopMetrics();\n }\n\n async getActiveApps(): Promise<CNSDTOApp[]> {\n return this.repository.listApps();\n }\n\n stop(): void {\n this.stopMetrics();\n }\n\n // ─── App batch item handlers ──────────────────────────────────────────────\n\n private async handleAppBatchItem(ws: WebSocket, item: any): Promise<void> {\n switch (item.type) {\n case 'topology':\n await this.handleTopology(ws, item);\n break;\n case 'execution.started':\n await this.handleExecutionStarted(ws, item.execution);\n break;\n case 'execution.hop':\n await this.handleExecutionHop(item.hop);\n break;\n case 'execution.completed':\n await this.handleExecutionCompleted(item);\n break;\n }\n }\n\n private async handleTopology(ws: WebSocket, msg: any): Promise<void> {\n const { appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites } = msg;\n\n const now = Date.now();\n const app: CNSDTOApp = {\n id: appId,\n name: appName,\n version,\n connectedAt: now,\n lastSeenAt: now,\n };\n\n await this.repository.upsertApp(app);\n await this.repository.addCnsToApp(appId, cnsId);\n await this.repository.saveTopology({ appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites });\n\n // Track app socket\n this.appSockets.set(ws, appId);\n if (!this.appWsByAppId.has(appId)) this.appWsByAppId.set(appId, new Set());\n this.appWsByAppId.get(appId)!.add(ws);\n\n // Broadcast topology + app connected to UI clients\n const topologyBroadcast = {\n type: 'topology.result' as const,\n requestId: '__broadcast__',\n snapshots: await this.repository.getTopology(cnsId),\n };\n\n this.broadcast({ type: 'app.connected', app, topology: { cnsId, neurons, collaterals, dendrites } });\n // Also send topology snapshot so UI can refresh graph\n this.broadcastRaw(JSON.stringify(topologyBroadcast));\n }\n\n private async handleExecutionStarted(ws: WebSocket, execution: CNSDTOExecution): Promise<void> {\n // Update lastSeenAt for the app\n const appId = this.appSockets.get(ws);\n if (appId) {\n const apps = await this.repository.listApps();\n const app = apps.find(a => a.id === appId);\n if (app) await this.repository.upsertApp({ ...app, lastSeenAt: Date.now() });\n }\n\n await this.repository.saveExecution(execution);\n this.broadcast({ type: 'execution.started', execution });\n }\n\n private async handleExecutionHop(hop: CNSDTOHop): Promise<void> {\n await this.repository.saveHop(hop);\n this.broadcast({ type: 'execution.hop', hop });\n }\n\n private async handleExecutionCompleted(item: any): Promise<void> {\n await this.repository.completeExecution(\n item.executionId,\n item.completedAt,\n item.hopCount,\n item.hasError\n );\n this.broadcast({\n type: 'execution.completed',\n executionId: item.executionId,\n completedAt: item.completedAt,\n hopCount: item.hopCount,\n hasError: item.hasError,\n });\n }\n\n // ─── UI client query handlers ─────────────────────────────────────────────\n\n private async handleClientConnect(ws: WebSocket): Promise<void> {\n this.addClient(ws);\n this.send(ws, { type: 'apps.result', requestId: '__init__', items: await this.repository.listApps() });\n this.send(ws, {\n type: 'topology.result',\n requestId: '__init__',\n snapshots: await this.repository.getTopology(),\n });\n }\n\n private async handleAppsQuery(ws: WebSocket, requestId: string): Promise<void> {\n const items = await this.repository.listApps();\n this.send(ws, { type: 'apps.result', requestId, items });\n }\n\n private async handleTopologyQuery(\n ws: WebSocket,\n requestId: string,\n cnsId?: string,\n appId?: string\n ): Promise<void> {\n let snapshots = await this.repository.getTopology(cnsId);\n if (appId) snapshots = snapshots.filter(s => s.appId === appId);\n this.send(ws, { type: 'topology.result', requestId, snapshots });\n }\n\n private async handleExecutionsQuery(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n\n if (!appId) {\n this.send(ws, { type: 'executions.result', requestId: msg.requestId, items: [], total: 0, offset: 0 });\n return;\n }\n\n const { items, total } = await this.repository.getExecutions(appId, msg.filter ?? {});\n this.send(ws, {\n type: 'executions.result',\n requestId: msg.requestId,\n items,\n total,\n offset: msg.filter?.offset ?? 0,\n });\n }\n\n private async handleHopsQuery(ws: WebSocket, msg: any): Promise<void> {\n const items = await this.repository.getHops(msg.executionId);\n this.send(ws, { type: 'hops.result', requestId: msg.requestId, items });\n }\n\n private async handleReplayStart(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n const appSockets = appId ? this.appWsByAppId.get(appId) : undefined;\n\n if (!appSockets || appSockets.size === 0) {\n this.send(ws, { type: 'replay.rejected', replayId: msg.replayId, reason: 'App not connected' });\n return;\n }\n\n const newExecutionId = `${msg.executionId}-replay-${Date.now()}`;\n this.send(ws, { type: 'replay.accepted', replayId: msg.replayId, newExecutionId });\n\n const payload = JSON.stringify(msg);\n for (const appWs of appSockets) {\n try { appWs.send(payload); } catch {}\n }\n }\n\n // ─── Broadcast helpers ────────────────────────────────────────────────────\n\n private broadcast(message: object): void {\n this.broadcastRaw(JSON.stringify(message));\n }\n\n private broadcastRaw(payload: string): void {\n for (const client of this.uiClients) {\n try {\n if ((client as any).readyState === 1) client.send(payload);\n } catch {}\n }\n }\n\n private send(ws: WebSocket, message: object): void {\n try {\n if ((ws as any).readyState === 1) ws.send(JSON.stringify(message));\n } catch {}\n }\n\n // ─── Metrics ──────────────────────────────────────────────────────────────\n\n private startMetrics(): void {\n if (this.metricsTimer) return;\n this.metricsTimer = setInterval(() => {\n const mem = process.memoryUsage();\n const now = Date.now();\n const cpu = process.cpuUsage(this.lastCpuUsage);\n const elapsed = (now - this.lastCpuTime) * 1000;\n const cpuPercent = elapsed > 0 ? ((cpu.user + cpu.system) / elapsed) * 100 : 0;\n this.lastCpuUsage = process.cpuUsage();\n this.lastCpuTime = now;\n\n this.broadcast({\n type: 'server.metrics',\n timestamp: now,\n rssMB: mem.rss / 1024 / 1024,\n heapUsedMB: mem.heapUsed / 1024 / 1024,\n heapTotalMB: mem.heapTotal / 1024 / 1024,\n cpuPercent,\n });\n }, 1000);\n }\n\n private stopMetrics(): void {\n if (this.metricsTimer) {\n clearInterval(this.metricsTimer);\n this.metricsTimer = undefined;\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["CNSDTOAppBatchMessageSchema","CNSDTOClientMessageSchema"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n CNSDTOApp,\n CNSDTOAppBatchMessageSchema,\n CNSDTOClientMessageSchema,\n CNSDTOStimulation,\n CNSDTOStimulationFilter,\n CNSDTOHop,\n CNSDTOTopologyMessage,\n} from '@cnstra/devtools-dto';\nimport { WebSocket } from 'ws';\n\n// ─── Repository interface ─────────────────────────────────────────────────────\n\nexport type CNSDTOTopologySnapshot = Omit<CNSDTOTopologyMessage, 'type'>;\n\nexport interface ICNSDevToolsServerRepository {\n // Apps\n upsertApp(app: CNSDTOApp): void | Promise<void>;\n listApps(): CNSDTOApp[] | Promise<CNSDTOApp[]>;\n\n // Topology\n saveTopology(snapshot: CNSDTOTopologySnapshot): void | Promise<void>;\n getTopology(cnsId?: string): CNSDTOTopologySnapshot[] | Promise<CNSDTOTopologySnapshot[]>;\n\n // Stimulations\n saveStimulation(stimulation: CNSDTOStimulation): void | Promise<void>;\n completeStimulation(\n stimulationId: string,\n completedAt: number,\n hopCount: number,\n hasError: boolean\n ): void | Promise<void>;\n getStimulations(\n appId: string,\n filter: CNSDTOStimulationFilter\n ): { items: CNSDTOStimulation[]; total: number } | Promise<{ items: CNSDTOStimulation[]; total: number }>;\n\n // Hops\n saveHop(hop: CNSDTOHop): void | Promise<void>;\n getHops(stimulationId: string): CNSDTOHop[] | Promise<CNSDTOHop[]>;\n\n // CNS ↔ App mapping\n addCnsToApp(appId: string, cnsId: string): void | Promise<void>;\n getCnsByApp(appId: string): string[] | Promise<string[]>;\n findAppByCns(cnsId: string): string | undefined | Promise<string | undefined>;\n}\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport class CNSDevToolsServer {\n /** WebSocket → appId (for app clients) */\n private appSockets = new Map<WebSocket, string>();\n /** appId → WebSocket[] (one app may have multiple CNS instances) */\n private appWsByAppId = new Map<string, Set<WebSocket>>();\n /** WebSocket clients that registered as UI clients */\n private uiClients = new Set<WebSocket>();\n\n private metricsTimer?: NodeJS.Timeout;\n private lastCpuUsage = process.cpuUsage();\n private lastCpuTime = Date.now();\n\n constructor(private readonly repository: ICNSDevToolsServerRepository) {}\n\n // ─── Message entry point ─────────────────────────────────────────────────\n\n async handleMessage(\n ws: WebSocket,\n raw: unknown\n ): Promise<void> {\n if (typeof raw !== 'string' && typeof raw !== 'object') return;\n\n let data: unknown;\n try {\n data = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n return;\n }\n\n if (!data || typeof data !== 'object' || !('type' in data)) return;\n const type = (data as any).type as string;\n\n // App batch (topology + stimulation events)\n if (type === 'batch') {\n const result = CNSDTOAppBatchMessageSchema.safeParse(data);\n if (!result.success) return;\n for (const item of result.data.items) {\n await this.handleAppBatchItem(ws, item);\n }\n return;\n }\n\n // UI client message\n const clientResult = CNSDTOClientMessageSchema.safeParse(data);\n if (!clientResult.success) return;\n const msg = clientResult.data;\n\n switch (msg.type) {\n case 'client.connect':\n await this.handleClientConnect(ws);\n break;\n case 'apps.query':\n await this.handleAppsQuery(ws, msg.requestId);\n break;\n case 'topology.query':\n await this.handleTopologyQuery(ws, msg.requestId, msg.cnsId, msg.appId);\n break;\n case 'stimulations.query':\n await this.handleStimulationsQuery(ws, msg);\n break;\n case 'hops.query':\n await this.handleHopsQuery(ws, msg);\n break;\n case 'replay.start':\n await this.handleReplayStart(ws, msg);\n break;\n }\n }\n\n addClient(ws: WebSocket): void {\n this.uiClients.add(ws);\n if (this.uiClients.size === 1) this.startMetrics();\n }\n\n removeClient(ws: WebSocket): void {\n this.uiClients.delete(ws);\n this.appSockets.delete(ws);\n if (this.uiClients.size === 0) this.stopMetrics();\n }\n\n async getActiveApps(): Promise<CNSDTOApp[]> {\n return this.repository.listApps();\n }\n\n stop(): void {\n this.stopMetrics();\n }\n\n // ─── App batch item handlers ──────────────────────────────────────────────\n\n private async handleAppBatchItem(ws: WebSocket, item: any): Promise<void> {\n switch (item.type) {\n case 'topology':\n await this.handleTopology(ws, item);\n break;\n case 'stimulation.started':\n await this.handleStimulationStarted(ws, item.stimulation);\n break;\n case 'stimulation.hop':\n await this.handleStimulationHop(item.hop);\n break;\n case 'stimulation.completed':\n await this.handleStimulationCompleted(item);\n break;\n }\n }\n\n private async handleTopology(ws: WebSocket, msg: any): Promise<void> {\n const { appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites } = msg;\n\n const now = Date.now();\n const app: CNSDTOApp = {\n id: appId,\n name: appName,\n version,\n connectedAt: now,\n lastSeenAt: now,\n };\n\n await this.repository.upsertApp(app);\n await this.repository.addCnsToApp(appId, cnsId);\n await this.repository.saveTopology({ appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites });\n\n // Track app socket\n this.appSockets.set(ws, appId);\n if (!this.appWsByAppId.has(appId)) this.appWsByAppId.set(appId, new Set());\n this.appWsByAppId.get(appId)!.add(ws);\n\n // Broadcast topology + app connected to UI clients\n const topologyBroadcast = {\n type: 'topology.result' as const,\n requestId: '__broadcast__',\n snapshots: await this.repository.getTopology(cnsId),\n };\n\n this.broadcast({ type: 'app.connected', app, topology: { cnsId, neurons, collaterals, dendrites } });\n // Also send topology snapshot so UI can refresh graph\n this.broadcastRaw(JSON.stringify(topologyBroadcast));\n }\n\n private async handleStimulationStarted(ws: WebSocket, stimulation: CNSDTOStimulation): Promise<void> {\n // Update lastSeenAt for the app\n const appId = this.appSockets.get(ws);\n if (appId) {\n const apps = await this.repository.listApps();\n const app = apps.find(a => a.id === appId);\n if (app) await this.repository.upsertApp({ ...app, lastSeenAt: Date.now() });\n }\n\n await this.repository.saveStimulation(stimulation);\n this.broadcast({ type: 'stimulation.started', stimulation });\n }\n\n private async handleStimulationHop(hop: CNSDTOHop): Promise<void> {\n await this.repository.saveHop(hop);\n this.broadcast({ type: 'stimulation.hop', hop });\n }\n\n private async handleStimulationCompleted(item: any): Promise<void> {\n await this.repository.completeStimulation(\n item.stimulationId,\n item.completedAt,\n item.hopCount,\n item.hasError\n );\n this.broadcast({\n type: 'stimulation.completed',\n stimulationId: item.stimulationId,\n completedAt: item.completedAt,\n hopCount: item.hopCount,\n hasError: item.hasError,\n });\n }\n\n // ─── UI client query handlers ─────────────────────────────────────────────\n\n private async handleClientConnect(ws: WebSocket): Promise<void> {\n this.addClient(ws);\n this.send(ws, { type: 'apps.result', requestId: '__init__', items: await this.repository.listApps() });\n this.send(ws, {\n type: 'topology.result',\n requestId: '__init__',\n snapshots: await this.repository.getTopology(),\n });\n }\n\n private async handleAppsQuery(ws: WebSocket, requestId: string): Promise<void> {\n const items = await this.repository.listApps();\n this.send(ws, { type: 'apps.result', requestId, items });\n }\n\n private async handleTopologyQuery(\n ws: WebSocket,\n requestId: string,\n cnsId?: string,\n appId?: string\n ): Promise<void> {\n let snapshots = await this.repository.getTopology(cnsId);\n if (appId) snapshots = snapshots.filter(s => s.appId === appId);\n this.send(ws, { type: 'topology.result', requestId, snapshots });\n }\n\n private async handleStimulationsQuery(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n\n if (!appId) {\n this.send(ws, { type: 'stimulations.result', requestId: msg.requestId, items: [], total: 0, offset: 0 });\n return;\n }\n\n const { items, total } = await this.repository.getStimulations(appId, msg.filter ?? {});\n this.send(ws, {\n type: 'stimulations.result',\n requestId: msg.requestId,\n items,\n total,\n offset: msg.filter?.offset ?? 0,\n });\n }\n\n private async handleHopsQuery(ws: WebSocket, msg: any): Promise<void> {\n const items = await this.repository.getHops(msg.stimulationId);\n this.send(ws, { type: 'hops.result', requestId: msg.requestId, items });\n }\n\n private async handleReplayStart(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n const appSockets = appId ? this.appWsByAppId.get(appId) : undefined;\n\n if (!appSockets || appSockets.size === 0) {\n this.send(ws, { type: 'replay.rejected', replayId: msg.replayId, reason: 'App not connected' });\n return;\n }\n\n const newStimulationId = `${msg.stimulationId}-replay-${Date.now()}`;\n this.send(ws, { type: 'replay.accepted', replayId: msg.replayId, newStimulationId });\n\n const payload = JSON.stringify(msg);\n for (const appWs of appSockets) {\n try { appWs.send(payload); } catch {}\n }\n }\n\n // ─── Broadcast helpers ────────────────────────────────────────────────────\n\n private broadcast(message: object): void {\n this.broadcastRaw(JSON.stringify(message));\n }\n\n private broadcastRaw(payload: string): void {\n for (const client of this.uiClients) {\n try {\n if ((client as any).readyState === 1) client.send(payload);\n } catch {}\n }\n }\n\n private send(ws: WebSocket, message: object): void {\n try {\n if ((ws as any).readyState === 1) ws.send(JSON.stringify(message));\n } catch {}\n }\n\n // ─── Metrics ──────────────────────────────────────────────────────────────\n\n private startMetrics(): void {\n if (this.metricsTimer) return;\n this.metricsTimer = setInterval(() => {\n const mem = process.memoryUsage();\n const now = Date.now();\n const cpu = process.cpuUsage(this.lastCpuUsage);\n const elapsed = (now - this.lastCpuTime) * 1000;\n const cpuPercent = elapsed > 0 ? ((cpu.user + cpu.system) / elapsed) * 100 : 0;\n this.lastCpuUsage = process.cpuUsage();\n this.lastCpuTime = now;\n\n this.broadcast({\n type: 'server.metrics',\n timestamp: now,\n rssMB: mem.rss / 1024 / 1024,\n heapUsedMB: mem.heapUsed / 1024 / 1024,\n heapTotalMB: mem.heapTotal / 1024 / 1024,\n cpuPercent,\n });\n }, 1000);\n }\n\n private stopMetrics(): void {\n if (this.metricsTimer) {\n clearInterval(this.metricsTimer);\n this.metricsTimer = undefined;\n }\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CNSDTOApp, CNSDTOExecution, CNSDTOExecutionFilter, CNSDTOHop, CNSDTOTopologyMessage } from '@cnstra/devtools-dto';
1
+ import { CNSDTOApp, CNSDTOStimulation, CNSDTOStimulationFilter, CNSDTOHop, CNSDTOTopologyMessage } from '@cnstra/devtools-dto';
2
2
  import { WebSocket } from 'ws';
3
3
  export type CNSDTOTopologySnapshot = Omit<CNSDTOTopologyMessage, 'type'>;
4
4
  export interface ICNSDevToolsServerRepository {
@@ -6,17 +6,17 @@ export interface ICNSDevToolsServerRepository {
6
6
  listApps(): CNSDTOApp[] | Promise<CNSDTOApp[]>;
7
7
  saveTopology(snapshot: CNSDTOTopologySnapshot): void | Promise<void>;
8
8
  getTopology(cnsId?: string): CNSDTOTopologySnapshot[] | Promise<CNSDTOTopologySnapshot[]>;
9
- saveExecution(execution: CNSDTOExecution): void | Promise<void>;
10
- completeExecution(executionId: string, completedAt: number, hopCount: number, hasError: boolean): void | Promise<void>;
11
- getExecutions(appId: string, filter: CNSDTOExecutionFilter): {
12
- items: CNSDTOExecution[];
9
+ saveStimulation(stimulation: CNSDTOStimulation): void | Promise<void>;
10
+ completeStimulation(stimulationId: string, completedAt: number, hopCount: number, hasError: boolean): void | Promise<void>;
11
+ getStimulations(appId: string, filter: CNSDTOStimulationFilter): {
12
+ items: CNSDTOStimulation[];
13
13
  total: number;
14
14
  } | Promise<{
15
- items: CNSDTOExecution[];
15
+ items: CNSDTOStimulation[];
16
16
  total: number;
17
17
  }>;
18
18
  saveHop(hop: CNSDTOHop): void | Promise<void>;
19
- getHops(executionId: string): CNSDTOHop[] | Promise<CNSDTOHop[]>;
19
+ getHops(stimulationId: string): CNSDTOHop[] | Promise<CNSDTOHop[]>;
20
20
  addCnsToApp(appId: string, cnsId: string): void | Promise<void>;
21
21
  getCnsByApp(appId: string): string[] | Promise<string[]>;
22
22
  findAppByCns(cnsId: string): string | undefined | Promise<string | undefined>;
@@ -40,13 +40,13 @@ export declare class CNSDevToolsServer {
40
40
  stop(): void;
41
41
  private handleAppBatchItem;
42
42
  private handleTopology;
43
- private handleExecutionStarted;
44
- private handleExecutionHop;
45
- private handleExecutionCompleted;
43
+ private handleStimulationStarted;
44
+ private handleStimulationHop;
45
+ private handleStimulationCompleted;
46
46
  private handleClientConnect;
47
47
  private handleAppsQuery;
48
48
  private handleTopologyQuery;
49
- private handleExecutionsQuery;
49
+ private handleStimulationsQuery;
50
50
  private handleHopsQuery;
51
51
  private handleReplayStart;
52
52
  private broadcast;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -45,8 +45,8 @@ var CNSDevToolsServer = class {
45
45
  case "topology.query":
46
46
  await this.handleTopologyQuery(ws, msg.requestId, msg.cnsId, msg.appId);
47
47
  break;
48
- case "executions.query":
49
- await this.handleExecutionsQuery(ws, msg);
48
+ case "stimulations.query":
49
+ await this.handleStimulationsQuery(ws, msg);
50
50
  break;
51
51
  case "hops.query":
52
52
  await this.handleHopsQuery(ws, msg);
@@ -77,14 +77,14 @@ var CNSDevToolsServer = class {
77
77
  case "topology":
78
78
  await this.handleTopology(ws, item);
79
79
  break;
80
- case "execution.started":
81
- await this.handleExecutionStarted(ws, item.execution);
80
+ case "stimulation.started":
81
+ await this.handleStimulationStarted(ws, item.stimulation);
82
82
  break;
83
- case "execution.hop":
84
- await this.handleExecutionHop(item.hop);
83
+ case "stimulation.hop":
84
+ await this.handleStimulationHop(item.hop);
85
85
  break;
86
- case "execution.completed":
87
- await this.handleExecutionCompleted(item);
86
+ case "stimulation.completed":
87
+ await this.handleStimulationCompleted(item);
88
88
  break;
89
89
  }
90
90
  }
@@ -112,30 +112,30 @@ var CNSDevToolsServer = class {
112
112
  this.broadcast({ type: "app.connected", app, topology: { cnsId, neurons, collaterals, dendrites } });
113
113
  this.broadcastRaw(JSON.stringify(topologyBroadcast));
114
114
  }
115
- async handleExecutionStarted(ws, execution) {
115
+ async handleStimulationStarted(ws, stimulation) {
116
116
  const appId = this.appSockets.get(ws);
117
117
  if (appId) {
118
118
  const apps = await this.repository.listApps();
119
119
  const app = apps.find((a) => a.id === appId);
120
120
  if (app) await this.repository.upsertApp({ ...app, lastSeenAt: Date.now() });
121
121
  }
122
- await this.repository.saveExecution(execution);
123
- this.broadcast({ type: "execution.started", execution });
122
+ await this.repository.saveStimulation(stimulation);
123
+ this.broadcast({ type: "stimulation.started", stimulation });
124
124
  }
125
- async handleExecutionHop(hop) {
125
+ async handleStimulationHop(hop) {
126
126
  await this.repository.saveHop(hop);
127
- this.broadcast({ type: "execution.hop", hop });
127
+ this.broadcast({ type: "stimulation.hop", hop });
128
128
  }
129
- async handleExecutionCompleted(item) {
130
- await this.repository.completeExecution(
131
- item.executionId,
129
+ async handleStimulationCompleted(item) {
130
+ await this.repository.completeStimulation(
131
+ item.stimulationId,
132
132
  item.completedAt,
133
133
  item.hopCount,
134
134
  item.hasError
135
135
  );
136
136
  this.broadcast({
137
- type: "execution.completed",
138
- executionId: item.executionId,
137
+ type: "stimulation.completed",
138
+ stimulationId: item.stimulationId,
139
139
  completedAt: item.completedAt,
140
140
  hopCount: item.hopCount,
141
141
  hasError: item.hasError
@@ -160,15 +160,15 @@ var CNSDevToolsServer = class {
160
160
  if (appId) snapshots = snapshots.filter((s) => s.appId === appId);
161
161
  this.send(ws, { type: "topology.result", requestId, snapshots });
162
162
  }
163
- async handleExecutionsQuery(ws, msg) {
163
+ async handleStimulationsQuery(ws, msg) {
164
164
  const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : void 0);
165
165
  if (!appId) {
166
- this.send(ws, { type: "executions.result", requestId: msg.requestId, items: [], total: 0, offset: 0 });
166
+ this.send(ws, { type: "stimulations.result", requestId: msg.requestId, items: [], total: 0, offset: 0 });
167
167
  return;
168
168
  }
169
- const { items, total } = await this.repository.getExecutions(appId, msg.filter ?? {});
169
+ const { items, total } = await this.repository.getStimulations(appId, msg.filter ?? {});
170
170
  this.send(ws, {
171
- type: "executions.result",
171
+ type: "stimulations.result",
172
172
  requestId: msg.requestId,
173
173
  items,
174
174
  total,
@@ -176,7 +176,7 @@ var CNSDevToolsServer = class {
176
176
  });
177
177
  }
178
178
  async handleHopsQuery(ws, msg) {
179
- const items = await this.repository.getHops(msg.executionId);
179
+ const items = await this.repository.getHops(msg.stimulationId);
180
180
  this.send(ws, { type: "hops.result", requestId: msg.requestId, items });
181
181
  }
182
182
  async handleReplayStart(ws, msg) {
@@ -186,8 +186,8 @@ var CNSDevToolsServer = class {
186
186
  this.send(ws, { type: "replay.rejected", replayId: msg.replayId, reason: "App not connected" });
187
187
  return;
188
188
  }
189
- const newExecutionId = `${msg.executionId}-replay-${Date.now()}`;
190
- this.send(ws, { type: "replay.accepted", replayId: msg.replayId, newExecutionId });
189
+ const newStimulationId = `${msg.stimulationId}-replay-${Date.now()}`;
190
+ this.send(ws, { type: "replay.accepted", replayId: msg.replayId, newStimulationId });
191
191
  const payload = JSON.stringify(msg);
192
192
  for (const appWs of appSockets) {
193
193
  try {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n CNSDTOApp,\n CNSDTOAppBatchMessageSchema,\n CNSDTOClientMessageSchema,\n CNSDTOExecution,\n CNSDTOExecutionFilter,\n CNSDTOHop,\n CNSDTOTopologyMessage,\n} from '@cnstra/devtools-dto';\nimport { WebSocket } from 'ws';\n\n// ─── Repository interface ─────────────────────────────────────────────────────\n\nexport type CNSDTOTopologySnapshot = Omit<CNSDTOTopologyMessage, 'type'>;\n\nexport interface ICNSDevToolsServerRepository {\n // Apps\n upsertApp(app: CNSDTOApp): void | Promise<void>;\n listApps(): CNSDTOApp[] | Promise<CNSDTOApp[]>;\n\n // Topology\n saveTopology(snapshot: CNSDTOTopologySnapshot): void | Promise<void>;\n getTopology(cnsId?: string): CNSDTOTopologySnapshot[] | Promise<CNSDTOTopologySnapshot[]>;\n\n // Executions\n saveExecution(execution: CNSDTOExecution): void | Promise<void>;\n completeExecution(\n executionId: string,\n completedAt: number,\n hopCount: number,\n hasError: boolean\n ): void | Promise<void>;\n getExecutions(\n appId: string,\n filter: CNSDTOExecutionFilter\n ): { items: CNSDTOExecution[]; total: number } | Promise<{ items: CNSDTOExecution[]; total: number }>;\n\n // Hops\n saveHop(hop: CNSDTOHop): void | Promise<void>;\n getHops(executionId: string): CNSDTOHop[] | Promise<CNSDTOHop[]>;\n\n // CNS ↔ App mapping\n addCnsToApp(appId: string, cnsId: string): void | Promise<void>;\n getCnsByApp(appId: string): string[] | Promise<string[]>;\n findAppByCns(cnsId: string): string | undefined | Promise<string | undefined>;\n}\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport class CNSDevToolsServer {\n /** WebSocket → appId (for app clients) */\n private appSockets = new Map<WebSocket, string>();\n /** appId → WebSocket[] (one app may have multiple CNS instances) */\n private appWsByAppId = new Map<string, Set<WebSocket>>();\n /** WebSocket clients that registered as UI clients */\n private uiClients = new Set<WebSocket>();\n\n private metricsTimer?: NodeJS.Timeout;\n private lastCpuUsage = process.cpuUsage();\n private lastCpuTime = Date.now();\n\n constructor(private readonly repository: ICNSDevToolsServerRepository) {}\n\n // ─── Message entry point ─────────────────────────────────────────────────\n\n async handleMessage(\n ws: WebSocket,\n raw: unknown\n ): Promise<void> {\n if (typeof raw !== 'string' && typeof raw !== 'object') return;\n\n let data: unknown;\n try {\n data = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n return;\n }\n\n if (!data || typeof data !== 'object' || !('type' in data)) return;\n const type = (data as any).type as string;\n\n // App batch (topology + execution events)\n if (type === 'batch') {\n const result = CNSDTOAppBatchMessageSchema.safeParse(data);\n if (!result.success) return;\n for (const item of result.data.items) {\n await this.handleAppBatchItem(ws, item);\n }\n return;\n }\n\n // UI client message\n const clientResult = CNSDTOClientMessageSchema.safeParse(data);\n if (!clientResult.success) return;\n const msg = clientResult.data;\n\n switch (msg.type) {\n case 'client.connect':\n await this.handleClientConnect(ws);\n break;\n case 'apps.query':\n await this.handleAppsQuery(ws, msg.requestId);\n break;\n case 'topology.query':\n await this.handleTopologyQuery(ws, msg.requestId, msg.cnsId, msg.appId);\n break;\n case 'executions.query':\n await this.handleExecutionsQuery(ws, msg);\n break;\n case 'hops.query':\n await this.handleHopsQuery(ws, msg);\n break;\n case 'replay.start':\n await this.handleReplayStart(ws, msg);\n break;\n }\n }\n\n addClient(ws: WebSocket): void {\n this.uiClients.add(ws);\n if (this.uiClients.size === 1) this.startMetrics();\n }\n\n removeClient(ws: WebSocket): void {\n this.uiClients.delete(ws);\n this.appSockets.delete(ws);\n if (this.uiClients.size === 0) this.stopMetrics();\n }\n\n async getActiveApps(): Promise<CNSDTOApp[]> {\n return this.repository.listApps();\n }\n\n stop(): void {\n this.stopMetrics();\n }\n\n // ─── App batch item handlers ──────────────────────────────────────────────\n\n private async handleAppBatchItem(ws: WebSocket, item: any): Promise<void> {\n switch (item.type) {\n case 'topology':\n await this.handleTopology(ws, item);\n break;\n case 'execution.started':\n await this.handleExecutionStarted(ws, item.execution);\n break;\n case 'execution.hop':\n await this.handleExecutionHop(item.hop);\n break;\n case 'execution.completed':\n await this.handleExecutionCompleted(item);\n break;\n }\n }\n\n private async handleTopology(ws: WebSocket, msg: any): Promise<void> {\n const { appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites } = msg;\n\n const now = Date.now();\n const app: CNSDTOApp = {\n id: appId,\n name: appName,\n version,\n connectedAt: now,\n lastSeenAt: now,\n };\n\n await this.repository.upsertApp(app);\n await this.repository.addCnsToApp(appId, cnsId);\n await this.repository.saveTopology({ appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites });\n\n // Track app socket\n this.appSockets.set(ws, appId);\n if (!this.appWsByAppId.has(appId)) this.appWsByAppId.set(appId, new Set());\n this.appWsByAppId.get(appId)!.add(ws);\n\n // Broadcast topology + app connected to UI clients\n const topologyBroadcast = {\n type: 'topology.result' as const,\n requestId: '__broadcast__',\n snapshots: await this.repository.getTopology(cnsId),\n };\n\n this.broadcast({ type: 'app.connected', app, topology: { cnsId, neurons, collaterals, dendrites } });\n // Also send topology snapshot so UI can refresh graph\n this.broadcastRaw(JSON.stringify(topologyBroadcast));\n }\n\n private async handleExecutionStarted(ws: WebSocket, execution: CNSDTOExecution): Promise<void> {\n // Update lastSeenAt for the app\n const appId = this.appSockets.get(ws);\n if (appId) {\n const apps = await this.repository.listApps();\n const app = apps.find(a => a.id === appId);\n if (app) await this.repository.upsertApp({ ...app, lastSeenAt: Date.now() });\n }\n\n await this.repository.saveExecution(execution);\n this.broadcast({ type: 'execution.started', execution });\n }\n\n private async handleExecutionHop(hop: CNSDTOHop): Promise<void> {\n await this.repository.saveHop(hop);\n this.broadcast({ type: 'execution.hop', hop });\n }\n\n private async handleExecutionCompleted(item: any): Promise<void> {\n await this.repository.completeExecution(\n item.executionId,\n item.completedAt,\n item.hopCount,\n item.hasError\n );\n this.broadcast({\n type: 'execution.completed',\n executionId: item.executionId,\n completedAt: item.completedAt,\n hopCount: item.hopCount,\n hasError: item.hasError,\n });\n }\n\n // ─── UI client query handlers ─────────────────────────────────────────────\n\n private async handleClientConnect(ws: WebSocket): Promise<void> {\n this.addClient(ws);\n this.send(ws, { type: 'apps.result', requestId: '__init__', items: await this.repository.listApps() });\n this.send(ws, {\n type: 'topology.result',\n requestId: '__init__',\n snapshots: await this.repository.getTopology(),\n });\n }\n\n private async handleAppsQuery(ws: WebSocket, requestId: string): Promise<void> {\n const items = await this.repository.listApps();\n this.send(ws, { type: 'apps.result', requestId, items });\n }\n\n private async handleTopologyQuery(\n ws: WebSocket,\n requestId: string,\n cnsId?: string,\n appId?: string\n ): Promise<void> {\n let snapshots = await this.repository.getTopology(cnsId);\n if (appId) snapshots = snapshots.filter(s => s.appId === appId);\n this.send(ws, { type: 'topology.result', requestId, snapshots });\n }\n\n private async handleExecutionsQuery(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n\n if (!appId) {\n this.send(ws, { type: 'executions.result', requestId: msg.requestId, items: [], total: 0, offset: 0 });\n return;\n }\n\n const { items, total } = await this.repository.getExecutions(appId, msg.filter ?? {});\n this.send(ws, {\n type: 'executions.result',\n requestId: msg.requestId,\n items,\n total,\n offset: msg.filter?.offset ?? 0,\n });\n }\n\n private async handleHopsQuery(ws: WebSocket, msg: any): Promise<void> {\n const items = await this.repository.getHops(msg.executionId);\n this.send(ws, { type: 'hops.result', requestId: msg.requestId, items });\n }\n\n private async handleReplayStart(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n const appSockets = appId ? this.appWsByAppId.get(appId) : undefined;\n\n if (!appSockets || appSockets.size === 0) {\n this.send(ws, { type: 'replay.rejected', replayId: msg.replayId, reason: 'App not connected' });\n return;\n }\n\n const newExecutionId = `${msg.executionId}-replay-${Date.now()}`;\n this.send(ws, { type: 'replay.accepted', replayId: msg.replayId, newExecutionId });\n\n const payload = JSON.stringify(msg);\n for (const appWs of appSockets) {\n try { appWs.send(payload); } catch {}\n }\n }\n\n // ─── Broadcast helpers ────────────────────────────────────────────────────\n\n private broadcast(message: object): void {\n this.broadcastRaw(JSON.stringify(message));\n }\n\n private broadcastRaw(payload: string): void {\n for (const client of this.uiClients) {\n try {\n if ((client as any).readyState === 1) client.send(payload);\n } catch {}\n }\n }\n\n private send(ws: WebSocket, message: object): void {\n try {\n if ((ws as any).readyState === 1) ws.send(JSON.stringify(message));\n } catch {}\n }\n\n // ─── Metrics ──────────────────────────────────────────────────────────────\n\n private startMetrics(): void {\n if (this.metricsTimer) return;\n this.metricsTimer = setInterval(() => {\n const mem = process.memoryUsage();\n const now = Date.now();\n const cpu = process.cpuUsage(this.lastCpuUsage);\n const elapsed = (now - this.lastCpuTime) * 1000;\n const cpuPercent = elapsed > 0 ? ((cpu.user + cpu.system) / elapsed) * 100 : 0;\n this.lastCpuUsage = process.cpuUsage();\n this.lastCpuTime = now;\n\n this.broadcast({\n type: 'server.metrics',\n timestamp: now,\n rssMB: mem.rss / 1024 / 1024,\n heapUsedMB: mem.heapUsed / 1024 / 1024,\n heapTotalMB: mem.heapTotal / 1024 / 1024,\n cpuPercent,\n });\n }, 1000);\n }\n\n private stopMetrics(): void {\n if (this.metricsTimer) {\n clearInterval(this.metricsTimer);\n this.metricsTimer = undefined;\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n CNSDTOApp,\n CNSDTOAppBatchMessageSchema,\n CNSDTOClientMessageSchema,\n CNSDTOStimulation,\n CNSDTOStimulationFilter,\n CNSDTOHop,\n CNSDTOTopologyMessage,\n} from '@cnstra/devtools-dto';\nimport { WebSocket } from 'ws';\n\n// ─── Repository interface ─────────────────────────────────────────────────────\n\nexport type CNSDTOTopologySnapshot = Omit<CNSDTOTopologyMessage, 'type'>;\n\nexport interface ICNSDevToolsServerRepository {\n // Apps\n upsertApp(app: CNSDTOApp): void | Promise<void>;\n listApps(): CNSDTOApp[] | Promise<CNSDTOApp[]>;\n\n // Topology\n saveTopology(snapshot: CNSDTOTopologySnapshot): void | Promise<void>;\n getTopology(cnsId?: string): CNSDTOTopologySnapshot[] | Promise<CNSDTOTopologySnapshot[]>;\n\n // Stimulations\n saveStimulation(stimulation: CNSDTOStimulation): void | Promise<void>;\n completeStimulation(\n stimulationId: string,\n completedAt: number,\n hopCount: number,\n hasError: boolean\n ): void | Promise<void>;\n getStimulations(\n appId: string,\n filter: CNSDTOStimulationFilter\n ): { items: CNSDTOStimulation[]; total: number } | Promise<{ items: CNSDTOStimulation[]; total: number }>;\n\n // Hops\n saveHop(hop: CNSDTOHop): void | Promise<void>;\n getHops(stimulationId: string): CNSDTOHop[] | Promise<CNSDTOHop[]>;\n\n // CNS ↔ App mapping\n addCnsToApp(appId: string, cnsId: string): void | Promise<void>;\n getCnsByApp(appId: string): string[] | Promise<string[]>;\n findAppByCns(cnsId: string): string | undefined | Promise<string | undefined>;\n}\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport class CNSDevToolsServer {\n /** WebSocket → appId (for app clients) */\n private appSockets = new Map<WebSocket, string>();\n /** appId → WebSocket[] (one app may have multiple CNS instances) */\n private appWsByAppId = new Map<string, Set<WebSocket>>();\n /** WebSocket clients that registered as UI clients */\n private uiClients = new Set<WebSocket>();\n\n private metricsTimer?: NodeJS.Timeout;\n private lastCpuUsage = process.cpuUsage();\n private lastCpuTime = Date.now();\n\n constructor(private readonly repository: ICNSDevToolsServerRepository) {}\n\n // ─── Message entry point ─────────────────────────────────────────────────\n\n async handleMessage(\n ws: WebSocket,\n raw: unknown\n ): Promise<void> {\n if (typeof raw !== 'string' && typeof raw !== 'object') return;\n\n let data: unknown;\n try {\n data = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n return;\n }\n\n if (!data || typeof data !== 'object' || !('type' in data)) return;\n const type = (data as any).type as string;\n\n // App batch (topology + stimulation events)\n if (type === 'batch') {\n const result = CNSDTOAppBatchMessageSchema.safeParse(data);\n if (!result.success) return;\n for (const item of result.data.items) {\n await this.handleAppBatchItem(ws, item);\n }\n return;\n }\n\n // UI client message\n const clientResult = CNSDTOClientMessageSchema.safeParse(data);\n if (!clientResult.success) return;\n const msg = clientResult.data;\n\n switch (msg.type) {\n case 'client.connect':\n await this.handleClientConnect(ws);\n break;\n case 'apps.query':\n await this.handleAppsQuery(ws, msg.requestId);\n break;\n case 'topology.query':\n await this.handleTopologyQuery(ws, msg.requestId, msg.cnsId, msg.appId);\n break;\n case 'stimulations.query':\n await this.handleStimulationsQuery(ws, msg);\n break;\n case 'hops.query':\n await this.handleHopsQuery(ws, msg);\n break;\n case 'replay.start':\n await this.handleReplayStart(ws, msg);\n break;\n }\n }\n\n addClient(ws: WebSocket): void {\n this.uiClients.add(ws);\n if (this.uiClients.size === 1) this.startMetrics();\n }\n\n removeClient(ws: WebSocket): void {\n this.uiClients.delete(ws);\n this.appSockets.delete(ws);\n if (this.uiClients.size === 0) this.stopMetrics();\n }\n\n async getActiveApps(): Promise<CNSDTOApp[]> {\n return this.repository.listApps();\n }\n\n stop(): void {\n this.stopMetrics();\n }\n\n // ─── App batch item handlers ──────────────────────────────────────────────\n\n private async handleAppBatchItem(ws: WebSocket, item: any): Promise<void> {\n switch (item.type) {\n case 'topology':\n await this.handleTopology(ws, item);\n break;\n case 'stimulation.started':\n await this.handleStimulationStarted(ws, item.stimulation);\n break;\n case 'stimulation.hop':\n await this.handleStimulationHop(item.hop);\n break;\n case 'stimulation.completed':\n await this.handleStimulationCompleted(item);\n break;\n }\n }\n\n private async handleTopology(ws: WebSocket, msg: any): Promise<void> {\n const { appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites } = msg;\n\n const now = Date.now();\n const app: CNSDTOApp = {\n id: appId,\n name: appName,\n version,\n connectedAt: now,\n lastSeenAt: now,\n };\n\n await this.repository.upsertApp(app);\n await this.repository.addCnsToApp(appId, cnsId);\n await this.repository.saveTopology({ appId, cnsId, appName, version, timestamp, neurons, collaterals, dendrites });\n\n // Track app socket\n this.appSockets.set(ws, appId);\n if (!this.appWsByAppId.has(appId)) this.appWsByAppId.set(appId, new Set());\n this.appWsByAppId.get(appId)!.add(ws);\n\n // Broadcast topology + app connected to UI clients\n const topologyBroadcast = {\n type: 'topology.result' as const,\n requestId: '__broadcast__',\n snapshots: await this.repository.getTopology(cnsId),\n };\n\n this.broadcast({ type: 'app.connected', app, topology: { cnsId, neurons, collaterals, dendrites } });\n // Also send topology snapshot so UI can refresh graph\n this.broadcastRaw(JSON.stringify(topologyBroadcast));\n }\n\n private async handleStimulationStarted(ws: WebSocket, stimulation: CNSDTOStimulation): Promise<void> {\n // Update lastSeenAt for the app\n const appId = this.appSockets.get(ws);\n if (appId) {\n const apps = await this.repository.listApps();\n const app = apps.find(a => a.id === appId);\n if (app) await this.repository.upsertApp({ ...app, lastSeenAt: Date.now() });\n }\n\n await this.repository.saveStimulation(stimulation);\n this.broadcast({ type: 'stimulation.started', stimulation });\n }\n\n private async handleStimulationHop(hop: CNSDTOHop): Promise<void> {\n await this.repository.saveHop(hop);\n this.broadcast({ type: 'stimulation.hop', hop });\n }\n\n private async handleStimulationCompleted(item: any): Promise<void> {\n await this.repository.completeStimulation(\n item.stimulationId,\n item.completedAt,\n item.hopCount,\n item.hasError\n );\n this.broadcast({\n type: 'stimulation.completed',\n stimulationId: item.stimulationId,\n completedAt: item.completedAt,\n hopCount: item.hopCount,\n hasError: item.hasError,\n });\n }\n\n // ─── UI client query handlers ─────────────────────────────────────────────\n\n private async handleClientConnect(ws: WebSocket): Promise<void> {\n this.addClient(ws);\n this.send(ws, { type: 'apps.result', requestId: '__init__', items: await this.repository.listApps() });\n this.send(ws, {\n type: 'topology.result',\n requestId: '__init__',\n snapshots: await this.repository.getTopology(),\n });\n }\n\n private async handleAppsQuery(ws: WebSocket, requestId: string): Promise<void> {\n const items = await this.repository.listApps();\n this.send(ws, { type: 'apps.result', requestId, items });\n }\n\n private async handleTopologyQuery(\n ws: WebSocket,\n requestId: string,\n cnsId?: string,\n appId?: string\n ): Promise<void> {\n let snapshots = await this.repository.getTopology(cnsId);\n if (appId) snapshots = snapshots.filter(s => s.appId === appId);\n this.send(ws, { type: 'topology.result', requestId, snapshots });\n }\n\n private async handleStimulationsQuery(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n\n if (!appId) {\n this.send(ws, { type: 'stimulations.result', requestId: msg.requestId, items: [], total: 0, offset: 0 });\n return;\n }\n\n const { items, total } = await this.repository.getStimulations(appId, msg.filter ?? {});\n this.send(ws, {\n type: 'stimulations.result',\n requestId: msg.requestId,\n items,\n total,\n offset: msg.filter?.offset ?? 0,\n });\n }\n\n private async handleHopsQuery(ws: WebSocket, msg: any): Promise<void> {\n const items = await this.repository.getHops(msg.stimulationId);\n this.send(ws, { type: 'hops.result', requestId: msg.requestId, items });\n }\n\n private async handleReplayStart(ws: WebSocket, msg: any): Promise<void> {\n const appId = msg.appId ?? (msg.cnsId ? await this.repository.findAppByCns(msg.cnsId) : undefined);\n const appSockets = appId ? this.appWsByAppId.get(appId) : undefined;\n\n if (!appSockets || appSockets.size === 0) {\n this.send(ws, { type: 'replay.rejected', replayId: msg.replayId, reason: 'App not connected' });\n return;\n }\n\n const newStimulationId = `${msg.stimulationId}-replay-${Date.now()}`;\n this.send(ws, { type: 'replay.accepted', replayId: msg.replayId, newStimulationId });\n\n const payload = JSON.stringify(msg);\n for (const appWs of appSockets) {\n try { appWs.send(payload); } catch {}\n }\n }\n\n // ─── Broadcast helpers ────────────────────────────────────────────────────\n\n private broadcast(message: object): void {\n this.broadcastRaw(JSON.stringify(message));\n }\n\n private broadcastRaw(payload: string): void {\n for (const client of this.uiClients) {\n try {\n if ((client as any).readyState === 1) client.send(payload);\n } catch {}\n }\n }\n\n private send(ws: WebSocket, message: object): void {\n try {\n if ((ws as any).readyState === 1) ws.send(JSON.stringify(message));\n } catch {}\n }\n\n // ─── Metrics ──────────────────────────────────────────────────────────────\n\n private startMetrics(): void {\n if (this.metricsTimer) return;\n this.metricsTimer = setInterval(() => {\n const mem = process.memoryUsage();\n const now = Date.now();\n const cpu = process.cpuUsage(this.lastCpuUsage);\n const elapsed = (now - this.lastCpuTime) * 1000;\n const cpuPercent = elapsed > 0 ? ((cpu.user + cpu.system) / elapsed) * 100 : 0;\n this.lastCpuUsage = process.cpuUsage();\n this.lastCpuTime = now;\n\n this.broadcast({\n type: 'server.metrics',\n timestamp: now,\n rssMB: mem.rss / 1024 / 1024,\n heapUsedMB: mem.heapUsed / 1024 / 1024,\n heapTotalMB: mem.heapTotal / 1024 / 1024,\n cpuPercent,\n });\n }, 1000);\n }\n\n private stopMetrics(): void {\n if (this.metricsTimer) {\n clearInterval(this.metricsTimer);\n this.metricsTimer = undefined;\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnstra/devtools-server",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "CNStra DevTools server (WebSocket only for now)",
5
5
  "keywords": [
6
6
  "cnstra",