chore: tighten cli validation and tooling checks

This commit is contained in:
di-sukharev
2026-04-10 16:56:51 +03:00
parent 58b9d844b8
commit 5fde6dbb63
22 changed files with 2250 additions and 2509 deletions

View File

@@ -1,5 +1,7 @@
import {
Content,
FinishReason,
GenerateContentResponse,
GoogleGenerativeAI,
HarmBlockThreshold,
HarmCategory,
@@ -12,6 +14,59 @@ import { AiEngine, AiEngineConfig } from './Engine';
interface GeminiConfig extends AiEngineConfig {}
const GEMINI_BLOCKING_FINISH_REASONS = new Set<FinishReason>([
FinishReason.RECITATION,
FinishReason.SAFETY,
FinishReason.LANGUAGE
]);
const formatGeminiBlockMessage = (
response: GenerateContentResponse
): string => {
const promptFeedback = response.promptFeedback;
if (promptFeedback?.blockReason) {
return promptFeedback.blockReasonMessage
? `Gemini response was blocked due to ${promptFeedback.blockReason}: ${promptFeedback.blockReasonMessage}`
: `Gemini response was blocked due to ${promptFeedback.blockReason}`;
}
const firstCandidate = response.candidates?.[0];
if (firstCandidate?.finishReason) {
return firstCandidate.finishMessage
? `Gemini response was blocked due to ${firstCandidate.finishReason}: ${firstCandidate.finishMessage}`
: `Gemini response was blocked due to ${firstCandidate.finishReason}`;
}
return 'Gemini response did not contain usable text';
};
const extractGeminiText = (response: GenerateContentResponse): string => {
const firstCandidate = response.candidates?.[0];
if (
firstCandidate?.finishReason &&
GEMINI_BLOCKING_FINISH_REASONS.has(firstCandidate.finishReason)
) {
throw new Error(formatGeminiBlockMessage(response));
}
const text = firstCandidate?.content?.parts
?.flatMap((part) =>
'text' in part && typeof part.text === 'string' ? [part.text] : []
)
.join('');
if (typeof text === 'string' && text.length > 0) {
return text;
}
if (response.promptFeedback?.blockReason) {
throw new Error(formatGeminiBlockMessage(response));
}
return '';
};
export class GeminiEngine implements AiEngine {
config: GeminiConfig;
client: GoogleGenerativeAI;
@@ -77,7 +132,7 @@ export class GeminiEngine implements AiEngine {
}
});
const content = result.response.text();
const content = extractGeminiText(result.response);
return removeContentTags(content, 'think');
} catch (error) {
throw normalizeEngineError(error, 'gemini', this.config.model);