@parhelia/core 0.1.12221 → 0.1.12241

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.
Files changed (77) hide show
  1. package/dist/components/ui/button.d.ts +1 -1
  2. package/dist/components/ui/dialog.js +2 -1
  3. package/dist/components/ui/dialog.js.map +1 -1
  4. package/dist/editor/ConfirmationDialog.js +1 -1
  5. package/dist/editor/ConfirmationDialog.js.map +1 -1
  6. package/dist/editor/ContentTree.js.map +1 -1
  7. package/dist/editor/FieldListField.js +1 -1
  8. package/dist/editor/FieldListField.js.map +1 -1
  9. package/dist/editor/GlobalMenuBar.js +1 -2
  10. package/dist/editor/GlobalMenuBar.js.map +1 -1
  11. package/dist/editor/ai/AgentTerminal.js +187 -109
  12. package/dist/editor/ai/AgentTerminal.js.map +1 -1
  13. package/dist/editor/ai/dialogs/AgentDialogHandler.js +3 -7
  14. package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
  15. package/dist/editor/ai/dialogs/QuestionnaireInline.js +21 -5
  16. package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
  17. package/dist/editor/client/EditorShell.js +2 -1
  18. package/dist/editor/client/EditorShell.js.map +1 -1
  19. package/dist/editor/client/editContext.d.ts +1 -1
  20. package/dist/editor/client/operations.d.ts +1 -1
  21. package/dist/editor/client/operations.js +1 -0
  22. package/dist/editor/client/operations.js.map +1 -1
  23. package/dist/editor/commands/itemCommands.js +7 -4
  24. package/dist/editor/commands/itemCommands.js.map +1 -1
  25. package/dist/editor/context-menu/InsertMenu.js +2 -1
  26. package/dist/editor/context-menu/InsertMenu.js.map +1 -1
  27. package/dist/editor/page-editor-chrome/InlineEditor.js +20 -7
  28. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
  29. package/dist/editor/page-viewer/MiniMap.d.ts +3 -1
  30. package/dist/editor/page-viewer/MiniMap.js +13 -57
  31. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  32. package/dist/editor/page-viewer/PageViewerFrame.js +1 -1
  33. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  34. package/dist/editor/services/agentService.d.ts +12 -0
  35. package/dist/editor/services/agentService.js +20 -0
  36. package/dist/editor/services/agentService.js.map +1 -1
  37. package/dist/editor/sidebar/WorkspaceRail.js +2 -1
  38. package/dist/editor/sidebar/WorkspaceRail.js.map +1 -1
  39. package/dist/editor/views/EditView.js +1 -1
  40. package/dist/editor/views/EditView.js.map +1 -1
  41. package/dist/editor/views/EditorSlot.js +17 -24
  42. package/dist/editor/views/EditorSlot.js.map +1 -1
  43. package/dist/revision.d.ts +2 -2
  44. package/dist/revision.js +2 -2
  45. package/dist/task-board/TaskBoardWorkspace.js +159 -27
  46. package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
  47. package/dist/task-board/components/CreateProjectDialog.js +18 -9
  48. package/dist/task-board/components/CreateProjectDialog.js.map +1 -1
  49. package/dist/task-board/components/ProjectDashboard.js +0 -1
  50. package/dist/task-board/components/ProjectDashboard.js.map +1 -1
  51. package/dist/task-board/components/ProjectSelector.d.ts +1 -0
  52. package/dist/task-board/components/ProjectSelector.js +2 -2
  53. package/dist/task-board/components/ProjectSelector.js.map +1 -1
  54. package/dist/task-board/components/ProjectSettingsDialog.js +0 -1
  55. package/dist/task-board/components/ProjectSettingsDialog.js.map +1 -1
  56. package/dist/task-board/components/TaskAgentPanel.d.ts +3 -0
  57. package/dist/task-board/components/TaskAgentPanel.js +13 -4
  58. package/dist/task-board/components/TaskAgentPanel.js.map +1 -1
  59. package/dist/task-board/components/TaskBoardTitlebar.js +3 -3
  60. package/dist/task-board/components/TaskBoardTitlebar.js.map +1 -1
  61. package/dist/task-board/components/TaskCard.d.ts +2 -1
  62. package/dist/task-board/components/TaskCard.js.map +1 -1
  63. package/dist/task-board/taskBoardNavStore.d.ts +1 -0
  64. package/dist/task-board/taskBoardNavStore.js +1 -0
  65. package/dist/task-board/taskBoardNavStore.js.map +1 -1
  66. package/dist/task-board/taskExecutionStatus.js +34 -8
  67. package/dist/task-board/taskExecutionStatus.js.map +1 -1
  68. package/dist/task-board/types.d.ts +1 -1
  69. package/dist/task-board/views/KanbanView.d.ts +2 -0
  70. package/dist/task-board/views/KanbanView.js +177 -37
  71. package/dist/task-board/views/KanbanView.js.map +1 -1
  72. package/dist/task-board/views/ListView.d.ts +2 -0
  73. package/dist/task-board/views/ListView.js +4 -3
  74. package/dist/task-board/views/ListView.js.map +1 -1
  75. package/dist/task-board/views/PlanningView.js +1 -1
  76. package/dist/task-board/views/PlanningView.js.map +1 -1
  77. package/package.json +2 -1
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useEffect, useState, useRef, useCallback, useLayoutEffect, useMemo, } from "react";
3
3
  import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, ChevronDown, ChevronUp, ListTodo, ArrowLeft, DollarSign, ExternalLink, Settings2, Target, Plus, X, } from "lucide-react";
