refactor: replaced ReturnType<typeof setTimeout> with Timer type
- Replaced usage of `ReturnType<typeof setTimeout>` and `ReturnType<typeof setInterval>` 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.
This commit is contained in:
@@ -718,7 +718,7 @@ async function runLoopBody(
|
||||
stepCounter: StepCounter,
|
||||
streamFn?: StreamFn,
|
||||
): Promise<void> {
|
||||
let deadlineTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
let deadlineTimer: Timer | undefined;
|
||||
if (config.deadline !== undefined) {
|
||||
const deadlineAbortController = new AbortController();
|
||||
const delay = config.deadline - Date.now();
|
||||
|
||||
@@ -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<typeof spyOn>).mock.calls.length).toBe(0);
|
||||
expect((fetchImpl as unknown as Mock<typeof globalThis.fetch>).mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it("forwards the caller's AbortSignal to the underlying fetch", async () => {
|
||||
|
||||
@@ -39,7 +39,6 @@ import type { LoadedConfig } from "./config";
|
||||
|
||||
## Exceptions
|
||||
|
||||
- Timer handles: `ReturnType<typeof setTimeout>` / `setInterval`.
|
||||
- Generic type utilities where the function is a type parameter.
|
||||
|
||||
Concrete function? Export a concrete type.
|
||||
|
||||
@@ -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<typeof setTimeout> | 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. */
|
||||
|
||||
@@ -179,9 +179,9 @@ export class ModelSelectorComponent extends Container {
|
||||
#providers: ProviderTabState[] = STATIC_PROVIDER_TABS;
|
||||
#activeTabIndex: number = 0;
|
||||
#refreshingProviders: Set<string> = new Set();
|
||||
#scheduledProviderRefreshes: Map<string, ReturnType<typeof setTimeout>> = new Map();
|
||||
#scheduledProviderRefreshes: Map<string, Timer> = new Map();
|
||||
#refreshSpinnerFrame: number = 0;
|
||||
#refreshSpinnerInterval?: NodeJS.Timeout;
|
||||
#refreshSpinnerInterval?: Timer;
|
||||
|
||||
// Context menu state
|
||||
#isMenuOpen: boolean = false;
|
||||
|
||||
@@ -142,7 +142,7 @@ export interface LspServerInfo {
|
||||
*/
|
||||
export class WelcomeComponent implements Component {
|
||||
#animStart: number | null = null;
|
||||
#animTimer: ReturnType<typeof setInterval> | 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.
|
||||
|
||||
@@ -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<void> {
|
||||
const session = this.ctx.session;
|
||||
this.ctx.showStatus("Checking saved rate-limit resets…", { dim: true });
|
||||
let statuses: Awaited<ReturnType<typeof session.listResetCredits>>;
|
||||
let statuses: ResetCreditAccountStatus[];
|
||||
try {
|
||||
statuses = await session.listResetCredits();
|
||||
} catch (error) {
|
||||
|
||||
@@ -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<AuthBrokerClientConfig | null
|
||||
export function discoverAuthStorage(
|
||||
agentDir: string = getAgentDir(),
|
||||
options?: Omit<DiscoverAuthStorageOptions, "agentDir" | "configValueResolver">,
|
||||
): ReturnType<typeof discoverAuthStorageShared> {
|
||||
): Promise<AuthStorage> {
|
||||
return discoverAuthStorageShared({
|
||||
...options,
|
||||
agentDir,
|
||||
|
||||
@@ -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<ReturnType<ModelRegistry["find"]>>;
|
||||
model: Model;
|
||||
baseDir: TempDir;
|
||||
};
|
||||
|
||||
|
||||
@@ -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<typeof vi.fn>;
|
||||
requestRender: ReturnType<typeof vi.fn>;
|
||||
setFocus: Mock;
|
||||
requestRender: Mock;
|
||||
};
|
||||
const ctx = {
|
||||
editor,
|
||||
|
||||
@@ -102,7 +102,7 @@ const flushAsync = (): Promise<void> => new Promise<void>(resolve => setTimeout(
|
||||
// instead of polling, racing a generous timeout so a stalled regression fails
|
||||
// loudly rather than hanging.
|
||||
async function settle(promise: Promise<void>, label: string, timeoutMs = 3000): Promise<void> {
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
let timer: Timer | undefined;
|
||||
const timeout = new Promise<never>((_, reject) => {
|
||||
timer = setTimeout(() => reject(new Error(`Timed out waiting for ${label}`)), timeoutMs);
|
||||
});
|
||||
|
||||
@@ -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<typeof vi.spyOn>;
|
||||
let exitSpy: Mock<typeof process.exit>;
|
||||
let stderrOutput: string[];
|
||||
let stdoutOutput: string[];
|
||||
|
||||
|
||||
@@ -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<typeof vi.fn>;
|
||||
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<typeof vi.fn>;
|
||||
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<typeof vi.fn>;
|
||||
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<typeof vi.fn>).mockImplementation(async () => {
|
||||
(session.sendCustomMessage as Mock).mockImplementation(async () => {
|
||||
callOrder.push("sendCustomMessage");
|
||||
});
|
||||
|
||||
|
||||
@@ -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<ReturnType<typeof createAgentSession>>["session"];
|
||||
let session: AgentSession;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), `pi-approval-mode-${Snowflake.next()}-`));
|
||||
|
||||
@@ -180,6 +180,11 @@ async function createPrFixture(): Promise<PrFixture> {
|
||||
* `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<void>;
|
||||
}
|
||||
|
||||
async function setupTempHome(): Promise<{ home: string; cleanup: () => Promise<void> }> {
|
||||
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<ReturnType<typeof setupTempHome>>;
|
||||
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<ReturnType<typeof setupTempHome>>;
|
||||
let tempHome: TempHome;
|
||||
beforeAll(async () => {
|
||||
fixture = await createPrFixture();
|
||||
tempHome = await setupTempHome();
|
||||
|
||||
@@ -78,7 +78,7 @@ function installFakeLsp(handler: FakeLspHandler): FakeLspServer {
|
||||
const waiters: Array<{
|
||||
predicate: (message: RpcMessage) => boolean;
|
||||
resolve: (message: RpcMessage) => void;
|
||||
timer: ReturnType<typeof setTimeout>;
|
||||
timer: Timer;
|
||||
}> = [];
|
||||
let exitCode: number | null = null;
|
||||
let killed = false;
|
||||
|
||||
@@ -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<typeof todoToolRenderer.renderResult>): 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());
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ describe("extraction integration", () => {
|
||||
const callback = handler as (...callbackArgs: unknown[]) => void;
|
||||
queueMicrotask(() => callback(...args));
|
||||
}
|
||||
return 0 as unknown as ReturnType<typeof setTimeout>;
|
||||
return 0 as unknown as Timer;
|
||||
}) as typeof setTimeout;
|
||||
|
||||
class RateLimitedClient extends ExtractionClient {
|
||||
|
||||
@@ -437,7 +437,7 @@ export class ProcessTerminal implements Terminal {
|
||||
#reportedRows?: number;
|
||||
#osc11PollTimer?: Timer;
|
||||
#mode2031DebounceTimer?: Timer;
|
||||
#progressTimer?: ReturnType<typeof setInterval>;
|
||||
#progressTimer?: Timer;
|
||||
|
||||
get kittyProtocolActive(): boolean {
|
||||
return this.#kittyProtocolActive;
|
||||
|
||||
Reference in New Issue
Block a user