@parhelia/core 0.1.12331 → 0.1.12339

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 (54) hide show
  1. package/dist/editor/ai/AgentTerminal.js +61 -20
  2. package/dist/editor/ai/AgentTerminal.js.map +1 -1
  3. package/dist/editor/ai/ToolCallDisplay.d.ts +5 -0
  4. package/dist/editor/ai/ToolCallDisplay.js +139 -92
  5. package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
  6. package/dist/editor/ai/dialogs/AgentDialogHandler.js +22 -4
  7. package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
  8. package/dist/editor/ai/dialogs/QuestionnaireInline.js +1 -1
  9. package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
  10. package/dist/editor/services/agentService.d.ts +8 -0
  11. package/dist/editor/services/agentService.js +7 -0
  12. package/dist/editor/services/agentService.js.map +1 -1
  13. package/dist/revision.d.ts +2 -2
  14. package/dist/revision.js +2 -2
  15. package/dist/task-board/TaskBoardWorkspace.js +3 -0
  16. package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
  17. package/dist/task-board/components/CreateProjectDialog.js +76 -65
  18. package/dist/task-board/components/CreateProjectDialog.js.map +1 -1
  19. package/dist/task-board/components/CreateTaskDialog.js +1 -0
  20. package/dist/task-board/components/CreateTaskDialog.js.map +1 -1
  21. package/dist/task-board/components/ItemCollectionPicker.js +5 -3
  22. package/dist/task-board/components/ItemCollectionPicker.js.map +1 -1
  23. package/dist/task-board/components/ProjectDashboard.d.ts +1 -0
  24. package/dist/task-board/components/ProjectDashboard.js +6 -2
  25. package/dist/task-board/components/ProjectDashboard.js.map +1 -1
  26. package/dist/task-board/components/ProjectSettingsDialog.js +7 -0
  27. package/dist/task-board/components/ProjectSettingsDialog.js.map +1 -1
  28. package/dist/task-board/components/TaskAttachmentsSection.d.ts +7 -0
  29. package/dist/task-board/components/TaskAttachmentsSection.js +137 -0
  30. package/dist/task-board/components/TaskAttachmentsSection.js.map +1 -0
  31. package/dist/task-board/components/TaskDetailPanel.js +6 -123
  32. package/dist/task-board/components/TaskDetailPanel.js.map +1 -1
  33. package/dist/task-board/components/TaskReviewActions.d.ts +1 -1
  34. package/dist/task-board/components/TaskReviewActions.js +2 -2
  35. package/dist/task-board/components/TaskReviewActions.js.map +1 -1
  36. package/dist/task-board/components/WizardCommunicationShared.js +11 -5
  37. package/dist/task-board/components/WizardCommunicationShared.js.map +1 -1
  38. package/dist/task-board/components/WizardTaskDetailsPanel.js +4 -2
  39. package/dist/task-board/components/WizardTaskDetailsPanel.js.map +1 -1
  40. package/dist/task-board/services/taskService.d.ts +3 -1
  41. package/dist/task-board/services/taskService.js +3 -0
  42. package/dist/task-board/services/taskService.js.map +1 -1
  43. package/dist/task-board/taskExecutionStatus.js +12 -1
  44. package/dist/task-board/taskExecutionStatus.js.map +1 -1
  45. package/dist/task-board/taskStatus.js +3 -0
  46. package/dist/task-board/taskStatus.js.map +1 -1
  47. package/dist/task-board/types.d.ts +15 -3
  48. package/dist/task-board/views/KanbanView.js +2 -1
  49. package/dist/task-board/views/KanbanView.js.map +1 -1
  50. package/dist/task-board/views/ListView.js +1 -0
  51. package/dist/task-board/views/ListView.js.map +1 -1
  52. package/dist/task-board/views/WizardView.js +38 -33
  53. package/dist/task-board/views/WizardView.js.map +1 -1
  54. package/package.json +1 -1
