mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-08 04:10:35 -07:00
Disallow unsafe type assertions (#18688)
This commit is contained in:
committed by
GitHub
parent
bce1caefd0
commit
fd65416a2f
@@ -175,6 +175,7 @@ export class ActivateSkillTool extends BaseDeclarativeTool<
|
||||
} else {
|
||||
schema = z.object({
|
||||
name: z
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
.enum(skillNames as [string, ...string[]])
|
||||
.describe('The name of the skill to activate.'),
|
||||
});
|
||||
|
||||
@@ -875,6 +875,7 @@ class LenientJsonSchemaValidator implements jsonSchemaValidator {
|
||||
);
|
||||
return (input: unknown) => ({
|
||||
valid: true as const,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
data: input as T,
|
||||
errorMessage: undefined,
|
||||
});
|
||||
@@ -889,6 +890,7 @@ export function populateMcpServerCommand(
|
||||
): Record<string, MCPServerConfig> {
|
||||
if (mcpServerCommand) {
|
||||
const cmd = mcpServerCommand;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const args = parse(cmd, process.env) as string[];
|
||||
if (args.some((arg) => typeof arg !== 'string')) {
|
||||
throw new Error('failed to parse mcpServerCommand: ' + cmd);
|
||||
@@ -1068,6 +1070,7 @@ export async function discoverTools(
|
||||
'error',
|
||||
`Error discovering tool: '${
|
||||
toolDef.name
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
}' from MCP server '${mcpServerName}': ${(error as Error).message}`,
|
||||
error,
|
||||
);
|
||||
@@ -1121,6 +1124,7 @@ class McpCallableTool implements CallableTool {
|
||||
const result = await this.client.callTool(
|
||||
{
|
||||
name: call.name!,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
arguments: call.args as Record<string, unknown>,
|
||||
},
|
||||
undefined,
|
||||
@@ -1550,6 +1554,7 @@ export async function connectToMcpServer(
|
||||
return { client: mcpClient, transport };
|
||||
} catch (error) {
|
||||
await transport.close();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
firstAttemptError = error as Error;
|
||||
throw error;
|
||||
}
|
||||
@@ -1589,6 +1594,7 @@ export async function connectToMcpServer(
|
||||
);
|
||||
return { client: mcpClient, transport: sseTransport };
|
||||
} catch (sseFallbackError) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
sseError = sseFallbackError as Error;
|
||||
|
||||
// If SSE also returned 401, handle OAuth below
|
||||
@@ -1929,6 +1935,7 @@ export async function createTransport(
|
||||
let transport: Transport = new StdioClientTransport({
|
||||
command: mcpServerConfig.command,
|
||||
args: mcpServerConfig.args || [],
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
env: sanitizeEnvironment(
|
||||
{
|
||||
...process.env,
|
||||
@@ -1965,7 +1972,7 @@ export async function createTransport(
|
||||
|
||||
const underlyingTransport =
|
||||
transport instanceof XcodeMcpBridgeFixTransport
|
||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
||||
(transport as any).transport
|
||||
: transport;
|
||||
|
||||
|
||||
@@ -373,6 +373,7 @@ function transformResourceLinkBlock(block: McpResourceLinkBlock): Part {
|
||||
*/
|
||||
function transformMcpContentToParts(sdkResponse: Part[]): Part[] {
|
||||
const funcResponse = sdkResponse?.[0]?.functionResponse;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const mcpContent = funcResponse?.response?.['content'] as McpContentBlock[];
|
||||
const toolName = funcResponse?.name || 'unknown tool';
|
||||
|
||||
@@ -410,6 +411,7 @@ function transformMcpContentToParts(sdkResponse: Part[]): Part[] {
|
||||
* @returns A formatted string representing the tool's output.
|
||||
*/
|
||||
function getStringifiedResultForDisplay(rawResponse: Part[]): string {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const mcpContent = rawResponse?.[0]?.functionResponse?.response?.[
|
||||
'content'
|
||||
] as McpContentBlock[];
|
||||
|
||||
@@ -94,6 +94,7 @@ async function readMemoryFileContent(): Promise<string> {
|
||||
try {
|
||||
return await fs.readFile(getGlobalMemoryFilePath(), 'utf-8');
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const error = err as Error & { code?: string };
|
||||
if (!(error instanceof Error) || error.code !== 'ENOENT') throw err;
|
||||
return '';
|
||||
|
||||
@@ -265,7 +265,9 @@ export class ToolRegistry {
|
||||
}
|
||||
|
||||
if (priorityA === 2) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const serverA = (toolA as DiscoveredMCPTool).serverName;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const serverB = (toolB as DiscoveredMCPTool).serverName;
|
||||
return serverA.localeCompare(serverB);
|
||||
}
|
||||
@@ -319,6 +321,7 @@ export class ToolRegistry {
|
||||
'Tool discovery command is empty or contains only whitespace.',
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const proc = spawn(cmdParts[0] as string, cmdParts.slice(1) as string[]);
|
||||
let stdout = '';
|
||||
const stdoutDecoder = new StringDecoder('utf8');
|
||||
@@ -398,6 +401,7 @@ export class ToolRegistry {
|
||||
} else if (Array.isArray(tool['functionDeclarations'])) {
|
||||
functions.push(...tool['functionDeclarations']);
|
||||
} else if (tool['name']) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
functions.push(tool as FunctionDeclaration);
|
||||
}
|
||||
}
|
||||
@@ -420,6 +424,7 @@ export class ToolRegistry {
|
||||
func.name,
|
||||
DISCOVERED_TOOL_PREFIX + func.name,
|
||||
func.description ?? '',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
parameters as Record<string, unknown>,
|
||||
this.messageBus,
|
||||
),
|
||||
@@ -552,6 +557,7 @@ export class ToolRegistry {
|
||||
getToolsByServer(serverName: string): AnyDeclarativeTool[] {
|
||||
const serverTools: AnyDeclarativeTool[] = [];
|
||||
for (const tool of this.getActiveTools()) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
if ((tool as DiscoveredMCPTool)?.serverName === serverName) {
|
||||
serverTools.push(tool);
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ export abstract class BaseToolInvocation<
|
||||
correlationId,
|
||||
toolCall: {
|
||||
name: this._toolName,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
args: this.params as Record<string, unknown>,
|
||||
},
|
||||
serverName: this._serverName,
|
||||
@@ -536,6 +537,7 @@ export function isTool(obj: unknown): obj is AnyDeclarativeTool {
|
||||
obj !== null &&
|
||||
'name' in obj &&
|
||||
'build' in obj &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
typeof (obj as AnyDeclarativeTool).build === 'function'
|
||||
);
|
||||
}
|
||||
@@ -590,8 +592,10 @@ export function hasCycleInSchema(schema: object): boolean {
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
current = (current as Record<string, unknown>)[segment];
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return current as object;
|
||||
}
|
||||
|
||||
@@ -639,6 +643,7 @@ export function hasCycleInSchema(schema: object): boolean {
|
||||
if (Object.prototype.hasOwnProperty.call(node, key)) {
|
||||
if (
|
||||
traverse(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(node as Record<string, unknown>)[key],
|
||||
visitedRefs,
|
||||
pathRefs,
|
||||
|
||||
@@ -194,6 +194,7 @@ ${textContent}
|
||||
returnDisplay: `Content for ${url} processed using fallback fetch.`,
|
||||
};
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const error = e as Error;
|
||||
const errorMessage = `Error during fallback fetch for ${url}: ${error.message}`;
|
||||
return {
|
||||
@@ -291,6 +292,7 @@ ${textContent}
|
||||
const sources = groundingMetadata?.groundingChunks as
|
||||
| GroundingChunkItem[]
|
||||
| undefined;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const groundingSupports = groundingMetadata?.groundingSupports as
|
||||
| GroundingSupportItem[]
|
||||
| undefined;
|
||||
|
||||
@@ -91,6 +91,7 @@ class WebSearchToolInvocation extends BaseToolInvocation<
|
||||
const sources = groundingMetadata?.groundingChunks as
|
||||
| GroundingChunkItem[]
|
||||
| undefined;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const groundingSupports = groundingMetadata?.groundingSupports as
|
||||
| GroundingSupportItem[]
|
||||
| undefined;
|
||||
|
||||
@@ -75,7 +75,7 @@ export class XcodeMcpBridgeFixTransport
|
||||
// We can cast because we verified 'result' is in response,
|
||||
// but TS might still be picky if the type is a strict union.
|
||||
// Let's treat it safely.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
||||
const result = response.result as any;
|
||||
|
||||
// Check if we have content but missing structuredContent
|
||||
|
||||
Reference in New Issue
Block a user