Remove unnecessary type assertions across codebase

Add oxlint-tsgolint and configure typescript/no-unnecessary-type-assertion
to flag redundant `!` and `as Foo` casts. Type-aware mode is left off by
default to keep `npm run lint` fast; the rule sits configured for when we
turn type-aware on intentionally. Auto-fix removed ~283 redundant casts;
two manual touch-ups: a real tsgolint false positive in split-container.tsx
and a stale ChildProcess import after a double-cast collapsed.
This commit is contained in:
Mohamed Boudra
2026-05-04 10:21:52 +07:00
parent 78fe3e4df3
commit 4cd9e76bd2
129 changed files with 409 additions and 323 deletions

View File

@@ -138,7 +138,7 @@ export class DaemonClientRuntimeMetrics {
private pruneBuckets(now: number): void {
const cutoff = now - this.windowMs;
while (this.buckets.length > 0 && this.buckets[0]!.endedAt < cutoff) {
while (this.buckets.length > 0 && this.buckets[0].endedAt < cutoff) {
this.buckets.shift();
}
}

View File

@@ -128,7 +128,7 @@ export function bindWsHandler(
}
};
}
const prop = `on${event}` as "onopen" | "onclose" | "onerror" | "onmessage";
const prop = `on${event}`;
const wsRecord = ws as unknown as Record<string, unknown>;
const previous = wsRecord[prop];
wsRecord[prop] = handler;

View File

