@alpaca-editor/core 1.0.4124 → 1.0.4128

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.
@@ -26,7 +26,9 @@ export function AgentCostDisplay({ className = "", response, totalTokens, }) {
26
26
  // Calculate estimated cost based on typical pricing (rough estimates)
27
27
  // Claude 3.5 Sonnet pricing: ~$3/MTok input, ~$15/MTok output
28
28
  const calculateEstimatedCost = (inputTokens, outputTokens, cachedTokens) => {
29
- const inputCost = (inputTokens / 1000000) * 3; // $3 per million tokens
29
+ // Cached tokens are a subset of input tokens, not additional tokens
30
+ const freshInputTokens = inputTokens - cachedTokens;
31
+ const inputCost = (freshInputTokens / 1000000) * 3; // $3 per million tokens
30
32
  const outputCost = (outputTokens / 1000000) * 15; // $15 per million tokens
31
33
  const cachedCost = (cachedTokens / 1000000) * 0.3; // Cached tokens are typically much cheaper
32
34
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"AgentCostDisplay.js","sourceRoot":"","sources":["../../../src/editor/ai/AgentCostDisplay.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentCostDisplay.js","sourceRoot":"","sources":["../../../src/editor/ai/AgentCostDisplay.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useEffect, useState, useRef, useCallback, useLayoutEffect, } from "react";
3
- import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, } from "lucide-react";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useEffect, useState, useRef, useCallback, useLayoutEffect, useMemo, } from "react";
3
+ import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, ChevronDown, ChevronUp, ListTodo, } from "lucide-react";
4
4
  import { DancingDots } from "./DancingDots";
5
5
  import { getAgent, startAgent, connectToAgentStream, updateAgentMetadata, updateAgentSettings, updateAgentCostLimit, } from "../services/agentService";
6
6
  import { useEditContext, useFieldsEditContext } from "../client/editContext";
@@ -18,6 +18,115 @@ import { Tooltip, TooltipTrigger, TooltipContent, } from "../../components/ui/to
18
18
  const UserMessage = ({ message }) => {
19
19
  return (_jsxs("div", { className: "flex gap-3 p-4", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx(User, { className: "h-6 w-6 text-blue-600", strokeWidth: 1 }) }), _jsxs("div", { className: "min-w-0 flex-1 select-text", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-gray-900", children: "You" }), message.createdDate && (_jsx("span", { className: "text-xs text-gray-400", children: formatTime(new Date(message.createdDate)) }))] }), _jsx("div", { className: "prose prose-sm max-w-none text-xs text-gray-700 select-text", children: message.content })] })] }));
20
20
  };
21
+ const extractTodosFromMessages = (messages) => {
22
+ const todos = [];
23
+ const fencedTodoToken = "```todo_list";
24
+ const plainTodoToken = "todo_list";
25
+ for (const message of messages) {
26
+ if (message.role !== "assistant" || !message.content)
27
+ continue;
28
+ const content = message.content;
29
+ let cursor = 0;
30
+ while (cursor < content.length) {
31
+ const nextFenced = content.indexOf(fencedTodoToken, cursor);
32
+ const nextPlain = content.indexOf(plainTodoToken, cursor);
33
+ let todoStart = -1;
34
+ let isFenced = false;
35
+ if (nextFenced !== -1 && (nextPlain === -1 || nextFenced < nextPlain)) {
36
+ todoStart = nextFenced;
37
+ isFenced = true;
38
+ }
39
+ else if (nextPlain !== -1) {
40
+ // Check if it's at line start
41
+ const before = nextPlain > 0 ? content[nextPlain - 1] : "\n";
42
+ if (before === "\n" || before === "\r" || nextPlain === 0) {
43
+ todoStart = nextPlain;
44
+ isFenced = false;
45
+ }
46
+ }
47
+ if (todoStart === -1)
48
+ break;
49
+ try {
50
+ let jsonText = "";
51
+ if (isFenced) {
52
+ const afterToken = todoStart + fencedTodoToken.length;
53
+ const closePos = content.indexOf("```", afterToken);
54
+ if (closePos === -1)
55
+ break;
56
+ jsonText = content.slice(afterToken, closePos).trim();
57
+ cursor = closePos + 3;
58
+ }
59
+ else {
60
+ const afterToken = todoStart + plainTodoToken.length;
61
+ const braceStart = content.indexOf("{", afterToken);
62
+ if (braceStart === -1)
63
+ break;
64
+ let depth = 0;
65
+ let braceEnd = -1;
66
+ for (let i = braceStart; i < content.length; i++) {
67
+ if (content[i] === "{")
68
+ depth++;
69
+ if (content[i] === "}") {
70
+ depth--;
71
+ if (depth === 0) {
72
+ braceEnd = i;
73
+ break;
74
+ }
75
+ }
76
+ }
77
+ if (braceEnd === -1)
78
+ break;
79
+ jsonText = content.slice(braceStart, braceEnd + 1).trim();
80
+ cursor = braceEnd + 1;
81
+ }
82
+ const parsed = JSON.parse(jsonText);
83
+ const todoItems = Array.isArray(parsed) ? parsed : parsed?.items || [];
84
+ const title = Array.isArray(parsed) ? undefined : parsed?.title;
85
+ todoItems.forEach((item) => {
86
+ if (!item)
87
+ return;
88
+ const text = item.text || item.label || String(item.task || item.title || "");
89
+ if (!text)
90
+ return;
91
+ todos.push({
92
+ id: item.id,
93
+ text,
94
+ done: !!(item.done ?? item.completed ?? item.checked),
95
+ note: item.note || item.description,
96
+ messageId: message.id,
97
+ sourceTitle: title,
98
+ });
99
+ });
100
+ }
101
+ catch (e) {
102
+ cursor++;
103
+ continue;
104
+ }
105
+ }
106
+ }
107
+ return todos;
108
+ };
109
+ // TodoListPanel component
110
+ const TodoListPanel = ({ messages }) => {
111
+ const [isExpanded, setIsExpanded] = useState(true);
112
+ const todos = useMemo(() => extractTodosFromMessages(messages), [messages]);
113
+ // Check if there's an active streaming message with todo content
114
+ const isUpdating = useMemo(() => {
115
+ return messages.some((msg) => {
116
+ if (msg.role !== "assistant" || msg.isCompleted)
117
+ return false;
118
+ const content = msg.content || "";
119
+ return content.includes("```todo_list") || content.includes("todo_list");
120
+ });
121
+ }, [messages]);
122
+ if (todos.length === 0 && !isUpdating)
123
+ return null;
124
+ const completedCount = todos.filter((t) => t.done).length;
125
+ const totalCount = todos.length;
126
+ return (_jsxs("div", { className: "border-t border-gray-200 bg-gray-50", children: [_jsxs("button", { onClick: () => setIsExpanded(!isExpanded), className: "flex w-full cursor-pointer items-center justify-between px-4 py-2 text-left transition-colors hover:bg-gray-100", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ListTodo, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }), _jsx("span", { className: "text-xs font-medium text-gray-700", children: "Todo List" }), isUpdating ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-blue-600", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), "Updating..."] })) : (_jsxs("span", { className: "text-xs text-gray-500", children: [completedCount, "/", totalCount, " completed"] }))] }), isExpanded ? (_jsx(ChevronUp, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 })) : (_jsx(ChevronDown, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }))] }), isExpanded && (_jsx("div", { className: "max-h-64 overflow-y-auto px-4 pb-3", children: isUpdating && todos.length === 0 ? (_jsxs("div", { className: "flex items-center justify-center gap-2 py-4 text-xs text-gray-500", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", strokeWidth: 1 }), _jsx("span", { children: "Loading todo list..." })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "space-y-1.5", children: todos.map((todo, idx) => (_jsxs("div", { className: "flex items-start gap-2 rounded bg-white p-2 text-xs", children: [_jsx("div", { className: "flex-shrink-0 pt-0.5", children: todo.done ? (_jsx("div", { className: "flex h-4 w-4 items-center justify-center rounded border-2 border-green-500 bg-green-500", children: _jsx("svg", { className: "h-3 w-3 text-white", fill: "none", strokeWidth: 2, stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }) })) : (_jsx("div", { className: "h-4 w-4 rounded border-2 border-gray-300" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: `${todo.done
127
+ ? "text-gray-500 line-through"
128
+ : "text-gray-900"}`, children: todo.text }), todo.note && (_jsx("div", { className: "mt-0.5 text-xs text-gray-500", children: todo.note }))] })] }, todo.id || `${todo.messageId}-${idx}`))) }), isUpdating && todos.length > 0 && (_jsxs("div", { className: "mt-2 flex items-center gap-2 rounded bg-blue-50 px-3 py-2 text-xs text-blue-700", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), _jsx("span", { children: "Updating todo list..." })] }))] })) }))] }));
129
+ };
21
130
  const groupConsecutiveMessages = (agentMessages) => {
22
131
  // Work directly with the messages array - streaming messages are identified by their properties
23
132
  const allMessages = agentMessages;
@@ -93,6 +202,8 @@ const convertAgentMessagesToAiFormat = (agentMessages) => {
93
202
  result: toolCall.functionResult,
94
203
  error: toolCall.functionError,
95
204
  },
205
+ // Pass through approval info if present on the tool call
206
+ requiresApproval: toolCall.requiresApproval,
96
207
  }))
