tycono 0.1.96-beta.22 → 0.1.96-beta.23
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
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* CommandMode — scrollable terminal mode (like Claude Code)
|
|
3
3
|
*
|
|
4
4
|
* Uses Ink's <Static> to push past output into terminal scrollback.
|
|
5
|
-
*
|
|
6
|
-
* User can scroll up with mouse wheel to see history.
|
|
5
|
+
* Shows full output: text, tools, thinking, dispatch — no aggressive truncation.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
import React, { useState, useCallback, useRef } from 'react';
|
|
@@ -32,17 +31,13 @@ interface CommandModeProps {
|
|
|
32
31
|
|
|
33
32
|
let lineCounter = 0;
|
|
34
33
|
|
|
35
|
-
/** Filter out system prompt
|
|
34
|
+
/** Filter out only truly internal system prompt fragments */
|
|
36
35
|
function isSystemNoise(text: string): boolean {
|
|
37
36
|
const t = text.trim();
|
|
38
37
|
if (!t) return true;
|
|
39
|
-
|
|
40
|
-
if (t.startsWith('
|
|
41
|
-
if (t.startsWith('
|
|
42
|
-
if (t.startsWith('[Question from')) return true;
|
|
43
|
-
if (t.includes('\u26D4 AKB Rule')) return true;
|
|
44
|
-
if (t.includes('\u26D4 Read the')) return true;
|
|
45
|
-
if (t.startsWith('\u26D4')) return true;
|
|
38
|
+
// Only filter the injected supervisor system prompt header
|
|
39
|
+
if (t.startsWith('[CEO Supervisor]') && t.includes('Your Role')) return true;
|
|
40
|
+
if (t.startsWith('\u26D4 AKB Rule:')) return true;
|
|
46
41
|
return false;
|
|
47
42
|
}
|
|
48
43
|
|
|
@@ -59,7 +54,7 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
59
54
|
if (isSupervisor) {
|
|
60
55
|
return {
|
|
61
56
|
id: ++lineCounter,
|
|
62
|
-
text
|
|
57
|
+
text,
|
|
63
58
|
color: 'white',
|
|
64
59
|
};
|
|
65
60
|
} else {
|
|
@@ -67,17 +62,30 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
67
62
|
id: ++lineCounter,
|
|
68
63
|
prefix: event.roleId,
|
|
69
64
|
prefixColor: roleColor,
|
|
70
|
-
text
|
|
65
|
+
text,
|
|
71
66
|
color: 'white',
|
|
72
67
|
indent: true,
|
|
73
68
|
};
|
|
74
69
|
}
|
|
75
70
|
}
|
|
76
71
|
|
|
72
|
+
case 'thinking': {
|
|
73
|
+
const text = ((event.data.text as string) ?? '').slice(0, 120);
|
|
74
|
+
if (!text.trim()) return null;
|
|
75
|
+
return {
|
|
76
|
+
id: ++lineCounter,
|
|
77
|
+
prefix: isSupervisor ? undefined : event.roleId,
|
|
78
|
+
prefixColor: roleColor,
|
|
79
|
+
text: `\uD83D\uDCAD ${text}`,
|
|
80
|
+
color: 'gray',
|
|
81
|
+
indent: !isSupervisor,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
77
85
|
case 'dispatch:start': {
|
|
78
86
|
const target = (event.data.targetRole as string) ?? '';
|
|
79
87
|
const task = ((event.data.task as string) ?? '');
|
|
80
|
-
const cleanTask = task.replace(/\u26D4[^\u26D4]*\u26D4[^"]*/g, '').trim().slice(0,
|
|
88
|
+
const cleanTask = task.replace(/\u26D4[^\u26D4]*\u26D4[^"]*/g, '').trim().slice(0, 80);
|
|
81
89
|
if (isSupervisor) {
|
|
82
90
|
return {
|
|
83
91
|
id: ++lineCounter,
|
|
@@ -89,7 +97,7 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
89
97
|
id: ++lineCounter,
|
|
90
98
|
prefix: event.roleId,
|
|
91
99
|
prefixColor: roleColor,
|
|
92
|
-
text: `\u2192 ${target} \uBC30\uC815`,
|
|
100
|
+
text: `\u2192 ${target} \uBC30\uC815${cleanTask ? ': ' + cleanTask : ''}`,
|
|
93
101
|
color: 'yellow',
|
|
94
102
|
indent: true,
|
|
95
103
|
};
|
|
@@ -99,7 +107,7 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
99
107
|
const target = (event.data.targetRole as string) ?? '';
|
|
100
108
|
return {
|
|
101
109
|
id: ++lineCounter,
|
|
102
|
-
prefix: event.roleId,
|
|
110
|
+
prefix: isSupervisor ? undefined : event.roleId,
|
|
103
111
|
prefixColor: roleColor,
|
|
104
112
|
text: `\u2190 ${target} \uC644\uB8CC`,
|
|
105
113
|
color: 'yellow',
|
|
@@ -113,31 +121,43 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
113
121
|
let detail = '';
|
|
114
122
|
if (input && typeof input === 'object') {
|
|
115
123
|
const inp = input as Record<string, unknown>;
|
|
116
|
-
if (inp.file_path) detail = ` ${String(inp.file_path)
|
|
117
|
-
else if (inp.command) detail = ` ${String(inp.command).slice(0,
|
|
124
|
+
if (inp.file_path) detail = ` ${String(inp.file_path)}`;
|
|
125
|
+
else if (inp.command) detail = ` ${String(inp.command).slice(0, 80)}`;
|
|
126
|
+
else if (inp.pattern) detail = ` ${String(inp.pattern)}`;
|
|
127
|
+
else if (inp.description) detail = ` ${String(inp.description).slice(0, 60)}`;
|
|
118
128
|
}
|
|
129
|
+
return {
|
|
130
|
+
id: ++lineCounter,
|
|
131
|
+
prefix: isSupervisor ? undefined : event.roleId,
|
|
132
|
+
prefixColor: roleColor,
|
|
133
|
+
text: ` \u2192 ${toolName}${detail}`,
|
|
134
|
+
color: 'gray',
|
|
135
|
+
indent: !isSupervisor,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
119
138
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
id: ++lineCounter,
|
|
123
|
-
text: ` \u2192 ${toolName}${detail}`,
|
|
124
|
-
color: 'gray',
|
|
125
|
-
};
|
|
126
|
-
}
|
|
139
|
+
case 'tool:result': {
|
|
140
|
+
const toolName = (event.data.name as string) ?? 'tool';
|
|
127
141
|
return {
|
|
128
142
|
id: ++lineCounter,
|
|
129
|
-
prefix: event.roleId,
|
|
143
|
+
prefix: isSupervisor ? undefined : event.roleId,
|
|
130
144
|
prefixColor: roleColor,
|
|
131
|
-
text:
|
|
145
|
+
text: ` \u2190 ${toolName} done`,
|
|
132
146
|
color: 'gray',
|
|
133
|
-
indent:
|
|
147
|
+
indent: !isSupervisor,
|
|
134
148
|
};
|
|
135
149
|
}
|
|
136
150
|
|
|
137
151
|
case 'msg:start': {
|
|
138
|
-
if (isSupervisor) return null;
|
|
139
152
|
const task = ((event.data.task as string) ?? '');
|
|
140
|
-
const cleanTask = task.replace(/\u26D4[^\u26D4]*\u26D4[^"]*/g, '').trim().slice(0,
|
|
153
|
+
const cleanTask = task.replace(/\u26D4[^\u26D4]*\u26D4[^"]*/g, '').trim().slice(0, 60);
|
|
154
|
+
if (isSupervisor) {
|
|
155
|
+
return {
|
|
156
|
+
id: ++lineCounter,
|
|
157
|
+
text: `\u25B6 Supervisor started${cleanTask ? ': ' + cleanTask : ''}`,
|
|
158
|
+
color: 'cyan',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
141
161
|
return {
|
|
142
162
|
id: ++lineCounter,
|
|
143
163
|
prefix: event.roleId,
|
|
@@ -150,7 +170,13 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
150
170
|
|
|
151
171
|
case 'msg:done': {
|
|
152
172
|
const turns = event.data.turns as number | undefined;
|
|
153
|
-
if (isSupervisor)
|
|
173
|
+
if (isSupervisor) {
|
|
174
|
+
return {
|
|
175
|
+
id: ++lineCounter,
|
|
176
|
+
text: `\u2713 Supervisor done${turns ? ` (${turns} turns)` : ''}`,
|
|
177
|
+
color: 'cyan',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
154
180
|
return {
|
|
155
181
|
id: ++lineCounter,
|
|
156
182
|
prefix: event.roleId,
|
|
@@ -162,8 +188,14 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
162
188
|
}
|
|
163
189
|
|
|
164
190
|
case 'msg:error': {
|
|
165
|
-
|
|
166
|
-
|
|
191
|
+
const error = ((event.data.error as string) ?? (event.data.message as string) ?? '').slice(0, 120);
|
|
192
|
+
if (isSupervisor) {
|
|
193
|
+
return {
|
|
194
|
+
id: ++lineCounter,
|
|
195
|
+
text: `\u2717 Supervisor error: ${error}`,
|
|
196
|
+
color: 'red',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
167
199
|
return {
|
|
168
200
|
id: ++lineCounter,
|
|
169
201
|
prefix: event.roleId,
|
|
@@ -174,20 +206,23 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
|
|
|
174
206
|
};
|
|
175
207
|
}
|
|
176
208
|
|
|
177
|
-
case 'msg:awaiting_input':
|
|
209
|
+
case 'msg:awaiting_input': {
|
|
210
|
+
const question = (event.data.question as string) ?? '';
|
|
178
211
|
return {
|
|
179
212
|
id: ++lineCounter,
|
|
180
|
-
|
|
213
|
+
prefix: isSupervisor ? undefined : event.roleId,
|
|
214
|
+
prefixColor: roleColor,
|
|
215
|
+
text: question ? `? ${question.slice(0, 100)}` : '? Awaiting input...',
|
|
181
216
|
color: 'yellow',
|
|
217
|
+
indent: !isSupervisor,
|
|
182
218
|
};
|
|
219
|
+
}
|
|
183
220
|
|
|
184
|
-
// Hidden
|
|
185
|
-
case 'thinking':
|
|
221
|
+
// Hidden (truly internal)
|
|
186
222
|
case 'heartbeat:tick':
|
|
187
223
|
case 'heartbeat:skip':
|
|
188
224
|
case 'prompt:assembled':
|
|
189
225
|
case 'trace:response':
|
|
190
|
-
case 'tool:result':
|
|
191
226
|
return null;
|
|
192
227
|
|
|
193
228
|
default:
|
|
@@ -205,7 +240,7 @@ function StreamLineRow({ line }: { line: StreamLine }) {
|
|
|
205
240
|
{(line.prefix).padEnd(12)}
|
|
206
241
|
</Text>
|
|
207
242
|
)}
|
|
208
|
-
<Text color={line.color}>{line.text}</Text>
|
|
243
|
+
<Text color={line.color} wrap="wrap">{line.text}</Text>
|
|
209
244
|
</Box>
|
|
210
245
|
);
|
|
211
246
|
}
|
|
@@ -230,11 +265,9 @@ export const CommandMode: React.FC<CommandModeProps> = ({
|
|
|
230
265
|
const allLines = [...systemMessages, ...eventLines];
|
|
231
266
|
|
|
232
267
|
// Split into committed (scrollback) and live (re-rendered)
|
|
233
|
-
// Lines up to committedRef are frozen in scrollback
|
|
234
268
|
const newCommitted = allLines.slice(committedRef.current);
|
|
235
|
-
if (newCommitted.length >
|
|
236
|
-
|
|
237
|
-
const toCommit = newCommitted.slice(0, -5);
|
|
269
|
+
if (newCommitted.length > 8) {
|
|
270
|
+
const toCommit = newCommitted.slice(0, -8);
|
|
238
271
|
committedRef.current += toCommit.length;
|
|
239
272
|
}
|
|
240
273
|
|
|
@@ -251,12 +284,12 @@ export const CommandMode: React.FC<CommandModeProps> = ({
|
|
|
251
284
|
|
|
252
285
|
return (
|
|
253
286
|
<Box flexDirection="column">
|
|
254
|
-
{/* Committed lines → pushed to terminal scrollback
|
|
287
|
+
{/* Committed lines → pushed to terminal scrollback */}
|
|
255
288
|
<Static items={committedLines}>
|
|
256
289
|
{(line) => <StreamLineRow key={line.id} line={line} />}
|
|
257
290
|
</Static>
|
|
258
291
|
|
|
259
|
-
{/* Live lines → re-rendered
|
|
292
|
+
{/* Live lines → re-rendered */}
|
|
260
293
|
{liveLines.map((line) => (
|
|
261
294
|
<StreamLineRow key={line.id} line={line} />
|
|
262
295
|
))}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* StreamView — detailed stream panel for Panel Mode (right side)
|
|
3
3
|
* Shows full event details with timestamps for a selected role.
|
|
4
|
-
*
|
|
4
|
+
* No aggressive truncation — shows tools, thinking, dispatch like Claude Code.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
@@ -26,11 +26,11 @@ function formatTime(ts: string): string {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function renderEvent(event: SSEEvent
|
|
29
|
+
function renderEvent(event: SSEEvent): { content: string; contentColor: string } | null {
|
|
30
30
|
switch (event.type) {
|
|
31
31
|
case 'msg:start':
|
|
32
32
|
return {
|
|
33
|
-
content: `\u25B6 Started: ${(event.data.task as string)?.slice(0,
|
|
33
|
+
content: `\u25B6 Started: ${(event.data.task as string)?.replace(/\u26D4[^\u26D4]*\u26D4[^"]*/g, '').trim().slice(0, 80) ?? ''}`,
|
|
34
34
|
contentColor: 'green',
|
|
35
35
|
};
|
|
36
36
|
|
|
@@ -44,16 +44,23 @@ function renderEvent(event: SSEEvent, allRoleIds: string[]): { content: string;
|
|
|
44
44
|
|
|
45
45
|
case 'msg:error':
|
|
46
46
|
return {
|
|
47
|
-
content: `\u2717 Error: ${(event.data.error as string)
|
|
47
|
+
content: `\u2717 Error: ${(event.data.error as string ?? event.data.message as string ?? '').slice(0, 120)}`,
|
|
48
48
|
contentColor: 'red',
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
case 'text': {
|
|
52
|
-
const text = ((event.data.text as string) ?? '')
|
|
52
|
+
const text = ((event.data.text as string) ?? '');
|
|
53
53
|
if (!text.trim()) return null;
|
|
54
|
+
// Don't truncate — let terminal wrap
|
|
54
55
|
return { content: text, contentColor: 'white' };
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
case 'thinking': {
|
|
59
|
+
const text = ((event.data.text as string) ?? '').slice(0, 150);
|
|
60
|
+
if (!text.trim()) return null;
|
|
61
|
+
return { content: `\uD83D\uDCAD ${text}`, contentColor: 'gray' };
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
case 'tool:start': {
|
|
58
65
|
const name = (event.data.name as string) ?? 'tool';
|
|
59
66
|
const input = event.data.input;
|
|
@@ -61,8 +68,9 @@ function renderEvent(event: SSEEvent, allRoleIds: string[]): { content: string;
|
|
|
61
68
|
if (input && typeof input === 'object') {
|
|
62
69
|
const inp = input as Record<string, unknown>;
|
|
63
70
|
if (inp.file_path) detail = ` ${String(inp.file_path)}`;
|
|
64
|
-
else if (inp.command) detail = ` ${String(inp.command).slice(0,
|
|
65
|
-
else detail = ` ${
|
|
71
|
+
else if (inp.command) detail = ` ${String(inp.command).slice(0, 80)}`;
|
|
72
|
+
else if (inp.pattern) detail = ` ${String(inp.pattern)}`;
|
|
73
|
+
else detail = ` ${JSON.stringify(input).slice(0, 80)}`;
|
|
66
74
|
}
|
|
67
75
|
return {
|
|
68
76
|
content: `\u2192 ${name}${detail}`,
|
|
@@ -78,7 +86,7 @@ function renderEvent(event: SSEEvent, allRoleIds: string[]): { content: string;
|
|
|
78
86
|
|
|
79
87
|
case 'dispatch:start':
|
|
80
88
|
return {
|
|
81
|
-
content: `\u21D2 dispatch ${event.data.targetRole as string ?? ''}: ${(event.data.task as string)?.slice(0,
|
|
89
|
+
content: `\u21D2 dispatch ${event.data.targetRole as string ?? ''}: ${(event.data.task as string)?.replace(/\u26D4[^\u26D4]*\u26D4[^"]*/g, '').trim().slice(0, 80) ?? ''}`,
|
|
82
90
|
contentColor: 'yellow',
|
|
83
91
|
};
|
|
84
92
|
|
|
@@ -88,14 +96,15 @@ function renderEvent(event: SSEEvent, allRoleIds: string[]): { content: string;
|
|
|
88
96
|
contentColor: 'yellow',
|
|
89
97
|
};
|
|
90
98
|
|
|
91
|
-
case 'msg:awaiting_input':
|
|
99
|
+
case 'msg:awaiting_input': {
|
|
100
|
+
const question = (event.data.question as string) ?? '';
|
|
92
101
|
return {
|
|
93
|
-
content: '? Awaiting input...',
|
|
102
|
+
content: question ? `? ${question.slice(0, 120)}` : '? Awaiting input...',
|
|
94
103
|
contentColor: 'yellow',
|
|
95
104
|
};
|
|
105
|
+
}
|
|
96
106
|
|
|
97
|
-
// Hidden
|
|
98
|
-
case 'thinking':
|
|
107
|
+
// Hidden (truly internal only)
|
|
99
108
|
case 'heartbeat:tick':
|
|
100
109
|
case 'heartbeat:skip':
|
|
101
110
|
case 'prompt:assembled':
|
|
@@ -114,7 +123,7 @@ export const StreamView: React.FC<StreamViewProps> = ({
|
|
|
114
123
|
waveId,
|
|
115
124
|
roleLabel,
|
|
116
125
|
}) => {
|
|
117
|
-
const maxVisible =
|
|
126
|
+
const maxVisible = 30;
|
|
118
127
|
const visibleEvents = events.slice(-maxVisible);
|
|
119
128
|
|
|
120
129
|
const turnCount = events.filter(e => e.type === 'text' || e.type === 'tool:start').length;
|
|
@@ -146,14 +155,14 @@ export const StreamView: React.FC<StreamViewProps> = ({
|
|
|
146
155
|
)}
|
|
147
156
|
|
|
148
157
|
{visibleEvents.map((event, i) => {
|
|
149
|
-
const rendered = renderEvent(event
|
|
158
|
+
const rendered = renderEvent(event);
|
|
150
159
|
if (!rendered) return null;
|
|
151
160
|
const roleColor = getRoleColor(event.roleId, allRoleIds);
|
|
152
161
|
return (
|
|
153
162
|
<Box key={`${event.seq}-${i}`}>
|
|
154
163
|
<Text color="gray" dimColor>{formatTime(event.ts)} </Text>
|
|
155
164
|
<Text color={roleColor} bold>{event.roleId.padEnd(12)}</Text>
|
|
156
|
-
<Text color={rendered.contentColor}>{rendered.content}</Text>
|
|
165
|
+
<Text color={rendered.contentColor} wrap="wrap">{rendered.content}</Text>
|
|
157
166
|
</Box>
|
|
158
167
|
);
|
|
159
168
|
})}
|