agentgui 1.0.96 → 1.0.98
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/.prd +0 -6
- package/package.json +1 -1
- package/server.js +51 -5
- package/static/index.html +164 -0
- package/static/js/client.js +68 -12
package/.prd
CHANGED
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -475,10 +475,27 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
|
|
|
475
475
|
let eventCount = 0;
|
|
476
476
|
|
|
477
477
|
const onEvent = (parsed) => {
|
|
478
|
-
|
|
478
|
+
eventCount++;
|
|
479
|
+
|
|
480
|
+
if (parsed.type === 'system') {
|
|
481
|
+
broadcastSync({
|
|
482
|
+
type: 'streaming_progress',
|
|
483
|
+
sessionId,
|
|
484
|
+
conversationId,
|
|
485
|
+
block: {
|
|
486
|
+
type: 'system',
|
|
487
|
+
subtype: parsed.subtype,
|
|
488
|
+
model: parsed.model,
|
|
489
|
+
cwd: parsed.cwd,
|
|
490
|
+
tools: parsed.tools,
|
|
491
|
+
session_id: parsed.session_id
|
|
492
|
+
},
|
|
493
|
+
blockIndex: allBlocks.length,
|
|
494
|
+
timestamp: Date.now()
|
|
495
|
+
});
|
|
496
|
+
} else if (parsed.type === 'assistant' && parsed.message?.content) {
|
|
479
497
|
for (const block of parsed.message.content) {
|
|
480
498
|
allBlocks.push(block);
|
|
481
|
-
eventCount++;
|
|
482
499
|
broadcastSync({
|
|
483
500
|
type: 'streaming_progress',
|
|
484
501
|
sessionId,
|
|
@@ -488,16 +505,45 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
|
|
|
488
505
|
timestamp: Date.now()
|
|
489
506
|
});
|
|
490
507
|
}
|
|
491
|
-
} else if (parsed.type === '
|
|
508
|
+
} else if (parsed.type === 'user' && parsed.message?.content) {
|
|
509
|
+
for (const block of parsed.message.content) {
|
|
510
|
+
if (block.type === 'tool_result') {
|
|
511
|
+
broadcastSync({
|
|
512
|
+
type: 'streaming_progress',
|
|
513
|
+
sessionId,
|
|
514
|
+
conversationId,
|
|
515
|
+
block: {
|
|
516
|
+
type: 'tool_result',
|
|
517
|
+
tool_use_id: block.tool_use_id,
|
|
518
|
+
content: typeof block.content === 'string' ? block.content : JSON.stringify(block.content),
|
|
519
|
+
is_error: block.is_error || false
|
|
520
|
+
},
|
|
521
|
+
blockIndex: allBlocks.length,
|
|
522
|
+
timestamp: Date.now()
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
} else if (parsed.type === 'result') {
|
|
492
527
|
broadcastSync({
|
|
493
528
|
type: 'streaming_progress',
|
|
494
529
|
sessionId,
|
|
495
530
|
conversationId,
|
|
496
|
-
block: {
|
|
497
|
-
|
|
531
|
+
block: {
|
|
532
|
+
type: 'result',
|
|
533
|
+
subtype: parsed.subtype,
|
|
534
|
+
duration_ms: parsed.duration_ms,
|
|
535
|
+
total_cost_usd: parsed.total_cost_usd,
|
|
536
|
+
num_turns: parsed.num_turns,
|
|
537
|
+
is_error: parsed.is_error || false,
|
|
538
|
+
result: parsed.result
|
|
539
|
+
},
|
|
540
|
+
blockIndex: allBlocks.length,
|
|
498
541
|
isResult: true,
|
|
499
542
|
timestamp: Date.now()
|
|
500
543
|
});
|
|
544
|
+
if (parsed.result && allBlocks.length === 0) {
|
|
545
|
+
allBlocks.push({ type: 'text', text: String(parsed.result) });
|
|
546
|
+
}
|
|
501
547
|
}
|
|
502
548
|
};
|
|
503
549
|
|
package/static/index.html
CHANGED
|
@@ -431,6 +431,170 @@
|
|
|
431
431
|
margin: 0.25rem 0;
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
+
/* --- Streaming block types --- */
|
|
435
|
+
.streaming-block-system {
|
|
436
|
+
padding: 0.5rem 0.75rem;
|
|
437
|
+
margin: 0.25rem 0;
|
|
438
|
+
background: rgba(59,130,246,0.08);
|
|
439
|
+
border: 1px solid rgba(59,130,246,0.2);
|
|
440
|
+
border-radius: 0.375rem;
|
|
441
|
+
font-size: 0.8rem;
|
|
442
|
+
display: flex;
|
|
443
|
+
align-items: center;
|
|
444
|
+
gap: 0.5rem;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.system-model-badge {
|
|
448
|
+
background: var(--color-primary);
|
|
449
|
+
color: white;
|
|
450
|
+
padding: 0.125rem 0.5rem;
|
|
451
|
+
border-radius: 1rem;
|
|
452
|
+
font-size: 0.7rem;
|
|
453
|
+
font-weight: 600;
|
|
454
|
+
white-space: nowrap;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.system-info {
|
|
458
|
+
color: var(--color-text-secondary);
|
|
459
|
+
font-size: 0.75rem;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.streaming-block-tool-use {
|
|
463
|
+
margin: 0.5rem 0;
|
|
464
|
+
border-left: 3px solid #06b6d4;
|
|
465
|
+
background: rgba(6,182,212,0.06);
|
|
466
|
+
border-radius: 0 0.375rem 0.375rem 0;
|
|
467
|
+
overflow: hidden;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.tool-use-header {
|
|
471
|
+
padding: 0.5rem 0.75rem;
|
|
472
|
+
font-weight: 600;
|
|
473
|
+
font-size: 0.85rem;
|
|
474
|
+
display: flex;
|
|
475
|
+
align-items: center;
|
|
476
|
+
gap: 0.375rem;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.tool-use-icon {
|
|
480
|
+
font-size: 0.9rem;
|
|
481
|
+
opacity: 0.7;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.tool-use-name {
|
|
485
|
+
color: #0891b2;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
html.dark .tool-use-name { color: #22d3ee; }
|
|
489
|
+
|
|
490
|
+
.tool-input-details {
|
|
491
|
+
border-top: 1px solid rgba(6,182,212,0.15);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.tool-input-summary {
|
|
495
|
+
padding: 0.375rem 0.75rem;
|
|
496
|
+
font-size: 0.75rem;
|
|
497
|
+
color: var(--color-text-secondary);
|
|
498
|
+
cursor: pointer;
|
|
499
|
+
user-select: none;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.tool-input-summary:hover {
|
|
503
|
+
background: rgba(6,182,212,0.08);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.tool-input-pre {
|
|
507
|
+
margin: 0;
|
|
508
|
+
padding: 0.5rem 0.75rem;
|
|
509
|
+
font-size: 0.75rem;
|
|
510
|
+
font-family: 'Monaco','Menlo','Ubuntu Mono', monospace;
|
|
511
|
+
background: rgba(0,0,0,0.03);
|
|
512
|
+
overflow-x: auto;
|
|
513
|
+
max-height: 200px;
|
|
514
|
+
overflow-y: auto;
|
|
515
|
+
white-space: pre-wrap;
|
|
516
|
+
word-break: break-all;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
html.dark .tool-input-pre { background: rgba(255,255,255,0.03); }
|
|
520
|
+
|
|
521
|
+
.streaming-block-tool-result {
|
|
522
|
+
margin: 0.25rem 0 0.5rem 0;
|
|
523
|
+
border-radius: 0.375rem;
|
|
524
|
+
background: var(--color-bg-code);
|
|
525
|
+
overflow: hidden;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.tool-result-header {
|
|
529
|
+
padding: 0.375rem 0.75rem;
|
|
530
|
+
font-size: 0.7rem;
|
|
531
|
+
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.tool-result-ok-badge {
|
|
535
|
+
color: #10b981;
|
|
536
|
+
font-weight: 600;
|
|
537
|
+
text-transform: uppercase;
|
|
538
|
+
letter-spacing: 0.05em;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.tool-result-error-badge {
|
|
542
|
+
color: #ef4444;
|
|
543
|
+
font-weight: 600;
|
|
544
|
+
text-transform: uppercase;
|
|
545
|
+
letter-spacing: 0.05em;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.tool-result-pre {
|
|
549
|
+
margin: 0;
|
|
550
|
+
padding: 0.5rem 0.75rem;
|
|
551
|
+
font-size: 0.75rem;
|
|
552
|
+
font-family: 'Monaco','Menlo','Ubuntu Mono', monospace;
|
|
553
|
+
color: #d1d5db;
|
|
554
|
+
overflow-x: auto;
|
|
555
|
+
max-height: 300px;
|
|
556
|
+
overflow-y: auto;
|
|
557
|
+
white-space: pre-wrap;
|
|
558
|
+
word-break: break-all;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.streaming-block-tool-result.tool-result-error {
|
|
562
|
+
border: 1px solid rgba(239,68,68,0.3);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.streaming-block-result {
|
|
566
|
+
padding: 0.5rem 0.75rem;
|
|
567
|
+
margin: 0.5rem 0;
|
|
568
|
+
border-radius: 0.375rem;
|
|
569
|
+
background: rgba(16,185,129,0.08);
|
|
570
|
+
border: 1px solid rgba(16,185,129,0.2);
|
|
571
|
+
font-size: 0.8rem;
|
|
572
|
+
display: flex;
|
|
573
|
+
align-items: center;
|
|
574
|
+
gap: 0.5rem;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.streaming-block-result.result-error {
|
|
578
|
+
background: rgba(239,68,68,0.08);
|
|
579
|
+
border-color: rgba(239,68,68,0.2);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
.result-status {
|
|
583
|
+
font-weight: 600;
|
|
584
|
+
color: #10b981;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.result-error .result-status { color: #ef4444; }
|
|
588
|
+
|
|
589
|
+
.result-stats {
|
|
590
|
+
color: var(--color-text-secondary);
|
|
591
|
+
font-size: 0.75rem;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.streaming-indicator-label {
|
|
595
|
+
white-space: nowrap;
|
|
596
|
+
}
|
|
597
|
+
|
|
434
598
|
/* --- Input area: fixed at bottom --- */
|
|
435
599
|
.input-section {
|
|
436
600
|
flex-shrink: 0;
|
package/static/js/client.js
CHANGED
|
@@ -274,7 +274,7 @@ class AgentGUIClient {
|
|
|
274
274
|
<div class="message-blocks streaming-blocks"></div>
|
|
275
275
|
<div class="streaming-indicator" style="display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0;color:var(--color-text-secondary);font-size:0.875rem;">
|
|
276
276
|
<span class="animate-spin" style="display:inline-block;width:1rem;height:1rem;border:2px solid var(--color-border);border-top-color:var(--color-primary);border-radius:50%;"></span>
|
|
277
|
-
Thinking
|
|
277
|
+
<span class="streaming-indicator-label">Thinking...</span>
|
|
278
278
|
</div>
|
|
279
279
|
`;
|
|
280
280
|
messagesEl.appendChild(streamingDiv);
|
|
@@ -300,37 +300,75 @@ class AgentGUIClient {
|
|
|
300
300
|
if (!blocksEl) return;
|
|
301
301
|
|
|
302
302
|
const indicator = streamingEl.querySelector('.streaming-indicator');
|
|
303
|
+
let indicatorText = 'Responding...';
|
|
303
304
|
|
|
304
|
-
if (block.type === '
|
|
305
|
+
if (block.type === 'system') {
|
|
306
|
+
const div = document.createElement('div');
|
|
307
|
+
div.className = 'streaming-block-system';
|
|
308
|
+
const toolCount = block.tools ? block.tools.length : 0;
|
|
309
|
+
div.innerHTML = `<span class="system-model-badge">${this.escapeHtml(block.model || 'unknown')}</span> <span class="system-info">${toolCount} tools available</span>`;
|
|
310
|
+
blocksEl.appendChild(div);
|
|
311
|
+
indicatorText = 'Initializing...';
|
|
312
|
+
} else if (block.type === 'text' && block.text) {
|
|
305
313
|
const existingTextEl = blocksEl.querySelector('.streaming-text-current');
|
|
306
314
|
if (existingTextEl && !data.isResult) {
|
|
307
315
|
existingTextEl.innerHTML = this.renderBlockContent(block);
|
|
308
316
|
} else {
|
|
317
|
+
const prevTextEl = blocksEl.querySelector('.streaming-text-current');
|
|
318
|
+
if (prevTextEl) prevTextEl.classList.remove('streaming-text-current');
|
|
309
319
|
const div = document.createElement('div');
|
|
310
320
|
div.className = 'message-text streaming-text-current';
|
|
311
321
|
div.innerHTML = this.renderBlockContent(block);
|
|
312
322
|
blocksEl.appendChild(div);
|
|
313
323
|
}
|
|
324
|
+
indicatorText = 'Responding...';
|
|
314
325
|
} else if (block.type === 'tool_use') {
|
|
315
326
|
const prevTextEl = blocksEl.querySelector('.streaming-text-current');
|
|
316
327
|
if (prevTextEl) prevTextEl.classList.remove('streaming-text-current');
|
|
317
328
|
|
|
318
329
|
const div = document.createElement('div');
|
|
319
|
-
div.className = '
|
|
320
|
-
div.
|
|
330
|
+
div.className = 'streaming-block-tool-use';
|
|
331
|
+
div.dataset.toolUseId = block.id || '';
|
|
332
|
+
let inputHtml = '';
|
|
333
|
+
if (block.input && Object.keys(block.input).length > 0) {
|
|
334
|
+
const inputStr = JSON.stringify(block.input, null, 2);
|
|
335
|
+
inputHtml = `<details class="tool-input-details"><summary class="tool-input-summary">Input</summary><pre class="tool-input-pre">${this.escapeHtml(inputStr)}</pre></details>`;
|
|
336
|
+
}
|
|
337
|
+
div.innerHTML = `<div class="tool-use-header"><span class="tool-use-icon">⚙</span> <span class="tool-use-name">${this.escapeHtml(block.name || 'unknown')}</span></div>${inputHtml}`;
|
|
321
338
|
blocksEl.appendChild(div);
|
|
339
|
+
indicatorText = `Using ${block.name || 'tool'}...`;
|
|
322
340
|
} else if (block.type === 'tool_result') {
|
|
323
341
|
const div = document.createElement('div');
|
|
324
|
-
div.className = '
|
|
325
|
-
|
|
342
|
+
div.className = 'streaming-block-tool-result' + (block.is_error ? ' tool-result-error' : '');
|
|
343
|
+
const content = block.content || '';
|
|
344
|
+
const displayContent = content.length > 2000 ? content.substring(0, 2000) + '\n... (truncated)' : content;
|
|
345
|
+
div.innerHTML = `<div class="tool-result-header">${block.is_error ? '<span class="tool-result-error-badge">Error</span>' : '<span class="tool-result-ok-badge">Result</span>'}</div><pre class="tool-result-pre">${this.escapeHtml(displayContent)}</pre>`;
|
|
346
|
+
blocksEl.appendChild(div);
|
|
347
|
+
indicatorText = 'Processing result...';
|
|
348
|
+
} else if (block.type === 'result') {
|
|
349
|
+
const div = document.createElement('div');
|
|
350
|
+
div.className = 'streaming-block-result' + (block.is_error ? ' result-error' : '');
|
|
351
|
+
const duration = block.duration_ms ? (block.duration_ms / 1000).toFixed(1) + 's' : '';
|
|
352
|
+
const cost = block.total_cost_usd ? '$' + block.total_cost_usd.toFixed(4) : '';
|
|
353
|
+
const turns = block.num_turns ? block.num_turns + ' turns' : '';
|
|
354
|
+
const parts = [duration, cost, turns].filter(Boolean);
|
|
355
|
+
div.innerHTML = `<span class="result-status">${block.is_error ? 'Failed' : 'Complete'}</span>${parts.length ? ' <span class="result-stats">' + parts.join(' / ') + '</span>' : ''}`;
|
|
326
356
|
blocksEl.appendChild(div);
|
|
357
|
+
indicatorText = 'Complete';
|
|
327
358
|
}
|
|
328
359
|
|
|
329
|
-
if (indicator) indicator.querySelector('span:last-child')?.remove();
|
|
330
360
|
if (indicator) {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
361
|
+
const labelEl = indicator.querySelector('.streaming-indicator-label');
|
|
362
|
+
if (labelEl) {
|
|
363
|
+
labelEl.textContent = indicatorText;
|
|
364
|
+
} else {
|
|
365
|
+
const existingLabel = indicator.querySelector('span:last-child');
|
|
366
|
+
if (existingLabel && !existingLabel.classList.contains('animate-spin')) existingLabel.remove();
|
|
367
|
+
const label = document.createElement('span');
|
|
368
|
+
label.className = 'streaming-indicator-label';
|
|
369
|
+
label.textContent = indicatorText;
|
|
370
|
+
indicator.appendChild(label);
|
|
371
|
+
}
|
|
334
372
|
}
|
|
335
373
|
|
|
336
374
|
this.scrollToBottom();
|
|
@@ -555,7 +593,16 @@ class AgentGUIClient {
|
|
|
555
593
|
html += `<div class="message-code"><pre>${this.escapeHtml(block.code)}</pre></div>`;
|
|
556
594
|
}
|
|
557
595
|
} else if (block.type === 'tool_use') {
|
|
558
|
-
|
|
596
|
+
let inputHtml = '';
|
|
597
|
+
if (block.input && Object.keys(block.input).length > 0) {
|
|
598
|
+
const inputStr = JSON.stringify(block.input, null, 2);
|
|
599
|
+
inputHtml = `<details class="tool-input-details"><summary class="tool-input-summary">Input</summary><pre class="tool-input-pre">${this.escapeHtml(inputStr)}</pre></details>`;
|
|
600
|
+
}
|
|
601
|
+
html += `<div class="streaming-block-tool-use"><div class="tool-use-header"><span class="tool-use-icon">⚙</span> <span class="tool-use-name">${this.escapeHtml(block.name || 'unknown')}</span></div>${inputHtml}</div>`;
|
|
602
|
+
} else if (block.type === 'tool_result') {
|
|
603
|
+
const content = typeof block.content === 'string' ? block.content : JSON.stringify(block.content);
|
|
604
|
+
const displayContent = content.length > 2000 ? content.substring(0, 2000) + '\n... (truncated)' : content;
|
|
605
|
+
html += `<div class="streaming-block-tool-result${block.is_error ? ' tool-result-error' : ''}"><div class="tool-result-header">${block.is_error ? '<span class="tool-result-error-badge">Error</span>' : '<span class="tool-result-ok-badge">Result</span>'}</div><pre class="tool-result-pre">${this.escapeHtml(displayContent)}</pre></div>`;
|
|
559
606
|
}
|
|
560
607
|
});
|
|
561
608
|
}
|
|
@@ -843,7 +890,16 @@ class AgentGUIClient {
|
|
|
843
890
|
contentHtml += `<div class="message-code"><pre>${this.escapeHtml(block.code)}</pre></div>`;
|
|
844
891
|
}
|
|
845
892
|
} else if (block.type === 'tool_use') {
|
|
846
|
-
|
|
893
|
+
let inputHtml = '';
|
|
894
|
+
if (block.input && Object.keys(block.input).length > 0) {
|
|
895
|
+
const inputStr = JSON.stringify(block.input, null, 2);
|
|
896
|
+
inputHtml = `<details class="tool-input-details"><summary class="tool-input-summary">Input</summary><pre class="tool-input-pre">${this.escapeHtml(inputStr)}</pre></details>`;
|
|
897
|
+
}
|
|
898
|
+
contentHtml += `<div class="streaming-block-tool-use"><div class="tool-use-header"><span class="tool-use-icon">⚙</span> <span class="tool-use-name">${this.escapeHtml(block.name || 'unknown')}</span></div>${inputHtml}</div>`;
|
|
899
|
+
} else if (block.type === 'tool_result') {
|
|
900
|
+
const content = typeof block.content === 'string' ? block.content : JSON.stringify(block.content);
|
|
901
|
+
const displayContent = content.length > 2000 ? content.substring(0, 2000) + '\n... (truncated)' : content;
|
|
902
|
+
contentHtml += `<div class="streaming-block-tool-result${block.is_error ? ' tool-result-error' : ''}"><div class="tool-result-header">${block.is_error ? '<span class="tool-result-error-badge">Error</span>' : '<span class="tool-result-ok-badge">Result</span>'}</div><pre class="tool-result-pre">${this.escapeHtml(displayContent)}</pre></div>`;
|
|
847
903
|
}
|
|
848
904
|
});
|
|
849
905
|
}
|