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.
- package/package.json +1 -1
- package/static/js/client.js +70 -154
package/package.json
CHANGED
package/static/js/client.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
2851
|
-
|
|
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
|
}
|