mirror of
https://github.com/google-gemini/gemini-cli
synced 2026-04-21 13:37:17 +00:00
Merge 655495de79 into a38e2f0048
This commit is contained in:
commit
442d2802f7
11 changed files with 84 additions and 103 deletions
|
|
@ -877,23 +877,21 @@ export class Task {
|
|||
}
|
||||
|
||||
private async _handleToolConfirmationPart(part: Part): Promise<boolean> {
|
||||
if (
|
||||
part.kind !== 'data' ||
|
||||
!part.data ||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof part.data['callId'] !== 'string' ||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof part.data['outcome'] !== 'string'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (!part.data['outcome']) {
|
||||
if (part.kind !== 'data' || !part.data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const callId = part.data['callId'];
|
||||
const outcomeString = part.data['outcome'];
|
||||
|
||||
if (typeof callId !== 'string' || typeof outcomeString !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!outcomeString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.toolsAlreadyConfirmed.add(callId);
|
||||
|
||||
let confirmationOutcome: ToolConfirmationOutcome | undefined;
|
||||
|
|
|
|||
|
|
@ -79,9 +79,10 @@ function migrateClaudeHook(claudeHook: unknown): unknown {
|
|||
migrated['command'] = hook['command'];
|
||||
|
||||
// Replace CLAUDE_PROJECT_DIR with GEMINI_PROJECT_DIR in command
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if (typeof migrated['command'] === 'string') {
|
||||
migrated['command'] = migrated['command'].replace(
|
||||
|
||||
const command = migrated['command'];
|
||||
if (typeof command === 'string') {
|
||||
migrated['command'] = command.replace(
|
||||
/\$CLAUDE_PROJECT_DIR/g,
|
||||
'$GEMINI_PROJECT_DIR',
|
||||
);
|
||||
|
|
@ -94,9 +95,10 @@ function migrateClaudeHook(claudeHook: unknown): unknown {
|
|||
}
|
||||
|
||||
// Map timeout field (Claude uses seconds, Gemini uses seconds)
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if ('timeout' in hook && typeof hook['timeout'] === 'number') {
|
||||
migrated['timeout'] = hook['timeout'];
|
||||
|
||||
const timeout = hook['timeout'];
|
||||
if ('timeout' in hook && typeof timeout === 'number') {
|
||||
migrated['timeout'] = timeout;
|
||||
}
|
||||
|
||||
return migrated;
|
||||
|
|
@ -140,12 +142,9 @@ function migrateClaudeHooks(claudeConfig: unknown): Record<string, unknown> {
|
|||
const migratedDef: Record<string, unknown> = {};
|
||||
|
||||
// Transform matcher
|
||||
if (
|
||||
'matcher' in definition &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof definition['matcher'] === 'string'
|
||||
) {
|
||||
migratedDef['matcher'] = transformMatcher(definition['matcher']);
|
||||
const matcher = definition['matcher'];
|
||||
if ('matcher' in definition && typeof matcher === 'string') {
|
||||
migratedDef['matcher'] = transformMatcher(matcher);
|
||||
}
|
||||
|
||||
// Copy sequential flag
|
||||
|
|
|
|||
|
|
@ -157,18 +157,12 @@ async function truncateHistoryToBudget(
|
|||
if (typeof responseObj === 'string') {
|
||||
contentStr = responseObj;
|
||||
} else if (responseObj && typeof responseObj === 'object') {
|
||||
if (
|
||||
'output' in responseObj &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof responseObj['output'] === 'string'
|
||||
) {
|
||||
contentStr = responseObj['output'];
|
||||
} else if (
|
||||
'content' in responseObj &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof responseObj['content'] === 'string'
|
||||
) {
|
||||
contentStr = responseObj['content'];
|
||||
const output = responseObj['output'];
|
||||
const content = responseObj['content'];
|
||||
if (typeof output === 'string') {
|
||||
contentStr = output;
|
||||
} else if (typeof content === 'string') {
|
||||
contentStr = content;
|
||||
} else {
|
||||
contentStr = JSON.stringify(responseObj, null, 2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,12 +360,9 @@ export class HookAggregator {
|
|||
}
|
||||
|
||||
// Extract additionalContext from various hook types
|
||||
if (
|
||||
'additionalContext' in specific &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof specific['additionalContext'] === 'string'
|
||||
) {
|
||||
contexts.push(specific['additionalContext']);
|
||||
const additionalContext = specific['additionalContext'];
|
||||
if (typeof additionalContext === 'string') {
|
||||
contexts.push(additionalContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -583,16 +583,12 @@ export class LoopDetectionService {
|
|||
return { isLoop: false };
|
||||
}
|
||||
|
||||
const flashConfidenceValue = flashResult['unproductive_state_confidence'];
|
||||
const flashConfidence =
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof flashResult['unproductive_state_confidence'] === 'number'
|
||||
? flashResult['unproductive_state_confidence']
|
||||
: 0;
|
||||
typeof flashConfidenceValue === 'number' ? flashConfidenceValue : 0;
|
||||
const flashAnalysisValue = flashResult['unproductive_state_analysis'];
|
||||
const flashAnalysis =
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof flashResult['unproductive_state_analysis'] === 'string'
|
||||
? flashResult['unproductive_state_analysis']
|
||||
: '';
|
||||
typeof flashAnalysisValue === 'string' ? flashAnalysisValue : '';
|
||||
|
||||
const doubleCheckModelName =
|
||||
this.context.config.modelConfigService.getResolvedConfig({
|
||||
|
|
@ -634,17 +630,17 @@ export class LoopDetectionService {
|
|||
signal,
|
||||
);
|
||||
|
||||
const mainModelConfidenceValue =
|
||||
mainModelResult?.['unproductive_state_confidence'];
|
||||
const mainModelConfidence =
|
||||
mainModelResult &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof mainModelResult['unproductive_state_confidence'] === 'number'
|
||||
? mainModelResult['unproductive_state_confidence']
|
||||
typeof mainModelConfidenceValue === 'number'
|
||||
? mainModelConfidenceValue
|
||||
: 0;
|
||||
const mainModelAnalysisValue =
|
||||
mainModelResult?.['unproductive_state_analysis'];
|
||||
const mainModelAnalysis =
|
||||
mainModelResult &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof mainModelResult['unproductive_state_analysis'] === 'string'
|
||||
? mainModelResult['unproductive_state_analysis']
|
||||
typeof mainModelAnalysisValue === 'string'
|
||||
? mainModelAnalysisValue
|
||||
: undefined;
|
||||
|
||||
logLlmLoopCheck(
|
||||
|
|
@ -689,11 +685,8 @@ export class LoopDetectionService {
|
|||
role: LlmRole.UTILITY_LOOP_DETECTOR,
|
||||
});
|
||||
|
||||
if (
|
||||
result &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof result['unproductive_state_confidence'] === 'number'
|
||||
) {
|
||||
const confidenceValue = result?.['unproductive_state_confidence'];
|
||||
if (result && typeof confidenceValue === 'number') {
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -63,8 +63,9 @@ function getStringReferences(parts: AnyPart[]): StringReference[] {
|
|||
});
|
||||
}
|
||||
} else if (part instanceof GenericPart) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if (part.type === 'executableCode' && typeof part['code'] === 'string') {
|
||||
const codeValue = part['code'];
|
||||
const outputValue = part['output'];
|
||||
if (part.type === 'executableCode' && typeof codeValue === 'string') {
|
||||
refs.push({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
get: () => part['code'] as string,
|
||||
|
|
@ -74,8 +75,7 @@ function getStringReferences(parts: AnyPart[]): StringReference[] {
|
|||
});
|
||||
} else if (
|
||||
part.type === 'codeExecutionResult' &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof part['output'] === 'string'
|
||||
typeof outputValue === 'string'
|
||||
) {
|
||||
refs.push({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ export class MockMessageBus {
|
|||
if (!this.subscriptions.has(type)) {
|
||||
this.subscriptions.set(type, new Set());
|
||||
}
|
||||
|
||||
this.subscriptions.get(type)!.add(listener as (message: Message) => void);
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -106,13 +106,12 @@ export interface McpToolAnnotation extends Record<string, unknown> {
|
|||
export function isMcpToolAnnotation(
|
||||
annotation: unknown,
|
||||
): annotation is McpToolAnnotation {
|
||||
if (typeof annotation !== 'object' || annotation === null) {
|
||||
return false;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const record = annotation as Record<string, unknown>;
|
||||
const serverName = record['_serverName'];
|
||||
return typeof serverName === 'string';
|
||||
return (
|
||||
typeof annotation === 'object' &&
|
||||
annotation !== null &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
typeof (annotation as Record<string, unknown>)['_serverName'] === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
type ToolParams = Record<string, unknown>;
|
||||
|
|
|
|||
|
|
@ -110,13 +110,13 @@ Return ONLY the corrected string in the specified JSON format with the key 'corr
|
|||
role: LlmRole.UTILITY_EDIT_CORRECTOR,
|
||||
});
|
||||
|
||||
const correctedStringValue = result?.['corrected_string_escaping'];
|
||||
if (
|
||||
result &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof result['corrected_string_escaping'] === 'string' &&
|
||||
result['corrected_string_escaping'].length > 0
|
||||
typeof correctedStringValue === 'string' &&
|
||||
correctedStringValue.length > 0
|
||||
) {
|
||||
return result['corrected_string_escaping'];
|
||||
return correctedStringValue;
|
||||
} else {
|
||||
return potentiallyProblematicString;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,8 +231,9 @@ export function parseGoogleApiError(error: unknown): GoogleApiError | null {
|
|||
}
|
||||
// Basic structural check before casting.
|
||||
// Since the proto definitions are loose, we primarily rely on @type presence.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if (typeof detailObj['@type'] === 'string') {
|
||||
|
||||
const typeValue = detailObj['@type'];
|
||||
if (typeof typeValue === 'string') {
|
||||
// We can just cast it; the consumer will have to switch on @type
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
details.push(detailObj as unknown as GoogleApiErrorDetail);
|
||||
|
|
|
|||
|
|
@ -372,31 +372,30 @@ async function parseTokenEndpointResponse(
|
|||
// Try to parse as JSON first, fall back to form-urlencoded
|
||||
try {
|
||||
const data: unknown = JSON.parse(responseText);
|
||||
if (
|
||||
data &&
|
||||
typeof data === 'object' &&
|
||||
'access_token' in data &&
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof (data as Record<string, unknown>)['access_token'] === 'string'
|
||||
) {
|
||||
if (data && typeof data === 'object' && 'access_token' in data) {
|
||||
const obj = data as Record<string, unknown>;
|
||||
const result: OAuthTokenResponse = {
|
||||
access_token: String(obj['access_token']),
|
||||
token_type:
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof obj['token_type'] === 'string' ? obj['token_type'] : 'Bearer',
|
||||
expires_in:
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof obj['expires_in'] === 'number' ? obj['expires_in'] : undefined,
|
||||
refresh_token:
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
typeof obj['refresh_token'] === 'string'
|
||||
? obj['refresh_token']
|
||||
: undefined,
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
scope: typeof obj['scope'] === 'string' ? obj['scope'] : undefined,
|
||||
};
|
||||
return result;
|
||||
const accessTokenValue = obj['access_token'];
|
||||
if (typeof accessTokenValue === 'string') {
|
||||
const tokenTypeValue = obj['token_type'];
|
||||
const expiresInValue = obj['expires_in'];
|
||||
const refreshTokenValue = obj['refresh_token'];
|
||||
const scopeValue = obj['scope'];
|
||||
|
||||
const result: OAuthTokenResponse = {
|
||||
access_token: accessTokenValue,
|
||||
token_type:
|
||||
typeof tokenTypeValue === 'string' ? tokenTypeValue : 'Bearer',
|
||||
expires_in:
|
||||
typeof expiresInValue === 'number' ? expiresInValue : undefined,
|
||||
refresh_token:
|
||||
typeof refreshTokenValue === 'string'
|
||||
? refreshTokenValue
|
||||
: undefined,
|
||||
|
||||
scope: typeof scopeValue === 'string' ? scopeValue : undefined,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// JSON parsed but doesn't look like a token response — fall through
|
||||
} catch {
|
||||
|
|
|
|||
Loading…
Reference in a new issue