tycono 0.1.96-beta.35 → 0.1.96-beta.36

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.96-beta.35",
3
+ "version": "0.1.96-beta.36",
4
4
  "description": "Build an AI company. Watch them work.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/tui/app.tsx CHANGED
@@ -395,6 +395,64 @@ export const App: React.FC = () => {
395
395
  api.refresh();
396
396
  break;
397
397
  }
398
+ case 'docs': {
399
+ // Extract written/edited files from SSE events in current wave
400
+ const writtenFiles = new Set<string>();
401
+ for (const event of sse.events) {
402
+ if (event.type === 'tool:start') {
403
+ const name = (event.data.name as string) ?? '';
404
+ const input = event.data.input as Record<string, unknown> | undefined;
405
+ if (['Write', 'Edit', 'NotebookEdit'].includes(name) && input?.file_path) {
406
+ writtenFiles.add(String(input.file_path));
407
+ }
408
+ }
409
+ }
410
+ if (writtenFiles.size === 0) {
411
+ addSystemMessage('No files created/modified in this wave.', 'gray');
412
+ } else {
413
+ addSystemMessage(`Files in this wave (${writtenFiles.size}):`, 'cyan');
414
+ for (const f of writtenFiles) {
415
+ const short = f.split('/').slice(-3).join('/');
416
+ addSystemMessage(` ${short}`, 'white');
417
+ }
418
+ addSystemMessage(' /read <path> to preview | /open <path> to edit', 'gray');
419
+ }
420
+ break;
421
+ }
422
+ case 'read_file': {
423
+ const filePath = result.message;
424
+ try {
425
+ const content = await import('node:fs').then(fs =>
426
+ fs.readFileSync(filePath, 'utf-8')
427
+ );
428
+ const lines = content.split('\n');
429
+ const preview = lines.slice(0, 30);
430
+ addSystemMessage(`\u2500\u2500 ${filePath.split('/').slice(-2).join('/')} \u2500\u2500`, 'cyan');
431
+ for (const line of preview) {
432
+ addSystemMessage(line, 'white');
433
+ }
434
+ if (lines.length > 30) {
435
+ addSystemMessage(` ... +${lines.length - 30} more lines (/open to see full)`, 'gray');
436
+ }
437
+ addSystemMessage('\u2500'.repeat(40), 'gray');
438
+ } catch (err) {
439
+ addSystemMessage(`Cannot read: ${err instanceof Error ? err.message : 'unknown'}`, 'red');
440
+ }
441
+ break;
442
+ }
443
+ case 'open_file': {
444
+ const filePath = result.message;
445
+ const editor = process.env.EDITOR || process.env.VISUAL || 'less';
446
+ try {
447
+ const { execSync } = await import('node:child_process');
448
+ execSync(`${editor} "${filePath}"`, { stdio: 'inherit' });
449
+ addSystemMessage(`Opened: ${filePath}`, 'green');
450
+ } catch {
451
+ // Fallback to /read
452
+ addSystemMessage(`Cannot open with ${editor}. Use /read instead.`, 'yellow');
453
+ }
454
+ break;
455
+ }
398
456
  case 'error':
399
457
  addSystemMessage(result.message, 'red');
400
458
  break;
@@ -404,11 +462,13 @@ export const App: React.FC = () => {
404
462
  addSystemMessage(' /new [text] Create new wave', 'white');
405
463
  addSystemMessage(' /waves List all waves', 'white');
406
464
  addSystemMessage(' /focus <n> Switch to wave n', 'white');
465
+ addSystemMessage(' /docs Files created in this wave', 'white');
466
+ addSystemMessage(' /read <path> Preview file content', 'white');
467
+ addSystemMessage(' /open <path> Open in $EDITOR', 'white');
407
468
  addSystemMessage(' /agents Wave \u2192 Role \u2192 Session tree', 'white');
408
469
  addSystemMessage(' /sessions Sessions + ports (kill/cleanup)', 'white');
409
470
  addSystemMessage(' /kill <id> Kill a session', 'white');
410
471
  addSystemMessage(' /cleanup Remove dead sessions', 'white');
411
- addSystemMessage(' /status Current status', 'white');
412
472
  addSystemMessage(' /help This help', 'white');
413
473
  addSystemMessage(' /quit Exit', 'white');
414
474
  addSystemMessage('Keys: [Tab] team panel [1-9] wave [Esc] back [Ctrl+C] quit', 'gray');
@@ -16,7 +16,7 @@
16
16
  */
17
17
 
18
18
  import { useCallback } from 'react';
19
- import { dispatchWave, sendDirective, fetchJson, killSession, cleanupSessions } from '../api';
19
+ import { dispatchWave, sendDirective, fetchJson, killSession, cleanupSessions, fetchActiveSessions } from '../api';
20
20
 
21
21
  export interface WaveInfo {
22
22
  waveId: string;
@@ -25,7 +25,7 @@ export interface WaveInfo {
25
25
  }
26
26
 
27
27
  export interface CommandResult {
28
- type: 'success' | 'error' | 'info' | 'wave_started' | 'directive_sent' | 'stopped' | 'quit' | 'help' | 'panel' | 'waves_list' | 'focus_changed' | 'agents' | 'ports' | 'sessions' | 'cleanup';
28
+ type: 'success' | 'error' | 'info' | 'wave_started' | 'directive_sent' | 'stopped' | 'quit' | 'help' | 'panel' | 'waves_list' | 'focus_changed' | 'agents' | 'ports' | 'sessions' | 'cleanup' | 'docs' | 'read_file' | 'open_file';
29
29
  message: string;
30
30
  waveId?: string;
31
31
  }
@@ -123,6 +123,19 @@ export function useCommand(options: UseCommandOptions) {
123
123
  }
124
124
  }
125
125
 
126
+ case 'docs':
127
+ return { type: 'docs', message: '__docs__' };
128
+
129
+ case 'read': {
130
+ if (!args) return { type: 'error', message: 'Usage: /read <file_path>' };
131
+ return { type: 'read_file', message: args.trim() };
132
+ }
133
+
134
+ case 'open': {
135
+ if (!args) return { type: 'error', message: 'Usage: /open <file_path>' };
136
+ return { type: 'open_file', message: args.trim() };
137
+ }
138
+
126
139
  case 'status':
127
140
  return { type: 'info', message: '__status__' };
128
141