tycono 0.1.111 → 0.1.113

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tycono",
3
- "version": "0.1.111",
3
+ "version": "0.1.113",
4
4
  "description": "Build an AI company. Watch them work.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -338,36 +338,44 @@ class SupervisorHeartbeat {
338
338
  if (waveCeoSessions.length === 0) return '';
339
339
 
340
340
  const exchanges: Array<{ role: 'ceo' | 'supervisor'; text: string }> = [];
341
- for (const ses of waveCeoSessions.slice(-3)) { // Last 3 sessions only
341
+ for (const ses of waveCeoSessions.slice(-3)) {
342
342
  if (!ActivityStream.exists(ses.id)) continue;
343
343
  const events = ActivityStream.readAll(ses.id);
344
344
 
345
- let lastSupervisorText = '';
345
+ let currentText = '';
346
346
  for (const e of events) {
347
- if (e.type === 'msg:start' && e.data.task) {
348
- const task = String(e.data.task);
349
- const directiveMatch = task.match(/\[CEO (?:Supervisor|Question)\]\s*(.*?)(?:\n|$)/);
350
- if (directiveMatch) {
351
- // Flush previous supervisor response
352
- if (lastSupervisorText) {
353
- exchanges.push({ role: 'supervisor', text: lastSupervisorText.slice(0, 100) });
354
- lastSupervisorText = '';
355
- }
356
- exchanges.push({ role: 'ceo', text: directiveMatch[1].slice(0, 80) });
347
+ // New turn starts flush accumulated text from previous turn
348
+ if (e.type === 'msg:start') {
349
+ if (currentText.trim()) {
350
+ exchanges.push({ role: 'supervisor', text: currentText.trim().slice(0, 100) });
351
+ currentText = '';
352
+ }
353
+ // Extract CEO directive
354
+ const task = String(e.data.task ?? '');
355
+ const match = task.match(/\[CEO (?:Supervisor|Question)\]\s*(.*?)(?:\n|$)/);
356
+ if (match) {
357
+ exchanges.push({ role: 'ceo', text: match[1].slice(0, 80) });
357
358
  }
358
359
  }
359
- // Accumulate text chunks into one response (not one entry per chunk)
360
+ // Accumulate supervisor response text
360
361
  if (e.type === 'text' && e.roleId === 'ceo') {
361
362
  const text = String(e.data.text ?? '').trim();
362
363
  if (text && !text.startsWith('#') && !text.startsWith('\u26D4')) {
363
- lastSupervisorText += text + ' ';
364
+ currentText += text + ' ';
364
365
  }
365
366
  }
366
- if (e.type === 'msg:done' && lastSupervisorText) {
367
- exchanges.push({ role: 'supervisor', text: lastSupervisorText.trim().slice(0, 100) });
368
- lastSupervisorText = '';
367
+ // Turn boundary flush
368
+ if (e.type === 'msg:done' || e.type === 'msg:awaiting_input' || e.type === 'msg:error') {
369
+ if (currentText.trim()) {
370
+ exchanges.push({ role: 'supervisor', text: currentText.trim().slice(0, 100) });
371
+ currentText = '';
372
+ }
369
373
  }
370
374
  }
375
+ // Flush any remaining text
376
+ if (currentText.trim()) {
377
+ exchanges.push({ role: 'supervisor', text: currentText.trim().slice(0, 100) });
378
+ }
371
379
  }
372
380
 
373
381
  if (exchanges.length === 0) return '';
package/src/tui/app.tsx CHANGED
@@ -293,8 +293,10 @@ export const App: React.FC = () => {
293
293
  directive: pw.directive || '',
294
294
  startedAt: pw.startedAt ? new Date(pw.startedAt).getTime() : 0,
295
295
  }));
296
+ // Sort by startedAt ascending (oldest first = Wave 1)
297
+ pastEntries.sort((a, b) => a.startedAt - b.startedAt);
296
298
  setWaves(pastEntries);
297
- // Focus last wave user can /new if they want a fresh one
299
+ // Focus most recent wave (last in sorted list)
298
300
  setFocusedWaveId(pastEntries[pastEntries.length - 1]?.waveId ?? null);
299
301
  } else if (api.loaded) {
300
302
  // No active waves, no past waves — fresh start