@alpaca-editor/core 1.0.4131 → 1.0.4133
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 +35 -77
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/ToolCallDisplay.d.ts +1 -1
- package/dist/editor/ai/ToolCallDisplay.js +24 -49
- package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +3 -3
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ToolbarButton.js +1 -1
- package/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +1 -0
- package/dist/editor/services/agentService.js +137 -3
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/sidebar/ComponentPalette.js +8 -0
- package/dist/editor/sidebar/ComponentPalette.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 +69 -117
- package/src/editor/ai/ToolCallDisplay.tsx +185 -200
- package/src/editor/field-types/richtext/components/ReactSlate.tsx +22 -23
- package/src/editor/field-types/richtext/components/ToolbarButton.tsx +1 -1
- package/src/editor/services/agentService.ts +135 -4
- package/src/editor/sidebar/ComponentPalette.tsx +11 -0
- package/src/revision.ts +2 -2
|
@@ -487,7 +487,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
487
487
|
});
|
|
488
488
|
throw new Error("No agent available");
|
|
489
489
|
}
|
|
490
|
-
|
|
490
|
+
// Reduced: avoid verbose logging during streaming
|
|
491
491
|
return {
|
|
492
492
|
id: messageId,
|
|
493
493
|
agentId: currentAgent.id,
|
|
@@ -594,7 +594,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
594
594
|
// Final check before adding to prevent duplicates
|
|
595
595
|
const finalCheck = prev.find((msg) => msg.id === toolCallMessageId);
|
|
596
596
|
if (finalCheck) {
|
|
597
|
-
console.log("#!# ⚠️ Tool call message already exists in state, skipping:", toolCallMessageId);
|
|
598
597
|
return prev;
|
|
599
598
|
}
|
|
600
599
|
const updated = [...prev, newStreamMessage];
|
|
@@ -603,9 +602,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
603
602
|
});
|
|
604
603
|
}
|
|
605
604
|
}
|
|
606
|
-
else {
|
|
607
|
-
console.log("📋 Adding tool call to existing message:", toolCallMessageId);
|
|
608
|
-
}
|
|
609
605
|
}
|
|
610
606
|
// Add tool call to the message in the array
|
|
611
607
|
if (toolCallMessageId && message.data && toolCallId) {
|
|
@@ -667,10 +663,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
667
663
|
}
|
|
668
664
|
// Update tool result directly in the messages array
|
|
669
665
|
if (!resultMessageId) {
|
|
670
|
-
console.warn("⚠️ No messageId available for tool result");
|
|
671
666
|
return;
|
|
672
667
|
}
|
|
673
|
-
console.log("📋 Updating tool result in message:", resultMessageId);
|
|
674
668
|
// Update the message with tool result
|
|
675
669
|
setMessages((prev) => {
|
|
676
670
|
const updated = prev.map((msg) => {
|
|
@@ -729,7 +723,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
729
723
|
};
|
|
730
724
|
updatedMessage.toolCalls = [...updatedMessage.toolCalls, toolCall];
|
|
731
725
|
}
|
|
732
|
-
|
|
726
|
+
// Updated tool calls count
|
|
733
727
|
return updatedMessage;
|
|
734
728
|
});
|
|
735
729
|
messagesRef.current = updated;
|
|
@@ -763,16 +757,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
763
757
|
abortControllerRef.current = abortController;
|
|
764
758
|
try {
|
|
765
759
|
setIsConnecting(true);
|
|
766
|
-
|
|
760
|
+
// Reduced: minimal logging
|
|
767
761
|
// Expose agent id globally for approval actions
|
|
768
762
|
window.currentAgentId = currentAgent.id;
|
|
769
|
-
|
|
770
|
-
|
|
763
|
+
// Expose id for approval actions
|
|
764
|
+
// Connecting to agent stream
|
|
771
765
|
await connectToAgentStream(currentAgent.id, (message) => {
|
|
772
|
-
console.log("📨 Received stream message:", {
|
|
773
|
-
type: message.type,
|
|
774
|
-
data: message.data,
|
|
775
|
-
});
|
|
776
766
|
switch (message.type) {
|
|
777
767
|
case "contentChunk":
|
|
778
768
|
handleContentChunk(message, currentAgent);
|
|
@@ -786,15 +776,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
786
776
|
case "statusUpdate":
|
|
787
777
|
try {
|
|
788
778
|
const kind = message?.data?.kind;
|
|
789
|
-
console.log("📡 Received status update:", {
|
|
790
|
-
kind,
|
|
791
|
-
data: message.data,
|
|
792
|
-
});
|
|
793
779
|
if (kind === "toolApprovalsRequired") {
|
|
794
780
|
const data = message.data || {};
|
|
795
781
|
const msgId = data.messageId;
|
|
796
782
|
const ids = data.toolCallIds || [];
|
|
797
|
-
|
|
783
|
+
// Pause stream until approval
|
|
798
784
|
// Annotate tool calls with a temporary pending marker so UI can reflect paused state on reload
|
|
799
785
|
if (msgId && Array.isArray(ids) && ids.length > 0) {
|
|
800
786
|
setMessages((prev) => {
|
|
@@ -899,21 +885,9 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
899
885
|
const data = message.data || {};
|
|
900
886
|
const toolCallId = data.toolCallId;
|
|
901
887
|
const msgId = data.messageId;
|
|
902
|
-
|
|
903
|
-
kind,
|
|
904
|
-
toolCallId,
|
|
905
|
-
msgId,
|
|
906
|
-
data,
|
|
907
|
-
});
|
|
888
|
+
// Processing tool approval
|
|
908
889
|
if (toolCallId && msgId) {
|
|
909
890
|
setMessages((prev) => {
|
|
910
|
-
console.log("🔍 Looking for message:", {
|
|
911
|
-
targetMsgId: msgId,
|
|
912
|
-
availableMessages: prev.map((m) => ({
|
|
913
|
-
id: m.id,
|
|
914
|
-
toolCallsCount: m.toolCalls?.length || 0,
|
|
915
|
-
})),
|
|
916
|
-
});
|
|
917
891
|
const updated = prev.map((m) => {
|
|
918
892
|
if (m.id !== msgId)
|
|
919
893
|
return m;
|
|
@@ -925,11 +899,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
925
899
|
? " (approved)"
|
|
926
900
|
: " (rejected)";
|
|
927
901
|
const newFunctionName = (tc.functionName || "") + suffix;
|
|
928
|
-
|
|
929
|
-
toolCallId,
|
|
930
|
-
oldName: tc.functionName,
|
|
931
|
-
newName: newFunctionName,
|
|
932
|
-
});
|
|
902
|
+
// Update function name with approval suffix
|
|
933
903
|
return {
|
|
934
904
|
...tc,
|
|
935
905
|
functionName: newFunctionName,
|
|
@@ -948,7 +918,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
948
918
|
break;
|
|
949
919
|
case "completed":
|
|
950
920
|
const completedMessageId = message.data?.messageId;
|
|
951
|
-
console.log("💾 Stream completed for message:", completedMessageId, "messages count:", messages.length);
|
|
952
921
|
// If the completed event carries full messages, merge them into state
|
|
953
922
|
try {
|
|
954
923
|
const completionMessages = message?.data
|
|
@@ -1101,7 +1070,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1101
1070
|
}
|
|
1102
1071
|
}
|
|
1103
1072
|
finally {
|
|
1104
|
-
console.log("🔌 Stream connection finished, cleaning up");
|
|
1105
1073
|
setIsConnecting(false);
|
|
1106
1074
|
// Guard: clear waiting state if connection finished without content
|
|
1107
1075
|
setIsWaitingForResponse(false);
|
|
@@ -1115,18 +1083,13 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1115
1083
|
return;
|
|
1116
1084
|
// Check if we're already connected
|
|
1117
1085
|
if (abortControllerRef.current) {
|
|
1118
|
-
console.log("🔄 Already connected to stream, skipping reconnect");
|
|
1119
1086
|
return;
|
|
1120
1087
|
}
|
|
1121
1088
|
const msgs = messagesRef.current || [];
|
|
1122
1089
|
const hasPending = msgs.some((m) => (m.toolCalls || []).some((tc) => (tc.functionName || "").includes("(pending approval)")));
|
|
1123
1090
|
if (!hasPending) {
|
|
1124
|
-
console.log("🔄 No pending approvals; reconnecting stream");
|
|
1125
1091
|
await connectToStream(currentAgent);
|
|
1126
1092
|
}
|
|
1127
|
-
else {
|
|
1128
|
-
console.log("⏸️ Still have pending approvals, not reconnecting yet");
|
|
1129
|
-
}
|
|
1130
1093
|
}
|
|
1131
1094
|
catch (err) {
|
|
1132
1095
|
console.error("❌ Error attempting reconnect:", err);
|
|
@@ -1142,11 +1105,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1142
1105
|
const approved = !!detail.approved;
|
|
1143
1106
|
if (!messageId || !toolCallId)
|
|
1144
1107
|
return;
|
|
1145
|
-
|
|
1146
|
-
messageId,
|
|
1147
|
-
toolCallId,
|
|
1148
|
-
approved,
|
|
1149
|
-
});
|
|
1108
|
+
// Approval resolved; update local state
|
|
1150
1109
|
setMessages((prev) => {
|
|
1151
1110
|
const updated = prev.map((m) => {
|
|
1152
1111
|
if (m.id !== messageId)
|
|
@@ -1184,10 +1143,9 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1184
1143
|
const loadAgent = useCallback(async () => {
|
|
1185
1144
|
try {
|
|
1186
1145
|
if (agentStub.status === "new") {
|
|
1187
|
-
console.log("✅ Setting up new agent", agentStub.id);
|
|
1188
1146
|
// Set agent ID immediately for new agents
|
|
1189
1147
|
window.currentAgentId = agentStub.id;
|
|
1190
|
-
|
|
1148
|
+
// Set currentAgentId for new agent
|
|
1191
1149
|
// Derive initial profile from provided metadata if present
|
|
1192
1150
|
const initialProfileIdFromMeta = (() => {
|
|
1193
1151
|
try {
|
|
@@ -1369,7 +1327,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1369
1327
|
setMessages(agentData.messages || []);
|
|
1370
1328
|
// Set agent ID for existing agents too
|
|
1371
1329
|
window.currentAgentId = agentData.id;
|
|
1372
|
-
console.log("🔗 Setting currentAgentId for existing agent:", agentData.id);
|
|
1373
1330
|
// Parse metadata from DB if present (do not seed for existing agents)
|
|
1374
1331
|
const parsedMeta = (() => {
|
|
1375
1332
|
try {
|
|
@@ -1392,16 +1349,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1392
1349
|
// Connect to stream if agent is running (handle both string and numeric status)
|
|
1393
1350
|
const isRunning = agentData.status === "running" || agentData.status === 1;
|
|
1394
1351
|
if (isRunning) {
|
|
1395
|
-
console.log("🚀 Agent is running, connecting to stream...", {
|
|
1396
|
-
agentId: agentData.id,
|
|
1397
|
-
status: agentData.status,
|
|
1398
|
-
messageCount: agentData.messages?.length || 0,
|
|
1399
|
-
});
|
|
1400
1352
|
// Use setTimeout to ensure state updates are processed first
|
|
1401
1353
|
setTimeout(async () => {
|
|
1402
1354
|
// Check if we're already connecting to avoid duplicate connections
|
|
1403
1355
|
if (abortControllerRef.current) {
|
|
1404
|
-
console.log("⚠️ loadAgent: Already connected to stream, skipping duplicate connection");
|
|
1405
1356
|
return;
|
|
1406
1357
|
}
|
|
1407
1358
|
// Reset streaming state for reconnection
|
|
@@ -1411,7 +1362,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1411
1362
|
const hasPending = (agentData.messages || []).some((m) => (m.toolCalls || []).some((tc) => typeof tc?.functionName === "string" &&
|
|
1412
1363
|
tc.functionName.includes("(pending approval)")));
|
|
1413
1364
|
if (hasPending) {
|
|
1414
|
-
console.log("⏸️ loadAgent: Pending approvals detected, delaying stream reconnect");
|
|
1415
1365
|
return;
|
|
1416
1366
|
}
|
|
1417
1367
|
}
|
|
@@ -1426,7 +1376,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1426
1376
|
// For new agents that don't exist yet, this is expected
|
|
1427
1377
|
if (err?.message?.includes("404") ||
|
|
1428
1378
|
err?.message?.includes("not found")) {
|
|
1429
|
-
|
|
1379
|
+
// Agent does not exist, treat as new
|
|
1430
1380
|
setAgent(undefined);
|
|
1431
1381
|
setMessages([]);
|
|
1432
1382
|
setError(null);
|
|
@@ -1495,7 +1445,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1495
1445
|
useEffect(() => {
|
|
1496
1446
|
return () => {
|
|
1497
1447
|
if (abortControllerRef.current) {
|
|
1498
|
-
console.log("Cleaning up stream connection");
|
|
1499
1448
|
abortControllerRef.current.abort();
|
|
1500
1449
|
}
|
|
1501
1450
|
};
|
|
@@ -1655,7 +1604,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
1655
1604
|
deterministic: deterministicFlags.deterministic,
|
|
1656
1605
|
seed: deterministicFlags.seed,
|
|
1657
1606
|
};
|
|
1658
|
-
|
|
1607
|
+
// Starting agent
|
|
1659
1608
|
// Set waiting state to show dancing dots immediately
|
|
1660
1609
|
setIsWaitingForResponse(true);
|
|
1661
1610
|
// Start idle timer; dots appear only if no chunks for >1s
|
|
@@ -2284,7 +2233,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
2284
2233
|
resetDotsTimer,
|
|
2285
2234
|
]);
|
|
2286
2235
|
if (isLoading) {
|
|
2287
|
-
return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-
|
|
2236
|
+
return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", strokeWidth: 1 }), "Loading agent..."] }) }));
|
|
2288
2237
|
}
|
|
2289
2238
|
// Calculate total token usage for cost display
|
|
2290
2239
|
const totalTokens = calculateTotalTokens(messages);
|
|
@@ -2435,19 +2384,28 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
|
|
|
2435
2384
|
setShowPredefined(false);
|
|
2436
2385
|
if (textareaRef.current)
|
|
2437
2386
|
textareaRef.current.focus();
|
|
2438
|
-
}, children: p.title }, index))) }) })] })) : null] }), _jsxs("div", { className: "flex items-center gap-1 self-end", children: [isVoiceSupported ? (_jsx(Button, { onClick: toggleVoice, size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isListening ? "Stop voice input" : "Start voice input", "aria-label": isListening ? "Stop voice input" : "Start voice input", "aria-pressed": isListening, children: isListening ? (_jsx(MicOff, { className: "size-3", strokeWidth: 1 })) : (_jsx(Mic, { className: "size-3", strokeWidth: 1 })) })) : null, _jsx(Button, { onClick: isExecuting ? handleStop : handleSubmit, disabled: !isExecuting && !prompt.trim(), size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isExecuting ? "Stop" : "Send", "aria-label": isExecuting ? "Stop" : "Send", "data-testid": "agent-send-stop-button", "data-executing": isExecuting ? "true" : "false", children: isExecuting ? (_jsx(Square, { className: "size-3", strokeWidth: 1 })) : (_jsx(Send, { className: "size-3", strokeWidth: 1 })) })] })] }),
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2387
|
+
}, children: p.title }, index))) }) })] })) : null] }), _jsxs("div", { className: "flex items-center gap-1 self-end", children: [isVoiceSupported ? (_jsx(Button, { onClick: toggleVoice, size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isListening ? "Stop voice input" : "Start voice input", "aria-label": isListening ? "Stop voice input" : "Start voice input", "aria-pressed": isListening, children: isListening ? (_jsx(MicOff, { className: "size-3", strokeWidth: 1 })) : (_jsx(Mic, { className: "size-3", strokeWidth: 1 })) })) : null, _jsx(Button, { onClick: isExecuting ? handleStop : handleSubmit, disabled: !isExecuting && !prompt.trim(), size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isExecuting ? "Stop" : "Send", "aria-label": isExecuting ? "Stop" : "Send", "data-testid": "agent-send-stop-button", "data-executing": isExecuting ? "true" : "false", children: isExecuting ? (_jsx(Square, { className: "size-3", strokeWidth: 1 })) : (_jsx(Send, { className: "size-3", strokeWidth: 1 })) })] })] }), _jsxs("div", { className: "mt-1 flex items-center gap-2 text-[10px] text-gray-500", children: [_jsx(AgentCostDisplay, { totalTokens: totalTokens }), (() => {
|
|
2388
|
+
try {
|
|
2389
|
+
const s = window.__agentContextWindowStatus;
|
|
2390
|
+
if (!s || !s.contextWindowTokens)
|
|
2391
|
+
return null;
|
|
2392
|
+
const pct = typeof s.contextUsedPercent === "number"
|
|
2393
|
+
? `${s.contextUsedPercent.toFixed(1)}%`
|
|
2394
|
+
: undefined;
|
|
2395
|
+
// Helper function to format tokens as "k"
|
|
2396
|
+
const formatTokens = (tokens) => {
|
|
2397
|
+
if (tokens >= 1000) {
|
|
2398
|
+
return `${(tokens / 1000).toFixed(1)}k`;
|
|
2399
|
+
}
|
|
2400
|
+
return tokens.toString();
|
|
2401
|
+
};
|
|
2402
|
+
if (!pct)
|
|
2403
|
+
return null;
|
|
2404
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "cursor-help rounded border border-gray-200 bg-gray-50 px-2 py-0.5", children: ["Context: ", pct] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: _jsxs("div", { className: "max-w-[320px] space-y-1 text-xs", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Model:" }), " ", s.model, s.normalizedModel && ` (${s.normalizedModel})`] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Context window:" }), " ", formatTokens(s.estimatedInputTokens || 0), " /", " ", formatTokens(s.contextWindowTokens), " tokens"] }), typeof s.maxCompletionTokens === "number" && (_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Max completion:" }), " ", formatTokens(s.maxCompletionTokens), " tokens"] })), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Used:" }), " ", pct] })] }) })] }));
|
|
2405
|
+
}
|
|
2406
|
+
catch {
|
|
2442
2407
|
return null;
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
: undefined;
|
|
2446
|
-
return (_jsxs("div", { className: "rounded border border-gray-200 bg-gray-50 px-2 py-0.5", children: [_jsxs("span", { title: `Model: ${s.model} (${s.normalizedModel || ""})`, children: ["Context window: ", s.estimatedInputTokens || 0, " /", " ", s.contextWindowTokens] }), typeof s.maxCompletionTokens === "number" && (_jsxs("span", { children: [" \u00B7 Max completion: ", s.maxCompletionTokens] })), pct && _jsxs("span", { children: [" \u00B7 Used: ", pct] })] }));
|
|
2447
|
-
}
|
|
2448
|
-
catch {
|
|
2449
|
-
return null;
|
|
2450
|
-
}
|
|
2451
|
-
})() })] })] }));
|
|
2408
|
+
}
|
|
2409
|
+
})()] })] })] }));
|
|
2452
2410
|
}
|
|
2453
2411
|
//# sourceMappingURL=AgentTerminal.js.map
|