97
208
  : [],
98
209
  };
@@ -515,6 +626,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
515
626
  isCompleted: false,
516
627
  responseTimeMs: message.data.responseTimeMs,
517
628
  createdDate: new Date().toISOString(),
629
+ requiresApproval: message.data?.requiresApproval,
518
630
  };
519
631
  // Check for duplicates using the current messages ref
520
632
  const currentMessages = messagesRef.current;
@@ -623,6 +735,18 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
623
735
  messagesRef.current = updated;
624
736
  return updated;
625
737
  });
738
+ // Dispatch a local event so the UI can attempt reconnect when approvals get resolved while paused
739
+ try {
740
+ const ev = new CustomEvent("agent:toolApprovalResolved", {
741
+ detail: {
742
+ messageId: resultMessageId,
743
+ toolCallId: resultToolCallId,
744
+ approved: !(message.data?.functionError || message.data?.error),
745
+ },
746
+ });
747
+ window.dispatchEvent(ev);
748
+ }
749
+ catch { }
626
750
  // Tool result activity; reset idle timer
627
751
  resetDotsTimer();
628
752
  }, [resetDotsTimer]);
@@ -640,7 +764,15 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
640
764
  try {
641
765
  setIsConnecting(true);
642
766
  console.log("🔌 connectToStream: Starting stream connection");
767
+ // Expose agent id globally for approval actions
768
+ window.currentAgentId = currentAgent.id;
769
+ console.log("🔗 Setting currentAgentId:", currentAgent.id);
770
+ console.log("🌐 Attempting to connect to agent stream for:", currentAgent.id);
643
771
  await connectToAgentStream(currentAgent.id, (message) => {
772
+ console.log("📨 Received stream message:", {
773
+ type: message.type,
774
+ data: message.data,
775
+ });
644
776
  switch (message.type) {
645
777
  case "contentChunk":
646
778
  handleContentChunk(message, currentAgent);
@@ -654,6 +786,49 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
654
786
  case "statusUpdate":
655
787
  try {
656
788
  const kind = message?.data?.kind;
789
+ console.log("📡 Received status update:", {
790
+ kind,
791
+ data: message.data,
792
+ });
793
+ if (kind === "toolApprovalsRequired") {
794
+ const data = message.data || {};
795
+ const msgId = data.messageId;
796
+ const ids = data.toolCallIds || [];
797
+ console.log("⏸️ Approvals required; pausing stream until approval:", { msgId, ids });
798
+ // Annotate tool calls with a temporary pending marker so UI can reflect paused state on reload
799
+ if (msgId && Array.isArray(ids) && ids.length > 0) {
800
+ setMessages((prev) => {
801
+ const updated = prev.map((m) => {
802
+ if (m.id !== msgId)
803
+ return m;
804
+ const existingToolCalls = m.toolCalls || [];
805
+ const updatedToolCalls = existingToolCalls.map((tc) => {
806
+ if (!ids.includes(tc.toolCallId))
807
+ return tc;
808
+ const fn = tc.functionName || "";
809
+ return {
810
+ ...tc,
811
+ functionName: fn.includes("(pending approval)")
812
+ ? fn
813
+ : fn + " (pending approval)",
814
+ };
815
+ });
816
+ return { ...m, toolCalls: updatedToolCalls };
817
+ });
818
+ messagesRef.current = updated;
819
+ return updated;
820
+ });
821
+ }
822
+ // Proactively stop the current stream so that the page can be reloaded safely or stay idle until approval
823
+ try {
824
+ abortControllerRef.current?.abort();
825
+ abortControllerRef.current = null;
826
+ setIsConnecting(false);
827
+ setIsWaitingForResponse(false);
828
+ }
829
+ catch { }
830
+ break;
831
+ }
657
832
  if (kind === "contextWindow") {
658
833
  const data = message.data || {};
659
834
  // Store last context window status in a ref so we can render it below
@@ -675,8 +850,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
675
850
  // Merge incoming context into local metadata
676
851
  setAgentMetadata((prev) => {
677
852
  const current = (prev || {});
853
+ // Exclude top-level context to avoid duplicate keys when spreading
854
+ const { context: _, ...currentWithoutContext } = current;
678
855
  const next = {
679
- ...current,
856
+ ...currentWithoutContext,
680
857
  additionalData: {
681
858
  ...(current.additionalData || {}),
682
859
  context: nextContext,
@@ -717,6 +894,55 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
717
894
  }
718
895
  });
719
896
  }
897
+ else if (kind === "toolApprovalGranted" ||
898
+ kind === "toolApprovalRejected") {
899
+ const data = message.data || {};
900
+ const toolCallId = data.toolCallId;
901
+ const msgId = data.messageId;
902
+ console.log("🔧 Processing tool approval:", {
903
+ kind,
904
+ toolCallId,
905
+ msgId,
906
+ data,
907
+ });
908
+ if (toolCallId && msgId) {
909
+ 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
+ const updated = prev.map((m) => {
918
+ if (m.id !== msgId)
919
+ return m;
920
+ const existingToolCalls = m.toolCalls || [];
921
+ const updatedToolCalls = existingToolCalls.map((tc) => {
922
+ if (tc.toolCallId !== toolCallId)
923
+ return tc;
924
+ const suffix = kind === "toolApprovalGranted"
925
+ ? " (approved)"
926
+ : " (rejected)";
927
+ const newFunctionName = (tc.functionName || "") + suffix;
928
+ console.log("🏷️ Updating function name:", {
929
+ toolCallId,
930
+ oldName: tc.functionName,
931
+ newName: newFunctionName,
932
+ });
933
+ return {
934
+ ...tc,
935
+ functionName: newFunctionName,
936
+ };
937
+ });
938
+ return { ...m, toolCalls: updatedToolCalls };
939
+ });
940
+ messagesRef.current = updated;
941
+ return updated;
942
+ });
943
+ }
944
+ break;
945
+ }
720
946
  }
721
947
  catch { }
722
948
  break;
@@ -875,16 +1101,93 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
875
1101
  }
876
1102
  }
877
1103
  finally {
1104
+ console.log("🔌 Stream connection finished, cleaning up");
878
1105
  setIsConnecting(false);
879
1106
  // Guard: clear waiting state if connection finished without content
880
1107
  setIsWaitingForResponse(false);
881
1108
  }
882
1109
  }, [agent?.id, handleContentChunk, handleToolCall, handleToolResult]);