4
- import { getAgent, startAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, getAgentSkills, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, } from "../services/agentService";
4
+ import { getAgent, startAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, getAgentSkills, getAgentTriggerSubscriptions, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, } from "../services/agentService";
5
5
  import { useEditContext, useFieldsEditContext } from "../client/editContext";
6
6
  import { localStorageService } from "../services/localStorageService";
7
7
  import { Textarea } from "../../components/ui/textarea";
@@ -51,9 +51,19 @@ function buildPlaceholderAgentDetails(agentStub) {
51
51
  }
52
52
  // Simple user message component
53
53
  const UserMessage = ({ message }) => {
54
+ const content = message.content || "";
55
+ const [isTriggerExpanded, setIsTriggerExpanded] = useState(false);
56
+ // Trigger-sourced prompts are prefixed by backend as "[Trigger: {name}]: {content}"
57
+ const triggerPattern = /^\[Trigger: ([^\]]+)\]:\s*(.*)$/s;
58
+ const triggerMatch = content.match(triggerPattern);
59
+ const triggerName = triggerMatch?.[1]?.trim() || "";
60
+ const triggerContent = triggerMatch?.[2] || "";
61
+ const isTriggerMessage = triggerName.length > 0;
62
+ if (isTriggerMessage) {
63
+ return (_jsx("div", { className: "px-4 py-2", children: _jsxs("div", { className: "text-[11px]", children: [_jsxs("button", { type: "button", onClick: () => setIsTriggerExpanded((expanded) => !expanded), className: "text-theme-secondary hover:bg-theme-hover flex w-full items-center gap-2 rounded-md border-l-2 border-cyan-200 px-2 py-1 text-left transition-colors", "data-testid": "trigger-message-toggle", "data-expanded": isTriggerExpanded ? "true" : "false", children: [_jsx(Target, { className: "h-3.5 w-3.5 shrink-0", strokeWidth: 1.5 }), _jsxs("span", { className: "truncate font-medium", children: ["Trigger: ", triggerName] }), message.createdDate && (_jsx("span", { className: "ml-1 shrink-0 text-[10px] text-gray-400", children: formatTime(new Date(message.createdDate)) })), _jsx("span", { className: "ml-auto shrink-0", children: isTriggerExpanded ? (_jsx(ChevronUp, { className: "h-3.5 w-3.5" })) : (_jsx(ChevronDown, { className: "h-3.5 w-3.5" })) })] }), isTriggerExpanded && (_jsx("div", { className: "mt-1 border-l-2 border-cyan-100 pl-[1.35rem] text-[11px] text-gray-600", children: triggerContent }))] }) }));
64
+ }
54
65
  // Parse source agent name from content if it starts with "[From ...]:"
55
66
  // Backend formats messages from other agents as "[From {sourceAgentName}]: {content}"
56
- const content = message.content || "";
57
67
  const fromPattern = /^\[From ([^\]]+)\]:\s*(.*)$/s;
