refactor(dashboard,desktop,engine): remove unused imports, props, and locals
Clears the remaining no-unused-vars warnings across the dashboard app and server, desktop main, and engine sources. Dead React state destructures are collapsed to setter-only, unused props are underscore-prefixed to preserve API shape, and unreferenced catch bindings are dropped. No behaviour change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,7 +52,7 @@ import { useRemoteNodeData } from "./hooks/useRemoteNodeData";
|
||||
import { useRemoteNodeEvents } from "./hooks/useRemoteNodeEvents";
|
||||
import { NodeProvider, useNodeContext } from "./context/NodeContext";
|
||||
import type { AiSessionSummary } from "./api";
|
||||
import { fetchAiSession, fetchUnreadCount, reportDashboardPerf } from "./api";
|
||||
import { fetchUnreadCount, reportDashboardPerf } from "./api";
|
||||
import { getScopedItem, setScopedItem } from "./utils/projectStorage";
|
||||
import { subscribeSse } from "./sse-bus";
|
||||
|
||||
@@ -63,7 +63,7 @@ function AppInner() {
|
||||
const isElectron = typeof window !== "undefined" && Boolean((window as Window & { electronAPI?: unknown }).electronAPI);
|
||||
|
||||
// Project management hooks - MUST be called before any conditional logic
|
||||
const { projects, loading: projectsLoading, error: projectsError, refresh: refreshProjects, register: registerProject, update: updateProjectHook, unregister: unregisterProjectHook } = useProjects();
|
||||
const { projects, loading: projectsLoading, refresh: refreshProjects } = useProjects();
|
||||
const { nodes } = useNodes();
|
||||
|
||||
// Node context for local/remote node switching - must be called before useCurrentProject
|
||||
@@ -109,11 +109,10 @@ function AppInner() {
|
||||
|
||||
// Remote node data and events when in remote mode (pass searchQuery for server-side filtering)
|
||||
const remoteData = useRemoteNodeData(currentNodeId, { projectId: currentProject?.id, searchQuery: searchQuery || undefined });
|
||||
const remoteEvents = useRemoteNodeEvents(currentNodeId);
|
||||
|
||||
useRemoteNodeEvents(currentNodeId);
|
||||
|
||||
// Use remote data when in remote mode, local data otherwise
|
||||
const effectiveProjects = isRemote && remoteData.projects.length > 0 ? remoteData.projects : projects;
|
||||
const effectiveTasks = isRemote && remoteData.tasks.length > 0 ? remoteData.tasks : [];
|
||||
|
||||
// Theme management - required before useViewState
|
||||
const { themeMode, colorTheme, setThemeMode, setColorTheme } = useTheme();
|
||||
@@ -131,7 +130,7 @@ function AppInner() {
|
||||
});
|
||||
|
||||
// View state must be defined before useTasks since useTasks depends on taskView for SSE gating
|
||||
const { viewMode, setViewMode, taskView, handleChangeTaskView, handleToggleTheme } = useViewState({
|
||||
const { viewMode, setViewMode, taskView, handleChangeTaskView } = useViewState({
|
||||
projectsLoading,
|
||||
currentProjectLoading,
|
||||
currentProject,
|
||||
@@ -270,7 +269,6 @@ function AppInner() {
|
||||
// Settings state
|
||||
const {
|
||||
maxConcurrent,
|
||||
rootDir,
|
||||
autoMerge,
|
||||
globalPaused,
|
||||
enginePaused,
|
||||
@@ -401,12 +399,6 @@ function AppInner() {
|
||||
setNodesOpen((prev) => !prev);
|
||||
}, [nodesEnabled]);
|
||||
|
||||
const handleOpenMissionsView = useCallback(() => {
|
||||
setMissionTargetId(undefined);
|
||||
setMissionResumeSessionId(undefined);
|
||||
handleChangeTaskView("missions");
|
||||
}, [handleChangeTaskView]);
|
||||
|
||||
const handleOpenMission = useCallback((missionId: string) => {
|
||||
setMissionTargetId(missionId);
|
||||
setMissionResumeSessionId(undefined);
|
||||
|
||||
@@ -57,10 +57,8 @@ import type {
|
||||
Insight,
|
||||
InsightCategory,
|
||||
InsightStatus,
|
||||
InsightListOptions,
|
||||
InsightRun,
|
||||
InsightRunTrigger,
|
||||
InsightRunCreateInput,
|
||||
} from "@fusion/core";
|
||||
import type { PlanningQuestion, PlanningSummary } from "@fusion/core";
|
||||
import type { ScheduledTask, ScheduledTaskCreateInput, ScheduledTaskUpdateInput, AutomationRunResult, Routine, RoutineCreateInput, RoutineUpdateInput, RoutineExecutionResult } from "@fusion/core";
|
||||
@@ -2523,7 +2521,7 @@ export async function fetchDevServers(projectId?: string): Promise<DevServerSess
|
||||
}
|
||||
: undefined,
|
||||
previewUrl: legacy.previewUrl ?? legacy.detectedUrl ?? undefined,
|
||||
logHistory: (legacy.logs ?? []).map<DevServerLogEntry>((text, i) => ({
|
||||
logHistory: (legacy.logs ?? []).map<DevServerLogEntry>((text) => ({
|
||||
timestamp: new Date().toISOString(),
|
||||
stream: text.startsWith("[stderr]") ? "stderr" : "stdout",
|
||||
text: text.replace(/^\[stderr\]\s*/, ""),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { memo, useCallback, useMemo } from "react";
|
||||
import {
|
||||
GitPullRequest,
|
||||
GitMerge,
|
||||
GitMerge,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
Plus,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { X, History, Trash2, Filter, RefreshCw, CheckCircle, XCircle, ArrowRight, Plus, Settings, AlertCircle, Loader2, Folder } from "lucide-react";
|
||||
import { clearActivityLog, type ActivityLogEntry, type ActivityEventType, type ActivityFeedEntry } from "../api";
|
||||
import { useActivityLog } from "../hooks/useActivityLog";
|
||||
@@ -72,10 +72,10 @@ function formatTimestamp(timestamp: string): string {
|
||||
* - Real-time updates via useActivityLog hook
|
||||
*/
|
||||
export function ActivityLogModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
tasks,
|
||||
onOpenTaskDetail,
|
||||
isOpen,
|
||||
onClose,
|
||||
tasks: _tasks,
|
||||
onOpenTaskDetail,
|
||||
projectId,
|
||||
projects = [],
|
||||
onProjectFilterChange,
|
||||
@@ -136,7 +136,7 @@ export function ActivityLogModal({
|
||||
await clearActivityLog();
|
||||
refresh();
|
||||
setShowConfirmClear(false);
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// Error handled by hook
|
||||
setShowConfirmClear(false);
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ export function AgentListModal({ isOpen, onClose, addToast, projectId }: AgentLi
|
||||
}
|
||||
};
|
||||
|
||||
const handleRoleKeyDown = (e: React.KeyboardEvent, agentId: string) => {
|
||||
const handleRoleKeyDown = (e: React.KeyboardEvent, _agentId: string) => {
|
||||
if (e.key === "Escape") {
|
||||
setEditingRoleForAgent(null);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState, useCallback, useEffect, useRef } from "react";
|
||||
import { BUILTIN_AGENT_PROMPTS, PROMPT_KEY_CATALOG } from "../utils/builtinPrompts";
|
||||
import type { AgentPromptTemplate, AgentPromptsConfig, AgentCapability } from "@fusion/core";
|
||||
import type { PromptKey } from "@fusion/core";
|
||||
import { X, Plus, Pencil, Trash2, BookOpen, Users, Settings2, ChevronDown, ChevronUp, Maximize2, Minimize2 } from "lucide-react";
|
||||
import { Plus, Pencil, Trash2, BookOpen, Users, Settings2, ChevronDown, ChevronUp, Maximize2, Minimize2 } from "lucide-react";
|
||||
|
||||
/**
|
||||
* Props for the AgentPromptsManager component.
|
||||
@@ -807,7 +807,6 @@ export function AgentPromptsManager({
|
||||
(t) => t.id === currentAssignment,
|
||||
);
|
||||
const isOverriding = !!currentAssignment;
|
||||
const isOverridingBuiltin = isBuiltinId(currentAssignment);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -464,9 +464,8 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
const [mentionStartPos, setMentionStartPos] = useState(-1);
|
||||
|
||||
// File mention state and hook
|
||||
const [fileMentionPopupVisible, setFileMentionPopupVisible] = useState(false);
|
||||
const [, setFileMentionPopupVisible] = useState(false);
|
||||
const [fileMentionPosition, setFileMentionPosition] = useState({ top: 0, left: 0 });
|
||||
const fileMentionRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const fileMention = useFileMention({ projectId });
|
||||
|
||||
|
||||
@@ -95,11 +95,6 @@ export function CustomModelDropdown({
|
||||
}, [favoriteModels, filteredModels]);
|
||||
|
||||
// Sort providers: favorites first (in order), then alphabetically
|
||||
// Exclude providers that are already favorited as models (they appear at top as pinned rows)
|
||||
const favoritedProviderSet = new Set(favoriteModels.map((fullId) => {
|
||||
const idx = fullId.indexOf("/");
|
||||
return idx !== -1 ? fullId.slice(0, idx) : fullId;
|
||||
}));
|
||||
const sortedProviderEntries = useMemo(() => {
|
||||
const entries = Object.entries(modelsByProvider);
|
||||
const favoritesSet = new Set(favoriteProviders);
|
||||
|
||||
@@ -80,8 +80,6 @@ function truncateCommand(command: string): string {
|
||||
export function DevServerView({ addToast, projectId }: DevServerViewProps) {
|
||||
const {
|
||||
session,
|
||||
sessions,
|
||||
logs,
|
||||
detectedCommands,
|
||||
previewUrl,
|
||||
isLoading,
|
||||
@@ -294,7 +292,6 @@ export function DevServerView({ addToast, projectId }: DevServerViewProps) {
|
||||
}
|
||||
|
||||
const fallbackCwd = normalizeSourceToCwd(selectedSource) ?? ".";
|
||||
const scriptName = selectedCandidate?.scriptName ?? selectedScript ?? "custom";
|
||||
const cwd = selectedCandidate?.cwd ?? fallbackCwd;
|
||||
|
||||
void runAction(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMemo } from "react";
|
||||
import type { Task } from "@fusion/core";
|
||||
import { Activity, AlertTriangle, Clock, Pause, Play, Zap } from "lucide-react";
|
||||
import { AlertTriangle, Clock, Pause, Play, Zap } from "lucide-react";
|
||||
import { useExecutorStats } from "../hooks/useExecutorStats";
|
||||
import type { ExecutorState, AiSessionSummary } from "../api";
|
||||
import { BackgroundTasksIndicator } from "./BackgroundTasksIndicator";
|
||||
|
||||
@@ -16,7 +16,7 @@ function getIssueModifierClass(state: string, stateReason?: string): string {
|
||||
return "card-github-badge--closed";
|
||||
}
|
||||
|
||||
export function GitHubBadge({ prInfo, issueInfo, onIssueRefresh }: GitHubBadgeProps) {
|
||||
export function GitHubBadge({ prInfo, issueInfo, onIssueRefresh: _onIssueRefresh }: GitHubBadgeProps) {
|
||||
const handlePrClick = () => {
|
||||
if (prInfo?.url) {
|
||||
window.open(prInfo.url, "_blank", "noopener,noreferrer");
|
||||
|
||||
@@ -319,7 +319,6 @@ export function GitHubImportModal({ isOpen, onClose, onImport, tasks, projectId
|
||||
// Determine state flags
|
||||
const hasRemotes = remotes.length > 0;
|
||||
const singleRemote = remotes.length === 1;
|
||||
const multipleRemotes = remotes.length > 1;
|
||||
|
||||
// Tab-specific counts
|
||||
const importedIssueCount = issues.filter((issue) => importedUrls.has(issue.html_url)).length;
|
||||
|
||||
@@ -168,7 +168,7 @@ interface GitManagerModalProps {
|
||||
|
||||
// ── Main Component ────────────────────────────────────────────────
|
||||
|
||||
export function GitManagerModal({ isOpen, onClose, tasks, addToast, projectId }: GitManagerModalProps) {
|
||||
export function GitManagerModal({ isOpen, onClose, tasks: _tasks, addToast, projectId }: GitManagerModalProps) {
|
||||
const [activeSection, setActiveSection] = useState<SectionId>("status");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [sectionError, setSectionError] = useState<string | null>(null);
|
||||
|
||||
@@ -23,15 +23,13 @@ import {
|
||||
Users,
|
||||
LineChart,
|
||||
TrendingUp,
|
||||
MoreVertical,
|
||||
ExternalLink,
|
||||
Archive,
|
||||
Clock,
|
||||
} from "lucide-react";
|
||||
import { useInsights, INSIGHT_CATEGORIES, CATEGORY_LABELS, type InsightSection } from "../hooks/useInsights";
|
||||
import { useInsights, type InsightSection } from "../hooks/useInsights";
|
||||
import type { InsightCategory } from "@fusion/core";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import { createTask } from "../api";
|
||||
|
||||
interface InsightsViewProps {
|
||||
projectId?: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback, useMemo, Fragment, useEffect, useRef } from "react";
|
||||
import { LayoutGrid, List as ListIcon, ArrowUpDown, ArrowUp, ArrowDown, Link, Columns3, EyeOff, Eye, ChevronRight } from "lucide-react";
|
||||
import { ArrowUpDown, ArrowUp, ArrowDown, Link, Columns3, EyeOff, Eye, ChevronRight } from "lucide-react";
|
||||
import type { Task, TaskDetail, Column, TaskCreateInput } from "@fusion/core";
|
||||
import { COLUMN_LABELS, COLUMNS } from "@fusion/core";
|
||||
import { batchUpdateTaskModels } from "../api";
|
||||
@@ -163,7 +163,7 @@ export function ListView({
|
||||
onSubtaskBreakdown,
|
||||
onTasksUpdated,
|
||||
projectId,
|
||||
projectName,
|
||||
projectName: _projectName,
|
||||
taskStuckTimeoutMs,
|
||||
searchQuery = "",
|
||||
lastFetchTimeMs,
|
||||
|
||||
@@ -87,11 +87,7 @@ export function MilestoneSliceInterviewModal({
|
||||
const trackedLockSessionRef = useRef<string | null>(null);
|
||||
const [lockSessionId, setLockSessionId] = useState<string | null>(null);
|
||||
const sessionTabId = useMemo(() => getSessionTabId(), []);
|
||||
const {
|
||||
isLockedByOther,
|
||||
takeControl,
|
||||
isLoading: isLockLoading,
|
||||
} = useSessionLock(isOpen ? lockSessionId : null);
|
||||
useSessionLock(isOpen ? lockSessionId : null);
|
||||
const {
|
||||
activeTabMap,
|
||||
broadcastUpdate,
|
||||
|
||||
@@ -39,16 +39,11 @@ import type {
|
||||
MilestoneStatus,
|
||||
SliceStatus,
|
||||
FeatureStatus,
|
||||
MilestoneWithSlices,
|
||||
SliceWithFeatures,
|
||||
MissionHealth,
|
||||
MissionEvent,
|
||||
MissionEventType,
|
||||
FeatureLoopState,
|
||||
MissionAssertionStatus,
|
||||
MissionContractAssertion,
|
||||
ContractAssertionCreateInput,
|
||||
ContractAssertionUpdateInput,
|
||||
MilestoneValidationRollup,
|
||||
MilestoneValidationTelemetry,
|
||||
MissionFeatureLoopSnapshot,
|
||||
@@ -79,17 +74,13 @@ import {
|
||||
stopMission,
|
||||
startMission,
|
||||
updateMissionAutopilot,
|
||||
fetchMissionHealth,
|
||||
fetchMissionsHealth,
|
||||
fetchMissionEvents,
|
||||
fetchAssertions,
|
||||
createAssertion,
|
||||
updateAssertion,
|
||||
deleteAssertion,
|
||||
reorderAssertions,
|
||||
linkFeatureToAssertion,
|
||||
unlinkFeatureFromAssertion,
|
||||
fetchAssertionsForFeature,
|
||||
fetchFeaturesForAssertion,
|
||||
fetchMilestoneValidation,
|
||||
fetchMilestoneValidationTelemetry,
|
||||
@@ -97,12 +88,11 @@ import {
|
||||
fetchValidationLoopState,
|
||||
fetchValidationRuns,
|
||||
fetchValidationRun,
|
||||
fetchAssertion,
|
||||
fetchAiSessions,
|
||||
fetchAiSession,
|
||||
type AiSessionSummary,
|
||||
} from "../api";
|
||||
import type { AutopilotStatus as AutopilotStatusType, AutopilotState } from "./mission-types";
|
||||
import type { AutopilotState } from "./mission-types";
|
||||
|
||||
interface MissionManagerProps {
|
||||
isOpen: boolean;
|
||||
@@ -157,16 +147,6 @@ const autopilotStateColors: Record<AutopilotState, { bg: string; text: string }>
|
||||
completing: { bg: "var(--autopilot-completing-bg)", text: "var(--autopilot-completing-text)" },
|
||||
};
|
||||
|
||||
/** Loop state colors for feature execution loop */
|
||||
const loopStateColors: Record<FeatureLoopState, { bg: string; text: string; indicator: string }> = {
|
||||
idle: { bg: "var(--loop-idle-bg)", text: "var(--loop-idle-text)", indicator: "var(--loop-idle-indicator)" },
|
||||
implementing: { bg: "var(--loop-implementing-bg)", text: "var(--loop-implementing-text)", indicator: "var(--loop-implementing-indicator)" },
|
||||
validating: { bg: "var(--loop-validating-bg)", text: "var(--loop-validating-text)", indicator: "var(--loop-validating-indicator)" },
|
||||
needs_fix: { bg: "var(--loop-needs-fix-bg)", text: "var(--loop-needs-fix-text)", indicator: "var(--loop-needs-fix-indicator)" },
|
||||
passed: { bg: "var(--loop-passed-bg)", text: "var(--loop-passed-text)", indicator: "var(--loop-passed-indicator)" },
|
||||
blocked: { bg: "var(--loop-blocked-bg)", text: "var(--loop-blocked-text)", indicator: "var(--loop-blocked-indicator)" },
|
||||
};
|
||||
|
||||
/** Assertion status colors */
|
||||
const assertionStatusColors: Record<MissionAssertionStatus, { bg: string; text: string }> = {
|
||||
pending: { bg: "var(--assertion-pending-bg)", text: "var(--assertion-pending-text)" },
|
||||
@@ -570,7 +550,6 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
|
||||
// Assertion panel state
|
||||
const [assertionsByMilestone, setAssertionsByMilestone] = useState<Map<string, MissionContractAssertion[]>>(new Map());
|
||||
const [assertionsLoading, setAssertionsLoading] = useState(false);
|
||||
const [editingAssertionId, setEditingAssertionId] = useState<string | null>(null);
|
||||
const [assertionForm, setAssertionForm] = useState<{ title: string; assertion: string; status: MissionAssertionStatus }>({
|
||||
title: "",
|
||||
@@ -929,7 +908,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
}
|
||||
};
|
||||
|
||||
const handleSliceUpdated = (rawEvent: Event) => {
|
||||
const handleSliceUpdated = (_rawEvent: Event) => {
|
||||
refreshHealth();
|
||||
// Reload the selected mission detail to reflect updated slice status
|
||||
if (selectedMissionRef.current) {
|
||||
@@ -1560,7 +1539,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
next.set(milestoneId, assertions);
|
||||
return next;
|
||||
});
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
// Silently fail - assertions are optional
|
||||
}
|
||||
}, [projectId]);
|
||||
@@ -1573,7 +1552,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
next.set(milestoneId, rollup);
|
||||
return next;
|
||||
});
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
// Silently fail
|
||||
}
|
||||
}, [projectId]);
|
||||
@@ -1640,18 +1619,6 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
}
|
||||
}, [assertionForm, addToast, loadAssertionsForMilestone, loadValidationRollup, handleCancelAssertion, projectId]);
|
||||
|
||||
const handleDeleteAssertion = useCallback(async (assertionId: string, milestoneId: string) => {
|
||||
try {
|
||||
await deleteAssertion(assertionId, projectId);
|
||||
addToast("Assertion deleted", "success");
|
||||
await loadAssertionsForMilestone(milestoneId);
|
||||
await loadValidationRollup(milestoneId);
|
||||
setDeleteConfirmId(null);
|
||||
} catch (err: any) {
|
||||
addToast(err.message || "Failed to delete assertion", "error");
|
||||
}
|
||||
}, [addToast, loadAssertionsForMilestone, loadValidationRollup, projectId]);
|
||||
|
||||
const loadLinkedFeaturesForAssertion = useCallback(async (assertionId: string) => {
|
||||
try {
|
||||
const features = await fetchFeaturesForAssertion(assertionId, projectId);
|
||||
@@ -1660,7 +1627,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
next.set(assertionId, features);
|
||||
return next;
|
||||
});
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
// Silently fail
|
||||
}
|
||||
}, [projectId]);
|
||||
@@ -1753,7 +1720,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
next.set(featureId, snapshot);
|
||||
return next;
|
||||
});
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
// Silently fail
|
||||
}
|
||||
}, [projectId]);
|
||||
@@ -1767,7 +1734,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
next.set(featureId, runs);
|
||||
return next;
|
||||
});
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
// Silently fail
|
||||
}
|
||||
}, [projectId]);
|
||||
@@ -1821,7 +1788,7 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
next.set(runId, detail);
|
||||
return next;
|
||||
});
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
// Silently fail
|
||||
}
|
||||
}, [projectId]);
|
||||
|
||||
@@ -406,7 +406,6 @@ function ApiKeyEntryForm({
|
||||
import {
|
||||
getOnboardingState,
|
||||
saveOnboardingState,
|
||||
clearOnboardingState,
|
||||
markOnboardingCompleted,
|
||||
markStepSkipped,
|
||||
getSkippedSteps,
|
||||
@@ -1523,7 +1522,6 @@ export function ModelOnboardingModal({
|
||||
const connectedCount = authProviders.filter(p => p.id !== "github" && p.authenticated).length;
|
||||
const totalAiProviders = authProviders.filter(p => p.id !== "github").length;
|
||||
const skippedCount = Object.keys(skippedProviders).filter(id => !authProviders.find(p => p.id === id)?.authenticated).length;
|
||||
const connectedProviders = authProviders.filter(p => p.id !== "github" && p.authenticated);
|
||||
|
||||
if (totalAiProviders === 0) return null;
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ export function ModelSelectorTab({ task, addToast, onTaskUpdated, settings }: Mo
|
||||
|
||||
try {
|
||||
await updateGlobalSettings({ favoriteProviders: newFavorites, favoriteModels });
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// Revert on error
|
||||
setFavoriteProviders(currentFavorites);
|
||||
addToast("Failed to update favorites", "error");
|
||||
@@ -193,7 +193,7 @@ export function ModelSelectorTab({ task, addToast, onTaskUpdated, settings }: Mo
|
||||
|
||||
try {
|
||||
await updateGlobalSettings({ favoriteProviders, favoriteModels: newFavorites });
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// Revert on error
|
||||
setFavoriteModels(currentFavorites);
|
||||
addToast("Failed to update model favorites", "error");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Activity, Download, Key, Pencil, Save, Shield, Upload, X } from "lucide-react";
|
||||
import { Activity, Download, Pencil, Save, Shield, Upload, X } from "lucide-react";
|
||||
import type { NodeInfo, NodeUpdateInput, ProjectInfo } from "../api";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import { getProjectsForNode } from "../utils/nodeProjectAssignment";
|
||||
@@ -66,7 +66,7 @@ export function NodeDetailModal({
|
||||
|
||||
// Conflict resolution modal state
|
||||
const [showConflictModal, setShowConflictModal] = useState(false);
|
||||
const [conflicts, setConflicts] = useState<SettingsConflictEntry[]>([]);
|
||||
const [conflicts] = useState<SettingsConflictEntry[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
isMountedRef.current = true;
|
||||
|
||||
@@ -88,8 +88,6 @@ export function PluginManager({ addToast, projectId }: PluginManagerProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPlugins = pluginsRef.current;
|
||||
|
||||
switch (payload.transition) {
|
||||
case "installing":
|
||||
case "enabled":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { memo, useCallback, useState } from "react";
|
||||
import { Play, Pause, AlertCircle, Loader2, MoreHorizontal, Trash2, Folder, ArrowRight } from "lucide-react";
|
||||
import { Play, Pause, AlertCircle, Loader2, Trash2, Folder, ArrowRight } from "lucide-react";
|
||||
import type { RegisteredProject, ProjectHealth, ProjectStatus } from "@fusion/core";
|
||||
import type { NodeInfo } from "../api";
|
||||
|
||||
|
||||
@@ -203,16 +203,6 @@ export function ProjectOverview({
|
||||
}));
|
||||
}, [projects, nodes]);
|
||||
|
||||
// Handle sort change
|
||||
const handleSort = useCallback((option: SortOption) => {
|
||||
if (sortBy === option) {
|
||||
setSortDirection((prev) => (prev === "asc" ? "desc" : "asc"));
|
||||
} else {
|
||||
setSortBy(option);
|
||||
setSortDirection(option === "name" ? "asc" : "desc");
|
||||
}
|
||||
}, [sortBy]);
|
||||
|
||||
// Handle project selection
|
||||
const handleSelectProject = useCallback((project: ProjectInfo) => {
|
||||
// Update recent projects in localStorage
|
||||
|
||||
@@ -437,7 +437,7 @@ export function QuickChatFAB({
|
||||
const [mentionStartPos, setMentionStartPos] = useState(-1);
|
||||
|
||||
// File mention state and hook
|
||||
const [fileMentionPopupVisible, setFileMentionPopupVisible] = useState(false);
|
||||
const [, setFileMentionPopupVisible] = useState(false);
|
||||
const [fileMentionPosition, setFileMentionPosition] = useState({ top: 0, left: 0 });
|
||||
const fileMention = useFileMention({ projectId });
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback, useEffect, useRef } from "react";
|
||||
import { Plus, Pencil, Trash2, Check, X, GripVertical, Sparkles, Download, Copy, Loader, ChevronLeft, ArrowLeft, ChevronUp } from "lucide-react";
|
||||
import { Plus, Pencil, Trash2, Check, X, GripVertical, Sparkles, Download, Copy, Loader, ArrowLeft, ChevronUp } from "lucide-react";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import { useRoadmaps, type FeatureSuggestion, type MilestoneSuggestion, type SuggestionDraftPatch } from "../hooks/useRoadmaps";
|
||||
import { useViewportMode } from "../hooks/useViewportMode";
|
||||
@@ -466,11 +466,11 @@ function MilestoneCard({
|
||||
onCancelMilestoneEdit,
|
||||
onSaveMilestoneEdit,
|
||||
featureEdit,
|
||||
onStartFeatureEdit,
|
||||
onStartFeatureEdit: _onStartFeatureEdit,
|
||||
onCancelFeatureEdit,
|
||||
onSaveFeatureEdit,
|
||||
projectId,
|
||||
addToast,
|
||||
projectId: _projectId,
|
||||
addToast: _addToast,
|
||||
// Milestone drag-and-drop props
|
||||
isMilestoneDragging,
|
||||
isMilestoneDropTarget,
|
||||
@@ -631,7 +631,7 @@ function MilestoneCard({
|
||||
type="text"
|
||||
className="roadmaps-view__inline-input"
|
||||
value={milestoneEdit.value}
|
||||
onChange={(e) =>
|
||||
onChange={() =>
|
||||
onStartMilestoneEdit()
|
||||
}
|
||||
onKeyDown={handleMilestoneTitleKeyDown}
|
||||
@@ -659,7 +659,7 @@ function MilestoneCard({
|
||||
<textarea
|
||||
className="roadmaps-view__inline-textarea"
|
||||
value={milestoneEdit.field === "description" ? milestoneEdit.value : milestone.description || ""}
|
||||
onChange={(e) => {
|
||||
onChange={() => {
|
||||
// Update the edit state with description
|
||||
}}
|
||||
onKeyDown={handleMilestoneDescKeyDown}
|
||||
@@ -1623,9 +1623,6 @@ export function RoadmapsView({ projectId, addToast }: RoadmapsViewProps) {
|
||||
const isCrossMilestone = draggingMilestoneId !== targetMilestoneId;
|
||||
|
||||
if (isCrossMilestone) {
|
||||
// Cross-milestone move
|
||||
const targetFeatures = featuresByMilestoneId[targetMilestoneId] || [];
|
||||
|
||||
// No-op check: if moving to same position in same milestone (shouldn't happen but safety check)
|
||||
if (draggingMilestoneId === targetMilestoneId) {
|
||||
handleFeatureDragEnd();
|
||||
@@ -1907,7 +1904,7 @@ export function RoadmapsView({ projectId, addToast }: RoadmapsViewProps) {
|
||||
|
||||
// Feature handlers
|
||||
const handleStartFeatureEdit = useCallback(
|
||||
(featureId: string, currentTitle: string, currentDescription?: string) => {
|
||||
(featureId: string, currentTitle: string, _currentDescription?: string) => {
|
||||
setFeatureEdit({
|
||||
featureId,
|
||||
field: "title",
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Calendar, Webhook, Code, Zap, Globe, Folder } from "lucide-react";
|
||||
import type {
|
||||
Routine,
|
||||
RoutineCreateInput,
|
||||
RoutineUpdateInput,
|
||||
RoutineTrigger,
|
||||
RoutineTriggerType,
|
||||
RoutineCronTrigger,
|
||||
@@ -126,13 +125,6 @@ function extractTriggerFields(routine: Routine) {
|
||||
}
|
||||
}
|
||||
|
||||
const TRIGGER_TYPE_LABELS: Record<RoutineTriggerType, string> = {
|
||||
cron: "Cron Schedule",
|
||||
webhook: "Webhook",
|
||||
api: "API",
|
||||
manual: "Manual",
|
||||
};
|
||||
|
||||
const EXECUTION_POLICY_OPTIONS: { value: RoutineExecutionPolicy; label: string }[] = [
|
||||
{ value: "parallel", label: "Allow concurrent runs" },
|
||||
{ value: "queue", label: "Queue after current (one at a time)" },
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { Globe, Folder } from "lucide-react";
|
||||
import { THINKING_LEVELS, PROMPT_KEY_CATALOG, isGlobalSettingsKey, isProjectSettingsKey } from "@fusion/core";
|
||||
import type { Settings, GlobalSettings, ThemeMode, ColorTheme, ModelPreset, NtfyNotificationEvent, PromptKey, AgentPromptsConfig } from "@fusion/core";
|
||||
import { THINKING_LEVELS, isGlobalSettingsKey, isProjectSettingsKey } from "@fusion/core";
|
||||
import type { Settings, GlobalSettings, ThemeMode, ColorTheme, ModelPreset, NtfyNotificationEvent, AgentPromptsConfig } from "@fusion/core";
|
||||
import { fetchSettings, fetchSettingsByScope, updateSettings, updateGlobalSettings, fetchAuthStatus, loginProvider, logoutProvider, saveApiKey, clearApiKey, fetchModels, testNtfyNotification, fetchBackups, createBackup, exportSettings, importSettings, fetchMemoryFile, fetchMemoryFiles, saveMemoryFile, compactMemory, fetchGlobalConcurrency, updateGlobalConcurrency, installQmd, testMemoryRetrieval, fetchGitRemotesDetailed } from "../api";
|
||||
import type { AuthProvider, ModelInfo, BackupListResponse, SettingsExportData, MemoryBackendCapabilities, MemoryFileInfo, MemoryRetrievalTestResult, GitRemoteDetailed } from "../api";
|
||||
import type { AuthProvider, ModelInfo, BackupListResponse, SettingsExportData, MemoryFileInfo, MemoryRetrievalTestResult, GitRemoteDetailed } from "../api";
|
||||
import { useMemoryBackendStatus } from "../hooks/useMemoryBackendStatus";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import { ThemeSelector } from "./ThemeSelector";
|
||||
|
||||
@@ -31,7 +31,7 @@ interface SettingsSyncLogProps {
|
||||
* with filtering by direction and node name.
|
||||
*/
|
||||
export function SettingsSyncLog({
|
||||
nodeId,
|
||||
nodeId: _nodeId,
|
||||
entries,
|
||||
loading = false,
|
||||
singleNode = false,
|
||||
|
||||
@@ -507,7 +507,7 @@ function TaskCardComponent({
|
||||
try {
|
||||
const detail = await fetchTaskDetail(depId, projectId);
|
||||
onOpenDetail(detail);
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
addToast(`Failed to load dependency ${depId}`, "error");
|
||||
}
|
||||
}, [onOpenDetail, addToast]);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Pencil, Bot, X, ChevronDown } from "lucide-react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import type { Task, TaskDetail, TaskAttachment, Column, MergeResult, PrInfo, Settings, AgentLogEntry, Agent } from "@fusion/core";
|
||||
import type { Task, TaskDetail, TaskAttachment, Column, MergeResult, Settings, AgentLogEntry, Agent } from "@fusion/core";
|
||||
import { COLUMN_LABELS, VALID_TRANSITIONS } from "@fusion/core";
|
||||
import { uploadAttachment, deleteAttachment, updateTask, pauseTask, unpauseTask, fetchTaskDetail, fetchSettings, requestSpecRevision, rebuildTaskSpec, approvePlan, rejectPlan, refineTask, fetchWorkflowResults, assignTask, fetchAgents, fetchAgent } from "../api";
|
||||
import type { WorkflowStepResult } from "@fusion/core";
|
||||
@@ -27,23 +27,7 @@ interface ModelSelection {
|
||||
modelId?: string;
|
||||
}
|
||||
|
||||
function normalizeModelField(value: string | null | undefined): string | undefined {
|
||||
return value ?? undefined;
|
||||
}
|
||||
|
||||
function getExecutorSelection(task: Task | TaskDetail): ModelSelection {
|
||||
return {
|
||||
provider: normalizeModelField(task.modelProvider),
|
||||
modelId: normalizeModelField(task.modelId),
|
||||
};
|
||||
}
|
||||
|
||||
function getValidatorSelection(task: Task | TaskDetail): ModelSelection {
|
||||
return {
|
||||
provider: normalizeModelField(task.validatorModelProvider),
|
||||
modelId: normalizeModelField(task.validatorModelId),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the effective executor model following the engine's resolution order:
|
||||
@@ -996,7 +980,7 @@ export function TaskDetailModal({
|
||||
try {
|
||||
const detail = await fetchTaskDetail(depId, projectId);
|
||||
onOpenDetail(detail);
|
||||
} catch (err: any) {
|
||||
} catch {
|
||||
addToast(`Failed to load dependency ${depId}`, "error");
|
||||
}
|
||||
}, [onOpenDetail, addToast]);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { FileText, ChevronDown, ChevronUp, Plus, Trash2, History, X } from "lucide-react";
|
||||
import { FileText, ChevronDown, ChevronUp, Plus, Trash2, History } from "lucide-react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import type { Task, TaskDocument, TaskDocumentRevision } from "@fusion/core";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import {
|
||||
fetchTaskDocuments,
|
||||
fetchTaskDocument,
|
||||
fetchTaskDocumentRevisions,
|
||||
putTaskDocument,
|
||||
deleteTaskDocument,
|
||||
@@ -37,7 +36,7 @@ function getContentPreview(content: string, maxLength: number = MAX_CONTENT_PREV
|
||||
export function TaskDocumentsTab({
|
||||
taskId,
|
||||
addToast,
|
||||
onTaskUpdated,
|
||||
onTaskUpdated: _onTaskUpdated,
|
||||
projectId,
|
||||
canEdit = false,
|
||||
}: TaskDocumentsTabProps) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback, useEffect, useRef, type ReactNode } from "react";
|
||||
import type { Task, ModelPreset, Settings, WorkflowStep } from "@fusion/core";
|
||||
import type { Task, Settings, WorkflowStep } from "@fusion/core";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import { fetchModels, fetchSettings, fetchWorkflowSteps, refineText, getRefineErrorMessage, updateGlobalSettings, type RefinementType, type ModelInfo } from "../api";
|
||||
import { applyPresetToSelection, getRecommendedPresetForSize } from "../utils/modelPresets";
|
||||
|
||||
@@ -87,7 +87,7 @@ interface UsageWindowRowProps {
|
||||
/**
|
||||
* Single usage window row with progress bar
|
||||
*/
|
||||
function UsageWindowRow({ window, viewMode, providerName }: UsageWindowRowProps) {
|
||||
function UsageWindowRow({ window, viewMode, providerName: _providerName }: UsageWindowRowProps) {
|
||||
const colorClass = getUsageColorClass(window.percentUsed);
|
||||
const isRemainingMode = viewMode === 'remaining';
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ export function useBatchBadgeFetch(projectId?: string): UseBatchBadgeFetchResult
|
||||
batchBadgeStore.data.set(getScopedTaskKey(taskId, projectId), { result, timestamp });
|
||||
}
|
||||
batchBadgeStore.lastFetchTime = timestamp;
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// Even on error, we don't throw - the hook handles errors gracefully
|
||||
// and partial results are still stored
|
||||
} finally {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
detectDevServerCommands,
|
||||
fetchDevServer,
|
||||
fetchDevServerLogs,
|
||||
fetchDevServers,
|
||||
getDevServerLogsStreamUrl,
|
||||
getDevServerSessionLogsStreamUrl,
|
||||
@@ -26,8 +25,6 @@ import { subscribeSse } from "../sse-bus";
|
||||
const MAX_LOG_LINES = 500;
|
||||
const POLL_INTERVAL_MS = 3000;
|
||||
|
||||
let resetVersion = 0;
|
||||
|
||||
function normalizeError(error: unknown): string {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
@@ -161,7 +158,7 @@ export interface UseDevServerReturn {
|
||||
}
|
||||
|
||||
export function __resetUseDevServerForTests(): void {
|
||||
resetVersion += 1;
|
||||
// no-op: reserved hook for future test reset coordination.
|
||||
}
|
||||
|
||||
export function useDevServer(projectId?: string): UseDevServerReturn {
|
||||
|
||||
@@ -210,7 +210,7 @@ export function useFileMention(options: UseFileMentionOptions = {}): UseFileMent
|
||||
* Supports ArrowUp/ArrowDown to navigate, Enter/Tab to select, Escape to dismiss.
|
||||
*/
|
||||
const handleKeyDown = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLElement>, currentText: string): boolean => {
|
||||
(event: React.KeyboardEvent<HTMLElement>, _currentText: string): boolean => {
|
||||
if (!mentionActive || files.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ export interface ModalManager {
|
||||
* and cross-modal transitions (for example, script runner -> terminal handoff).
|
||||
*/
|
||||
export function useModalManager(options: UseModalManagerOptions): ModalManager {
|
||||
const { projectId, planningSessions } = options;
|
||||
const { planningSessions } = options;
|
||||
|
||||
const [newTaskModalOpen, setNewTaskModalOpen] = useState(false);
|
||||
const [isPlanningOpen, setIsPlanningOpen] = useState(false);
|
||||
|
||||
@@ -156,7 +156,7 @@ export function useNodeSettingsSync(): UseNodeSettingsSyncResult {
|
||||
* Fetch sync status for a single node and update state.
|
||||
* Does NOT set loading=true (called during polling and initial fetch).
|
||||
*/
|
||||
const fetchNodeStatus = useCallback(async (nodeId: string, isInitial: boolean): Promise<void> => {
|
||||
const fetchNodeStatus = useCallback(async (nodeId: string, _isInitial: boolean): Promise<void> => {
|
||||
try {
|
||||
const status = await fetchNodeSettingsSyncStatus(nodeId);
|
||||
setSyncStatusMap((prev) => ({
|
||||
|
||||
@@ -49,7 +49,7 @@ export function usePreviewEmbed(url: string | null, options: UsePreviewEmbedOpti
|
||||
|
||||
const [embedStatus, setEmbedStatusState] = useState<EmbedStatus>("unknown");
|
||||
const [blockReason, setBlockReason] = useState<string | null>(null);
|
||||
const [detectionMethod, setDetectionMethod] = useState<EmbedDetectionMethod>(initialDetectionMethod);
|
||||
const [detectionMethod] = useState<EmbedDetectionMethod>(initialDetectionMethod);
|
||||
|
||||
const clearLoadingTimeout = useCallback(() => {
|
||||
if (timeoutRef.current !== null) {
|
||||
|
||||
@@ -25,11 +25,6 @@ export interface TerminalTab {
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
interface StoredTab extends TerminalTab {
|
||||
/** Marked as unverified during server validation */
|
||||
_verified?: boolean;
|
||||
}
|
||||
|
||||
interface UseTerminalSessionsReturn {
|
||||
/** All terminal tabs */
|
||||
tabs: TerminalTab[];
|
||||
|
||||
@@ -23,8 +23,6 @@ import type {
|
||||
import { summarizeTitle } from "@fusion/core";
|
||||
import { EventEmitter } from "node:events";
|
||||
import { join, resolve, relative } from "node:path";
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
import { SessionEventBuffer } from "./sse-buffer.js";
|
||||
|
||||
// Dynamic import for @fusion/engine to avoid resolution issues in test environment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Router, type Request, type Response } from "express";
|
||||
import { Router, type Response } from "express";
|
||||
import { badRequest, conflict, ApiError, sendErrorResponse } from "./api-error.js";
|
||||
import { detectDevServerScripts } from "./dev-server-detect.js";
|
||||
import {
|
||||
|
||||
@@ -26,10 +26,8 @@ import type { AiSessionStore, AiSessionRow } from "./ai-session-store.js";
|
||||
import { SessionEventBuffer, type SessionBufferedEvent } from "./sse-buffer.js";
|
||||
import {
|
||||
createSessionDiagnostics,
|
||||
setDiagnosticsSink,
|
||||
resetDiagnosticsSink,
|
||||
nonfatal,
|
||||
nonfatalAsync,
|
||||
} from "./ai-session-diagnostics.js";
|
||||
|
||||
// Dynamic import for @fusion/engine to avoid resolution issues in test environment
|
||||
|
||||
@@ -455,9 +455,7 @@ export function createRoadmapRouter(store: TaskStore): Router {
|
||||
router.post("/:roadmapId/suggestions/milestones", async (req, res) => {
|
||||
// Route-level timeout as safety net (slightly longer than internal timeout)
|
||||
const ROUTE_TIMEOUT_MS = SUGGESTION_TIMEOUT_MS + 10_000;
|
||||
let routeTimedOut = false;
|
||||
const routeTimeoutId = setTimeout(() => {
|
||||
routeTimedOut = true;
|
||||
if (!res.headersSent) {
|
||||
res.status(503).json({ error: "Request timed out" });
|
||||
}
|
||||
@@ -528,9 +526,7 @@ export function createRoadmapRouter(store: TaskStore): Router {
|
||||
router.post("/milestones/:milestoneId/suggestions/features", async (req, res) => {
|
||||
// Route-level timeout as safety net (slightly longer than internal timeout)
|
||||
const ROUTE_TIMEOUT_MS = SUGGESTION_TIMEOUT_MS + 10_000;
|
||||
let routeTimedOut = false;
|
||||
const routeTimeoutId = setTimeout(() => {
|
||||
routeTimedOut = true;
|
||||
if (!res.headersSent) {
|
||||
res.status(503).json({ error: "Request timed out" });
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ const {
|
||||
writeFile: fsWriteFile,
|
||||
} = fsPromises;
|
||||
import type { TaskStore, Column, ScheduleType, ActivityEventType, ModelPreset, MessageType, ParticipantType, RoutineTriggerType, ProjectSettings, EnrichedChatSession, PlanningSummary } from "@fusion/core";
|
||||
import { COLUMNS, VALID_TRANSITIONS, GLOBAL_SETTINGS_KEYS, type BatchStatusEntry, type BatchStatusResponse, type BatchStatusResult, type IssueInfo, type PrInfo, type Task, type PiExtensionEntry, type PiExtensionSettings, getCurrentRepo, isGhAvailable, isGhAuthenticated, AutomationStore, validateBackupSchedule, validateBackupRetention, validateBackupDir, syncBackupRoutine, exportSettings, importSettings, validateImportData, MessageStore, validateMessageMetadata, RoutineStore, isWebhookTrigger, resolveMemoryBackend, getMemoryBackendCapabilities, listMemoryBackendTypes, listProjectMemoryFiles, readProjectMemoryFile, readProjectMemoryFileContent, writeProjectMemoryFile, listAgentMemoryFiles, readAgentMemoryFile, writeAgentMemoryFile, readMemory, writeMemory, searchProjectMemory, isQmdAvailable, installQmd, refreshQmdProjectMemoryIndex, QMD_INSTALL_COMMAND, MemoryBackendError, scheduleQmdProjectMemoryRefresh, discoverPiExtensions, updatePiExtensionDisabledIds, getFusionAgentDir, getLegacyPiAgentDir, ensureMemoryFileWithBackend, readInsightsMemory, writeInsightsMemory, generateMemoryAudit, buildInsightExtractionPrompt, parseInsightExtractionResponse, processAndAuditInsightExtraction } from "@fusion/core";
|
||||
import { COLUMNS, VALID_TRANSITIONS, GLOBAL_SETTINGS_KEYS, type BatchStatusEntry, type BatchStatusResponse, type BatchStatusResult, type IssueInfo, type PrInfo, type Task, type PiExtensionEntry, type PiExtensionSettings, getCurrentRepo, isGhAvailable, isGhAuthenticated, AutomationStore, validateBackupSchedule, validateBackupRetention, validateBackupDir, syncBackupRoutine, exportSettings, importSettings, validateImportData, MessageStore, validateMessageMetadata, RoutineStore, isWebhookTrigger, resolveMemoryBackend, getMemoryBackendCapabilities, listMemoryBackendTypes, listProjectMemoryFiles, readProjectMemoryFile, readProjectMemoryFileContent, writeProjectMemoryFile, listAgentMemoryFiles, readAgentMemoryFile, writeAgentMemoryFile, readMemory, writeMemory, searchProjectMemory, isQmdAvailable, installQmd, refreshQmdProjectMemoryIndex, QMD_INSTALL_COMMAND, MemoryBackendError, scheduleQmdProjectMemoryRefresh, discoverPiExtensions, updatePiExtensionDisabledIds, getFusionAgentDir, getLegacyPiAgentDir, ensureMemoryFileWithBackend, readInsightsMemory, writeInsightsMemory, generateMemoryAudit, buildInsightExtractionPrompt, processAndAuditInsightExtraction } from "@fusion/core";
|
||||
import type { ServerOptions } from "./server.js";
|
||||
import { probeClaudeCli } from "./claude-cli-probe.js";
|
||||
import { GitHubClient, parseBadgeUrl } from "./github.js";
|
||||
@@ -16353,9 +16353,6 @@ async function persistImportedSkills(
|
||||
const globalSettingsStore = store.getGlobalSettingsStore();
|
||||
const globalSettings = await globalSettingsStore.getSettings();
|
||||
|
||||
// Get local node ID for source tracking
|
||||
const localPeerInfo = await central.getLocalPeerInfo();
|
||||
|
||||
// Build sync payload
|
||||
const payload = {
|
||||
global: globalSettings,
|
||||
|
||||
Reference in New Issue
Block a user