agentgui 1.0.727 → 1.0.728

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/static/js/client.js +70 -154
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.727",
3
+ "version": "1.0.728",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
@@ -880,58 +880,7 @@ class AgentGUIClient {
880
880
  }));
881
881
  const userMsgs = (fullData.messages || []).filter(m => m.role === 'user');
882
882
  if (priorChunks.length > 0) {
883
- const sessionOrder = [];
884
- const sessionGroups = {};
885
- priorChunks.forEach(c => {
886
- if (!sessionGroups[c.sessionId]) { sessionGroups[c.sessionId] = []; sessionOrder.push(c.sessionId); }
887
- sessionGroups[c.sessionId].push(c);
888
- });
889
- const priorFrag = document.createDocumentFragment();
890
- let ui = 0;
891
- sessionOrder.forEach(sid => {
892
- const sList = sessionGroups[sid];
893
- const sStart = sList[0].created_at;
894
- while (ui < userMsgs.length && userMsgs[ui].created_at <= sStart) {
895
- const m = userMsgs[ui++];
896
- const uDiv = document.createElement('div');
897
- uDiv.className = 'message message-user';
898
- uDiv.setAttribute('data-msg-id', m.id);
899
- uDiv.innerHTML = `<div class="message-role">User</div>${this.renderMessageContent(m.content)}<div class="message-timestamp">${new Date(m.created_at).toLocaleString()}</div>`;
900
- priorFrag.appendChild(uDiv);
901
- }
902
- const mDiv = document.createElement('div');
903
- mDiv.className = 'message message-assistant';
904
- mDiv.id = `message-${sid}`;
905
- mDiv.innerHTML = '<div class="message-role">Assistant</div><div class="message-blocks streaming-blocks"></div>';
906
- const bEl = mDiv.querySelector('.message-blocks');
907
- const bFrag = document.createDocumentFragment();
908
- sList.forEach(chunk => {
909
- if (!chunk.block?.type) return;
910
- if (chunk.block.type === 'tool_result') {
911
- const lastInFrag = bFrag.lastElementChild;
912
- if (lastInFrag?.classList?.contains('block-tool-use')) {
913
- this.renderer.mergeResultIntoToolUse(lastInFrag, chunk.block);
914
- return;
915
- }
916
- }
917
- const el = this.renderer.renderBlock(chunk.block, chunk, bFrag);
918
- if (!el) return;
919
- bFrag.appendChild(el);
920
- });
921
- bEl.appendChild(bFrag);
922
- const ts = document.createElement('div'); ts.className = 'message-timestamp'; ts.textContent = new Date(sList[sList.length - 1].created_at).toLocaleString();
923
- mDiv.appendChild(ts);
924
- priorFrag.appendChild(mDiv);
925
- });
926
- while (ui < userMsgs.length) {
927
- const m = userMsgs[ui++];
928
- const uDiv = document.createElement('div');
929
- uDiv.className = 'message message-user';
930
- uDiv.setAttribute('data-msg-id', m.id);
931
- uDiv.innerHTML = `<div class="message-role">User</div>${this.renderMessageContent(m.content)}<div class="message-timestamp">${new Date(m.created_at).toLocaleString()}</div>`;
932
- priorFrag.appendChild(uDiv);
933
- }
934
- messagesEl.appendChild(priorFrag);
883
+ this._renderConversationContent(messagesEl, priorChunks, userMsgs, null);
935
884
  } else {
936
885
  messagesEl.appendChild(this.renderMessagesFragment(fullData.messages || []));
937
886
  }
