Skip to content

Commit a78218c

Browse files
committed
release: merge develop into main for v0.19.1
2 parents cd13259 + b06d3d6 commit a78218c

File tree

20 files changed

+184
-8
lines changed

20 files changed

+184
-8
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.19.1] - 2026-04-13
9+
10+
### Added
11+
12+
- **Subagent cards in chat** — when an agent delegates to another (e.g., Oracle → Sage), the tool card shows the subagent's avatar, name with `@`, description, live progress summary, and completion status
13+
- **Subagent progress summaries** — enabled `agentProgressSummaries` in the SDK so subagent activity is streamed in real-time
14+
- **Chat UI screenshot** — added `print-chat.webp` to README, site screenshots carousel, and i18n (en/pt-BR/es)
15+
16+
### Fixed
17+
18+
- **Textarea height reset** — Shift+Enter expanded the input area but it did not shrink back after sending. Now resets to single line on send
19+
- **Agent SDK dependency** — added `npm install` step to production deploy (the SDK was listed in package.json but not installed on the server)
20+
821
## [0.19.0] - 2026-04-13
922

1023
### Added

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,13 @@ It turns a single CLI installation into a team of **38 specialized agents** orga
6262

6363
<p align="center">
6464
<img src="public/print-overview.webp" alt="Overview" width="49%" />
65-
<img src="public/print-agents.webp" alt="Agents" width="49%" />
65+
<img src="public/print-chat.webp" alt="Agent Chat" width="49%" />
6666
</p>
6767
<p align="center">
68+
<img src="public/print-agents.webp" alt="Agents" width="49%" />
6869
<img src="public/print-integrations.webp" alt="Integrations" width="49%" />
70+
</p>
71+
<p align="center">
6972
<img src="public/print-costs.webp" alt="Costs" width="49%" />
7073
</p>
7174

cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evoapi/evo-nexus",
3-
"version": "0.19.0",
3+
"version": "0.19.1",
44
"description": "Unofficial open source toolkit for Claude Code — AI-powered business operating system",
55
"keywords": [
66
"claude-code",

dashboard/frontend/src/components/AgentChat.tsx

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type ChatMessage =
4141
type AssistantBlock =
4242
| { type: 'text'; text: string }
4343
| { type: 'thinking'; text: string }
44-
| { type: 'tool_use'; toolName: string; toolId: string; input: string; result?: string; done?: boolean }
44+
| { type: 'tool_use'; toolName: string; toolId: string; input: string; result?: string; done?: boolean; subagentType?: string; subagentStatus?: string; subagentSummary?: string }
4545

4646
type Status = 'idle' | 'connecting' | 'running' | 'error'
4747

@@ -260,6 +260,64 @@ export default function AgentChat({ agent, sessionId, accentColor = '#00FFA7' }:
260260
break
261261
}
262262

263+
case 'task_started': {
264+
// Subagent started — find the Agent tool_use block and enrich it
265+
const last2 = copy[copy.length - 1]
266+
if (last2?.role === 'assistant') {
267+
const blocks = [...(last2 as any).blocks]
268+
// Find the Agent tool block by toolUseId or last Agent block
269+
for (let k = blocks.length - 1; k >= 0; k--) {
270+
if (blocks[k].type === 'tool_use' && blocks[k].toolName === 'Agent') {
271+
blocks[k] = { ...blocks[k], subagentType: msg.description, subagentStatus: 'running' }
272+
break
273+
}
274+
}
275+
copy[copy.length - 1] = { ...last2, blocks } as any
276+
}
277+
break
278+
}
279+
280+
case 'task_progress': {
281+
const last3 = copy[copy.length - 1]
282+
if (last3?.role === 'assistant') {
283+
const blocks = [...(last3 as any).blocks]
284+
for (let k = blocks.length - 1; k >= 0; k--) {
285+
if (blocks[k].type === 'tool_use' && blocks[k].toolName === 'Agent' && blocks[k].subagentStatus === 'running') {
286+
blocks[k] = { ...blocks[k], subagentSummary: msg.summary || msg.description }
287+
break
288+
}
289+
}
290+
copy[copy.length - 1] = { ...last3, blocks } as any
291+
}
292+
break
293+
}
294+
295+
case 'task_complete': {
296+
const last4 = copy[copy.length - 1]
297+
if (last4?.role === 'assistant') {
298+
const blocks = [...(last4 as any).blocks]
299+
for (let k = blocks.length - 1; k >= 0; k--) {
300+
if (blocks[k].type === 'tool_use' && blocks[k].toolName === 'Agent') {
301+
blocks[k] = { ...blocks[k], subagentStatus: msg.status, done: true }
302+
break
303+
}
304+
}
305+
copy[copy.length - 1] = { ...last4, blocks } as any
306+
}
307+
break
308+
}
309+
310+
case 'tool_use_summary': {
311+
// Show summary text after tool completes
312+
const last5 = copy[copy.length - 1]
313+
if (last5?.role === 'assistant' && msg.summary) {
314+
const blocks = [...(last5 as any).blocks]
315+
blocks.push({ type: 'text', text: msg.summary })
316+
copy[copy.length - 1] = { ...last5, blocks } as any
317+
}
318+
break
319+
}
320+
263321
case 'result': {
264322
const last = copy[copy.length - 1]
265323
if (last?.role === 'assistant') {
@@ -391,7 +449,10 @@ export default function AgentChat({ agent, sessionId, accentColor = '#00FFA7' }:
391449
}))
392450

393451
scrollToBottom()
394-
inputRef.current?.focus()
452+
if (inputRef.current) {
453+
inputRef.current.style.height = 'auto'
454+
inputRef.current.focus()
455+
}
395456
}, [input, attachedFiles, scrollToBottom])
396457

