@esotech/contextuate 2.0.0 → 2.1.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 (105) hide show
  1. package/README.md +169 -1
  2. package/dist/commands/claude.d.ts +21 -0
  3. package/dist/commands/claude.js +213 -0
  4. package/dist/commands/context.d.ts +1 -0
  5. package/dist/commands/create.d.ts +3 -0
  6. package/dist/commands/index.d.ts +4 -0
  7. package/dist/commands/init.d.ts +7 -0
  8. package/dist/commands/init.js +67 -6
  9. package/dist/commands/install.d.ts +28 -0
  10. package/dist/commands/install.js +116 -11
  11. package/dist/commands/monitor.d.ts +55 -0
  12. package/dist/commands/monitor.js +1007 -0
  13. package/dist/commands/remove.d.ts +3 -0
  14. package/dist/commands/run.d.ts +6 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +113 -1
  17. package/dist/monitor/daemon/circuit-breaker.d.ts +121 -0
  18. package/dist/monitor/daemon/circuit-breaker.js +552 -0
  19. package/dist/monitor/daemon/cli.d.ts +8 -0
  20. package/dist/monitor/daemon/cli.js +82 -0
  21. package/dist/monitor/daemon/index.d.ts +137 -0
  22. package/dist/monitor/daemon/index.js +695 -0
  23. package/dist/monitor/daemon/notifier.d.ts +25 -0
  24. package/dist/monitor/daemon/notifier.js +98 -0
  25. package/dist/monitor/daemon/processor.d.ts +89 -0
  26. package/dist/monitor/daemon/processor.js +455 -0
  27. package/dist/monitor/daemon/state.d.ts +80 -0
  28. package/dist/monitor/daemon/state.js +162 -0
  29. package/dist/monitor/daemon/watcher.d.ts +47 -0
  30. package/dist/monitor/daemon/watcher.js +171 -0
  31. package/dist/monitor/daemon/wrapper-manager.d.ts +106 -0
  32. package/dist/monitor/daemon/wrapper-manager.js +374 -0
  33. package/dist/monitor/hooks/emit-event.js +652 -0
  34. package/dist/monitor/persistence/file-store.d.ts +88 -0
  35. package/dist/monitor/persistence/file-store.js +335 -0
  36. package/dist/monitor/persistence/index.d.ts +7 -0
  37. package/dist/monitor/persistence/index.js +10 -0
  38. package/dist/monitor/server/adapters/redis.d.ts +38 -0
  39. package/dist/monitor/server/adapters/redis.js +213 -0
  40. package/dist/monitor/server/adapters/unix-socket.d.ts +33 -0
  41. package/dist/monitor/server/adapters/unix-socket.js +182 -0
  42. package/dist/monitor/server/broker.d.ts +135 -0
  43. package/dist/monitor/server/broker.js +475 -0
  44. package/dist/monitor/server/cli.d.ts +8 -0
  45. package/dist/monitor/server/cli.js +98 -0
  46. package/dist/monitor/server/fastify.d.ts +16 -0
  47. package/dist/monitor/server/fastify.js +184 -0
  48. package/dist/monitor/server/index.d.ts +36 -0
  49. package/dist/monitor/server/index.js +153 -0
  50. package/dist/monitor/server/websocket.d.ts +80 -0
  51. package/dist/monitor/server/websocket.js +453 -0
  52. package/dist/monitor/ui/assets/index-4IssW9On.js +59 -0
  53. package/dist/monitor/ui/assets/index-vo9hLe5R.css +32 -0
  54. package/dist/monitor/ui/favicon.png +0 -0
  55. package/dist/monitor/ui/index.html +14 -0
  56. package/dist/monitor/ui/logo.png +0 -0
  57. package/dist/monitor/ui/logo.svg +1 -0
  58. package/dist/runtime/driver.d.ts +16 -0
  59. package/dist/runtime/tools.d.ts +10 -0
  60. package/dist/templates/README.md +33 -7
  61. package/dist/templates/agents/aegis.md +4 -0
  62. package/dist/templates/agents/archon.md +13 -22
  63. package/dist/templates/agents/atlas.md +4 -0
  64. package/dist/templates/agents/canvas.md +4 -0
  65. package/dist/templates/agents/chronicle.md +4 -0
  66. package/dist/templates/agents/chronos.md +4 -0
  67. package/dist/templates/agents/cipher.md +4 -0
  68. package/dist/templates/agents/crucible.md +4 -0
  69. package/dist/templates/agents/echo.md +4 -0
  70. package/dist/templates/agents/forge.md +4 -0
  71. package/dist/templates/agents/ledger.md +4 -0
  72. package/dist/templates/agents/meridian.md +4 -0
  73. package/dist/templates/agents/nexus.md +4 -0
  74. package/dist/templates/agents/pythia.md +217 -0
  75. package/dist/templates/agents/scribe.md +4 -0
  76. package/dist/templates/agents/sentinel.md +4 -0
  77. package/dist/templates/agents/{oracle.md → thoth.md} +11 -7
  78. package/dist/templates/agents/unity.md +4 -0
  79. package/dist/templates/agents/vox.md +4 -0
  80. package/dist/templates/agents/weaver.md +4 -0
  81. package/dist/templates/framework-agents/documentation-expert.md +3 -3
  82. package/dist/templates/framework-agents/tools-expert.md +8 -8
  83. package/dist/templates/skills/consult.md +138 -0
  84. package/dist/templates/skills/orchestrate.md +173 -0
  85. package/dist/templates/skills/pythia.md +37 -0
  86. package/dist/templates/standards/agent-roles.md +68 -21
  87. package/dist/templates/standards/coding-standards.md +9 -26
  88. package/dist/templates/templates/context.md +17 -2
  89. package/dist/templates/templates/contextuate.md +21 -28
  90. package/dist/templates/templates/standards/go.md +167 -0
  91. package/dist/templates/templates/standards/java.md +167 -0
  92. package/dist/templates/templates/standards/javascript.md +292 -0
  93. package/dist/templates/templates/standards/php.md +181 -0
  94. package/dist/templates/templates/standards/python.md +175 -0
  95. package/dist/templates/tools/agent-creator.md +252 -0
  96. package/dist/templates/tools/agent-creator.tool.md +2 -2
  97. package/dist/templates/tools/quickref.md +216 -0
  98. package/dist/templates/tools/spawn.md +31 -0
  99. package/dist/templates/tools/standards-detector.md +301 -0
  100. package/dist/templates/version.json +1 -1
  101. package/dist/types/monitor.d.ts +660 -0
  102. package/dist/types/monitor.js +75 -0
  103. package/dist/utils/git.d.ts +9 -0
  104. package/dist/utils/tokens.d.ts +10 -0
  105. package/package.json +18 -5
