tycono 0.1.109 → 0.1.111

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.109",
3
+ "version": "0.1.111",
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,41 +329,60 @@ 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
- const history: string[] = [];
328
- for (const ses of waveCeoSessions) {
340
+ const exchanges: Array<{ role: 'ceo' | 'supervisor'; text: string }> = [];
341
+ for (const ses of waveCeoSessions.slice(-3)) { // Last 3 sessions only
329
342
  if (!ActivityStream.exists(ses.id)) continue;
330
343
  const events = ActivityStream.readAll(ses.id);
331
344
 
332
- // Extract CEO directives (from messages) and supervisor text responses
345
+ let lastSupervisorText = '';
333
346
  for (const e of events) {
334
347
  if (e.type === 'msg:start' && e.data.task) {
335
- // Extract directive from task (remove system prompt noise)
336
348
  const task = String(e.data.task);
337
349
  const directiveMatch = task.match(/\[CEO (?:Supervisor|Question)\]\s*(.*?)(?:\n|$)/);
338
350
  if (directiveMatch) {
339
- history.push(`CEO: "${directiveMatch[1].slice(0, 100)}"`);
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) });
340
357
  }
341
358
  }
359
+ // Accumulate text chunks into one response (not one entry per chunk)
342
360
  if (e.type === 'text' && e.roleId === 'ceo') {
343
361
  const text = String(e.data.text ?? '').trim();
344
- if (text && text.length > 10 && !text.startsWith('#') && !text.startsWith('')) {
345
- history.push(`Supervisor: ${text.slice(0, 150)}`);
362
+ if (text && !text.startsWith('#') && !text.startsWith('\u26D4')) {
363
+ lastSupervisorText += text + ' ';
346
364
  }
347
365
  }
366
+ if (e.type === 'msg:done' && lastSupervisorText) {
367
+ exchanges.push({ role: 'supervisor', text: lastSupervisorText.trim().slice(0, 100) });
368
+ lastSupervisorText = '';
369
+ }
348
370
  }
349
371
  }
350
372
 
351
- if (history.length === 0) return '';
373
+ if (exchanges.length === 0) return '';
374
+
375
+ // Keep last 4 exchanges (2 Q&A pairs), cap total at 500 chars
376
+ const recent = exchanges.slice(-4);
377
+ const formatted = recent.map(e =>
378
+ e.role === 'ceo' ? `CEO: "${e.text}"` : `→ ${e.text}`
379
+ ).join('\n');
352
380
 
353
- // Keep last 10 exchanges to fit in context
354
- const recent = history.slice(-10);
355
- return `\n[Previous Conversation in Wave ${waveId}]\n${recent.join('\n')}\n`;
381
+ const result = formatted.length > 500
382
+ ? `\n[Previous conversation]\n${formatted.slice(-500)}\n`
383
+ : `\n[Previous conversation]\n${formatted}\n`;
384
+ console.log(`[WaveHistory] Result (${result.length} chars): ${result.slice(0, 200)}`);
385
+ return result;
356
386
  } catch {
357
387
  return '';
358
388
  }