@blackms/aistack 1.0.13 → 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.
Files changed (113) hide show
  1. package/README.md +16 -0
  2. package/dist/cli/commands/index.d.ts +1 -0
  3. package/dist/cli/commands/index.d.ts.map +1 -1
  4. package/dist/cli/commands/index.js +1 -0
  5. package/dist/cli/commands/index.js.map +1 -1
  6. package/dist/cli/commands/web.d.ts +6 -0
  7. package/dist/cli/commands/web.d.ts.map +1 -0
  8. package/dist/cli/commands/web.js +79 -0
  9. package/dist/cli/commands/web.js.map +1 -0
  10. package/dist/cli/index.js +2 -1
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/memory/index.d.ts +23 -1
  17. package/dist/memory/index.d.ts.map +1 -1
  18. package/dist/memory/index.js +54 -0
  19. package/dist/memory/index.js.map +1 -1
  20. package/dist/memory/sqlite-store.d.ts +26 -1
  21. package/dist/memory/sqlite-store.d.ts.map +1 -1
  22. package/dist/memory/sqlite-store.js +356 -0
  23. package/dist/memory/sqlite-store.js.map +1 -1
  24. package/dist/types.d.ts +56 -0
  25. package/dist/types.d.ts.map +1 -1
  26. package/dist/types.js +9 -0
  27. package/dist/types.js.map +1 -1
  28. package/dist/utils/validation.d.ts +2 -2
  29. package/dist/web/index.d.ts +8 -0
  30. package/dist/web/index.d.ts.map +1 -0
  31. package/dist/web/index.js +8 -0
  32. package/dist/web/index.js.map +1 -0
  33. package/dist/web/middleware/auth.d.ts +21 -0
  34. package/dist/web/middleware/auth.d.ts.map +1 -0
  35. package/dist/web/middleware/auth.js +31 -0
  36. package/dist/web/middleware/auth.js.map +1 -0
  37. package/dist/web/middleware/cors.d.ts +7 -0
  38. package/dist/web/middleware/cors.d.ts.map +1 -0
  39. package/dist/web/middleware/cors.js +28 -0
  40. package/dist/web/middleware/cors.js.map +1 -0
  41. package/dist/web/middleware/error.d.ts +16 -0
  42. package/dist/web/middleware/error.d.ts.map +1 -0
  43. package/dist/web/middleware/error.js +51 -0
  44. package/dist/web/middleware/error.js.map +1 -0
  45. package/dist/web/middleware/index.d.ts +7 -0
  46. package/dist/web/middleware/index.d.ts.map +1 -0
  47. package/dist/web/middleware/index.js +7 -0
  48. package/dist/web/middleware/index.js.map +1 -0
  49. package/dist/web/router.d.ts +40 -0
  50. package/dist/web/router.d.ts.map +1 -0
  51. package/dist/web/router.js +162 -0
  52. package/dist/web/router.js.map +1 -0
  53. package/dist/web/routes/agents.d.ts +7 -0
  54. package/dist/web/routes/agents.d.ts.map +1 -0
  55. package/dist/web/routes/agents.js +182 -0
  56. package/dist/web/routes/agents.js.map +1 -0
  57. package/dist/web/routes/filesystem.d.ts +7 -0
  58. package/dist/web/routes/filesystem.d.ts.map +1 -0
  59. package/dist/web/routes/filesystem.js +212 -0
  60. package/dist/web/routes/filesystem.js.map +1 -0
  61. package/dist/web/routes/index.d.ts +13 -0
  62. package/dist/web/routes/index.d.ts.map +1 -0
  63. package/dist/web/routes/index.js +13 -0
  64. package/dist/web/routes/index.js.map +1 -0
  65. package/dist/web/routes/memory.d.ts +7 -0
  66. package/dist/web/routes/memory.d.ts.map +1 -0
  67. package/dist/web/routes/memory.js +146 -0
  68. package/dist/web/routes/memory.js.map +1 -0
  69. package/dist/web/routes/projects.d.ts +7 -0
  70. package/dist/web/routes/projects.d.ts.map +1 -0
  71. package/dist/web/routes/projects.js +296 -0
  72. package/dist/web/routes/projects.js.map +1 -0
  73. package/dist/web/routes/sessions.d.ts +7 -0
  74. package/dist/web/routes/sessions.d.ts.map +1 -0
  75. package/dist/web/routes/sessions.js +75 -0
  76. package/dist/web/routes/sessions.js.map +1 -0
  77. package/dist/web/routes/specifications.d.ts +7 -0
  78. package/dist/web/routes/specifications.d.ts.map +1 -0
  79. package/dist/web/routes/specifications.js +267 -0
  80. package/dist/web/routes/specifications.js.map +1 -0
  81. package/dist/web/routes/system.d.ts +7 -0
  82. package/dist/web/routes/system.d.ts.map +1 -0
  83. package/dist/web/routes/system.js +147 -0
  84. package/dist/web/routes/system.js.map +1 -0
  85. package/dist/web/routes/tasks.d.ts +7 -0
  86. package/dist/web/routes/tasks.d.ts.map +1 -0
  87. package/dist/web/routes/tasks.js +188 -0
  88. package/dist/web/routes/tasks.js.map +1 -0
  89. package/dist/web/routes/workflows.d.ts +7 -0
  90. package/dist/web/routes/workflows.d.ts.map +1 -0
  91. package/dist/web/routes/workflows.js +132 -0
  92. package/dist/web/routes/workflows.js.map +1 -0
  93. package/dist/web/server.d.ts +49 -0
  94. package/dist/web/server.d.ts.map +1 -0
  95. package/dist/web/server.js +236 -0
  96. package/dist/web/server.js.map +1 -0
  97. package/dist/web/types.d.ts +191 -0
  98. package/dist/web/types.d.ts.map +1 -0
  99. package/dist/web/types.js +5 -0
  100. package/dist/web/types.js.map +1 -0
  101. package/dist/web/websocket/event-bridge.d.ts +115 -0
  102. package/dist/web/websocket/event-bridge.d.ts.map +1 -0
  103. package/dist/web/websocket/event-bridge.js +138 -0
  104. package/dist/web/websocket/event-bridge.js.map +1 -0
  105. package/dist/web/websocket/handler.d.ts +23 -0
  106. package/dist/web/websocket/handler.d.ts.map +1 -0
  107. package/dist/web/websocket/handler.js +282 -0
  108. package/dist/web/websocket/handler.js.map +1 -0
  109. package/dist/web/websocket/index.d.ts +6 -0
  110. package/dist/web/websocket/index.d.ts.map +1 -0
  111. package/dist/web/websocket/index.js +6 -0
  112. package/dist/web/websocket/index.js.map +1 -0
  113. package/package.json +6 -2
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Event bridge - connects internal EventEmitters to WebSocket clients
3
+ */
4
+ import { EventEmitter } from 'node:events';
5
+ export declare const agentEvents: EventEmitter<[never]>;
6
+ export interface AgentSpawnedEvent {
7
+ id: string;
8
+ type: string;
9
+ name: string;
10
+ }
11
+ export interface AgentStoppedEvent {
12
+ id: string;
13
+ }
14
+ export interface AgentStatusEvent {
15
+ id: string;
16
+ status: string;
17
+ }
18
+ export interface TaskCreatedEvent {
19
+ task: unknown;
20
+ }
21
+ export interface TaskAssignedEvent {
22
+ taskId: string;
23
+ agentId: string;
24
+ }
25
+ export interface TaskCompletedEvent {
26
+ taskId: string;
27
+ result?: unknown;
28
+ }
29
+ export interface WorkflowStartEvent {
30
+ workflowId: string;
31
+ config: unknown;
32
+ }
33
+ export interface WorkflowPhaseEvent {
34
+ workflowId: string;
35
+ phase: string;
36
+ status: string;
37
+ }
38
+ export interface WorkflowCompleteEvent {
39
+ workflowId: string;
40
+ report: unknown;
41
+ }
42
+ export interface WorkflowErrorEvent {
43
+ workflowId: string;
44
+ error: string;
45
+ }
46
+ export interface MessageReceivedEvent {
47
+ from: string;
48
+ to: string;
49
+ content: string;
50
+ }
51
+ export interface ProjectCreatedEvent {
52
+ id: string;
53
+ name: string;
54
+ path: string;
55
+ }
56
+ export interface ProjectUpdatedEvent {
57
+ id: string;
58
+ changes: Record<string, unknown>;
59
+ }
60
+ export interface ProjectTaskCreatedEvent {
61
+ projectId: string;
62
+ taskId: string;
63
+ title: string;
64
+ }
65
+ export interface ProjectTaskPhaseEvent {
66
+ projectId: string;
67
+ taskId: string;
68
+ fromPhase: string;
69
+ toPhase: string;
70
+ }
71
+ export interface SpecCreatedEvent {
72
+ id: string;
73
+ taskId: string;
74
+ type: string;
75
+ title: string;
76
+ }
77
+ export interface SpecStatusEvent {
78
+ id: string;
79
+ status: string;
80
+ reviewedBy?: string;
81
+ }
82
+ export interface AgentProgressEvent {
83
+ agentId: string;
84
+ taskId: string;
85
+ progress: number;
86
+ message?: string;
87
+ }
88
+ export type EventName = 'agent:spawned' | 'agent:stopped' | 'agent:status' | 'agent:progress' | 'task:created' | 'task:assigned' | 'task:completed' | 'workflow:start' | 'workflow:phase' | 'workflow:complete' | 'workflow:error' | 'workflow:finding' | 'message:received' | 'project:created' | 'project:updated' | 'project:task:created' | 'project:task:phase' | 'spec:created' | 'spec:status';
89
+ export declare class EventBridge {
90
+ private listeners;
91
+ constructor();
92
+ /**
93
+ * Subscribe to all events
94
+ */
95
+ subscribe(callback: (event: string, data: unknown) => void): () => void;
96
+ /**
97
+ * Subscribe to specific event
98
+ */
99
+ subscribeToEvent(event: string, callback: (data: unknown) => void): () => void;
100
+ /**
101
+ * Broadcast event to all subscribers
102
+ */
103
+ broadcast(event: string, data: unknown): void;
104
+ /**
105
+ * Get subscriber count for an event
106
+ */
107
+ getSubscriberCount(event?: string): number;
108
+ /**
109
+ * Clear all listeners
110
+ */
111
+ clear(): void;
112
+ }
113
+ export declare function getEventBridge(): EventBridge;
114
+ export declare function resetEventBridge(): void;
115
+ //# sourceMappingURL=event-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bridge.d.ts","sourceRoot":"","sources":["../../../src/web/websocket/event-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Event bridge - connects internal EventEmitters to WebSocket clients
3
+ */
4
+ import { EventEmitter } from 'node:events';
5
+ import { logger } from '../../utils/logger.js';
6
+ const log = logger.child('web:events');
7
+ // Agent events emitter - used by routes to emit events
8
+ export const agentEvents = new EventEmitter();
9
+ // Event bridge class for managing WebSocket subscriptions
10
+ export class EventBridge {
11
+ listeners = new Map();
12
+ constructor() {
13
+ // Wire up all agent events to broadcast
14
+ const events = [
15
+ 'agent:spawned',
16
+ 'agent:stopped',
17
+ 'agent:status',
18
+ 'agent:progress',
19
+ 'task:created',
20
+ 'task:assigned',
21
+ 'task:completed',
22
+ 'workflow:start',
23
+ 'workflow:phase',
24
+ 'workflow:complete',
25
+ 'workflow:error',
26
+ 'workflow:finding',
27
+ 'message:received',
28
+ 'project:created',
29
+ 'project:updated',
30
+ 'project:task:created',
31
+ 'project:task:phase',
32
+ 'spec:created',
33
+ 'spec:status',
34
+ ];
35
+ for (const event of events) {
36
+ agentEvents.on(event, (data) => {
37
+ this.broadcast(event, data);
38
+ });
39
+ }
40
+ }
41
+ /**
42
+ * Subscribe to all events
43
+ */
44
+ subscribe(callback) {
45
+ const wrappedCallback = (data) => callback('*', data);
46
+ // Subscribe to all events
47
+ if (!this.listeners.has('*')) {
48
+ this.listeners.set('*', new Set());
49
+ }
50
+ this.listeners.get('*').add(wrappedCallback);
51
+ // Return unsubscribe function
52
+ return () => {
53
+ this.listeners.get('*')?.delete(wrappedCallback);
54
+ };
55
+ }
56
+ /**
57
+ * Subscribe to specific event
58
+ */
59
+ subscribeToEvent(event, callback) {
60
+ if (!this.listeners.has(event)) {
61
+ this.listeners.set(event, new Set());
62
+ }
63
+ this.listeners.get(event).add(callback);
64
+ return () => {
65
+ this.listeners.get(event)?.delete(callback);
66
+ };
67
+ }
68
+ /**
69
+ * Broadcast event to all subscribers
70
+ */
71
+ broadcast(event, data) {
72
+ log.debug('Broadcasting event', { event });
73
+ // Notify event-specific listeners
74
+ const eventListeners = this.listeners.get(event);
75
+ if (eventListeners) {
76
+ for (const listener of eventListeners) {
77
+ try {
78
+ listener(data);
79
+ }
80
+ catch (error) {
81
+ log.error('Error in event listener', {
82
+ event,
83
+ error: error instanceof Error ? error.message : 'Unknown error',
84
+ });
85
+ }
86
+ }
87
+ }
88
+ // Notify wildcard listeners
89
+ const wildcardListeners = this.listeners.get('*');
90
+ if (wildcardListeners) {
91
+ for (const listener of wildcardListeners) {
92
+ try {
93
+ listener({ event, data });
94
+ }
95
+ catch (error) {
96
+ log.error('Error in wildcard listener', {
97
+ event,
98
+ error: error instanceof Error ? error.message : 'Unknown error',
99
+ });
100
+ }
101
+ }
102
+ }
103
+ }
104
+ /**
105
+ * Get subscriber count for an event
106
+ */
107
+ getSubscriberCount(event) {
108
+ if (event) {
109
+ return this.listeners.get(event)?.size ?? 0;
110
+ }
111
+ let total = 0;
112
+ for (const listeners of this.listeners.values()) {
113
+ total += listeners.size;
114
+ }
115
+ return total;
116
+ }
117
+ /**
118
+ * Clear all listeners
119
+ */
120
+ clear() {
121
+ this.listeners.clear();
122
+ }
123
+ }
124
+ // Singleton instance
125
+ let eventBridge = null;
126
+ export function getEventBridge() {
127
+ if (!eventBridge) {
128
+ eventBridge = new EventBridge();
129
+ }
130
+ return eventBridge;
131
+ }
132
+ export function resetEventBridge() {
133
+ if (eventBridge) {
134
+ eventBridge.clear();
135
+ eventBridge = null;
136
+ }
137
+ }
138
+ //# sourceMappingURL=event-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bridge.js","sourceRoot":"","sources":["../../../src/web/websocket/event-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * WebSocket handler
3
+ */
4
+ import type { IncomingMessage } from 'node:http';
5
+ import type { Duplex } from 'node:stream';
6
+ import type { WSMessage } from '../types.js';
7
+ /**
8
+ * Handle WebSocket upgrade request
9
+ */
10
+ export declare function handleWebSocketUpgrade(req: IncomingMessage, socket: Duplex, _head: Buffer): void;
11
+ /**
12
+ * Get connected client count
13
+ */
14
+ export declare function getClientCount(): number;
15
+ /**
16
+ * Broadcast message to all clients
17
+ */
18
+ export declare function broadcastMessage(message: WSMessage): void;
19
+ /**
20
+ * Close all connections
21
+ */
22
+ export declare function closeAllConnections(): void;
23
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/web/websocket/handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,aAAa,CAAC;AAW3D;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAkHN;AAoKD;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAIzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C"}
@@ -0,0 +1,282 @@
1
+ /**
2
+ * WebSocket handler
3
+ */
4
+ import { randomUUID, createHash } from 'node:crypto';
5
+ import { logger } from '../../utils/logger.js';
6
+ import { getEventBridge } from './event-bridge.js';
7
+ const log = logger.child('web:websocket');
8
+ // WebSocket client connections
9
+ const clients = new Map();
10
+ /**
11
+ * Handle WebSocket upgrade request
12
+ */
13
+ export function handleWebSocketUpgrade(req, socket, _head) {
14
+ // Verify WebSocket upgrade request
15
+ const upgradeHeader = req.headers.upgrade?.toLowerCase();
16
+ if (upgradeHeader !== 'websocket') {
17
+ socket.write('HTTP/1.1 400 Bad Request\r\n\r\n');
18
+ socket.destroy();
19
+ return;
20
+ }
21
+ // Get WebSocket key
22
+ const wsKey = req.headers['sec-websocket-key'];
23
+ if (!wsKey) {
24
+ socket.write('HTTP/1.1 400 Bad Request\r\n\r\n');
25
+ socket.destroy();
26
+ return;
27
+ }
28
+ // Calculate accept key
29
+ const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
30
+ const acceptKey = createHash('sha1')
31
+ .update(wsKey + GUID)
32
+ .digest('base64');
33
+ // Send upgrade response
34
+ const response = [
35
+ 'HTTP/1.1 101 Switching Protocols',
36
+ 'Upgrade: websocket',
37
+ 'Connection: Upgrade',
38
+ `Sec-WebSocket-Accept: ${acceptKey}`,
39
+ '',
40
+ '',
41
+ ].join('\r\n');
42
+ socket.write(response);
43
+ // Create client info
44
+ const clientId = randomUUID();
45
+ const clientInfo = {
46
+ id: clientId,
47
+ connectedAt: new Date(),
48
+ subscriptions: new Set(['*']), // Subscribe to all by default
49
+ };
50
+ // Subscribe to events
51
+ const eventBridge = getEventBridge();
52
+ const unsubscribe = eventBridge.subscribe((event, data) => {
53
+ sendMessage(socket, {
54
+ type: event,
55
+ payload: data,
56
+ timestamp: new Date().toISOString(),
57
+ });
58
+ });
59
+ // Store client
60
+ clients.set(clientId, { socket, info: clientInfo, unsubscribe });
61
+ log.info('WebSocket client connected', { clientId });
62
+ // Handle incoming data
63
+ let buffer = Buffer.alloc(0);
64
+ socket.on('data', (chunk) => {
65
+ buffer = Buffer.concat([buffer, chunk]);
66
+ // Try to parse frames
67
+ while (buffer.length >= 2) {
68
+ const frame = parseWebSocketFrame(buffer);
69
+ if (!frame)
70
+ break;
71
+ buffer = buffer.subarray(frame.totalLength);
72
+ // Handle frame
73
+ if (frame.opcode === 0x8) {
74
+ // Close frame
75
+ log.info('WebSocket client disconnected (close frame)', { clientId });
76
+ cleanupClient(clientId);
77
+ return;
78
+ }
79
+ if (frame.opcode === 0x9) {
80
+ // Ping - send pong
81
+ const pongFrame = createWebSocketFrame(0xa, frame.payload);
82
+ socket.write(pongFrame);
83
+ continue;
84
+ }
85
+ if (frame.opcode === 0xa) {
86
+ // Pong - ignore
87
+ continue;
88
+ }
89
+ if (frame.opcode === 0x1 || frame.opcode === 0x2) {
90
+ // Text or binary frame
91
+ handleClientMessage(clientId, frame.payload.toString('utf-8'));
92
+ }
93
+ }
94
+ });
95
+ socket.on('close', () => {
96
+ log.info('WebSocket client disconnected (socket close)', { clientId });
97
+ cleanupClient(clientId);
98
+ });
99
+ socket.on('error', (error) => {
100
+ log.error('WebSocket error', { clientId, error: error.message });
101
+ cleanupClient(clientId);
102
+ });
103
+ // Send welcome message
104
+ sendMessage(socket, {
105
+ type: 'connected',
106
+ payload: { clientId },
107
+ timestamp: new Date().toISOString(),
108
+ });
109
+ }
110
+ /**
111
+ * Parse WebSocket frame
112
+ */
113
+ function parseWebSocketFrame(buffer) {
114
+ if (buffer.length < 2)
115
+ return null;
116
+ const firstByte = buffer[0];
117
+ const secondByte = buffer[1];
118
+ const opcode = firstByte & 0x0f;
119
+ const masked = (secondByte & 0x80) !== 0;
120
+ let payloadLength = secondByte & 0x7f;
121
+ let offset = 2;
122
+ // Extended payload length
123
+ if (payloadLength === 126) {
124
+ if (buffer.length < 4)
125
+ return null;
126
+ payloadLength = buffer.readUInt16BE(2);
127
+ offset = 4;
128
+ }
129
+ else if (payloadLength === 127) {
130
+ if (buffer.length < 10)
131
+ return null;
132
+ // For simplicity, we'll only handle 32-bit lengths
133
+ payloadLength = buffer.readUInt32BE(6);
134
+ offset = 10;
135
+ }
136
+ // Masking key
137
+ let maskingKey = null;
138
+ if (masked) {
139
+ if (buffer.length < offset + 4)
140
+ return null;
141
+ maskingKey = buffer.subarray(offset, offset + 4);
142
+ offset += 4;
143
+ }
144
+ // Payload
145
+ if (buffer.length < offset + payloadLength)
146
+ return null;
147
+ let payload = buffer.subarray(offset, offset + payloadLength);
148
+ // Unmask if needed
149
+ if (maskingKey) {
150
+ const unmasked = Buffer.alloc(payloadLength);
151
+ for (let i = 0; i < payloadLength; i++) {
152
+ unmasked[i] = payload[i] ^ maskingKey[i % 4];
153
+ }
154
+ payload = unmasked;
155
+ }
156
+ return {
157
+ opcode,
158
+ payload,
159
+ totalLength: offset + payloadLength,
160
+ };
161
+ }
162
+ /**
163
+ * Create WebSocket frame
164
+ */
165
+ function createWebSocketFrame(opcode, payload) {
166
+ const payloadLength = payload.length;
167
+ let header;
168
+ if (payloadLength < 126) {
169
+ header = Buffer.alloc(2);
170
+ header[0] = 0x80 | opcode; // FIN + opcode
171
+ header[1] = payloadLength;
172
+ }
173
+ else if (payloadLength < 65536) {
174
+ header = Buffer.alloc(4);
175
+ header[0] = 0x80 | opcode;
176
+ header[1] = 126;
177
+ header.writeUInt16BE(payloadLength, 2);
178
+ }
179
+ else {
180
+ header = Buffer.alloc(10);
181
+ header[0] = 0x80 | opcode;
182
+ header[1] = 127;
183
+ header.writeUInt32BE(0, 2);
184
+ header.writeUInt32BE(payloadLength, 6);
185
+ }
186
+ return Buffer.concat([header, payload]);
187
+ }
188
+ /**
189
+ * Send message to WebSocket client
190
+ */
191
+ function sendMessage(socket, message) {
192
+ try {
193
+ const payload = Buffer.from(JSON.stringify(message), 'utf-8');
194
+ const frame = createWebSocketFrame(0x1, payload); // 0x1 = text frame
195
+ socket.write(frame);
196
+ }
197
+ catch (error) {
198
+ log.error('Failed to send WebSocket message', {
199
+ error: error instanceof Error ? error.message : 'Unknown error',
200
+ });
201
+ }
202
+ }
203
+ /**
204
+ * Handle message from client
205
+ */
206
+ function handleClientMessage(clientId, message) {
207
+ const client = clients.get(clientId);
208
+ if (!client)
209
+ return;
210
+ try {
211
+ const parsed = JSON.parse(message);
212
+ // Handle subscription changes
213
+ if (parsed.type === 'subscribe') {
214
+ const events = parsed.events;
215
+ if (Array.isArray(events)) {
216
+ for (const event of events) {
217
+ client.info.subscriptions.add(event);
218
+ }
219
+ log.debug('Client subscribed to events', { clientId, events });
220
+ }
221
+ }
222
+ if (parsed.type === 'unsubscribe') {
223
+ const events = parsed.events;
224
+ if (Array.isArray(events)) {
225
+ for (const event of events) {
226
+ client.info.subscriptions.delete(event);
227
+ }
228
+ log.debug('Client unsubscribed from events', { clientId, events });
229
+ }
230
+ }
231
+ // Handle ping
232
+ if (parsed.type === 'ping') {
233
+ sendMessage(client.socket, {
234
+ type: 'pong',
235
+ payload: {},
236
+ timestamp: new Date().toISOString(),
237
+ });
238
+ }
239
+ }
240
+ catch {
241
+ log.warn('Failed to parse client message', { clientId, message });
242
+ }
243
+ }
244
+ /**
245
+ * Cleanup disconnected client
246
+ */
247
+ function cleanupClient(clientId) {
248
+ const client = clients.get(clientId);
249
+ if (client) {
250
+ client.unsubscribe();
251
+ try {
252
+ client.socket.destroy();
253
+ }
254
+ catch {
255
+ // Ignore errors during cleanup
256
+ }
257
+ clients.delete(clientId);
258
+ }
259
+ }
260
+ /**
261
+ * Get connected client count
262
+ */
263
+ export function getClientCount() {
264
+ return clients.size;
265
+ }
266
+ /**
267
+ * Broadcast message to all clients
268
+ */
269
+ export function broadcastMessage(message) {
270
+ for (const client of clients.values()) {
271
+ sendMessage(client.socket, message);
272
+ }
273
+ }
274
+ /**
275
+ * Close all connections
276
+ */
277
+ export function closeAllConnections() {
278
+ for (const clientId of clients.keys()) {
279
+ cleanupClient(clientId);
280
+ }
281
+ }
282
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/web/websocket/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * WebSocket exports
3
+ */
4
+ export { handleWebSocketUpgrade, getClientCount, broadcastMessage, closeAllConnections, } from './handler.js';
5
+ export { agentEvents, getEventBridge, resetEventBridge, EventBridge, type EventName, } from './event-bridge.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/web/websocket/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,KAAK,SAAS,GACf,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * WebSocket exports
3
+ */
4
+ export { handleWebSocketUpgrade, getClientCount, broadcastMessage, closeAllConnections, } from './handler.js';
5
+ export { agentEvents, getEventBridge, resetEventBridge, EventBridge, } from './event-bridge.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/web/websocket/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,WAAW,GAEZ,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blackms/aistack",
3
- "version": "1.0.13",
3
+ "version": "1.2.0",
4
4
  "description": "Clean agent orchestration for Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -43,7 +43,11 @@
43
43
  "lint:fix": "eslint src --fix",
44
44
  "format": "prettier --write \"src/**/*.ts\"",
45
45
  "typecheck": "tsc --noEmit",
46
- "prepublishOnly": "npm run build"
46
+ "prepublishOnly": "npm run build",
47
+ "web": "node dist/cli/index.js web start",
48
+ "web:dev": "npm run build && npm run web",
49
+ "dev:web": "cd web && npm run dev",
50
+ "build:web": "cd web && npm run build"
47
51
  },
48
52
  "dependencies": {
49
53
  "@anthropic-ai/sdk": "^0.71.0",