@@ -955,7 +904,6 @@ class AgentGUIClient {
955
904
  `;
956
905
  messagesEl.appendChild(streamingDiv);
957
906
  } else {
958
- // Reuse existing div - ensure streaming class and single indicator
959
907
  streamingDiv.classList.add('streaming-message');
960
908
  streamingDiv.querySelectorAll('.streaming-indicator').forEach(ind => ind.remove());
961
909
  const indDiv = document.createElement('div');
@@ -2130,12 +2078,75 @@ class AgentGUIClient {
2130
2078
  }
2131
2079
  }
2132
2080
 
2133
- /**
2134
- * Render a single chunk to the output
2135
- */
2081
+ _renderConversationContent(messagesContainer, chunks, userMessages, activeSessionId) {
2082
+ if (!chunks || chunks.length === 0) return;
2083
+ const sessionMap = new Map();
2084
+ for (const chunk of chunks) {
2085
+ if (!sessionMap.has(chunk.sessionId)) sessionMap.set(chunk.sessionId, []);
2086
+ sessionMap.get(chunk.sessionId).push(chunk);
2087
+ }
2088
+ const frag = document.createDocumentFragment();
2089
+ let ui = 0;
2090
+ for (const [sid, list] of sessionMap) {
2091
+ const sessionStart = list[0].created_at;
2092
+ while (ui < userMessages.length && userMessages[ui].created_at <= sessionStart) {
2093
+ const m = userMessages[ui++];
2094
+ const uDiv = document.createElement('div');
2095
+ uDiv.className = 'message message-user';
2096
+ uDiv.setAttribute('data-msg-id', m.id);
2097
+ uDiv.innerHTML = `<div class="message-role">User</div>${this.renderMessageContent(m.content)}<div class="message-timestamp">${new Date(m.created_at).toLocaleString()}</div>`;
2098
+ frag.appendChild(uDiv);
2099
+ }
2100
+ const isActive = sid === activeSessionId;
2101
+ const msgDiv = document.createElement('div');
2102
+ msgDiv.className = `message message-assistant${isActive ? ' streaming-message' : ''}`;
2103
+ msgDiv.id = isActive ? `streaming-${sid}` : `message-${sid}`;
2104
+ msgDiv.innerHTML = '<div class="message-role">Assistant</div><div class="message-blocks streaming-blocks"></div>';
2105
+ const blocksEl = msgDiv.querySelector('.message-blocks');
2106
+ const blockFrag = document.createDocumentFragment();
2107
+ const deferred = [];
2108
+ for (const chunk of list) {
2109
+ if (!chunk.block?.type) continue;
2110
+ if (chunk.block.type === 'tool_result') { deferred.push(chunk); continue; }
2111
+ const el = this.renderer.renderBlock(chunk.block, chunk, blockFrag);
2112
+ if (!el) continue;
2113
+ el.classList.add('block-loaded');
2114
+ blockFrag.appendChild(el);
2115
+ }
2116
+ blocksEl.appendChild(blockFrag);
2117
+ for (const chunk of deferred) {
2118
+ const tid = chunk.block.tool_use_id;
2119
+ const toolUseEl = (tid ? blocksEl.querySelector(`.block-tool-use[data-tool-use-id="${tid}"]`) : null)
2120
+ || (blocksEl.lastElementChild?.classList.contains('block-tool-use') ? blocksEl.lastElementChild : null);
2121
+ if (toolUseEl) this.renderer.mergeResultIntoToolUse(toolUseEl, chunk.block);
2122
+ }
2123
+ if (isActive) {
2124
+ const ind = document.createElement('div');
2125
+ ind.className = 'streaming-indicator';
2126
+ ind.style = 'display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0;color:var(--color-text-secondary);font-size:0.875rem;';
2127
+ ind.innerHTML = '<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><span class="streaming-indicator-label">Processing...</span>';
2128
+ msgDiv.appendChild(ind);
2129
+ } else {
2130
+ const ts = document.createElement('div');
2131
+ ts.className = 'message-timestamp';
2132
+ ts.textContent = new Date(list[list.length - 1].created_at).toLocaleString();
2133
+ msgDiv.appendChild(ts);
2134
+ }
2135
+ frag.appendChild(msgDiv);
2136
+ }
2137
+ while (ui < userMessages.length) {
2138
+ const m = userMessages[ui++];
2139
+ const uDiv = document.createElement('div');
2140
+ uDiv.className = 'message message-user';
2141
+ uDiv.setAttribute('data-msg-id', m.id);
2142
+ uDiv.innerHTML = `<div class="message-role">User</div>${this.renderMessageContent(m.content)}<div class="message-timestamp">${new Date(m.created_at).toLocaleString()}</div>`;
2143
+ frag.appendChild(uDiv);
2144
+ }
2145
+ messagesContainer.appendChild(frag);
2146
+ }
2147
+
2136
2148
  renderChunk(chunk) {
2137
2149
  if (!chunk || !chunk.block) return;
2138
- // Deduplicate: skip if already rendered via WebSocket streaming_progress
2139
2150
  const seq = chunk.sequence;
2140
2151
  if (seq !== undefined) {
2141
2152
  const seen = (this._renderedSeqs = this._renderedSeqs || {})[chunk.sessionId] || (this._renderedSeqs[chunk.sessionId] = new Set());
@@ -2847,103 +2858,8 @@ class AgentGUIClient {
2847
2858
  }
2848
2859
 
2849
2860
  if (chunks.length > 0) {
2850
- const sessionOrder = [];
2851
- const sessionChunks = {};
2852
- chunks.forEach(chunk => {
2853
- if (!sessionChunks[chunk.sessionId]) {
2854
- sessionChunks[chunk.sessionId] = [];
2855
- sessionOrder.push(chunk.sessionId);
2856
- }
2857
- sessionChunks[chunk.sessionId].push(chunk);
2858
- });
2859
-
2860
- const frag = document.createDocumentFragment();
2861
- let userMsgIdx = 0;
2862
-
2863
- sessionOrder.forEach((sessionId) => {
2864
- const sessionChunkList = sessionChunks[sessionId];
2865
- const sessionStart = sessionChunkList[0].created_at;
2866
-
2867
- while (userMsgIdx < userMessages.length && userMessages[userMsgIdx].created_at <= sessionStart) {
2868
- const msg = userMessages[userMsgIdx];
2869
- const userDiv = document.createElement('div');
2870
- userDiv.className = 'message message-user';
2871
- userDiv.setAttribute('data-msg-id', msg.id);
2872
- userDiv.innerHTML = `
2873
- <div class="message-role">User</div>
2874
- ${this.renderMessageContent(msg.content)}
2875
- <div class="message-timestamp">${new Date(msg.created_at).toLocaleString()}</div>
2876
- `;
2877
- frag.appendChild(userDiv);
2878
- userMsgIdx++;
2879
- }
2880
-
2881
- const isCurrentActiveSession = shouldResumeStreaming && latestSession && latestSession.id === sessionId;
2882
- const messageDiv = document.createElement('div');
2883
- messageDiv.className = `message message-assistant${isCurrentActiveSession ? ' streaming-message' : ''}`;
2884
- messageDiv.id = isCurrentActiveSession ? `streaming-${sessionId}` : `message-${sessionId}`;
2885
- messageDiv.innerHTML = '<div class="message-role">Assistant</div><div class="message-blocks streaming-blocks"></div>';
2886
-
2887
- const blocksEl = messageDiv.querySelector('.message-blocks');
2888
- const blockFrag = document.createDocumentFragment();
2889
- const toolResultBlocks = new Map();
2890
-
2891
- sessionChunkList.forEach(chunk => {
2892
- if (!chunk.block?.type) return;
2893
- if (chunk.block.type === 'tool_result') {
2894
- toolResultBlocks.set(chunk.id, chunk);
2895
- return;
2896
- }
2897
- const element = this.renderer.renderBlock(chunk.block, chunk, blockFrag);
2898
- if (!element) return;
2899
- element.classList.add('block-loaded');
2900
- blockFrag.appendChild(element);
2901
- });
2902
-
2903
- blocksEl.appendChild(blockFrag);
2904
-
2905
- toolResultBlocks.forEach((chunk) => {
2906
- const toolUseId = chunk.block.tool_use_id;
2907
- const toolUseEl = toolUseId
2908
- ? blocksEl.querySelector(`.block-tool-use[data-tool-use-id="${toolUseId}"]`)
2909
- : blocksEl.lastElementChild?.classList?.contains('block-type-tool_use') ? blocksEl.lastElementChild : null;
2910
- if (!toolUseEl) return;
2911
- this.renderer.mergeResultIntoToolUse(toolUseEl, chunk.block);
2912
- });
2913
-
2914
- if (isCurrentActiveSession) {
2915
- const indicatorDiv = document.createElement('div');
2916
- indicatorDiv.className = 'streaming-indicator';
2917
- indicatorDiv.style = 'display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0;color:var(--color-text-secondary);font-size:0.875rem;';
2918
- indicatorDiv.innerHTML = `
2919
- <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>
2920
- <span class="streaming-indicator-label">Processing...</span>
2921
- `;
2922
- messageDiv.appendChild(indicatorDiv);
2923
- } else {
2924
- const ts = document.createElement('div');
2925
- ts.className = 'message-timestamp';
2926
- ts.textContent = new Date(sessionChunkList[sessionChunkList.length - 1].created_at).toLocaleString();
2927
- messageDiv.appendChild(ts);
2928
- }
2929
-
2930
- frag.appendChild(messageDiv);
2931
- });
2932
-
2933
- while (userMsgIdx < userMessages.length) {
2934
- const msg = userMessages[userMsgIdx];
2935
- const userDiv = document.createElement('div');
2936
- userDiv.className = 'message message-user';
2937
- userDiv.setAttribute('data-msg-id', msg.id);
2938
- userDiv.innerHTML = `
2939
- <div class="message-role">User</div>
2940
- ${this.renderMessageContent(msg.content)}
2941
- <div class="message-timestamp">${new Date(msg.created_at).toLocaleString()}</div>
2942
- `;
2943
- frag.appendChild(userDiv);
2944
- userMsgIdx++;
2945
- }
2946
- if (!convSignal.aborted) messagesEl.appendChild(frag);
2861
+ const activeSessionId = (shouldResumeStreaming && latestSession) ? latestSession.id : null;
2862
+ if (!convSignal.aborted) this._renderConversationContent(messagesEl, chunks, userMessages, activeSessionId);
2947
2863
  } else {
2948
2864
  if (!convSignal.aborted) messagesEl.appendChild(this.renderMessagesFragment(allMessages || []));
2949
2865
  }