58
68
  const match = content.match(fromPattern);
59
69
  let sourceAgentName;
@@ -766,6 +776,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
766
776
  const [selectedModelId, setSelectedModelId] = useState(undefined);
767
777
  const [mode, setMode] = useState("supervised");
768
778
  const [queuedPrompts, setQueuedPrompts] = useState([]);
779
+ const [expandedQueuedTriggerIds, setExpandedQueuedTriggerIds] = useState({});
769
780
  const isMobile = useMediaQuery("(max-width: 768px)");
770
781
  const [contextPanelsActiveTab, setContextPanelsActiveTab] = useState(0);
771
782
  const [hiddenContextPanelTabIds, setHiddenContextPanelTabIds] = useState(new Set());
@@ -775,6 +786,9 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
775
786
  const [availableSkills, setAvailableSkills] = useState([]);
776
787
  const [skillsLoading, setSkillsLoading] = useState(false);
777
788
  const [skillsError, setSkillsError] = useState(null);
789
+ const [triggerSubscriptions, setTriggerSubscriptions] = useState([]);
790
+ const [triggerSubscriptionsLoading, setTriggerSubscriptionsLoading] = useState(false);
791
+ const [triggerSubscriptionsError, setTriggerSubscriptionsError] = useState(null);
778
792
  const hasSpawnedAgents = useMemo(() => {
779
793
  if (!agentMetadata)
780
794
  return false;
@@ -896,6 +910,45 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
896
910
  active = false;
897
911
  };
898
912
  }, []);
913
+ useEffect(() => {
914
+ let active = true;
915
+ if (!showAgentSettings) {
916
+ return () => {
917
+ active = false;
918
+ };
919
+ }
920
+ if (!agent?.id || agent.status === "new") {
921
+ setTriggerSubscriptions([]);
922
+ setTriggerSubscriptionsError(null);
923
+ return () => {
924
+ active = false;
925
+ };
926
+ }
927
+ const loadTriggerSubscriptions = async () => {
928
+ try {
929
+ setTriggerSubscriptionsLoading(true);
930
+ setTriggerSubscriptionsError(null);
931
+ const subscriptions = await getAgentTriggerSubscriptions(agent.id);
932
+ if (active) {
933
+ setTriggerSubscriptions(subscriptions);
934
+ }
935
+ }
936
+ catch (e) {
937
+ if (active) {
938
+ setTriggerSubscriptionsError(e?.message || "Failed to load trigger subscriptions");
939
+ }
940
+ }
941
+ finally {
942
+ if (active) {
943
+ setTriggerSubscriptionsLoading(false);
944
+ }
945
+ }
946
+ };
947
+ void loadTriggerSubscriptions();
948
+ return () => {
949
+ active = false;
950
+ };
951
+ }, [showAgentSettings, agent?.id, agent?.status]);
899
952
  const modeOptions = useMemo(() => [
900
953
  {
901
954
  value: "supervised",
@@ -965,6 +1018,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
965
1018
  }
966
1019
  return unique;
967
1020
  }, [backendAssignedSkillIds, metadataSelectedSkillIds]);
1021
+ const activeTriggerSubscriptions = useMemo(() => triggerSubscriptions.filter((sub) => sub.isActive), [triggerSubscriptions]);
968
1022
  const allowedProfileSkillIdSet = useMemo(() => {
969
1023
  const ids = activeProfile?.allowedSkills
970
1024
  ?.map((skill) => String(skill?.id || "").toLowerCase())
@@ -1077,6 +1131,17 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
1077
1131
  });
1078
1132
  editContext.switchWorkspace("editor");
1079
1133
  }, [editContext, activeProfile?.id]);
1134
+ const handleOpenSkillItem = useCallback(async (skillId) => {
1135
+ if (!editContext || !skillId)
1136
+ return;
1137
+ const lang = editContext.currentItemDescriptor?.language || "en";
1138
+ await editContext.loadItem({
1139
+ id: skillId,
1140
+ language: lang,
1141
+ version: 0,
1142
+ });
1143
+ editContext.switchWorkspace("editor");
1144
+ }, [editContext]);
1080
1145
  // Read deterministic flags from query string once
1081
1146
  let deterministicFlags;