1110
+ // Attempt to reconnect stream when all pending approvals are resolved
1111
+ const attemptReconnectIfNoPending = useCallback(async () => {
1112
+ try {
1113
+ const currentAgent = agent;
1114
+ if (!currentAgent)
1115
+ return;
1116
+ // Check if we're already connected
1117
+ if (abortControllerRef.current) {
1118
+ console.log("🔄 Already connected to stream, skipping reconnect");
1119
+ return;
1120
+ }
1121
+ const msgs = messagesRef.current || [];
1122
+ const hasPending = msgs.some((m) => (m.toolCalls || []).some((tc) => (tc.functionName || "").includes("(pending approval)")));
1123
+ if (!hasPending) {
1124
+ console.log("🔄 No pending approvals; reconnecting stream");
1125
+ await connectToStream(currentAgent);
1126
+ }
1127
+ else {
1128
+ console.log("⏸️ Still have pending approvals, not reconnecting yet");
1129
+ }
1130
+ }
1131
+ catch (err) {
1132
+ console.error("❌ Error attempting reconnect:", err);
1133
+ }
1134
+ }, [agent, connectToStream]);
1135
+ // Listen for local approval resolution (when stream is paused) to update UI and reconnect
1136
+ useEffect(() => {
1137
+ const onApprovalResolved = (ev) => {
1138
+ try {
1139
+ const detail = ev?.detail || {};
1140
+ const messageId = detail.messageId;
1141
+ const toolCallId = detail.toolCallId;
1142
+ const approved = !!detail.approved;
1143
+ if (!messageId || !toolCallId)
1144
+ return;
1145
+ console.log("🔔 Approval resolved:", {
1146
+ messageId,
1147
+ toolCallId,
1148
+ approved,
1149
+ });
1150
+ setMessages((prev) => {
1151
+ const updated = prev.map((m) => {
1152
+ if (m.id !== messageId)
1153
+ return m;
1154
+ const updatedToolCalls = (m.toolCalls || []).map((tc) => {
1155
+ if (tc.toolCallId !== toolCallId)
1156
+ return tc;
1157
+ const base = (tc.functionName || "")
1158
+ .replace(" (pending approval)", "")
1159
+ .replace(" (approved)", "")
1160
+ .replace(" (rejected)", "");
1161
+ return {
1162
+ ...tc,
1163
+ functionName: base + (approved ? " (approved)" : " (rejected)"),
1164
+ };
1165
+ });
1166
+ return { ...m, toolCalls: updatedToolCalls };
1167
+ });
1168
+ messagesRef.current = updated;
1169
+ return updated;
1170
+ });
1171
+ // Try to reconnect if no more pending approvals remain
1172
+ setTimeout(() => {
1173
+ attemptReconnectIfNoPending();
1174
+ }, 100);
1175
+ }
1176
+ catch (err) {
1177
+ console.error("❌ Error handling approval resolution:", err);
1178
+ }
1179
+ };
1180
+ window.addEventListener("agent:toolApprovalResolved", onApprovalResolved);
1181
+ return () => window.removeEventListener("agent:toolApprovalResolved", onApprovalResolved);
1182
+ }, [attemptReconnectIfNoPending]);
883
1183
  // Load agent data and messages
