agentgui 1.0.234 → 1.0.235
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/lib/claude-runner.js +92 -18
- package/package.json +1 -1
- package/server.js +40 -0
- package/static/js/streaming-renderer.js +95 -0
package/lib/claude-runner.js
CHANGED
|
@@ -580,26 +580,63 @@ registry.register({
|
|
|
580
580
|
content: [{
|
|
581
581
|
type: 'tool_use',
|
|
582
582
|
id: update.toolCallId,
|
|
583
|
-
name: update.title || 'tool',
|
|
584
|
-
input: update.input || {}
|
|
583
|
+
name: update.title || update.kind || 'tool',
|
|
584
|
+
input: update.rawInput || update.input || {}
|
|
585
585
|
}]
|
|
586
586
|
},
|
|
587
587
|
session_id: params.sessionId
|
|
588
588
|
};
|
|
589
589
|
}
|
|
590
590
|
|
|
591
|
-
// Tool call update (result)
|
|
592
|
-
if (update.sessionUpdate === 'tool_call_update'
|
|
593
|
-
const
|
|
591
|
+
// Tool call update (result) - handle all statuses
|
|
592
|
+
if (update.sessionUpdate === 'tool_call_update') {
|
|
593
|
+
const status = update.status;
|
|
594
|
+
const isError = status === 'failed';
|
|
595
|
+
const isCompleted = status === 'completed';
|
|
596
|
+
|
|
597
|
+
if (!isCompleted && !isError) {
|
|
598
|
+
return {
|
|
599
|
+
type: 'tool_status',
|
|
600
|
+
tool_use_id: update.toolCallId,
|
|
601
|
+
status: status,
|
|
602
|
+
session_id: params.sessionId
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const contentParts = [];
|
|
607
|
+
if (update.content && Array.isArray(update.content)) {
|
|
608
|
+
for (const item of update.content) {
|
|
609
|
+
if (item.type === 'content' && item.content) {
|
|
610
|
+
const innerContent = item.content;
|
|
611
|
+
if (innerContent.type === 'text' && innerContent.text) {
|
|
612
|
+
contentParts.push(innerContent.text);
|
|
613
|
+
} else if (innerContent.type === 'resource' && innerContent.resource) {
|
|
614
|
+
contentParts.push(innerContent.resource.text || JSON.stringify(innerContent.resource));
|
|
615
|
+
} else {
|
|
616
|
+
contentParts.push(JSON.stringify(innerContent));
|
|
617
|
+
}
|
|
618
|
+
} else if (item.type === 'diff') {
|
|
619
|
+
const diffText = item.oldText
|
|
620
|
+
? `--- ${item.path}\n+++ ${item.path}\n${item.oldText}\n---\n${item.newText}`
|
|
621
|
+
: `+++ ${item.path}\n${item.newText}`;
|
|
622
|
+
contentParts.push(diffText);
|
|
623
|
+
} else if (item.type === 'terminal') {
|
|
624
|
+
contentParts.push(`[Terminal: ${item.terminalId}]`);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const combinedContent = contentParts.join('\n') || (update.rawOutput ? JSON.stringify(update.rawOutput) : '');
|
|
630
|
+
|
|
594
631
|
return {
|
|
595
|
-
type: '
|
|
632
|
+
type: 'user',
|
|
596
633
|
message: {
|
|
597
|
-
role: '
|
|
634
|
+
role: 'user',
|
|
598
635
|
content: [{
|
|
599
636
|
type: 'tool_result',
|
|
600
637
|
tool_use_id: update.toolCallId,
|
|
601
|
-
content:
|
|
602
|
-
is_error:
|
|
638
|
+
content: combinedContent,
|
|
639
|
+
is_error: isError
|
|
603
640
|
}]
|
|
604
641
|
},
|
|
605
642
|
session_id: params.sessionId
|
|
@@ -687,26 +724,63 @@ function createACPProtocolHandler() {
|
|
|
687
724
|
content: [{
|
|
688
725
|
type: 'tool_use',
|
|
689
726
|
id: update.toolCallId,
|
|
690
|
-
name: update.title || 'tool',
|
|
691
|
-
input: update.input || {}
|
|
727
|
+
name: update.title || update.kind || 'tool',
|
|
728
|
+
input: update.rawInput || update.input || {}
|
|
692
729
|
}]
|
|
693
730
|
},
|
|
694
731
|
session_id: params.sessionId
|
|
695
732
|
};
|
|
696
733
|
}
|
|
697
734
|
|
|
698
|
-
// Tool call update (result)
|
|
699
|
-
if (update.sessionUpdate === 'tool_call_update'
|
|
700
|
-
const
|
|
735
|
+
// Tool call update (result) - handle all statuses
|
|
736
|
+
if (update.sessionUpdate === 'tool_call_update') {
|
|
737
|
+
const status = update.status;
|
|
738
|
+
const isError = status === 'failed';
|
|
739
|
+
const isCompleted = status === 'completed';
|
|
740
|
+
|
|
741
|
+
if (!isCompleted && !isError) {
|
|
742
|
+
return {
|
|
743
|
+
type: 'tool_status',
|
|
744
|
+
tool_use_id: update.toolCallId,
|
|
745
|
+
status: status,
|
|
746
|
+
session_id: params.sessionId
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
const contentParts = [];
|
|
751
|
+
if (update.content && Array.isArray(update.content)) {
|
|
752
|
+
for (const item of update.content) {
|
|
753
|
+
if (item.type === 'content' && item.content) {
|
|
754
|
+
const innerContent = item.content;
|
|
755
|
+
if (innerContent.type === 'text' && innerContent.text) {
|
|
756
|
+
contentParts.push(innerContent.text);
|
|
757
|
+
} else if (innerContent.type === 'resource' && innerContent.resource) {
|
|
758
|
+
contentParts.push(innerContent.resource.text || JSON.stringify(innerContent.resource));
|
|
759
|
+
} else {
|
|
760
|
+
contentParts.push(JSON.stringify(innerContent));
|
|
761
|
+
}
|
|
762
|
+
} else if (item.type === 'diff') {
|
|
763
|
+
const diffText = item.oldText
|
|
764
|
+
? `--- ${item.path}\n+++ ${item.path}\n${item.oldText}\n---\n${item.newText}`
|
|
765
|
+
: `+++ ${item.path}\n${item.newText}`;
|
|
766
|
+
contentParts.push(diffText);
|
|
767
|
+
} else if (item.type === 'terminal') {
|
|
768
|
+
contentParts.push(`[Terminal: ${item.terminalId}]`);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const combinedContent = contentParts.join('\n') || (update.rawOutput ? JSON.stringify(update.rawOutput) : '');
|
|
774
|
+
|
|
701
775
|
return {
|
|
702
|
-
type: '
|
|
776
|
+
type: 'user',
|
|
703
777
|
message: {
|
|
704
|
-
role: '
|
|
778
|
+
role: 'user',
|
|
705
779
|
content: [{
|
|
706
780
|
type: 'tool_result',
|
|
707
781
|
tool_use_id: update.toolCallId,
|
|
708
|
-
content:
|
|
709
|
-
is_error:
|
|
782
|
+
content: combinedContent,
|
|
783
|
+
is_error: isError
|
|
710
784
|
}]
|
|
711
785
|
},
|
|
712
786
|
session_id: params.sessionId
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -2069,6 +2069,46 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
|
|
|
2069
2069
|
if (parsed.result && allBlocks.length === 0) {
|
|
2070
2070
|
allBlocks.push({ type: 'text', text: String(parsed.result) });
|
|
2071
2071
|
}
|
|
2072
|
+
} else if (parsed.type === 'tool_status') {
|
|
2073
|
+
// Handle ACP tool status updates (in_progress, pending)
|
|
2074
|
+
broadcastSync({
|
|
2075
|
+
type: 'streaming_progress',
|
|
2076
|
+
sessionId,
|
|
2077
|
+
conversationId,
|
|
2078
|
+
block: {
|
|
2079
|
+
type: 'tool_status',
|
|
2080
|
+
tool_use_id: parsed.tool_use_id,
|
|
2081
|
+
status: parsed.status
|
|
2082
|
+
},
|
|
2083
|
+
seq: currentSequence,
|
|
2084
|
+
timestamp: Date.now()
|
|
2085
|
+
});
|
|
2086
|
+
} else if (parsed.type === 'usage') {
|
|
2087
|
+
// Handle ACP usage updates
|
|
2088
|
+
broadcastSync({
|
|
2089
|
+
type: 'streaming_progress',
|
|
2090
|
+
sessionId,
|
|
2091
|
+
conversationId,
|
|
2092
|
+
block: {
|
|
2093
|
+
type: 'usage',
|
|
2094
|
+
usage: parsed.usage
|
|
2095
|
+
},
|
|
2096
|
+
seq: currentSequence,
|
|
2097
|
+
timestamp: Date.now()
|
|
2098
|
+
});
|
|
2099
|
+
} else if (parsed.type === 'plan') {
|
|
2100
|
+
// Handle ACP plan updates
|
|
2101
|
+
broadcastSync({
|
|
2102
|
+
type: 'streaming_progress',
|
|
2103
|
+
sessionId,
|
|
2104
|
+
conversationId,
|
|
2105
|
+
block: {
|
|
2106
|
+
type: 'plan',
|
|
2107
|
+
entries: parsed.entries
|
|
2108
|
+
},
|
|
2109
|
+
seq: currentSequence,
|
|
2110
|
+
timestamp: Date.now()
|
|
2111
|
+
});
|
|
2072
2112
|
}
|
|
2073
2113
|
};
|
|
2074
2114
|
|
|
@@ -351,6 +351,12 @@ class StreamingRenderer {
|
|
|
351
351
|
return this.renderBlockSystem(block, context);
|
|
352
352
|
case 'result':
|
|
353
353
|
return this.renderBlockResult(block, context);
|
|
354
|
+
case 'tool_status':
|
|
355
|
+
return this.renderBlockToolStatus(block, context);
|
|
356
|
+
case 'usage':
|
|
357
|
+
return this.renderBlockUsage(block, context);
|
|
358
|
+
case 'plan':
|
|
359
|
+
return this.renderBlockPlan(block, context);
|
|
354
360
|
default:
|
|
355
361
|
return this.renderBlockGeneric(block, context);
|
|
356
362
|
}
|
|
@@ -1320,6 +1326,95 @@ class StreamingRenderer {
|
|
|
1320
1326
|
return details;
|
|
1321
1327
|
}
|
|
1322
1328
|
|
|
1329
|
+
/**
|
|
1330
|
+
* Render tool status block (ACP in_progress/pending updates)
|
|
1331
|
+
*/
|
|
1332
|
+
renderBlockToolStatus(block, context) {
|
|
1333
|
+
const status = block.status || 'pending';
|
|
1334
|
+
const statusIcons = {
|
|
1335
|
+
pending: '<svg viewBox="0 0 20 20" fill="currentColor" style="color:var(--color-text-secondary)"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/></svg>',
|
|
1336
|
+
in_progress: '<svg viewBox="0 0 20 20" fill="currentColor" class="animate-spin" style="color:var(--color-info)"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/></svg>'
|
|
1337
|
+
};
|
|
1338
|
+
const statusLabels = {
|
|
1339
|
+
pending: 'Pending',
|
|
1340
|
+
in_progress: 'Running...'
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
const div = document.createElement('div');
|
|
1344
|
+
div.className = 'block-tool-status';
|
|
1345
|
+
div.dataset.toolUseId = block.tool_use_id || '';
|
|
1346
|
+
div.innerHTML = `
|
|
1347
|
+
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.25rem 0.5rem;font-size:0.75rem;color:var(--color-text-secondary)">
|
|
1348
|
+
${statusIcons[status] || statusIcons.pending}
|
|
1349
|
+
<span>${statusLabels[status] || status}</span>
|
|
1350
|
+
</div>
|
|
1351
|
+
`;
|
|
1352
|
+
return div;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* Render usage block (ACP usage updates)
|
|
1357
|
+
*/
|
|
1358
|
+
renderBlockUsage(block, context) {
|
|
1359
|
+
const usage = block.usage || {};
|
|
1360
|
+
const used = usage.used || 0;
|
|
1361
|
+
const size = usage.size || 0;
|
|
1362
|
+
const cost = usage.cost ? '$' + usage.cost.toFixed(4) : '';
|
|
1363
|
+
|
|
1364
|
+
const div = document.createElement('div');
|
|
1365
|
+
div.className = 'block-usage';
|
|
1366
|
+
div.innerHTML = `
|
|
1367
|
+
<div style="display:flex;gap:1rem;padding:0.25rem 0.5rem;font-size:0.7rem;color:var(--color-text-secondary);background:var(--color-bg-secondary);border-radius:0.25rem">
|
|
1368
|
+
${used ? `<span><strong>Used:</strong> ${used.toLocaleString()}</span>` : ''}
|
|
1369
|
+
${size ? `<span><strong>Context:</strong> ${size.toLocaleString()}</span>` : ''}
|
|
1370
|
+
${cost ? `<span><strong>Cost:</strong> ${cost}</span>` : ''}
|
|
1371
|
+
</div>
|
|
1372
|
+
`;
|
|
1373
|
+
return div;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
/**
|
|
1377
|
+
* Render plan block (ACP plan updates)
|
|
1378
|
+
*/
|
|
1379
|
+
renderBlockPlan(block, context) {
|
|
1380
|
+
const entries = block.entries || [];
|
|
1381
|
+
if (entries.length === 0) return null;
|
|
1382
|
+
|
|
1383
|
+
const priorityColors = {
|
|
1384
|
+
high: '#ef4444',
|
|
1385
|
+
medium: '#f59e0b',
|
|
1386
|
+
low: '#6b7280'
|
|
1387
|
+
};
|
|
1388
|
+
const statusIcons = {
|
|
1389
|
+
pending: '○',
|
|
1390
|
+
in_progress: '◐',
|
|
1391
|
+
completed: '●'
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
const div = document.createElement('div');
|
|
1395
|
+
div.className = 'block-plan';
|
|
1396
|
+
div.innerHTML = `
|
|
1397
|
+
<details class="folded-tool folded-tool-info">
|
|
1398
|
+
<summary class="folded-tool-bar">
|
|
1399
|
+
<span class="folded-tool-icon"><svg viewBox="0 0 20 20" fill="currentColor"><path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"/><path fill-rule="evenodd" d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 4a1 1 0 000 2h.01a1 1 0 100-2H7zm3 0a1 1 0 000 2h3a1 1 0 100-2h-3zm-3 4a1 1 0 100 2h.01a1 1 0 100-2H7zm3 0a1 1 0 100 2h3a1 1 0 100-2h-3z" clip-rule="evenodd"/></svg></span>
|
|
1400
|
+
<span class="folded-tool-name">Plan</span>
|
|
1401
|
+
<span class="folded-tool-desc">${entries.length} tasks</span>
|
|
1402
|
+
</summary>
|
|
1403
|
+
<div class="folded-tool-body">
|
|
1404
|
+
<div style="display:flex;flex-direction:column;gap:0.375rem">
|
|
1405
|
+
${entries.map(e => `
|
|
1406
|
+
<div style="display:flex;align-items:center;gap:0.5rem;font-size:0.8rem">
|
|
1407
|
+
<span style="color:${priorityColors[e.priority] || priorityColors.low}">${statusIcons[e.status] || statusIcons.pending}</span>
|
|
1408
|
+
<span style="${e.status === 'completed' ? 'text-decoration:line-through;opacity:0.6' : ''}">${this.escapeHtml(e.content || '')}</span>
|
|
1409
|
+
</div>
|
|
1410
|
+
`).join('')}
|
|
1411
|
+
</div>
|
|
1412
|
+
</div>
|
|
1413
|
+
</details>
|
|
1414
|
+
`;
|
|
1415
|
+
return div;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1323
1418
|
/**
|
|
1324
1419
|
* Render generic block with formatted key-value pairs
|
|
1325
1420
|
*/
|