@@ -54,6 +54,10 @@ function buildPlaceholderAgentDetails(agentStub) {
54
54
  function normalizeDialogAgentId(value) {
55
55
  return value?.trim().toLowerCase() || "";
56
56
  }
57
+ function getVisibleDialogRegistry() {
58
+ const registry = globalThis.__agentDialogVisibleCallbacks;
59
+ return registry && typeof registry === "object" ? registry : {};
60
+ }
57
61
  // Simple user message component
58
62
  const UserMessage = ({ message }) => {
59
63
  const content = message.content || "";
@@ -731,6 +735,21 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
731
735
  const orphanTimeoutRef = useRef(null);
732
736
  useEffect(() => {
733
737
  activeInlineDialogRef.current = activeInlineDialog;
738
+ const visibleRegistry = { ...getVisibleDialogRegistry() };
739
+ const callbackId = activeInlineDialog?.request.callbackId || null;
740
+ const agentKeys = [
741
+ normalizeDialogAgentId(agentStubIdRefForDialogs.current),
742
+ normalizeDialogAgentId(agentIdRefForDialogs.current),
743
+ ].filter(Boolean);
744
+ agentKeys.forEach((key) => {
745
+ if (callbackId) {
746
+ visibleRegistry[key] = callbackId;
747
+ }
748
+ else {
749
+ delete visibleRegistry[key];
750
+ }
751
+ });
752
+ globalThis.__agentDialogVisibleCallbacks = visibleRegistry;
734
753
  }, [activeInlineDialog]);
735
754
  useEffect(() => {
736
755
  onQuestionnaireOpenChange?.(isQuestionnaireDialogOpen);
@@ -819,6 +838,19 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
819
838
  const [showPredefined, setShowPredefined] = useState(false);
820
839
  const [activeProfile, setActiveProfile] = useState(undefined);
821
840
  const [selectedModelId, setSelectedModelId] = useState(undefined);
841
+ const normalizeAgentMode = (value) => {
842
+ if (value === "autonomous" ||
843
+ value === "read-only" ||
844
+ value === "supervised") {
845
+ return value;
846
+ }
847
+ // Backend task/spawned agents persist raw "agent", which behaves like
848
+ // autonomous in the frontend's current 3-mode model.
849
+ if (value === "agent") {
850
+ return "autonomous";
851
+ }
852
+ return null;
853
+ };
822
854
  const [mode, setMode] = useState("supervised");
823
855
  const [queuedPrompts, setQueuedPrompts] = useState([]);
824
856
  const [expandedQueuedTriggerIds, setExpandedQueuedTriggerIds] = useState({});
@@ -3237,6 +3269,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
3237
3269
  useEffect(() => {
3238
3270
  const prevId = agentStubIdRefForDialogs.current;
3239
3271
  agentStubIdRefForDialogs.current = agentStub.id;
3272
+ const visibleRegistry = { ...getVisibleDialogRegistry() };
3273
+ const normalizedPrevId = normalizeDialogAgentId(prevId);
3274
+ if (normalizedPrevId) {
3275
+ delete visibleRegistry[normalizedPrevId];
3276
+ globalThis.__agentDialogVisibleCallbacks = visibleRegistry;
3277
+ }
3240
3278
  if (prevId && prevId !== agentStub.id) {
3241
3279
  const orphanedDialog = activeInlineDialogRef.current;
3242
3280
  if (orphanedDialog) {
@@ -3318,6 +3356,13 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
3318
3356
  return () => {
3319
3357
  const mounted = (globalThis.__agentDialogMountedAgents ?? []).filter((x) => typeof x === "string");
3320
3358
  globalThis.__agentDialogMountedAgents = mounted.filter((id) => id !== normalizeDialogAgentId(agentStubIdRefForDialogs.current));
3359
+ const visibleRegistry = { ...getVisibleDialogRegistry() };
3360
+ const idsToClear = [
3361
+ normalizeDialogAgentId(agentStubIdRefForDialogs.current),
3362
+ normalizeDialogAgentId(agentIdRefForDialogs.current),
3363
+ ].filter(Boolean);
3364
+ idsToClear.forEach((id) => delete visibleRegistry[id]);
3365
+ globalThis.__agentDialogVisibleCallbacks = visibleRegistry;
3321
3366
  // If unmounting with an active dialog, defer the orphan event so that
3322
3367
  // React strict mode remounts can cancel it. Only real unmounts fire.
3323
3368
  const orphanedDialog = activeInlineDialogRef.current;
@@ -3405,20 +3450,16 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
3405
3450
  // Initialize mode from metadata; fall back to agent.Mode from server
3406
3451
  useEffect(() => {
3407
3452
  try {
3408
- const metaMode = agentMetadata?.mode;
3409
- if (metaMode === "autonomous" ||
3410
- metaMode === "read-only" ||
3411
- metaMode === "supervised") {
3453
+ const metaMode = normalizeAgentMode(agentMetadata?.mode);
3454
+ if (metaMode) {
3412
3455
  setMode(metaMode);
3413
3456
  return;
3414
3457
  }
3415
3458
  }
3416
3459
  catch { }
3417
3460
  try {
3418
- const serverMode = agent?.mode;
3419
- if (serverMode === "autonomous" ||
3420
- serverMode === "read-only" ||
3421
- serverMode === "supervised") {
3461
+ const serverMode = normalizeAgentMode(agent?.mode);
3462
+ if (serverMode) {
3422
3463
  setMode(serverMode);
3423
3464
  }
3424
3465
  }
@@ -4362,6 +4403,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4362
4403
  isConnecting ||
4363
4404
  isWaitingForResponse ||
4364
4405
  hasActiveStreaming();
4406
+ const showInitialThinkingSplash = messages.length === 0 && !error && hideGreeting && (isSubmitting || isConnecting);
4365
4407
  // Compute dots visibility: only show BEFORE any assistant message exists
4366
4408
  // This prevents duplicate headers - the dots indicator has its own header,
4367
4409
  // and we don't want to show a second header below existing messages
@@ -4376,6 +4418,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4376
4418
  // The message with the pending approval will display its own UI for approval
4377
4419
  if (allPendingApprovals.length > 0)
4378
4420
  return false;
4421
+ // The hidden-greeting startup splash already renders its own bouncing dots.
4422
+ // Suppress the generic indicator so reopening/running terminals don't show two.
4423
+ if (showInitialThinkingSplash)
4424
+ return false;
4379
4425
  // IMPORTANT: If the last message is an assistant message and we're still executing,
4380
4426
  // the AiResponseMessage for that message will show its own activity indicator.
4381
4427
  // We only want these global thinking dots if the last message was from the user
@@ -4398,6 +4444,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4398
4444
  messages,
4399
4445
  activeInlineDialog,
4400
4446
  allPendingApprovals,
4447
+ showInitialThinkingSplash,
4401
4448
  ]);
4402
4449
  // Move useMemo hook before early return to comply with Rules of Hooks
4403
4450
  const isLiveEditorContextMode = React.useMemo(() => {
@@ -4524,10 +4571,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4524
4571
  const summaryOperations = latestSummaryAssistantGroup
4525
4572
  ? getOperationsForMessageGroup(summaryMessages, agentOperations)
4526
4573
  : [];
4527
- return (_jsxs("div", { className: `flex h-full min-h-0 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 &&
4528
- !error &&
4529
- hideGreeting &&
4530
- (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: {
4574
+ return (_jsxs("div", { className: `flex h-full min-h-0 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 })] })] }) })), 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: {
4531
4575
  __html: activeProfile.svgIcon,
4532
4576
  } })) : (_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" })] })] }) })), 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, error: error || undefined, defaultCollapseJson: defaultCollapseJson, profileSvgIcon: activeProfile?.svgIcon, agentId: agent?.id || agentStub.id, agentName: activeProfile?.agentName ||
4533
4577
  activeProfile?.displayTitle ||
@@ -4652,10 +4696,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4652
4696
  handleSubmit();
4653
4697
  }
4654
4698
  }, 0);
