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 +1 -1
- package/src/tui/app.tsx +61 -1
- package/src/tui/hooks/useCommand.ts +15 -2
package/package.json
CHANGED
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
|
|