Disallow redundant typecasts. (#15030)

This commit is contained in:
Christian Gunderman
2025-12-12 17:43:43 -08:00
committed by GitHub
parent fcc3b2b5ec
commit 942bcfc61e
86 changed files with 235 additions and 371 deletions
@@ -14,7 +14,7 @@ import {
type Mock,
} from 'vitest';
import { format } from 'node:util';
import { type CommandModule, type Argv } from 'yargs';
import { type Argv } from 'yargs';
import { handleDisable, disableCommand } from './disable.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import {
@@ -148,7 +148,7 @@ describe('extensions disable command', () => {
});
describe('disableCommand', () => {
const command = disableCommand as CommandModule;
const command = disableCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('disable [--scope] <name>');
@@ -65,7 +65,7 @@ export const disableCommand: CommandModule = {
argv.scope &&
!Object.values(SettingScope)
.map((s) => s.toLowerCase())
.includes((argv.scope as string).toLowerCase())
.includes(argv.scope.toLowerCase())
) {
throw new Error(
`Invalid scope: ${argv.scope}. Please use one of ${Object.values(
@@ -14,7 +14,7 @@ import {
type Mock,
} from 'vitest';
import { format } from 'node:util';
import { type CommandModule, type Argv } from 'yargs';
import { type Argv } from 'yargs';
import { handleEnable, enableCommand } from './enable.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import {
@@ -137,7 +137,7 @@ describe('extensions enable command', () => {
});
describe('enableCommand', () => {
const command = enableCommand as CommandModule;
const command = enableCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('enable [--scope] <name>');
@@ -70,7 +70,7 @@ export const enableCommand: CommandModule = {
argv.scope &&
!Object.values(SettingScope)
.map((s) => s.toLowerCase())
.includes((argv.scope as string).toLowerCase())
.includes(argv.scope.toLowerCase())
) {
throw new Error(
`Invalid scope: ${argv.scope}. Please use one of ${Object.values(
@@ -4,15 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import {
describe,
it,
expect,
vi,
beforeEach,
afterEach,
type Mock,
} from 'vitest';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
@@ -90,7 +82,7 @@ describe('MCP Server Example', () => {
json: vi.fn().mockResolvedValue(mockPosts),
});
const toolFn = (mockRegisterTool as Mock).mock.calls[0][2];
const toolFn = mockRegisterTool.mock.calls[0][2];
const result = await toolFn();
expect(global.fetch).toHaveBeenCalledWith(
@@ -109,7 +101,7 @@ describe('MCP Server Example', () => {
describe('poem-writer prompt implementation', () => {
it('should generate a prompt with a title', () => {
const promptFn = (mockRegisterPrompt as Mock).mock.calls[0][2];
const promptFn = mockRegisterPrompt.mock.calls[0][2];
const result = promptFn({ title: 'My Poem' });
expect(result).toEqual({
messages: [
@@ -125,7 +117,7 @@ describe('MCP Server Example', () => {
});
it('should generate a prompt with a title and mood', () => {
const promptFn = (mockRegisterPrompt as Mock).mock.calls[0][2];
const promptFn = mockRegisterPrompt.mock.calls[0][2];
const result = promptFn({ title: 'My Poem', mood: 'sad' });
expect(result).toEqual({
messages: [
@@ -14,7 +14,7 @@ import {
type Mock,
} from 'vitest';
import { format } from 'node:util';
import { type CommandModule, type Argv } from 'yargs';
import { type Argv } from 'yargs';
import { handleLink, linkCommand } from './link.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';
@@ -126,7 +126,7 @@ describe('extensions link command', () => {
});
describe('linkCommand', () => {
const command = linkCommand as CommandModule;
const command = linkCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('link <path>');
@@ -6,7 +6,6 @@
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
import { format } from 'node:util';
import { type CommandModule } from 'yargs';
import { handleList, listCommand } from './list.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';
@@ -124,7 +123,7 @@ describe('extensions list command', () => {
});
describe('listCommand', () => {
const command = listCommand as CommandModule;
const command = listCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('list');
@@ -14,7 +14,7 @@ import {
type Mock,
} from 'vitest';
import { format } from 'node:util';
import { type CommandModule, type Argv } from 'yargs';
import { type Argv } from 'yargs';
import { handleUninstall, uninstallCommand } from './uninstall.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';
@@ -233,7 +233,7 @@ describe('extensions uninstall command', () => {
});
describe('uninstallCommand', () => {
const command = uninstallCommand as CommandModule;
const command = uninstallCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('uninstall <names..>');
@@ -62,7 +62,7 @@ export const uninstallCommand: CommandModule = {
array: true,
})
.check((argv) => {
if (!argv.names || (argv.names as string[]).length === 0) {
if (!argv.names || argv.names.length === 0) {
throw new Error(
'Please include at least one extension name to uninstall as a positional argument.',
);
@@ -14,7 +14,7 @@ import {
type Mock,
} from 'vitest';
import { format } from 'node:util';
import { type CommandModule, type Argv } from 'yargs';
import { type Argv } from 'yargs';
import { handleUpdate, updateCommand } from './update.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';
@@ -155,7 +155,7 @@ describe('extensions update command', () => {
});
describe('updateCommand', () => {
const command = updateCommand as CommandModule;
const command = updateCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('update [<name>] [--all]');
+1 -1
View File
@@ -60,7 +60,7 @@ vi.mock('fs', async (importOriginal) => {
if (mockPaths.has(p.toString())) {
return { isDirectory: () => true } as unknown as import('fs').Stats;
}
return (actualFs as typeof import('fs')).statSync(p as unknown as string);
return actualFs.statSync(p as unknown as string);
}),
realpathSync: vi.fn((p) => p),
};
+2 -2
View File
@@ -123,7 +123,7 @@ export class ExtensionManager extends ExtensionLoader {
'Extensions not yet loaded, must call `loadExtensions` first',
);
}
return this.loadedExtensions!;
return this.loadedExtensions;
}
async installOrUpdateExtension(
@@ -319,7 +319,7 @@ export class ExtensionManager extends ExtensionLoader {
// TODO: Gracefully handle this call failing, we should back up the old
// extension prior to overwriting it and then restore and restart it.
extension = await this.loadExtension(destinationPath)!;
extension = await this.loadExtension(destinationPath);
if (!extension) {
throw new Error(`Extension not found`);
}
@@ -31,7 +31,7 @@ export async function fetchJson<T>(
if (!res.headers.location) {
return reject(new Error('No location header in redirect response'));
}
fetchJson<T>(res.headers.location!, redirectCount++)
fetchJson<T>(res.headers.location, redirectCount++)
.then(resolve)
.catch(reject);
return;
@@ -18,7 +18,7 @@ function buildZodSchemaFromJsonSchema(def: any): z.ZodTypeAny {
if (def.anyOf) {
return z.union(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
def.anyOf.map((d: any) => buildZodSchemaFromJsonSchema(d)) as any,
def.anyOf.map((d: any) => buildZodSchemaFromJsonSchema(d)),
);
}
+15 -19
View File
@@ -2231,7 +2231,7 @@ describe('Settings Loading and Merging', () => {
beforeEach(() => {
vi.resetAllMocks();
mockFsExistsSync = vi.mocked(fs.existsSync);
(mockFsExistsSync as Mock).mockReturnValue(true);
mockFsExistsSync.mockReturnValue(true);
mockFsReadFileSync = vi.mocked(fs.readFileSync);
mockFsReadFileSync.mockReturnValue('{}');
vi.mocked(isWorkspaceTrusted).mockReturnValue({
@@ -2256,15 +2256,13 @@ describe('Settings Loading and Merging', () => {
},
};
(mockFsReadFileSync as Mock).mockImplementation(
(p: fs.PathOrFileDescriptor) => {
if (p === USER_SETTINGS_PATH)
return JSON.stringify(userSettingsContent);
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
return JSON.stringify(workspaceSettingsContent);
return '{}';
},
);
mockFsReadFileSync.mockImplementation((p: fs.PathOrFileDescriptor) => {
if (p === USER_SETTINGS_PATH)
return JSON.stringify(userSettingsContent);
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
return JSON.stringify(workspaceSettingsContent);
return '{}';
});
const loadedSettings = loadSettings(MOCK_WORKSPACE_DIR);
const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
@@ -2329,15 +2327,13 @@ describe('Settings Loading and Merging', () => {
someOtherSetting: 'value',
};
(mockFsReadFileSync as Mock).mockImplementation(
(p: fs.PathOrFileDescriptor) => {
if (p === USER_SETTINGS_PATH)
return JSON.stringify(userSettingsContent);
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
return JSON.stringify(workspaceSettingsContent);
return '{}';
},
);
mockFsReadFileSync.mockImplementation((p: fs.PathOrFileDescriptor) => {
if (p === USER_SETTINGS_PATH)
return JSON.stringify(userSettingsContent);
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
return JSON.stringify(workspaceSettingsContent);
return '{}';
});
const loadedSettings = loadSettings(MOCK_WORKSPACE_DIR);
const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
@@ -33,7 +33,7 @@ describe('SettingsSchema', () => {
];
expectedSettings.forEach((setting) => {
expect(getSettingsSchema()[setting as keyof Settings]).toBeDefined();
expect(getSettingsSchema()[setting]).toBeDefined();
});
});
@@ -66,9 +66,7 @@ describe('SettingsSchema', () => {
];
nestedSettings.forEach((setting) => {
const definition = getSettingsSchema()[
setting as keyof Settings
] as SettingDefinition;
const definition = getSettingsSchema()[setting] as SettingDefinition;
expect(definition.type).toBe('object');
expect(definition.properties).toBeDefined();
expect(typeof definition.properties).toBe('object');
@@ -142,7 +140,7 @@ describe('SettingsSchema', () => {
it('should have consistent default values for boolean settings', () => {
const checkBooleanDefaults = (schema: SettingsSchema) => {
Object.entries(schema).forEach(([, definition]) => {
const def = definition as SettingDefinition;
const def = definition;
if (def.type === 'boolean') {
// Boolean settings can have boolean or undefined defaults (for optional settings)
expect(['boolean', 'undefined']).toContain(typeof def.default);
@@ -238,7 +238,7 @@ describe('FileCommandLoader', () => {
const loader = new FileCommandLoader(mockConfig);
const commands = await loader.loadCommands(signal);
expect(commands).toHaveLength(1);
expect(commands[0]!.name).toBe('gcp:pipelines:run');
expect(commands[0].name).toBe('gcp:pipelines:run');
});
it('creates namespaces from nested directories', async () => {
@@ -326,7 +326,7 @@ describe('chatCommand', () => {
const fakeFiles = ['checkpoint-alpha.json', 'checkpoint-beta.json'];
mockFs.readdir.mockImplementation(
(async (_: string): Promise<string[]> =>
fakeFiles as string[]) as unknown as typeof fsPromises.readdir,
fakeFiles) as unknown as typeof fsPromises.readdir,
);
mockFs.stat.mockImplementation(
@@ -346,7 +346,7 @@ describe('chatCommand', () => {
const date = new Date();
mockFs.readdir.mockImplementation(
(async (_: string): Promise<string[]> =>
fakeFiles as string[]) as unknown as typeof fsPromises.readdir,
fakeFiles) as unknown as typeof fsPromises.readdir,
);
mockFs.stat.mockImplementation((async (
path: string,
@@ -406,7 +406,7 @@ describe('chatCommand', () => {
const fakeFiles = ['checkpoint-alpha.json', 'checkpoint-beta.json'];
mockFs.readdir.mockImplementation(
(async (_: string): Promise<string[]> =>
fakeFiles as string[]) as unknown as typeof fsPromises.readdir,
fakeFiles) as unknown as typeof fsPromises.readdir,
);
mockFs.stat.mockImplementation(
@@ -110,7 +110,7 @@ describe('ideCommand', () => {
status: core.IDEConnectionStatus.Connected,
});
const command = await ideCommand();
const result = await command!.subCommands!.find(
const result = await command.subCommands!.find(
(c) => c.name === 'status',
)!.action!(mockContext, '');
expect(vi.mocked(mockIdeClient.getConnectionStatus)).toHaveBeenCalled();
@@ -126,7 +126,7 @@ describe('ideCommand', () => {
status: core.IDEConnectionStatus.Connecting,
});
const command = await ideCommand();
const result = await command!.subCommands!.find(
const result = await command.subCommands!.find(
(c) => c.name === 'status',
)!.action!(mockContext, '');
expect(vi.mocked(mockIdeClient.getConnectionStatus)).toHaveBeenCalled();
@@ -141,7 +141,7 @@ describe('ideCommand', () => {
status: core.IDEConnectionStatus.Disconnected,
});
const command = await ideCommand();
const result = await command!.subCommands!.find(
const result = await command.subCommands!.find(
(c) => c.name === 'status',
)!.action!(mockContext, '');
expect(vi.mocked(mockIdeClient.getConnectionStatus)).toHaveBeenCalled();
@@ -159,7 +159,7 @@ describe('ideCommand', () => {
details,
});
const command = await ideCommand();
const result = await command!.subCommands!.find(
const result = await command.subCommands!.find(
(c) => c.name === 'status',
)!.action!(mockContext, '');
expect(vi.mocked(mockIdeClient.getConnectionStatus)).toHaveBeenCalled();
@@ -200,7 +200,7 @@ describe('ideCommand', () => {
status: core.IDEConnectionStatus.Connected,
});
const actionPromise = command!.subCommands!.find(
const actionPromise = command.subCommands!.find(
(c) => c.name === 'install',
)!.action!(mockContext, '');
await vi.runAllTimersAsync();
@@ -239,7 +239,7 @@ describe('ideCommand', () => {
});
const command = await ideCommand();
await command!.subCommands!.find((c) => c.name === 'install')!.action!(
await command.subCommands!.find((c) => c.name === 'install')!.action!(
mockContext,
'',
);
+6 -15
View File
@@ -10,11 +10,7 @@ import type {
CommandContext,
} from './types.js';
import { CommandKind } from './types.js';
import type {
DiscoveredMCPPrompt,
DiscoveredMCPResource,
MessageActionReturn,
} from '@google/gemini-cli-core';
import type { MessageActionReturn } from '@google/gemini-cli-core';
import {
DiscoveredMCPTool,
getMCPDiscoveryState,
@@ -218,25 +214,20 @@ const listAction = async (
connectingServers.length > 0;
const allTools = toolRegistry.getAllTools();
const mcpTools = allTools.filter(
(tool) => tool instanceof DiscoveredMCPTool,
) as DiscoveredMCPTool[];
const mcpTools = allTools.filter((tool) => tool instanceof DiscoveredMCPTool);
const promptRegistry = await config.getPromptRegistry();
const mcpPrompts = promptRegistry
.getAllPrompts()
.filter(
(prompt) =>
'serverName' in prompt &&
serverNames.includes(prompt.serverName as string),
) as DiscoveredMCPPrompt[];
'serverName' in prompt && serverNames.includes(prompt.serverName),
);
const resourceRegistry = config.getResourceRegistry();
const mcpResources = resourceRegistry
.getAllResources()
.filter((entry) =>
serverNames.includes(entry.serverName),
) as DiscoveredMCPResource[];
.filter((entry) => serverNames.includes(entry.serverName));
const authStatus: HistoryItemMcpStatus['authStatus'] = {};
const tokenStorage = new MCPOAuthTokenStorage();
@@ -269,7 +260,7 @@ const listAction = async (
schema: tool.schema,
})),
prompts: mcpPrompts.map((prompt) => ({
serverName: prompt.serverName as string,
serverName: prompt.serverName,
name: prompt.name,
description: prompt.description,
})),
@@ -22,7 +22,6 @@ import {
CommandKind,
} from './types.js';
import type { HistoryItem } from '../types.js';
import type { Content } from '@google/genai';
const HistoryItemSchema = z
.object({
@@ -117,9 +116,7 @@ async function restoreAction(
} else if (action.type === 'load_history' && loadHistory) {
loadHistory(action.history);
if (action.clientHistory) {
await config
?.getGeminiClient()
?.setHistory(action.clientHistory as Content[]);
await config?.getGeminiClient()?.setHistory(action.clientHistory);
}
}
}
@@ -17,7 +17,7 @@ vi.mock('./HistoryItemDisplay.js', async () => {
const { Text } = await vi.importActual('ink');
return {
HistoryItemDisplay: ({ item }: { item: { content: string } }) =>
React.createElement(Text as unknown as React.FC, null, item.content),
React.createElement(Text as React.FC, null, item.content),
};
});
@@ -326,7 +326,7 @@ describe('SettingsDialog', () => {
// Navigate down
act(() => {
stdin.write(down as string);
stdin.write(down);
});
await waitFor(() => {
@@ -335,7 +335,7 @@ describe('SettingsDialog', () => {
// Navigate up
act(() => {
stdin.write(up as string);
stdin.write(up);
});
await waitFor(() => {
@@ -144,7 +144,7 @@ export const ToolStatsDisplay: React.FC = () => {
{/* Tool Rows */}
{activeTools.map(([name, stats]) => (
<StatRow key={name} name={name} stats={stats as ToolCallStats} />
<StatRow key={name} name={name} stats={stats} />
))}
<Box height={1} />
@@ -119,7 +119,7 @@ export const TodoTray: React.FC = () => {
) {
continue;
}
return tool.resultDisplay as TodoList;
return tool.resultDisplay;
}
}
return null;
@@ -11,8 +11,6 @@ import { DiffRenderer } from './DiffRenderer.js';
import { RenderInline } from '../../utils/InlineMarkdownRenderer.js';
import type {
ToolCallConfirmationDetails,
ToolExecuteConfirmationDetails,
ToolMcpConfirmationDetails,
Config,
} from '@google/gemini-cli-core';
import { IdeClient, ToolConfirmationOutcome } from '@google/gemini-cli-core';
@@ -135,8 +133,7 @@ export const ToolConfirmationMessage: React.FC<
});
}
} else if (confirmationDetails.type === 'exec') {
const executionProps =
confirmationDetails as ToolExecuteConfirmationDetails;
const executionProps = confirmationDetails;
question = `Allow execution of: '${executionProps.rootCommand}'?`;
options.push({
@@ -187,7 +184,7 @@ export const ToolConfirmationMessage: React.FC<
});
} else {
// mcp tool confirmation
const mcpProps = confirmationDetails as ToolMcpConfirmationDetails;
const mcpProps = confirmationDetails;
question = `Allow execution of MCP tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"?`;
options.push({
label: 'Yes, allow once',
@@ -258,8 +255,7 @@ export const ToolConfirmationMessage: React.FC<
);
}
} else if (confirmationDetails.type === 'exec') {
const executionProps =
confirmationDetails as ToolExecuteConfirmationDetails;
const executionProps = confirmationDetails;
let bodyContentHeight = availableBodyContentHeight();
if (bodyContentHeight !== undefined) {
bodyContentHeight -= 2; // Account for padding;
@@ -312,7 +308,7 @@ export const ToolConfirmationMessage: React.FC<
);
} else {
// mcp tool confirmation
const mcpProps = confirmationDetails as ToolMcpConfirmationDetails;
const mcpProps = confirmationDetails;
bodyContent = (
<Box flexDirection="column">
@@ -59,7 +59,7 @@ function findLastIndex<T>(
predicate: (value: T, index: number, obj: T[]) => unknown,
): number {
for (let i = array.length - 1; i >= 0; i--) {
if (predicate(array[i]!, i, array)) {
if (predicate(array[i], i, array)) {
return i;
}
}
@@ -192,7 +192,7 @@ function VirtualizedList<T>(
return { index: 0, offset: 0 };
}
return { index, offset: scrollTop - offsets[index]! };
return { index, offset: scrollTop - offsets[index] };
},
[],
);
@@ -433,7 +433,7 @@ export async function handleAtCommand({
const processedQueryParts: PartListUnion = [{ text: initialQueryText }];
const resourcePromises = resourceAttachments.map(async (resource) => {
const uri = resource.uri!;
const uri = resource.uri;
const client = mcpClientManager?.getClient(resource.serverName);
try {
if (!client) {
@@ -26,9 +26,7 @@ import { MessageType } from '../types.js';
vi.mock('./useKeypress.js');
vi.mock('@google/gemini-cli-core', async () => {
const actualServerModule = (await vi.importActual(
'@google/gemini-cli-core',
)) as Record<string, unknown>;
const actualServerModule = await vi.importActual('@google/gemini-cli-core');
return {
...actualServerModule,
Config: vi.fn(),
@@ -24,7 +24,6 @@ import { useReactToolScheduler } from './useReactToolScheduler.js';
import type {
Config,
EditorType,
GeminiClient,
AnyToolInvocation,
} from '@google/gemini-cli-core';
import {
@@ -809,8 +808,8 @@ describe('useGeminiStream', () => {
expect(client.addHistory).toHaveBeenCalledWith({
role: 'user',
parts: [
...(cancelledToolCall1.response.responseParts as Part[]),
...(cancelledToolCall2.response.responseParts as Part[]),
...cancelledToolCall1.response.responseParts,
...cancelledToolCall2.response.responseParts,
],
});
@@ -2074,7 +2073,7 @@ describe('useGeminiStream', () => {
const { result } = renderHook(() =>
useGeminiStream(
mockConfig.getGeminiClient() as GeminiClient,
mockConfig.getGeminiClient(),
[],
mockAddItem,
mockConfig,
+1 -4
View File
@@ -833,10 +833,7 @@ export const useGeminiStream = (
);
break;
case ServerGeminiEventType.Finished:
handleFinishedEvent(
event as ServerGeminiFinishedEvent,
userMessageTimestamp,
);
handleFinishedEvent(event, userMessageTimestamp);
break;
case ServerGeminiEventType.Citation:
handleCitationEvent(event.value, userMessageTimestamp);
@@ -183,7 +183,7 @@ describe('useIncludeDirsTrust', () => {
).props;
expect(dialogProps.folders).toEqual(['/undefined']);
expect(dialogProps.trustedDirs).toEqual(['/trusted']);
expect(dialogProps.errors as string[]).toEqual([
expect(dialogProps.errors).toEqual([
`The following directories are explicitly untrusted and cannot be added to a trusted workspace:\n- /untrusted\nPlease use the permissions command to modify their trust level.`,
]);
});
@@ -99,7 +99,7 @@ export function useReactToolScheduler(
setToolCallsForDisplay((prevCalls) =>
prevCalls.map((tc) => {
if (tc.request.callId === toolCallId && tc.status === 'executing') {
const executingTc = tc as TrackedExecutingToolCall;
const executingTc = tc;
return { ...executingTc, liveOutput: outputChunk };
}
return tc;
@@ -137,7 +137,7 @@ export function useReactToolScheduler(
...coreTc,
responseSubmittedToGemini,
liveOutput,
pid: (coreTc as ExecutingToolCall).pid,
pid: coreTc.pid,
};
} else {
return {
@@ -312,10 +312,9 @@ export function mapToDisplay(
return {
...baseDisplayProperties,
status: mapCoreStatusToDisplayStatus(trackedCall.status),
resultDisplay:
(trackedCall as TrackedExecutingToolCall).liveOutput ?? undefined,
resultDisplay: trackedCall.liveOutput ?? undefined,
confirmationDetails: undefined,
ptyId: (trackedCall as TrackedExecutingToolCall).pid,
ptyId: trackedCall.pid,
};
case 'validating': // Fallthrough
case 'scheduled':
@@ -106,7 +106,7 @@ const computeInitialIndex = (
if (initialKey !== undefined) {
for (let i = 0; i < items.length; i++) {
if (items[i]!.key === initialKey && !items[i]!.disabled) {
if (items[i].key === initialKey && !items[i].disabled) {
return i;
}
}
@@ -212,7 +212,7 @@ function areBaseItemsEqual(
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i]!.key !== b[i]!.key || a[i]!.disabled !== b[i]!.disabled) {
if (a[i].key !== b[i].key || a[i].disabled !== b[i].disabled) {
return false;
}
}
@@ -283,7 +283,7 @@ export function useSelectionList<T>({
let needsClear = false;
if (state.pendingHighlight && items[state.activeIndex]) {
onHighlight?.(items[state.activeIndex]!.value);
onHighlight?.(items[state.activeIndex].value);
needsClear = true;
}
@@ -231,7 +231,7 @@ describe('commandUtils', () => {
const expected = `${ESC}]52;c;${b64}${BEL}`;
expect(tty.write).toHaveBeenCalledTimes(1);
expect((tty.write as Mock).mock.calls[0][0]).toBe(expected);
expect(tty.write.mock.calls[0][0]).toBe(expected);
expect(tty.end).toHaveBeenCalledTimes(1); // /dev/tty closed after write
expect(mockClipboardyWrite).not.toHaveBeenCalled();
});
@@ -245,7 +245,7 @@ describe('commandUtils', () => {
await copyToClipboard(testText);
const written = (tty.write as Mock).mock.calls[0][0] as string;
const written = tty.write.mock.calls[0][0] as string;
// Starts with tmux DCS wrapper and ends with ST
expect(written.startsWith(`${ESC}Ptmux;`)).toBe(true);
expect(written.endsWith(ST)).toBe(true);
@@ -264,7 +264,7 @@ describe('commandUtils', () => {
await copyToClipboard(testText);
const written = (tty.write as Mock).mock.calls[0][0] as string;
const written = tty.write.mock.calls[0][0] as string;
const chunkStarts = (written.match(new RegExp(`${ESC}P`, 'g')) || [])
.length;
const chunkEnds = written.split(ST).length - 1;
@@ -240,7 +240,7 @@ describe('resolveEnvVarsInObject', () => {
// Create circular reference
arr.push(arr);
const result = resolveEnvVarsInObject(arr) as ArrayWithCircularRef;
const result = resolveEnvVarsInObject(arr);
expect(result[0]).toBe('array-value');
expect(result[1]).toBe(123);
+2 -2
View File
@@ -25,10 +25,10 @@ export function resolveEnvVarsInString(
return value.replace(envVarRegex, (match, varName1, varName2) => {
const varName = varName1 || varName2;
if (customEnv && typeof customEnv[varName] === 'string') {
return customEnv[varName]!;
return customEnv[varName];
}
if (process && process.env && typeof process.env[varName] === 'string') {
return process.env[varName]!;
return process.env[varName];
}
return match;
});
@@ -52,7 +52,7 @@ export async function validateNonInteractiveAuth(
throw new Error(message);
}
const authType: AuthType = effectiveAuthType as AuthType;
const authType: AuthType = effectiveAuthType;
if (!useExternalAuth) {
const err = validateAuthMethod(String(authType));
+11 -19
View File
@@ -121,8 +121,7 @@ describe('acp', () => {
authMethods: [],
protocolVersion: 1,
};
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
const result = await handler('initialize', initializeParams);
expect(mockAgent.initialize).toHaveBeenCalledWith(initializeParams);
@@ -132,8 +131,7 @@ describe('acp', () => {
it('should call agent.newSession when Connection handler receives session_new method', async () => {
const newSessionParams = { cwd: '/tmp', mcpServers: [] };
const newSessionResponse = { sessionId: 'session-1' };
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
const result = await handler('session/new', newSessionParams);
expect(mockAgent.newSession).toHaveBeenCalledWith(newSessionParams);
@@ -147,8 +145,7 @@ describe('acp', () => {
sessionId: 'session-1',
};
const loadSessionResponse = { sessionId: 'session-1' };
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
const result = await handler('session/load', loadSessionParams);
expect(mockAgent.loadSession).toHaveBeenCalledWith(loadSessionParams);
@@ -162,8 +159,7 @@ describe('acp', () => {
mcpServers: [],
sessionId: 'session-1',
};
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
await expect(handler('session/load', loadSessionParams)).rejects.toThrow(
RequestError.methodNotFound().message,
);
@@ -173,8 +169,7 @@ describe('acp', () => {
const authenticateParams = {
methodId: 'test-auth-method',
};
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
const result = await handler('authenticate', authenticateParams);
expect(mockAgent.authenticate).toHaveBeenCalledWith(authenticateParams);
@@ -191,8 +186,7 @@ describe('acp', () => {
traceId: 'trace-1',
};
(mockAgent.prompt as Mock).mockResolvedValue(promptResponse);
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
const result = await handler('session/prompt', promptParams);
expect(mockAgent.prompt).toHaveBeenCalledWith(promptParams);
@@ -201,8 +195,7 @@ describe('acp', () => {
it('should call agent.cancel when Connection handler receives session_cancel method', async () => {
const cancelParams = { sessionId: 'session-1' };
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
const result = await handler('session/cancel', cancelParams);
expect(mockAgent.cancel).toHaveBeenCalledWith(cancelParams);
@@ -210,8 +203,7 @@ describe('acp', () => {
});
it('should throw methodNotFound for unknown methods', async () => {
const handler = mockConnectionConstructor.mock
.calls[0][0]! as MethodHandler;
const handler = mockConnectionConstructor.mock.calls[0][0];
await expect(handler('unknown_method', {})).rejects.toThrow(
RequestError.methodNotFound().message,
);
@@ -248,7 +240,7 @@ describe('acp', () => {
const response = {
outcome: { outcome: 'selected', optionId: 'option-1' },
};
(connectionInstance.sendRequest as Mock).mockResolvedValue(response);
connectionInstance.sendRequest.mockResolvedValue(response);
const result = await agentSideConnection.requestPermission(params);
expect(connectionInstance.sendRequest).toHaveBeenCalledWith(
@@ -261,7 +253,7 @@ describe('acp', () => {
it('should send readTextFile request via connection', async () => {
const params = { path: '/a/b.txt', sessionId: 'session-1' };
const response = { content: 'file content' };
(connectionInstance.sendRequest as Mock).mockResolvedValue(response);
connectionInstance.sendRequest.mockResolvedValue(response);
const result = await agentSideConnection.readTextFile(params);
expect(connectionInstance.sendRequest).toHaveBeenCalledWith(
@@ -278,7 +270,7 @@ describe('acp', () => {
sessionId: 'session-1',
};
const response = { success: true };
(connectionInstance.sendRequest as Mock).mockResolvedValue(response);
connectionInstance.sendRequest.mockResolvedValue(response);
const result = await agentSideConnection.writeTextFile(params);
expect(connectionInstance.sendRequest).toHaveBeenCalledWith(
@@ -147,7 +147,7 @@ export class Connection {
await this.#tryCallHandler(message.method, message.params);
} else if ('id' in message) {
// It's a response
this.#handleResponse(message as AnyResponse);
this.#handleResponse(message);
}
}
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import type { WritableStream, ReadableStream } from 'node:stream/web';
import type { ReadableStream } from 'node:stream/web';
import type {
Config,
@@ -53,7 +53,7 @@ export async function runZedIntegration(
argv: CliArgs,
) {
const { stdout: workingStdout } = createWorkingStdio();
const stdout = Writable.toWeb(workingStdout) as WritableStream;
const stdout = Writable.toWeb(workingStdout);
const stdin = Readable.toWeb(process.stdin) as ReadableStream<Uint8Array>;
new acp.AgentSideConnection(
@@ -355,7 +355,7 @@ export class Session {
fc: FunctionCall,
): Promise<Part[]> {
const callId = fc.id ?? `${fc.name}-${Date.now()}`;
const args = (fc.args ?? {}) as Record<string, unknown>;
const args = fc.args ?? {};
const startTime = Date.now();
@@ -393,7 +393,7 @@ export class Session {
}
const toolRegistry = this.config.getToolRegistry();
const tool = toolRegistry.getTool(fc.name as string);
const tool = toolRegistry.getTool(fc.name);
if (!tool) {
return errorResponse(