884
1184
  const loadAgent = useCallback(async () => {
885
1185
  try {
886
1186
  if (agentStub.status === "new") {
887
- console.log("✅ Setting up new agent");
1187
+ console.log("✅ Setting up new agent", agentStub.id);
1188
+ // Set agent ID immediately for new agents
1189
+ window.currentAgentId = agentStub.id;
1190
+ console.log("🔗 Setting currentAgentId for new agent:", agentStub.id);
888
1191
  // Derive initial profile from provided metadata if present
889
1192
  const initialProfileIdFromMeta = (() => {
890
1193
  try {
@@ -1064,12 +1367,21 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1064
1367
  const agentData = await getAgent(agentStub.id);
1065
1368
  setAgent(agentData);
1066
1369
  setMessages(agentData.messages || []);
1370
+ // Set agent ID for existing agents too
1371
+ window.currentAgentId = agentData.id;
1372
+ console.log("🔗 Setting currentAgentId for existing agent:", agentData.id);
1067
1373
  // Parse metadata from DB if present (do not seed for existing agents)
1068
1374
  const parsedMeta = (() => {
1069
1375
  try {
1070
- return agentData.metadata
1071
- ? JSON.parse(agentData.metadata)
1072
- : null;
1376
+ if (!agentData.metadata)
1377
+ return null;
1378
+ const meta = JSON.parse(agentData.metadata);
1379
+ // Clean up: remove top-level context if present (should only be in additionalData)
1380
+ if (meta && meta.context) {
1381
+ const { context: _, ...cleanMeta } = meta;
1382
+ return cleanMeta;
1383
+ }
1384
+ return meta;
1073
1385
  }
1074
1386
  catch {
1075
1387
  return null;
@@ -1094,6 +1406,16 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1094
1406
  }
1095
1407
  // Reset streaming state for reconnection
1096
1408
  shouldCreateNewMessage.current = false;
1409
+ // If there are pending approvals in current messages, skip reconnect for now
1410
+ try {
1411
+ const hasPending = (agentData.messages || []).some((m) => (m.toolCalls || []).some((tc) => typeof tc?.functionName === "string" &&
1412
+ tc.functionName.includes("(pending approval)")));
1413
+ if (hasPending) {
1414
+ console.log("⏸️ loadAgent: Pending approvals detected, delaying stream reconnect");
1415
+ return;
1416
+ }
1417
+ }
1418
+ catch { }
1097
1419
  // Use the existing connectToStream function with the loaded agent data
1098
1420
  await connectToStream(agentData);
1099
1421
  }, 100);
@@ -1230,12 +1552,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1230
1552
  scrollToBottom();
1231
1553
  }
1232
1554
  }, [messages, scrollToBottom, shouldAutoScroll]);
1233
- // Re-apply bottom alignment when loading dots appear/disappear, as it changes the content height
1234
- useEffect(() => {
1235
- if (shouldAutoScroll) {
1236
- scrollToBottom();
1237
- }
1238
- }, [showDots, shouldAutoScroll, scrollToBottom]);
1239
1555
  // Persist any pending settings (mode/model) once an agent exists server-side
1240
1556
  const persistPendingSettingsIfNeeded = useCallback(async () => {
1241
1557
  try {
@@ -1521,8 +1837,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1521
1837
  if (!agent?.id)
1522
1838
  return;
1523
1839
  const current = agentMetadata || {};
1840
+ // Exclude top-level context to avoid duplicate keys when spreading
1841
+ const { context: _, ...currentWithoutContext } = current;
1524
1842
  const next = {
1525
- ...current,
1843
+ ...currentWithoutContext,
1526
1844
  additionalData: {
1527
1845
  ...(current.additionalData || {}),
1528
1846
  context: {
@@ -1589,8 +1907,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1589
1907
  if (existingPageIds.has(`${pageToAdd.id}-${pageToAdd.language}-${pageToAdd.version}`)) {
1590
1908
  return; // Page already exists
1591
1909
  }
1910
+ // Exclude top-level context to avoid duplicate keys when spreading
1911
+ const { context: _, ...currentWithoutContext } = current;
1592
1912
  const next = {
1593
- ...current,
1913
+ ...currentWithoutContext,
1594
1914
  additionalData: {
1595
1915
  ...(current.additionalData || {}),
1596
1916
  context: {
@@ -1625,8 +1945,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1625
1945
  const newComponentIds = editContext.selection.filter((id) => !existingIds.has(id));
1626
1946
  if (newComponentIds.length === 0)
1627
1947
  return; // No new components to add
1948
+ // Exclude top-level context to avoid duplicate keys when spreading
1949
+ const { context: _, ...currentWithoutContext } = current;
1628
1950
  const next = {
1629
- ...current,
1951
+ ...currentWithoutContext,
1630
1952
  additionalData: {
1631
1953
  ...(current.additionalData || {}),
1632
1954
  context: {
@@ -1661,8 +1983,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1661
1983
  const newComponentIds = ids.filter((id) => !!id && !existingIds.has(id));
1662
1984
  if (newComponentIds.length === 0)
1663
1985
  return;
1986
+ // Exclude top-level context to avoid duplicate keys when spreading
1987
+ const { context: _, ...currentWithoutContext } = current;
1664
1988
  const next = {
1665
- ...current,
1989
+ ...currentWithoutContext,
1666
1990
  additionalData: {
1667
1991
  ...(current.additionalData || {}),
1668
1992
  context: {
@@ -1702,8 +2026,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1702
2026
  .filter((p) => !existingPageIds.has(`${p.id}-${p.language}-${p.version}`));
1703
2027
  if (pagesToAdd.length === 0)
1704
2028
  return;
2029
+ // Exclude top-level context to avoid duplicate keys when spreading
2030
+ const { context: _, ...currentWithoutContext } = current;
1705
2031
  const next = {
1706
- ...current,
2032
+ ...currentWithoutContext,
1707
2033
  additionalData: {
1708
2034
  ...(current.additionalData || {}),
1709
2035
  context: {
@@ -1802,8 +2128,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
1802
2128
  return undefined;
1803
2129
  })();
1804
2130
  const current = agentMetadata || {};
2131
+ // Exclude top-level context to avoid duplicate keys when spreading
2132
+ const { context: _, ...currentWithoutContext } = current;
1805
2133
  const next = {
1806
- ...current,
2134
+ ...currentWithoutContext,
1807
2135
  additionalData: {
1808
2136
  ...(current.additionalData || {}),
1809
2137
  context: {
@@ -2038,7 +2366,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, }) {
2038
2366
  sendQuickMessage(text);
2039
2367
  } }, groupIndex));
2040
2368
  }
2041
- }) }), showDots && _jsx(DancingDots, {}), _jsx("div", { ref: messagesEndRef })] }), renderContextInfoBar(), _jsxs("div", { className: "border-t border-gray-200 p-4", children: [_jsx("div", { className: "flex items-stretch gap-2", children: _jsx(Textarea, { ref: textareaRef, value: prompt, onChange: (e) => {
2369
+ }) }), _jsx("div", { className: showDots ? "visible" : "invisible", children: _jsx(DancingDots, {}) }), _jsx("div", { ref: messagesEndRef })] }), renderContextInfoBar(), _jsx(TodoListPanel, { messages: messages }), _jsxs("div", { className: "border-t border-gray-200 p-4", children: [_jsx("div", { className: "flex items-stretch gap-2", children: _jsx(Textarea, { ref: textareaRef, value: prompt, onChange: (e) => {
2042
2370
  setPrompt(e.target.value);
2043
2371
  // Reset history index when user starts typing
2044
2372
  if (currentHistoryIndex !== -1) {