@@ -0,0 +1,453 @@
1
+ "use strict";
2
+ /**
3
+ * WebSocket Server
4
+ *
5
+ * Provides real-time event streaming to connected UI clients.
6
+ * Uses the 'ws' library for WebSocket handling.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MonitorWebSocketServer = void 0;
10
+ const ws_1 = require("ws");
11
+ const uuid_1 = require("uuid");
12
+ class MonitorWebSocketServer {
13
+ constructor(options) {
14
+ this.wss = null;
15
+ this.clients = new Map();
16
+ this.port = options.port;
17
+ this.host = options.host || '0.0.0.0';
18
+ this.broker = options.broker;
19
+ this.persistence = options.persistence;
20
+ }
21
+ /**
22
+ * Start the WebSocket server
23
+ */
24
+ async start() {
25
+ this.wss = new ws_1.WebSocketServer({
26
+ port: this.port,
27
+ host: this.host,
28
+ });
29
+ this.wss.on('connection', (ws) => this.handleConnection(ws));
30
+ this.wss.on('error', (err) => {
31
+ console.error('[WebSocket] Server error:', err);
32
+ });
33
+ // Subscribe to broker events
34
+ this.unsubscribeBroker = this.broker.onEvent((type, data) => {
35
+ this.handleBrokerEvent(type, data);
36
+ });
37
+ console.log(`[WebSocket] Server listening on ws://${this.host}:${this.port}`);
38
+ }
39
+ /**
40
+ * Stop the WebSocket server
41
+ */
42
+ async stop() {
43
+ if (this.unsubscribeBroker) {
44
+ this.unsubscribeBroker();
45
+ }
46
+ if (this.wss) {
47
+ // Forcefully close all client connections
48
+ for (const ws of this.wss.clients) {
49
+ try {
50
+ ws.send(JSON.stringify({ type: 'error', message: 'Server shutting down' }));
51
+ ws.terminate(); // Force close the connection
52
+ }
53
+ catch (err) {
54
+ // Ignore errors during shutdown
55
+ }
56
+ }
57
+ return new Promise((resolve) => {
58
+ // Add timeout to force resolve if close takes too long
59
+ const timeout = setTimeout(() => {
60
+ console.log('[WebSocket] Server close timeout, forcing shutdown');
61
+ this.wss = null;
62
+ this.clients.clear();
63
+ resolve();
64
+ }, 3000);
65
+ this.wss.close(() => {
66
+ clearTimeout(timeout);
67
+ this.wss = null;
68
+ this.clients.clear();
69
+ console.log('[WebSocket] Server stopped');
70
+ resolve();
71
+ });
72
+ });
73
+ }
74
+ }
75
+ /**
76
+ * Handle new WebSocket connection
77
+ */
78
+ handleConnection(ws) {
79
+ const clientId = (0, uuid_1.v4)();
80
+ const client = {
81
+ id: clientId,
82
+ subscription: {
83
+ sessionIds: new Set(),
84
+ allSessions: false,
85
+ },
86
+ showHidden: false,
87
+ send: (message) => {
88
+ if (ws.readyState === ws_1.WebSocket.OPEN) {
89
+ ws.send(JSON.stringify(message));
90
+ }
91
+ },
92
+ };
93
+ this.clients.set(clientId, client);
94
+ console.log(`[WebSocket] Client connected: ${clientId}`);
95
+ ws.on('message', (data) => {
96
+ try {
97
+ const message = JSON.parse(data.toString());
98
+ this.handleClientMessage(client, message);
99
+ }
100
+ catch (err) {
101
+ console.error('[WebSocket] Failed to parse message:', err);
102
+ client.send({ type: 'error', message: 'Invalid message format' });
103
+ }
104
+ });
105
+ ws.on('close', () => {
106
+ this.clients.delete(clientId);
107
+ console.log(`[WebSocket] Client disconnected: ${clientId}`);
108
+ });
109
+ ws.on('error', (err) => {
110
+ console.error(`[WebSocket] Client error (${clientId}):`, err);
111
+ });
112
+ }
113
+ /**
114
+ * Handle message from client
115
+ */
116
+ async handleClientMessage(client, message) {
117
+ switch (message.type) {
118
+ case 'subscribe':
119
+ if (message.sessionIds && message.sessionIds.length > 0) {
120
+ // Subscribe to specific sessions
121
+ client.subscription.allSessions = false;
122
+ for (const id of message.sessionIds) {
123
+ client.subscription.sessionIds.add(id);
124
+ }
125
+ }
126
+ else {
127
+ // Subscribe to all sessions
128
+ client.subscription.allSessions = true;
129
+ }
130
+ break;
131
+ case 'unsubscribe':
132
+ for (const id of message.sessionIds) {
133
+ client.subscription.sessionIds.delete(id);
134
+ }
135
+ break;
136
+ case 'get_sessions':
137
+ const sessions = this.broker.getSessions(client.showHidden);
138
+ client.send({ type: 'sessions', sessions });
139
+ break;
140
+ case 'get_events':
141
+ await this.sendHistoricalEvents(client, message.sessionId, message.limit, message.before);
142
+ break;
143
+ case 'get_all_recent_events':
144
+ await this.sendAllRecentEvents(client, message.limit);
145
+ break;
146
+ case 'get_event_detail':
147
+ await this.sendEventDetail(client, message.sessionId, message.eventId);
148
+ break;
149
+ case 'send_input':
150
+ // Legacy - kept for backward compatibility
151
+ console.log(`[WebSocket] Input for session ${message.sessionId}: ${message.input}`);
152
+ break;
153
+ case 'inject_input':
154
+ // Forward input injection to daemon via broker
155
+ this.broker.sendToDaemon({
156
+ type: 'inject_input',
157
+ wrapperId: message.wrapperId,
158
+ input: message.input,
159
+ });
160
+ break;
161
+ case 'resize_wrapper':
162
+ // Forward resize to daemon via broker
163
+ this.broker.sendToDaemon({
164
+ type: 'resize_wrapper',
165
+ wrapperId: message.wrapperId,
166
+ cols: message.cols,
167
+ rows: message.rows,
168
+ });
169
+ break;
170
+ case 'get_wrappers':
171
+ // Request current wrapper list from daemon
172
+ this.broker.sendToDaemon({ type: 'get_wrappers' });
173
+ break;
174
+ case 'spawn_wrapper':
175
+ // Forward spawn request to daemon
176
+ this.broker.sendToDaemon({
177
+ type: 'spawn_wrapper',
178
+ cwd: message.cwd,
179
+ args: message.args,
180
+ cols: message.cols,
181
+ rows: message.rows,
182
+ });
183
+ break;
184
+ case 'kill_wrapper':
185
+ // Forward kill request to daemon
186
+ this.broker.sendToDaemon({
187
+ type: 'kill_wrapper',
188
+ wrapperId: message.wrapperId,
189
+ });
190
+ break;
191
+ case 'hide_session':
192
+ try {
193
+ await this.broker.hideSession(message.sessionId);
194
+ }
195
+ catch (err) {
196
+ const error = err;
197
+ client.send({ type: 'error', message: error.message });
198
+ }
199
+ break;
200
+ case 'unhide_session':
201
+ try {
202
+ await this.broker.unhideSession(message.sessionId);
203
+ }
204
+ catch (err) {
205
+ const error = err;
206
+ client.send({ type: 'error', message: error.message });
207
+ }
208
+ break;
209
+ case 'delete_session':
210
+ try {
211
+ await this.broker.deleteSession(message.sessionId);
212
+ }
213
+ catch (err) {
214
+ const error = err;
215
+ client.send({ type: 'error', message: error.message });
216
+ }
217
+ break;
218
+ case 'hide_all_sessions':
219
+ try {
220
+ await this.broker.hideAllSessions();
221
+ const updatedSessions = this.broker.getSessions(client.showHidden);
222
+ this.broadcastSessionsUpdate(updatedSessions);
223
+ }
224
+ catch (err) {
225
+ const error = err;
226
+ client.send({ type: 'error', message: error.message });
227
+ }
228
+ break;
229
+ case 'delete_all_sessions':
230
+ try {
231
+ await this.broker.deleteAllSessions();
232
+ const updatedSessions = this.broker.getSessions(client.showHidden);
233
+ this.broadcastSessionsUpdate(updatedSessions);
234
+ }
235
+ catch (err) {
236
+ const error = err;
237
+ client.send({ type: 'error', message: error.message });
238
+ }
239
+ break;
240
+ case 'set_show_hidden':
241
+ client.showHidden = message.showHidden;
242
+ const filteredSessions = this.broker.getSessions(client.showHidden);
243
+ client.send({ type: 'sessions', sessions: filteredSessions });
244
+ break;
245
+ case 'set_parent':
246
+ try {
247
+ await this.broker.setParentSession(message.sessionId, message.parentSessionId);
248
+ }
249
+ catch (err) {
250
+ const error = err;
251
+ client.send({ type: 'error', message: error.message });
252
+ }
253
+ break;
254
+ case 'toggle_pin':
255
+ try {
256
+ await this.broker.togglePin(message.sessionId);
257
+ }
258
+ catch (err) {
259
+ const error = err;
260
+ client.send({ type: 'error', message: error.message });
261
+ }
262
+ break;
263
+ case 'set_user_initiated':
264
+ try {
265
+ await this.broker.setUserInitiated(message.sessionId, message.isUserInitiated);
266
+ }
267
+ catch (err) {
268
+ const error = err;
269
+ client.send({ type: 'error', message: error.message });
270
+ }
271
+ break;
272
+ case 'rename_session':
273
+ try {
274
+ await this.broker.renameSession(message.sessionId, message.label);
275
+ }
276
+ catch (err) {
277
+ const error = err;
278
+ client.send({ type: 'error', message: error.message });
279
+ }
280
+ break;
281
+ }
282
+ }
283
+ /**
284
+ * Send historical events to a client
285
+ */
286
+ async sendHistoricalEvents(client, sessionId, limit, before) {
287
+ if (!this.persistence) {
288
+ client.send({ type: 'error', message: 'Persistence not available' });
289
+ return;
290
+ }
291
+ try {
292
+ const events = await this.persistence.getEvents(sessionId, {
293
+ limit: limit || 100,
294
+ before,
295
+ });
296
+ client.send({ type: 'events', sessionId, events });
297
+ }
298
+ catch (err) {
299
+ console.error('[WebSocket] Failed to fetch events:', err);
300
+ client.send({ type: 'error', message: 'Failed to fetch events' });
301
+ }
302
+ }
303
+ /**
304
+ * Send all recent events across all sessions to a client
305
+ */
306
+ async sendAllRecentEvents(client, limit) {
307
+ if (!this.persistence) {
308
+ client.send({ type: 'error', message: 'Persistence not available' });
309
+ return;
310
+ }
311
+ try {
312
+ const events = await this.persistence.getAllRecentEvents(limit || 200);
313
+ client.send({ type: 'all_events', events });
314
+ }
315
+ catch (err) {
316
+ console.error('[WebSocket] Failed to fetch all events:', err);
317
+ client.send({ type: 'error', message: 'Failed to fetch events' });
318
+ }
319
+ }
320
+ /**
321
+ * Send event detail to a client
322
+ */
323
+ async sendEventDetail(client, sessionId, eventId) {
324
+ if (!this.persistence) {
325
+ client.send({ type: 'error', message: 'Persistence not available' });
326
+ return;
327
+ }
328
+ try {
329
+ const event = await this.persistence.getEventById(sessionId, eventId);
330
+ if (event) {
331
+ client.send({ type: 'event_detail', event });
332
+ }
333
+ else {
334
+ client.send({ type: 'error', message: 'Event not found' });
335
+ }
336
+ }
337
+ catch (err) {
338
+ console.error('[WebSocket] Failed to fetch event detail:', err);
339
+ client.send({ type: 'error', message: 'Failed to fetch event detail' });
340
+ }
341
+ }
342
+ /**
343
+ * Handle events from the broker
344
+ */
345
+ handleBrokerEvent(type, data) {
346
+ switch (type) {
347
+ case 'event':
348
+ this.broadcastEvent(data);
349
+ break;
350
+ case 'session_created':
351
+ case 'session_updated':
352
+ case 'session_ended':
353
+ this.broadcastSessionUpdate(data);
354
+ break;
355
+ case 'wrapper_connected':
356
+ this.broadcastToAll({
357
+ type: 'wrapper_connected',
358
+ wrapperId: data.wrapperId,
359
+ state: data.state,
360
+ });
361
+ break;
362
+ case 'wrapper_disconnected':
363
+ this.broadcastToAll({
364
+ type: 'wrapper_disconnected',
365
+ wrapperId: data.wrapperId,
366
+ exitCode: data.exitCode,
367
+ });
368
+ break;
369
+ case 'wrapper_state':
370
+ this.broadcastToAll({
371
+ type: 'wrapper_state',
372
+ wrapperId: data.wrapperId,
373
+ state: data.state,
374
+ claudeSessionId: data.claudeSessionId,
375
+ });
376
+ break;
377
+ case 'wrapper_output':
378
+ this.broadcastToAll({
379
+ type: 'wrapper_output',
380
+ wrapperId: data.wrapperId,
381
+ data: data.data,
382
+ timestamp: data.timestamp,
383
+ });
384
+ break;
385
+ case 'wrapper_spawned':
386
+ this.broadcastToAll({
387
+ type: 'wrapper_spawned',
388
+ wrapperId: data.wrapperId,
389
+ success: data.success ?? false,
390
+ error: data.error,
391
+ });
392
+ break;
393
+ case 'wrappers_list':
394
+ this.broadcastToAll({
395
+ type: 'wrappers',
396
+ wrappers: data.wrappers || [],
397
+ });
398
+ break;
399
+ }
400
+ }
401
+ /**
402
+ * Broadcast a message to all connected clients
403
+ */
404
+ broadcastToAll(message) {
405
+ for (const [, client] of this.clients) {
406
+ client.send(message);
407
+ }
408
+ }
409
+ /**
410
+ * Broadcast an event to subscribed clients
411
+ */
412
+ broadcastEvent(event) {
413
+ for (const [, client] of this.clients) {
414
+ if (this.isClientSubscribed(client, event.sessionId)) {
415
+ client.send({ type: 'event', event });
416
+ }
417
+ }
418
+ }
419
+ /**
420
+ * Broadcast a session update to all clients
421
+ */
422
+ broadcastSessionUpdate(session) {
423
+ const message = { type: 'session_update', session };
424
+ for (const [, client] of this.clients) {
425
+ // Session updates go to all clients
426
+ client.send(message);
427
+ }
428
+ }
429
+ /**
430
+ * Broadcast updated session list to all clients (for bulk operations)
431
+ */
432
+ broadcastSessionsUpdate(sessions) {
433
+ const message = { type: 'sessions_updated', sessions };
434
+ for (const [, client] of this.clients) {
435
+ // Filter sessions based on client's showHidden preference
436
+ const filteredSessions = sessions.filter(s => client.showHidden || !s.hidden);
437
+ client.send({ type: 'sessions_updated', sessions: filteredSessions });
438
+ }
439
+ }
440
+ /**
441
+ * Check if a client is subscribed to events for a session
442
+ */
443
+ isClientSubscribed(client, sessionId) {
444
+ return client.subscription.allSessions || client.subscription.sessionIds.has(sessionId);
445
+ }
446
+ /**
447
+ * Get the number of connected clients
448
+ */
449
+ getClientCount() {
450
+ return this.clients.size;
451
+ }
452
+ }
453
+ exports.MonitorWebSocketServer = MonitorWebSocketServer;