tycono 0.1.96-beta.34 → 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/components/PanelMode.tsx +12 -24
- 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');
|
|
@@ -172,20 +172,10 @@ export const PanelMode: React.FC<PanelModeProps> = ({
|
|
|
172
172
|
{/* Left: Wave title + Org Tree + Wave tabs */}
|
|
173
173
|
<Box flexDirection="column" width={leftWidth}>
|
|
174
174
|
{/* Wave title */}
|
|
175
|
-
|
|
176
|
-
<
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
<Text color="gray"> </Text>
|
|
180
|
-
<Text color="white" wrap="truncate">
|
|
181
|
-
{focusedWave?.directive ? focusedWave.directive.slice(0, leftWidth - 6) : '(idle)'}
|
|
182
|
-
</Text>
|
|
183
|
-
</Box>
|
|
184
|
-
|
|
185
|
-
{/* Session count */}
|
|
186
|
-
{waveSessionCount > 0 && (
|
|
187
|
-
<Box paddingX={1}>
|
|
188
|
-
<Text color="gray">{waveSessionCount} sessions</Text>
|
|
175
|
+
{focusedWaveIndex > 0 && (
|
|
176
|
+
<Box paddingX={1} marginBottom={0}>
|
|
177
|
+
<Text color="green" bold>Wave {focusedWaveIndex}</Text>
|
|
178
|
+
{waveSessionCount > 0 && <Text color="gray"> ({waveSessionCount})</Text>}
|
|
189
179
|
</Box>
|
|
190
180
|
)}
|
|
191
181
|
|
|
@@ -198,21 +188,19 @@ export const PanelMode: React.FC<PanelModeProps> = ({
|
|
|
198
188
|
ceoStatus={waveScopedStatuses['ceo'] ?? 'idle'}
|
|
199
189
|
/>
|
|
200
190
|
|
|
201
|
-
{/* Wave tabs at bottom */}
|
|
191
|
+
{/* Wave tabs at bottom — compact inline */}
|
|
202
192
|
{waves.length > 1 && (
|
|
203
193
|
<Box paddingX={1} marginTop={1}>
|
|
194
|
+
<Text color="gray">W </Text>
|
|
204
195
|
{waves.map((w, i) => {
|
|
205
196
|
const isFocused = w.waveId === focusedWaveId;
|
|
206
197
|
return (
|
|
207
|
-
<
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
{` ${i + 1} `}
|
|
214
|
-
</Text>
|
|
215
|
-
</Box>
|
|
198
|
+
<Text key={w.waveId}
|
|
199
|
+
color={isFocused ? 'green' : 'gray'}
|
|
200
|
+
bold={isFocused}
|
|
201
|
+
>
|
|
202
|
+
{isFocused ? `[${i + 1}]` : ` ${i + 1} `}
|
|
203
|
+
</Text>
|
|
216
204
|
);
|
|
217
205
|
})}
|
|
218
206
|
</Box>
|
|
@@ -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
|
|