From 9478e3cc5ce652bec683c2cbde24d17d78c5190f Mon Sep 17 00:00:00 2001 From: can1357 Date: Fri, 19 Jun 2026 17:38:07 +0200 Subject: [PATCH] refactor: replaced ReturnType with Timer type - Replaced usage of `ReturnType` and `ReturnType` with the explicit `Timer` type across the codebase. - Updated several type definitions and function signatures to use concrete types instead of inferred return types for improved clarity and maintainability. --- packages/agent/src/agent-loop.ts | 2 +- packages/ai/test/pi-native-client.test.ts | 4 ++-- .../src/discovery/builtin-rules/ts-no-return-type.md | 1 - .../coding-agent/src/modes/components/custom-editor.ts | 2 +- .../src/modes/components/model-selector.ts | 4 ++-- packages/coding-agent/src/modes/components/welcome.ts | 2 +- .../src/modes/controllers/selector-controller.ts | 4 ++-- .../coding-agent/src/session/auth-broker-config.ts | 3 ++- .../test/goals/goal-mode-integration.test.ts | 3 ++- packages/coding-agent/test/hook-editor.test.ts | 6 +++--- packages/coding-agent/test/memories-runtime.test.ts | 2 +- .../coding-agent/test/silent-abort-print-mode.test.ts | 4 ++-- .../coding-agent/test/task/autoload-skills.test.ts | 10 +++++----- packages/coding-agent/test/tools/approval-mode.test.ts | 3 ++- packages/coding-agent/test/tools/gh.test.ts | 9 +++++++-- .../coding-agent/test/tools/lsp-regressions.test.ts | 2 +- packages/coding-agent/test/tools/todo.test.ts | 3 ++- packages/mnemopi/test/extraction-integration.test.ts | 2 +- packages/tui/src/terminal.ts | 2 +- 19 files changed, 38 insertions(+), 30 deletions(-) diff --git a/packages/agent/src/agent-loop.ts b/packages/agent/src/agent-loop.ts index 0c1d92d93..988b97760 100644 --- a/packages/agent/src/agent-loop.ts +++ b/packages/agent/src/agent-loop.ts @@ -718,7 +718,7 @@ async function runLoopBody( stepCounter: StepCounter, streamFn?: StreamFn, ): Promise { - let deadlineTimer: ReturnType | undefined; + let deadlineTimer: Timer | undefined; if (config.deadline !== undefined) { const deadlineAbortController = new AbortController(); const delay = config.deadline - Date.now(); diff --git a/packages/ai/test/pi-native-client.test.ts b/packages/ai/test/pi-native-client.test.ts index 2034b4068..a65e1094e 100644 --- a/packages/ai/test/pi-native-client.test.ts +++ b/packages/ai/test/pi-native-client.test.ts @@ -1,4 +1,4 @@ -import { afterEach, describe, expect, it, mock, spyOn } from "bun:test"; +import { afterEach, describe, expect, it, type Mock, mock, spyOn } from "bun:test"; import { streamPiNative } from "@oh-my-pi/pi-ai/providers/pi-native-client"; import type { AssistantMessage, @@ -288,7 +288,7 @@ describe("streamPiNative event flow", () => { await expect(stream.result()).rejects.toThrow(/pre-aborted/); // fetch was never called — short-circuit happened in the abort guard - expect((fetchImpl as unknown as ReturnType).mock.calls.length).toBe(0); + expect((fetchImpl as unknown as Mock).mock.calls.length).toBe(0); }); it("forwards the caller's AbortSignal to the underlying fetch", async () => { diff --git a/packages/coding-agent/src/discovery/builtin-rules/ts-no-return-type.md b/packages/coding-agent/src/discovery/builtin-rules/ts-no-return-type.md index cbba659af..17af06855 100644 --- a/packages/coding-agent/src/discovery/builtin-rules/ts-no-return-type.md +++ b/packages/coding-agent/src/discovery/builtin-rules/ts-no-return-type.md @@ -39,7 +39,6 @@ import type { LoadedConfig } from "./config"; ## Exceptions -- Timer handles: `ReturnType` / `setInterval`. - Generic type utilities where the function is a type parameter. Concrete function? Export a concrete type. diff --git a/packages/coding-agent/src/modes/components/custom-editor.ts b/packages/coding-agent/src/modes/components/custom-editor.ts index 195a16f13..c917357d2 100644 --- a/packages/coding-agent/src/modes/components/custom-editor.ts +++ b/packages/coding-agent/src/modes/components/custom-editor.ts @@ -177,7 +177,7 @@ export class CustomEditor extends Editor { /** Per-render scratch flag: did any layout line in this render contain a magic * keyword that should shimmer? Reset by {@link #scheduleShimmerIfNeeded} each * time a frame is queued. */ - #shimmerTimer: ReturnType | undefined; + #shimmerTimer: Timer | undefined; /** Repaint hook the host wires once at construction. Called from the shimmer * timer to request the next animation frame. Undefined when nobody is * listening (tests, headless callers); the timer chain still self-cleans. */ diff --git a/packages/coding-agent/src/modes/components/model-selector.ts b/packages/coding-agent/src/modes/components/model-selector.ts index 184559a06..c6b141cc9 100644 --- a/packages/coding-agent/src/modes/components/model-selector.ts +++ b/packages/coding-agent/src/modes/components/model-selector.ts @@ -179,9 +179,9 @@ export class ModelSelectorComponent extends Container { #providers: ProviderTabState[] = STATIC_PROVIDER_TABS; #activeTabIndex: number = 0; #refreshingProviders: Set = new Set(); - #scheduledProviderRefreshes: Map> = new Map(); + #scheduledProviderRefreshes: Map = new Map(); #refreshSpinnerFrame: number = 0; - #refreshSpinnerInterval?: NodeJS.Timeout; + #refreshSpinnerInterval?: Timer; // Context menu state #isMenuOpen: boolean = false; diff --git a/packages/coding-agent/src/modes/components/welcome.ts b/packages/coding-agent/src/modes/components/welcome.ts index d4dd93505..cc1fadf4a 100644 --- a/packages/coding-agent/src/modes/components/welcome.ts +++ b/packages/coding-agent/src/modes/components/welcome.ts @@ -142,7 +142,7 @@ export interface LspServerInfo { */ export class WelcomeComponent implements Component { #animStart: number | null = null; - #animTimer: ReturnType | null = null; + #animTimer: Timer | null = null; #selectedTip: string | undefined; // Render cache: the welcome box is the first transcript-area component, so // returning a stable array reference keeps the whole frame prefix stable. diff --git a/packages/coding-agent/src/modes/controllers/selector-controller.ts b/packages/coding-agent/src/modes/controllers/selector-controller.ts index d3d47a29a..f5e0b2410 100644 --- a/packages/coding-agent/src/modes/controllers/selector-controller.ts +++ b/packages/coding-agent/src/modes/controllers/selector-controller.ts @@ -27,7 +27,7 @@ import { theme, } from "../../modes/theme/theme"; import type { InteractiveModeContext } from "../../modes/types"; -import type { ResetCreditRedeemOutcome } from "../../session/auth-storage"; +import type { ResetCreditAccountStatus, ResetCreditRedeemOutcome } from "../../session/auth-storage"; import type { SessionInfo } from "../../session/session-listing"; import { SessionManager } from "../../session/session-manager"; import { FileSessionStorage } from "../../session/session-storage"; @@ -1161,7 +1161,7 @@ export class SelectorController { async showResetUsageSelector(): Promise { const session = this.ctx.session; this.ctx.showStatus("Checking saved rate-limit resets…", { dim: true }); - let statuses: Awaited>; + let statuses: ResetCreditAccountStatus[]; try { statuses = await session.listResetCredits(); } catch (error) { diff --git a/packages/coding-agent/src/session/auth-broker-config.ts b/packages/coding-agent/src/session/auth-broker-config.ts index 49b3b5d30..184c8ef65 100644 --- a/packages/coding-agent/src/session/auth-broker-config.ts +++ b/packages/coding-agent/src/session/auth-broker-config.ts @@ -30,6 +30,7 @@ import { } from "@oh-my-pi/pi-ai/auth-broker/discover"; import { getAgentDir } from "@oh-my-pi/pi-utils"; import { resolveConfigValue } from "../config/resolve-config-value"; +import type { AuthStorage } from "./auth-storage"; export { type AuthBrokerClientConfig, getAuthBrokerTokenFilePath }; @@ -82,7 +83,7 @@ export function resolveAuthBrokerConfig(): Promise, -): ReturnType { +): Promise { return discoverAuthStorageShared({ ...options, agentDir, diff --git a/packages/coding-agent/test/goals/goal-mode-integration.test.ts b/packages/coding-agent/test/goals/goal-mode-integration.test.ts index 4ba11e90d..07635fc09 100644 --- a/packages/coding-agent/test/goals/goal-mode-integration.test.ts +++ b/packages/coding-agent/test/goals/goal-mode-integration.test.ts @@ -1,5 +1,6 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "bun:test"; import * as path from "node:path"; +import type { Model } from "@oh-my-pi/pi-ai"; import { Agent } from "@oh-my-pi/pi-agent-core"; import { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry"; import { resetSettingsForTest, Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; @@ -41,7 +42,7 @@ type GoalHarness = { type SharedFixture = { authStorage: AuthStorage; modelRegistry: ModelRegistry; - model: NonNullable>; + model: Model; baseDir: TempDir; }; diff --git a/packages/coding-agent/test/hook-editor.test.ts b/packages/coding-agent/test/hook-editor.test.ts index a5316b722..1111803b5 100644 --- a/packages/coding-agent/test/hook-editor.test.ts +++ b/packages/coding-agent/test/hook-editor.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeAll, describe, expect, it, vi } from "bun:test"; +import { afterEach, beforeAll, describe, expect, it, type Mock, vi } from "bun:test"; import { KeybindingsManager } from "@oh-my-pi/pi-coding-agent/config/keybindings"; import { HookEditorComponent } from "@oh-my-pi/pi-coding-agent/modes/components/hook-editor"; import { ExtensionUiController } from "@oh-my-pi/pi-coding-agent/modes/controllers/extension-ui-controller"; @@ -67,8 +67,8 @@ function createControllerContext() { stop: vi.fn(), terminal: { columns: 120 }, } as unknown as TestContext["ui"] & { - setFocus: ReturnType; - requestRender: ReturnType; + setFocus: Mock; + requestRender: Mock; }; const ctx = { editor, diff --git a/packages/coding-agent/test/memories-runtime.test.ts b/packages/coding-agent/test/memories-runtime.test.ts index 155d7f90d..fb99e0540 100644 --- a/packages/coding-agent/test/memories-runtime.test.ts +++ b/packages/coding-agent/test/memories-runtime.test.ts @@ -102,7 +102,7 @@ const flushAsync = (): Promise => new Promise(resolve => setTimeout( // instead of polling, racing a generous timeout so a stalled regression fails // loudly rather than hanging. async function settle(promise: Promise, label: string, timeoutMs = 3000): Promise { - let timer: ReturnType | undefined; + let timer: Timer | undefined; const timeout = new Promise((_, reject) => { timer = setTimeout(() => reject(new Error(`Timed out waiting for ${label}`)), timeoutMs); }); diff --git a/packages/coding-agent/test/silent-abort-print-mode.test.ts b/packages/coding-agent/test/silent-abort-print-mode.test.ts index 9e0fb82c2..c88c68e28 100644 --- a/packages/coding-agent/test/silent-abort-print-mode.test.ts +++ b/packages/coding-agent/test/silent-abort-print-mode.test.ts @@ -5,7 +5,7 @@ * when stopReason is "aborted", which would surface the sentinel to stderr * (and exit with code 1). This test verifies the guard skips silent-abort. */ -import { afterEach, beforeEach, describe, expect, it, vi } from "bun:test"; +import { afterEach, beforeEach, describe, expect, it, type Mock, vi } from "bun:test"; import type { AssistantMessage } from "@oh-my-pi/pi-ai"; import { runPrintMode } from "@oh-my-pi/pi-coding-agent/modes/print-mode"; import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session"; @@ -47,7 +47,7 @@ function createMockSession(messages: AssistantMessage[]): AgentSession { } describe("Print-mode silent-abort regression", () => { - let exitSpy: ReturnType; + let exitSpy: Mock; let stderrOutput: string[]; let stdoutOutput: string[]; diff --git a/packages/coding-agent/test/task/autoload-skills.test.ts b/packages/coding-agent/test/task/autoload-skills.test.ts index 06f395163..c2d18ae55 100644 --- a/packages/coding-agent/test/task/autoload-skills.test.ts +++ b/packages/coding-agent/test/task/autoload-skills.test.ts @@ -1,4 +1,4 @@ -import { afterEach, describe, expect, it, vi } from "bun:test"; +import { afterEach, describe, expect, it, type Mock, vi } from "bun:test"; import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import type { Skill } from "@oh-my-pi/pi-coding-agent/extensibility/skills"; import * as skillsModule from "@oh-my-pi/pi-coding-agent/extensibility/skills"; @@ -143,7 +143,7 @@ describe("autoloadSkills in executor", () => { autoloadSkills: mockSkills, }); - const sendCustomMessage = session.sendCustomMessage as ReturnType; + const sendCustomMessage = session.sendCustomMessage as Mock; expect(sendCustomMessage).toHaveBeenCalledTimes(2); // Verify first skill @@ -189,7 +189,7 @@ describe("autoloadSkills in executor", () => { await runSubprocess(baseOptions); - const sendCustomMessage = session.sendCustomMessage as ReturnType; + const sendCustomMessage = session.sendCustomMessage as Mock; expect(sendCustomMessage).not.toHaveBeenCalled(); }); @@ -211,7 +211,7 @@ describe("autoloadSkills in executor", () => { await runSubprocess({ ...baseOptions, autoloadSkills: undefined }); - const sendCustomMessage = session.sendCustomMessage as ReturnType; + const sendCustomMessage = session.sendCustomMessage as Mock; expect(sendCustomMessage).not.toHaveBeenCalled(); }); @@ -231,7 +231,7 @@ describe("autoloadSkills in executor", () => { }); // Track sendCustomMessage call order - (session.sendCustomMessage as ReturnType).mockImplementation(async () => { + (session.sendCustomMessage as Mock).mockImplementation(async () => { callOrder.push("sendCustomMessage"); }); diff --git a/packages/coding-agent/test/tools/approval-mode.test.ts b/packages/coding-agent/test/tools/approval-mode.test.ts index 4f1bd9459..a5fa4ce2d 100644 --- a/packages/coding-agent/test/tools/approval-mode.test.ts +++ b/packages/coding-agent/test/tools/approval-mode.test.ts @@ -6,6 +6,7 @@ import type { AgentToolContext } from "@oh-my-pi/pi-agent-core"; import { getBundledModel } from "@oh-my-pi/pi-catalog/models"; import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import { createAgentSession } from "@oh-my-pi/pi-coding-agent/sdk"; +import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session"; import { SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager"; import { Snowflake } from "@oh-my-pi/pi-utils"; @@ -34,7 +35,7 @@ describe("tools.approvalMode setting", () => { // settings per assertion. This avoids paying createAgentSession's cost (model registry, // auth-storage discovery, settings init) nine times over. let tempDir: string; - let session: Awaited>["session"]; + let session: AgentSession; beforeAll(async () => { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), `pi-approval-mode-${Snowflake.next()}-`)); diff --git a/packages/coding-agent/test/tools/gh.test.ts b/packages/coding-agent/test/tools/gh.test.ts index 2d1a84ba6..a762aeb9e 100644 --- a/packages/coding-agent/test/tools/gh.test.ts +++ b/packages/coding-agent/test/tools/gh.test.ts @@ -180,6 +180,11 @@ async function createPrFixture(): Promise { * `getWorktreesDir()` resolves under an isolated temp home instead of the * user's real `~/.omp/wt`. Returns the temp home and a cleanup hook. */ +interface TempHome { + home: string; + cleanup: () => Promise; +} + async function setupTempHome(): Promise<{ home: string; cleanup: () => Promise }> { const home = await fs.mkdtemp(path.join(os.tmpdir(), "gh-pr-tool-home-")); vi.spyOn(os, "homedir").mockReturnValue(home); @@ -765,7 +770,7 @@ describe("github tool", () => { // Arrange the mutable fixture + isolated $HOME once in beforeAll (excluded // from test-body time); the body only performs the checkout and assertions. let fixture: PrFixture; - let tempHome: Awaited>; + let tempHome: TempHome; beforeAll(async () => { fixture = await createPrFixture(); tempHome = await setupTempHome(); @@ -867,7 +872,7 @@ describe("github tool", () => { describe("pr_checkout (array of pull requests)", () => { // Same beforeAll-hoisted arrange: the body only runs the array checkout. let fixture: PrFixture; - let tempHome: Awaited>; + let tempHome: TempHome; beforeAll(async () => { fixture = await createPrFixture(); tempHome = await setupTempHome(); diff --git a/packages/coding-agent/test/tools/lsp-regressions.test.ts b/packages/coding-agent/test/tools/lsp-regressions.test.ts index edf312ab7..9898d8c62 100644 --- a/packages/coding-agent/test/tools/lsp-regressions.test.ts +++ b/packages/coding-agent/test/tools/lsp-regressions.test.ts @@ -78,7 +78,7 @@ function installFakeLsp(handler: FakeLspHandler): FakeLspServer { const waiters: Array<{ predicate: (message: RpcMessage) => boolean; resolve: (message: RpcMessage) => void; - timer: ReturnType; + timer: Timer; }> = []; let exitCode: number | null = null; let killed = false; diff --git a/packages/coding-agent/test/tools/todo.test.ts b/packages/coding-agent/test/tools/todo.test.ts index 96191f61f..7b44bd8f9 100644 --- a/packages/coding-agent/test/tools/todo.test.ts +++ b/packages/coding-agent/test/tools/todo.test.ts @@ -12,6 +12,7 @@ import { todoMatchesAnyDescription, todoToolRenderer, } from "@oh-my-pi/pi-coding-agent/tools"; +import type { Component } from "@oh-my-pi/pi-tui"; function createSession(initialPhases: TodoPhase[] = []): ToolSession { let phases = initialPhases; @@ -435,7 +436,7 @@ describe("todoToolRenderer.renderResult phase collapsing", () => { // Beta and Gamma untouched by this update. return tool.execute("done", { ops: [{ op: "done", task: "a1" }] }); } - function innerLines(component: ReturnType): string[] { + function innerLines(component: Component): string[] { const lines = Bun.stripANSI(component.render(100).join("\n")).split("\n"); return lines.slice(1, -1).map(line => line.replace(/^│/, "").replace(/│\s*$/, "").trim()); } diff --git a/packages/mnemopi/test/extraction-integration.test.ts b/packages/mnemopi/test/extraction-integration.test.ts index f2513d1e1..25d9646f8 100644 --- a/packages/mnemopi/test/extraction-integration.test.ts +++ b/packages/mnemopi/test/extraction-integration.test.ts @@ -113,7 +113,7 @@ describe("extraction integration", () => { const callback = handler as (...callbackArgs: unknown[]) => void; queueMicrotask(() => callback(...args)); } - return 0 as unknown as ReturnType; + return 0 as unknown as Timer; }) as typeof setTimeout; class RateLimitedClient extends ExtractionClient { diff --git a/packages/tui/src/terminal.ts b/packages/tui/src/terminal.ts index ec3fd2ff4..ff736c7d2 100644 --- a/packages/tui/src/terminal.ts +++ b/packages/tui/src/terminal.ts @@ -437,7 +437,7 @@ export class ProcessTerminal implements Terminal { #reportedRows?: number; #osc11PollTimer?: Timer; #mode2031DebounceTimer?: Timer; - #progressTimer?: ReturnType; + #progressTimer?: Timer; get kittyProtocolActive(): boolean { return this.#kittyProtocolActive;