tycono 0.1.110 → 0.1.112

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.110",
3
+ "version": "0.1.112",
4
4
  "description": "Build an AI company. Watch them work.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,6 +14,8 @@
14
14
  import { executionManager, type Execution } from './execution-manager.js';
15
15
  import { createSession, getSession, listSessions, addMessage, type Message } from './session-store.js';
16
16
  import { buildOrgTree, getSubordinates } from '../engine/org-tree.js';
17
+ import fs from 'node:fs';
18
+ import path from 'node:path';
17
19
  import { COMPANY_ROOT } from './file-reader.js';
18
20
  import { ActivityStream } from './activity-stream.js';
19
21
  import { saveCompletedWave } from './wave-tracker.js';
@@ -138,9 +140,18 @@ class SupervisorHeartbeat {
138
140
  if (waveSessions.length > 0) {
139
141
  // Restore supervisor state for this wave
140
142
  const ceoSession = waveSessions.find(s => s.roleId === 'ceo');
143
+ // Read original directive from wave artifact file (not the new text)
144
+ let originalDirective = '';
145
+ try {
146
+ const waveFile = path.join(COMPANY_ROOT, 'operations', 'waves', `${waveId}.json`);
147
+ if (fs.existsSync(waveFile)) {
148
+ const waveData = JSON.parse(fs.readFileSync(waveFile, 'utf-8'));
149
+ originalDirective = waveData.directive ?? '';
150
+ }
151
+ } catch { /* ignore */ }
141
152
  state = {
142
153
  waveId,
143
- directive: text,
154
+ directive: originalDirective || text,
144
155
  continuous: false,
145
156
  supervisorSessionId: ceoSession?.id ?? null,
146
157
  executionId: null,
@@ -318,43 +329,53 @@ class SupervisorHeartbeat {
318
329
  try {
319
330
  // Find CEO sessions for this wave from session-store
320
331
  const allSessions = listSessions();
332
+ console.log(`[WaveHistory] Loading for wave=${waveId}, total sessions=${allSessions.length}`);
321
333
  const waveCeoSessions = allSessions
322
334
  .filter(s => s.waveId === waveId && s.roleId === 'ceo')
323
335
  .sort((a, b) => a.createdAt.localeCompare(b.createdAt));
324
336
 
337
+ console.log(`[WaveHistory] Found ${waveCeoSessions.length} CEO sessions for wave=${waveId}: ${waveCeoSessions.map(s => s.id).join(', ')}`);
325
338
  if (waveCeoSessions.length === 0) return '';
326
339
 
327
340
  const exchanges: Array<{ role: 'ceo' | 'supervisor'; text: string }> = [];
328
- for (const ses of waveCeoSessions.slice(-3)) { // Last 3 sessions only
341
+ for (const ses of waveCeoSessions.slice(-3)) {
329
342
  if (!ActivityStream.exists(ses.id)) continue;
330
343
  const events = ActivityStream.readAll(ses.id);
331
344
 
332
- let lastSupervisorText = '';
345
+ let currentText = '';
333
346
  for (const e of events) {
334
- if (e.type === 'msg:start' && e.data.task) {
335
- const task = String(e.data.task);
336
- const directiveMatch = task.match(/\[CEO (?:Supervisor|Question)\]\s*(.*?)(?:\n|$)/);
337
- if (directiveMatch) {
338
- // Flush previous supervisor response
339
- if (lastSupervisorText) {
340
- exchanges.push({ role: 'supervisor', text: lastSupervisorText.slice(0, 100) });
341
- lastSupervisorText = '';
342
- }
343
- 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) });
344
358
  }
345
359
  }
346
- // Accumulate text chunks into one response (not one entry per chunk)
360
+ // Accumulate supervisor response text
347
361
  if (e.type === 'text' && e.roleId === 'ceo') {
348
362
  const text = String(e.data.text ?? '').trim();
349
363
  if (text && !text.startsWith('#') && !text.startsWith('\u26D4')) {
350
- lastSupervisorText += text + ' ';
364
+ currentText += text + ' ';
351
365
  }
352
366
  }
353
- if (e.type === 'msg:done' && lastSupervisorText) {
354
- exchanges.push({ role: 'supervisor', text: lastSupervisorText.trim().slice(0, 100) });
355
- 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
+ }
356
373
  }
357
374
  }
375
+ // Flush any remaining text
376
+ if (currentText.trim()) {
377
+ exchanges.push({ role: 'supervisor', text: currentText.trim().slice(0, 100) });
378
+ }
358
379
  }
359
380
 
360
381
  if (exchanges.length === 0) return '';
@@ -365,8 +386,11 @@ class SupervisorHeartbeat {
365
386
  e.role === 'ceo' ? `CEO: "${e.text}"` : `→ ${e.text}`
366
387
  ).join('\n');
367
388
 
368
- if (formatted.length > 500) return `\n[Previous conversation]\n${formatted.slice(-500)}\n`;
369
- return `\n[Previous conversation]\n${formatted}\n`;
389
+ const result = formatted.length > 500
390
+ ? `\n[Previous conversation]\n${formatted.slice(-500)}\n`
391
+ : `\n[Previous conversation]\n${formatted}\n`;
392
+ console.log(`[WaveHistory] Result (${result.length} chars): ${result.slice(0, 200)}`);
393
+ return result;
370
394
  } catch {
371
395
  return '';
372
396
  }