Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/components/ComposerInput/composerInput.pillPortals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,7 @@ export function useComposerPillPortals({
placeCaretAfterPill(insertedPill);
insertedPill.removeAttribute("data-last-inserted-pill");
pendingCaretAfterPillRef.current = false;
// pendingCaretAfterPillRef is a stable ref passed in from the parent —
// listing it would not change behavior, only silence the linter's
// inability to see it originates from a `useRef()` in this scope.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hostRef, pillEntries]);
}, [hostRef, pendingCaretAfterPillRef, pillEntries]);

return pillPortals;
}
4 changes: 1 addition & 3 deletions src/contexts/workspace/ChatContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,7 @@ export const ChatProvider: React.FC<{ children: ReactNode }> = ({
setFeedBackInfo,
chatContainerRef, // ref is stable
}),
// These are all stable references from useState/useCallback/useRef
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
[setChatWidth]
);

const historyActionsValue = useMemo(
Expand Down
9 changes: 7 additions & 2 deletions src/engines/ChatPanel/ChatHistory/hooks/useChatScrollPin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export function useChatScrollPin({
}, [bottomInset, footerSpacerHeight, staticScrollerRef, virtuosoScrollerRef]);

const scheduleFollowToEnd = useCallback(() => {
// eslint-disable-next-line react-hooks/immutability -- These caller-owned refs are the documented mutable coordination channel between the scroll hooks.
effectiveManualScrollAtRef.current = 0;
programmaticScrollAtRef.current = performance.now();
let secondFrameId = 0;
Expand Down Expand Up @@ -190,8 +191,12 @@ export function useChatScrollPin({
return () => {
el.removeEventListener("scroll", handleScroll);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [virtuosoScrollerRef, pinLastGroupRef]);
}, [
virtuosoScrollerRef,
pinLastGroupRef,
programmaticScrollAtRef,
effectiveManualScrollAtRef,
]);

return { scrollToEnd, programmaticScrollAtRef };
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ const A2UIRenderer = forwardRef<A2UIRendererHandle, A2UIRendererProps>(
evalScript(js: string) {
try {
// Sandboxed eval: no iframe boundary, but wrapped in try/catch.
// eslint-disable-next-line no-new-func
new Function(js)();
} catch (err) {
log.error("[canvas_eval]", err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export interface UseCodeBlockStateOptions {
isCollapsed: boolean;
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function useCodeBlockState({
code,
language,
Expand Down
1 change: 0 additions & 1 deletion src/engines/ChatPanel/blocks/primitives/BlockOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,6 @@ const BlockOutput: React.FC<BlockOutputProps> = memo(
) : highlightLang && highlightedHtml ? (
<div
className={`${preClassesShared} [&_pre.shiki]:!m-0 [&_pre.shiki]:!bg-transparent [&_pre.shiki]:!p-0 [&_pre.shiki]:!shadow-none`}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: highlightedHtml }}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ describe("waitForSnapshotChange — stress: many timeouts must not leak", () =>
timeoutMs: 10,
});
vi.advanceTimersByTime(10);
// eslint-disable-next-line no-await-in-loop
await expect(pending).resolves.toBe("timeout");
}
expect(store.listeners.size).toBe(0);
Expand All @@ -334,7 +333,6 @@ describe("waitForSnapshotChange — stress: many timeouts must not leak", () =>
timeoutMs: 100,
});
store.emit(buildSnapshot(i + 1), `s${i}`);
// eslint-disable-next-line no-await-in-loop
await expect(pending).resolves.toBe("snapshot");
}
expect(store.listeners.size).toBe(0);
Expand Down
1 change: 0 additions & 1 deletion src/features/GanttChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ const GanttChart: React.FC<GanttChartProps> = ({
return `task:${tasks[index - markerRows.length]?.id ?? index}`;
},
});
// eslint-disable-next-line react-hooks/incompatible-library -- TanStack Virtual exposes imperative helpers that cannot be memoized safely.
const periodVirtualizer = useVirtualizer({
horizontal: true,
count: periods.length,
Expand Down
11 changes: 8 additions & 3 deletions src/modules/MainApp/AgentOrgs/hooks/useEnsureAgentDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,14 @@ export function useEnsureAgentDefs(enabled = true): boolean {
return () => {
cancelled = true;
};
// Only run when `loaded` transitions from false to true (first time)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [enabled, loaded]);
}, [
enabled,
loaded,
setAllDefs,
setBuiltInAgents,
setCustomAgents,
setLoaded,
]);

return loaded;
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ const MOCK_INTERVENTION: AgentOrgMemberIntervention = {
clearedAt: null,
};

function isInteractivePending(
event: SessionEvent,
canonicalName: string
): boolean {
return (
stripMcpPrefix(event.functionName ?? "") === canonicalName &&
(event.displayStatus === "awaiting_user" ||
event.displayStatus === "running" ||
event.displayStatus === "pending")
);
}

// ============================================
// Public component
// ============================================
Expand Down Expand Up @@ -121,28 +133,17 @@ export function PlaygroundChatPanel({
return items;
}, [events]);

const isInteractivePending = (
evt: (typeof events)[number],
canonicalName: string
) =>
stripMcpPrefix(evt.functionName ?? "") === canonicalName &&
(evt.displayStatus === "awaiting_user" ||
evt.displayStatus === "running" ||
evt.displayStatus === "pending");

const pendingAskUser = useMemo(
() =>
events.find((evt) => isInteractivePending(evt, "ask_user_questions")) ??
null,
// eslint-disable-next-line react-hooks/exhaustive-deps
[events]
);

const pendingModeSwitch = useMemo(
() =>
events.find((evt) => isInteractivePending(evt, "suggest_mode_switch")) ??
null,
// eslint-disable-next-line react-hooks/exhaustive-deps
[events]
);
const showModeSwitchPreview =
Expand All @@ -157,7 +158,6 @@ export function PlaygroundChatPanel({
() =>
events.find((evt) => isInteractivePending(evt, "ask_user_permissions")) ??
null,
// eslint-disable-next-line react-hooks/exhaustive-deps
[events]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ export function useIntegrationsCategoryTableProps(
handleModelsTabChange,
} = params;

// eslint-disable-next-line react-hooks/preserve-manual-memoization
const tableProps = useMemo<CategoryTableContentProps>(
() => ({
category,
Expand Down
2 changes: 0 additions & 2 deletions src/modules/MainApp/Integrations/useIntegrationsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ export function useIntegrationsPage() {
[extensions, navigate]
);

// eslint-disable-next-line react-hooks/preserve-manual-memoization -- intentional: deps include hook objects whose methods are called
const handleCategoryChange = useCallback(
(cat: IntegrationCategory) => {
if (cat !== category) {
Expand Down Expand Up @@ -156,7 +155,6 @@ export function useIntegrationsPage() {
[accountsHook]
);

// eslint-disable-next-line react-hooks/preserve-manual-memoization -- intentional: deps include hook objects whose methods are called
const handleAddAction = useCallback(
(action: AddAction) => {
switch (action) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ const GitHubWorkItemsSurface: React.FC<GitHubWorkItemsSurfaceProps> = ({

useEffect(() => {
if (!loading && currentPage > totalLoadedPages) {
// eslint-disable-next-line react-hooks/set-state-in-effect -- Remote result shrinkage requires clamping the controlled page.
setCurrentPage(totalLoadedPages);
}
}, [currentPage, loading, setCurrentPage, totalLoadedPages]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ export function useBrowserStatusBar({
if (ref.current) return;
setStatusBarCallbacks({});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
isActive,
primarySidebarCollapsed,
Expand All @@ -148,5 +147,6 @@ export function useBrowserStatusBar({
setAddToAgent,
toastSuccess,
chatSentToastMessage,
isMountedRef,
]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ const IssuesContent: React.FC<IssuesContentProps> = memo(
openStatus,
]);

// eslint-disable-next-line react-hooks/incompatible-library -- TanStack Virtual exposes imperative helpers that cannot be memoized safely.
const issueListVirtualizer = useVirtualizer({
count: virtualRows.length,
getScrollElement: () => listRef.current,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ export function useTabLabelCollapse({
rafId = null;
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [enabled, tabsDependency, activeTabDependency]);
}, [enabled, tabsDependency, activeTabDependency, containerRef]);

return enabled && overflowCollapsed;
}
2 changes: 1 addition & 1 deletion src/store/repo/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export function isValidUUID(uuid: string | undefined | null): boolean {
*/
export function resetRepoStore(): void {
// Dynamic import to avoid circular dependency
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-var-requires -- Runtime require intentionally breaks the storage/atom import cycle.
const atoms = require("./atoms");

try {
Expand Down
1 change: 0 additions & 1 deletion src/util/secretScan/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ export function validateCustomPattern(pattern: string): string | null {
const trimmed = pattern.trim();
if (!trimmed) return null;
try {
// eslint-disable-next-line no-new
new RegExp(trimmed);
return null;
} catch (err) {
Expand Down
Loading