tycono 0.3.4 → 0.3.6

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/tui/app.tsx +17 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tycono",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Build an AI company. Watch them work.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/tui/app.tsx CHANGED
@@ -361,27 +361,41 @@ export const App: React.FC = () => {
361
361
  const sse = useSSE(focusedWaveId);
362
362
 
363
363
  // Load wave history into SSE events (for Panel Mode Stream tab)
364
+ const historyLoadingRef = useRef<string | null>(null);
364
365
  const loadWaveHistoryEvents = useCallback(async (waveId: string) => {
366
+ // Guard: skip if already loading this wave
367
+ if (historyLoadingRef.current === waveId) return;
368
+ historyLoadingRef.current = waveId;
369
+ // Wait for SSE reconnection to settle (it calls setEvents([]) on connect)
370
+ await new Promise(r => setTimeout(r, 500));
371
+
365
372
  try {
366
373
  const sessions = api.sessions.filter(s => s.waveId === waveId && s.roleId === 'ceo');
367
374
  const allEvents: import('./api').SSEEvent[] = [];
368
375
 
369
376
  for (const ses of sessions.slice(-2)) {
377
+ // Abort if wave changed during loading
378
+ if (historyLoadingRef.current !== waveId) return;
370
379
  try {
371
380
  const resp = await import('./api').then(m => m.fetchJson<{ events: any[] }>(`/api/jobs/${ses.id}/history`));
372
381
  const events = resp?.events ?? [];
373
382
  for (const e of events) {
374
- if (['text', 'tool:start', 'tool:result', 'msg:start', 'msg:done', 'msg:error', 'dispatch:start', 'thinking'].includes(e.type)) {
383
+ if (['text', 'tool:start', 'msg:start', 'msg:done', 'msg:error', 'dispatch:start', 'thinking'].includes(e.type)) {
375
384
  allEvents.push(e as import('./api').SSEEvent);
376
385
  }
377
386
  }
378
387
  } catch { /* skip */ }
379
388
  }
380
389
 
381
- if (allEvents.length > 0) {
390
+ // Only apply if still on this wave
391
+ if (historyLoadingRef.current === waveId && allEvents.length > 0) {
382
392
  sse.loadHistory(allEvents);
383
393
  }
384
- } catch { /* ignore */ }
394
+ } catch { /* ignore */ } finally {
395
+ if (historyLoadingRef.current === waveId) {
396
+ historyLoadingRef.current = null;
397
+ }
398
+ }
385
399
  }, [api.sessions, sse]);
386
400
 
387
401
  // Build org tree — flatRoleIds follows visual top-to-bottom order