mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-23 20:40:41 -07:00
Disallow unsafe type assertions (#18688)
This commit is contained in:
committed by
GitHub
parent
bce1caefd0
commit
fd65416a2f
@@ -73,6 +73,7 @@ export async function executeToolWithHooks(
|
||||
setPidCallback?: (pid: number) => void,
|
||||
config?: Config,
|
||||
): Promise<ToolResult> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const toolInput = (invocation.params || {}) as Record<string, unknown>;
|
||||
let inputWasModified = false;
|
||||
let modifiedKeys: string[] = [];
|
||||
|
||||
@@ -224,6 +224,7 @@ export class CoreToolScheduler {
|
||||
tool: toolInstance,
|
||||
invocation,
|
||||
status: 'success',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
response: auxiliaryData as ToolCallResponseInfo,
|
||||
durationMs,
|
||||
outcome,
|
||||
@@ -237,6 +238,7 @@ export class CoreToolScheduler {
|
||||
request: currentCall.request,
|
||||
status: 'error',
|
||||
tool: toolInstance,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
response: auxiliaryData as ToolCallResponseInfo,
|
||||
durationMs,
|
||||
outcome,
|
||||
@@ -247,6 +249,7 @@ export class CoreToolScheduler {
|
||||
request: currentCall.request,
|
||||
tool: toolInstance,
|
||||
status: 'awaiting_approval',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
confirmationDetails: auxiliaryData as ToolCallConfirmationDetails,
|
||||
startTime: existingStartTime,
|
||||
outcome,
|
||||
@@ -347,6 +350,7 @@ export class CoreToolScheduler {
|
||||
|
||||
const invocationOrError = this.buildInvocation(
|
||||
call.tool,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
args as Record<string, unknown>,
|
||||
);
|
||||
if (invocationOrError instanceof Error) {
|
||||
@@ -356,6 +360,7 @@ export class CoreToolScheduler {
|
||||
ToolErrorType.INVALID_TOOL_PARAMS,
|
||||
);
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
request: { ...call.request, args: args as Record<string, unknown> },
|
||||
status: 'error',
|
||||
tool: call.tool,
|
||||
@@ -365,6 +370,7 @@ export class CoreToolScheduler {
|
||||
|
||||
return {
|
||||
...call,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
request: { ...call.request, args: args as Record<string, unknown> },
|
||||
invocation: invocationOrError,
|
||||
};
|
||||
@@ -749,6 +755,7 @@ export class CoreToolScheduler {
|
||||
this.cancelAll(signal);
|
||||
return; // `cancelAll` calls `checkAndNotifyCompletion`, so we can exit here.
|
||||
} else if (outcome === ToolConfirmationOutcome.ModifyWithEditor) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const waitingToolCall = toolCall as WaitingToolCall;
|
||||
|
||||
const editorType = this.getPreferredEditor();
|
||||
@@ -756,6 +763,7 @@ export class CoreToolScheduler {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
this.setStatusInternal(callId, 'awaiting_approval', signal, {
|
||||
...waitingToolCall.confirmationDetails,
|
||||
isModifying: true,
|
||||
@@ -770,12 +778,14 @@ export class CoreToolScheduler {
|
||||
// Restore status (isModifying: false) and update diff if result exists
|
||||
if (result) {
|
||||
this.setArgsInternal(callId, result.updatedParams);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
this.setStatusInternal(callId, 'awaiting_approval', signal, {
|
||||
...waitingToolCall.confirmationDetails,
|
||||
fileDiff: result.updatedDiff,
|
||||
isModifying: false,
|
||||
} as ToolCallConfirmationDetails);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
this.setStatusInternal(callId, 'awaiting_approval', signal, {
|
||||
...waitingToolCall.confirmationDetails,
|
||||
isModifying: false,
|
||||
@@ -786,13 +796,16 @@ export class CoreToolScheduler {
|
||||
// re-confirmation.
|
||||
if (payload && 'newContent' in payload && toolCall) {
|
||||
const result = await this.toolModifier.applyInlineModify(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
toolCall as WaitingToolCall,
|
||||
payload,
|
||||
signal,
|
||||
);
|
||||
if (result) {
|
||||
this.setArgsInternal(callId, result.updatedParams);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
this.setStatusInternal(callId, 'awaiting_approval', signal, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
...(toolCall as WaitingToolCall).confirmationDetails,
|
||||
fileDiff: result.updatedDiff,
|
||||
} as ToolCallConfirmationDetails);
|
||||
|
||||
@@ -51,6 +51,7 @@ export class FakeContentGenerator implements ContentGenerator {
|
||||
const responses = fileContent
|
||||
.split('\n')
|
||||
.filter((line) => line.trim() !== '')
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
.map((line) => JSON.parse(line) as FakeResponse);
|
||||
return new FakeContentGenerator(responses);
|
||||
}
|
||||
@@ -71,6 +72,7 @@ export class FakeContentGenerator implements ContentGenerator {
|
||||
`Unexpected response type, next response was for ${response.method} but expected ${method}`,
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return response.response as R;
|
||||
}
|
||||
|
||||
|
||||
@@ -560,6 +560,7 @@ export class GeminiChat {
|
||||
beforeModelResult.modifiedContents &&
|
||||
Array.isArray(beforeModelResult.modifiedContents)
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
contentsToUse = beforeModelResult.modifiedContents as Content[];
|
||||
}
|
||||
|
||||
@@ -577,6 +578,7 @@ export class GeminiChat {
|
||||
toolSelectionResult.tools &&
|
||||
Array.isArray(toolSelectionResult.tools)
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
config.tools = toolSelectionResult.tools as Tool[];
|
||||
}
|
||||
}
|
||||
@@ -820,6 +822,7 @@ export class GeminiChat {
|
||||
(candidate) => candidate.finishReason,
|
||||
);
|
||||
if (candidateWithReason) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
finishReason = candidateWithReason.finishReason as FinishReason;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ export class Logger {
|
||||
await this._backupCorruptedLogFile('malformed_array');
|
||||
return [];
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return parsedLogs.filter(
|
||||
(entry) =>
|
||||
typeof entry.sessionId === 'string' &&
|
||||
@@ -105,6 +106,7 @@ export class Logger {
|
||||
typeof entry.message === 'string',
|
||||
) as LogEntry[];
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code === 'ENOENT') {
|
||||
return [];
|
||||
@@ -298,6 +300,7 @@ export class Logger {
|
||||
await fs.access(newPath);
|
||||
return newPath; // Found it, use the new path.
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code !== 'ENOENT') {
|
||||
throw error; // A real error occurred, rethrow it.
|
||||
@@ -311,6 +314,7 @@ export class Logger {
|
||||
await fs.access(oldPath);
|
||||
return oldPath; // Found it, use the old path.
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code !== 'ENOENT') {
|
||||
throw error; // A real error occurred, rethrow it.
|
||||
@@ -352,6 +356,7 @@ export class Logger {
|
||||
|
||||
// Handle legacy format (just an array of Content)
|
||||
if (Array.isArray(parsedContent)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return { history: parsedContent as Content[] };
|
||||
}
|
||||
|
||||
@@ -360,6 +365,7 @@ export class Logger {
|
||||
parsedContent !== null &&
|
||||
'history' in parsedContent
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return parsedContent as Checkpoint;
|
||||
}
|
||||
|
||||
@@ -368,6 +374,7 @@ export class Logger {
|
||||
);
|
||||
return { history: [] };
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code === 'ENOENT') {
|
||||
// This is okay, it just means the checkpoint doesn't exist in either format.
|
||||
@@ -397,6 +404,7 @@ export class Logger {
|
||||
await fs.unlink(newPath);
|
||||
deletedSomething = true;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code !== 'ENOENT') {
|
||||
debugLogger.error(
|
||||
@@ -415,6 +423,7 @@ export class Logger {
|
||||
await fs.unlink(oldPath);
|
||||
deletedSomething = true;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code !== 'ENOENT') {
|
||||
debugLogger.error(
|
||||
@@ -444,6 +453,7 @@ export class Logger {
|
||||
await fs.access(filePath);
|
||||
return true;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const nodeError = error as NodeJS.ErrnoException;
|
||||
if (nodeError.code === 'ENOENT') {
|
||||
return false; // It truly doesn't exist in either format.
|
||||
|
||||
@@ -177,7 +177,8 @@ export class LoggingContentGenerator implements ContentGenerator {
|
||||
this.config.getContentGeneratorConfig()?.authType,
|
||||
errorType,
|
||||
isStructuredError(error)
|
||||
? (error as StructuredError).status
|
||||
? // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(error as StructuredError).status
|
||||
: undefined,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -48,6 +48,7 @@ export class RecordingContentGenerator implements ContentGenerator {
|
||||
);
|
||||
const recordedResponse: FakeResponse = {
|
||||
method: 'generateContent',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
response: {
|
||||
candidates: response.candidates,
|
||||
usageMetadata: response.usageMetadata,
|
||||
@@ -73,6 +74,7 @@ export class RecordingContentGenerator implements ContentGenerator {
|
||||
|
||||
async function* stream(filePath: string) {
|
||||
for await (const response of realResponses) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(recordedResponse.response as GenerateContentResponse[]).push({
|
||||
candidates: response.candidates,
|
||||
usageMetadata: response.usageMetadata,
|
||||
|
||||
@@ -384,7 +384,8 @@ export class Turn {
|
||||
error !== null &&
|
||||
'status' in error &&
|
||||
typeof (error as { status: unknown }).status === 'number'
|
||||
? (error as { status: number }).status
|
||||
? // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(error as { status: number }).status
|
||||
: undefined;
|
||||
const structuredError: StructuredError = {
|
||||
message: getErrorMessage(error),
|
||||
|
||||
Reference in New Issue
Block a user