agentgui 1.0.231 → 1.0.233
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 +25 -0
- package/static/js/client.js +40 -5
- package/static/js/conversations.js +3 -0
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1757,6 +1757,30 @@ const server = http.createServer(async (req, res) => {
|
|
|
1757
1757
|
return;
|
|
1758
1758
|
}
|
|
1759
1759
|
|
|
1760
|
+
if (pathOnly === '/api/git/check-remote-ownership' && req.method === 'GET') {
|
|
1761
|
+
try {
|
|
1762
|
+
const result = execSync('git remote get-url origin 2>/dev/null', { encoding: 'utf-8', cwd: STARTUP_CWD });
|
|
1763
|
+
const remoteUrl = result.trim();
|
|
1764
|
+
const statusResult = execSync('git status --porcelain', { encoding: 'utf-8', cwd: STARTUP_CWD });
|
|
1765
|
+
const hasChanges = statusResult.trim().length > 0;
|
|
1766
|
+
const ownsRemote = !remoteUrl.includes('github.com/') || remoteUrl.includes(process.env.GITHUB_USER || '');
|
|
1767
|
+
sendJSON(req, res, 200, { ownsRemote, hasChanges, remoteUrl });
|
|
1768
|
+
} catch {
|
|
1769
|
+
sendJSON(req, res, 200, { ownsRemote: false, hasChanges: false, remoteUrl: '' });
|
|
1770
|
+
}
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
if (pathOnly === '/api/git/push' && req.method === 'POST') {
|
|
1775
|
+
try {
|
|
1776
|
+
execSync('git add -A && git commit -m "Auto-commit" && git push', { encoding: 'utf-8', cwd: STARTUP_CWD });
|
|
1777
|
+
sendJSON(req, res, 200, { success: true });
|
|
1778
|
+
} catch (err) {
|
|
1779
|
+
sendJSON(req, res, 500, { error: err.message });
|
|
1780
|
+
}
|
|
1781
|
+
return;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1760
1784
|
if (routePath.startsWith('/api/image/')) {
|
|
1761
1785
|
const imagePath = routePath.slice('/api/image/'.length);
|
|
1762
1786
|
const decodedPath = decodeURIComponent(imagePath);
|
|
@@ -2085,6 +2109,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
|
|
|
2085
2109
|
type: 'streaming_complete',
|
|
2086
2110
|
sessionId,
|
|
2087
2111
|
conversationId,
|
|
2112
|
+
agentId,
|
|
2088
2113
|
eventCount,
|
|
2089
2114
|
seq: currentSequence,
|
|
2090
2115
|
timestamp: Date.now()
|
package/static/js/client.js
CHANGED
|
@@ -764,7 +764,6 @@ class AgentGUIClient {
|
|
|
764
764
|
|
|
765
765
|
this.state.streamingConversations.delete(conversationId);
|
|
766
766
|
|
|
767
|
-
// Stop polling for chunks
|
|
768
767
|
this.stopChunkPolling();
|
|
769
768
|
|
|
770
769
|
const sessionId = data.sessionId || this.state.currentSession?.id;
|
|
@@ -782,13 +781,36 @@ class AgentGUIClient {
|
|
|
782
781
|
streamingEl.appendChild(ts);
|
|
783
782
|
}
|
|
784
783
|
|
|
785
|
-
// Save scroll position after streaming completes
|
|
786
784
|
if (conversationId) {
|
|
787
785
|
this.saveScrollPosition(conversationId);
|
|
788
786
|
}
|
|
789
787
|
|
|
790
788
|
this.enableControls();
|
|
791
789
|
this.emit('streaming:complete', data);
|
|
790
|
+
|
|
791
|
+
if (data.agentId && this._isACPAgent(data.agentId)) {
|
|
792
|
+
this._promptPushIfWeOwnRemote();
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
_isACPAgent(agentId) {
|
|
797
|
+
const acpAgents = ['opencode', 'gemini', 'goose', 'openhands', 'augment', 'cline', 'kimi', 'qwen', 'codex', 'mistral', 'kiro', 'fast-agent'];
|
|
798
|
+
return acpAgents.includes(agentId);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async _promptPushIfWeOwnRemote() {
|
|
802
|
+
try {
|
|
803
|
+
const result = await fetch(window.__BASE_URL + '/api/git/check-remote-ownership');
|
|
804
|
+
const { ownsRemote, hasChanges, remoteUrl } = await result.json();
|
|
805
|
+
if (ownsRemote && hasChanges) {
|
|
806
|
+
const shouldPush = confirm('Push changes to remote?');
|
|
807
|
+
if (shouldPush) {
|
|
808
|
+
await fetch(window.__BASE_URL + '/api/git/push', { method: 'POST' });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
} catch (e) {
|
|
812
|
+
console.warn('Failed to check git remote ownership:', e);
|
|
813
|
+
}
|
|
792
814
|
}
|
|
793
815
|
|
|
794
816
|
/**
|
|
@@ -796,6 +818,9 @@ class AgentGUIClient {
|
|
|
796
818
|
*/
|
|
797
819
|
handleConversationCreated(data) {
|
|
798
820
|
if (data.conversation) {
|
|
821
|
+
if (this.state.conversations.some(c => c.id === data.conversation.id)) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
799
824
|
this.state.conversations.push(data.conversation);
|
|
800
825
|
this.emit('conversation:created', data.conversation);
|
|
801
826
|
}
|
|
@@ -833,6 +858,19 @@ class AgentGUIClient {
|
|
|
833
858
|
this.emit('message:created', data);
|
|
834
859
|
return;
|
|
835
860
|
}
|
|
861
|
+
// Also check for pending ID (in case message-sending was already removed by _confirmOptimisticMessage)
|
|
862
|
+
const pendingById = outputEl.querySelector('[id^="pending-"]');
|
|
863
|
+
if (pendingById) {
|
|
864
|
+
pendingById.id = '';
|
|
865
|
+
pendingById.setAttribute('data-msg-id', data.message.id);
|
|
866
|
+
const ts = pendingById.querySelector('.message-timestamp');
|
|
867
|
+
if (ts) {
|
|
868
|
+
ts.style.opacity = '1';
|
|
869
|
+
ts.textContent = new Date(data.message.created_at).toLocaleString();
|
|
870
|
+
}
|
|
871
|
+
this.emit('message:created', data);
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
836
874
|
// Check if a user message with this ID already exists (prevents duplicate on race condition)
|
|
837
875
|
const existingMsg = outputEl.querySelector(`[data-msg-id="${data.message.id}"]`);
|
|
838
876
|
if (existingMsg) {
|
|
@@ -1465,7 +1503,6 @@ class AgentGUIClient {
|
|
|
1465
1503
|
}
|
|
1466
1504
|
|
|
1467
1505
|
this._lastSendTime = Date.now();
|
|
1468
|
-
this._startThinkingCountdown();
|
|
1469
1506
|
this.emit('execution:started', result);
|
|
1470
1507
|
} catch (error) {
|
|
1471
1508
|
console.error('Stream execution error:', error);
|
|
@@ -1954,14 +1991,12 @@ class AgentGUIClient {
|
|
|
1954
1991
|
* Disable UI controls during streaming
|
|
1955
1992
|
*/
|
|
1956
1993
|
disableControls() {
|
|
1957
|
-
if (this.ui.sendButton) this.ui.sendButton.disabled = true;
|
|
1958
1994
|
}
|
|
1959
1995
|
|
|
1960
1996
|
/**
|
|
1961
1997
|
* Enable UI controls
|
|
1962
1998
|
*/
|
|
1963
1999
|
enableControls() {
|
|
1964
|
-
if (this.ui.sendButton) this.ui.sendButton.disabled = false;
|
|
1965
2000
|
}
|
|
1966
2001
|
|
|
1967
2002
|
/**
|