diff --git a/.oxlintrc.json b/.oxlintrc.json index 51677b672..31f765836 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -1,14 +1,6 @@ { "$schema": "./node_modules/oxlint/configuration_schema.json", - "plugins": [ - "react", - "react-perf", - "unicorn", - "typescript", - "oxc", - "import", - "promise" - ], + "plugins": ["react", "react-perf", "unicorn", "typescript", "oxc", "import", "promise"], "categories": { "correctness": "warn", "suspicious": "warn", diff --git a/packages/app/e2e/helpers/app.ts b/packages/app/e2e/helpers/app.ts index faec0bc19..ab65c8524 100644 --- a/packages/app/e2e/helpers/app.ts +++ b/packages/app/e2e/helpers/app.ts @@ -156,7 +156,9 @@ async function assertE2EUsesSeededTestDaemon(page: Page): Promise { } } catch (error) { if (error instanceof Error) throw error; - throw new Error("E2E expected @paseo:create-agent-preferences to be valid JSON."); + throw new Error("E2E expected @paseo:create-agent-preferences to be valid JSON.", { + cause: error, + }); } } diff --git a/packages/app/e2e/startup-wire-metrics.spec.ts b/packages/app/e2e/startup-wire-metrics.spec.ts index 39b194d26..fca4e8dc2 100644 --- a/packages/app/e2e/startup-wire-metrics.spec.ts +++ b/packages/app/e2e/startup-wire-metrics.spec.ts @@ -368,7 +368,7 @@ function summarizeByType(records: WireFrameRecord[]): Array<{ byType.set(type, current); } return [...byType.entries()] - .map(([type, value]) => ({ type, ...value })) + .map(([type, value]) => Object.assign({ type }, value)) .sort((left, right) => right.bytes - left.bytes); } diff --git a/packages/app/e2e/terminal-alternate-screen.spec.ts b/packages/app/e2e/terminal-alternate-screen.spec.ts index 1054ea083..5bd502590 100644 --- a/packages/app/e2e/terminal-alternate-screen.spec.ts +++ b/packages/app/e2e/terminal-alternate-screen.spec.ts @@ -45,6 +45,7 @@ async function waitForAlternateScreenExit(page: Page, afterAlt: string, timeout: null, 2, )}`, + { cause: error }, ); } diff --git a/packages/app/metro.config.cjs b/packages/app/metro.config.cjs index de41c277d..1852ad545 100644 --- a/packages/app/metro.config.cjs +++ b/packages/app/metro.config.cjs @@ -22,7 +22,7 @@ const escapedAppSrcRoot = appSrcRoot const pathSeparatorPattern = "[\\\\/]"; config.resolver.extraNodeModules = { - ...(config.resolver.extraNodeModules ?? {}), + ...config.resolver.extraNodeModules, react: path.join(appNodeModulesRoot, "react"), "react-dom": path.join(appNodeModulesRoot, "react-dom"), "react/jsx-runtime": path.join(appNodeModulesRoot, "react/jsx-runtime"), diff --git a/packages/app/src/components/combined-model-selector.tsx b/packages/app/src/components/combined-model-selector.tsx index ec1d6cf3b..06abc0cc1 100644 --- a/packages/app/src/components/combined-model-selector.tsx +++ b/packages/app/src/components/combined-model-selector.tsx @@ -618,7 +618,7 @@ export function CombinedModelSelector({ }); return () => cancelAnimationFrame(frame); - }, [isOpen, platformIsWeb]); + }, [isOpen]); return ( <> diff --git a/packages/app/src/components/file-explorer-pane.tsx b/packages/app/src/components/file-explorer-pane.tsx index 7e2a1cacb..327ebbba2 100644 --- a/packages/app/src/components/file-explorer-pane.tsx +++ b/packages/app/src/components/file-explorer-pane.tsx @@ -287,14 +287,14 @@ export function FileExplorerPane({ directoryPaths.unshift("."); } - await Promise.all([ - ...directoryPaths.map((path) => + await Promise.all( + directoryPaths.map((path) => requestDirectoryListing(path, { recordHistory: false, setCurrentPath: false, }), ), - ]); + ); return null; }, enabled: false, diff --git a/packages/app/src/components/sidebar-workspace-list.tsx b/packages/app/src/components/sidebar-workspace-list.tsx index 47d56870b..eec143cd5 100644 --- a/packages/app/src/components/sidebar-workspace-list.tsx +++ b/packages/app/src/components/sidebar-workspace-list.tsx @@ -2158,7 +2158,6 @@ export function SidebarWorkspaceList({ serverId, shortcutIndexByWorkspaceKey, showShortcutBadges, - platformIsNative, creatingWorkspaceIds, ], ); diff --git a/packages/app/src/components/stream-strategy.ts b/packages/app/src/components/stream-strategy.ts index bca2508a4..c7f3f013b 100644 --- a/packages/app/src/components/stream-strategy.ts +++ b/packages/app/src/components/stream-strategy.ts @@ -122,8 +122,9 @@ export function createStreamStrategy(config: StreamStrategyConfig): StreamStrate return { render: config.render, orderTail: (streamItems) => - config.orderTailReverse ? [...streamItems].reverse() : streamItems, - orderHead: (streamHead) => (config.orderHeadReverse ? [...streamHead].reverse() : streamHead), + config.orderTailReverse ? [...streamItems].toReversed() : streamItems, + orderHead: (streamHead) => + config.orderHeadReverse ? [...streamHead].toReversed() : streamHead, getNeighborIndex: (index, relation) => relation === "above" ? index + config.assistantTurnTraversalStep @@ -153,7 +154,7 @@ export function createStreamStrategy(config: StreamStrategyConfig): StreamStrate messages.push(currentItem.text); } } - return messages.reverse().join("\n\n"); + return messages.toReversed().join("\n\n"); }, isNearBottom: (input) => config.isNearBottom(input), getBottomOffset: (metrics) => config.getBottomOffset(metrics), diff --git a/packages/app/src/components/ui/autocomplete-utils.ts b/packages/app/src/components/ui/autocomplete-utils.ts index 92f5c6e95..f8250856d 100644 --- a/packages/app/src/components/ui/autocomplete-utils.ts +++ b/packages/app/src/components/ui/autocomplete-utils.ts @@ -9,7 +9,7 @@ export function orderAutocompleteOptions( if (position === "below-input") { return [...options]; } - return [...options].reverse(); + return [...options].toReversed(); } export function getAutocompleteFallbackIndex( diff --git a/packages/app/src/components/ui/combobox-options.ts b/packages/app/src/components/ui/combobox-options.ts index 407c5bc99..06cfc107f 100644 --- a/packages/app/src/components/ui/combobox-options.ts +++ b/packages/app/src/components/ui/combobox-options.ts @@ -113,7 +113,7 @@ export function orderVisibleComboboxOptions( if (optionsPosition !== "above-search") { return visibleOptions; } - return [...visibleOptions].reverse(); + return [...visibleOptions].toReversed(); } export function getComboboxFallbackIndex( diff --git a/packages/app/src/components/web-desktop-scrollbar.tsx b/packages/app/src/components/web-desktop-scrollbar.tsx index cc4a944a2..ce0977038 100644 --- a/packages/app/src/components/web-desktop-scrollbar.tsx +++ b/packages/app/src/components/web-desktop-scrollbar.tsx @@ -279,26 +279,23 @@ export function WebDesktopScrollbarOverlay({ setIsDragging(false); }, }); - }, [applyDragDelta, platformIsWeb]); + }, [applyDragDelta]); - const startWebDrag = useCallback( - (event: any) => { - if (!platformIsWeb) { - return; - } - const clientY = readClientY(event); - if (clientY === null) { - return; - } - event?.preventDefault?.(); - event?.stopPropagation?.(); - event?.nativeEvent?.preventDefault?.(); - dragStartOffsetRef.current = normalizedOffsetRef.current; - dragStartClientYRef.current = clientY; - setIsDragging(true); - }, - [platformIsWeb], - ); + const startWebDrag = useCallback((event: any) => { + if (!platformIsWeb) { + return; + } + const clientY = readClientY(event); + if (clientY === null) { + return; + } + event?.preventDefault?.(); + event?.stopPropagation?.(); + event?.nativeEvent?.preventDefault?.(); + dragStartOffsetRef.current = normalizedOffsetRef.current; + dragStartClientYRef.current = clientY; + setIsDragging(true); + }, []); const handleGrabHoverIn = useCallback(() => { if (!isScrollVisible && !isDragging) { @@ -334,7 +331,7 @@ export function WebDesktopScrollbarOverlay({ window.removeEventListener("pointerup", stopDragging); window.removeEventListener("pointercancel", stopDragging); }; - }, [applyDragDelta, isDragging, platformIsWeb]); + }, [applyDragDelta, isDragging]); if (!enabled || !geometry.isVisible) { return null; diff --git a/packages/app/src/contexts/session-context.tsx b/packages/app/src/contexts/session-context.tsx index aa61ab253..6ad2f9c2c 100644 --- a/packages/app/src/contexts/session-context.tsx +++ b/packages/app/src/contexts/session-context.tsx @@ -1580,7 +1580,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider console.error("[Session] Failed to send agent message:", error); }); }, - [encodeImages, serverId, client, setAgentStreamTail, setAgentStreamHead], + [serverId, client, setAgentStreamTail, setAgentStreamHead], ); // Keep the ref updated so the agent_update handler can call it @@ -1677,7 +1677,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider ...(requestId ? { requestId } : {}), }); }, - [encodeImages, client], + [client], ); const setAgentMode = useCallback( diff --git a/packages/app/src/hooks/use-audio-recorder.native.ts b/packages/app/src/hooks/use-audio-recorder.native.ts index 459c56335..8babad104 100644 --- a/packages/app/src/hooks/use-audio-recorder.native.ts +++ b/packages/app/src/hooks/use-audio-recorder.native.ts @@ -227,7 +227,7 @@ export function useAudioRecorder(config?: AudioCaptureConfig) { if (error?.message !== "Recording cancelled") { console.error("[AudioRecorder] Failed to start recording:", error); } - throw new Error(`Failed to start audio recording: ${error.message}`); + throw new Error(`Failed to start audio recording: ${error.message}`, { cause: error }); } }, [recordingOptions.sampleRate, recordingOptions.numberOfChannels, recordingOptions.bitRate]); @@ -293,7 +293,7 @@ export function useAudioRecorder(config?: AudioCaptureConfig) { } catch (error: any) { setRecordingStartTime(null); console.error("[AudioRecorder] Failed to stop recording:", error); - throw new Error(`Failed to stop audio recording: ${error.message}`); + throw new Error(`Failed to stop audio recording: ${error.message}`, { cause: error }); } finally { startStopMutexRef.current = null; } diff --git a/packages/app/src/hooks/use-audio-recorder.web.ts b/packages/app/src/hooks/use-audio-recorder.web.ts index 170b44a36..2e783bac3 100644 --- a/packages/app/src/hooks/use-audio-recorder.web.ts +++ b/packages/app/src/hooks/use-audio-recorder.web.ts @@ -190,7 +190,7 @@ export function useAudioRecorder(config?: AudioCaptureConfig) { try { stream = await navigator.mediaDevices.getUserMedia(constraints); } catch (error: any) { - throw new Error(`Failed to access microphone: ${error?.message ?? error}`); + throw new Error(`Failed to access microphone: ${error?.message ?? error}`, { cause: error }); } try { @@ -225,7 +225,9 @@ export function useAudioRecorder(config?: AudioCaptureConfig) { recorder = new MediaRecorder(stream, recorderOptions); } catch (error: any) { cleanupStream(); - throw new Error(`Failed to initialize recorder: ${error?.message ?? error}`); + throw new Error(`Failed to initialize recorder: ${error?.message ?? error}`, { + cause: error, + }); } mediaRecorderRef.current = recorder; diff --git a/packages/app/src/runtime/host-runtime.ts b/packages/app/src/runtime/host-runtime.ts index 2beb4c2b0..ae0b24650 100644 --- a/packages/app/src/runtime/host-runtime.ts +++ b/packages/app/src/runtime/host-runtime.ts @@ -1530,13 +1530,13 @@ export class HostRuntimeStore { this.emit(host.serverId); }); void controller - .start({ - ...(initialConnection + .start( + initialConnection ? { initialConnection, } - : {}), - }) + : {}, + ) .catch((error) => { const message = error instanceof Error ? error.message : String(error); controller.markStartupError(message); diff --git a/packages/app/src/screens/new-workspace-screen.tsx b/packages/app/src/screens/new-workspace-screen.tsx index 29c0af402..aa79d92ac 100644 --- a/packages/app/src/screens/new-workspace-screen.tsx +++ b/packages/app/src/screens/new-workspace-screen.tsx @@ -292,7 +292,7 @@ export function NewWorkspaceScreen({ cwd: input.cwd, worktreeSlug: createNameId(), ...(input.attachments.length > 0 ? { attachments: input.attachments } : {}), - ...(checkoutRequest ?? {}), + ...checkoutRequest, }; }, [selectedItem], diff --git a/packages/app/src/stores/checkout-git-actions-store.ts b/packages/app/src/stores/checkout-git-actions-store.ts index a47c51809..70d78e2fc 100644 --- a/packages/app/src/stores/checkout-git-actions-store.ts +++ b/packages/app/src/stores/checkout-git-actions-store.ts @@ -53,7 +53,7 @@ function setStatus( statusByCheckout: { ...state.statusByCheckout, [key]: { - ...(state.statusByCheckout[key] ?? {}), + ...state.statusByCheckout[key], [actionId]: status, }, }, diff --git a/packages/app/src/stores/workspace-layout-store.ts b/packages/app/src/stores/workspace-layout-store.ts index 91585d504..d422cd070 100644 --- a/packages/app/src/stores/workspace-layout-store.ts +++ b/packages/app/src/stores/workspace-layout-store.ts @@ -531,7 +531,7 @@ export const useWorkspaceLayoutStore = create()( splitSizesByWorkspace: { ...state.splitSizesByWorkspace, [normalizedWorkspaceKey]: { - ...(state.splitSizesByWorkspace[normalizedWorkspaceKey] ?? {}), + ...state.splitSizesByWorkspace[normalizedWorkspaceKey], [normalizedGroupId]: clampNormalizedSizes(sizes), }, }, diff --git a/packages/cli/src/commands/agent/run.ts b/packages/cli/src/commands/agent/run.ts index adbbfb6a9..b9c00475a 100644 --- a/packages/cli/src/commands/agent/run.ts +++ b/packages/cli/src/commands/agent/run.ts @@ -325,7 +325,7 @@ export async function runRunCommand( }; } catch (err) { const message = err instanceof Error ? err.message : String(err); - throw new Error(`Failed to read image ${imagePath}: ${message}`); + throw new Error(`Failed to read image ${imagePath}: ${message}`, { cause: err }); } }); } diff --git a/packages/cli/src/commands/daemon/status.ts b/packages/cli/src/commands/daemon/status.ts index fa2b0f0fa..a019f5855 100644 --- a/packages/cli/src/commands/daemon/status.ts +++ b/packages/cli/src/commands/daemon/status.ts @@ -193,7 +193,7 @@ async function checkProviderBinaries(): Promise { const results = await Promise.all( PROVIDER_BINARIES.map(async ({ label, binary }) => { const result = await checkProviderBinary(binary); - return { label, ...result }; + return Object.assign({ label }, result); }), ); return results; diff --git a/packages/cli/tests/helpers/test-daemon.ts b/packages/cli/tests/helpers/test-daemon.ts index 144081fbe..ec48a3ebd 100644 --- a/packages/cli/tests/helpers/test-daemon.ts +++ b/packages/cli/tests/helpers/test-daemon.ts @@ -315,6 +315,7 @@ export async function startTestDaemon(options?: { const message = err instanceof Error ? err.message : String(err); throw new Error( `Failed to start test daemon: ${message}\nStdout: ${formatOutputCapture(stdout)}\nStderr: ${formatOutputCapture(stderr)}`, + { cause: err }, ); } diff --git a/packages/desktop/src/daemon/daemon-manager.ts b/packages/desktop/src/daemon/daemon-manager.ts index 57571503b..62d35a347 100644 --- a/packages/desktop/src/daemon/daemon-manager.ts +++ b/packages/desktop/src/daemon/daemon-manager.ts @@ -153,7 +153,7 @@ function tailFile(filePath: string, lines = 50): string { function logDesktopDaemonLifecycle(message: string, details?: Record): void { log.info("[desktop daemon]", message, { pid: process.pid, - ...(details ?? {}), + ...details, }); } diff --git a/packages/desktop/src/daemon/runtime-paths.ts b/packages/desktop/src/daemon/runtime-paths.ts index 8eaae01da..d719123a3 100644 --- a/packages/desktop/src/daemon/runtime-paths.ts +++ b/packages/desktop/src/daemon/runtime-paths.ts @@ -349,6 +349,7 @@ export async function runCliJsonCommand(args: string[]): Promise { } catch (error) { throw new Error( `CLI command returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`, + { cause: error }, ); } } diff --git a/packages/server/src/server/agent/agent-manager.ts b/packages/server/src/server/agent/agent-manager.ts index 072c1309a..214ddcce6 100644 --- a/packages/server/src/server/agent/agent-manager.ts +++ b/packages/server/src/server/agent/agent-manager.ts @@ -267,7 +267,7 @@ function attachPersistenceCwd( return { ...handle, metadata: { - ...(handle.metadata ?? {}), + ...handle.metadata, cwd, }, }; @@ -278,11 +278,11 @@ type SubscriptionRecord = { agentId: string | null; }; -const BUSY_STATUSES: AgentLifecycleStatus[] = ["initializing", "running"]; +const BUSY_STATUSES: AgentLifecycleStatus[] = new Set(["initializing", "running"]); const AgentIdSchema = z.string().uuid(); function isAgentBusy(status: AgentLifecycleStatus): boolean { - return BUSY_STATUSES.includes(status); + return BUSY_STATUSES.has(status); } function isTurnTerminalEvent(event: AgentStreamEvent): boolean { @@ -649,7 +649,7 @@ export class AgentManager { type: "http" as const, url: `${this.mcpBaseUrl}?callerAgentId=${resolvedAgentId}`, }, - ...(config.mcpServers ?? {}), + ...config.mcpServers, }, }; const normalizedConfig = await this.normalizeConfig(injectedConfig); @@ -1708,7 +1708,7 @@ export class AgentManager { } return { - text: chunks.reverse().join(""), + text: chunks.toReversed().join(""), startsAtBeginning, }; } @@ -2847,12 +2847,12 @@ export class AgentManager { "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT" ) { - throw new Error(`Working directory does not exist: ${normalized.cwd}`); + throw new Error(`Working directory does not exist: ${normalized.cwd}`, { cause: error }); } if (error instanceof Error) { throw error; } - throw new Error(`Failed to access working directory: ${normalized.cwd}`); + throw new Error(`Failed to access working directory: ${normalized.cwd}`, { cause: error }); } } diff --git a/packages/server/src/server/agent/agent-timeline-store.ts b/packages/server/src/server/agent/agent-timeline-store.ts index c3b2ecd01..53248d4db 100644 --- a/packages/server/src/server/agent/agent-timeline-store.ts +++ b/packages/server/src/server/agent/agent-timeline-store.ts @@ -244,7 +244,7 @@ export class InMemoryAgentTimelineStore { return null; } - return chunks.reverse().join(""); + return chunks.toReversed().join(""); } getCanonicalUserMessagesById(agentId: string): Map { diff --git a/packages/server/src/server/agent/mcp-server.ts b/packages/server/src/server/agent/mcp-server.ts index 5fe6e060e..5dff74ae9 100644 --- a/packages/server/src/server/agent/mcp-server.ts +++ b/packages/server/src/server/agent/mcp-server.ts @@ -666,8 +666,8 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom const childAgentDefaultLabels = callerContext?.childAgentDefaultLabels; const mergedLabels = { ...(callerAgentId ? { "paseo.parent-agent-id": callerAgentId } : {}), - ...(childAgentDefaultLabels ?? {}), - ...(labels ?? {}), + ...childAgentDefaultLabels, + ...labels, }; const snapshot = await agentManager.createAgent( { diff --git a/packages/server/src/server/agent/provider-launch-config.ts b/packages/server/src/server/agent/provider-launch-config.ts index d8ca845da..49867ac59 100644 --- a/packages/server/src/server/agent/provider-launch-config.ts +++ b/packages/server/src/server/agent/provider-launch-config.ts @@ -185,7 +185,7 @@ export function applyProviderEnv( ): Record { const merged: Record = { ...baseEnv, - ...(runtimeSettings?.env ?? {}), + ...runtimeSettings?.env, }; for (const key of PARENT_SESSION_ENV_VARS) { delete merged[key]; diff --git a/packages/server/src/server/agent/provider-registry.ts b/packages/server/src/server/agent/provider-registry.ts index 1f04bb206..482db8aa6 100644 --- a/packages/server/src/server/agent/provider-registry.ts +++ b/packages/server/src/server/agent/provider-registry.ts @@ -130,8 +130,8 @@ function mergeRuntimeSettings( env: base?.env || override?.env ? { - ...(base?.env ?? {}), - ...(override?.env ?? {}), + ...base?.env, + ...override?.env, } : undefined, disallowedTools: diff --git a/packages/server/src/server/agent/providers/acp-agent.ts b/packages/server/src/server/agent/providers/acp-agent.ts index 988defdac..5244af210 100644 --- a/packages/server/src/server/agent/providers/acp-agent.ts +++ b/packages/server/src/server/agent/providers/acp-agent.ts @@ -516,9 +516,9 @@ export class ACPAgentClient implements AgentClient { const sessions: PersistedAgentDescriptor[] = []; let cursor: string | null | undefined; do { - const page: ListSessionsResponse = await probe.connection.listSessions({ - ...(cursor ? { cursor } : {}), - }); + const page: ListSessionsResponse = await probe.connection.listSessions( + cursor ? { cursor } : {}, + ); for (const session of page.sessions) { sessions.push({ provider: this.provider, @@ -566,7 +566,7 @@ export class ACPAgentClient implements AgentClient { process.env as Record, this.runtimeSettings, ), - ...(launchEnv ?? {}), + ...launchEnv, }, stdio: ["pipe", "pipe", "pipe"], }) as ChildProcessWithoutNullStreams; @@ -1413,7 +1413,7 @@ export class ACPAgentSession implements AgentSession, ACPClient { process.env as Record, this.runtimeSettings, ), - ...(this.launchEnv ?? {}), + ...this.launchEnv, }, stdio: ["pipe", "pipe", "pipe"], }) as ChildProcessWithoutNullStreams; diff --git a/packages/server/src/server/agent/providers/claude-agent.integration.test.ts b/packages/server/src/server/agent/providers/claude-agent.integration.test.ts index 49bd8331c..8bc531dd8 100644 --- a/packages/server/src/server/agent/providers/claude-agent.integration.test.ts +++ b/packages/server/src/server/agent/providers/claude-agent.integration.test.ts @@ -131,7 +131,7 @@ function getToolCalls(events: AgentStreamEvent[]): ToolCallTimelineItem[] { function getLatestCompletedBashCall(events: AgentStreamEvent[]): ToolCallTimelineItem | undefined { return [...getToolCalls(events)] - .reverse() + .toReversed() .find((item) => item.status === "completed" && item.name.toLowerCase() === "bash"); } diff --git a/packages/server/src/server/agent/providers/claude-agent.ts b/packages/server/src/server/agent/providers/claude-agent.ts index b08c54809..cf27e788f 100644 --- a/packages/server/src/server/agent/providers/claude-agent.ts +++ b/packages/server/src/server/agent/providers/claude-agent.ts @@ -220,7 +220,7 @@ function applyRuntimeSettingsToClaudeOptions( cwd: spawnOptions.cwd, env: { ...applyProviderEnv(spawnOptions.env, runtimeSettings), - ...(launchEnv ?? {}), + ...launchEnv, }, signal: spawnOptions.signal, stdio: ["pipe", "pipe", "pipe"], @@ -1057,7 +1057,7 @@ export function readEventIdentifiers(message: SDKMessage): EventIdentifiers { const claudeDebug = process.env.PASEO_CLAUDE_DEBUG === "1"; export class ClaudeAgentClient implements AgentClient { - readonly provider: "claude" = "claude"; + readonly provider = "claude" as const; readonly capabilities = CLAUDE_CAPABILITIES; private readonly defaults?: { agents?: Record }; @@ -1347,7 +1347,7 @@ function readStreamRequestOutputTokens(event: Record): number | } class ClaudeAgentSession implements AgentSession { - readonly provider: "claude" = "claude"; + readonly provider = "claude" as const; readonly capabilities = CLAUDE_CAPABILITIES; private readonly config: ClaudeAgentConfig; @@ -2174,7 +2174,7 @@ class ClaudeAgentSession implements AgentSession { // Increase MCP timeouts for long-running tool calls (10 minutes) MCP_TIMEOUT: "600000", MCP_TOOL_TIMEOUT: "600000", - ...(this.launchEnv ?? {}), + ...this.launchEnv, }, // Required for provider-level /rewind support. enableFileCheckpointing: true, diff --git a/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts b/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts index 441f24026..028170ce5 100644 --- a/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts +++ b/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts @@ -96,11 +96,12 @@ export class ClaudeSidechainTracker { action.summary ? `[${action.toolName}] ${action.summary}` : `[${action.toolName}]`, ) .join("\n"), - actions: state.actions.map((action) => ({ - index: action.index, - toolName: action.toolName, - ...(action.summary ? { summary: action.summary } : {}), - })), + actions: state.actions.map((action) => + Object.assign( + { index: action.index, toolName: action.toolName }, + action.summary ? { summary: action.summary } : {}, + ), + ), }; return [ diff --git a/packages/server/src/server/agent/providers/codex-app-server-agent.e2e.test.ts b/packages/server/src/server/agent/providers/codex-app-server-agent.e2e.test.ts index 00dbb8ac7..d0f1303ac 100644 --- a/packages/server/src/server/agent/providers/codex-app-server-agent.e2e.test.ts +++ b/packages/server/src/server/agent/providers/codex-app-server-agent.e2e.test.ts @@ -387,7 +387,7 @@ describe("Codex app-server provider (e2e)", () => { ).toBe(true); const finalAssistantMessage = [...events] - .reverse() + .toReversed() .find((event) => event.type === "timeline" && event.item.type === "assistant_message"); expect(finalAssistantMessage).toBeDefined(); if ( diff --git a/packages/server/src/server/agent/providers/codex-app-server-agent.ts b/packages/server/src/server/agent/providers/codex-app-server-agent.ts index 7216342a9..d0b80ad8c 100644 --- a/packages/server/src/server/agent/providers/codex-app-server-agent.ts +++ b/packages/server/src/server/agent/providers/codex-app-server-agent.ts @@ -1408,11 +1408,13 @@ function mapCodexPatchNotificationToToolCall(params: { : { ...(files.length > 0 ? { - files: files.map((file) => ({ - path: file.path, - ...(file.kind ? { kind: file.kind } : {}), - ...codexPatchTextFields(file.content ?? patchText), - })), + files: files.map((file) => + Object.assign( + { path: file.path }, + file.kind ? { kind: file.kind } : {}, + codexPatchTextFields(file.content ?? patchText), + ), + ), } : {}), ...(params.stdout ? { stdout: params.stdout } : {}), @@ -2667,7 +2669,7 @@ class CodexAppServerAgentSession implements AgentSession { private applyFeatureValue(featureId: "fast_mode" | "plan_mode", value: boolean): void { this.config.featureValues = { - ...(this.config.featureValues ?? {}), + ...this.config.featureValues, [featureId]: value, }; diff --git a/packages/server/src/server/agent/providers/codex/tool-call-mapper.ts b/packages/server/src/server/agent/providers/codex/tool-call-mapper.ts index ec0726286..60f433665 100644 --- a/packages/server/src/server/agent/providers/codex/tool-call-mapper.ts +++ b/packages/server/src/server/agent/providers/codex/tool-call-mapper.ts @@ -764,19 +764,18 @@ function mapFileChangeItem( ): CodexNormalizedToolCallEnvelope { const files = parseFileChangeEntries(item.changes, options); - const inputBase = { - ...(files.length > 0 + const inputBase = + files.length > 0 ? { files: files.map((file) => ({ path: file.path, ...(file.kind !== undefined ? { kind: file.kind } : {}), })), } - : {}), - }; + : {}; - const output = toNullableObject({ - ...(files.length > 0 + const output = toNullableObject( + files.length > 0 ? { files: files.map((file) => ({ path: file.path, @@ -786,8 +785,8 @@ function mapFileChangeItem( : asEditFileOutputFields(file.diff)), })), } - : {}), - }); + : {}, + ); const name = "apply_patch"; const error = item.error ?? null; diff --git a/packages/server/src/server/agent/providers/opencode-agent.ts b/packages/server/src/server/agent/providers/opencode-agent.ts index 05b529972..1fa98298b 100644 --- a/packages/server/src/server/agent/providers/opencode-agent.ts +++ b/packages/server/src/server/agent/providers/opencode-agent.ts @@ -948,7 +948,7 @@ type OpenCodeServerGeneration = { }; export class OpenCodeAgentClient implements AgentClient { - readonly provider: "opencode" = "opencode"; + readonly provider = "opencode" as const; readonly capabilities = OPENCODE_CAPABILITIES; private readonly serverManager: OpenCodeServerManager; @@ -1667,7 +1667,7 @@ export function translateOpenCodeEvent( input: { questions }, metadata: { source: "opencode_question", - ...(event.properties.tool ?? {}), + ...event.properties.tool, }, }, }); @@ -1757,7 +1757,7 @@ export function translateOpenCodeEvent( } class OpenCodeAgentSession implements AgentSession { - readonly provider: "opencode" = "opencode"; + readonly provider = "opencode" as const; readonly capabilities = OPENCODE_CAPABILITIES; private readonly config: OpenCodeAgentConfig; diff --git a/packages/server/src/server/agent/providers/provider-windows-launch.test.ts b/packages/server/src/server/agent/providers/provider-windows-launch.test.ts index a56c1d7d9..72dff9f96 100644 --- a/packages/server/src/server/agent/providers/provider-windows-launch.test.ts +++ b/packages/server/src/server/agent/providers/provider-windows-launch.test.ts @@ -55,7 +55,7 @@ console.log("ARGV_OK"); const shim = path.join(root, `${binaryName}.cmd`); writeFileSync( shim, - ["@echo off", "setlocal", `\"${fakeDaemonNode}\" \"${assertScript}\" %*`, ""].join("\r\n"), + ["@echo off", "setlocal", `"${fakeDaemonNode}" "${assertScript}" %*`, ""].join("\r\n"), ); return { root, shim, expectedArgs }; diff --git a/packages/server/src/server/agent/timeline-projection.ts b/packages/server/src/server/agent/timeline-projection.ts index 84ccd663a..bac08fd69 100644 --- a/packages/server/src/server/agent/timeline-projection.ts +++ b/packages/server/src/server/agent/timeline-projection.ts @@ -79,7 +79,7 @@ function mergeToolCallItems( const mergedDetail = mergeToolCallDetail(existing.detail, incoming.detail); const mergedMetadata = existing.metadata || incoming.metadata - ? { ...(existing.metadata ?? {}), ...(incoming.metadata ?? {}) } + ? { ...existing.metadata, ...incoming.metadata } : undefined; const merged: Extract = { diff --git a/packages/server/src/server/daemon-e2e/checkout-diff-subscription.e2e.test.ts b/packages/server/src/server/daemon-e2e/checkout-diff-subscription.e2e.test.ts index 041a24a74..f4cb8645a 100644 --- a/packages/server/src/server/daemon-e2e/checkout-diff-subscription.e2e.test.ts +++ b/packages/server/src/server/daemon-e2e/checkout-diff-subscription.e2e.test.ts @@ -92,8 +92,8 @@ describe("daemon E2E checkout diff subscriptions", () => { writeFileSync(path.join(cwd, "alpha.txt"), "alpha\n"); const update = await waitForCheckoutDiffUpdate(ctx, subscriptionId, (payload) => { - const paths = payload.files.map((file) => file.path); - return paths.includes("alpha.txt") && paths.includes("zeta.txt"); + const paths = new Set(payload.files.map((file) => file.path)); + return paths.has("alpha.txt") && paths.has("zeta.txt"); }); expect(update.error).toBeNull(); diff --git a/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts b/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts index bf624bb83..15fd9d2c8 100644 --- a/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts +++ b/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts @@ -26,7 +26,7 @@ const BACKGROUND_TASK_SLEEP_5_PROMPT = [ const BACKGROUND_TASK_SLEEP_5_REPEAT_PROMPT = `do it again: ${BACKGROUND_TASK_SLEEP_5_PROMPT}`; function sanitizeClaudeProjectPath(cwd: string): string { - return cwd.replace(/[\\/\.]/g, "-").replace(/_/g, "-"); + return cwd.replace(/[\\/.]/g, "-").replace(/_/g, "-"); } function resolveClaudeTranscriptPath(params: { cwd: string; sessionId: string }): string { @@ -169,13 +169,13 @@ function extractTranscriptRaceEvidence( const userLines = lines.filter((line) => line.type === "user"); const assistantLines = lines.filter((line) => line.type === "assistant"); const doItAgain = [...userLines] - .reverse() + .toReversed() .find((line) => readUserText(line).toLowerCase().includes("do it again")); const isHelloPrompt = (line: ClaudeTranscriptLine): boolean => { const text = readUserText(line).trim().toLowerCase(); return text === "hello" || text === "say exactly hello"; }; - const helloUser = [...userLines].reverse().find((line) => isHelloPrompt(line)); + const helloUser = [...userLines].toReversed().find((line) => isHelloPrompt(line)); if (!doItAgain || !helloUser || typeof helloUser.uuid !== "string") { return null; @@ -201,7 +201,7 @@ function extractTranscriptRaceEvidence( return readUserText(line).includes(""); }); const taskNotificationUser = - [...taskNotificationCandidates].reverse().find((line) => parseTimestamp(line) >= helloTs) ?? + [...taskNotificationCandidates].toReversed().find((line) => parseTimestamp(line) >= helloTs) ?? taskNotificationCandidates[0]; if (!taskNotificationUser || typeof taskNotificationUser.uuid !== "string") { return null; diff --git a/packages/server/src/server/daemon-e2e/connection-offer.e2e.test.ts b/packages/server/src/server/daemon-e2e/connection-offer.e2e.test.ts index 2c065c93c..3ce0aa71d 100644 --- a/packages/server/src/server/daemon-e2e/connection-offer.e2e.test.ts +++ b/packages/server/src/server/daemon-e2e/connection-offer.e2e.test.ts @@ -260,7 +260,9 @@ describe("ConnectionOfferV2 (daemon E2E)", () => { expect(sawListeningLog).toBe(true); } catch (err) { - throw new Error(`failed; stdout so far:\\n${stdoutLines.join("")}\\n\\n${String(err)}`); + throw new Error(`failed; stdout so far:\\n${stdoutLines.join("")}\\n\\n${String(err)}`, { + cause: err, + }); } finally { proc.kill(); await rm(tempHome, { recursive: true, force: true }); diff --git a/packages/server/src/server/logger.ts b/packages/server/src/server/logger.ts index 981ceb798..76f85efd3 100644 --- a/packages/server/src/server/logger.ts +++ b/packages/server/src/server/logger.ts @@ -37,7 +37,7 @@ type ResolveLogConfigOptions = { env?: NodeJS.ProcessEnv; }; -const LOG_LEVELS: LogLevel[] = ["trace", "debug", "info", "warn", "error", "fatal"]; +const LOG_LEVELS: LogLevel[] = new Set(["trace", "debug", "info", "warn", "error", "fatal"]); const LOG_FORMATS: LogFormat[] = ["pretty", "json"]; const LOG_LEVEL_PRIORITIES: Record = { trace: 10, @@ -56,7 +56,7 @@ const DEFAULT_FILE_ROTATE_MAX_FILES = 2; const DEFAULT_DAEMON_LOG_FILENAME = "daemon.log"; function parseLogLevel(value: string | undefined): LogLevel | undefined { - if (!value || !LOG_LEVELS.includes(value as LogLevel)) { + if (!value || !LOG_LEVELS.has(value as LogLevel)) { return undefined; } return value as LogLevel; @@ -158,7 +158,7 @@ function rotateOnRestart(filePath: string, maxFiles: number): void { const rotatedFiles = readdirSync(dir) .filter((f) => f.endsWith(`-${base}`) && f !== base) .sort() - .reverse(); + .toReversed(); for (const file of rotatedFiles.slice(maxFiles)) { try { diff --git a/packages/server/src/server/persisted-config.ts b/packages/server/src/server/persisted-config.ts index 362369932..a96ef7f69 100644 --- a/packages/server/src/server/persisted-config.ts +++ b/packages/server/src/server/persisted-config.ts @@ -362,7 +362,7 @@ export function loadPersistedConfig(paseoHome: string, logger?: LoggerLike): Per log?.info(`Initialized config file at ${configPath}`); } catch (err) { const message = err instanceof Error ? err.message : String(err); - throw new Error(`[Config] Failed to initialize ${configPath}: ${message}`); + throw new Error(`[Config] Failed to initialize ${configPath}: ${message}`, { cause: err }); } } @@ -371,7 +371,7 @@ export function loadPersistedConfig(paseoHome: string, logger?: LoggerLike): Per raw = readFileSync(configPath, "utf-8"); } catch (err) { const message = err instanceof Error ? err.message : String(err); - throw new Error(`[Config] Failed to read ${configPath}: ${message}`); + throw new Error(`[Config] Failed to read ${configPath}: ${message}`, { cause: err }); } let parsed: unknown; @@ -379,7 +379,7 @@ export function loadPersistedConfig(paseoHome: string, logger?: LoggerLike): Per parsed = JSON.parse(raw); } catch (err) { const message = err instanceof Error ? err.message : String(err); - throw new Error(`[Config] Invalid JSON in ${configPath}: ${message}`); + throw new Error(`[Config] Invalid JSON in ${configPath}: ${message}`, { cause: err }); } const migrated = stripDeprecatedLocalSpeechConfigFields(parsed); @@ -416,6 +416,6 @@ export function savePersistedConfig( log?.info(`Saved to ${configPath}`); } catch (err) { const message = err instanceof Error ? err.message : String(err); - throw new Error(`[Config] Failed to write ${configPath}: ${message}`); + throw new Error(`[Config] Failed to write ${configPath}: ${message}`, { cause: err }); } } diff --git a/packages/server/src/server/session.ts b/packages/server/src/server/session.ts index d011aa230..c32fb1dac 100644 --- a/packages/server/src/server/session.ts +++ b/packages/server/src/server/session.ts @@ -3665,7 +3665,9 @@ export class Session { const snapshot = await this.workspaceGitService.getSnapshot(cwd); return snapshot.git.isDirty === true; } catch (error) { - throw new Error(`Unable to inspect git status for ${cwd}: ${(error as Error).message}`); + throw new Error(`Unable to inspect git status for ${cwd}: ${(error as Error).message}`, { + cause: error, + }); } } @@ -7452,7 +7454,7 @@ export class Session { const final = await this.getAgentPayloadById(agentId); if (!final) { - throw new Error(`Agent ${agentId} disappeared while waiting`); + throw new Error(`Agent ${agentId} disappeared while waiting`, { cause: error }); } this.emit({ type: "wait_for_finish_response", @@ -8721,11 +8723,12 @@ export class Session { this.emitTerminalsChangedSnapshot({ cwd: event.cwd, - terminals: this.filterStandaloneTerminals(event.terminals).map((terminal) => ({ - id: terminal.id, - name: terminal.name, - ...(terminal.title ? { title: terminal.title } : {}), - })), + terminals: this.filterStandaloneTerminals(event.terminals).map((terminal) => + Object.assign( + { id: terminal.id, name: terminal.name }, + terminal.title ? { title: terminal.title } : {}, + ), + ), }); } diff --git a/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts b/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts index 98a6ee8fe..2b7e05b68 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts @@ -208,10 +208,7 @@ export type SherpaOnnxModelSpec = SherpaOnnxCatalogEntry & { }; export function listSherpaOnnxModels(): SherpaOnnxModelSpec[] { - return ALL_MODEL_IDS.map((id) => ({ - id, - ...SHERPA_ONNX_MODEL_CATALOG[id], - })); + return ALL_MODEL_IDS.map((id) => Object.assign({ id }, SHERPA_ONNX_MODEL_CATALOG[id])); } export function getSherpaOnnxModelSpec(id: SherpaOnnxModelId): SherpaOnnxModelSpec { diff --git a/packages/server/src/server/speech/providers/openai/stt.ts b/packages/server/src/server/speech/providers/openai/stt.ts index eba3123b0..8ad596972 100644 --- a/packages/server/src/server/speech/providers/openai/stt.ts +++ b/packages/server/src/server/speech/providers/openai/stt.ts @@ -245,7 +245,7 @@ export class OpenAISTT implements SpeechToTextProvider { }; } catch (error: any) { logger.error({ err: error }, "Transcription error"); - throw new Error(`STT transcription failed: ${error.message}`); + throw new Error(`STT transcription failed: ${error.message}`, { cause: error }); } finally { if (tempFilePath) { try { diff --git a/packages/server/src/server/speech/providers/openai/tts.ts b/packages/server/src/server/speech/providers/openai/tts.ts index 145f1c47c..2700ac7aa 100644 --- a/packages/server/src/server/speech/providers/openai/tts.ts +++ b/packages/server/src/server/speech/providers/openai/tts.ts @@ -76,7 +76,7 @@ export class OpenAITTS implements TextToSpeechProvider { }; } catch (error: any) { this.logger.error({ err: error }, "Speech synthesis error"); - throw new Error(`TTS synthesis failed: ${error.message}`); + throw new Error(`TTS synthesis failed: ${error.message}`, { cause: error }); } } } diff --git a/packages/server/src/server/test-utils/fake-agent-client.ts b/packages/server/src/server/test-utils/fake-agent-client.ts index 6d0cce1ce..a92e362e9 100644 --- a/packages/server/src/server/test-utils/fake-agent-client.ts +++ b/packages/server/src/server/test-utils/fake-agent-client.ts @@ -88,7 +88,7 @@ function buildPersistence( metadata?: Record, ): AgentPersistenceHandle { if (provider === "codex") { - return { provider, sessionId, metadata: { conversationId: sessionId, ...(metadata ?? {}) } }; + return { provider, sessionId, metadata: { conversationId: sessionId, ...metadata } }; } return { provider, sessionId, ...(metadata ? { metadata } : {}) }; } @@ -150,7 +150,7 @@ function buildToolCallForPrompt(provider: string, prompt: string) { return { name: "apply_patch", input: { patch: "*** Begin Patch\n*** End Patch\n" }, output }; } const printfMatch = - /printf\s+\"ok\"\s*>\s*([^\s`]+)/i.exec(text) ?? /printf\s+ok\s*>\s*([^\s`]+)/i.exec(text); + /printf\s+"ok"\s*>\s*([^\s`]+)/i.exec(text) ?? /printf\s+ok\s*>\s*([^\s`]+)/i.exec(text); if (printfMatch) { const fileName = printfMatch[1] ?? "permission.txt"; return { diff --git a/packages/server/src/server/voice-roundtrip.e2e.test.ts b/packages/server/src/server/voice-roundtrip.e2e.test.ts index b962f47fb..59d8eda3d 100644 --- a/packages/server/src/server/voice-roundtrip.e2e.test.ts +++ b/packages/server/src/server/voice-roundtrip.e2e.test.ts @@ -285,6 +285,7 @@ describe("voice roundtrip e2e", () => { } catch (error) { throw new Error( `${error instanceof Error ? error.message : String(error)} | requestedVoiceAgentId=${voiceAgentId} | timelineTools=${JSON.stringify(timelineTools)} | timelineToolAgentIds=${JSON.stringify(Array.from(timelineToolAgentIds))} | activityErrors=${JSON.stringify(activityErrors)}`, + { cause: error }, ); } finally { offStream(); diff --git a/packages/server/src/server/worktree-session.ts b/packages/server/src/server/worktree-session.ts index 9dfd8687a..77c9ae5f5 100644 --- a/packages/server/src/server/worktree-session.ts +++ b/packages/server/src/server/worktree-session.ts @@ -46,7 +46,7 @@ import { } from "./paseo-worktree-archive-service.js"; import { toWorktreeWireError } from "./worktree-errors.js"; -const SAFE_GIT_REF_PATTERN = /^[A-Za-z0-9._\/-]+$/; +const SAFE_GIT_REF_PATTERN = /^[A-Za-z0-9._/-]+$/; export interface NormalizedGitOptions { baseBranch?: string; diff --git a/packages/server/src/shared/agent-attention-notification.ts b/packages/server/src/shared/agent-attention-notification.ts index 2cd6a2b4d..c258bb7b7 100644 --- a/packages/server/src/shared/agent-attention-notification.ts +++ b/packages/server/src/shared/agent-attention-notification.ts @@ -153,7 +153,7 @@ export function findLatestAssistantMessageFromTimeline( return null; } - return chunks.reverse().join(""); + return chunks.toReversed().join(""); } export function findLatestPermissionRequest( diff --git a/packages/server/src/tasks/cli.ts b/packages/server/src/tasks/cli.ts index cb10035c8..4cf9dd610 100644 --- a/packages/server/src/tasks/cli.ts +++ b/packages/server/src/tasks/cli.ts @@ -240,7 +240,7 @@ program // Print ancestors first (root to immediate parent) if (ancestors.length > 0) { process.stdout.write("# Parent Context\n\n"); - for (const ancestor of ancestors.reverse()) { + for (const ancestor of ancestors.toReversed()) { process.stdout.write(`## ${ancestor.title} (${ancestor.id}) [${ancestor.status}]\n`); if (ancestor.body) { process.stdout.write(`\n${ancestor.body}\n`); @@ -702,7 +702,7 @@ async function buildTaskContext(task: Task, scopeId?: string): Promise { let parentContext = ""; if (ancestors.length > 0) { parentContext = "# Parent Context\n\n"; - for (const ancestor of ancestors.reverse()) { + for (const ancestor of ancestors.toReversed()) { parentContext += `## ${ancestor.title} (${ancestor.id})\n`; if (ancestor.body) { parentContext += `\n${ancestor.body}\n`; diff --git a/packages/server/src/terminal/terminal-manager.test.ts b/packages/server/src/terminal/terminal-manager.test.ts index c427f1108..974b52c99 100644 --- a/packages/server/src/terminal/terminal-manager.test.ts +++ b/packages/server/src/terminal/terminal-manager.test.ts @@ -154,7 +154,7 @@ describe("TerminalManager", () => { for (let attempt = 0; attempt < 10 && !existsSync(markerPath); attempt++) { session.send({ type: "input", - data: `printf '%s' \"$PASEO_WORKTREE_PORT\" > ${JSON.stringify(markerPath)}\r`, + data: `printf '%s' "$PASEO_WORKTREE_PORT" > ${JSON.stringify(markerPath)}\r`, }); await new Promise((resolve) => setTimeout(resolve, 100)); } @@ -181,7 +181,7 @@ describe("TerminalManager", () => { for (let attempt = 0; attempt < 10 && !existsSync(markerPath); attempt++) { session.send({ type: "input", - data: `printf '%s' \"$PASEO_WORKTREE_PORT\" > ${JSON.stringify(markerPath)}\r`, + data: `printf '%s' "$PASEO_WORKTREE_PORT" > ${JSON.stringify(markerPath)}\r`, }); await new Promise((resolve) => setTimeout(resolve, 100)); } diff --git a/packages/server/src/terminal/terminal-manager.ts b/packages/server/src/terminal/terminal-manager.ts index 104dd1104..336226c48 100644 --- a/packages/server/src/terminal/terminal-manager.ts +++ b/packages/server/src/terminal/terminal-manager.ts @@ -172,9 +172,7 @@ export function createTerminalManager(): TerminalManager { const defaultName = `Terminal ${terminals.length + 1}`; const inheritedEnv = resolveDefaultEnvForCwd(options.cwd); const mergedEnv = - inheritedEnv || options.env - ? { ...(inheritedEnv ?? {}), ...(options.env ?? {}) } - : undefined; + inheritedEnv || options.env ? { ...inheritedEnv, ...options.env } : undefined; const session = registerSession( await createTerminal({ ...(options.id ? { id: options.id } : {}), diff --git a/packages/server/src/utils/checkout-git.ts b/packages/server/src/utils/checkout-git.ts index d02134fa3..a09399d58 100644 --- a/packages/server/src/utils/checkout-git.ts +++ b/packages/server/src/utils/checkout-git.ts @@ -1047,15 +1047,17 @@ export async function resolveRepositoryDefaultBranch(repoRoot: string): Promise< cwd: repoRoot, env: READ_ONLY_GIT_ENV, }); - const branches = stdout - .split("\n") - .map((line) => line.trim()) - .filter((line) => line.length > 0); + const branches = new Set( + stdout + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.length > 0), + ); - if (branches.includes("main")) { + if (branches.has("main")) { return "main"; } - if (branches.includes("master")) { + if (branches.has("master")) { return "master"; } diff --git a/packages/server/src/utils/spawn.launch-regression.test.ts b/packages/server/src/utils/spawn.launch-regression.test.ts index c1087962b..079cf78dc 100644 --- a/packages/server/src/utils/spawn.launch-regression.test.ts +++ b/packages/server/src/utils/spawn.launch-regression.test.ts @@ -57,7 +57,7 @@ console.log("ARGV_OK"); if (options?.includeCmdShim !== false) { writeFileSync( shim, - ["@echo off", "setlocal", `\"${fakeDaemonNode}\" \"${assertScript}\" %*`, ""].join("\r\n"), + ["@echo off", "setlocal", `"${fakeDaemonNode}" "${assertScript}" %*`, ""].join("\r\n"), ); }