1082
1147
  try {
@@ -2064,46 +2129,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
2064
2129
  })();
2065
2130
  // Create context with top-level properties (what ContextInfoBar expects)
2066
2131
  const localCtx = item && shouldSeedContext
2067
- ? {
2068
- items: [
2069
- {
2070
- id: item.id,
2071
- language: item.language,
2072
- version: item.version,
2073
- name: editContext?.item?.name,
2074
- path: editContext?.item?.path,
2075
- },
2076
- ],
2077
- components: editContext?.selection?.length && item
2078
- ? editContext.selection.map((componentId) => ({
2079
- componentId,
2080
- pageItem: {
2081
- id: item.id,
2082
- language: item.language,
2083
- version: item.version,
2084
- name: editContext?.item?.name,
2085
- },
2086
- }))
2087
- : undefined,
2088
- field: fieldsContext?.focusedField?.fieldId &&
2089
- fieldsContext.focusedField?.item?.id
2090
- ? {
2091
- fieldId: fieldsContext.focusedField.fieldId,
2092
- fieldName: fieldsContext.focusedField
2093
- .fieldName,
2094
- item: {
2095
- id: fieldsContext.focusedField.item.id,
2096
- language: fieldsContext.focusedField.item.language ||
2097
- editContext?.currentItemDescriptor?.language ||
2098
- "en",
2099
- version: fieldsContext.focusedField.item.version ??
2100
- editContext?.currentItemDescriptor?.version ??
2101
- 0,
2102
- name: editContext?.item?.name,
2103
- },
2104
- }
2105
- : undefined,
2106
- }
2132
+ ? buildEditorContextPayload(item)
2107
2133
  : null;
2108
2134
  let nextMetadata = null;
2109
2135
  if (initialMetadata) {
@@ -3957,66 +3983,93 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
3957
3983
  }
3958
3984
  return context;
3959
3985
  }, [collectVisibleTestIds]);
