@parhelia/core 0.1.12638 → 0.1.12676
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/alert-dialog.js +2 -2
- package/dist/components/ui/alert-dialog.js.map +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/dialog.js +67 -3
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/config/config.js +3 -1
- package/dist/config/config.js.map +1 -1
- package/dist/editor/ItemInfo.js +15 -3
- package/dist/editor/ItemInfo.js.map +1 -1
- package/dist/editor/ai/AgentDocumentList.js +16 -1
- package/dist/editor/ai/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.js +156 -9
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AgentTerminalStatusBar.js +44 -0
- package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.d.ts +2 -0
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/ToolCallDisplay.d.ts +2 -0
- package/dist/editor/ai/ToolCallDisplay.js +14 -8
- package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
- package/dist/editor/ai/agentDiagnostics.d.ts +3 -1
- package/dist/editor/ai/agentDiagnostics.js +20 -0
- package/dist/editor/ai/agentDiagnostics.js.map +1 -1
- package/dist/editor/client/EditorShell.js +24 -0
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +1 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +15 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/operations.d.ts +1 -0
- package/dist/editor/client/operations.js +50 -2
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.js +28 -1
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/client/waitForEditOperationTerminal.d.ts +6 -0
- package/dist/editor/client/waitForEditOperationTerminal.js +54 -0
- package/dist/editor/client/waitForEditOperationTerminal.js.map +1 -1
- package/dist/editor/commands/itemCommands.d.ts +2 -0
- package/dist/editor/commands/itemCommands.js +87 -4
- package/dist/editor/commands/itemCommands.js.map +1 -1
- package/dist/editor/field-types/InternalLinkFieldEditor.js +1 -1
- package/dist/editor/field-types/InternalLinkFieldEditor.js.map +1 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js +10 -10
- package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
- package/dist/editor/media-selector/TreeSelector.js +7 -1
- package/dist/editor/media-selector/TreeSelector.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +35 -0
- package/dist/editor/services/agentService.js +20 -0
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/contentService.d.ts +2 -0
- package/dist/editor/services/contentService.js.map +1 -1
- package/dist/editor/settings/panels/AgentProfileConfigPanel.js +3 -2
- package/dist/editor/settings/panels/AgentProfileConfigPanel.js.map +1 -1
- package/dist/editor/settings/panels/AgentsPanel.js +3 -2
- package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
- package/dist/editor/settings/panels/GroupedFieldConfigPanel.d.ts +3 -1
- package/dist/editor/settings/panels/GroupedFieldConfigPanel.js +2 -2
- package/dist/editor/settings/panels/GroupedFieldConfigPanel.js.map +1 -1
- package/dist/editor/ui/InternalLink.d.ts +2 -2
- package/dist/editor/ui/InternalLink.js +2 -2
- package/dist/editor/ui/InternalLink.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/types.d.ts +11 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import React, { useEffect, useState, useRef, useCallback, useLayoutEffect, useMemo, } from "react";
|
|
3
3
|
import { flushSync } from "react-dom";
|
|
4
4
|
import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, ChevronDown, ChevronUp, ListTodo, ArrowLeft, DollarSign, ExternalLink, Settings2, Target, X, Plus, } from "lucide-react";
|
|
5
|
-
import { getAgent, startAgent, claimAgentBrowser, assignAgentSkill, persistDraftAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, getAgentSkillCatalog, getAgentAvailableTools, getAgentOperationAllowances, getAgentTriggerSubscriptions, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, releaseAgentBrowser, revokeAgentSkill, } from "../services/agentService";
|
|
5
|
+
import { getAgent, startAgent, claimAgentBrowser, cancelAgentDialog, assignAgentSkill, persistDraftAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, getAgentSkillCatalog, getAgentAvailableTools, getAgentOperationAllowances, getAgentTriggerSubscriptions, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, releaseAgentBrowser, revokeAgentSkill, } from "../services/agentService";
|
|
6
6
|
import { parseAgentStatus } from "../services/agentStatus";
|
|
7
7
|
import { useEditContext, useFieldsEditContext } from "../client/editContext";
|
|
8
8
|
import { localStorageService } from "../services/localStorageService";
|
|
@@ -83,6 +83,8 @@ function buildPlaceholderAgentDetails(agentStub) {
|
|
|
83
83
|
function normalizeDialogAgentId(value) {
|
|
84
84
|
return value?.trim().toLowerCase() || "";
|
|
85
85
|
}
|
|
86
|
+
const MACHINE_CAPACITY_REASON = "machineCapacity";
|
|
87
|
+
const MACHINE_CAPACITY_DETAIL = "waitingForCapacity";
|
|
86
88
|
function formatAllowanceSource(source) {
|
|
87
89
|
const normalized = source?.trim();
|
|
88
90
|
if (!normalized)
|
|
@@ -116,6 +118,9 @@ function getAgentRunMessageDetail(type, payload) {
|
|
|
116
118
|
return payload?.type || null;
|
|
117
119
|
}
|
|
118
120
|
if (type === "agent:run:status") {
|
|
121
|
+
if (payload?.data?.reason === MACHINE_CAPACITY_REASON) {
|
|
122
|
+
return MACHINE_CAPACITY_DETAIL;
|
|
123
|
+
}
|
|
119
124
|
return payload?.data?.state || payload?.data?.status || null;
|
|
120
125
|
}
|
|
121
126
|
if (type === "agent:run:error") {
|
|
@@ -821,6 +826,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
821
826
|
const [agentMetadata, setAgentMetadata] = useState(null);
|
|
822
827
|
const [isBrowserClaimMutationPending, setIsBrowserClaimMutationPending] = useState(false);
|
|
823
828
|
const [pendingBrowserCaptureDialogType, setPendingBrowserCaptureDialogType] = useState(null);
|
|
829
|
+
const [pendingBrowserCaptureCallbackId, setPendingBrowserCaptureCallbackId] = useState(null);
|
|
824
830
|
// Ensure we always have an agent object for streaming handlers, even before `getAgent()` resolves.
|
|
825
831
|
// This prevents early tool calls (e.g., ask-questionnaire) from being dropped in compact/workspace UIs.
|
|
826
832
|
useEffect(() => {
|
|
@@ -965,6 +971,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
965
971
|
}
|
|
966
972
|
// Server-driven state: true when agent is actively processing (set by WebSocket messages)
|
|
967
973
|
const [isAgentThinking, setIsAgentThinking] = useState(false);
|
|
974
|
+
const [lastRunStatusReason, setLastRunStatusReason] = useState(null);
|
|
968
975
|
useEffect(() => {
|
|
969
976
|
return () => {
|
|
970
977
|
if (stopGuardReleaseTimeoutRef.current) {
|
|
@@ -1391,9 +1398,35 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1391
1398
|
}
|
|
1392
1399
|
}
|
|
1393
1400
|
};
|
|
1401
|
+
const refreshAssignedSkills = async () => {
|
|
1402
|
+
try {
|
|
1403
|
+
const latest = await getAgent(agent.id);
|
|
1404
|
+
if (!active)
|
|
1405
|
+
return;
|
|
1406
|
+
const latestSkillIds = latest?.assignedSkillIds;
|
|
1407
|
+
if (!Array.isArray(latestSkillIds))
|
|
1408
|
+
return;
|
|
1409
|
+
setAgent((prev) => {
|
|
1410
|
+
if (!prev)
|
|
1411
|
+
return prev;
|
|
1412
|
+
const prevIds = Array.isArray(prev.assignedSkillIds)
|
|
1413
|
+
? prev.assignedSkillIds
|
|
1414
|
+
: [];
|
|
1415
|
+
if (prevIds.length === latestSkillIds.length &&
|
|
1416
|
+
prevIds.every((id, i) => id === latestSkillIds[i])) {
|
|
1417
|
+
return prev;
|
|
1418
|
+
}
|
|
1419
|
+
return { ...prev, assignedSkillIds: latestSkillIds };
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
catch (e) {
|
|
1423
|
+
console.error("Failed to refresh assigned skills:", e);
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1394
1426
|
void loadTriggerSubscriptions();
|
|
1395
1427
|
void loadAvailableTools();
|
|
1396
1428
|
void loadOperationAllowances();
|
|
1429
|
+
void refreshAssignedSkills();
|
|
1397
1430
|
return () => {
|
|
1398
1431
|
active = false;
|
|
1399
1432
|
};
|
|
@@ -1404,7 +1437,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1404
1437
|
agent?.userId,
|
|
1405
1438
|
agent?.profileId,
|
|
1406
1439
|
mode,
|
|
1407
|
-
selectedSkillIds,
|
|
1408
1440
|
]);
|
|
1409
1441
|
const activeTriggerSubscriptions = useMemo(() => triggerSubscriptions.filter((sub) => sub.isActive), [triggerSubscriptions]);
|
|
1410
1442
|
const allowanceGroups = useMemo(() => [
|
|
@@ -2684,7 +2716,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
2684
2716
|
appendToolUiEvent("ui:tool-result-applied", `${extractedToolCall.functionName || "unknown"} toolCallId=${resultToolCallId} targetMessageId=${resultMessageId} completed=${matchingToolCall?.isCompleted ? "yes" : "no"} messageToolCalls=${messageWithToolResult?.toolCalls?.length || 0}`);
|
|
2685
2717
|
return updated;
|
|
2686
2718
|
});
|
|
2687
|
-
|
|
2719
|
+
// Document-store refresh is now triggered by the backend agent:documents:changed
|
|
2720
|
+
// WebSocket message (fired from AgentDocumentRepository), bridged to the in-process
|
|
2721
|
+
// emitAgentDocumentsChanged event in EditorShell. No per-tool allow-list here.
|
|
2722
|
+
}, [agent?.id, agentStub.id, appendToolUiEvent]);
|
|
2688
2723
|
// Listen for local approval resolution to update UI
|
|
2689
2724
|
useEffect(() => {
|
|
2690
2725
|
const onApprovalResolved = (ev) => {
|
|
@@ -3292,6 +3327,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3292
3327
|
// Reset run-scoped deduplication so new run seq values (starting at 1)
|
|
3293
3328
|
// are not discarded due to previous run's lastSeqRef
|
|
3294
3329
|
lastSeqRef.current = 0;
|
|
3330
|
+
setLastRunStatusReason(null);
|
|
3295
3331
|
// Prep streaming UI state for the new run
|
|
3296
3332
|
setIsConnecting(true);
|
|
3297
3333
|
setIsWaitingForResponse(true);
|
|
@@ -3520,8 +3556,16 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3520
3556
|
// Normalize various status shapes and handle Cancelled uniformly
|
|
3521
3557
|
const normalizedStatus = parseAgentStatus(statusData?.state) ||
|
|
3522
3558
|
parseAgentStatus(statusData?.status);
|
|
3559
|
+
const statusReason = typeof statusData?.reason === "string"
|
|
3560
|
+
? statusData.reason.trim() || null
|
|
3561
|
+
: null;
|
|
3562
|
+
const statusMessage = typeof statusData?.message === "string"
|
|
3563
|
+
? statusData.message.trim() || null
|
|
3564
|
+
: null;
|
|
3523
3565
|
if (normalizedStatus === "idle") {
|
|
3524
3566
|
clearStopGuard();
|
|
3567
|
+
setLastRunStatusReason(null);
|
|
3568
|
+
setError(null);
|
|
3525
3569
|
// Stop indicators and mark any in-progress streaming messages as completed
|
|
3526
3570
|
clearHeartbeatMessages();
|
|
3527
3571
|
setAgent((prev) => (prev ? { ...prev, status: "idle" } : prev));
|
|
@@ -3628,6 +3672,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3628
3672
|
}
|
|
3629
3673
|
if (statusData?.state === "ToolApprovalsRequired") {
|
|
3630
3674
|
setPendingBrowserCaptureDialogType(null);
|
|
3675
|
+
setPendingBrowserCaptureCallbackId(null);
|
|
3676
|
+
setLastRunStatusReason(null);
|
|
3631
3677
|
const msgId = statusData.messageId;
|
|
3632
3678
|
const ids = statusData.toolCallIds || [];
|
|
3633
3679
|
if (msgId && Array.isArray(ids) && ids.length > 0) {
|
|
@@ -3662,7 +3708,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3662
3708
|
// Handle waiting states explicitly
|
|
3663
3709
|
if (normalizedStatus === "waitingForApproval") {
|
|
3664
3710
|
clearStopGuard();
|
|
3711
|
+
setLastRunStatusReason(null);
|
|
3712
|
+
setError(null);
|
|
3665
3713
|
setPendingBrowserCaptureDialogType(null);
|
|
3714
|
+
setPendingBrowserCaptureCallbackId(null);
|
|
3666
3715
|
setAgent((prev) => prev ? { ...prev, status: "waitingForApproval" } : prev);
|
|
3667
3716
|
setIsConnecting(false);
|
|
3668
3717
|
setIsWaitingForResponse(false);
|
|
@@ -3672,12 +3721,20 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3672
3721
|
}
|
|
3673
3722
|
if (normalizedStatus === "waitingForInput") {
|
|
3674
3723
|
clearStopGuard();
|
|
3724
|
+
setLastRunStatusReason(null);
|
|
3725
|
+
setError(null);
|
|
3675
3726
|
const dialogType = typeof statusData?.dialogType === "string"
|
|
3676
3727
|
? statusData.dialogType
|
|
3677
3728
|
: null;
|
|
3678
3729
|
const isBrowserCaptureWait = dialogType === DIALOG_TYPES.CAPTURE_PAGE_DOM ||
|
|
3679
3730
|
dialogType === DIALOG_TYPES.CAPTURE_PAGE_SCREENSHOT;
|
|
3680
3731
|
setPendingBrowserCaptureDialogType(isBrowserCaptureWait ? dialogType : null);
|
|
3732
|
+
const captureCallbackId = isBrowserCaptureWait &&
|
|
3733
|
+
typeof statusData?.callbackId === "string" &&
|
|
3734
|
+
statusData.callbackId.trim()
|
|
3735
|
+
? statusData.callbackId.trim()
|
|
3736
|
+
: null;
|
|
3737
|
+
setPendingBrowserCaptureCallbackId(captureCallbackId);
|
|
3681
3738
|
setAgent((prev) => prev
|
|
3682
3739
|
? {
|
|
3683
3740
|
...prev,
|
|
@@ -3696,7 +3753,9 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3696
3753
|
}
|
|
3697
3754
|
if (normalizedStatus === "costLimitReached") {
|
|
3698
3755
|
clearStopGuard();
|
|
3756
|
+
setError(null);
|
|
3699
3757
|
setPendingBrowserCaptureDialogType(null);
|
|
3758
|
+
setPendingBrowserCaptureCallbackId(null);
|
|
3700
3759
|
const totalCost = Number(statusData.totalCost) || 0;
|
|
3701
3760
|
const costLimit = Number(statusData.costLimit) || agent?.costLimit || 0;
|
|
3702
3761
|
setCostLimitExceeded({
|
|
@@ -3745,6 +3804,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3745
3804
|
// Handle "completed" state (fallback for legacy code paths that send status instead of lifecycle event)
|
|
3746
3805
|
if (normalizedStatus === "completed") {
|
|
3747
3806
|
clearStopGuard();
|
|
3807
|
+
setError(null);
|
|
3748
3808
|
// Reset deduplication for the next run
|
|
3749
3809
|
lastSeqRef.current = 0;
|
|
3750
3810
|
clearHeartbeatMessages();
|
|
@@ -3775,6 +3835,25 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3775
3835
|
if (isStoppingRef.current) {
|
|
3776
3836
|
return;
|
|
3777
3837
|
}
|
|
3838
|
+
if (statusReason === MACHINE_CAPACITY_REASON) {
|
|
3839
|
+
clearHeartbeatMessages();
|
|
3840
|
+
setLastRunStatusReason(statusReason);
|
|
3841
|
+
setAgent((prev) => prev
|
|
3842
|
+
? {
|
|
3843
|
+
...prev,
|
|
3844
|
+
status: "running",
|
|
3845
|
+
statusMessage: statusMessage ||
|
|
3846
|
+
"Waiting for capacity. The agent will start automatically when a slot becomes available.",
|
|
3847
|
+
}
|
|
3848
|
+
: prev);
|
|
3849
|
+
setIsWaitingForResponse(false);
|
|
3850
|
+
isWaitingRef.current = false;
|
|
3851
|
+
setIsConnecting(false);
|
|
3852
|
+
setIsAgentThinking(false);
|
|
3853
|
+
return;
|
|
3854
|
+
}
|
|
3855
|
+
setLastRunStatusReason(null);
|
|
3856
|
+
setError(null);
|
|
3778
3857
|
// Update agent status to running and clear any previous error statusMessage
|
|
3779
3858
|
setAgent((prev) => prev
|
|
3780
3859
|
? { ...prev, status: "running", statusMessage: undefined }
|
|
@@ -3787,8 +3866,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3787
3866
|
// Handle "Error" state
|
|
3788
3867
|
if (normalizedStatus === "error") {
|
|
3789
3868
|
clearStopGuard();
|
|
3790
|
-
|
|
3869
|
+
setLastRunStatusReason(null);
|
|
3870
|
+
const errorMsg = toUserFacingAgentErrorMessage(statusData?.statusMessage ??
|
|
3871
|
+
statusData?.message ??
|
|
3872
|
+
statusData?.error) || "Unknown error";
|
|
3791
3873
|
clearHeartbeatMessages();
|
|
3874
|
+
setError(errorMsg);
|
|
3792
3875
|
setAgent((prev) => prev
|
|
3793
3876
|
? { ...prev, status: "error", statusMessage: errorMsg }
|
|
3794
3877
|
: prev);
|
|
@@ -3808,6 +3891,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3808
3891
|
if (messageType === "agent:run:complete") {
|
|
3809
3892
|
// Reset deduplication for the next run
|
|
3810
3893
|
lastSeqRef.current = 0;
|
|
3894
|
+
setLastRunStatusReason(null);
|
|
3811
3895
|
clearHeartbeatMessages();
|
|
3812
3896
|
// Mark the last assistant message as completed
|
|
3813
3897
|
setMessages((prev) => {
|
|
@@ -3836,6 +3920,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3836
3920
|
const errorMsg = toUserFacingAgentErrorMessage(message.payload?.error) ||
|
|
3837
3921
|
"AI could not complete this request.";
|
|
3838
3922
|
clearHeartbeatMessages();
|
|
3923
|
+
setLastRunStatusReason(null);
|
|
3839
3924
|
// Reset deduplication for the next run after an error
|
|
3840
3925
|
lastSeqRef.current = 0;
|
|
3841
3926
|
setError(errorMsg);
|
|
@@ -4488,9 +4573,28 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
4488
4573
|
console.log("[AgentTerminal] Calling startAgent API for agent:", agentId);
|
|
4489
4574
|
const response = await startAgent(request);
|
|
4490
4575
|
console.log("[AgentTerminal] startAgent response:", response);
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4576
|
+
const isQueuedForCapacity = response.reason === MACHINE_CAPACITY_REASON ||
|
|
4577
|
+
response.message?.toLowerCase().includes("machine slot") ||
|
|
4578
|
+
false;
|
|
4579
|
+
// Check if prompt was queued because another execution was already active
|
|
4580
|
+
const wasQueued = !isQueuedForCapacity &&
|
|
4581
|
+
response.message?.toLowerCase().includes("queued");
|
|
4582
|
+
if (isQueuedForCapacity) {
|
|
4583
|
+
setLastRunStatusReason(MACHINE_CAPACITY_REASON);
|
|
4584
|
+
setAgent((prev) => prev
|
|
4585
|
+
? {
|
|
4586
|
+
...prev,
|
|
4587
|
+
status: "running",
|
|
4588
|
+
statusMessage: response.message ||
|
|
4589
|
+
"Waiting for capacity. The agent will start automatically when a slot becomes available.",
|
|
4590
|
+
}
|
|
4591
|
+
: prev);
|
|
4592
|
+
setIsWaitingForResponse(false);
|
|
4593
|
+
isWaitingRef.current = false;
|
|
4594
|
+
setIsConnecting(false);
|
|
4595
|
+
setIsAgentThinking(false);
|
|
4596
|
+
}
|
|
4597
|
+
else if (wasQueued) {
|
|
4494
4598
|
// Prompt was queued - show a brief notification but don't set waiting state
|
|
4495
4599
|
// The prompt will be processed when the agent becomes idle
|
|
4496
4600
|
console.log("[AgentTerminal] Prompt queued for processing");
|
|
@@ -4499,6 +4603,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
4499
4603
|
isWaitingRef.current = false;
|
|
4500
4604
|
}
|
|
4501
4605
|
else {
|
|
4606
|
+
setLastRunStatusReason(null);
|
|
4502
4607
|
clearSuppressedQueuedPrompt(suppressedQueuedPromptToken);
|
|
4503
4608
|
// Normal submission - set waiting state to show dancing dots immediately
|
|
4504
4609
|
setIsWaitingForResponse(true);
|
|
@@ -5332,6 +5437,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
5332
5437
|
isWaitingForResponse,
|
|
5333
5438
|
isAgentThinking,
|
|
5334
5439
|
isExecuting,
|
|
5440
|
+
lastStatusReason: lastRunStatusReason,
|
|
5441
|
+
lastStatusMessage: agent?.statusMessage || null,
|
|
5335
5442
|
hasActiveStreaming: hasActiveStreaming(),
|
|
5336
5443
|
isSubscribed: normalizeDialogAgentId(subscribedAgentIdRef.current) ===
|
|
5337
5444
|
normalizeDialogAgentId(currentAgentId),
|
|
@@ -5359,10 +5466,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
5359
5466
|
isExecuting,
|
|
5360
5467
|
isSubmitting,
|
|
5361
5468
|
isWaitingForResponse,
|
|
5469
|
+
lastRunStatusReason,
|
|
5362
5470
|
messagesWithToolCallsCount,
|
|
5363
5471
|
recentAgentRunEvents,
|
|
5364
5472
|
recentToolUiEvents,
|
|
5365
5473
|
totalToolCallCount,
|
|
5474
|
+
agent?.statusMessage,
|
|
5366
5475
|
]);
|
|
5367
5476
|
const showInitialThinkingSplash = messages.length === 0 &&
|
|
5368
5477
|
!error &&
|
|
@@ -5517,6 +5626,15 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
5517
5626
|
const errorMessage = toUserFacingAgentErrorMessage(rawErrorMessage) || rawErrorMessage;
|
|
5518
5627
|
return (_jsx("div", { className: "m-3 rounded border border-red-300 bg-red-50 p-3 text-[11px] text-red-900", "data-testid": "agent-error-banner", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertCircle, { className: "mt-0.5 h-4 w-4 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 })] })] }) }));
|
|
5519
5628
|
};
|
|
5629
|
+
const renderCapacityBanner = () => {
|
|
5630
|
+
if (lastRunStatusReason !== MACHINE_CAPACITY_REASON) {
|
|
5631
|
+
return null;
|
|
5632
|
+
}
|
|
5633
|
+
const currentAgent = agent || agentStub;
|
|
5634
|
+
const message = currentAgent?.statusMessage ||
|
|
5635
|
+
"Waiting for capacity. The agent will start automatically when a slot becomes available.";
|
|
5636
|
+
return (_jsx("div", { className: "m-3 rounded border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900", "data-testid": "agent-capacity-banner", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-500", strokeWidth: 1 }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "mb-1 font-semibold", children: "Waiting for capacity" }), _jsx("div", { className: "text-amber-800", children: message })] })] }) }));
|
|
5637
|
+
};
|
|
5520
5638
|
const renderBrowserClaimBanner = (variant = "inline") => {
|
|
5521
5639
|
if (!agent?.id || !editContext?.sessionId)
|
|
5522
5640
|
return null;
|
|
@@ -5567,13 +5685,42 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
5567
5685
|
onAction: () => {
|
|
5568
5686
|
void handleClaimBrowser(isClaimedByAnotherBrowser);
|
|
5569
5687
|
},
|
|
5688
|
+
cancelLabel: "Cancel capture",
|
|
5689
|
+
onCancel: pendingBrowserCaptureCallbackId
|
|
5690
|
+
? () => {
|
|
5691
|
+
void handleCancelBrowserCapture();
|
|
5692
|
+
}
|
|
5693
|
+
: undefined,
|
|
5570
5694
|
}
|
|
5571
5695
|
: null;
|
|
5572
5696
|
useEffect(() => {
|
|
5573
5697
|
if (agent?.status !== "waitingForInput") {
|
|
5574
5698
|
setPendingBrowserCaptureDialogType(null);
|
|
5699
|
+
setPendingBrowserCaptureCallbackId(null);
|
|
5575
5700
|
}
|
|
5576
5701
|
}, [agent?.status]);
|
|
5702
|
+
const handleCancelBrowserCapture = useCallback(async () => {
|
|
5703
|
+
const callbackId = pendingBrowserCaptureCallbackId;
|
|
5704
|
+
if (!callbackId || !editContext?.sessionId)
|
|
5705
|
+
return;
|
|
5706
|
+
setIsBrowserClaimMutationPending(true);
|
|
5707
|
+
try {
|
|
5708
|
+
await cancelAgentDialog({
|
|
5709
|
+
callbackId,
|
|
5710
|
+
sessionId: editContext.sessionId,
|
|
5711
|
+
error: "Cancelled by user from the capture waiting banner.",
|
|
5712
|
+
});
|
|
5713
|
+
setPendingBrowserCaptureDialogType(null);
|
|
5714
|
+
setPendingBrowserCaptureCallbackId(null);
|
|
5715
|
+
}
|
|
5716
|
+
catch (err) {
|
|
5717
|
+
console.error("[AgentTerminal] Failed to cancel capture dialog:", err);
|
|
5718
|
+
editContext?.showErrorToast?.(err);
|
|
5719
|
+
}
|
|
5720
|
+
finally {
|
|
5721
|
+
setIsBrowserClaimMutationPending(false);
|
|
5722
|
+
}
|
|
5723
|
+
}, [pendingBrowserCaptureCallbackId, editContext]);
|
|
5577
5724
|
const renderInlineDialogContent = () => {
|
|
5578
5725
|
if (!activeInlineDialog)
|
|
5579
5726
|
return null;
|
|
@@ -5636,7 +5783,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
5636
5783
|
return (_jsxs("div", { className: `flex h-full min-h-0 flex-col ${className || ""}`, children: [fixedBrowserClaimBanner, _jsxs("div", { ref: messagesContainerRef, className: "flex-1 overflow-y-auto", onScroll: handleScroll, children: [error &&
|
|
5637
5784
|
!isAgentErrorStatusValue((agent || agentStub)?.status) && (_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 })] })] }) })), showInitialThinkingSplash && (_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: {
|
|
5638
5785
|
__html: sanitizeSvg(activeProfile.svgIcon),
|
|
5639
|
-
} })) : (_jsx(SecretAgentIcon, { size: 64, strokeWidth: 1, className: "text-gray-400" })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400" })] })] }) })), inlineBrowserClaimBanner, renderErrorBanner(), inlineDialog ? (inlineDialog) : latestSummaryAssistantGroup ? (_jsx("div", { className: "space-y-0 divide-y divide-gray-100 select-text", children: _jsx(AiResponseMessage, { messages: summaryMessages, finished: !latestSummaryAssistantGroup.isLastGroup || !isExecuting, editOperations: summaryOperations, defaultCollapseJson: defaultCollapseJson, profileSvgIcon: activeProfile?.svgIcon, agentId: agent?.id || agentStub.id, agentName: activeProfile?.agentName ||
|
|
5786
|
+
} })) : (_jsx(SecretAgentIcon, { size: 64, strokeWidth: 1, className: "text-gray-400" })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400" })] })] }) })), inlineBrowserClaimBanner, renderCapacityBanner(), renderErrorBanner(), inlineDialog ? (inlineDialog) : latestSummaryAssistantGroup ? (_jsx("div", { className: "space-y-0 divide-y divide-gray-100 select-text", children: _jsx(AiResponseMessage, { messages: summaryMessages, finished: !latestSummaryAssistantGroup.isLastGroup || !isExecuting, editOperations: summaryOperations, defaultCollapseJson: defaultCollapseJson, profileSvgIcon: activeProfile?.svgIcon, agentId: agent?.id || agentStub.id, agentName: activeProfile?.agentName ||
|
|
5640
5787
|
activeProfile?.displayTitle ||
|
|
5641
5788
|
activeProfile?.name, allPendingApprovals: allPendingApprovals, onSwitchToAutonomous: handleSwitchToAutonomous, browserCaptureInlinePrompt: browserCaptureInlinePrompt, onQuickAction: (action) => {
|
|
5642
5789
|
const text = (action.prompt ||
|
|
@@ -5762,7 +5909,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
5762
5909
|
}, 0);
|
|
5763
5910
|
} })) })), showInitialThinkingSplash && (_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: {
|
|
5764
5911
|
__html: sanitizeSvg(activeProfile.svgIcon),
|
|
5765
|
-
} })) : (_jsx(SecretAgentIcon, { size: 64, strokeWidth: 1, className: "text-gray-400" })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400" })] })] }) })), inlineBrowserClaimBanner, renderErrorBanner(), _jsxs("div", { className: "space-y-0 divide-y divide-gray-100 select-text", children: [(() => {
|
|
5912
|
+
} })) : (_jsx(SecretAgentIcon, { size: 64, strokeWidth: 1, className: "text-gray-400" })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-gray-400" })] })] }) })), inlineBrowserClaimBanner, renderCapacityBanner(), renderErrorBanner(), _jsxs("div", { className: "space-y-0 divide-y divide-gray-100 select-text", children: [(() => {
|
|
5766
5913
|
const groups = groupConsecutiveMessages(messages);
|
|
5767
5914
|
return groups.map((group, groupIndex) => {
|
|
5768
5915
|
const isLastGroup = groupIndex === groups.length - 1;
|