4655
- } })) })), messages.length === 0 &&
4656
- !error &&
4657
- hideGreeting &&
4658
- (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: {
4699
+ } })) })), 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: {
4659
4700
  __html: activeProfile.svgIcon,
4660
4701
  } })) : (_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" })] })] }) })), renderErrorBanner(), _jsxs("div", { className: "space-y-0 divide-y divide-gray-100 select-text", children: [(() => {
4661
4702
  const groups = groupConsecutiveMessages(messages);
@@ -5044,10 +5085,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
5044
5085
  }, 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: () => {
5045
5086
  void handleRemoveSkill(skillId);
5046
5087
  }, title: "Remove skill", "aria-label": `Remove ${skill?.name || skillId}`, children: _jsx(X, { className: "h-2.5 w-2.5", strokeWidth: 1 }) }))] }, skillId));
5047
- }) }))] }), _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) => {
5048
- const filterText = (sub.filter || "").trim();
5049
- 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 text-[9px] break-all text-gray-500", children: ["filter: ", filterText] }))] }, sub.id));
5050
- })) : (_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: () => {
5088
+ }) }))] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 px-0.5 text-[11px] font-medium text-gray-700", children: "Subscribed triggers" }), _jsx("div", { className: "max-h-28 overflow-y-auto rounded border border-gray-100 bg-gray-50/50 p-1", children: triggerSubscriptionsLoading ? (_jsx("div", { className: "px-1 text-[10px] text-gray-500", children: "Loading subscribed triggers..." })) : activeTriggerSubscriptions.length > 0 ? (_jsx("div", { className: "space-y-0.5", children: activeTriggerSubscriptions.map((sub) => {
5089
+ const filterText = (sub.filter || "").trim();
5090
+ return (_jsxs("div", { className: "flex items-baseline gap-1.5 rounded px-1 py-0.5 hover:bg-white/60 transition-colors", children: [_jsx("div", { className: "shrink-0 text-[10px] font-medium text-gray-700", children: sub.triggerName }), filterText.length > 0 && (_jsx("div", { className: "truncate text-[9px] text-gray-400", title: filterText, children: filterText }))] }, sub.id));
5091
+ }) })) : (_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: () => {
5051
5092
  setPrompt(p.prompt);
5052
5093
  setShowPredefined(false);
5053
5094
  if (textareaRef.current)