@alpaca-editor/core 1.0.4145 → 1.0.4146
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/dist/editor/ai/AgentTerminal.js +53 -51
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +1 -1
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/ToolCallDisplay.js +2 -1
- package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
- package/dist/editor/services/agentService.js +9 -1
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/package.json +1 -1
- package/src/editor/ai/AgentTerminal.tsx +65 -60
- package/src/editor/ai/AiResponseMessage.tsx +4 -1
- package/src/editor/ai/ToolCallDisplay.tsx +2 -1
- package/src/editor/services/agentService.ts +9 -1
- package/src/revision.ts +2 -2
|
@@ -1000,18 +1000,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1000
1000
|
messagesRef.current = updated;
|
|
1001
1001
|
return updated;
|
|
1002
1002
|
});
|
|
1003
|
-
// Dispatch a local event so the UI can attempt reconnect when approvals get resolved while paused
|
|
1004
|
-
try {
|
|
1005
|
-
const ev = new CustomEvent("agent:toolApprovalResolved", {
|
|
1006
|
-
detail: {
|
|
1007
|
-
messageId: resultMessageId,
|
|
1008
|
-
toolCallId: resultToolCallId,
|
|
1009
|
-
approved: !(message.data?.functionError || message.data?.error),
|
|
1010
|
-
},
|
|
1011
|
-
});
|
|
1012
|
-
window.dispatchEvent(ev);
|
|
1013
|
-
}
|
|
1014
|
-
catch { }
|
|
1015
1003
|
// Tool result activity; reset idle timer
|
|
1016
1004
|
resetDotsTimer();
|
|
1017
1005
|
}, [resetDotsTimer]);
|
|
@@ -1047,6 +1035,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1047
1035
|
case "statusUpdate":
|
|
1048
1036
|
try {
|
|
1049
1037
|
const kind = message?.data?.kind;
|
|
1038
|
+
if (kind === "streamOpen") {
|
|
1039
|
+
setIsConnecting(false);
|
|
1040
|
+
setIsWaitingForResponse(false);
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1050
1043
|
// Live token usage totals update from backend
|
|
1051
1044
|
if (kind === "tokenUsage") {
|
|
1052
1045
|
const totals = message?.data?.totals;
|
|
@@ -1106,10 +1099,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1106
1099
|
return updated;
|
|
1107
1100
|
});
|
|
1108
1101
|
}
|
|
1109
|
-
//
|
|
1102
|
+
// Keep the stream open; just clear waiting flags so UI reflects pause state
|
|
1110
1103
|
try {
|
|
1111
|
-
abortControllerRef.current?.abort();
|
|
1112
|
-
abortControllerRef.current = null;
|
|
1113
1104
|
setIsConnecting(false);
|
|
1114
1105
|
setIsWaitingForResponse(false);
|
|
1115
1106
|
}
|
|
@@ -1196,7 +1187,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1196
1187
|
const suffix = kind === "toolApprovalGranted"
|
|
1197
1188
|
? " (approved)"
|
|
1198
1189
|
: " (rejected)";
|
|
1199
|
-
|
|
1190
|
+
// Remove "(pending approval)" suffix before adding new suffix
|
|
1191
|
+
const baseFunctionName = (tc.functionName || "")
|
|
1192
|
+
.replace(" (pending approval)", "")
|
|
1193
|
+
.trim();
|
|
1194
|
+
const newFunctionName = baseFunctionName + suffix;
|
|
1200
1195
|
// Update function name with approval suffix
|
|
1201
1196
|
return {
|
|
1202
1197
|
...tc,
|
|
@@ -1398,27 +1393,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1398
1393
|
setIsWaitingForResponse(false);
|
|
1399
1394
|
}
|
|
1400
1395
|
}, [agent?.id, handleContentChunk, handleToolCall, handleToolResult]);
|
|
1401
|
-
//
|
|
1402
|
-
const attemptReconnectIfNoPending = useCallback(async () => {
|
|
1403
|
-
try {
|
|
1404
|
-
const currentAgent = agent;
|
|
1405
|
-
if (!currentAgent)
|
|
1406
|
-
return;
|
|
1407
|
-
// Check if we're already connected
|
|
1408
|
-
if (abortControllerRef.current) {
|
|
1409
|
-
return;
|
|
1410
|
-
}
|
|
1411
|
-
const msgs = messagesRef.current || [];
|
|
1412
|
-
const hasPending = msgs.some((m) => (m.toolCalls || []).some((tc) => (tc.functionName || "").includes("(pending approval)")));
|
|
1413
|
-
if (!hasPending) {
|
|
1414
|
-
await connectToStream(currentAgent);
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
catch (err) {
|
|
1418
|
-
console.error("❌ Error attempting reconnect:", err);
|
|
1419
|
-
}
|
|
1420
|
-
}, [agent, connectToStream]);
|
|
1421
|
-
// Listen for local approval resolution (when stream is paused) to update UI and reconnect
|
|
1396
|
+
// Listen for local approval resolution to update UI
|
|
1422
1397
|
useEffect(() => {
|
|
1423
1398
|
const onApprovalResolved = (ev) => {
|
|
1424
1399
|
try {
|
|
@@ -1428,7 +1403,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1428
1403
|
const approved = !!detail.approved;
|
|
1429
1404
|
if (!messageId || !toolCallId)
|
|
1430
1405
|
return;
|
|
1431
|
-
//
|
|
1406
|
+
// Update local state to reflect approval status
|
|
1432
1407
|
setMessages((prev) => {
|
|
1433
1408
|
const updated = prev.map((m) => {
|
|
1434
1409
|
if (m.id !== messageId)
|
|
@@ -1450,10 +1425,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1450
1425
|
messagesRef.current = updated;
|
|
1451
1426
|
return updated;
|
|
1452
1427
|
});
|
|
1453
|
-
// Try to reconnect if no more pending approvals remain
|
|
1454
|
-
setTimeout(() => {
|
|
1455
|
-
attemptReconnectIfNoPending();
|
|
1456
|
-
}, 100);
|
|
1457
1428
|
}
|
|
1458
1429
|
catch (err) {
|
|
1459
1430
|
console.error("❌ Error handling approval resolution:", err);
|
|
@@ -1461,7 +1432,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1461
1432
|
};
|
|
1462
1433
|
window.addEventListener("agent:toolApprovalResolved", onApprovalResolved);
|
|
1463
1434
|
return () => window.removeEventListener("agent:toolApprovalResolved", onApprovalResolved);
|
|
1464
|
-
}, [
|
|
1435
|
+
}, []);
|
|
1465
1436
|
// Load agent data and messages
|
|
1466
1437
|
const loadAgent = useCallback(async () => {
|
|
1467
1438
|
try {
|
|
@@ -1627,7 +1598,42 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1627
1598
|
setError(null);
|
|
1628
1599
|
const agentData = await getAgent(agentStub.id);
|
|
1629
1600
|
setAgent(agentData);
|
|
1630
|
-
|
|
1601
|
+
// Merge database messages with any existing streaming messages
|
|
1602
|
+
// to prevent losing responses that are currently being streamed
|
|
1603
|
+
setMessages((prevMessages) => {
|
|
1604
|
+
const dbMessages = agentData.messages || [];
|
|
1605
|
+
// Find any streaming (incomplete) messages that exist locally but not in DB
|
|
1606
|
+
const streamingMessages = prevMessages.filter((msg) => !msg.isCompleted && msg.role === "assistant");
|
|
1607
|
+
// If we have streaming messages, preserve them
|
|
1608
|
+
if (streamingMessages.length > 0) {
|
|
1609
|
+
// Get all completed messages from DB
|
|
1610
|
+
const completedDbMessages = dbMessages.filter((msg) => {
|
|
1611
|
+
// Check if this message is one of our streaming messages
|
|
1612
|
+
const isStreamingMessage = streamingMessages.some((sm) => sm.id === msg.id);
|
|
1613
|
+
return !isStreamingMessage;
|
|
1614
|
+
});
|
|
1615
|
+
// Merge: use DB messages but keep streaming ones
|
|
1616
|
+
const merged = [...completedDbMessages];
|
|
1617
|
+
// Add back the streaming messages at the end
|
|
1618
|
+
for (const streamingMsg of streamingMessages) {
|
|
1619
|
+
// Check if this message ID exists in DB messages
|
|
1620
|
+
const dbVersion = dbMessages.find((m) => m.id === streamingMsg.id);
|
|
1621
|
+
if (dbVersion &&
|
|
1622
|
+
dbVersion.content &&
|
|
1623
|
+
dbVersion.content.length > streamingMsg.content.length) {
|
|
1624
|
+
// DB has more content, skip the streaming version
|
|
1625
|
+
merged.push(dbVersion);
|
|
1626
|
+
}
|
|
1627
|
+
else {
|
|
1628
|
+
// Keep the streaming version
|
|
1629
|
+
merged.push(streamingMsg);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
return merged;
|
|
1633
|
+
}
|
|
1634
|
+
// No streaming messages, just use DB messages
|
|
1635
|
+
return dbMessages;
|
|
1636
|
+
});
|
|
1631
1637
|
// Set agent ID for existing agents too
|
|
1632
1638
|
window.currentAgentId = agentData.id;
|
|
1633
1639
|
// Check if cost limit was exceeded (detect from existing messages)
|
|
@@ -1686,8 +1692,9 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1686
1692
|
const isRunning = agentData.status === "running" || agentData.status === 1;
|
|
1687
1693
|
const isWaitingForApproval = agentData.status === "waitingForApproval" ||
|
|
1688
1694
|
agentData.status === 2;
|
|
1689
|
-
if (isRunning) {
|
|
1690
|
-
//
|
|
1695
|
+
if (isRunning || isWaitingForApproval) {
|
|
1696
|
+
// Auto-connect for running agents AND agents waiting for approval
|
|
1697
|
+
// (stream stays open during approval now)
|
|
1691
1698
|
setTimeout(async () => {
|
|
1692
1699
|
if (abortControllerRef.current) {
|
|
1693
1700
|
return;
|
|
@@ -1710,11 +1717,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1710
1717
|
await connectToStream(agentData);
|
|
1711
1718
|
}, 100);
|
|
1712
1719
|
}
|
|
1713
|
-
else if (isWaitingForApproval) {
|
|
1714
|
-
// For agents waiting for approval, just show the UI
|
|
1715
|
-
// The approval button handler will restart the agent if needed
|
|
1716
|
-
console.log("Agent is waiting for approval - showing approval UI without auto-reconnect");
|
|
1717
|
-
}
|
|
1718
1720
|
}
|
|
1719
1721
|
catch (err) {
|
|
1720
1722
|
console.error("❌ Failed to load agent:", err);
|