agentgui 1.0.814 → 1.0.816

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.
@@ -1,5 +1,3 @@
1
- // Per-conversation UI state machine using XState v5
2
- // Tracks IDLE -> STREAMING -> QUEUED states per conversation
3
1
 
4
2
  const { createMachine: cmCreateMachine, createActor: cmCreateActor, assign: cmAssign } = XState;
5
3
 
@@ -91,7 +89,6 @@ function isStreaming(convId) {
91
89
  return getState(convId) === 'streaming';
92
90
  }
93
91
 
94
- // isActive: streaming OR queued — use this to gate optimistic messages
95
92
  function isActive(convId) {
96
93
  const s = getState(convId);
97
94
  return s === 'streaming' || s === 'queued';
@@ -1,8 +1,3 @@
1
- /**
2
- * Conversations Module
3
- * Manages conversation list sidebar with real-time updates
4
- * Includes folder browser for selecting working directory on new conversation
5
- */
6
1
 
7
2
  function pathSplit(p) {
8
3
  return p.split(/[\/\\]/).filter(Boolean);
@@ -1,7 +1,3 @@
1
- /**
2
- * Event Filter & Search
3
- * Provides event filtering, searching, and replay functionality
4
- */
5
1
 
6
2
  class EventFilter {
7
3
  constructor(renderer) {
@@ -22,9 +18,6 @@ class EventFilter {
22
18
  };
23
19
  }
24
20
 
25
- /**
26
- * Store all events for filtering
27
- */
28
21
  trackEvent(event) {
29
22
  this.allEvents.push({
30
23
  ...event,
@@ -32,12 +25,10 @@ class EventFilter {
32
25
  trackedAt: Date.now()
33
26
  });
34
27
 
35
- // Limit history
36
28
  if (this.allEvents.length > 5000) {
37
29
  this.allEvents.shift();
38
30
  }
39
31
 
40
- // Apply current filters
41
32
  if (this.filterState.isActive) {
42
33
  this.applyFilters();
43
34
  }
@@ -45,17 +36,11 @@ class EventFilter {
45
36
  return event;
46
37
  }
47
38
 
48
- /**
49
- * Set event type filter
50
- */
51
39
  setTypeFilter(types) {
52
40
  this.filterState.types = new Set(types);
53
41
  this.applyFilters();
54
42
  }
55
43
 
56
- /**
57
- * Toggle event type in filter
58
- */
59
44
  toggleType(type) {
60
45
  if (this.filterState.types.has(type)) {
61
46
  this.filterState.types.delete(type);
@@ -65,26 +50,17 @@ class EventFilter {
65
50
  this.applyFilters();
66
51
  }
67
52
 
68
- /**
69
- * Set search text
70
- */
71
53
  setSearchText(text) {
72
54
  this.filterState.searchText = text.toLowerCase();
73
55
  this.applyFilters();
74
56
  }
75
57
 
76
- /**
77
- * Set time range
78
- */
79
58
  setTimeRange(startTime, endTime) {
80
59
  this.filterState.startTime = startTime;
81
60
  this.filterState.endTime = endTime;
82
61
  this.applyFilters();
83
62
  }
84
63
 
85
- /**
86
- * Apply all filters
87
- */
88
64
  applyFilters() {
89
65
  this.filterState.isActive =
90
66
  this.filterState.types.size > 0 ||
@@ -98,12 +74,10 @@ class EventFilter {
98
74
  }
99
75
 
100
76
  this.filteredEvents = this.allEvents.filter(event => {
101
- // Type filter
102
77
  if (this.filterState.types.size > 0 && !this.filterState.types.has(event.type)) {
103
78
  return false;
104
79
  }
105
80
 
106
- // Search filter
107
81
  if (this.filterState.searchText.length > 0) {
108
82
  const searchable = JSON.stringify(event).toLowerCase();
109
83
  if (!searchable.includes(this.filterState.searchText)) {
@@ -111,7 +85,6 @@ class EventFilter {
111
85
  }
112
86
  }
113
87
 
114
- // Time range filter
115
88
  const eventTime = event.timestamp || event.trackedAt;
116
89
  if (this.filterState.startTime && eventTime < this.filterState.startTime) {
117
90
  return false;
@@ -126,9 +99,6 @@ class EventFilter {
126
99
  return this.filteredEvents;
127
100
  }
128
101
 
129
- /**
130
- * Search events by text
131
- */
132
102
  search(query) {
133
103
  const results = [];
134
104
  const lowerQuery = query.toLowerCase();
@@ -149,9 +119,6 @@ class EventFilter {
149
119
  return results.sort((a, b) => b.matchCount - a.matchCount);
150
120
  }
151
121
 
152
- /**
153
- * Get event statistics
154
- */
155
122
  getStats() {
156
123
  const stats = {
157
124
  total: this.allEvents.length,
@@ -164,10 +131,8 @@ class EventFilter {
164
131
  };
165
132
 
166
133
  for (const event of this.allEvents) {
167
- // Count by type
168
134
  stats.byType[event.type] = (stats.byType[event.type] || 0) + 1;
169
135
 
170
- // Time stats
171
136
  const time = event.timestamp || event.trackedAt;
172
137
  if (!stats.byTime.oldest || time < stats.byTime.oldest) {
173
138
  stats.byTime.oldest = time;
@@ -184,9 +149,6 @@ class EventFilter {
184
149
  return stats;
185
150
  }
186
151
 
187
- /**
188
- * Start event replay
189
- */
190
152
  async startReplay(events = null, speed = 1) {
191
153
  const replayEvents = events || this.filteredEvents;
192
154
  if (replayEvents.length === 0) return;
@@ -195,13 +157,11 @@ class EventFilter {
195
157
  this.replayState.currentIndex = 0;
196
158
  this.replayState.speed = speed;
197
159
 
198
- // Clear renderer
199
160
  this.renderer.clear();
200
161
 
201
162
  for (const event of replayEvents) {
202
163
  if (!this.replayState.isReplaying) break;
203
164
 
204
- // Estimate delay based on event timestamps
205
165
  const delay = 100 / this.replayState.speed;
206
166
  await new Promise(resolve => setTimeout(resolve, delay));
207
167
 
@@ -212,16 +172,10 @@ class EventFilter {
212
172
  this.replayState.isReplaying = false;
213
173
  }
214
174
 
215
- /**
216
- * Stop event replay
217
- */
218
175
  stopReplay() {
219
176
  this.replayState.isReplaying = false;
220
177
  }
221
178
 
222
- /**
223
- * Get replay progress
224
- */
225
179
  getReplayProgress() {
226
180
  const total = this.filteredEvents.length;
227
181
  const current = this.replayState.currentIndex;
@@ -233,9 +187,6 @@ class EventFilter {
233
187
  };
234
188
  }
235
189
 
236
- /**
237
- * Export filtered events
238
- */
239
190
  export(format = 'json') {
240
191
  const events = this.filterState.isActive ? this.filteredEvents : this.allEvents;
241
192
 
@@ -254,9 +205,6 @@ class EventFilter {
254
205
  }
255
206
  }
256
207
 
257
- /**
258
- * Export as CSV
259
- */
260
208
  exportAsCSV(events) {
261
209
  const headers = ['timestamp', 'type', 'id', 'sessionId', 'message'];
262
210
  const rows = [headers.join(',')];
@@ -275,9 +223,6 @@ class EventFilter {
275
223
  return rows.join('\n');
276
224
  }
277
225
 
278
- /**
279
- * Export as Markdown
280
- */
281
226
  exportAsMarkdown(events) {
282
227
  const lines = ['# Event Export\n'];
283
228
  let currentType = null;
@@ -295,9 +240,6 @@ class EventFilter {
295
240
  return lines.join('\n');
296
241
  }
297
242
 
298
- /**
299
- * Clear history
300
- */
301
243
  clear() {
302
244
  this.allEvents = [];
303
245
  this.filteredEvents = [];
@@ -305,7 +247,6 @@ class EventFilter {
305
247
  }
306
248
  }
307
249
 
308
- // Export for use in browser
309
250
  if (typeof module !== 'undefined' && module.exports) {
310
251
  module.exports = EventFilter;
311
252
  }
@@ -1,8 +1,3 @@
1
- /**
2
- * Image Loader Module
3
- * Detects image file reads from agent events and manages lazy loading
4
- * Supports PNG, JPG, JPEG, GIF, WebP, SVG formats
5
- */
6
1
 
7
2
  class ImageLoader {
8
3
  constructor(config = {}) {
@@ -20,26 +15,17 @@ class ImageLoader {
20
15
  this.initIntersectionObserver();
21
16
  }
22
17
 
23
- /**
24
- * Check if a path is an image file
25
- */
26
18
  isImagePath(filePath) {
27
19
  if (!filePath || typeof filePath !== 'string') return false;
28
20
  const ext = this.getExtension(filePath).toLowerCase();
29
21
  return this.config.supportedExts.includes(ext);
30
22
  }
31
23
 
32
- /**
33
- * Extract file extension from path
34
- */
35
24
  getExtension(filePath) {
36
25
  const match = filePath.match(/\.([^.]+)$/);
37
26
  return match ? match[1] : '';
38
27
  }
39
28
 
40
- /**
41
- * Extract image paths from text content
42
- */
43
29
  extractImagePaths(content) {
44
30
  if (typeof content !== 'string') return [];
45
31
 
@@ -56,9 +42,6 @@ class ImageLoader {
56
42
  return [...new Set(paths)];
57
43
  }
58
44
 
59
- /**
60
- * Register images from event
61
- */
62
45
  registerImagesFromEvent(event) {
63
46
  const images = [];
64
47
 
@@ -106,9 +89,6 @@ class ImageLoader {
106
89
  return images;
107
90
  }
108
91
 
109
- /**
110
- * Create image element with lazy loading
111
- */
112
92
  createImageElement(imagePath, options = {}) {
113
93
  const container = document.createElement('div');
114
94
  container.className = 'image-container';
@@ -183,9 +163,6 @@ class ImageLoader {
183
163
  return container;
184
164
  }
185
165
 
186
- /**
187
- * Initialize Intersection Observer for lazy loading
188
- */
189
166
  initIntersectionObserver() {
190
167
  this.intersectionObserver = new IntersectionObserver(
191
168
  (entries) => {
@@ -203,9 +180,6 @@ class ImageLoader {
203
180
  );
204
181
  }
205
182
 
206
- /**
207
- * Setup drawer observer to load images when drawer opens
208
- */
209
183
  setupDrawerObserver(drawerSelector = '.drawer-panel, [role="dialog"]') {
210
184
  const drawers = document.querySelectorAll(drawerSelector);
211
185
  drawers.forEach(drawer => {
@@ -219,9 +193,6 @@ class ImageLoader {
219
193
  });
220
194
  }
221
195
 
222
- /**
223
- * Load all visible images in a container
224
- */
225
196
  loadVisibleImages(container = document) {
226
197
  const images = container.querySelectorAll('img.lazy-image[data-src]');
227
198
  images.forEach(img => {
@@ -231,9 +202,6 @@ class ImageLoader {
231
202
  });
232
203
  }
233
204
 
234
- /**
235
- * Get cached images for a session/conversation
236
- */
237
205
  getImages(eventId = null) {
238
206
  if (!eventId) {
239
207
  return Array.from(this.imageCache.values());
@@ -241,9 +209,6 @@ class ImageLoader {
241
209
  return Array.from(this.imageCache.values()).filter(img => img.eventId === eventId);
242
210
  }
243
211
 
244
- /**
245
- * Clear cache
246
- */
247
212
  clear() {
248
213
  this.imageCache.clear();
249
214
  this.pendingImages.clear();
@@ -13,7 +13,6 @@
13
13
  window.addEventListener('conversation-selected', function(e) {
14
14
  currentConversationId = e.detail.conversationId;
15
15
  hasTerminalContent = false;
16
- // Do not hide terminal tab; it should always be visible
17
16
  fetchConversationAndCheckScripts();
18
17
  });
19
18
 
@@ -61,12 +60,10 @@
61
60
  window.wsClient.rpc('conv.get', { id: currentConversationId })
62
61
  .then(function(data) {
63
62
  currentWorkingDirectory = data.conversation?.workingDirectory || null;
64
- // Always show the terminal tab, even without a working directory
65
63
  showTerminalTab();
66
64
  checkScripts();
67
65
  })
68
66
  .catch(function() {
69
- // Still show terminal tab on error
70
67
  showTerminalTab();
71
68
  checkScripts();
72
69
  });
@@ -1,7 +1,3 @@
1
- /**
2
- * State Barrier - Atomic state machine for conversation management
3
- * Eliminates race conditions through single source of truth and version tracking
4
- */
5
1
 
6
2
  class ConversationState {
7
3
  constructor() {