chore: apply oxlint autofix (safe level)

Auto-fixed 102 warnings (6040 → 5938) across 57 files. Main categories:
- preserve-caught-error: add { cause: error } to re-thrown errors
- unicorn/no-array-reverse: .reverse() → .toReversed()
- unicorn/no-useless-fallback-in-spread: drop unnecessary ?? {} in spreads
- oxc/no-map-spread: rewrite object spread in .map() to Object.assign
- react-hooks/exhaustive-deps: trim module-level constants from dep arrays

Ran npm run format after to clean up whitespace from lint mutations.
This commit is contained in:
Mohamed Boudra
2026-04-23 21:47:36 +07:00
parent 9c88850de0
commit 177153e5e8
57 changed files with 152 additions and 151 deletions
+1 -9
View File
@@ -1,14 +1,6 @@
{ {
"$schema": "./node_modules/oxlint/configuration_schema.json", "$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": [ "plugins": ["react", "react-perf", "unicorn", "typescript", "oxc", "import", "promise"],
"react",
"react-perf",
"unicorn",
"typescript",
"oxc",
"import",
"promise"
],
"categories": { "categories": {
"correctness": "warn", "correctness": "warn",
"suspicious": "warn", "suspicious": "warn",
+3 -1
View File
@@ -156,7 +156,9 @@ async function assertE2EUsesSeededTestDaemon(page: Page): Promise<void> {
} }
} catch (error) { } catch (error) {
if (error instanceof Error) throw 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,
});
} }
} }
@@ -368,7 +368,7 @@ function summarizeByType(records: WireFrameRecord[]): Array<{
byType.set(type, current); byType.set(type, current);
} }
return [...byType.entries()] return [...byType.entries()]
.map(([type, value]) => ({ type, ...value })) .map(([type, value]) => Object.assign({ type }, value))
.sort((left, right) => right.bytes - left.bytes); .sort((left, right) => right.bytes - left.bytes);
} }
@@ -45,6 +45,7 @@ async function waitForAlternateScreenExit(page: Page, afterAlt: string, timeout:
null, null,
2, 2,
)}`, )}`,
{ cause: error },
); );
} }
+1 -1
View File
@@ -22,7 +22,7 @@ const escapedAppSrcRoot = appSrcRoot
const pathSeparatorPattern = "[\\\\/]"; const pathSeparatorPattern = "[\\\\/]";
config.resolver.extraNodeModules = { config.resolver.extraNodeModules = {
...(config.resolver.extraNodeModules ?? {}), ...config.resolver.extraNodeModules,
react: path.join(appNodeModulesRoot, "react"), react: path.join(appNodeModulesRoot, "react"),
"react-dom": path.join(appNodeModulesRoot, "react-dom"), "react-dom": path.join(appNodeModulesRoot, "react-dom"),
"react/jsx-runtime": path.join(appNodeModulesRoot, "react/jsx-runtime"), "react/jsx-runtime": path.join(appNodeModulesRoot, "react/jsx-runtime"),
@@ -618,7 +618,7 @@ export function CombinedModelSelector({
}); });
return () => cancelAnimationFrame(frame); return () => cancelAnimationFrame(frame);
}, [isOpen, platformIsWeb]); }, [isOpen]);
return ( return (
<> <>
@@ -287,14 +287,14 @@ export function FileExplorerPane({
directoryPaths.unshift("."); directoryPaths.unshift(".");
} }
await Promise.all([ await Promise.all(
...directoryPaths.map((path) => directoryPaths.map((path) =>
requestDirectoryListing(path, { requestDirectoryListing(path, {
recordHistory: false, recordHistory: false,
setCurrentPath: false, setCurrentPath: false,
}), }),
), ),
]); );
return null; return null;
}, },
enabled: false, enabled: false,
@@ -2158,7 +2158,6 @@ export function SidebarWorkspaceList({
serverId, serverId,
shortcutIndexByWorkspaceKey, shortcutIndexByWorkspaceKey,
showShortcutBadges, showShortcutBadges,
platformIsNative,
creatingWorkspaceIds, creatingWorkspaceIds,
], ],
); );
@@ -122,8 +122,9 @@ export function createStreamStrategy(config: StreamStrategyConfig): StreamStrate
return { return {
render: config.render, render: config.render,
orderTail: (streamItems) => orderTail: (streamItems) =>
config.orderTailReverse ? [...streamItems].reverse() : streamItems, config.orderTailReverse ? [...streamItems].toReversed() : streamItems,
orderHead: (streamHead) => (config.orderHeadReverse ? [...streamHead].reverse() : streamHead), orderHead: (streamHead) =>
config.orderHeadReverse ? [...streamHead].toReversed() : streamHead,
getNeighborIndex: (index, relation) => getNeighborIndex: (index, relation) =>
relation === "above" relation === "above"
? index + config.assistantTurnTraversalStep ? index + config.assistantTurnTraversalStep
@@ -153,7 +154,7 @@ export function createStreamStrategy(config: StreamStrategyConfig): StreamStrate
messages.push(currentItem.text); messages.push(currentItem.text);
} }
} }
return messages.reverse().join("\n\n"); return messages.toReversed().join("\n\n");
}, },
isNearBottom: (input) => config.isNearBottom(input), isNearBottom: (input) => config.isNearBottom(input),
getBottomOffset: (metrics) => config.getBottomOffset(metrics), getBottomOffset: (metrics) => config.getBottomOffset(metrics),
@@ -9,7 +9,7 @@ export function orderAutocompleteOptions<T>(
if (position === "below-input") { if (position === "below-input") {
return [...options]; return [...options];
} }
return [...options].reverse(); return [...options].toReversed();
} }
export function getAutocompleteFallbackIndex( export function getAutocompleteFallbackIndex(
@@ -113,7 +113,7 @@ export function orderVisibleComboboxOptions(
if (optionsPosition !== "above-search") { if (optionsPosition !== "above-search") {
return visibleOptions; return visibleOptions;
} }
return [...visibleOptions].reverse(); return [...visibleOptions].toReversed();
} }
export function getComboboxFallbackIndex( export function getComboboxFallbackIndex(
@@ -279,26 +279,23 @@ export function WebDesktopScrollbarOverlay({
setIsDragging(false); setIsDragging(false);
}, },
}); });
}, [applyDragDelta, platformIsWeb]); }, [applyDragDelta]);
const startWebDrag = useCallback( const startWebDrag = useCallback((event: any) => {
(event: any) => { if (!platformIsWeb) {
if (!platformIsWeb) { return;
return; }
} const clientY = readClientY(event);
const clientY = readClientY(event); if (clientY === null) {
if (clientY === null) { return;
return; }
} event?.preventDefault?.();
event?.preventDefault?.(); event?.stopPropagation?.();
event?.stopPropagation?.(); event?.nativeEvent?.preventDefault?.();
event?.nativeEvent?.preventDefault?.(); dragStartOffsetRef.current = normalizedOffsetRef.current;
dragStartOffsetRef.current = normalizedOffsetRef.current; dragStartClientYRef.current = clientY;
dragStartClientYRef.current = clientY; setIsDragging(true);
setIsDragging(true); }, []);
},
[platformIsWeb],
);
const handleGrabHoverIn = useCallback(() => { const handleGrabHoverIn = useCallback(() => {
if (!isScrollVisible && !isDragging) { if (!isScrollVisible && !isDragging) {
@@ -334,7 +331,7 @@ export function WebDesktopScrollbarOverlay({
window.removeEventListener("pointerup", stopDragging); window.removeEventListener("pointerup", stopDragging);
window.removeEventListener("pointercancel", stopDragging); window.removeEventListener("pointercancel", stopDragging);
}; };
}, [applyDragDelta, isDragging, platformIsWeb]); }, [applyDragDelta, isDragging]);
if (!enabled || !geometry.isVisible) { if (!enabled || !geometry.isVisible) {
return null; return null;
@@ -1580,7 +1580,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
console.error("[Session] Failed to send agent message:", error); 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 // Keep the ref updated so the agent_update handler can call it
@@ -1677,7 +1677,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
...(requestId ? { requestId } : {}), ...(requestId ? { requestId } : {}),
}); });
}, },
[encodeImages, client], [client],
); );
const setAgentMode = useCallback( const setAgentMode = useCallback(
@@ -227,7 +227,7 @@ export function useAudioRecorder(config?: AudioCaptureConfig) {
if (error?.message !== "Recording cancelled") { if (error?.message !== "Recording cancelled") {
console.error("[AudioRecorder] Failed to start recording:", error); 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]); }, [recordingOptions.sampleRate, recordingOptions.numberOfChannels, recordingOptions.bitRate]);
@@ -293,7 +293,7 @@ export function useAudioRecorder(config?: AudioCaptureConfig) {
} catch (error: any) { } catch (error: any) {
setRecordingStartTime(null); setRecordingStartTime(null);
console.error("[AudioRecorder] Failed to stop recording:", error); 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 { } finally {
startStopMutexRef.current = null; startStopMutexRef.current = null;
} }
@@ -190,7 +190,7 @@ export function useAudioRecorder(config?: AudioCaptureConfig) {
try { try {
stream = await navigator.mediaDevices.getUserMedia(constraints); stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (error: any) { } 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 { try {
@@ -225,7 +225,9 @@ export function useAudioRecorder(config?: AudioCaptureConfig) {
recorder = new MediaRecorder(stream, recorderOptions); recorder = new MediaRecorder(stream, recorderOptions);
} catch (error: any) { } catch (error: any) {
cleanupStream(); 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; mediaRecorderRef.current = recorder;
+4 -4
View File
@@ -1530,13 +1530,13 @@ export class HostRuntimeStore {
this.emit(host.serverId); this.emit(host.serverId);
}); });
void controller void controller
.start({ .start(
...(initialConnection initialConnection
? { ? {
initialConnection, initialConnection,
} }
: {}), : {},
}) )
.catch((error) => { .catch((error) => {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
controller.markStartupError(message); controller.markStartupError(message);
@@ -292,7 +292,7 @@ export function NewWorkspaceScreen({
cwd: input.cwd, cwd: input.cwd,
worktreeSlug: createNameId(), worktreeSlug: createNameId(),
...(input.attachments.length > 0 ? { attachments: input.attachments } : {}), ...(input.attachments.length > 0 ? { attachments: input.attachments } : {}),
...(checkoutRequest ?? {}), ...checkoutRequest,
}; };
}, },
[selectedItem], [selectedItem],
@@ -53,7 +53,7 @@ function setStatus(
statusByCheckout: { statusByCheckout: {
...state.statusByCheckout, ...state.statusByCheckout,
[key]: { [key]: {
...(state.statusByCheckout[key] ?? {}), ...state.statusByCheckout[key],
[actionId]: status, [actionId]: status,
}, },
}, },
@@ -531,7 +531,7 @@ export const useWorkspaceLayoutStore = create<WorkspaceLayoutStore>()(
splitSizesByWorkspace: { splitSizesByWorkspace: {
...state.splitSizesByWorkspace, ...state.splitSizesByWorkspace,
[normalizedWorkspaceKey]: { [normalizedWorkspaceKey]: {
...(state.splitSizesByWorkspace[normalizedWorkspaceKey] ?? {}), ...state.splitSizesByWorkspace[normalizedWorkspaceKey],
[normalizedGroupId]: clampNormalizedSizes(sizes), [normalizedGroupId]: clampNormalizedSizes(sizes),
}, },
}, },
+1 -1
View File
@@ -325,7 +325,7 @@ export async function runRunCommand(
}; };
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : String(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 });
} }
}); });
} }
+1 -1
View File
@@ -193,7 +193,7 @@ async function checkProviderBinaries(): Promise<ProviderBinaryStatus[]> {
const results = await Promise.all( const results = await Promise.all(
PROVIDER_BINARIES.map(async ({ label, binary }) => { PROVIDER_BINARIES.map(async ({ label, binary }) => {
const result = await checkProviderBinary(binary); const result = await checkProviderBinary(binary);
return { label, ...result }; return Object.assign({ label }, result);
}), }),
); );
return results; return results;
@@ -315,6 +315,7 @@ export async function startTestDaemon(options?: {
const message = err instanceof Error ? err.message : String(err); const message = err instanceof Error ? err.message : String(err);
throw new Error( throw new Error(
`Failed to start test daemon: ${message}\nStdout: ${formatOutputCapture(stdout)}\nStderr: ${formatOutputCapture(stderr)}`, `Failed to start test daemon: ${message}\nStdout: ${formatOutputCapture(stdout)}\nStderr: ${formatOutputCapture(stderr)}`,
{ cause: err },
); );
} }
@@ -153,7 +153,7 @@ function tailFile(filePath: string, lines = 50): string {
function logDesktopDaemonLifecycle(message: string, details?: Record<string, unknown>): void { function logDesktopDaemonLifecycle(message: string, details?: Record<string, unknown>): void {
log.info("[desktop daemon]", message, { log.info("[desktop daemon]", message, {
pid: process.pid, pid: process.pid,
...(details ?? {}), ...details,
}); });
} }
@@ -349,6 +349,7 @@ export async function runCliJsonCommand(args: string[]): Promise<unknown> {
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`CLI command returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`, `CLI command returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`,
{ cause: error },
); );
} }
} }
@@ -267,7 +267,7 @@ function attachPersistenceCwd(
return { return {
...handle, ...handle,
metadata: { metadata: {
...(handle.metadata ?? {}), ...handle.metadata,
cwd, cwd,
}, },
}; };
@@ -278,11 +278,11 @@ type SubscriptionRecord = {
agentId: string | null; agentId: string | null;
}; };
const BUSY_STATUSES: AgentLifecycleStatus[] = ["initializing", "running"]; const BUSY_STATUSES: AgentLifecycleStatus[] = new Set(["initializing", "running"]);
const AgentIdSchema = z.string().uuid(); const AgentIdSchema = z.string().uuid();
function isAgentBusy(status: AgentLifecycleStatus): boolean { function isAgentBusy(status: AgentLifecycleStatus): boolean {
return BUSY_STATUSES.includes(status); return BUSY_STATUSES.has(status);
} }
function isTurnTerminalEvent(event: AgentStreamEvent): boolean { function isTurnTerminalEvent(event: AgentStreamEvent): boolean {
@@ -649,7 +649,7 @@ export class AgentManager {
type: "http" as const, type: "http" as const,
url: `${this.mcpBaseUrl}?callerAgentId=${resolvedAgentId}`, url: `${this.mcpBaseUrl}?callerAgentId=${resolvedAgentId}`,
}, },
...(config.mcpServers ?? {}), ...config.mcpServers,
}, },
}; };
const normalizedConfig = await this.normalizeConfig(injectedConfig); const normalizedConfig = await this.normalizeConfig(injectedConfig);
@@ -1708,7 +1708,7 @@ export class AgentManager {
} }
return { return {
text: chunks.reverse().join(""), text: chunks.toReversed().join(""),
startsAtBeginning, startsAtBeginning,
}; };
} }
@@ -2847,12 +2847,12 @@ export class AgentManager {
"code" in error && "code" in error &&
(error as NodeJS.ErrnoException).code === "ENOENT" (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) { if (error instanceof Error) {
throw 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 });
} }
} }
@@ -244,7 +244,7 @@ export class InMemoryAgentTimelineStore {
return null; return null;
} }
return chunks.reverse().join(""); return chunks.toReversed().join("");
} }
getCanonicalUserMessagesById(agentId: string): Map<string, string> { getCanonicalUserMessagesById(agentId: string): Map<string, string> {
@@ -666,8 +666,8 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom
const childAgentDefaultLabels = callerContext?.childAgentDefaultLabels; const childAgentDefaultLabels = callerContext?.childAgentDefaultLabels;
const mergedLabels = { const mergedLabels = {
...(callerAgentId ? { "paseo.parent-agent-id": callerAgentId } : {}), ...(callerAgentId ? { "paseo.parent-agent-id": callerAgentId } : {}),
...(childAgentDefaultLabels ?? {}), ...childAgentDefaultLabels,
...(labels ?? {}), ...labels,
}; };
const snapshot = await agentManager.createAgent( const snapshot = await agentManager.createAgent(
{ {
@@ -185,7 +185,7 @@ export function applyProviderEnv(
): Record<string, string | undefined> { ): Record<string, string | undefined> {
const merged: Record<string, string | undefined> = { const merged: Record<string, string | undefined> = {
...baseEnv, ...baseEnv,
...(runtimeSettings?.env ?? {}), ...runtimeSettings?.env,
}; };
for (const key of PARENT_SESSION_ENV_VARS) { for (const key of PARENT_SESSION_ENV_VARS) {
delete merged[key]; delete merged[key];
@@ -130,8 +130,8 @@ function mergeRuntimeSettings(
env: env:
base?.env || override?.env base?.env || override?.env
? { ? {
...(base?.env ?? {}), ...base?.env,
...(override?.env ?? {}), ...override?.env,
} }
: undefined, : undefined,
disallowedTools: disallowedTools:
@@ -516,9 +516,9 @@ export class ACPAgentClient implements AgentClient {
const sessions: PersistedAgentDescriptor[] = []; const sessions: PersistedAgentDescriptor[] = [];
let cursor: string | null | undefined; let cursor: string | null | undefined;
do { do {
const page: ListSessionsResponse = await probe.connection.listSessions({ const page: ListSessionsResponse = await probe.connection.listSessions(
...(cursor ? { cursor } : {}), cursor ? { cursor } : {},
}); );
for (const session of page.sessions) { for (const session of page.sessions) {
sessions.push({ sessions.push({
provider: this.provider, provider: this.provider,
@@ -566,7 +566,7 @@ export class ACPAgentClient implements AgentClient {
process.env as Record<string, string | undefined>, process.env as Record<string, string | undefined>,
this.runtimeSettings, this.runtimeSettings,
), ),
...(launchEnv ?? {}), ...launchEnv,
}, },
stdio: ["pipe", "pipe", "pipe"], stdio: ["pipe", "pipe", "pipe"],
}) as ChildProcessWithoutNullStreams; }) as ChildProcessWithoutNullStreams;
@@ -1413,7 +1413,7 @@ export class ACPAgentSession implements AgentSession, ACPClient {
process.env as Record<string, string | undefined>, process.env as Record<string, string | undefined>,
this.runtimeSettings, this.runtimeSettings,
), ),
...(this.launchEnv ?? {}), ...this.launchEnv,
}, },
stdio: ["pipe", "pipe", "pipe"], stdio: ["pipe", "pipe", "pipe"],
}) as ChildProcessWithoutNullStreams; }) as ChildProcessWithoutNullStreams;
@@ -131,7 +131,7 @@ function getToolCalls(events: AgentStreamEvent[]): ToolCallTimelineItem[] {
function getLatestCompletedBashCall(events: AgentStreamEvent[]): ToolCallTimelineItem | undefined { function getLatestCompletedBashCall(events: AgentStreamEvent[]): ToolCallTimelineItem | undefined {
return [...getToolCalls(events)] return [...getToolCalls(events)]
.reverse() .toReversed()
.find((item) => item.status === "completed" && item.name.toLowerCase() === "bash"); .find((item) => item.status === "completed" && item.name.toLowerCase() === "bash");
} }
@@ -220,7 +220,7 @@ function applyRuntimeSettingsToClaudeOptions(
cwd: spawnOptions.cwd, cwd: spawnOptions.cwd,
env: { env: {
...applyProviderEnv(spawnOptions.env, runtimeSettings), ...applyProviderEnv(spawnOptions.env, runtimeSettings),
...(launchEnv ?? {}), ...launchEnv,
}, },
signal: spawnOptions.signal, signal: spawnOptions.signal,
stdio: ["pipe", "pipe", "pipe"], stdio: ["pipe", "pipe", "pipe"],
@@ -1057,7 +1057,7 @@ export function readEventIdentifiers(message: SDKMessage): EventIdentifiers {
const claudeDebug = process.env.PASEO_CLAUDE_DEBUG === "1"; const claudeDebug = process.env.PASEO_CLAUDE_DEBUG === "1";
export class ClaudeAgentClient implements AgentClient { export class ClaudeAgentClient implements AgentClient {
readonly provider: "claude" = "claude"; readonly provider = "claude" as const;
readonly capabilities = CLAUDE_CAPABILITIES; readonly capabilities = CLAUDE_CAPABILITIES;
private readonly defaults?: { agents?: Record<string, AgentDefinition> }; private readonly defaults?: { agents?: Record<string, AgentDefinition> };
@@ -1347,7 +1347,7 @@ function readStreamRequestOutputTokens(event: Record<string, unknown>): number |
} }
class ClaudeAgentSession implements AgentSession { class ClaudeAgentSession implements AgentSession {
readonly provider: "claude" = "claude"; readonly provider = "claude" as const;
readonly capabilities = CLAUDE_CAPABILITIES; readonly capabilities = CLAUDE_CAPABILITIES;
private readonly config: ClaudeAgentConfig; private readonly config: ClaudeAgentConfig;
@@ -2174,7 +2174,7 @@ class ClaudeAgentSession implements AgentSession {
// Increase MCP timeouts for long-running tool calls (10 minutes) // Increase MCP timeouts for long-running tool calls (10 minutes)
MCP_TIMEOUT: "600000", MCP_TIMEOUT: "600000",
MCP_TOOL_TIMEOUT: "600000", MCP_TOOL_TIMEOUT: "600000",
...(this.launchEnv ?? {}), ...this.launchEnv,
}, },
// Required for provider-level /rewind support. // Required for provider-level /rewind support.
enableFileCheckpointing: true, enableFileCheckpointing: true,
@@ -96,11 +96,12 @@ export class ClaudeSidechainTracker {
action.summary ? `[${action.toolName}] ${action.summary}` : `[${action.toolName}]`, action.summary ? `[${action.toolName}] ${action.summary}` : `[${action.toolName}]`,
) )
.join("\n"), .join("\n"),
actions: state.actions.map((action) => ({ actions: state.actions.map((action) =>
index: action.index, Object.assign(
toolName: action.toolName, { index: action.index, toolName: action.toolName },
...(action.summary ? { summary: action.summary } : {}), action.summary ? { summary: action.summary } : {},
})), ),
),
}; };
return [ return [
@@ -387,7 +387,7 @@ describe("Codex app-server provider (e2e)", () => {
).toBe(true); ).toBe(true);
const finalAssistantMessage = [...events] const finalAssistantMessage = [...events]
.reverse() .toReversed()
.find((event) => event.type === "timeline" && event.item.type === "assistant_message"); .find((event) => event.type === "timeline" && event.item.type === "assistant_message");
expect(finalAssistantMessage).toBeDefined(); expect(finalAssistantMessage).toBeDefined();
if ( if (
@@ -1408,11 +1408,13 @@ function mapCodexPatchNotificationToToolCall(params: {
: { : {
...(files.length > 0 ...(files.length > 0
? { ? {
files: files.map((file) => ({ files: files.map((file) =>
path: file.path, Object.assign(
...(file.kind ? { kind: file.kind } : {}), { path: file.path },
...codexPatchTextFields(file.content ?? patchText), file.kind ? { kind: file.kind } : {},
})), codexPatchTextFields(file.content ?? patchText),
),
),
} }
: {}), : {}),
...(params.stdout ? { stdout: params.stdout } : {}), ...(params.stdout ? { stdout: params.stdout } : {}),
@@ -2667,7 +2669,7 @@ class CodexAppServerAgentSession implements AgentSession {
private applyFeatureValue(featureId: "fast_mode" | "plan_mode", value: boolean): void { private applyFeatureValue(featureId: "fast_mode" | "plan_mode", value: boolean): void {
this.config.featureValues = { this.config.featureValues = {
...(this.config.featureValues ?? {}), ...this.config.featureValues,
[featureId]: value, [featureId]: value,
}; };
@@ -764,19 +764,18 @@ function mapFileChangeItem(
): CodexNormalizedToolCallEnvelope { ): CodexNormalizedToolCallEnvelope {
const files = parseFileChangeEntries(item.changes, options); const files = parseFileChangeEntries(item.changes, options);
const inputBase = { const inputBase =
...(files.length > 0 files.length > 0
? { ? {
files: files.map((file) => ({ files: files.map((file) => ({
path: file.path, path: file.path,
...(file.kind !== undefined ? { kind: file.kind } : {}), ...(file.kind !== undefined ? { kind: file.kind } : {}),
})), })),
} }
: {}), : {};
};
const output = toNullableObject({ const output = toNullableObject(
...(files.length > 0 files.length > 0
? { ? {
files: files.map((file) => ({ files: files.map((file) => ({
path: file.path, path: file.path,
@@ -786,8 +785,8 @@ function mapFileChangeItem(
: asEditFileOutputFields(file.diff)), : asEditFileOutputFields(file.diff)),
})), })),
} }
: {}), : {},
}); );
const name = "apply_patch"; const name = "apply_patch";
const error = item.error ?? null; const error = item.error ?? null;
@@ -948,7 +948,7 @@ type OpenCodeServerGeneration = {
}; };
export class OpenCodeAgentClient implements AgentClient { export class OpenCodeAgentClient implements AgentClient {
readonly provider: "opencode" = "opencode"; readonly provider = "opencode" as const;
readonly capabilities = OPENCODE_CAPABILITIES; readonly capabilities = OPENCODE_CAPABILITIES;
private readonly serverManager: OpenCodeServerManager; private readonly serverManager: OpenCodeServerManager;
@@ -1667,7 +1667,7 @@ export function translateOpenCodeEvent(
input: { questions }, input: { questions },
metadata: { metadata: {
source: "opencode_question", source: "opencode_question",
...(event.properties.tool ?? {}), ...event.properties.tool,
}, },
}, },
}); });
@@ -1757,7 +1757,7 @@ export function translateOpenCodeEvent(
} }
class OpenCodeAgentSession implements AgentSession { class OpenCodeAgentSession implements AgentSession {
readonly provider: "opencode" = "opencode"; readonly provider = "opencode" as const;
readonly capabilities = OPENCODE_CAPABILITIES; readonly capabilities = OPENCODE_CAPABILITIES;
private readonly config: OpenCodeAgentConfig; private readonly config: OpenCodeAgentConfig;
@@ -55,7 +55,7 @@ console.log("ARGV_OK");
const shim = path.join(root, `${binaryName}.cmd`); const shim = path.join(root, `${binaryName}.cmd`);
writeFileSync( writeFileSync(
shim, shim,
["@echo off", "setlocal", `\"${fakeDaemonNode}\" \"${assertScript}\" %*`, ""].join("\r\n"), ["@echo off", "setlocal", `"${fakeDaemonNode}" "${assertScript}" %*`, ""].join("\r\n"),
); );
return { root, shim, expectedArgs }; return { root, shim, expectedArgs };
@@ -79,7 +79,7 @@ function mergeToolCallItems(
const mergedDetail = mergeToolCallDetail(existing.detail, incoming.detail); const mergedDetail = mergeToolCallDetail(existing.detail, incoming.detail);
const mergedMetadata = const mergedMetadata =
existing.metadata || incoming.metadata existing.metadata || incoming.metadata
? { ...(existing.metadata ?? {}), ...(incoming.metadata ?? {}) } ? { ...existing.metadata, ...incoming.metadata }
: undefined; : undefined;
const merged: Extract<AgentTimelineItem, { type: "tool_call" }> = { const merged: Extract<AgentTimelineItem, { type: "tool_call" }> = {
@@ -92,8 +92,8 @@ describe("daemon E2E checkout diff subscriptions", () => {
writeFileSync(path.join(cwd, "alpha.txt"), "alpha\n"); writeFileSync(path.join(cwd, "alpha.txt"), "alpha\n");
const update = await waitForCheckoutDiffUpdate(ctx, subscriptionId, (payload) => { const update = await waitForCheckoutDiffUpdate(ctx, subscriptionId, (payload) => {
const paths = payload.files.map((file) => file.path); const paths = new Set(payload.files.map((file) => file.path));
return paths.includes("alpha.txt") && paths.includes("zeta.txt"); return paths.has("alpha.txt") && paths.has("zeta.txt");
}); });
expect(update.error).toBeNull(); expect(update.error).toBeNull();
@@ -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}`; const BACKGROUND_TASK_SLEEP_5_REPEAT_PROMPT = `do it again: ${BACKGROUND_TASK_SLEEP_5_PROMPT}`;
function sanitizeClaudeProjectPath(cwd: string): string { 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 { function resolveClaudeTranscriptPath(params: { cwd: string; sessionId: string }): string {
@@ -169,13 +169,13 @@ function extractTranscriptRaceEvidence(
const userLines = lines.filter((line) => line.type === "user"); const userLines = lines.filter((line) => line.type === "user");
const assistantLines = lines.filter((line) => line.type === "assistant"); const assistantLines = lines.filter((line) => line.type === "assistant");
const doItAgain = [...userLines] const doItAgain = [...userLines]
.reverse() .toReversed()
.find((line) => readUserText(line).toLowerCase().includes("do it again")); .find((line) => readUserText(line).toLowerCase().includes("do it again"));
const isHelloPrompt = (line: ClaudeTranscriptLine): boolean => { const isHelloPrompt = (line: ClaudeTranscriptLine): boolean => {
const text = readUserText(line).trim().toLowerCase(); const text = readUserText(line).trim().toLowerCase();
return text === "hello" || text === "say exactly hello"; 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") { if (!doItAgain || !helloUser || typeof helloUser.uuid !== "string") {
return null; return null;
@@ -201,7 +201,7 @@ function extractTranscriptRaceEvidence(
return readUserText(line).includes("<task-notification>"); return readUserText(line).includes("<task-notification>");
}); });
const taskNotificationUser = const taskNotificationUser =
[...taskNotificationCandidates].reverse().find((line) => parseTimestamp(line) >= helloTs) ?? [...taskNotificationCandidates].toReversed().find((line) => parseTimestamp(line) >= helloTs) ??
taskNotificationCandidates[0]; taskNotificationCandidates[0];
if (!taskNotificationUser || typeof taskNotificationUser.uuid !== "string") { if (!taskNotificationUser || typeof taskNotificationUser.uuid !== "string") {
return null; return null;
@@ -260,7 +260,9 @@ describe("ConnectionOfferV2 (daemon E2E)", () => {
expect(sawListeningLog).toBe(true); expect(sawListeningLog).toBe(true);
} catch (err) { } 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 { } finally {
proc.kill(); proc.kill();
await rm(tempHome, { recursive: true, force: true }); await rm(tempHome, { recursive: true, force: true });
+3 -3
View File
@@ -37,7 +37,7 @@ type ResolveLogConfigOptions = {
env?: NodeJS.ProcessEnv; 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_FORMATS: LogFormat[] = ["pretty", "json"];
const LOG_LEVEL_PRIORITIES: Record<LogLevel, number> = { const LOG_LEVEL_PRIORITIES: Record<LogLevel, number> = {
trace: 10, trace: 10,
@@ -56,7 +56,7 @@ const DEFAULT_FILE_ROTATE_MAX_FILES = 2;
const DEFAULT_DAEMON_LOG_FILENAME = "daemon.log"; const DEFAULT_DAEMON_LOG_FILENAME = "daemon.log";
function parseLogLevel(value: string | undefined): LogLevel | undefined { 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 undefined;
} }
return value as LogLevel; return value as LogLevel;
@@ -158,7 +158,7 @@ function rotateOnRestart(filePath: string, maxFiles: number): void {
const rotatedFiles = readdirSync(dir) const rotatedFiles = readdirSync(dir)
.filter((f) => f.endsWith(`-${base}`) && f !== base) .filter((f) => f.endsWith(`-${base}`) && f !== base)
.sort() .sort()
.reverse(); .toReversed();
for (const file of rotatedFiles.slice(maxFiles)) { for (const file of rotatedFiles.slice(maxFiles)) {
try { try {
@@ -362,7 +362,7 @@ export function loadPersistedConfig(paseoHome: string, logger?: LoggerLike): Per
log?.info(`Initialized config file at ${configPath}`); log?.info(`Initialized config file at ${configPath}`);
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : String(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"); raw = readFileSync(configPath, "utf-8");
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : String(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; let parsed: unknown;
@@ -379,7 +379,7 @@ export function loadPersistedConfig(paseoHome: string, logger?: LoggerLike): Per
parsed = JSON.parse(raw); parsed = JSON.parse(raw);
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : String(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); const migrated = stripDeprecatedLocalSpeechConfigFields(parsed);
@@ -416,6 +416,6 @@ export function savePersistedConfig(
log?.info(`Saved to ${configPath}`); log?.info(`Saved to ${configPath}`);
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : String(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 });
} }
} }
+10 -7
View File
@@ -3665,7 +3665,9 @@ export class Session {
const snapshot = await this.workspaceGitService.getSnapshot(cwd); const snapshot = await this.workspaceGitService.getSnapshot(cwd);
return snapshot.git.isDirty === true; return snapshot.git.isDirty === true;
} catch (error) { } 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); const final = await this.getAgentPayloadById(agentId);
if (!final) { if (!final) {
throw new Error(`Agent ${agentId} disappeared while waiting`); throw new Error(`Agent ${agentId} disappeared while waiting`, { cause: error });
} }
this.emit({ this.emit({
type: "wait_for_finish_response", type: "wait_for_finish_response",
@@ -8721,11 +8723,12 @@ export class Session {
this.emitTerminalsChangedSnapshot({ this.emitTerminalsChangedSnapshot({
cwd: event.cwd, cwd: event.cwd,
terminals: this.filterStandaloneTerminals(event.terminals).map((terminal) => ({ terminals: this.filterStandaloneTerminals(event.terminals).map((terminal) =>
id: terminal.id, Object.assign(
name: terminal.name, { id: terminal.id, name: terminal.name },
...(terminal.title ? { title: terminal.title } : {}), terminal.title ? { title: terminal.title } : {},
})), ),
),
}); });
} }
@@ -208,10 +208,7 @@ export type SherpaOnnxModelSpec = SherpaOnnxCatalogEntry & {
}; };
export function listSherpaOnnxModels(): SherpaOnnxModelSpec[] { export function listSherpaOnnxModels(): SherpaOnnxModelSpec[] {
return ALL_MODEL_IDS.map((id) => ({ return ALL_MODEL_IDS.map((id) => Object.assign({ id }, SHERPA_ONNX_MODEL_CATALOG[id]));
id,
...SHERPA_ONNX_MODEL_CATALOG[id],
}));
} }
export function getSherpaOnnxModelSpec(id: SherpaOnnxModelId): SherpaOnnxModelSpec { export function getSherpaOnnxModelSpec(id: SherpaOnnxModelId): SherpaOnnxModelSpec {
@@ -245,7 +245,7 @@ export class OpenAISTT implements SpeechToTextProvider {
}; };
} catch (error: any) { } catch (error: any) {
logger.error({ err: error }, "Transcription error"); 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 { } finally {
if (tempFilePath) { if (tempFilePath) {
try { try {
@@ -76,7 +76,7 @@ export class OpenAITTS implements TextToSpeechProvider {
}; };
} catch (error: any) { } catch (error: any) {
this.logger.error({ err: error }, "Speech synthesis error"); 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 });
} }
} }
} }
@@ -88,7 +88,7 @@ function buildPersistence(
metadata?: Record<string, unknown>, metadata?: Record<string, unknown>,
): AgentPersistenceHandle { ): AgentPersistenceHandle {
if (provider === "codex") { if (provider === "codex") {
return { provider, sessionId, metadata: { conversationId: sessionId, ...(metadata ?? {}) } }; return { provider, sessionId, metadata: { conversationId: sessionId, ...metadata } };
} }
return { provider, sessionId, ...(metadata ? { 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 }; return { name: "apply_patch", input: { patch: "*** Begin Patch\n*** End Patch\n" }, output };
} }
const printfMatch = 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) { if (printfMatch) {
const fileName = printfMatch[1] ?? "permission.txt"; const fileName = printfMatch[1] ?? "permission.txt";
return { return {
@@ -285,6 +285,7 @@ describe("voice roundtrip e2e", () => {
} catch (error) { } catch (error) {
throw new 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)}`, `${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 { } finally {
offStream(); offStream();
@@ -46,7 +46,7 @@ import {
} from "./paseo-worktree-archive-service.js"; } from "./paseo-worktree-archive-service.js";
import { toWorktreeWireError } from "./worktree-errors.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 { export interface NormalizedGitOptions {
baseBranch?: string; baseBranch?: string;
@@ -153,7 +153,7 @@ export function findLatestAssistantMessageFromTimeline(
return null; return null;
} }
return chunks.reverse().join(""); return chunks.toReversed().join("");
} }
export function findLatestPermissionRequest( export function findLatestPermissionRequest(
+2 -2
View File
@@ -240,7 +240,7 @@ program
// Print ancestors first (root to immediate parent) // Print ancestors first (root to immediate parent)
if (ancestors.length > 0) { if (ancestors.length > 0) {
process.stdout.write("# Parent Context\n\n"); 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`); process.stdout.write(`## ${ancestor.title} (${ancestor.id}) [${ancestor.status}]\n`);
if (ancestor.body) { if (ancestor.body) {
process.stdout.write(`\n${ancestor.body}\n`); process.stdout.write(`\n${ancestor.body}\n`);
@@ -702,7 +702,7 @@ async function buildTaskContext(task: Task, scopeId?: string): Promise<string> {
let parentContext = ""; let parentContext = "";
if (ancestors.length > 0) { if (ancestors.length > 0) {
parentContext = "# Parent Context\n\n"; parentContext = "# Parent Context\n\n";
for (const ancestor of ancestors.reverse()) { for (const ancestor of ancestors.toReversed()) {
parentContext += `## ${ancestor.title} (${ancestor.id})\n`; parentContext += `## ${ancestor.title} (${ancestor.id})\n`;
if (ancestor.body) { if (ancestor.body) {
parentContext += `\n${ancestor.body}\n`; parentContext += `\n${ancestor.body}\n`;
@@ -154,7 +154,7 @@ describe("TerminalManager", () => {
for (let attempt = 0; attempt < 10 && !existsSync(markerPath); attempt++) { for (let attempt = 0; attempt < 10 && !existsSync(markerPath); attempt++) {
session.send({ session.send({
type: "input", 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)); await new Promise((resolve) => setTimeout(resolve, 100));
} }
@@ -181,7 +181,7 @@ describe("TerminalManager", () => {
for (let attempt = 0; attempt < 10 && !existsSync(markerPath); attempt++) { for (let attempt = 0; attempt < 10 && !existsSync(markerPath); attempt++) {
session.send({ session.send({
type: "input", 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)); await new Promise((resolve) => setTimeout(resolve, 100));
} }
@@ -172,9 +172,7 @@ export function createTerminalManager(): TerminalManager {
const defaultName = `Terminal ${terminals.length + 1}`; const defaultName = `Terminal ${terminals.length + 1}`;
const inheritedEnv = resolveDefaultEnvForCwd(options.cwd); const inheritedEnv = resolveDefaultEnvForCwd(options.cwd);
const mergedEnv = const mergedEnv =
inheritedEnv || options.env inheritedEnv || options.env ? { ...inheritedEnv, ...options.env } : undefined;
? { ...(inheritedEnv ?? {}), ...(options.env ?? {}) }
: undefined;
const session = registerSession( const session = registerSession(
await createTerminal({ await createTerminal({
...(options.id ? { id: options.id } : {}), ...(options.id ? { id: options.id } : {}),
+8 -6
View File
@@ -1047,15 +1047,17 @@ export async function resolveRepositoryDefaultBranch(repoRoot: string): Promise<
cwd: repoRoot, cwd: repoRoot,
env: READ_ONLY_GIT_ENV, env: READ_ONLY_GIT_ENV,
}); });
const branches = stdout const branches = new Set(
.split("\n") stdout
.map((line) => line.trim()) .split("\n")
.filter((line) => line.length > 0); .map((line) => line.trim())
.filter((line) => line.length > 0),
);
if (branches.includes("main")) { if (branches.has("main")) {
return "main"; return "main";
} }
if (branches.includes("master")) { if (branches.has("master")) {
return "master"; return "master";
} }
@@ -57,7 +57,7 @@ console.log("ARGV_OK");
if (options?.includeCmdShim !== false) { if (options?.includeCmdShim !== false) {
writeFileSync( writeFileSync(
shim, shim,
["@echo off", "setlocal", `\"${fakeDaemonNode}\" \"${assertScript}\" %*`, ""].join("\r\n"), ["@echo off", "setlocal", `"${fakeDaemonNode}" "${assertScript}" %*`, ""].join("\r\n"),
); );
} }