397458
const handleKeyDown = (e: React.KeyboardEvent) => {
@@ -717,6 +778,63 @@ function ToolCard({ block, accentColor }: { block: Extract<AssistantBlock, { typ
717778
let parsedInput: any = null
718779
try { parsedInput = JSON.parse(block.input) } catch {}
719780

781+
// Detect Agent tool — render special subagent card
782+
const isAgentTool = block.toolName === 'Agent'
783+
const subagentName = parsedInput?.subagent_type || parsedInput?.name || ''
784+
const subagentDesc = parsedInput?.description || block.subagentType || ''
785+
786+
if (isAgentTool) {
787+
const isRunning = block.subagentStatus === 'running'
788+
const isDone = block.done || block.subagentStatus === 'completed' || block.subagentStatus === 'failed'
789+
790+
return (
791+
<div className="border border-[#21262d] rounded-lg overflow-hidden">
792+
<button
793+
onClick={() => setOpen(!open)}
794+
className="flex items-center gap-2.5 w-full px-3 py-2.5 text-[12px] bg-[#161b22] hover:bg-[#1c2333] transition-colors"
795+
>
796+
{open ? <ChevronDown size={12} className="text-[#667085]" /> : <ChevronRight size={12} className="text-[#667085]" />}
797+
798+
{/* Subagent avatar */}
799+
{subagentName ? (
800+
<AgentAvatar name={subagentName.replace('custom-', '')} size={20} />
801+
) : (
802+
<FileCode size={13} style={{ color: accentColor }} />
803+
)}
804+
805+
<span className="font-medium text-[#e6edf3]">
806+
{subagentName ? `@${subagentName}` : 'Agent'}
807+
</span>
808+
{subagentDesc && (
809+
<span className="text-[#8b949e] truncate max-w-[300px] text-[11px]">{subagentDesc}</span>
810+
)}
811+
812+
<span className="ml-auto flex-shrink-0 flex items-center gap-2">
813+
{/* Progress summary */}
814+
{isRunning && block.subagentSummary && (
815+
<span className="text-[10px] text-[#667085] truncate max-w-[200px]" style={{ animation: 'chat-pulse 2s ease-in-out infinite' }}>
816+
{block.subagentSummary}
817+
</span>
818+
)}
819+
{isDone ? (
820+
<CheckCircle2 size={13} className={block.subagentStatus === 'failed' ? 'text-[#ef4444]' : 'text-[#22C55E]'} />
821+
) : (
822+
<TypingIndicatorMini accentColor={accentColor} />
823+
)}
824+
</span>
825+
</button>
826+
{open && block.input && (
827+
<div className="px-3 py-2 border-t border-[#21262d] bg-[#0d1117]">
828+
<pre className="text-[11px] text-[#8b949e] font-mono whitespace-pre-wrap break-all max-h-48 overflow-y-auto">
829+
{parsedInput ? JSON.stringify(parsedInput, null, 2) : block.input}
830+
</pre>
831+
</div>
832+
)}
833+
</div>
834+
)
835+
}
836+
837+
// Regular tool card
720838
const displayInfo = parsedInput
721839
? (parsedInput.command || parsedInput.file_path || parsedInput.path || parsedInput.pattern || parsedInput.description || '')
722840
: ''

dashboard/terminal-server/src/chat-bridge.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ class ChatBridge {
119119
'NotebookEdit', 'ToolSearch',
120120
];
121121

122+
// Enable subagent progress summaries
123+
queryOptions.agentProgressSummaries = true;
124+
122125
// Resume existing conversation if we have an SDK session ID
123126
if (sdkSessionId) {
124127
queryOptions.resume = sdkSessionId;
@@ -335,13 +338,47 @@ class ChatBridge {
335338
}
336339

337340
case 'system': {
341+
// Subagent lifecycle events
342+
if (msg.subtype === 'task_started') {
343+
return {
344+
type: 'task_started',
345+
taskId: msg.task_id,
346+
toolUseId: msg.tool_use_id,
347+
description: msg.description,
348+
prompt: msg.prompt,
349+
};
350+
}
351+
if (msg.subtype === 'task_progress') {
352+
return {
353+
type: 'task_progress',
354+
taskId: msg.task_id,
355+
description: msg.description,
356+
summary: msg.summary,
357+
};
358+
}
359+
if (msg.subtype === 'task_notification') {
360+
return {
361+
type: 'task_complete',
362+
taskId: msg.task_id,
363+
toolUseId: msg.tool_use_id,
364+
status: msg.status,
365+
};
366+
}
338367
return {
339368
type: 'system',
340369
subtype: msg.subtype,
341370
sessionId: msg.session_id,
342371
};
343372
}
344373

374+
case 'tool_use_summary': {
375+
return {
376+
type: 'tool_use_summary',
377+
summary: msg.summary,
378+
toolUseIds: msg.preceding_tool_use_ids,
379+
};
380+
}
381+
345382
default:
346383
return { type: msg.type || 'unknown', sessionId: msg.session_id };
347384
}

public/print-agents.webp

-90.6 KB
Loading

public/print-chat.webp

62.6 KB
Loading

public/print-costs.webp

-72 KB
Loading

public/print-integrations.webp

-54.9 KB
Loading

public/print-overview.webp

-72 KB
Loading

0 commit comments

Comments
 (0)