refactor: long-tail type-aware sweep (T3.c) (#759)

* refactor: long-tail type-aware sweep (T3.c)

Cluster T3.c — 15 files, 24 errors cleared.

Rules fixed:
- no-useless-default-assignment: 6 → 0 (mcp-server.ts — Zod .default() makes destructuring defaults redundant)
- no-unnecessary-type-assertion: 1 → 0 (workspace-registry-model.ts — remove redundant ! on string[])
- no-unsafe-enum-comparison: 3 → 0 (use-push-token-registration.ts, use-image-attachment-picker.ts — use PermissionStatus enum values)
- no-redundant-type-constituents: 6 → 0 (workspace-setup.ts, tool-call-detail-state.ts, workspace-draft-agent-tab.tsx, stream.test.ts, desktop-settings-commands.ts — unknown | T → unknown)
- no-unnecessary-type-parameters: 4 → 0 (indexeddb-attachment-store.test.ts, use-archive-agent.ts, class-mocks.ts, agent-stream-coalescer.ts — narrow interface / remove unused generics)
- no-unnecessary-type-conversion: 4 → 0 (session-context.tsx — remove String() on already-string values; class-mocks.ts — remove String(prop) after symbol guard)
- no-implied-eval: 1 → 0 (agent-stream-coalescer.test.ts — narrow timer interface to function-only, eliminating string overload)

Deferred (need caller updates or extra files beyond 15-file cap):
- no-unnecessary-type-parameters: host.ts:onResized/onDragDropEvent, electron/events.ts (callers pass typed handlers; removing generic breaks contravariance without cast)
- no-base-to-string: ~21 errors, 18 files
- restrict-template-expressions: ~11 errors, 9 files
- await-thenable: ~7 errors, 4 files
- no-unnecessary-type-conversion: ~9 remaining errors, 9 files

* fix(server): restore MCP tool handler defaults that the linter mis-flagged

The `no-useless-default-assignment` rule fires because Zod's `.default()`
chain makes the TypeScript type non-optional, so the linter treats the
destructuring defaults as redundant. But the MCP framework invokes
handlers with raw (untransformed) params — Zod defaults are not applied
before the call. The destructuring defaults are the runtime safety net.

Reverts the three handler changes from T3.c:
- send_prompt: background = false, notifyOnFinish = false
- list_agents: includeArchived = false, sinceHours = 48, limit = 50
- get_terminal_lines: stripAnsi = true

The no-useless-default-assignment errors on these lines remain and are
deferred to a future cluster that addresses the MCP framework integration.
This commit is contained in:
Mohamed Boudra
2026-05-05 22:38:55 +08:00
committed by GitHub
parent 2415858d8f
commit 60531b5e1b
13 changed files with 27 additions and 26 deletions
@@ -3,8 +3,8 @@ import { createIndexedDbAttachmentStore } from "./indexeddb-attachment-store";
type Listener = () => void;
class FakeRequest<T = unknown> {
result!: T;
class FakeRequest {
result!: unknown;
error: Error | null = null;
private listeners = new Map<string, Listener[]>();
@@ -70,7 +70,7 @@ describe("indexeddb attachment store", () => {
const store = new FakeObjectStore((record) => {
storedRecord = record;
});
const request = new FakeRequest<FakeDatabase>();
const request = new FakeRequest();
request.result = new FakeDatabase(store);
queueMicrotask(() => request.emit("success"));
return request;
+2 -2
View File
@@ -230,10 +230,10 @@ function getArchivedAgentListCacheSnapshot(
};
}
function restoreCachedQuerySnapshot<T>(
function restoreCachedQuerySnapshot(
queryClient: QueryClient,
queryKey: readonly unknown[],
snapshot: T | undefined,
snapshot: unknown,
): void {
if (snapshot === undefined) {
queryClient.removeQueries({ queryKey, exact: true });
@@ -20,7 +20,10 @@ export function useImageAttachmentPicker(): UseImageAttachmentPickerResult {
const ensurePermission = useCallback(async () => {
let currentPermission = mediaPermission;
if (!currentPermission || currentPermission.status === "undetermined") {
if (
!currentPermission ||
currentPermission.status === ImagePicker.PermissionStatus.UNDETERMINED
) {
currentPermission = await requestMediaPermission();
} else if (!currentPermission.granted) {
currentPermission = await requestMediaPermission();
@@ -24,10 +24,10 @@ function getExpoProjectId(): string | null {
async function ensurePushPermission(): Promise<boolean> {
const existing = await Notifications.getPermissionsAsync();
if (existing.status === "granted") return true;
if (existing.status === Notifications.PermissionStatus.GRANTED) return true;
if (!existing.canAskAgain) return false;
const requested = await Notifications.requestPermissionsAsync();
return requested.status === "granted";
return requested.status === Notifications.PermissionStatus.GRANTED;
}
export function usePushTokenRegistration(params: { client: DaemonClient; serverId: string }): void {
@@ -22,7 +22,7 @@ import { shouldAutoFocusWorkspaceDraftComposer } from "@/screens/workspace/works
import type { AgentCapabilityFlags } from "@server/server/agent/agent-sdk-types";
import type { AgentSnapshotPayload } from "@server/shared/messages";
import type { DaemonClient } from "@server/client/daemon-client";
import type { ComposerAttachment, WorkspaceComposerAttachment } from "@/attachments/types";
import type { WorkspaceComposerAttachment } from "@/attachments/types";
import {
useWorkspaceAttachments,
useWorkspaceAttachmentScopeKey,
@@ -147,7 +147,7 @@ async function submitDraftCreateRequest(input: {
attempt: { clientMessageId: string };
text: string;
images?: UserMessageImageAttachment[];
attachments?: ComposerAttachment[] | unknown;
attachments?: unknown;
client: DaemonClient | null;
workspaceDirectory: string | null;
workspaceExecutionAuthority: { workspaceId: string } | null;
+2 -2
View File
@@ -42,8 +42,8 @@ function canonicalToolTimeline(params: {
callId: string;
name: string;
status: CanonicalToolStatus;
input?: unknown | null;
output?: unknown | null;
input?: unknown;
output?: unknown;
error?: unknown;
metadata?: Record<string, unknown>;
detail?: ToolCallDetail;
@@ -96,7 +96,7 @@ export function hasMeaningfulToolCallDetail(detail: ToolCallDetail | undefined):
export function isPendingToolCallDetail(params: {
detail: ToolCallDetail | undefined;
status: "executing" | "running" | "completed" | "failed" | "canceled";
error: unknown | null | undefined;
error: unknown;
}): boolean {
const isRunning = params.status === "running" || params.status === "executing";
return isRunning && params.error == null && !hasMeaningfulToolCallDetail(params.detail);