agentgui 1.0.726 → 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/server.js +1 -1
- package/static/js/client.js +79 -167
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1506,7 +1506,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1506
1506
|
if (messagesMatch) {
|
|
1507
1507
|
if (req.method === 'GET') {
|
|
1508
1508
|
const url = new URL(req.url, 'http://localhost');
|
|
1509
|
-
const limit = Math.min(parseInt(url.searchParams.get('limit') || '50'),
|
|
1509
|
+
const limit = Math.min(parseInt(url.searchParams.get('limit') || '50'), 500);
|
|
1510
1510
|
const offset = Math.max(parseInt(url.searchParams.get('offset') || '0'), 0);
|
|
1511
1511
|
const result = queries.getPaginatedMessages(messagesMatch[1], limit, offset);
|
|
1512
1512
|
sendJSON(req, res, 200, result);
|
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());
|
|
@@ -2741,10 +2752,11 @@ class AgentGUIClient {
|
|
|
2741
2752
|
return;
|
|
2742
2753
|
}
|
|
2743
2754
|
try {
|
|
2755
|
+
const base = window.__BASE_URL || '';
|
|
2744
2756
|
const [convRes, chunksRes, msgsRes] = await Promise.all([
|
|
2745
|
-
fetch(
|
|
2746
|
-
fetch(
|
|
2747
|
-
fetch(
|
|
2757
|
+
fetch(`${base}/api/conversations/${conversationId}`),
|
|
2758
|
+
fetch(`${base}/api/conversations/${conversationId}/chunks`),
|
|
2759
|
+
fetch(`${base}/api/conversations/${conversationId}/messages?limit=500`)
|
|
2748
2760
|
]);
|
|
2749
2761
|
const convData = await convRes.json();
|
|
2750
2762
|
const chunksData = await chunksRes.json();
|
|
@@ -2834,14 +2846,7 @@ class AgentGUIClient {
|
|
|
2834
2846
|
try {
|
|
2835
2847
|
try {
|
|
2836
2848
|
await window.wsClient.rpc('conv.full', { id: conversationId, allChunks: true });
|
|
2837
|
-
} catch (wsErr) {
|
|
2838
|
-
const [chunksRes, msgsRes] = await Promise.all([
|
|
2839
|
-
fetch(`/gm/api/conversations/${conversationId}/chunks`),
|
|
2840
|
-
fetch(`/gm/api/conversations/${conversationId}/messages?limit=500`)
|
|
2841
|
-
]);
|
|
2842
|
-
const chunksData = await chunksRes.json();
|
|
2843
|
-
const msgsData = await msgsRes.json();
|
|
2844
|
-
}
|
|
2849
|
+
} catch (wsErr) {}
|
|
2845
2850
|
this.invalidateCache(conversationId);
|
|
2846
2851
|
await this.loadConversationMessages(conversationId);
|
|
2847
2852
|
} catch (e) {
|
|
@@ -2853,103 +2858,8 @@ class AgentGUIClient {
|
|
|
2853
2858
|
}
|
|
2854
2859
|
|
|
2855
2860
|
if (chunks.length > 0) {
|
|
2856
|
-
const
|
|
2857
|
-
|
|
2858
|
-
chunks.forEach(chunk => {
|
|
2859
|
-
if (!sessionChunks[chunk.sessionId]) {
|
|
2860
|
-
sessionChunks[chunk.sessionId] = [];
|
|
2861
|
-
sessionOrder.push(chunk.sessionId);
|
|
2862
|
-
}
|
|
2863
|
-
sessionChunks[chunk.sessionId].push(chunk);
|
|
2864
|
-
});
|
|
2865
|
-
|
|
2866
|
-
const frag = document.createDocumentFragment();
|
|
2867
|
-
let userMsgIdx = 0;
|
|
2868
|
-
|
|
2869
|
-
sessionOrder.forEach((sessionId) => {
|
|
2870
|
-
const sessionChunkList = sessionChunks[sessionId];
|
|
2871
|
-
const sessionStart = sessionChunkList[0].created_at;
|
|
2872
|
-
|
|
2873
|
-
while (userMsgIdx < userMessages.length && userMessages[userMsgIdx].created_at <= sessionStart) {
|
|
2874
|
-
const msg = userMessages[userMsgIdx];
|
|
2875
|
-
const userDiv = document.createElement('div');
|
|
2876
|
-
userDiv.className = 'message message-user';
|
|
2877
|
-
userDiv.setAttribute('data-msg-id', msg.id);
|
|
2878
|
-
userDiv.innerHTML = `
|
|
2879
|
-
<div class="message-role">User</div>
|
|
2880
|
-
${this.renderMessageContent(msg.content)}
|
|
2881
|
-
<div class="message-timestamp">${new Date(msg.created_at).toLocaleString()}</div>
|
|
2882
|
-
`;
|
|
2883
|
-
frag.appendChild(userDiv);
|
|
2884
|
-
userMsgIdx++;
|
|
2885
|
-
}
|
|
2886
|
-
|
|
2887
|
-
const isCurrentActiveSession = shouldResumeStreaming && latestSession && latestSession.id === sessionId;
|
|
2888
|
-
const messageDiv = document.createElement('div');
|
|
2889
|
-
messageDiv.className = `message message-assistant${isCurrentActiveSession ? ' streaming-message' : ''}`;
|
|
2890
|
-
messageDiv.id = isCurrentActiveSession ? `streaming-${sessionId}` : `message-${sessionId}`;
|
|
2891
|
-
messageDiv.innerHTML = '<div class="message-role">Assistant</div><div class="message-blocks streaming-blocks"></div>';
|
|
2892
|
-
|
|
2893
|
-
const blocksEl = messageDiv.querySelector('.message-blocks');
|
|
2894
|
-
const blockFrag = document.createDocumentFragment();
|
|
2895
|
-
const toolResultBlocks = new Map();
|
|
2896
|
-
|
|
2897
|
-
sessionChunkList.forEach(chunk => {
|
|
2898
|
-
if (!chunk.block?.type) return;
|
|
2899
|
-
if (chunk.block.type === 'tool_result') {
|
|
2900
|
-
toolResultBlocks.set(chunk.id, chunk);
|
|
2901
|
-
return;
|
|
2902
|
-
}
|
|
2903
|
-
const element = this.renderer.renderBlock(chunk.block, chunk, blockFrag);
|
|
2904
|
-
if (!element) return;
|
|
2905
|
-
element.classList.add('block-loaded');
|
|
2906
|
-
blockFrag.appendChild(element);
|
|
2907
|
-
});
|
|
2908
|
-
|
|
2909
|
-
blocksEl.appendChild(blockFrag);
|
|
2910
|
-
|
|
2911
|
-
toolResultBlocks.forEach((chunk) => {
|
|
2912
|
-
const toolUseId = chunk.block.tool_use_id;
|
|
2913
|
-
const toolUseEl = toolUseId
|
|
2914
|
-
? blocksEl.querySelector(`.block-tool-use[data-tool-use-id="${toolUseId}"]`)
|
|
2915
|
-
: blocksEl.lastElementChild?.classList?.contains('block-type-tool_use') ? blocksEl.lastElementChild : null;
|
|
2916
|
-
if (!toolUseEl) return;
|
|
2917
|
-
this.renderer.mergeResultIntoToolUse(toolUseEl, chunk.block);
|
|
2918
|
-
});
|
|
2919
|
-
|
|
2920
|
-
if (isCurrentActiveSession) {
|
|
2921
|
-
const indicatorDiv = document.createElement('div');
|
|
2922
|
-
indicatorDiv.className = 'streaming-indicator';
|
|
2923
|
-
indicatorDiv.style = 'display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0;color:var(--color-text-secondary);font-size:0.875rem;';
|
|
2924
|
-
indicatorDiv.innerHTML = `
|
|
2925
|
-
<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>
|
|
2926
|
-
<span class="streaming-indicator-label">Processing...</span>
|
|
2927
|
-
`;
|
|
2928
|
-
messageDiv.appendChild(indicatorDiv);
|
|
2929
|
-
} else {
|
|
2930
|
-
const ts = document.createElement('div');
|
|
2931
|
-
ts.className = 'message-timestamp';
|
|
2932
|
-
ts.textContent = new Date(sessionChunkList[sessionChunkList.length - 1].created_at).toLocaleString();
|
|
2933
|
-
messageDiv.appendChild(ts);
|
|
2934
|
-
}
|
|
2935
|
-
|
|
2936
|
-
frag.appendChild(messageDiv);
|
|
2937
|
-
});
|
|
2938
|
-
|
|
2939
|
-
while (userMsgIdx < userMessages.length) {
|
|
2940
|
-
const msg = userMessages[userMsgIdx];
|
|
2941
|
-
const userDiv = document.createElement('div');
|
|
2942
|
-
userDiv.className = 'message message-user';
|
|
2943
|
-
userDiv.setAttribute('data-msg-id', msg.id);
|
|
2944
|
-
userDiv.innerHTML = `
|
|
2945
|
-
<div class="message-role">User</div>
|
|
2946
|
-
${this.renderMessageContent(msg.content)}
|
|
2947
|
-
<div class="message-timestamp">${new Date(msg.created_at).toLocaleString()}</div>
|
|
2948
|
-
`;
|
|
2949
|
-
frag.appendChild(userDiv);
|
|
2950
|
-
userMsgIdx++;
|
|
2951
|
-
}
|
|
2952
|
-
if (!convSignal.aborted) messagesEl.appendChild(frag);
|
|
2861
|
+
const activeSessionId = (shouldResumeStreaming && latestSession) ? latestSession.id : null;
|
|
2862
|
+
if (!convSignal.aborted) this._renderConversationContent(messagesEl, chunks, userMessages, activeSessionId);
|
|
2953
2863
|
} else {
|
|
2954
2864
|
if (!convSignal.aborted) messagesEl.appendChild(this.renderMessagesFragment(allMessages || []));
|
|
2955
2865
|
}
|
|
@@ -3111,7 +3021,8 @@ class AgentGUIClient {
|
|
|
3111
3021
|
limit: 50
|
|
3112
3022
|
});
|
|
3113
3023
|
} catch (e) {
|
|
3114
|
-
const
|
|
3024
|
+
const base = window.__BASE_URL || '';
|
|
3025
|
+
const r = await fetch(`${base}/api/conversations/${conversationId}/messages?limit=50`);
|
|
3115
3026
|
const d = await r.json();
|
|
3116
3027
|
result = { messages: d.messages || [] };
|
|
3117
3028
|
}
|
|
@@ -3123,7 +3034,8 @@ class AgentGUIClient {
|
|
|
3123
3034
|
limit: 500
|
|
3124
3035
|
});
|
|
3125
3036
|
} catch (e) {
|
|
3126
|
-
const
|
|
3037
|
+
const base = window.__BASE_URL || '';
|
|
3038
|
+
const r = await fetch(`${base}/api/conversations/${conversationId}/chunks`);
|
|
3127
3039
|
const d = await r.json();
|
|
3128
3040
|
result = { chunks: d.chunks || [] };
|
|
3129
3041
|
}
|