3960
- // Helper function to build current context from editor state
3961
- const buildCurrentContext = useCallback(() => {
3962
- // Return context even without item - we want view info regardless
3963
- const item = editContext?.currentItemDescriptor;
3964
- return {
3965
- items: item
3966
- ? [
3967
- {
3968
- id: item.id,
3969
- language: item.language,
3970
- version: item.version,
3971
- name: editContext?.item?.name,
3972
- path: editContext?.item?.path,
3973
- },
3974
- ]
3975
- : undefined,
3976
- currentItemId: item?.id, // ID of the currently loaded item user is viewing
3977
- components: editContext?.selection?.length && item
3978
- ? editContext.selection.map((componentId) => ({
3979
- componentId,
3980
- pageItem: {
3981
- id: item.id,
3982
- language: item.language,
3983
- version: item.version,
3984
- name: editContext?.item?.name,
3985
- },
3986
- }))
3987
- : undefined,
3988
- field: fieldsContext?.focusedField?.fieldId &&
3989
- fieldsContext.focusedField?.item?.id
3990
- ? {
3991
- fieldId: fieldsContext.focusedField.fieldId,
3992
- fieldName: fieldsContext.focusedField.fieldName,
3993
- item: {
3994
- id: fieldsContext.focusedField.item.id,
3995
- language: fieldsContext.focusedField.item.language ||
3996
- editContext?.currentItemDescriptor?.language ||
3997
- "en",
3998
- version: fieldsContext.focusedField.item.version ??
3999
- editContext?.currentItemDescriptor?.version ??
4000
- 0,
4001
- name: editContext?.item?.name,
4002
- },
3986
+ const buildPageContextItem = useCallback((item) => ({
3987
+ id: item.id,
3988
+ language: item.language,
3989
+ version: item.version,
3990
+ name: editContext?.item?.name,
3991
+ path: editContext?.item?.path,
3992
+ }), [editContext?.item?.name, editContext?.item?.path]);
3993
+ const buildComponentContext = useCallback((item) => {
3994
+ if (!editContext?.selection?.length)
3995
+ return undefined;
3996
+ return editContext.selection.map((componentId) => {
3997
+ let componentName;
3998
+ let componentType;
3999
+ let renderingItemId;
4000
+ if (editContext.page) {
4001
+ try {
4002
+ const component = getComponentById(componentId, editContext.page);
4003
+ componentName =
4004
+ component?.datasourceItem?.name || component?.name || undefined;
4005
+ componentType = component?.type || undefined;
4006
+ renderingItemId = component?.rendering?.id || undefined;
4003
4007
  }
4004
- : undefined,
4005
- // View context - always include so agent knows editor state
4006
- activeWorkspace: editContext?.workspaceId,
4007
- hasPageLoaded: !!editContext?.getActiveSlotContext()?.primaryPageViewContext?.page,
4008
- // Open sidebars - helps agent understand what panels are currently visible
4009
- openSidebars: editContext?.openSidebars,
4008
+ catch { }
4009
+ }
4010
+ return {
4011
+ componentId,
4012
+ componentName,
4013
+ componentType,
4014
+ renderingItemId,
4015
+ pageItem: buildPageContextItem(item),
4016
+ };
4017
+ });
4018
+ }, [buildPageContextItem, editContext?.page, editContext?.selection]);
4019
+ const buildFieldContext = useCallback(() => {
4020
+ const focusedField = fieldsContext?.focusedField;
4021
+ if (!focusedField?.fieldId || !focusedField?.item?.id)
4022
+ return undefined;
4023
+ const fieldItem = focusedField.item;
4024
+ const currentItem = editContext?.currentItemDescriptor;
4025
+ let fieldItemName = fieldItem.id === currentItem?.id ? editContext?.item?.name : undefined;
4026
+ if (!fieldItemName && editContext?.page) {
4027
+ try {
4028
+ const component = getComponentById(fieldItem.id, editContext.page);
4029
+ fieldItemName =
4030
+ component?.datasourceItem?.name || component?.name || undefined;
4031
+ }
4032
+ catch { }
4033
+ }
4034
+ return {
4035
+ fieldId: focusedField.fieldId,
4036
+ fieldName: focusedField.fieldName,
4037
+ item: {
4038
+ id: fieldItem.id,
4039
+ language: fieldItem.language || currentItem?.language || "en",
4040
+ version: fieldItem.version ?? currentItem?.version ?? 0,
4041
+ name: fieldItem.name || fieldItemName,
4042
+ },
4010
4043
  };
4011
4044
  }, [
4012
4045
  editContext?.currentItemDescriptor,
4013
- editContext?.selection,
4014
- editContext?.workspaceId,
4015
4046
  editContext?.item?.name,
4016
- editContext?.activeSlotId,
4017
- editContext?.openSidebars,
4047
+ editContext?.page,
4018
4048
  fieldsContext?.focusedField,
4019
4049
  ]);
4050
+ const buildEditorContextPayload = useCallback((item) => ({
4051
+ items: item ? [buildPageContextItem(item)] : undefined,
4052
+ currentItemId: item?.id,
4053
+ components: item ? buildComponentContext(item) : undefined,
4054
+ field: buildFieldContext(),
4055
+ activeWorkspace: editContext?.workspaceId,
4056
+ hasPageLoaded: !!editContext?.getActiveSlotContext()?.primaryPageViewContext?.page,
4057
+ openSidebars: editContext?.openSidebars,
4058
+ }), [
4059
+ buildComponentContext,
4060
+ buildFieldContext,
4061
+ buildPageContextItem,
4062
+ editContext,
4063
+ ]);
4064
+ // Helper function to build current context from editor state
4065
+ const buildCurrentContext = useCallback(() => {
4066
+ // Return context even without item - we want view info regardless
4067
+ const item = editContext?.currentItemDescriptor;
4068
+ return buildEditorContextPayload(item);
4069
+ }, [
4070
+ buildEditorContextPayload,
4071
+ editContext?.currentItemDescriptor,
4072
+ ]);
4020
4073
  // Live context updates: watch for changes and update agent context when in "live" mode
4021
4074
  const previousContextRef = useRef("");
4022
4075
  useEffect(() => {
@@ -4474,12 +4527,36 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4474
4527
  hasTodoContent,
4475
4528
  hasSpawnedAgents,
4476
4529
  agent?.id && hasHistoryContent,
4477
- ].filter(Boolean).length - 1)), setActiveTab: setContextPanelsActiveTab, className: "justify-start px-4" }) })) : (_jsxs(_Fragment, { children: [renderContextInfoBar(), agent?.id && activeProfile && (_jsx(AgentDocumentList, { ref: documentListRef, agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)), _jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata }), _jsx(SpawnedAgentsPanel, { agentMetadata: agentMetadata }), agent?.id && _jsx(AgentEditOperationsPanel, { agentId: agent.id })] }))), queuedPrompts.length > 0 && !simpleMode && (_jsx("div", { className: "border-t border-gray-200 bg-amber-50/50", "data-testid": "queued-prompts-section", 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", "data-testid": "queued-prompts-count", children: ["Queued Messages (", queuedPrompts.length, ")"] })] }), _jsx("div", { className: "max-h-64 space-y-2 overflow-y-auto", children: queuedPrompts.map((qp) => (_jsx("div", { className: "rounded-md border border-amber-200 bg-white p-2.5 text-[11px]", "data-testid": "queued-prompt-item", 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: "wrap-break-word whitespace-pre-wrap text-gray-600", "data-testid": "queued-prompt-text", children: qp.prompt }), _jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] text-gray-400", children: [qp.createdDate && (_jsxs("span", { children: ["Queued ", formatTime(new Date(qp.createdDate))] })), qp.scheduledFor &&
4478
- new Date(qp.scheduledFor).getTime() >
4479
- new Date(qp.createdDate || 0).getTime() + 1000 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-gray-300", children: "\u2022" }), _jsxs("span", { className: "font-medium text-amber-600", children: ["Scheduled for", " ", new Date(qp.scheduledFor).toDateString() ===
4480
- new Date().toDateString()
4481
- ? formatTime(new Date(qp.scheduledFor))
4482
- : formatDateTime(new Date(qp.scheduledFor))] })] }))] })] }) }) }, qp.id))) })] }) })), activeInlineDialog &&
4530
+ ].filter(Boolean).length - 1)), setActiveTab: setContextPanelsActiveTab, className: "justify-start px-4" }) })) : (_jsxs(_Fragment, { children: [renderContextInfoBar(), agent?.id && activeProfile && (_jsx(AgentDocumentList, { ref: documentListRef, agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)), _jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata }), _jsx(SpawnedAgentsPanel, { agentMetadata: agentMetadata }), agent?.id && _jsx(AgentEditOperationsPanel, { agentId: agent.id })] }))), queuedPrompts.length > 0 && !simpleMode && (_jsx("div", { className: "border-t border-gray-200 bg-amber-50/50", "data-testid": "queued-prompts-section", children: _jsxs("div", { className: "px-4 pt-2.5 pb-2", children: [_jsxs("div", { className: "mb-1.5 flex items-center gap-1.5", children: [_jsx("div", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-amber-400" }), _jsxs("span", { className: "text-[10px] font-medium tracking-wide text-amber-600 uppercase", "data-testid": "queued-prompts-count", children: ["Queued (", queuedPrompts.length, ")"] })] }), _jsx("div", { className: "max-h-64 space-y-0.5 overflow-y-auto", children: queuedPrompts.map((qp) => {
4531
+ let triggerName = "";
4532
+ if (qp.data) {
4533
+ try {
4534
+ const parsed = JSON.parse(qp.data);
4535
+ triggerName =
4536
+ parsed?.TriggerName?.trim() ||
4537
+ parsed?.triggerName?.trim() ||
4538
+ "";
4539
+ }
4540
+ catch {
4541
+ // Ignore invalid JSON metadata and render as regular queued prompt.
4542
+ }
4543
+ }
4544
+ const isTriggerQueuedPrompt = !qp.sourceAgentName && triggerName.length > 0;
4545
+ const isTriggerExpanded = !!expandedQueuedTriggerIds[qp.id];
4546
+ if (isTriggerQueuedPrompt) {
4547
+ return (_jsxs("div", { className: "text-[11px]", "data-testid": "queued-prompt-item", children: [_jsxs("button", { type: "button", onClick: () => setExpandedQueuedTriggerIds((prev) => ({
4548
+ ...prev,
4549
+ [qp.id]: !prev[qp.id],
4550
+ })), className: "flex w-full items-center gap-1.5 rounded px-1 py-0.5 text-left text-amber-800 transition-colors hover:bg-amber-100/60", "data-testid": "queued-trigger-toggle", "data-expanded": isTriggerExpanded ? "true" : "false", children: [_jsx(Target, { className: "h-3 w-3 shrink-0 text-amber-500", strokeWidth: 2 }), _jsx("span", { className: "truncate font-medium", children: triggerName }), qp.createdDate && (_jsx("span", { className: "ml-1 shrink-0 text-[10px] text-amber-500", children: formatTime(new Date(qp.createdDate)) })), _jsx("span", { className: "ml-auto shrink-0 text-amber-400", children: isTriggerExpanded ? (_jsx(ChevronUp, { className: "h-3 w-3" })) : (_jsx(ChevronDown, { className: "h-3 w-3" })) })] }), isTriggerExpanded && (_jsx("div", { className: "mt-0.5 border-l-2 border-amber-200 pl-5 text-[11px] text-amber-700/80", children: qp.prompt }))] }, qp.id));
4551
+ }
4552
+ return (_jsx("div", { className: "rounded-md border border-amber-200 bg-white p-2.5 text-[11px]", "data-testid": "queued-prompt-item", 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: "wrap-break-word whitespace-pre-wrap text-gray-600", "data-testid": "queued-prompt-text", children: qp.prompt }), _jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] text-gray-400", children: [qp.createdDate && (_jsxs("span", { children: ["Queued ", formatTime(new Date(qp.createdDate))] })), qp.scheduledFor &&
4553
+ new Date(qp.scheduledFor).getTime() >
4554
+ new Date(qp.createdDate || 0).getTime() +
4555
+ 1000 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-gray-300", children: "\u2022" }), _jsxs("span", { className: "font-medium text-amber-600", children: ["Scheduled for", " ", new Date(qp.scheduledFor).toDateString() ===
4556
+ new Date().toDateString()
4557
+ ? formatTime(new Date(qp.scheduledFor))
4558
+ : formatDateTime(new Date(qp.scheduledFor))] })] }))] })] }) }) }, qp.id));
4559
+ }) })] }) })), activeInlineDialog &&
4483
4560
  (() => {
4484
4561
  // Look up dialog component from config
4485
4562
  const dialogRegistration = editContext?.configuration?.editor?.agentDialogs?.find((d) => d.dialogType === activeInlineDialog.request.dialogType);
@@ -4684,13 +4761,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4684
4761
  }
4685
4762
  } })] })) : null, _jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center gap-1 text-[11px] font-medium text-gray-700", children: [_jsx(Target, { className: "h-3 w-3", strokeWidth: 1 }), "Skills"] }), _jsx(Input, { value: skillSearchTerm, onChange: (e) => setSkillSearchTerm(e.target.value), placeholder: "Search skills...", className: "mb-2 h-6 px-2 text-[10px]" }), selectedSkillIds.length > 0 && (_jsx("div", { className: "mb-2 flex flex-wrap gap-1", children: selectedSkillIds.map((skillId) => {
