tycono 0.3.14-beta.20 → 0.3.14-beta.22

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.3.14-beta.20",
3
+ "version": "0.3.14-beta.22",
4
4
  "description": "Build an AI company. Watch them work.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -83,16 +83,8 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
83
83
  }
84
84
 
85
85
  case 'thinking': {
86
- const text = ((event.data.text as string) ?? '').slice(0, 120);
87
- if (!text.trim()) return null;
88
- return {
89
- id: ++lineCounter,
90
- prefix: isSupervisor ? undefined : event.roleId,
91
- prefixColor: roleColor,
92
- text: `\uD83D\uDCAD ${text}`,
93
- color: 'gray',
94
- indent: !isSupervisor,
95
- };
86
+ // Hide thinking by default internal noise for user
87
+ return null;
96
88
  }
97
89
 
98
90
  case 'dispatch:start': {
@@ -130,17 +122,19 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
130
122
 
131
123
  case 'tool:start': {
132
124
  const toolName = (event.data.name as string) ?? 'tool';
125
+ // Only show Write/Edit (file changes) + Bash (commands). Hide Read/Grep/Glob (noise).
126
+ const isWrite = ['Write', 'Edit', 'NotebookEdit'].includes(toolName);
127
+ const isBash = toolName === 'Bash';
128
+ if (!isWrite && !isBash) return null; // Hide read-only tools
129
+
133
130
  const input = event.data.input;
134
131
  let detail = '';
135
132
  if (input && typeof input === 'object') {
136
133
  const inp = input as Record<string, unknown>;
137
- if (inp.file_path) detail = ` ${String(inp.file_path)}`;
138
- else if (inp.command) detail = ` ${String(inp.command).slice(0, 80)}`;
139
- else if (inp.pattern) detail = ` ${String(inp.pattern)}`;
140
- else if (inp.description) detail = ` ${String(inp.description).slice(0, 60)}`;
134
+ if (inp.file_path) detail = ` ${String(inp.file_path).split('/').slice(-2).join('/')}`;
135
+ else if (inp.command) detail = ` ${String(inp.command).slice(0, 60)}`;
136
+ else if (inp.description) detail = ` ${String(inp.description).slice(0, 40)}`;
141
137
  }
142
- // Highlight file writes
143
- const isWrite = ['Write', 'Edit'].includes(toolName);
144
138
  return {
145
139
  id: ++lineCounter,
146
140
  prefix: isSupervisor ? undefined : event.roleId,
@@ -152,15 +146,8 @@ export function summarizeEvent(event: SSEEvent, allRoleIds: string[]): StreamLin
152
146
  }
153
147
 
154
148
  case 'tool:result': {
155
- const toolName = (event.data.name as string) ?? 'tool';
156
- return {
157
- id: ++lineCounter,
158
- prefix: isSupervisor ? undefined : event.roleId,
159
- prefixColor: roleColor,
160
- text: ` \u2190 ${toolName} done`,
161
- color: 'gray',
162
- indent: !isSupervisor,
163
- };
149
+ // Hide tool results tool:start is sufficient
150
+ return null;
164
151
  }
165
152
 
166
153
  case 'msg:start': {
@@ -421,10 +408,10 @@ export const CommandMode: React.FC<CommandModeProps> = ({
421
408
  const handleSubmit = useCallback((value: string) => {
422
409
  const trimmed = value.trim();
423
410
  if (trimmed) {
424
- // Show user input immediately in scrollback (before AI responds)
411
+ // Show user input with visual separator for emphasis
425
412
  setUserInputs(prev => [...prev.slice(-10), {
426
413
  id: ++lineCounter,
427
- text: `> ${trimmed}`,
414
+ text: `\u2501\u2501 > ${trimmed}`,
428
415
  color: 'green',
429
416
  }]);
430
417
  onSubmit(trimmed);
@@ -70,8 +70,8 @@ function eventLine(ev: SSEEvent): string | null {
70
70
  catch { t = '--:--:--'; }
71
71
  const r = (ev.roleId ?? '').padEnd(12);
72
72
  switch (ev.type) {
73
- case 'text': { const x = ((ev.data.text as string) ?? '').trim(); return x ? `${t} ${r} ${x.slice(0, 120)}` : null; }
74
- case 'thinking': { const x = ((ev.data.text as string) ?? '').trim(); return x ? `${t} ${r} \uD83D\uDCAD ${x.slice(0, 80)}` : null; }
73
+ case 'text': { const x = ((ev.data.text as string) ?? '').replace(/\n/g, ' ').trim(); return x ? `${t} ${r} ${x.slice(0, 120)}` : null; }
74
+ case 'thinking': { const x = ((ev.data.text as string) ?? '').replace(/\n/g, ' ').trim(); return x ? `${t} ${r} \uD83D\uDCAD ${x.slice(0, 80)}` : null; }
75
75
  case 'tool:start': { const n = (ev.data.name as string) ?? ''; const d = ev.data.input ? (((ev.data.input as any).file_path || (ev.data.input as any).command || (ev.data.input as any).pattern || '') as string).slice(0, 50) : ''; return `${t} ${r} \u2192 ${n} ${d}`; }
76
76
  case 'tool:result': return `${t} ${r} \u2190 ${(ev.data.name as string) ?? ''} done`;
77
77
  case 'msg:start': return `${t} ${r} \u25B6 Started`;
@@ -157,6 +157,9 @@ const PanelModeInner: React.FC<PanelModeProps> = ({
157
157
  const leftWidth = 28;
158
158
  const termCols = process.stdout.columns || 120;
159
159
  const rightWidth = termCols - leftWidth - 3;
160
+ const headerLines = 2;
161
+ const footerLines = 3;
162
+ const contentHeight = Math.max(termHeight - headerLines - footerLines, 5);
160
163
 
161
164
  // === Build left column: OrgTree ===
162
165
  const ceoIcon = statuses['ceo'] === 'working' ? '\u25CF' : statuses['ceo'] === 'done' ? '\u2713' : '\u25CB';
@@ -176,7 +179,8 @@ const PanelModeInner: React.FC<PanelModeProps> = ({
176
179
  const rightContentLines: string[] = [];
177
180
  let selectedDocPath: string | null = null;
178
181
  if (rightTab === 'stream') {
179
- const maxEv = Math.max(5, termHeight - 10);
182
+ if (selectedRoleId) rightContentLines.push(`\u25B8 ${selectedRoleId}`);
183
+ const maxEv = Math.max(5, contentHeight - 3);
180
184
  const filtered = selectedRoleId ? events.filter(e => e.roleId === selectedRoleId) : events;
181
185
  const visible = filtered.slice(-maxEv);
182
186
  for (const ev of visible) {
@@ -237,11 +241,8 @@ const PanelModeInner: React.FC<PanelModeProps> = ({
237
241
  }
238
242
  }
239
243
 
240
- // === Merge left + right, pad to fill terminal height ===
241
- const headerLines = 3; // header + separator + org tree title
242
- const footerLines = 2; // separator + keybindings
243
- const contentHeight = Math.max(termHeight - headerLines - footerLines, 5);
244
- const maxRows = Math.max(leftLines.length, rightContentLines.length, contentHeight);
244
+ // === Merge left + right, cap to terminal height ===
245
+ const maxRows = contentHeight;
245
246
 
246
247
  const rows: Array<{ left: string; right: string; leftSelected: boolean; leftWorking: boolean }> = [];
247
248
  for (let i = 0; i < maxRows; i++) {