@parhelia/core 0.4.12818 → 0.4.12825
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/config/config.js +3 -0
- package/dist/config/config.js.map +1 -1
- package/dist/editor/ai/AgentStatusBadge.js +11 -9
- package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
- package/dist/editor/ai/Agents.js +2 -2
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/agentDiagnostics.d.ts +1 -1
- package/dist/editor/ai/agentDiagnostics.js +8 -0
- package/dist/editor/ai/agentDiagnostics.js.map +1 -1
- package/dist/editor/ai/terminal/agentSessionSnapshot.d.ts +15 -0
- package/dist/editor/ai/terminal/agentSessionSnapshot.js +103 -3
- package/dist/editor/ai/terminal/agentSessionSnapshot.js.map +1 -1
- package/dist/editor/ai/terminal/agentSessionState.js +5 -1
- package/dist/editor/ai/terminal/agentSessionState.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentActivityOverviewPanel.js +5 -5
- package/dist/editor/ai/terminal/components/AgentActivityOverviewPanel.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSkillSettingsSection.js +2 -2
- package/dist/editor/ai/terminal/components/AgentSkillSettingsSection.js.map +1 -1
- package/dist/editor/ai/terminal/components/AiResponseMessage.js +8 -7
- package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/terminal/components/ContextInfoBar.js +1 -1
- package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentEditorContext.js +13 -3
- package/dist/editor/ai/terminal/useAgentEditorContext.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentOperationHistoryLoader.js +5 -1
- package/dist/editor/ai/terminal/useAgentOperationHistoryLoader.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentOperationSocketHandler.js +33 -1
- package/dist/editor/ai/terminal/useAgentOperationSocketHandler.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentServerReconciler.js +11 -0
- package/dist/editor/ai/terminal/useAgentServerReconciler.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +1 -0
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +6 -2
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentTerminalController.js +4 -0
- package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
- package/dist/editor/bridge/protocol.d.ts +5 -0
- package/dist/editor/bridge/protocol.js.map +1 -1
- package/dist/editor/client/EditorShell.js +4 -3
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +3 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/operations.js +34 -2
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/commands/commands.d.ts +6 -0
- package/dist/editor/commands/commands.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +10 -1
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +8 -2
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/useFormFieldCaretPresence.js +1 -0
- package/dist/editor/field-types/useFormFieldCaretPresence.js.map +1 -1
- package/dist/editor/find-replace/FindReplacePanel.d.ts +11 -0
- package/dist/editor/find-replace/FindReplacePanel.js +311 -0
- package/dist/editor/find-replace/FindReplacePanel.js.map +1 -0
- package/dist/editor/find-replace/findReplaceCommand.d.ts +8 -0
- package/dist/editor/find-replace/findReplaceCommand.js +25 -0
- package/dist/editor/find-replace/findReplaceCommand.js.map +1 -0
- package/dist/editor/find-replace/findReplaceMatches.d.ts +42 -0
- package/dist/editor/find-replace/findReplaceMatches.js +66 -0
- package/dist/editor/find-replace/findReplaceMatches.js.map +1 -0
- package/dist/editor/find-replace/findReplaceStore.d.ts +30 -0
- package/dist/editor/find-replace/findReplaceStore.js +61 -0
- package/dist/editor/find-replace/findReplaceStore.js.map +1 -0
- package/dist/editor/find-replace/findReplaceTargets.d.ts +49 -0
- package/dist/editor/find-replace/findReplaceTargets.js +110 -0
- package/dist/editor/find-replace/findReplaceTargets.js.map +1 -0
- package/dist/editor/find-replace/findReplaceText.d.ts +50 -0
- package/dist/editor/find-replace/findReplaceText.js +189 -0
- package/dist/editor/find-replace/findReplaceText.js.map +1 -0
- package/dist/editor/menubar/ActiveUsers.js +1 -1
- package/dist/editor/menubar/ActiveUsers.js.map +1 -1
- package/dist/editor/menubar/ToolbarFactory.js +9 -1
- package/dist/editor/menubar/ToolbarFactory.js.map +1 -1
- package/dist/editor/menubar/VersionSelector.js +2 -2
- package/dist/editor/menubar/VersionSelector.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/FindReplaceControls.d.ts +6 -0
- package/dist/editor/menubar/toolbar-sections/FindReplaceControls.js +31 -0
- package/dist/editor/menubar/toolbar-sections/FindReplaceControls.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/index.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/index.js +1 -0
- package/dist/editor/menubar/toolbar-sections/index.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js +8 -4
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FindReplaceHighlightings.d.ts +11 -0
- package/dist/editor/page-editor-chrome/FindReplaceHighlightings.js +117 -0
- package/dist/editor/page-editor-chrome/FindReplaceHighlightings.js.map +1 -0
- package/dist/editor/page-editor-chrome/PageEditorChrome.js +2 -1
- package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +8 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
- package/dist/editor/page-viewer/MiniMap.d.ts +6 -2
- package/dist/editor/page-viewer/MiniMap.js +139 -21
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +21 -5
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/bridgeKeyboardShortcuts.d.ts +6 -0
- package/dist/editor/page-viewer/bridgeKeyboardShortcuts.js +19 -1
- package/dist/editor/page-viewer/bridgeKeyboardShortcuts.js.map +1 -1
- package/dist/editor/page-viewer/minimapViewport.d.ts +2 -0
- package/dist/editor/page-viewer/minimapViewport.js +31 -0
- package/dist/editor/page-viewer/minimapViewport.js.map +1 -0
- package/dist/editor/reviews/CommentEditor.js +34 -29
- package/dist/editor/reviews/CommentEditor.js.map +1 -1
- package/dist/editor/reviews/CommentImageAttachments.d.ts +12 -0
- package/dist/editor/reviews/CommentImageAttachments.js +19 -0
- package/dist/editor/reviews/CommentImageAttachments.js.map +1 -0
- package/dist/editor/reviews/SuggestionDisplayPopover.d.ts +3 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +7 -2
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/commentAgentAttachments.d.ts +5 -0
- package/dist/editor/reviews/commentAgentAttachments.js +51 -0
- package/dist/editor/reviews/commentAgentAttachments.js.map +1 -0
- package/dist/editor/reviews/commentAi.d.ts +4 -2
- package/dist/editor/reviews/commentAi.js +19 -12
- package/dist/editor/reviews/commentAi.js.map +1 -1
- package/dist/editor/reviews/useCommentImagePaste.d.ts +41 -14
- package/dist/editor/reviews/useCommentImagePaste.js +102 -63
- package/dist/editor/reviews/useCommentImagePaste.js.map +1 -1
- package/dist/editor/services/agentStatus.d.ts +1 -0
- package/dist/editor/services/agentStatus.js +14 -0
- package/dist/editor/services/agentStatus.js.map +1 -1
- package/dist/editor/settings/index/RecentBatchesList.js +2 -1
- package/dist/editor/settings/index/RecentBatchesList.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +6 -3
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/OperationItem.js +2 -1
- package/dist/editor/sidebar/OperationItem.js.map +1 -1
- package/dist/editor/sidebar/liveComponentThumbnails.d.ts +6 -2
- package/dist/editor/sidebar/liveComponentThumbnails.js +7 -2
- package/dist/editor/sidebar/liveComponentThumbnails.js.map +1 -1
- package/dist/editor/ui/ParheliaMark.d.ts +15 -0
- package/dist/editor/ui/ParheliaMark.js +12 -0
- package/dist/editor/ui/ParheliaMark.js.map +1 -0
- package/dist/editor/undoEligibility.d.ts +2 -0
- package/dist/editor/undoEligibility.js +8 -0
- package/dist/editor/undoEligibility.js.map +1 -0
- package/dist/editor/utils/keyboardNavigation.js +16 -0
- package/dist/editor/utils/keyboardNavigation.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +7 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/ModernSplashScreen.js +4 -3
- package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +3 -3
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/task-board/TaskBoardWorkspace.js +179 -33
- package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
- package/dist/task-board/components/AttentionPromptDialog.d.ts +13 -0
- package/dist/task-board/components/AttentionPromptDialog.js +45 -0
- package/dist/task-board/components/AttentionPromptDialog.js.map +1 -0
- package/dist/task-board/components/GoalDataView.d.ts +22 -1
- package/dist/task-board/components/GoalDataView.js +63 -17
- package/dist/task-board/components/GoalDataView.js.map +1 -1
- package/dist/task-board/components/GoalFindingsTable.d.ts +43 -0
- package/dist/task-board/components/GoalFindingsTable.js +160 -0
- package/dist/task-board/components/GoalFindingsTable.js.map +1 -0
- package/dist/task-board/components/GoalsMatrix.js +33 -6
- package/dist/task-board/components/GoalsMatrix.js.map +1 -1
- package/dist/task-board/components/IssuePanel.d.ts +31 -0
- package/dist/task-board/components/IssuePanel.js +268 -0
- package/dist/task-board/components/IssuePanel.js.map +1 -0
- package/dist/task-board/components/ProjectGoalsPanel.js +66 -13
- package/dist/task-board/components/ProjectGoalsPanel.js.map +1 -1
- package/dist/task-board/components/SubgoalFindings.d.ts +40 -0
- package/dist/task-board/components/SubgoalFindings.js +88 -0
- package/dist/task-board/components/SubgoalFindings.js.map +1 -0
- package/dist/task-board/components/TaskAgentPanel.d.ts +2 -0
- package/dist/task-board/components/TaskAgentPanel.js +5 -4
- package/dist/task-board/components/TaskAgentPanel.js.map +1 -1
- package/dist/task-board/components/TaskDetailPanel.js +8 -12
- package/dist/task-board/components/TaskDetailPanel.js.map +1 -1
- package/dist/task-board/components/WizardCommunicationCenter.d.ts +2 -0
- package/dist/task-board/components/WizardCommunicationCenter.js +5 -3
- package/dist/task-board/components/WizardCommunicationCenter.js.map +1 -1
- package/dist/task-board/components/WizardCommunicationShared.js +2 -1
- package/dist/task-board/components/WizardCommunicationShared.js.map +1 -1
- package/dist/task-board/components/WizardTask.d.ts +2 -0
- package/dist/task-board/components/WizardTask.js +2 -2
- package/dist/task-board/components/WizardTask.js.map +1 -1
- package/dist/task-board/components/WizardTaskDetailsPanel.d.ts +4 -0
- package/dist/task-board/components/WizardTaskDetailsPanel.js +16 -3
- package/dist/task-board/components/WizardTaskDetailsPanel.js.map +1 -1
- package/dist/task-board/services/issueService.d.ts +193 -0
- package/dist/task-board/services/issueService.js +97 -0
- package/dist/task-board/services/issueService.js.map +1 -0
- package/dist/task-board/types.d.ts +24 -0
- package/dist/task-board/utils/projectDashboardModel.js +8 -0
- package/dist/task-board/utils/projectDashboardModel.js.map +1 -1
- package/package.json +1 -1
- package/styles.css +57 -3
|
@@ -34,6 +34,8 @@ import { normalizeTaskStatus } from "./taskStatus";
|
|
|
34
34
|
import { getTaskExecutionDisplay, } from "./taskExecutionStatus";
|
|
35
35
|
import { indexTaskExecutionRecords, overlayTaskExecutionList, taskExecutionRecordsEqual, } from "./taskExecutionRecords";
|
|
36
36
|
import { WizardCommunicationCenter } from "./components/WizardCommunicationCenter";
|
|
37
|
+
import { AttentionPromptDialog } from "./components/AttentionPromptDialog";
|
|
38
|
+
import { listAttentionTasks } from "./utils/projectDashboardModel";
|
|
37
39
|
import { Loader2 } from "lucide-react";
|
|
38
40
|
import { MainContentTree } from "../editor/sidebar/MainContentTree";
|
|
39
41
|
import { useTaskBoardAgentPanelState } from "./useTaskBoardAgentPanelState";
|
|
@@ -54,6 +56,12 @@ const TASKBOARD_PROJECT_QUERY_KEY = "tbProjectId";
|
|
|
54
56
|
const TASKBOARD_TASK_QUERY_KEY = "tbTaskId";
|
|
55
57
|
const TASKBOARD_VIEW_QUERY_KEY = "tbView";
|
|
56
58
|
const WS_REFRESH_DELAY_MS = 500;
|
|
59
|
+
const ATTENTION_PROMPT_DELAY_MS = 250;
|
|
60
|
+
// Pause after the user handles an action before the panel moves on to the
|
|
61
|
+
// next task that needs them, so the confirmation (approved, answered) is seen.
|
|
62
|
+
const WIZARD_AUTO_ADVANCE_DELAY_MS = 2000;
|
|
63
|
+
/** Retry delays when goal issue counts come back flagged as inconsistent. */
|
|
64
|
+
const GOAL_CONSISTENCY_BACKOFF_MS = [500, 1000, 2000];
|
|
57
65
|
const TASKBOARD_VIEW_TAB_IDS = [
|
|
58
66
|
"overview",
|
|
59
67
|
"kanban",
|
|
@@ -283,7 +291,15 @@ export function TaskBoardWorkspace() {
|
|
|
283
291
|
const directSubprojectIdsRef = useRef(new Set());
|
|
284
292
|
const tasksRef = useRef([]);
|
|
285
293
|
const previousTaskStatusesRef = useRef({});
|
|
286
|
-
const
|
|
294
|
+
const previousAttentionSnapshotRef = useRef(null);
|
|
295
|
+
const wizardDisplayedTaskIdRef = useRef(null);
|
|
296
|
+
const selectedTaskSourceRef = useRef(null);
|
|
297
|
+
const wizardDisplayedNeedsAttentionRef = useRef(false);
|
|
298
|
+
const previousDisplayedAttentionRef = useRef(null);
|
|
299
|
+
const autoAdvanceTimeoutRef = useRef(null);
|
|
300
|
+
const findNextAttentionTaskIdRef = useRef(() => null);
|
|
301
|
+
const [autoAdvancePending, setAutoAdvancePending] = useState(false);
|
|
302
|
+
const [attentionPromptTaskIds, setAttentionPromptTaskIds] = useState([]);
|
|
287
303
|
const autoSelectedProjectIdsRef = useRef(new Set());
|
|
288
304
|
const syncTaskBoardStateFromUrl = useCallback(() => {
|
|
289
305
|
const nextState = getTaskBoardStateFromUrl();
|
|
@@ -682,38 +698,80 @@ export function TaskBoardWorkspace() {
|
|
|
682
698
|
return;
|
|
683
699
|
setWizardApprovedTaskId(null);
|
|
684
700
|
}, [wizardApprovedTaskId, wizardDisplayedTask?.taskId]);
|
|
701
|
+
wizardDisplayedTaskIdRef.current = wizardDisplayedTask?.taskId ?? null;
|
|
702
|
+
selectedTaskSourceRef.current = selectedTaskSource;
|
|
703
|
+
const wizardDisplayedNeedsAttention = !!wizardDisplayedTask &&
|
|
704
|
+
(Boolean(wizardDisplayedExecutionDisplay?.needsAttention) ||
|
|
705
|
+
normalizeTaskStatus(wizardDisplayedTask.status, wizardDisplayedTask.executionState) === "Review");
|
|
706
|
+
wizardDisplayedNeedsAttentionRef.current = wizardDisplayedNeedsAttention;
|
|
707
|
+
// Dashboard attention prompt: open a semi-modal dialog when a task the user
|
|
708
|
+
// already saw newly needs them. Only transitions count, so opening the board
|
|
709
|
+
// with pending approvals, late-loading subproject lists, or re-renders never
|
|
710
|
+
// prompt. The check is deferred a tick so the panel's own auto-select can
|
|
711
|
+
// claim the task first; a task that is already displayed is not prompted.
|
|
685
712
|
useEffect(() => {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
selectedTaskSource,
|
|
689
|
-
wizardPinnedTaskId,
|
|
690
|
-
wizardForceOverview,
|
|
691
|
-
attentionTaskId: wizardAttentionState.task?.taskId ?? null,
|
|
692
|
-
attentionAgentId: wizardAttentionState.agentId ?? null,
|
|
693
|
-
summaryState: wizardAttentionState.summaryState,
|
|
694
|
-
totalCount: wizardAttentionState.stats.totalCount,
|
|
695
|
-
completedCount: wizardAttentionState.stats.completedCount,
|
|
696
|
-
approvalCount: wizardAttentionState.stats.approvalCount,
|
|
697
|
-
blockedCount: wizardAttentionState.stats.blockedCount,
|
|
698
|
-
runningCount: wizardAttentionState.stats.runningCount,
|
|
699
|
-
displayedTaskId: wizardDisplayedTask?.taskId ?? null,
|
|
700
|
-
displayedExecutionLabel: wizardDisplayedExecutionDisplay?.label ?? null,
|
|
701
|
-
displayedNeedsAttention: wizardDisplayedExecutionDisplay?.needsAttention ?? null,
|
|
702
|
-
});
|
|
703
|
-
if (previousWizardAttentionSignatureRef.current === attentionSnapshot) {
|
|
713
|
+
if (!isOverviewView || isTasksLoading || subprojectCountsLoading) {
|
|
714
|
+
previousAttentionSnapshotRef.current = null;
|
|
704
715
|
return;
|
|
705
716
|
}
|
|
706
|
-
|
|
717
|
+
const attentionIds = new Set(listAttentionTasks(orderedWizardTasks).map(({ task }) => task.taskId));
|
|
718
|
+
const knownIds = new Set(orderedWizardTasks.map((task) => task.taskId));
|
|
719
|
+
const previous = previousAttentionSnapshotRef.current;
|
|
720
|
+
previousAttentionSnapshotRef.current = { knownIds, attentionIds };
|
|
721
|
+
if (!previous)
|
|
722
|
+
return;
|
|
723
|
+
const arrivedIds = [...attentionIds].filter((taskId) => previous.knownIds.has(taskId) && !previous.attentionIds.has(taskId));
|
|
724
|
+
if (arrivedIds.length === 0)
|
|
725
|
+
return;
|
|
726
|
+
const timeoutId = window.setTimeout(() => {
|
|
727
|
+
const displayedId = wizardDisplayedTaskIdRef.current;
|
|
728
|
+
const promptIds = arrivedIds.filter((taskId) => taskId !== displayedId);
|
|
729
|
+
if (promptIds.length === 0)
|
|
730
|
+
return;
|
|
731
|
+
// One action at a time: while the displayed task itself needs the user,
|
|
732
|
+
// new arrivals just queue up in "Waiting for you" and the panel moves on
|
|
733
|
+
// to them by itself once this one is handled.
|
|
734
|
+
if (wizardDisplayedNeedsAttentionRef.current)
|
|
735
|
+
return;
|
|
736
|
+
// Nothing the user chose to look at is in the way: show the action
|
|
737
|
+
// directly instead of asking first.
|
|
738
|
+
if (selectedTaskSourceRef.current !== "user") {
|
|
739
|
+
setWizardForceOverview(false);
|
|
740
|
+
setTaskSelection(promptIds[0], {
|
|
741
|
+
source: "system",
|
|
742
|
+
pinInWizard: true,
|
|
743
|
+
});
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
setAttentionPromptTaskIds((current) => [
|
|
747
|
+
...current,
|
|
748
|
+
...promptIds.filter((taskId) => !current.includes(taskId)),
|
|
749
|
+
]);
|
|
750
|
+
}, ATTENTION_PROMPT_DELAY_MS);
|
|
751
|
+
return () => window.clearTimeout(timeoutId);
|
|
707
752
|
}, [
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
wizardDisplayedTask?.taskId,
|
|
714
|
-
wizardForceOverview,
|
|
715
|
-
wizardPinnedTaskId,
|
|
753
|
+
isOverviewView,
|
|
754
|
+
isTasksLoading,
|
|
755
|
+
subprojectCountsLoading,
|
|
756
|
+
orderedWizardTasks,
|
|
757
|
+
setTaskSelection,
|
|
716
758
|
]);
|
|
759
|
+
const attentionPromptTasks = useMemo(() => {
|
|
760
|
+
if (attentionPromptTaskIds.length === 0)
|
|
761
|
+
return [];
|
|
762
|
+
const displayedId = wizardDisplayedTask?.taskId ?? null;
|
|
763
|
+
const attentionById = new Map(listAttentionTasks(orderedWizardTasks).map(({ task }) => [
|
|
764
|
+
task.taskId,
|
|
765
|
+
task,
|
|
766
|
+
]));
|
|
767
|
+
return attentionPromptTaskIds
|
|
768
|
+
.filter((taskId) => taskId !== displayedId)
|
|
769
|
+
.map((taskId) => attentionById.get(taskId))
|
|
770
|
+
.filter((task) => Boolean(task));
|
|
771
|
+
}, [attentionPromptTaskIds, orderedWizardTasks, wizardDisplayedTask?.taskId]);
|
|
772
|
+
const dismissAttentionPrompt = useCallback(() => {
|
|
773
|
+
setAttentionPromptTaskIds([]);
|
|
774
|
+
}, []);
|
|
717
775
|
const clearWizardCloseTransitionTimeout = useCallback(() => {
|
|
718
776
|
if (wizardCloseTransitionTimeoutRef.current !== null) {
|
|
719
777
|
window.clearTimeout(wizardCloseTransitionTimeoutRef.current);
|
|
@@ -748,6 +806,61 @@ export function TaskBoardWorkspace() {
|
|
|
748
806
|
}
|
|
749
807
|
return null;
|
|
750
808
|
}, [orderedWizardTasks, wizardExecutionRecordsByTaskId]);
|
|
809
|
+
findNextAttentionTaskIdRef.current = findNextAttentionTaskId;
|
|
810
|
+
// One action at a time: once the displayed task stops needing the user (its
|
|
811
|
+
// tool call was approved, its question answered, it was reviewed), move on to
|
|
812
|
+
// the next task that does, after a short pause so the confirmation is seen.
|
|
813
|
+
const clearAutoAdvance = useCallback(() => {
|
|
814
|
+
if (autoAdvanceTimeoutRef.current !== null) {
|
|
815
|
+
window.clearTimeout(autoAdvanceTimeoutRef.current);
|
|
816
|
+
autoAdvanceTimeoutRef.current = null;
|
|
817
|
+
}
|
|
818
|
+
setAutoAdvancePending(false);
|
|
819
|
+
}, []);
|
|
820
|
+
useEffect(() => {
|
|
821
|
+
const current = wizardDisplayedTask
|
|
822
|
+
? {
|
|
823
|
+
taskId: wizardDisplayedTask.taskId,
|
|
824
|
+
needsAttention: wizardDisplayedNeedsAttention,
|
|
825
|
+
}
|
|
826
|
+
: null;
|
|
827
|
+
const previous = previousDisplayedAttentionRef.current;
|
|
828
|
+
previousDisplayedAttentionRef.current = current;
|
|
829
|
+
if (!current || !previous || previous.taskId !== current.taskId) {
|
|
830
|
+
clearAutoAdvance();
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
if (!isOverviewView)
|
|
834
|
+
return;
|
|
835
|
+
if (!previous.needsAttention || current.needsAttention)
|
|
836
|
+
return;
|
|
837
|
+
if (!findNextAttentionTaskId(current.taskId))
|
|
838
|
+
return;
|
|
839
|
+
clearAutoAdvance();
|
|
840
|
+
const sourceTaskId = current.taskId;
|
|
841
|
+
setAutoAdvancePending(true);
|
|
842
|
+
autoAdvanceTimeoutRef.current = window.setTimeout(() => {
|
|
843
|
+
autoAdvanceTimeoutRef.current = null;
|
|
844
|
+
setAutoAdvancePending(false);
|
|
845
|
+
if (wizardDisplayedTaskIdRef.current !== sourceTaskId)
|
|
846
|
+
return;
|
|
847
|
+
if (wizardDisplayedNeedsAttentionRef.current)
|
|
848
|
+
return;
|
|
849
|
+
const nextTaskId = findNextAttentionTaskIdRef.current(sourceTaskId);
|
|
850
|
+
if (!nextTaskId)
|
|
851
|
+
return;
|
|
852
|
+
setWizardForceOverview(false);
|
|
853
|
+
setTaskSelection(nextTaskId, { source: "system", pinInWizard: true });
|
|
854
|
+
}, WIZARD_AUTO_ADVANCE_DELAY_MS);
|
|
855
|
+
}, [
|
|
856
|
+
clearAutoAdvance,
|
|
857
|
+
findNextAttentionTaskId,
|
|
858
|
+
isOverviewView,
|
|
859
|
+
setTaskSelection,
|
|
860
|
+
wizardDisplayedNeedsAttention,
|
|
861
|
+
wizardDisplayedTask,
|
|
862
|
+
]);
|
|
863
|
+
useEffect(() => clearAutoAdvance, [clearAutoAdvance]);
|
|
751
864
|
// ── data fetching ──
|
|
752
865
|
const refreshProjects = useCallback(async (options) => {
|
|
753
866
|
projectsRequestCountRef.current += 1;
|
|
@@ -884,7 +997,7 @@ export function TaskBoardWorkspace() {
|
|
|
884
997
|
const indexed = indexTaskExecutionRecords(records);
|
|
885
998
|
setExecutionRecordsByTaskId(indexed);
|
|
886
999
|
}, []);
|
|
887
|
-
const refreshGoals = useCallback(async (projectId, includeDescendants) => {
|
|
1000
|
+
const refreshGoals = useCallback(async (projectId, includeDescendants, attempt = 0) => {
|
|
888
1001
|
const generation = ++goalsRequestGenerationRef.current;
|
|
889
1002
|
latestGoalsProjectIdRef.current = projectId;
|
|
890
1003
|
setGoalsLoading(true);
|
|
@@ -905,12 +1018,24 @@ export function TaskBoardWorkspace() {
|
|
|
905
1018
|
toast.error(message);
|
|
906
1019
|
return;
|
|
907
1020
|
}
|
|
908
|
-
|
|
1021
|
+
const goals = result.data?.goals ?? [];
|
|
1022
|
+
setGoals(goals);
|
|
909
1023
|
setGoalCatalog(result.data?.catalog ?? []);
|
|
910
1024
|
setGoalPermissions(result.data?.permissions ?? {});
|
|
911
1025
|
setGoalDisplaySpecs(result.data?.displaySpecs ?? {});
|
|
912
1026
|
setGoalStateScope({ projectId, includeDescendants });
|
|
913
1027
|
setGoalsError(null);
|
|
1028
|
+
// Issue counts read while issues were changing: read again with
|
|
1029
|
+
// bounded backoff (500 ms, 1 s, 2 s); the last result stays flagged
|
|
1030
|
+
// and the goal card says so. A later goal:changed is not relied on.
|
|
1031
|
+
const inconsistent = goals.some((goal) => goal.issueSummaryConsistent === false);
|
|
1032
|
+
if (inconsistent && attempt < GOAL_CONSISTENCY_BACKOFF_MS.length) {
|
|
1033
|
+
window.setTimeout(() => {
|
|
1034
|
+
if (latestGoalsProjectIdRef.current === projectId &&
|
|
1035
|
+
generation === goalsRequestGenerationRef.current)
|
|
1036
|
+
void refreshGoals(projectId, includeDescendants, attempt + 1);
|
|
1037
|
+
}, GOAL_CONSISTENCY_BACKOFF_MS[attempt]);
|
|
1038
|
+
}
|
|
914
1039
|
}
|
|
915
1040
|
finally {
|
|
916
1041
|
if (latestGoalsProjectIdRef.current === projectId &&
|
|
@@ -929,6 +1054,10 @@ export function TaskBoardWorkspace() {
|
|
|
929
1054
|
}
|
|
930
1055
|
};
|
|
931
1056
|
}, [refreshGoals, includeGoalSubprojects]);
|
|
1057
|
+
// Issue revisions and QA state may have changed while the socket was offline.
|
|
1058
|
+
useEffect(() => {
|
|
1059
|
+
refreshGoalsRef.current?.();
|
|
1060
|
+
}, [editContext?.socketConnectionVersion]);
|
|
932
1061
|
// Load goals when the Goals tab or the dashboard is active (and on
|
|
933
1062
|
// project/scope change); the dashboard shows each goal's figures.
|
|
934
1063
|
const needsGoals = isGoalsView || isOverviewView;
|
|
@@ -1777,7 +1906,8 @@ export function TaskBoardWorkspace() {
|
|
|
1777
1906
|
}, [refreshSubprojectTaskCounts]);
|
|
1778
1907
|
useEffect(() => {
|
|
1779
1908
|
previousTaskStatusesRef.current = {};
|
|
1780
|
-
|
|
1909
|
+
previousAttentionSnapshotRef.current = null;
|
|
1910
|
+
setAttentionPromptTaskIds([]);
|
|
1781
1911
|
transitionGoalTaskNavigation({
|
|
1782
1912
|
type: "projectSelected",
|
|
1783
1913
|
projectId: selectedProjectId,
|
|
@@ -2074,6 +2204,9 @@ export function TaskBoardWorkspace() {
|
|
|
2074
2204
|
const wizardNextReviewTaskId = useMemo(() => wizardDisplayedTask
|
|
2075
2205
|
? findNextAttentionTaskId(wizardDisplayedTask.taskId)
|
|
2076
2206
|
: null, [findNextAttentionTaskId, wizardDisplayedTask]);
|
|
2207
|
+
const wizardNextReviewTask = useMemo(() => wizardNextReviewTaskId
|
|
2208
|
+
? (orderedWizardTasks.find((task) => task.taskId === wizardNextReviewTaskId) ?? null)
|
|
2209
|
+
: null, [orderedWizardTasks, wizardNextReviewTaskId]);
|
|
2077
2210
|
const handleReviewNextWizardTask = useCallback(() => {
|
|
2078
2211
|
clearWizardCloseTransitionTimeout();
|
|
2079
2212
|
setWizardApprovedTaskId(null);
|
|
@@ -2115,7 +2248,7 @@ export function TaskBoardWorkspace() {
|
|
|
2115
2248
|
});
|
|
2116
2249
|
}
|
|
2117
2250
|
await refreshVisibleTaskData();
|
|
2118
|
-
}, showApprovedState: wizardDisplayedTask?.taskId === wizardApprovedTaskId, hasNextReviewTask: Boolean(wizardNextReviewTaskId), onReviewNext: handleReviewNextWizardTask, onInteractionSubmitted: () => {
|
|
2251
|
+
}, showApprovedState: wizardDisplayedTask?.taskId === wizardApprovedTaskId, hasNextReviewTask: Boolean(wizardNextReviewTaskId), nextAttentionTask: wizardNextReviewTask, autoAdvancePending: autoAdvancePending, onReviewNext: handleReviewNextWizardTask, onInteractionSubmitted: () => {
|
|
2119
2252
|
handleCloseWizardTask({ advanceToNext: true });
|
|
2120
2253
|
}, onCloseTask: () => handleCloseWizardTask(), onSelectTask: (taskId) => {
|
|
2121
2254
|
clearWizardCloseTransitionTimeout();
|
|
@@ -2141,6 +2274,8 @@ export function TaskBoardWorkspace() {
|
|
|
2141
2274
|
setTaskSelection,
|
|
2142
2275
|
wizardApprovedTaskId,
|
|
2143
2276
|
wizardNextReviewTaskId,
|
|
2277
|
+
wizardNextReviewTask,
|
|
2278
|
+
autoAdvancePending,
|
|
2144
2279
|
]);
|
|
2145
2280
|
const isProjectViewLoading = !!selectedProjectId && projectViewLoadingId === selectedProjectId;
|
|
2146
2281
|
const goalScopeMatches = goalScopesMatch(goalStateScope, {
|
|
@@ -2253,7 +2388,12 @@ export function TaskBoardWorkspace() {
|
|
|
2253
2388
|
return (_jsxs("div", { className: "flex h-full min-h-0 min-w-0 flex-col gap-3", children: [_jsx(ProjectDashboard, { projectId: selectedProjectId, selectedProjectTitle: selectedProject?.project.title ?? "No project selected", selectedProjectDescription: selectedProject?.project.description, selectedProjectCostUsed: selectedProjectCumulativeCostUsed, selectedProjectCostLimit: selectedProject?.project.costLimit ?? null, selectedProjectTaskCounts: selectedProjectTaskCounts, subprojects: directSubprojects, taskCountsByProjectId: subprojectTaskCounts, parentProjectId: parentProject?.project.projectId ?? null, parentProjectTitle: parentProject?.project.title ?? null, onSelectProject: handleSelectProject, canCreateTask: canEditTasks, onCreateTask: () => setCreateDialogOpen(true), showCreateTaskButton: false }), sharedViewSwitcher, _jsx("div", { className: "mt-3 min-h-0 flex-1", children: _jsx(ProjectDashboardView, { projectId: selectedProjectId, projectTitle: selectedProject?.project.title ?? "No project selected", tasks: tasksWithDisplayAssignees, projectTasksLoading: isTasksLoading, dependencies: dependencies, subprojectTaskLists: wizardSubprojectTaskLists, subprojectTasksLoading: subprojectCountsLoading, selectedTaskId: wizardDisplayedTask?.taskId ?? null, onSelectTask: (id) => {
|
|
2254
2389
|
setWizardForceOverview(false);
|
|
2255
2390
|
setTaskSelection(id, { source: "user", pinInWizard: true });
|
|
2256
|
-
}, projectCostUsed: selectedProjectCumulativeCostUsed, projectCostLimit: selectedProject?.project.costLimit ?? null, goals: goalScopeMatches ? goals : [], goalsLoading: goalsLoading || !goalScopeMatches, goalDisplaySpecs: goalScopeMatches ? goalDisplaySpecs : {}, onOpenGoals: () => setActiveTab(getTaskBoardViewTabIndex("goals")), communicationPanel: wizardDisplayedTask ? wizardCommunicationPanel : undefined }) })
|
|
2391
|
+
}, projectCostUsed: selectedProjectCumulativeCostUsed, projectCostLimit: selectedProject?.project.costLimit ?? null, goals: goalScopeMatches ? goals : [], goalsLoading: goalsLoading || !goalScopeMatches, goalDisplaySpecs: goalScopeMatches ? goalDisplaySpecs : {}, onOpenGoals: () => setActiveTab(getTaskBoardViewTabIndex("goals")), communicationPanel: wizardDisplayedTask ? wizardCommunicationPanel : undefined }) }), _jsx(AttentionPromptDialog, { tasks: attentionPromptTasks, onReview: (taskId) => {
|
|
2392
|
+
setAttentionPromptTaskIds([]);
|
|
2393
|
+
clearWizardCloseTransitionTimeout();
|
|
2394
|
+
setWizardForceOverview(false);
|
|
2395
|
+
setTaskSelection(taskId, { source: "user", pinInWizard: true });
|
|
2396
|
+
}, onDismiss: dismissAttentionPrompt })] }));
|
|
2257
2397
|
}
|
|
2258
2398
|
if (isSettingsView) {
|
|
2259
2399
|
return (_jsxs("div", { className: "flex h-full min-h-0 min-w-0 flex-col gap-3", children: [_jsx(ProjectDashboard, { projectId: selectedProjectId, selectedProjectTitle: selectedProject?.project.title ?? "No project selected", selectedProjectDescription: selectedProject?.project.description, selectedProjectCostUsed: selectedProjectCumulativeCostUsed, selectedProjectCostLimit: selectedProject?.project.costLimit ?? null, selectedProjectTaskCounts: selectedProjectTaskCounts, subprojects: directSubprojects, taskCountsByProjectId: subprojectTaskCounts, parentProjectId: parentProject?.project.projectId ?? null, parentProjectTitle: parentProject?.project.title ?? null, onSelectProject: handleSelectProject, canCreateTask: canEditTasks, onCreateTask: () => setCreateDialogOpen(true), showCreateTaskButton: false }), sharedViewSwitcher, _jsx("div", { className: "mt-3", children: _jsx(ProjectSettingsPanel, { projectId: selectedProjectId, selectedProject: selectedProject, projects: projects, canOpenSourceTemplate: isAdministrator, onOpenSourceTemplate: handleOpenSourceTemplate, onDeleteProject: handleDeleteProject, onChanged: async () => {
|
|
@@ -2335,6 +2475,9 @@ export function TaskBoardWorkspace() {
|
|
|
2335
2475
|
wizardSubprojectTaskLists,
|
|
2336
2476
|
wizardDisplayedTask?.taskId,
|
|
2337
2477
|
wizardCommunicationPanel,
|
|
2478
|
+
attentionPromptTasks,
|
|
2479
|
+
dismissAttentionPrompt,
|
|
2480
|
+
clearWizardCloseTransitionTimeout,
|
|
2338
2481
|
setTaskSelection,
|
|
2339
2482
|
refreshProjects,
|
|
2340
2483
|
refreshGoals,
|
|
@@ -2412,6 +2555,8 @@ export function TaskBoardWorkspace() {
|
|
|
2412
2555
|
]);
|
|
2413
2556
|
const agentTerminalPanel = useMemo(() => (_jsx(TaskAgentPanel, { agentId: displayAgentId, mode: agentPanelMode, label: selectedTaskIsPlan ? "Planner" : "Task Agent", taskDetailsContent: taskDetailsPopoverContent ?? undefined, taskDetailsPopoverOpen: isTaskDetailsPopoverOpen, onTaskDetailsPopoverOpenChange: setIsTaskDetailsPopoverOpen, assignedAgentStatus: undefined, onReopenTask: selectedTask && canEditTasks
|
|
2414
2557
|
? () => void handleReopenSelectedTask()
|
|
2558
|
+
: undefined, onClose: selectedTask
|
|
2559
|
+
? () => setTaskSelection(null, { source: "user" })
|
|
2415
2560
|
: undefined })), [
|
|
2416
2561
|
displayAgentId,
|
|
2417
2562
|
agentPanelMode,
|
|
@@ -2421,6 +2566,7 @@ export function TaskBoardWorkspace() {
|
|
|
2421
2566
|
canEditTasks,
|
|
2422
2567
|
selectedTask,
|
|
2423
2568
|
handleReopenSelectedTask,
|
|
2569
|
+
setTaskSelection,
|
|
2424
2570
|
]);
|
|
2425
2571
|
const buildRightHandPanels = useCallback((showAgentColumn) => {
|
|
2426
2572
|
const renderDetailPanel = (collapsedFlag) => (_jsx(TaskDetailPanel, { project: selectedTaskProject, projects: projects, task: selectedTask, allTasks: taskSelectionUniverse, dependencies: dependencies, onTaskChanged: () => {
|