4686
4763
  const skill = selectedSkills.find((s) => s.id === skillId);
4687
- return (_jsxs("button", { type: "button", className: "inline-flex items-center gap-1 rounded-full border border-gray-200 bg-gray-100 px-1.5 py-0.5 text-[10px] text-gray-700 hover:bg-gray-200", onClick: () => {
4688
- if (backendAssignedSkillSet.has(skillId.toLowerCase()))
4689
- return;
4690
- void handleRemoveSkill(skillId);
4691
- }, disabled: backendAssignedSkillSet.has(skillId.toLowerCase()), title: backendAssignedSkillSet.has(skillId.toLowerCase())
4692
- ? "Assigned by backend profile"
4693
- : "Remove skill", children: [_jsx("span", { children: skill?.name || skillId }), backendAssignedSkillSet.has(skillId.toLowerCase()) ? (_jsx("span", { className: "text-[9px] text-gray-500", children: "auto" })) : (_jsx(X, { className: "h-2.5 w-2.5", strokeWidth: 1 }))] }, skillId));
4764
+ return (_jsxs("div", { className: "inline-flex items-center gap-1 rounded-full border border-gray-200 bg-gray-100 px-1.5 py-0.5 text-[10px] text-gray-700", children: [_jsx("span", { children: skill?.name || skillId }), _jsx("button", { type: "button", className: "rounded p-0.5 text-gray-500 hover:bg-gray-200 hover:text-gray-700", title: "Open skill item", "aria-label": `Open ${skill?.name || skillId}`, onClick: () => {
4765
+ void handleOpenSkillItem(skillId);
4766
+ }, children: _jsx(ExternalLink, { className: "h-2.5 w-2.5", strokeWidth: 1.5 }) }), backendAssignedSkillSet.has(skillId.toLowerCase()) ? (_jsx("span", { className: "text-[9px] text-gray-500", children: "auto" })) : (_jsx("button", { type: "button", className: "rounded p-0.5 text-gray-500 hover:bg-gray-200 hover:text-gray-700", onClick: () => {
4767
+ void handleRemoveSkill(skillId);
4768
+ }, title: "Remove skill", "aria-label": `Remove ${skill?.name || skillId}`, children: _jsx(X, { className: "h-2.5 w-2.5", strokeWidth: 1 }) }))] }, skillId));
4694
4769
  }) })), _jsx("div", { className: "max-h-40 space-y-1 overflow-y-auto rounded border border-gray-200 bg-gray-50 p-1.5", children: skillsLoading ? (_jsx("div", { className: "px-1 text-[10px] text-gray-500", children: "Loading skills..." })) : filteredSelectableSkills.length > 0 ? (filteredSelectableSkills.map((skill) => (_jsxs("button", { type: "button", className: "flex w-full items-start gap-1 rounded px-1.5 py-1 text-left text-[10px] text-gray-700 hover:bg-gray-100", onClick: () => {
4695
4770
  void handleAddSkill(skill.id);
4696
4771
  setSkillSearchTerm("");
@@ -4698,7 +4773,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4698
4773
  ? selectedSkillIds.length > 0
4699
4774
  ? "All allowed skills are selected"
4700
4775
  : "No skills available for this profile"
4701
- : "No skills match your search" })) }), !skillsLoading && selectableSkills.length > 0 && (_jsxs("div", { className: "mt-1 text-[10px] text-gray-500", children: ["Showing ", filteredSelectableSkills.length, " of ", selectableSkills.length] })), skillsError && (_jsx("div", { className: "mt-1 text-[10px] text-red-600", children: skillsError }))] })] }) })] }), 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", type: "button", 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-[10px] text-gray-700 hover:bg-gray-100", onClick: () => {
4776
+ : "No skills match your search" })) }), !skillsLoading && selectableSkills.length > 0 && (_jsxs("div", { className: "mt-1 text-[10px] text-gray-500", children: ["Showing ", filteredSelectableSkills.length, " of ", selectableSkills.length] })), skillsError && (_jsx("div", { className: "mt-1 text-[10px] text-red-600", children: skillsError }))] }), _jsxs("div", { children: [_jsx("div", { className: "mb-1 text-[11px] font-medium text-gray-700", children: "Subscribed triggers" }), _jsx("div", { className: "max-h-28 space-y-1 overflow-y-auto rounded border border-gray-200 bg-gray-50 p-1.5", children: triggerSubscriptionsLoading ? (_jsx("div", { className: "px-1 text-[10px] text-gray-500", children: "Loading subscribed triggers..." })) : activeTriggerSubscriptions.length > 0 ? (activeTriggerSubscriptions.map((sub) => {
4777
+ const filterText = (sub.filter || "").trim();
4778
+ return (_jsxs("div", { className: "rounded border border-gray-200 bg-white px-1.5 py-1", children: [_jsx("div", { className: "truncate text-[10px] font-medium text-gray-800", children: sub.triggerName }), filterText.length > 0 && (_jsxs("div", { className: "mt-0.5 line-clamp-2 break-all text-[9px] text-gray-500", children: ["filter: ", filterText] }))] }, sub.id));
4779
+ })) : (_jsx("div", { className: "px-1 text-[10px] text-gray-500", children: "No active trigger subscriptions" })) }), triggerSubscriptionsError && (_jsx("div", { className: "mt-1 text-[10px] text-red-600", children: triggerSubscriptionsError }))] })] }) })] }), 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", type: "button", 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-[10px] text-gray-700 hover:bg-gray-100", onClick: () => {
4702
4780
  setPrompt(p.prompt);
4703
4781
  setShowPredefined(false);
4704
4782
  if (textareaRef.current)