@parhelia/core 0.1.11141 → 0.1.11147
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/components/ui/PlaceholderInput.d.ts +4 -5
- package/dist/components/ui/PlaceholderInput.js +5 -6
- package/dist/components/ui/PlaceholderInput.js.map +1 -1
- package/dist/components/ui/command.js +1 -1
- package/dist/editor/ContentTree.js +5 -0
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/ai/AgentCostDisplay.js +1 -1
- package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
- package/dist/editor/ai/AgentDocumentList.js +9 -1
- package/dist/editor/ai/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.js +45 -25
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/ContextInfoBar.js +24 -1
- package/dist/editor/ai/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/EditOperationsPanel.js +1 -1
- package/dist/editor/client/EditorShell.js +17 -3
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +8 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +10 -0
- package/package.json +1 -1
|
@@ -45,7 +45,7 @@ const UserMessage = ({ message }) => {
|
|
|
45
45
|
message.sourceAgent?.name;
|
|
46
46
|
}
|
|
47
47
|
const displayName = sourceAgentName ? `[From ${sourceAgentName}]` : "You";
|
|
48
|
-
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-
|
|
48
|
+
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-[11px] font-medium text-gray-900", children: displayName }), message.createdDate && (_jsx("span", { className: "text-[11px] text-gray-400", "data-testid": "user-message-timestamp", "data-timestamp": message.createdDate, children: formatTime(new Date(message.createdDate)) }))] }), _jsx("div", { className: "prose prose max-w-none text-[11px] text-gray-700 select-text", children: displayContent })] })] }));
|
|
49
49
|
};
|
|
50
50
|
// Helper to extract todos from potentially incomplete JSON during streaming
|
|
51
51
|
const extractPartialTodos = (jsonText) => {
|
|
@@ -378,9 +378,9 @@ const TodoListPanel = ({ messages, agentMetadata, }) => {
|
|
|
378
378
|
return null;
|
|
379
379
|
const completedCount = todos.filter((t) => t.done).length;
|
|
380
380
|
const totalCount = todos.length;
|
|
381
|
-
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-
|
|
381
|
+
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-[11px] font-medium text-gray-700", children: "Todo List" }), isUpdating ? (_jsxs("span", { className: "flex items-center gap-1 text-[11px] text-blue-600", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), "Updating..."] })) : (_jsxs("span", { className: "text-[11px] 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 && (_jsxs("div", { className: "max-h-64 overflow-y-auto px-4 pb-3", children: [todos.length > 0 && (_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-[11px]", 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
|
|
382
382
|
? "text-gray-500 line-through"
|
|
383
|
-
: "text-gray-900"}`, children: todo.text }), todo.note && (_jsx("div", { className: "mt-0.5 text-
|
|
383
|
+
: "text-gray-900"}`, children: todo.text }), todo.note && (_jsx("div", { className: "mt-0.5 text-[11px] text-gray-500", children: todo.note }))] })] }, todo.id || `${todo.messageId}-${idx}`))) })), isUpdating && (_jsxs("div", { className: `flex items-center gap-2 rounded px-3 py-2 text-[11px] ${todos.length > 0
|
|
384
384
|
? "mt-2 bg-blue-50 text-blue-700"
|
|
385
385
|
: "justify-center bg-white text-gray-500"}`, children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), _jsx("span", { children: todos.length > 0
|
|
386
386
|
? "Updating todo list..."
|
|
@@ -683,6 +683,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
683
683
|
const messagesEndRef = useRef(null);
|
|
684
684
|
const textareaRef = useRef(null);
|
|
685
685
|
const placeholderInputRef = useRef(null);
|
|
686
|
+
const promptPlaceholderInputRef = useRef(null);
|
|
686
687
|
const messagesContainerRef = useRef(null);
|
|
687
688
|
const [shouldAutoScroll, setShouldAutoScroll] = useState(true);
|
|
688
689
|
// WebSocket subscription state for agent streaming
|
|
@@ -1248,7 +1249,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1248
1249
|
toolCallId,
|
|
1249
1250
|
approved,
|
|
1250
1251
|
});
|
|
1251
|
-
console.log("[AgentTerminal] Current message IDs:", messagesRef.current.map((m) => m.id));
|
|
1252
1252
|
if (!messageId || !toolCallId)
|
|
1253
1253
|
return;
|
|
1254
1254
|
// Update local state to reflect approval status
|
|
@@ -2304,6 +2304,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
2304
2304
|
console.warn("[AgentTerminal] handleSubmit blocked: already submitting");
|
|
2305
2305
|
return;
|
|
2306
2306
|
}
|
|
2307
|
+
// Block submission while there is a pending tool call approval decision
|
|
2308
|
+
if (hasPendingApprovals()) {
|
|
2309
|
+
console.warn("[AgentTerminal] handleSubmit blocked: pending tool call approval");
|
|
2310
|
+
return;
|
|
2311
|
+
}
|
|
2307
2312
|
if (!editContext) {
|
|
2308
2313
|
console.error("[AgentTerminal] handleSubmit blocked: editContext is undefined");
|
|
2309
2314
|
setError("Editor context not available. Please refresh the page.");
|
|
@@ -2314,6 +2319,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
2314
2319
|
placeholderInputRef.current?.submit();
|
|
2315
2320
|
return;
|
|
2316
2321
|
}
|
|
2322
|
+
// If prompt contains placeholders, delegate to the prompt placeholder input's submit method
|
|
2323
|
+
if (prompt && /\{\{[^{}]+\}\}|<<[^<>]+>>/.test(prompt) && allPlaceholdersFilled) {
|
|
2324
|
+
promptPlaceholderInputRef.current?.submit();
|
|
2325
|
+
return;
|
|
2326
|
+
}
|
|
2317
2327
|
// Save the prompt text before any state changes
|
|
2318
2328
|
const savedPrompt = prompt.trim();
|
|
2319
2329
|
// Check if agent is new - allow empty prompts for new agents to trigger greeting
|
|
@@ -2534,6 +2544,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
2534
2544
|
console.warn("[AgentTerminal] sendQuickMessage blocked: already submitting");
|
|
2535
2545
|
return;
|
|
2536
2546
|
}
|
|
2547
|
+
// Block submission while there is a pending tool call approval decision
|
|
2548
|
+
if (hasPendingApprovals()) {
|
|
2549
|
+
console.warn("[AgentTerminal] sendQuickMessage blocked: pending tool call approval");
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2537
2552
|
if (!editContext) {
|
|
2538
2553
|
console.error("[AgentTerminal] sendQuickMessage blocked: editContext is undefined");
|
|
2539
2554
|
setError("Editor context not available. Please refresh the page.");
|
|
@@ -3000,14 +3015,14 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3000
3015
|
}
|
|
3001
3016
|
}, [activeProfile, profiles, agent?.profileId]);
|
|
3002
3017
|
if (isLoading) {
|
|
3003
|
-
return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-
|
|
3018
|
+
return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-[11px] text-gray-500", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", strokeWidth: 1 }), "Loading agent..."] }) }));
|
|
3004
3019
|
}
|
|
3005
3020
|
const renderContextInfoBar = () => (_jsx(ContextInfoBar, { agent: agent, agentMetadata: agentMetadata, setAgentMetadata: setAgentMetadata, setAgent: setAgent, resolvedPageName: resolvedPageName, resolvedComponentName: resolvedComponentName, resolvedFieldName: resolvedFieldName, isLiveEditorContextMode: isLiveEditorContextMode, activeProfile: activeProfile }));
|
|
3006
3021
|
const renderCostLimitBanner = () => {
|
|
3007
3022
|
if (!costLimitExceeded)
|
|
3008
3023
|
return null;
|
|
3009
3024
|
const { totalCost, costLimit, initialCostLimit } = costLimitExceeded;
|
|
3010
|
-
return (_jsxs("div", { className: "m-3 rounded border border-amber-300 bg-amber-50 p-3 text-
|
|
3025
|
+
return (_jsxs("div", { className: "m-3 rounded border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-amber-500", strokeWidth: 1 }), _jsxs("span", { children: ["Cost limit exceeded. Spent $", totalCost.toFixed(2), " / $", costLimit.toFixed(2), "."] })] }), _jsx("div", { className: "flex gap-2", children: _jsx("button", { className: "rounded border border-amber-300 bg-white px-2 py-1 hover:bg-amber-100", onClick: async () => {
|
|
3011
3026
|
if (!agent?.id)
|
|
3012
3027
|
return;
|
|
3013
3028
|
try {
|
|
@@ -3039,13 +3054,13 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3039
3054
|
const errorMessage = currentAgent?.statusMessage;
|
|
3040
3055
|
if (!isErrorStatus || !errorMessage)
|
|
3041
3056
|
return null;
|
|
3042
|
-
return (_jsx("div", { className: "m-3 rounded border border-red-300 bg-red-50 p-3 text-
|
|
3057
|
+
return (_jsx("div", { className: "m-3 rounded border border-red-300 bg-red-50 p-3 text-[11px] text-red-900", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertCircle, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-red-500", strokeWidth: 1 }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "mb-1 font-semibold", children: "Agent Error" }), _jsx("div", { className: "text-red-800", children: errorMessage })] })] }) }));
|
|
3043
3058
|
};
|
|
3044
|
-
return (_jsxs("div", { className: `flex h-full flex-col ${className || ""}`, children: [_jsxs("div", { ref: messagesContainerRef, className: "flex-1 overflow-y-auto", onScroll: handleScroll, children: [error && (_jsx("div", { className: "m-4 rounded-lg border-l-4 border-red-500 bg-red-50 p-3 select-text", children: _jsxs("div", { className: "flex items-start", children: [_jsx(AlertCircle, { className: "mt-0.5 h-5 w-5 text-red-400", strokeWidth: 1 }), _jsxs("div", { className: "ml-3", children: [_jsx("p", { className: "text-
|
|
3059
|
+
return (_jsxs("div", { className: `flex h-full flex-col ${className || ""}`, children: [_jsxs("div", { ref: messagesContainerRef, className: "flex-1 overflow-y-auto", onScroll: handleScroll, children: [error && (_jsx("div", { className: "m-4 rounded-lg border-l-4 border-red-500 bg-red-50 p-3 select-text", children: _jsxs("div", { className: "flex items-start", children: [_jsx(AlertCircle, { className: "mt-0.5 h-5 w-5 text-red-400", strokeWidth: 1 }), _jsxs("div", { className: "ml-3", children: [_jsx("p", { className: "text-[11px] font-medium text-red-800", children: "Error" }), _jsx("p", { className: "mt-1 text-[11px] text-red-700", children: error })] })] }) })), messages.length === 0 && !error && !hideGreeting && (_jsx("div", { className: "flex h-full items-center justify-center p-8", children: _jsx("div", { className: "max-w-prose text-center", children: !activeProfile ? (_jsx(Loader2, { className: "mx-auto h-8 w-8 animate-spin text-gray-400" })) : (_jsxs(_Fragment, { children: [activeProfile.svgIcon ? (_jsx("div", { className: "mx-auto mb-4 flex h-24 w-24 items-center justify-center text-gray-400 [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
|
|
3045
3060
|
__html: activeProfile.svgIcon,
|
|
3046
|
-
} })) : (_jsx(SecretAgentIcon, { size: 96, strokeWidth: 1, className: "mx-auto mb-4 text-gray-400" })), activeProfile.greetingMessage ? (_jsx(ViewTransition, { children: _jsx("div", { className: "prose prose
|
|
3061
|
+
} })) : (_jsx(SecretAgentIcon, { size: 96, strokeWidth: 1, className: "mx-auto mb-4 text-gray-400" })), activeProfile.greetingMessage ? (_jsx(ViewTransition, { children: _jsx("div", { className: "prose prose mx-auto text-center text-[20px]", dangerouslySetInnerHTML: {
|
|
3047
3062
|
__html: activeProfile.greetingMessage,
|
|
3048
|
-
} }) })) : (_jsxs(_Fragment, { children: [_jsx("h3", { className: "mb-2 text-
|
|
3063
|
+
} }) })) : (_jsxs(_Fragment, { children: [_jsx("h3", { className: "mb-2 text-[11px] font-medium text-gray-900", children: "Start a conversation" }), _jsx("p", { className: "mb-4 text-[11px] text-gray-500", children: "Send a message to begin working with your AI agent." }), _jsx("div", { className: "text-[11px] text-gray-400", children: "Your agent can help with content editing, research, and automation tasks." })] }))] })) }) })), messages.length === 0 &&
|
|
3049
3064
|
!error &&
|
|
3050
3065
|
hideGreeting &&
|
|
3051
3066
|
(isSubmitting || isConnecting) && (_jsx("div", { className: "flex h-full items-center justify-center p-8", children: _jsxs("div", { className: "flex flex-col items-center gap-4", children: [activeProfile?.svgIcon ? (_jsx("div", { className: "flex h-16 w-16 items-center justify-center text-gray-400 [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
|
|
@@ -3125,7 +3140,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3125
3140
|
}
|
|
3126
3141
|
// Content exists - show dots WITHOUT icon (inline at bottom)
|
|
3127
3142
|
return (_jsxs("div", { className: "flex gap-3 px-4 pb-4", children: [_jsx("div", { className: "w-7 flex-shrink-0" }), _jsx("div", { className: "min-w-0 flex-1", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400" })] }) })] }));
|
|
3128
|
-
})(), renderCostLimitBanner(), _jsx("div", { ref: messagesEndRef })] }), !hideContext && renderContextInfoBar(), !hideContext && agent?.id && activeProfile && (_jsx(AgentDocumentList, { agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)), !hideContext && (_jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata })), !hideContext && agent?.id && (_jsx(AgentEditOperationsPanel, { agentId: agent.id })), queuedPrompts.length > 0 && (_jsx("div", { className: "border-t border-gray-200 bg-amber-50/50", children: _jsxs("div", { className: "px-4 pt-3 pb-2", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx("div", { className: "h-2 w-2 animate-pulse rounded-full bg-amber-500" }), _jsxs("span", { className: "text-
|
|
3143
|
+
})(), renderCostLimitBanner(), _jsx("div", { ref: messagesEndRef })] }), !hideContext && renderContextInfoBar(), !hideContext && agent?.id && activeProfile && (_jsx(AgentDocumentList, { agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)), !hideContext && (_jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata })), !hideContext && agent?.id && (_jsx(AgentEditOperationsPanel, { agentId: agent.id })), queuedPrompts.length > 0 && (_jsx("div", { className: "border-t border-gray-200 bg-amber-50/50", children: _jsxs("div", { className: "px-4 pt-3 pb-2", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx("div", { className: "h-2 w-2 animate-pulse rounded-full bg-amber-500" }), _jsxs("span", { className: "text-[11px] font-semibold text-amber-900", children: ["Queued Messages (", queuedPrompts.length, ")"] })] }), _jsx("div", { className: "space-y-2", children: queuedPrompts.map((qp) => (_jsx("div", { className: "rounded-md border border-amber-200 bg-white p-2.5 text-[11px]", children: _jsx("div", { className: "flex items-start justify-between gap-2", children: _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "mb-1 flex items-center gap-1.5", children: qp.sourceAgentName ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "font-medium text-gray-700", children: ["From ", qp.sourceAgentName] }), qp.priority > 5 && (_jsx("span", { className: "rounded bg-red-100 px-1.5 py-0.5 text-[11px] font-medium text-red-700", children: "High Priority" }))] })) : (_jsx("span", { className: "font-medium text-gray-700", children: "From User" })) }), _jsx("div", { className: "break-words whitespace-pre-wrap text-gray-600", children: qp.prompt }), qp.createdDate && (_jsx("div", { className: "mt-1.5 text-[11px] text-gray-400", children: formatTime(new Date(qp.createdDate)) }))] }) }) }, qp.id))) })] }) })), _jsxs("div", { className: "border-t border-gray-200 p-4", children: [activePlaceholderInput ? (
|
|
3129
3144
|
// Placeholder Input (from quick actions)
|
|
3130
3145
|
// Show buttons when hideBottomControls is true (e.g., splash screen) since normal submit area is hidden
|
|
3131
3146
|
_jsx(PlaceholderInput, { ref: placeholderInputRef, text: activePlaceholderInput.text, showButtons: hideBottomControls, buttonsClassName: hideBottomControls ? "justify-end" : "", onFilledChange: setAllPlaceholdersFilled, onComplete: (filledText) => {
|
|
@@ -3157,10 +3172,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3157
3172
|
}, onCancel: () => {
|
|
3158
3173
|
setActivePlaceholderInput(null);
|
|
3159
3174
|
setAllPlaceholdersFilled(false);
|
|
3160
|
-
} })) : prompt && /\{
|
|
3175
|
+
} })) : prompt && /\{\{[^{}]+\}\}|<<[^<>]+>>/.test(prompt) ? (
|
|
3161
3176
|
// Template mode: show PlaceholderInput when prompt contains placeholders
|
|
3162
3177
|
// Show buttons when hideBottomControls is true (e.g., splash screen) since normal submit area is hidden
|
|
3163
|
-
_jsx(PlaceholderInput, { text: prompt, showButtons: hideBottomControls, buttonsClassName: hideBottomControls ? "justify-end" : "", onFilledChange: setAllPlaceholdersFilled, onComplete: (filledText) => {
|
|
3178
|
+
_jsx(PlaceholderInput, { ref: promptPlaceholderInputRef, text: prompt, showButtons: hideBottomControls, buttonsClassName: hideBottomControls ? "justify-end" : "", onFilledChange: setAllPlaceholdersFilled, onComplete: (filledText) => {
|
|
3164
3179
|
setPrompt(filledText);
|
|
3165
3180
|
setAllPlaceholdersFilled(false);
|
|
3166
3181
|
// Auto-submit after filling placeholders
|
|
@@ -3180,7 +3195,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3180
3195
|
} })) : (_jsx("div", { className: "flex items-stretch gap-2", children: _jsx(Textarea, { ref: textareaRef, value: prompt, onChange: (e) => {
|
|
3181
3196
|
setPrompt(e.target.value);
|
|
3182
3197
|
// Reset placeholder filled state when prompt changes
|
|
3183
|
-
if (!/\{
|
|
3198
|
+
if (!/\{\{[^{}]+\}\}|<<[^<>]+>>/.test(e.target.value)) {
|
|
3184
3199
|
setAllPlaceholdersFilled(false);
|
|
3185
3200
|
}
|
|
3186
3201
|
// Reset history index when user starts typing
|
|
@@ -3191,7 +3206,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3191
3206
|
shouldMaintainFocusRef.current = true;
|
|
3192
3207
|
}, onBlur: () => {
|
|
3193
3208
|
shouldMaintainFocusRef.current = false;
|
|
3194
|
-
}, placeholder: inputPlaceholder, className: "h-[80px] flex-1 resize-none overflow-y-auto text-
|
|
3209
|
+
}, placeholder: inputPlaceholder, className: "h-[80px] flex-1 resize-none overflow-y-auto text-[11px]", "data-testid": "agent-terminal-prompt", disabled: isSubmitting }) })), !hideBottomControls && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-stretch justify-between gap-2", children: [_jsxs("div", { className: "mt-2 flex flex-wrap items-center justify-start gap-2", children: [_jsxs(Tooltip, { delayDuration: 400, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("select", { className: `h-5 rounded border px-1.5 text-[11px] ${mode === "read-only"
|
|
3195
3210
|
? "border-green-300 bg-green-50 text-green-700"
|
|
3196
3211
|
: mode === "supervised"
|
|
3197
3212
|
? "border-amber-300 bg-amber-50 text-amber-700"
|
|
@@ -3225,7 +3240,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3225
3240
|
catch (e2) {
|
|
3226
3241
|
console.error("Failed to persist mode change", e2);
|
|
3227
3242
|
}
|
|
3228
|
-
}, title: "Mode", "aria-label": "Mode", "data-testid": "agent-mode-select", children: [_jsx("option", { value: "supervised", children: "Supervised" }), _jsx("option", { value: "autonomous", children: "Autonomous" }), _jsx("option", { value: "read-only", children: "Read-Only" })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: _jsxs("div", { className: "max-w-[320px] space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold text-green-500", children: "Read-Only" }), ": Limited tool access as configured by the profile (Ask Mode Tools)."] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold text-amber-500", children: "Supervised" }), ": Full tool access, but writes are limited to pages/items in the current context. Creating new items or updating existing items outside the current context requires explicit approval."] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold text-red-500", children: "Autonomous" }), ": Full tool access; can write across the site/project only limited by user permissions."] })] }) })] }), profiles?.length > 0 && (_jsx("select", { className: "h-5 rounded border px-1.5 text-[
|
|
3243
|
+
}, title: "Mode", "aria-label": "Mode", "data-testid": "agent-mode-select", children: [_jsx("option", { value: "supervised", children: "Supervised" }), _jsx("option", { value: "autonomous", children: "Autonomous" }), _jsx("option", { value: "read-only", children: "Read-Only" })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: _jsxs("div", { className: "max-w-[320px] space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold text-green-500", children: "Read-Only" }), ": Limited tool access as configured by the profile (Ask Mode Tools)."] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold text-amber-500", children: "Supervised" }), ": Full tool access, but writes are limited to pages/items in the current context. Creating new items or updating existing items outside the current context requires explicit approval."] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold text-red-500", children: "Autonomous" }), ": Full tool access; can write across the site/project only limited by user permissions."] })] }) })] }), profiles?.length > 0 && (_jsx("select", { className: "h-5 rounded border px-1.5 text-[11px] text-gray-500", value: activeProfile?.id || "", onChange: async (e) => {
|
|
3229
3244
|
const nextProfile = profiles.find((x) => x.id === e.target.value);
|
|
3230
3245
|
if (!nextProfile)
|
|
3231
3246
|
return;
|
|
@@ -3274,7 +3289,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3274
3289
|
catch (err) {
|
|
3275
3290
|
console.error("Failed to persist agent profile", err);
|
|
3276
3291
|
}
|
|
3277
|
-
}, title: "Profile", "aria-label": "Profile", "data-testid": "agent-profile-select", children: profiles.map((p) => (_jsx("option", { value: p.id, children: p.name }, p.id))) })), activeProfile?.models?.length ? (_jsx("select", { className: "h-5 rounded border px-1.5 text-[
|
|
3292
|
+
}, title: "Profile", "aria-label": "Profile", "data-testid": "agent-profile-select", children: profiles.map((p) => (_jsx("option", { value: p.id, children: p.name }, p.id))) })), activeProfile?.models?.length ? (_jsx("select", { className: "h-5 rounded border px-1.5 text-[11px] text-gray-500", value: selectedModelId || "", onChange: async (e) => {
|
|
3278
3293
|
const nextId = e.target.value;
|
|
3279
3294
|
setSelectedModelId(nextId);
|
|
3280
3295
|
const modelName = activeProfile?.models?.find((m) => m.id === nextId)
|
|
@@ -3298,17 +3313,22 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3298
3313
|
catch (err) {
|
|
3299
3314
|
console.error("Failed to persist agent model", err);
|
|
3300
3315
|
}
|
|
3301
|
-
}, title: "Model", "aria-label": "Model", "data-testid": "agent-model-select", children: activeProfile.models.map((m) => (_jsx("option", { value: m.id, children: m.name }, m.id))) })) : null, activeProfile?.prompts?.length ? (_jsxs(Popover, { open: showPredefined, onOpenChange: setShowPredefined, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "rounded p-1 hover:bg-gray-100", onClick: () => { }, title: "Predefined prompts", "aria-label": "Predefined prompts", children: _jsx(Wand2, { className: "h-3 w-3", strokeWidth: 1 }) }) }), _jsx(PopoverContent, { className: "w-64 p-0", align: "start", children: _jsx("div", { className: "max-h-56 overflow-y-auto p-2", children: activeProfile.prompts.map((p, index) => (_jsx("div", { className: "cursor-pointer rounded p-1.5 text-
|
|
3316
|
+
}, title: "Model", "aria-label": "Model", "data-testid": "agent-model-select", children: activeProfile.models.map((m) => (_jsx("option", { value: m.id, children: m.name }, m.id))) })) : null, activeProfile?.prompts?.length ? (_jsxs(Popover, { open: showPredefined, onOpenChange: setShowPredefined, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "rounded p-1 hover:bg-gray-100", onClick: () => { }, title: "Predefined prompts", "aria-label": "Predefined prompts", children: _jsx(Wand2, { className: "h-3 w-3", strokeWidth: 1 }) }) }), _jsx(PopoverContent, { className: "w-64 p-0", align: "start", children: _jsx("div", { className: "max-h-56 overflow-y-auto p-2", children: activeProfile.prompts.map((p, index) => (_jsx("div", { className: "cursor-pointer rounded p-1.5 text-[11px] text-gray-700 hover:bg-gray-100", onClick: () => {
|
|
3302
3317
|
setPrompt(p.prompt);
|
|
3303
3318
|
setShowPredefined(false);
|
|
3304
3319
|
if (textareaRef.current)
|
|
3305
3320
|
textareaRef.current.focus();
|
|
3306
3321
|
}, 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 &&
|
|
3307
|
-
(
|
|
3322
|
+
(allPendingApprovals.length > 0 ||
|
|
3323
|
+
(!prompt.trim() && !activePlaceholderInput) ||
|
|
3308
3324
|
(!!prompt &&
|
|
3309
|
-
/\{
|
|
3325
|
+
/\{\{[^{}]+\}\}|<<[^<>]+>>/.test(prompt) &&
|
|
3310
3326
|
!allPlaceholdersFilled) ||
|
|
3311
|
-
(!!activePlaceholderInput && !allPlaceholdersFilled)), size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isExecuting
|
|
3327
|
+
(!!activePlaceholderInput && !allPlaceholdersFilled)), size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isExecuting
|
|
3328
|
+
? "Stop"
|
|
3329
|
+
: allPendingApprovals.length > 0
|
|
3330
|
+
? "Approve or reject pending tool calls first"
|
|
3331
|
+
: "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-[11px] text-gray-500", children: [agent?.id &&
|
|
3312
3332
|
(() => {
|
|
3313
3333
|
const hasData = contextWindowStatus &&
|
|
3314
3334
|
contextWindowStatus.contextWindowTokens;
|
|
@@ -3338,11 +3358,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3338
3358
|
}
|
|
3339
3359
|
return tokens.toString();
|
|
3340
3360
|
};
|
|
3341
|
-
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("div", { className: "flex cursor-help items-center", children: _jsxs("svg", { className: "h-3 w-3", viewBox: "0 0 36 36", "aria-hidden": "true", children: [_jsx("circle", { cx: "18", cy: "18", r: radius, fill: "none", stroke: "#e5e7eb", strokeWidth: "4" }), hasData && (_jsx("circle", { cx: "18", cy: "18", r: radius, fill: "none", stroke: contextColor, strokeWidth: "4", strokeDasharray: `${percentValue} 100`, strokeLinecap: "round", style: {
|
|
3361
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("div", { className: "flex cursor-help items-center justify-center", children: _jsxs("svg", { className: "h-3 w-3 flex-shrink-0", viewBox: "0 0 36 36", "aria-hidden": "true", children: [_jsx("circle", { cx: "18", cy: "18", r: radius, fill: "none", stroke: "#e5e7eb", strokeWidth: "4" }), hasData && (_jsx("circle", { cx: "18", cy: "18", r: radius, fill: "none", stroke: contextColor, strokeWidth: "4", strokeDasharray: `${percentValue} 100`, strokeLinecap: "round", style: {
|
|
3342
3362
|
transformOrigin: "center",
|
|
3343
3363
|
transform: "rotate(-90deg)",
|
|
3344
|
-
} })), !hasData && (_jsx("circle", { cx: "18", cy: "18", r: radius, fill: "none", stroke: contextColor, strokeWidth: "4", strokeDasharray: "0 100", strokeLinecap: "round", opacity: 0.5 }))] }) }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: hasData && contextWindowStatus ? (_jsxs("div", { className: "max-w-[320px] space-y-1 text-
|
|
3345
|
-
})(), agent?.compressionMarkerIndex != null && (_jsxs(Popover, { open: showCompressionPopover, onOpenChange: setShowCompressionPopover, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "cursor-pointer rounded border border-blue-200 bg-blue-50 px-2 py-0.5 text-[
|
|
3364
|
+
} })), !hasData && (_jsx("circle", { cx: "18", cy: "18", r: radius, fill: "none", stroke: contextColor, strokeWidth: "4", strokeDasharray: "0 100", strokeLinecap: "round", opacity: 0.5 }))] }) }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: hasData && contextWindowStatus ? (_jsxs("div", { className: "max-w-[320px] space-y-1 text-[11px]", children: [contextWindowStatus.model && (_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Model:" }), " ", contextWindowStatus.model] })), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Context window:" }), " ", formatTokens(contextWindowStatus.estimatedInputTokens || 0), " ", "/", " ", formatTokens(contextWindowStatus.contextWindowTokens), " ", "tokens"] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Used:" }), " ", pct] })] })) : (_jsx("div", { className: "max-w-[320px] text-[11px]", children: "Context window usage will appear here when the agent starts processing." })) })] }));
|
|
3365
|
+
})(), agent?.compressionMarkerIndex != null && (_jsxs(Popover, { open: showCompressionPopover, onOpenChange: setShowCompressionPopover, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "flex cursor-pointer items-center rounded border border-blue-200 bg-blue-50 px-2 py-0.5 text-[11px] text-blue-700 transition-colors hover:bg-blue-100", onClick: () => setShowCompressionPopover(!showCompressionPopover), children: "Compressed" }) }), _jsx(PopoverContent, { className: "w-96 p-4", align: "start", side: "top", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-[10px] font-semibold text-gray-900", children: "Conversation Compressed" }), _jsxs("p", { className: "mt-1 text-[11px] text-gray-600", children: ["First ", agent.compressionMarkerIndex, " messages have been summarized to reduce context usage."] })] }), agent.compressedSummary && (_jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-[11px] font-medium text-gray-700", children: "Summary:" }), _jsx("div", { className: "max-h-64 overflow-y-auto rounded border border-gray-200 bg-gray-50 p-3 text-[11px] whitespace-pre-wrap text-gray-700", children: agent.compressedSummary })] }))] }) })] })), _jsx(AgentCostDisplay, { totalTokens: liveTotals
|
|
3346
3366
|
? {
|
|
3347
3367
|
input: liveTotals.input,
|
|
3348
3368
|
output: liveTotals.output,
|
|
@@ -3354,7 +3374,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3354
3374
|
cacheWriteCost: liveTotals.cacheWriteCost ?? 0,
|
|
3355
3375
|
totalCost: liveTotals.totalCost,
|
|
3356
3376
|
}
|
|
3357
|
-
: totalTokens, costLimit: effectiveCostLimit }), activeProfile && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "flex items-center gap-1 text-gray-400 hover:text-gray-600", onClick: async () => {
|
|
3377
|
+
: totalTokens, costLimit: effectiveCostLimit }), activeProfile && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "flex items-center gap-1 text-[10px] text-gray-400 hover:text-gray-600", onClick: async () => {
|
|
3358
3378
|
if (!editContext || !activeProfile?.id)
|
|
3359
3379
|
return;
|
|
3360
3380
|
// Load the profile item using editContext
|