@@ -1124,7 +1124,7 @@ export class DaemonClient {
return this.subscribe(arg1);
}
const type = arg1 as SessionOutboundMessage["type"];
const type = arg1;
const handler = arg2 as (message: SessionOutboundMessage) => void;
if (!this.messageHandlers.has(type)) {

View File

@@ -1833,7 +1833,7 @@ test("fetchTimeline returns a bounded reset window when cursor epoch is stale",
direction: "after",
cursor: {
epoch: "stale-epoch",
seq: baseline.rows[baseline.rows.length - 1]!.seq,
seq: baseline.rows[baseline.rows.length - 1].seq,
},
limit: 1,
});
@@ -2613,7 +2613,7 @@ test("replaceAgentRun does not emit idle or resolve waiters between interrupted
}, []);
expect(runningIndexes.length).toBeGreaterThanOrEqual(2);
const firstReplacementRunningIndex = runningIndexes[1]!;
const firstReplacementRunningIndex = runningIndexes[1];
expect(lifecycleUpdates.slice(0, firstReplacementRunningIndex).includes("idle")).toBe(false);
allowSecondRunToEnd.resolve();
@@ -4766,11 +4766,10 @@ test("hydrateTimeline suppresses only matching canonical user_message messageId"
const timeline = manager.getTimeline(snapshot.id);
const userMessages = timeline.filter((item) => item.type === "user_message");
expect(userMessages).toHaveLength(2);
expect(
userMessages.map(
(item) => (item as Extract<AgentTimelineItem, { type: "user_message" }>).messageId,
),
).toEqual(["msg_client_hello", "msg_provider_distinct"]);
expect(userMessages.map((item) => item.messageId)).toEqual([
"msg_client_hello",
"msg_provider_distinct",
]);
expect(userMessages.map((item) => item.text)).toEqual(["hello from user", "hello from user"]);
});
@@ -4815,11 +4814,11 @@ test("recordUserMessage normalizes blank/whitespace messageId to undefined", asy
expect(userMessages).toHaveLength(3);
// Empty string → undefined (not empty string)
expect(userMessages[0]!.messageId).toBeUndefined();
expect(userMessages[0].messageId).toBeUndefined();
// Whitespace → undefined
expect(userMessages[1]!.messageId).toBeUndefined();
expect(userMessages[1].messageId).toBeUndefined();
// Valid → preserved
expect(userMessages[2]!.messageId).toBe("msg_valid_123");
expect(userMessages[2].messageId).toBe("msg_valid_123");
});
test("recordUserMessage preserves provided messageId in timeline item and dispatched event", async () => {
@@ -4942,9 +4941,7 @@ test("live provider user_message echo is suppressed when recordUserMessage was c
// Should be exactly 1 (canonical), not 2 (canonical + provider echo)
expect(userMessages).toHaveLength(1);
// The canonical one must carry the client messageId for optimistic matching
expect((userMessages[0] as Extract<AgentTimelineItem, { type: "user_message" }>).messageId).toBe(
"msg_client_echo_1",
);
expect(userMessages[0].messageId).toBe("msg_client_echo_1");
// Assistant messages from the run should still appear
const assistantMessages = timeline.filter((item) => item.type === "assistant_message");
@@ -5135,9 +5132,7 @@ test("provider user_message is NOT suppressed when no prior recordUserMessage",
// Provider's user_message should be recorded (no canonical to dedup against)
expect(userMessages).toHaveLength(1);
expect((userMessages[0] as Extract<AgentTimelineItem, { type: "user_message" }>).text).toBe(
"continuation prompt",
);
expect(userMessages[0].text).toBe("continuation prompt");
});
test("replaceAgentRun succeeds when foreground turn terminal event is never delivered", async () => {

View File

@@ -1301,7 +1301,7 @@ export class AgentManager {
throw new Error(`Agent ${agentId} already has an active run`);
}
const agent = existingAgent as ActiveManagedAgent;
const agent = existingAgent;
agent.pendingReplacement = false;
agent.lastError = undefined;
@@ -1361,7 +1361,7 @@ export class AgentManager {
}
private finalizeForegroundTurn(agent: ActiveManagedAgent, turnId?: string): void {
const mutableAgent = agent as ActiveManagedAgent;
const mutableAgent = agent;
if (turnId) {
this.foregroundRuns.rememberFinalizedTurn(mutableAgent, turnId);
}
@@ -1430,7 +1430,7 @@ export class AgentManager {
} catch (error) {
const latest = this.agents.get(agentId);
if (latest) {
const latestActive = latest as ActiveManagedAgent;
const latestActive = latest;
latestActive.pendingReplacement = false;
if (!latestActive.activeForegroundTurnId && latestActive.lifecycle === "running") {
(latestActive as ActiveManagedAgent).lifecycle = "idle";
@@ -1502,7 +1502,7 @@ export class AgentManager {
if (options?.signal) {
abortHandler = () =>
finishErr(createAbortError(options.signal!, "wait_for_agent_start aborted"));
finishErr(createAbortError(options.signal, "wait_for_agent_start aborted"));
options.signal.addEventListener("abort", abortHandler, { once: true });
}
@@ -2636,7 +2636,7 @@ export class AgentManager {
"handleStreamEvent: turn_canceled",
);
if (!isForegroundEvent && !agent.pendingReplacement) {
(agent as ActiveManagedAgent).lifecycle = "idle";
agent.lifecycle = "idle";
}
agent.lastError = undefined;
this.resolvePendingPermissionsForAgent(agent, event.provider, options, "Interrupted");
@@ -2661,7 +2661,7 @@ export class AgentManager {
"handleStreamEvent: turn_started",
);
if (!isForegroundEvent) {
(agent as ActiveManagedAgent).lifecycle = "running";
agent.lifecycle = "running";
this.emitState(agent);
}
}

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { AGENT_LIFECYCLE_STATUSES, type AgentLifecycleStatus } from "./agent-manager.js";
import { AGENT_LIFECYCLE_STATUSES } from "./agent-manager.js";
import { toAgentPayload, toStoredAgentRecord, type ManagedAgent } from "./agent-projections.js";
import type { AgentSession } from "./agent-sdk-types.js";
import type {
@@ -203,7 +203,7 @@ describe("toStoredAgentRecord", () => {
it("propagates lifecycle status for all states", () => {
for (const status of AGENT_LIFECYCLE_STATUSES) {
const agent = createManagedAgent({ lifecycle: status as AgentLifecycleStatus });
const agent = createManagedAgent({ lifecycle: status });
const record = toStoredAgentRecord(agent);
expect(record.lastStatus).toBe(status);
}
@@ -301,7 +301,7 @@ describe("toAgentPayload", () => {
it("propagates lifecycle status for all states", () => {
for (const status of AGENT_LIFECYCLE_STATUSES) {
const agent = createManagedAgent({ lifecycle: status as AgentLifecycleStatus });
const agent = createManagedAgent({ lifecycle: status });
const payload = toAgentPayload(agent);
expect(payload.status).toBe(status);
}

View File

@@ -214,14 +214,14 @@ function tryParseJson(candidate: string): string | null {
}
function extractBalancedJsonCandidate(source: string, start: number): string | null {
const open = source[start]!;
const open = source[start];
const close = open === "{" ? "}" : "]";
let depth = 0;
let inString = false;
let escaped = false;
for (let i = start; i < source.length; i += 1) {
const ch = source[i]!;
const ch = source[i];
if (inString) {
if (escaped) {

View File

@@ -58,7 +58,7 @@ function fetchTail(ctx: FetchContext): AgentTimelineFetchResult {
staleCursor: false,
gap: false,
window,
hasOlder: selected.length > 0 && selected[0]!.seq > minSeq,
hasOlder: selected.length > 0 && selected[0].seq > minSeq,
hasNewer: false,
rows: selected.map(cloneRow),
};
@@ -93,7 +93,7 @@ function fetchAfter(ctx: FetchContext): AgentTimelineFetchResult {
staleCursor: false,
gap: false,
window,
hasOlder: selected[0]!.seq > minSeq,
hasOlder: selected[0].seq > minSeq,
hasNewer: Boolean(lastSelected && lastSelected.seq < maxSeq),
rows: selected.map(cloneRow),
};
@@ -115,7 +115,7 @@ function fetchBefore(ctx: FetchContext): AgentTimelineFetchResult {
staleCursor: false,
gap: false,
window,
hasOlder: selected.length > 0 && selected[0]!.seq > minSeq,
hasOlder: selected.length > 0 && selected[0].seq > minSeq,
hasNewer: endExclusive >= 0,
rows: selected.map(cloneRow),
};
@@ -137,7 +137,7 @@ function fetchReset(
staleCursor: flags.staleCursor,
gap: flags.gap,
window,
hasOlder: rows.length > 0 && rows[0]!.seq > minSeq,
hasOlder: rows.length > 0 && rows[0].seq > minSeq,
hasNewer: false,
rows,
};
@@ -155,7 +155,7 @@ export class InMemoryAgentTimelineStore {
const rows = options?.rows?.length
? options.rows.map(cloneRow)
: this.buildRowsFromItems(options?.items ?? [], options?.nextSeq ?? 1, timestamp);
const nextSeq = options?.nextSeq ?? (rows.length ? rows[rows.length - 1]!.seq + 1 : 1);
const nextSeq = options?.nextSeq ?? (rows.length ? rows[rows.length - 1].seq + 1 : 1);
this.states.set(agentId, {
epoch: options?.epoch ?? randomUUID(),
rows,
@@ -188,8 +188,8 @@ export class InMemoryAgentTimelineStore {
? DEFAULT_TIMELINE_FETCH_LIMIT
: Math.max(0, Math.floor(requestedLimit));
const cursor = options?.cursor;
const minSeq = state.rows.length ? state.rows[0]!.seq : 0;
const maxSeq = state.rows.length ? state.rows[state.rows.length - 1]!.seq : 0;
const minSeq = state.rows.length ? state.rows[0].seq : 0;
const maxSeq = state.rows.length ? state.rows[state.rows.length - 1].seq : 0;
const selectAll = limit === 0;
const window = {
@@ -265,7 +265,7 @@ export class InMemoryAgentTimelineStore {
const rows = this.requireState(agentId).rows;
const chunks: string[] = [];
for (let i = rows.length - 1; i >= 0; i -= 1) {
const item = rows[i]!.item;
const item = rows[i].item;
if (item.type !== "assistant_message") {
if (chunks.length > 0) {
break;

View File

@@ -141,7 +141,7 @@ function createTestDeps(): TestDeps {
}
function createProviderDefinition(overrides: Partial<ProviderDefinition>): ProviderDefinition {
const provider = (overrides.id ?? "claude") as AgentProvider;
const provider = overrides.id ?? "claude";
return {
id: provider,
label: "Claude",

View File

@@ -168,9 +168,7 @@ function resolveRegisteredProviderIds(
agentManager: AgentManager,
providerRegistry: Record<AgentProvider, ProviderDefinition> | null | undefined,
): AgentProvider[] {
return providerRegistry
? (Object.keys(providerRegistry) as AgentProvider[])
: agentManager.getRegisteredProviderIds();
return providerRegistry ? Object.keys(providerRegistry) : agentManager.getRegisteredProviderIds();
}
interface ProviderSummary {
@@ -239,7 +237,7 @@ function resolveScheduleProviderAndModel(params: {
const providerInput = params.provider?.trim() || params.defaultProvider;
const slashIndex = providerInput.indexOf("/");
if (slashIndex === -1) {
return { provider: providerInput as AgentProvider };
return { provider: providerInput };
}
const provider = providerInput.slice(0, slashIndex).trim();
@@ -249,7 +247,7 @@ function resolveScheduleProviderAndModel(params: {
}
return {
provider: provider as AgentProvider,
provider: provider,
model,
};
}
@@ -447,7 +445,7 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom
const resolvedProviderModel = resolveScheduleProviderAndModel({
provider: params?.provider,
defaultProvider: params.provider as AgentProvider,
defaultProvider: params.provider,
});
return {
type: "new-agent" as const,

View File

@@ -86,7 +86,7 @@ export function resolveRequiredProviderModel(
}
return {
provider: provider as AgentProvider,
provider: provider,
model,
};
}

View File

@@ -5,7 +5,7 @@ import { resolveAgentModel } from "./model-resolver.js";
vi.mock("./provider-registry.js", () => ({
buildProviderRegistry: vi.fn(),
isProviderEnabled: vi.fn((definition: { enabled: boolean }) => definition.enabled === true),
isProviderEnabled: vi.fn((definition: { enabled: boolean }) => definition.enabled),
}));
import { buildProviderRegistry } from "./provider-registry.js";

View File

@@ -51,8 +51,8 @@ export class Pcm16MonoResampler {
while (this.pos < maxPos) {
const i = Math.floor(this.pos);
const frac = this.pos - i;
const s0 = src[i]!;
const s1 = src[i + 1]!;
const s0 = src[i];
const s1 = src[i + 1];
const sample = s0 + (s1 - s0) * frac;
const clamped = Math.max(-1, Math.min(1, sample));
const int16 = Math.round(clamped * 32767);
@@ -61,7 +61,7 @@ export class Pcm16MonoResampler {
}
// Keep the last input sample as carry for the next chunk.
const lastInput = srcChunk[srcChunk.length - 1]!;
const lastInput = srcChunk[srcChunk.length - 1];
this.carrySample = lastInput;
// Shift position so next chunk (which will include carry sample) continues smoothly.

View File

@@ -112,7 +112,7 @@ export async function resolveProviderCommandPrefix(
}
return {
command: commandConfig.argv[0]!,
command: commandConfig.argv[0],
args: commandConfig.argv.slice(1),
};
}

View File

@@ -389,7 +389,7 @@ export class ProviderSnapshotManager {
}
private getProviderIds(): AgentProvider[] {
return Object.keys(this.providerRegistry) as AgentProvider[];
return Object.keys(this.providerRegistry);
}
private resolveRefreshProviders(providers?: AgentProvider[]): AgentProvider[] | undefined {

View File

@@ -317,7 +317,7 @@ test("Test 4: Autonomous run", async () => {
return;
}
const autoTurnId = autoStarts[0]!.turnId;
const autoTurnId = autoStarts[0].turnId;
expect(fgTurnId).not.toBe(autoTurnId);
// Autonomous turn reaches terminal

View File

@@ -653,14 +653,14 @@ export class ACPAgentClient implements AgentClient {
{ logger: this.logger, provider: this.provider },
);
const connection = new ClientSideConnection(() => this.buildProbeClient(), stream);
const initialize = (await Promise.race([
const initialize = await Promise.race([
connection.initialize({
protocolVersion: PROTOCOL_VERSION,
clientCapabilities: ACP_CLIENT_CAPABILITIES,
clientInfo: { name: "Paseo", version: "dev" },
}),
spawnErrorPromise,
])) as InitializeResponse;
]);
return { child, connection, initialize };
}
@@ -2093,7 +2093,7 @@ function mergeToolSnapshot(
): ACPToolSnapshot {
return {
toolCallId,
title: (update.title ?? previous?.title ?? toolCallId) as string,
title: update.title ?? previous?.title ?? toolCallId,
kind: update.kind ?? previous?.kind ?? null,
status: update.status ?? previous?.status ?? null,
content: coalesceDefined(update.content, previous?.content, null),

View File

@@ -1,7 +1,6 @@
import { beforeAll, beforeEach, describe, expect, test } from "vitest";
import pino from "pino";
import type { AgentSlashCommand } from "../agent-sdk-types.js";
import { isCommandAvailable } from "../../../utils/executable.js";
import { ClaudeAgentClient } from "./claude-agent.js";
@@ -40,7 +39,7 @@ describe("claude agent commands contract (real)", () => {
expect(commands.map((command) => command.name)).toContain("rewind");
for (const command of commands) {
const typed = command as AgentSlashCommand;
const typed = command;
expect(typeof typed.name).toBe("string");
expect(typed.name.length).toBeGreaterThan(0);
expect(typed.name.startsWith("/")).toBe(false);

View File

@@ -295,7 +295,7 @@ function resolveClaudeSpawnCommand(
}
return {
command: commandConfig.argv[0]!,
command: commandConfig.argv[0],
args: [...commandConfig.argv.slice(1), ...spawnOptions.args],
};
}
@@ -459,7 +459,7 @@ function normalizeForDeterministicString(value: unknown, seen: WeakSet<object>):
return value.map((entry) => normalizeForDeterministicString(entry, seen));
}
if (typeof value === "object") {
const objectValue = value as object;
const objectValue = value;
if (seen.has(objectValue)) {
return "[circular]";
}
@@ -1340,7 +1340,7 @@ async function resolveClaudeVersion(
try {
if (command?.mode === "replace") {
const { stdout } = await execCommand(
command.argv[0]!,
command.argv[0],
[...command.argv.slice(1), "--version"],
{ ...envSpec, timeout: 5_000 },
);
@@ -1392,7 +1392,7 @@ async function resolveClaudeAuth(
try {
let result: { stdout: string; stderr: string };
if (command?.mode === "replace") {
result = await run(command.argv[0]!, [...command.argv.slice(1), "auth", "status"]);
result = await run(command.argv[0], [...command.argv.slice(1), "auth", "status"]);
} else {
const executable = await findExecutable("claude");
if (!executable) {

View File

@@ -19,7 +19,7 @@ describe("getClaudeModels", () => {
const models = getClaudeModels();
const defaults = models.filter((m) => m.isDefault);
expect(defaults).toHaveLength(1);
expect(defaults[0]!.id).toBe("claude-opus-4-6");
expect(defaults[0].id).toBe("claude-opus-4-6");
});
it("returns fresh copies each call", () => {

View File

@@ -87,9 +87,9 @@ export function normalizeClaudeRuntimeModelId(value: string | null | undefined):
return null;
}
const family = runtimeMatch[1]!.toLowerCase();
const major = runtimeMatch[2]!;
const minor = runtimeMatch[3]!;
const family = runtimeMatch[1].toLowerCase();
const major = runtimeMatch[2];
const minor = runtimeMatch[3];
const suffix = runtimeMatch[4] ?? "";
return `claude-${family}-${major}-${minor}${suffix}`;
}

View File

@@ -289,14 +289,14 @@ function tokenizeCommandArgs(args: string): string[] {
let current = "";
let quote: "'" | '"' | null = null;
for (let i = 0; i < args.length; i += 1) {
const ch = args[i]!;
const ch = args[i];
if (quote) {
if (ch === quote) {
quote = null;
continue;
}
if (ch === "\\" && i + 1 < args.length) {
const next = args[i + 1]!;
const next = args[i + 1];
if (next === quote || next === "\\" || next === "n" || next === "t") {
i += 1;
current += decodeEscapedChar(next);

View File

@@ -130,7 +130,7 @@ function resolveModelProfile(modelId: string | null | undefined): {
durationMs: number;
intervalMs: number;
} {
const model = MODELS.find((entry) => entry.id === modelId) ?? MODELS[0]!;
const model = MODELS.find((entry) => entry.id === modelId) ?? MODELS[0];
const metadata = model.metadata ?? {};
return {
modelId: model.id,

View File

@@ -1,7 +1,6 @@
import { beforeAll, beforeEach, describe, expect, test } from "vitest";
import pino from "pino";
import type { AgentSlashCommand } from "../agent-sdk-types.js";
import { isCommandAvailable } from "../../../utils/executable.js";
import { OpenCodeAgentClient } from "./opencode-agent.js";
@@ -36,7 +35,7 @@ describe("opencode agent commands contract (real)", () => {
expect(commands.length).toBeGreaterThan(0);
for (const command of commands) {
const typed = command as AgentSlashCommand;
const typed = command;
expect(typeof typed.name).toBe("string");
expect(typed.name.length).toBeGreaterThan(0);
expect(typed.name.startsWith("/")).toBe(false);
@@ -63,7 +62,7 @@ describe("opencode agent commands contract (real)", () => {
expect(commands.length).toBeGreaterThan(0);
// Pick the first available command and send it without arguments.
const command = commands[0]!;
const command = commands[0];
const events: Array<{ type: string }> = [];
session.subscribe((event) => events.push(event));

View File

@@ -168,7 +168,7 @@ describe("opencode agent error handling (real)", () => {
const terminal = events.find(isTerminalEvent);
expect(terminal).toBeDefined();
expect(terminal!.type).toBe("turn_failed");
expect((terminal!.type === "turn_failed" ? terminal!.error : "").toLowerCase()).toMatch(
expect((terminal!.type === "turn_failed" ? terminal.error : "").toLowerCase()).toMatch(
/insufficient balance|resource package|recharge/,
);
} finally {

View File

@@ -46,7 +46,7 @@ export async function* streamSession(
turnId = result.turnId;
for (let idx = queue.length - 1; idx >= 0; idx -= 1) {
if (!matchesTurn(queue[idx]!)) {
if (!matchesTurn(queue[idx])) {
queue.splice(idx, 1);
}
}

View File

@@ -703,7 +703,7 @@ export function toShellToolDetail(
export function toReadToolDetail(
input: ParsedToolReadInput | null,
output: ParsedToolReadOutput | ParsedToolReadOutputWithPath | null,
output: ParsedToolReadOutput | null,
options?: { normalizePath?: NormalizePathFn },
): ToolCallDetail | undefined {
const filePath = normalizeDetailPath(input?.filePath ?? output?.filePath, options?.normalizePath);

View File

@@ -12,7 +12,7 @@ export function tokenizeToolName(name: string): string[] {
export function getToolLeafName(name: string): string | null {
const tokens = tokenizeToolName(name);
return tokens.length > 0 ? tokens[tokens.length - 1]! : null;
return tokens.length > 0 ? tokens[tokens.length - 1] : null;
}
export function isSpeakToolName(name: string): boolean {
@@ -33,7 +33,7 @@ export function isLikelyNamespacedToolName(name: string): boolean {
if (segments.length >= 3) {
return true;
}
if (segments.length === 2 && segments[1]!.includes("_")) {
if (segments.length === 2 && segments[1].includes("_")) {
return true;
}
return false;
@@ -49,11 +49,11 @@ export function isPaseoToolName(name: string): boolean {
return (
segments.length >= 3 &&
segments[0] === "mcp" &&
(segments[1] === "paseo" || segments[1]!.startsWith("paseo_"))
(segments[1] === "paseo" || segments[1].startsWith("paseo_"))
);
}
if (normalized.includes(".")) {
const firstSegment = normalized.split(".")[0]!;
const firstSegment = normalized.split(".")[0];
return firstSegment === "paseo" || firstSegment.startsWith("paseo_");
}
return false;
@@ -66,14 +66,14 @@ export function getPaseoToolLeafName(name: string): string | null {
if (
segments.length >= 3 &&
segments[0] === "mcp" &&
(segments[1] === "paseo" || segments[1]!.startsWith("paseo_"))
(segments[1] === "paseo" || segments[1].startsWith("paseo_"))
) {
return segments.slice(2).join("__");
}
return null;
}
if (normalized.includes(".")) {
const firstSegment = normalized.split(".")[0]!;
const firstSegment = normalized.split(".")[0];
if (firstSegment === "paseo" || firstSegment.startsWith("paseo_")) {
return normalized.split(".").slice(1).join(".");
}

View File

@@ -83,8 +83,8 @@ describe("TTSManager", () => {
expect(calls.length).toBeGreaterThan(1);
expect(calls.every((text) => text.length <= 260)).toBe(true);
expect(calls[0]!.length).toBeLessThanOrEqual(120);
expect(calls.slice(1).some((text) => text.length > calls[0]!.length)).toBe(true);
expect(calls[0].length).toBeLessThanOrEqual(120);
expect(calls.slice(1).some((text) => text.length > calls[0].length)).toBe(true);
});
it("prefetches the next segment before current playback completes", async () => {

View File

@@ -181,7 +181,7 @@ export class TTSManager {
const scheduleNextSegments = () => {
while (nextSegmentToSchedule < segments.length && inflight.size < TTS_PREFETCH_SEGMENTS) {
const segment = segments[nextSegmentToSchedule]!;
const segment = segments[nextSegmentToSchedule];
inflight.set(segment.index, this.scheduleSegmentSynthesis(segment, abortSignal));
nextSegmentToSchedule += 1;
}

View File

@@ -44,7 +44,7 @@ function pickTwoDistinctModels(models: Array<{ id: string }>): [string, string]
if (ids.length < 2) {
throw new Error(`Need at least 2 models to test switching; got ${ids.length}`);
}
return [ids[0]!, ids[1]!];
return [ids[0], ids[1]];
}
function isBinaryInstalled(binary: string): boolean {
@@ -127,7 +127,7 @@ test("live thinking switching works for Claude (off -> on)", async () => {
if (!modelList.models || modelList.models.length === 0) {
throw new Error("No Claude models returned");
}
const modelId = modelList.models[0]!.id;
const modelId = modelList.models[0].id;
const agent = await ctx.client.createAgent({
provider: "claude",

View File

@@ -20,7 +20,7 @@ function pickOpenCodeModel(
const preferred = models.find((model) =>
preferences.some((fragment) => model.id.includes(fragment)),
);
return preferred?.id ?? models[0]!.id;
return preferred?.id ?? models[0].id;
}
async function createHarness(): Promise<{

View File

@@ -36,7 +36,7 @@ function pickOpenCodeModel(
const preferred = models.find((model) =>
preferences.some((fragment) => model.id.includes(fragment)),
);
return preferred?.id ?? models[0]!.id;
return preferred?.id ?? models[0].id;
}
function hasRunningBashToolCall(messages: SessionOutboundMessage[], agentId: string): boolean {

View File

@@ -46,7 +46,7 @@ describe("daemon E2E - permission flow: Claude", () => {
const permissionState = await ctx.client.waitForFinish(agent.id, 5_000);
expect(permissionState.status).toBe("permission");
expect(permissionState.final?.pendingPermissions?.length).toBeGreaterThan(0);
const permission = permissionState.final!.pendingPermissions[0]!;
const permission = permissionState.final!.pendingPermissions[0];
await ctx.client.respondToPermission(agent.id, permission.id, { behavior: "allow" });
@@ -93,7 +93,7 @@ describe("daemon E2E - permission flow: Claude", () => {
const permissionState = await ctx.client.waitForFinish(agent.id, 5_000);
expect(permissionState.status).toBe("permission");
expect(permissionState.final?.pendingPermissions?.length).toBeGreaterThan(0);
const permission = permissionState.final!.pendingPermissions[0]!;
const permission = permissionState.final!.pendingPermissions[0];
await ctx.client.respondToPermission(agent.id, permission.id, {
behavior: "deny",

View File

@@ -503,7 +503,7 @@ function summarizeTerminalOutputCadence(input: {
}): TerminalOutputCadenceSummary {
const gaps = input.frames
.slice(1)
.map((frame, index) => frame.receivedAtMs - input.frames[index]!.receivedAtMs)
.map((frame, index) => frame.receivedAtMs - input.frames[index].receivedAtMs)
.sort((a, b) => a - b);
const p95Index =
gaps.length === 0 ? -1 : Math.min(gaps.length - 1, Math.ceil(gaps.length * 0.95) - 1);
@@ -512,7 +512,7 @@ function summarizeTerminalOutputCadence(input: {
return {
frameCount: input.frames.length,
maxGapMs: gaps.at(-1) ?? 0,
p95GapMs: p95Index === -1 ? 0 : gaps[p95Index]!,
p95GapMs: p95Index === -1 ? 0 : gaps[p95Index],
lastOutputAfterStopMs: lastFrame ? lastFrame.receivedAtMs - input.stoppedAtMs : 0,
payloadBytes: input.frames.map((frame) => frame.payloadBytes),
};

View File

@@ -37,7 +37,7 @@ export async function loadOrCreateDaemonKeyPair(
if (existsSync(filePath)) {
try {
const raw = readFileSync(filePath, "utf8");
const parsed = KeyPairSchema.parse(JSON.parse(raw)) as StoredKeyPair;
const parsed = KeyPairSchema.parse(JSON.parse(raw));
const publicKey = importPublicKey(parsed.publicKeyB64);
const secretKey = importSecretKey(parsed.secretKeyB64);

View File

@@ -83,7 +83,7 @@ export async function listAvailableEditorTargets(
const results: EditorTargetDescriptorPayload[] = [];
for (let i = 0; i < supportedTargets.length; i += 1) {
if (!executables[i]) continue;
const target = supportedTargets[i]!;
const target = supportedTargets[i];
results.push({
id: target.id,
label: target.label,

View File

@@ -41,15 +41,15 @@ export function ensureValidJson<T>(value: T): T {
}
if (typeof current === "object") {
if (seen.has(current as object)) {
if (seen.has(current)) {
throw new Error("Cannot serialize circular structure to JSON");
}
seen.add(current as object);
seen.add(current);
const obj: Record<string, JsonValue> = {};
for (const [key, val] of Object.entries(current as Record<string, unknown>)) {
obj[key] = sanitize(val);
}
seen.delete(current as object);
seen.delete(current);
return obj;
}

View File

@@ -98,11 +98,11 @@ function normalizeLoggerConfigInput(config: LoggerConfigInput): PersistedConfig
}
if ("log" in config) {
return config as PersistedConfig;
return config;
}
if ("level" in config || "format" in config) {
const legacy = config as LegacyLogConfig;
const legacy = config;
return {
log: {
...(legacy.level ? { level: legacy.level } : {}),

View File

@@ -376,15 +376,15 @@ describe("LoopService", () => {
expect(finalLoop.archive).toBe(true);
expect(iteration?.workerAgentId).toBeTruthy();
expect(iteration?.verifierAgentId).toBeTruthy();
expect(archivedAgentIds).toEqual([iteration!.workerAgentId!, iteration!.verifierAgentId!]);
expect(archivedAgentIds).toEqual([iteration.workerAgentId!, iteration.verifierAgentId!]);
await storage.flush();
await expect(storage.get(iteration!.workerAgentId!)).resolves.toMatchObject({
id: iteration!.workerAgentId!,
await expect(storage.get(iteration.workerAgentId!)).resolves.toMatchObject({
id: iteration.workerAgentId!,
archivedAt: expect.any(String),
internal: true,
});
await expect(storage.get(iteration!.verifierAgentId!)).resolves.toMatchObject({
id: iteration!.verifierAgentId!,
await expect(storage.get(iteration.verifierAgentId!)).resolves.toMatchObject({
id: iteration.verifierAgentId!,
archivedAt: expect.any(String),
internal: true,
});

View File

@@ -870,7 +870,7 @@ export class LoopService {
record.id.startsWith(trimmed),
);
if (matches.length === 1) {
return matches[0]!;
return matches[0];
}
if (matches.length > 1) {
throw new Error(`Loop id prefix is ambiguous: ${trimmed}`);

View File

@@ -19,7 +19,7 @@ type ExternalProcessEnv = NodeJS.ProcessEnv & Record<string, string>;
let resolvedProcessExecPath: string | undefined;
function buildInternalProcessEnv<T extends ProcessEnvRecord>(baseEnv: T): T {
return { ...baseEnv } as T;
return { ...baseEnv };
}
function buildExternalProcessEnv(

View File

@@ -124,7 +124,7 @@ function hasRegisteredProvider(registeredProviders: RegisteredProviders, value:
if (isProviderRegistry(registeredProviders)) {
return Object.prototype.hasOwnProperty.call(registeredProviders, value);
}
return new Set(registeredProviders).has(value as AgentProvider);
return new Set(registeredProviders).has(value);
}
export function isRegisteredProvider(

View File

@@ -105,8 +105,8 @@ export class ScriptHealthMonitor {
probeTargets.map(({ route }) => this.probeRoute(route.port)),
);
for (let i = 0; i < probeTargets.length; i += 1) {
const { route, state } = probeTargets[i]!;
const isHealthy = healthResults[i]!;
const { route, state } = probeTargets[i];
const isHealthy = healthResults[i];
const previousHealth = state.health;
if (isHealthy) {

View File

@@ -1402,7 +1402,7 @@ export class Session {
}
private getRegisteredProviderIds(): AgentProvider[] {
return Object.keys(this.getProviderRegistry()) as AgentProvider[];
return Object.keys(this.getProviderRegistry());
}
private buildStoredAgentPayload(
@@ -2382,7 +2382,7 @@ export class Session {
);
const agents = [];
for (let i = 0; i < archiveResults.length; i += 1) {
const result = archiveResults[i]!;
const result = archiveResults[i];
if (result.status === "fulfilled") {
agents.push(result.value);
} else {
@@ -3282,9 +3282,7 @@ export class Session {
throw new Error(`Agent not found: ${agentId}`);
}
const providerRegistry = this.getProviderRegistry();
if (
!isStoredAgentProviderAvailable(record, Object.keys(providerRegistry) as AgentProvider[])
) {
if (!isStoredAgentProviderAvailable(record, Object.keys(providerRegistry))) {
throw new Error(`Agent ${agentId} references unavailable provider '${record.provider}'`);
}
const handle = toAgentPersistenceHandle(providerRegistry, record.persistence);
@@ -5831,7 +5829,7 @@ export class Session {
),
);
for (let i = 0; i < pairs.length; i += 1) {
placementsByCwd.set(normalizePersistedWorkspaceId(pairs[i]!.workspace.cwd), placements[i]!);
placementsByCwd.set(normalizePersistedWorkspaceId(pairs[i].workspace.cwd), placements[i]);
}
return placementsByCwd;
@@ -7727,7 +7725,7 @@ export class Session {
);
const combinedAudio = Buffer.concat(pendingSegments.map((segment) => segment.audio));
const combinedFormat = pendingSegments[pendingSegments.length - 1]!.format;
const combinedFormat = pendingSegments[pendingSegments.length - 1].format;
await this.processAudio(combinedAudio, combinedFormat);
}

View File

@@ -3809,7 +3809,7 @@ test("subscribed fetch_workspaces includes git enrichment in the initial snapsho
session.workspaceRegistry.list = async () => [gitWorkspace, directoryWorkspace];
session.reconcileAndEmitWorkspaceUpdates = vi.fn(async () => {});
session.describeWorkspaceRecord = vi.fn(
async (workspace: typeof gitWorkspace | typeof directoryWorkspace, project: unknown) => {
async (workspace: typeof gitWorkspace, project: unknown) => {
if (workspace.workspaceId === gitWorkspace.workspaceId) {
expect(project).toEqual(gitProject);
return baselineGitDescriptor;

View File

@@ -59,7 +59,7 @@ export function parsePcmRateFromFormat(
if (!match) {
return fallback;
}
const rate = Number.parseInt(match[1]!, 10);
const rate = Number.parseInt(match[1], 10);
return Number.isFinite(rate) && rate > 0 ? rate : fallback;
}
@@ -73,7 +73,7 @@ export function pcm16lePeakAbs(pcm16le: Buffer): number {
const samples = new Int16Array(pcm16le.buffer, pcm16le.byteOffset, pcm16le.byteLength / 2);
let peak = 0;
for (let i = 0; i < samples.length; i += 1) {
const v = samples[i]!;
const v = samples[i];
const abs = v < 0 ? -v : v;
if (abs > peak) {
peak = abs;
@@ -92,7 +92,7 @@ export function pcm16leToFloat32(pcm16le: Buffer, gain: number = 1): Float32Arra
const int16 = new Int16Array(pcm16le.buffer, pcm16le.byteOffset, pcm16le.byteLength / 2);
const out = new Float32Array(int16.length);
for (let i = 0; i < int16.length; i += 1) {
const v = (int16[i]! / 32768.0) * gain;
const v = (int16[i] / 32768.0) * gain;
out[i] = Math.max(-1, Math.min(1, v));
}
return out;
@@ -101,7 +101,7 @@ export function pcm16leToFloat32(pcm16le: Buffer, gain: number = 1): Float32Arra
export function float32ToPcm16le(samples: Float32Array): Buffer {
const out = new Int16Array(samples.length);
for (let i = 0; i < samples.length; i += 1) {
const clamped = Math.max(-1, Math.min(1, samples[i]!));
const clamped = Math.max(-1, Math.min(1, samples[i]));
out[i] = Math.round(clamped * 32767);
}
return Buffer.from(out.buffer, out.byteOffset, out.byteLength);

View File

@@ -78,7 +78,7 @@ function getSessionInputMeta(
function toBigInt64(values: number[]): BigInt64Array {
const out = new BigInt64Array(values.length);
for (let i = 0; i < values.length; i += 1) {
out[i] = BigInt(values[i]!);
out[i] = BigInt(values[i]);
}
return out;
}
@@ -101,8 +101,8 @@ function normalizeTextForPocket(text: string): string {
if (out.length > 0 && /[A-Za-z0-9]$/.test(out)) {
out = `${out}.`;
}
if (out.length > 0 && /[a-z]/.test(out[0]!)) {
out = out[0]!.toUpperCase() + out.slice(1);
if (out.length > 0 && /[a-z]/.test(out[0])) {
out = out[0].toUpperCase() + out.slice(1);
}
return out;
}
@@ -452,8 +452,8 @@ class PocketTtsOnnxEngine {
const outputNames = (this.flowLmMain as unknown as { outputNames?: string[] }).outputNames;
const resStepRecord = resStep as unknown as Record<string, OrtTensor>;
const conditioningName = outputNames?.[0] ?? Object.keys(resStepRecord)[0]!;
const eosName = outputNames?.[1] ?? Object.keys(resStepRecord)[1]!;
const conditioningName = outputNames?.[0] ?? Object.keys(resStepRecord)[0];
const eosName = outputNames?.[1] ?? Object.keys(resStepRecord)[1];
const conditioning = resStepRecord[conditioningName];
const eos = resStepRecord[eosName];
@@ -463,7 +463,7 @@ class PocketTtsOnnxEngine {
updateStateFromOutputs(state, resStepRecord);
const eosData = tensorDataFloat32(eos);
if (eosData[0]! > -4.0 && eosStep === null) {
if (eosData[0] > -4.0 && eosStep === null) {
eosStep = step;
}
if (eosStep !== null && step >= eosStep + this.framesAfterEos) {
@@ -495,7 +495,7 @@ class PocketTtsOnnxEngine {
if (!flowTensor) throw new Error("PocketTTS flow_lm_flow: missing output");
const delta = tensorDataFloat32(flowTensor);
for (let i = 0; i < x.length; i += 1) {
x[i] = x[i]! + delta[i]! * dt;
x[i] = x[i] + delta[i] * dt;
}
}
@@ -512,7 +512,7 @@ class PocketTtsOnnxEngine {
const frameCount = frames.length;
const flattened = new Float32Array(frameCount * 32);
for (let i = 0; i < frameCount; i += 1) {
flattened.set(frames[i]!, i * 32);
flattened.set(frames[i], i * 32);
}
const latent = new ort.Tensor("float32", flattened, [1, frameCount, 32]);

View File

@@ -187,7 +187,7 @@ function createAliasedModelIdSchema<T extends string>(params: {
message: "Invalid model id",
},
)
.transform((value) => params.aliases[value] ?? (value as T));
.transform((value) => params.aliases[value] ?? value);
}
const STT_MODEL_ALIASES = buildAliasMap(LOCAL_STT_MODEL_IDS);

View File

@@ -218,7 +218,7 @@ export async function ensureSherpaOnnxModels(options: {
),
);
for (let i = 0; i < uniq.length; i += 1) {
out[uniq[i]!] = paths[i]!;
out[uniq[i]] = paths[i]!;
}
return out as Record<SherpaOnnxModelId, string>;
}

View File

@@ -79,12 +79,12 @@ describe("SherpaOnnxParakeetSTT session", () => {
expect(transcripts).toHaveLength(2);
expect(transcripts).toEqual([
expect.objectContaining({
segmentId: committed[0]!.segmentId,
segmentId: committed[0].segmentId,
transcript: "first",
isFinal: true,
}),
expect.objectContaining({
segmentId: committed[1]!.segmentId,
segmentId: committed[1].segmentId,
transcript: "second",
isFinal: true,
}),

View File

@@ -119,7 +119,7 @@ export class SherpaOnnxTTS implements TextToSpeechProvider {
if (audio && audio.samples instanceof Float32Array) {
rawSamples = audio.samples;
} else if (audio && Array.isArray(audio.samples)) {
rawSamples = Float32Array.from(audio.samples as number[]);
rawSamples = Float32Array.from(audio.samples);
}
// Copy to avoid "External buffers are not allowed" when sherpa-onnx
// returns a Float32Array backed by native memory.

View File

@@ -92,7 +92,7 @@ export async function findLargestDebugWavFixture(): Promise<string> {
}
const stats = await Promise.all(wavPaths.map((full) => fs.stat(full)));
for (let i = 0; i < wavPaths.length; i += 1) {
files.push({ filePath: wavPaths[i]!, size: stats[i]!.size });
files.push({ filePath: wavPaths[i], size: stats[i].size });
}
currentLevel = nextLevel;
}
@@ -101,7 +101,7 @@ export async function findLargestDebugWavFixture(): Promise<string> {
throw new Error(`No .wav files found under ${base}`);
}
files.sort((a, b) => b.size - a.size);
return files[0]!.filePath;
return files[0].filePath;
}
export function normalizeTranscript(text: string): string {
@@ -130,7 +130,7 @@ function levenshteinDistanceWords(a: string[], b: string[]): number {
}
for (let j = 0; j <= n; j += 1) prev[j] = cur[j]!;
}
return prev[n]!;
return prev[n];
}
export function wordSimilarity(aText: string, bText: string): number {

View File

@@ -386,7 +386,7 @@ describe("relay external socket reconnect behavior", () => {
clientId,
});
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
socket1.emit("close", 1006, "");
await vi.advanceTimersByTimeAsync(1_000);
@@ -425,7 +425,7 @@ describe("relay external socket reconnect behavior", () => {
await Promise.resolve();
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
expect(session.args.clientCapabilities).toEqual({
[CLIENT_CAPS.reasoningMergeEnum]: true,
});
@@ -542,7 +542,7 @@ describe("relay external socket reconnect behavior", () => {
clientId,
});
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
socket1.emit("close", 1006, "");
await vi.advanceTimersByTimeAsync(1_000);
@@ -573,7 +573,7 @@ describe("relay external socket reconnect behavior", () => {
clientId,
});
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
const relaySocket = new MockSocket();
await attachRelayAndHello({
@@ -617,7 +617,7 @@ describe("relay external socket reconnect behavior", () => {
clientId,
});
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
socket1.emit("close", 1006, "");
await vi.advanceTimersByTimeAsync(90_000);
@@ -721,7 +721,7 @@ describe("relay external socket reconnect behavior", () => {
clientId: "cid-binary-inbound",
});
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
socket.emit(
"message",
@@ -758,7 +758,7 @@ describe("relay external socket reconnect behavior", () => {
clientId: "cid-binary-outbound",
});
expect(sessionMock.instances).toHaveLength(1);
const session = sessionMock.instances[0]!;
const session = sessionMock.instances[0];
const onBinaryMessage = session.args.onBinaryMessage as
| ((frame: Uint8Array) => void)

View File

@@ -248,7 +248,7 @@ function bufferFromWsData(data: Buffer | ArrayBuffer | Buffer[] | string): Buffe
);
}
if (Buffer.isBuffer(data)) return data;
return Buffer.from(data as ArrayBuffer);
return Buffer.from(data);
}
interface WebSocketLike {
@@ -1653,9 +1653,9 @@ export class VoiceAssistantWebSocketServer {
if (latencies.length === 0) continue;
latencies.sort((a, b) => a - b);
const count = latencies.length;
const minMs = Math.round(latencies[0]!);
const maxMs = Math.round(latencies[count - 1]!);
const p50Ms = Math.round(latencies[Math.floor(count / 2)]!);
const minMs = Math.round(latencies[0]);
const maxMs = Math.round(latencies[count - 1]);
const p50Ms = Math.round(latencies[Math.floor(count / 2)]);
const totalMs = Math.round(latencies.reduce((sum, v) => sum + v, 0));
stats.push({ type, count, minMs, maxMs, p50Ms, totalMs });
}

View File

@@ -176,9 +176,9 @@ export class WorkspaceDirectory {
),
);
for (let i = 0; i < includedWorkspaces.length; i += 1) {
const workspaceId = includedWorkspaces[i]!.workspaceId;
const workspaceId = includedWorkspaces[i].workspaceId;
descriptorsByWorkspaceId.set(workspaceId, {
...workspaceDescriptors[i]!,
...workspaceDescriptors[i],
archivingAt: this.archivingByWorkspaceId.get(workspaceId) ?? null,
});
}

View File

@@ -1,7 +1,7 @@
import { readdir, readFile, writeFile, mkdir, unlink } from "node:fs/promises";
import { join } from "node:path";
import { randomBytes } from "node:crypto";
import type { Task, TaskStore, CreateTaskOptions, TaskStatus, AgentType } from "./types.js";
import type { Task, TaskStore, CreateTaskOptions, TaskStatus } from "./types.js";
function generateId(): string {
return randomBytes(4).toString("hex");
@@ -128,7 +128,7 @@ function parseTask(content: string): Task {
}
taskBody = taskBody.trim();
const assignee = getValue("assignee") as AgentType | "";
const assignee = getValue("assignee");
const parentId = getValue("parentId");
const priorityStr = getValue("priority");
const priority = priorityStr ? parseInt(priorityStr, 10) : undefined;

View File

@@ -58,7 +58,7 @@ export class TerminalOutputCoalescer {
}
const payload =
this.chunks.length === 1 ? this.chunks[0]! : Buffer.concat(this.chunks, this.bytes);
this.chunks.length === 1 ? this.chunks[0] : Buffer.concat(this.chunks, this.bytes);
const bytes = this.bytes;
const chars = this.chars;
this.clearPending();

View File

@@ -1,4 +1,4 @@
import { fork, type ChildProcess } from "node:child_process";
import { fork } from "node:child_process";
import { fileURLToPath } from "node:url";
import { randomUUID } from "node:crypto";
import type { TerminalState } from "../shared/messages.js";
@@ -109,7 +109,7 @@ function forkTerminalWorker(): TerminalWorkerProcess {
execArgv: resolveWorkerExecArgv(),
serialization: "advanced",
stdio: ["ignore", "ignore", "inherit", "ipc"],
}) as ChildProcess as TerminalWorkerProcess;
}) as TerminalWorkerProcess;
}
export function createWorkerTerminalManager(

View File

@@ -1478,11 +1478,11 @@ function parseCheckoutShortstat(text: string): CheckoutShortstat | null {
let deletions = 0;
const addMatch = trimmed.match(/(\d+)\s+insertion/);
if (addMatch) {
additions = Number.parseInt(addMatch[1]!, 10);
additions = Number.parseInt(addMatch[1], 10);
}
const delMatch = trimmed.match(/(\d+)\s+deletion/);
if (delMatch) {
deletions = Number.parseInt(delMatch[1]!, 10);
deletions = Number.parseInt(delMatch[1], 10);
}
if (additions === 0 && deletions === 0) {

View File

@@ -889,7 +889,7 @@ function pruneDirectoryListCache(): void {
}
while (directoryListCache.size > DIRECTORY_LIST_CACHE_MAX_ENTRIES) {
const oldestKey = directoryListCache.keys().next().value as string | undefined;
const oldestKey = directoryListCache.keys().next().value;
if (!oldestKey) {
return;
}
@@ -910,7 +910,7 @@ function pruneWorkspaceEntryListCache(): void {
}
while (workspaceEntryListCache.size > DIRECTORY_LIST_CACHE_MAX_ENTRIES) {
const oldestKey = workspaceEntryListCache.keys().next().value as string | undefined;
const oldestKey = workspaceEntryListCache.keys().next().value;
if (!oldestKey) {
return;
}

View File

@@ -901,7 +901,7 @@ export async function isPaseoOwnedWorktreeCwd(
};
}
const worktreesRoot = join(paseoHome, "worktrees", parts[0]!);
const worktreesRoot = join(paseoHome, "worktrees", parts[0]);
return {
allowed: true,
...(repoRoot !== undefined ? { repoRoot } : {}),