tycono 0.3.3 → 0.3.5
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/package.json +1 -1
- package/src/tui/app.tsx +36 -24
package/package.json
CHANGED
package/src/tui/app.tsx
CHANGED
|
@@ -258,30 +258,6 @@ export const App: React.FC = () => {
|
|
|
258
258
|
});
|
|
259
259
|
}, []);
|
|
260
260
|
|
|
261
|
-
// Load wave history into SSE events (for Panel Mode Stream tab)
|
|
262
|
-
const loadWaveHistoryEvents = useCallback(async (waveId: string) => {
|
|
263
|
-
try {
|
|
264
|
-
const sessions = api.sessions.filter(s => s.waveId === waveId && s.roleId === 'ceo');
|
|
265
|
-
const allEvents: import('./api').SSEEvent[] = [];
|
|
266
|
-
|
|
267
|
-
for (const ses of sessions.slice(-2)) {
|
|
268
|
-
try {
|
|
269
|
-
const resp = await import('./api').then(m => m.fetchJson<{ events: any[] }>(`/api/jobs/${ses.id}/history`));
|
|
270
|
-
const events = resp?.events ?? [];
|
|
271
|
-
for (const e of events) {
|
|
272
|
-
if (['text', 'tool:start', 'tool:result', 'msg:start', 'msg:done', 'msg:error', 'dispatch:start', 'thinking'].includes(e.type)) {
|
|
273
|
-
allEvents.push(e as import('./api').SSEEvent);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
} catch { /* skip */ }
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
if (allEvents.length > 0) {
|
|
280
|
-
sse.loadHistory(allEvents);
|
|
281
|
-
}
|
|
282
|
-
} catch { /* ignore */ }
|
|
283
|
-
}, [api.sessions, sse]);
|
|
284
|
-
|
|
285
261
|
// Load previous conversation from wave's activity stream into system messages
|
|
286
262
|
const loadPreviousConversation = useCallback(async (waveId: string) => {
|
|
287
263
|
try {
|
|
@@ -384,6 +360,42 @@ export const App: React.FC = () => {
|
|
|
384
360
|
// SSE subscription to focused wave
|
|
385
361
|
const sse = useSSE(focusedWaveId);
|
|
386
362
|
|
|
363
|
+
// Load wave history into SSE events (for Panel Mode Stream tab)
|
|
364
|
+
const historyLoadingRef = useRef<string | null>(null);
|
|
365
|
+
const loadWaveHistoryEvents = useCallback(async (waveId: string) => {
|
|
366
|
+
// Guard: skip if already loading this wave or another load in progress
|
|
367
|
+
if (historyLoadingRef.current === waveId) return;
|
|
368
|
+
historyLoadingRef.current = waveId;
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
const sessions = api.sessions.filter(s => s.waveId === waveId && s.roleId === 'ceo');
|
|
372
|
+
const allEvents: import('./api').SSEEvent[] = [];
|
|
373
|
+
|
|
374
|
+
for (const ses of sessions.slice(-2)) {
|
|
375
|
+
// Abort if wave changed during loading
|
|
376
|
+
if (historyLoadingRef.current !== waveId) return;
|
|
377
|
+
try {
|
|
378
|
+
const resp = await import('./api').then(m => m.fetchJson<{ events: any[] }>(`/api/jobs/${ses.id}/history`));
|
|
379
|
+
const events = resp?.events ?? [];
|
|
380
|
+
for (const e of events) {
|
|
381
|
+
if (['text', 'tool:start', 'msg:start', 'msg:done', 'msg:error', 'dispatch:start', 'thinking'].includes(e.type)) {
|
|
382
|
+
allEvents.push(e as import('./api').SSEEvent);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
} catch { /* skip */ }
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Only apply if still on this wave
|
|
389
|
+
if (historyLoadingRef.current === waveId && allEvents.length > 0) {
|
|
390
|
+
sse.loadHistory(allEvents);
|
|
391
|
+
}
|
|
392
|
+
} catch { /* ignore */ } finally {
|
|
393
|
+
if (historyLoadingRef.current === waveId) {
|
|
394
|
+
historyLoadingRef.current = null;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}, [api.sessions, sse]);
|
|
398
|
+
|
|
387
399
|
// Build org tree — flatRoleIds follows visual top-to-bottom order
|
|
388
400
|
const roles = api.company?.roles ?? [];
|
|
389
401
|
const statuses = api.execStatus?.statuses ?? {};
|