shitton
This commit is contained in:
@@ -119,6 +119,8 @@ export function getDefaultModelForPurpose(provider: AiProvider, purpose: AiRunti
|
|||||||
}
|
}
|
||||||
case AiProvider.GEMINI:
|
case AiProvider.GEMINI:
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
|
case "vision":
|
||||||
|
case "ocr":
|
||||||
case "outputImages":
|
case "outputImages":
|
||||||
return Environment.GEMINI_IMAGE_MODEL;
|
return Environment.GEMINI_IMAGE_MODEL;
|
||||||
case "speechToText":
|
case "speechToText":
|
||||||
|
|||||||
@@ -164,14 +164,14 @@ export async function getModelCapabilities(
|
|||||||
case AiProvider.GEMINI: {
|
case AiProvider.GEMINI: {
|
||||||
const chatLike = lowerModelName(model).startsWith("gemini-") && !isGeminiNonChatModel(model);
|
const chatLike = lowerModelName(model).startsWith("gemini-") && !isGeminiNonChatModel(model);
|
||||||
const reasoningModel = lowerModelName(model).includes("2.5") || lowerModelName(model).includes("thinking");
|
const reasoningModel = lowerModelName(model).includes("2.5") || lowerModelName(model).includes("thinking");
|
||||||
const imageTarget = resolveAiRuntimeTarget(provider, "outputImages");
|
const imageTarget = resolveAiRuntimeTarget(provider, "vision");
|
||||||
const speechTarget = resolveAiRuntimeTarget(provider, "speechToText");
|
const speechTarget = resolveAiRuntimeTarget(provider, "speechToText");
|
||||||
const ttsTarget = resolveAiRuntimeTarget(provider, "textToSpeech");
|
const ttsTarget = resolveAiRuntimeTarget(provider, "textToSpeech");
|
||||||
|
|
||||||
return buildCapabilities({
|
return buildCapabilities({
|
||||||
chat: capability(true, target, runtimeTarget),
|
chat: capability(true, target, runtimeTarget),
|
||||||
vision: capability(chatLike, target, runtimeTarget),
|
vision: capability(!!imageTarget.apiKey && !!imageTarget.model, imageTarget, runtimeTarget),
|
||||||
ocr: capability(chatLike, target, runtimeTarget),
|
ocr: capability(!!imageTarget.apiKey && !!imageTarget.model, imageTarget, runtimeTarget),
|
||||||
thinking: capability(reasoningModel, target, runtimeTarget),
|
thinking: capability(reasoningModel, target, runtimeTarget),
|
||||||
extendedThinking: capability(reasoningModel, target, runtimeTarget),
|
extendedThinking: capability(reasoningModel, target, runtimeTarget),
|
||||||
tools: capability(chatLike, target, runtimeTarget),
|
tools: capability(chatLike, target, runtimeTarget),
|
||||||
|
|||||||
@@ -6,7 +6,19 @@ import {GeminiMessage} from "./gemini-chat-message";
|
|||||||
import {createGoogleGenAiClient} from "./ai-runtime-target";
|
import {createGoogleGenAiClient} from "./ai-runtime-target";
|
||||||
import {aiLog, aiLogDuration, aiLogProviderTarget, aiLogToolCall} from "../logging/ai-logger";
|
import {aiLog, aiLogDuration, aiLogProviderTarget, aiLogToolCall} from "../logging/ai-logger";
|
||||||
|
|
||||||
import {AsyncIterableStream, GeminiFunctionCallLike, GeminiResponseLike, MAX_TOOL_ROUNDS, RuntimeConfigSnapshot, ToolCallData, ToolExecutionMemory, executeToolBatch, roundStatus, safeJsonParseObject, GeminiGenerationRequest} from "./unified-ai-runner.shared";
|
import {
|
||||||
|
AsyncIterableStream,
|
||||||
|
executeToolBatch,
|
||||||
|
GeminiFunctionCallLike,
|
||||||
|
GeminiGenerationRequest,
|
||||||
|
GeminiResponseLike,
|
||||||
|
MAX_TOOL_ROUNDS,
|
||||||
|
roundStatus,
|
||||||
|
RuntimeConfigSnapshot,
|
||||||
|
safeJsonParseObject,
|
||||||
|
ToolCallData,
|
||||||
|
ToolExecutionMemory
|
||||||
|
} from "./unified-ai-runner.shared";
|
||||||
|
|
||||||
function collectGeminiResponseText(response: GeminiResponseLike & { text?: string }): string {
|
function collectGeminiResponseText(response: GeminiResponseLike & { text?: string }): string {
|
||||||
if (typeof response.text === "string") return response.text;
|
if (typeof response.text === "string") return response.text;
|
||||||
@@ -88,6 +100,14 @@ export async function runGemini(
|
|||||||
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: 13.05.2026, Danil Nikolaev: find a better way?
|
||||||
|
const imageCount = messages.reduce((sum, m) => {
|
||||||
|
return sum + (m.parts.filter(p => "inlineData" in p && "mimeType" in p.inlineData && p.inlineData.mimeType.startsWith("image")).length)
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const target = imageCount ? config.geminiImageTarget : config.geminiChatTarget;
|
||||||
|
const model = target.model;
|
||||||
|
|
||||||
const toolMemory: ToolExecutionMemory = new Map();
|
const toolMemory: ToolExecutionMemory = new Map();
|
||||||
|
|
||||||
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
||||||
@@ -99,7 +119,7 @@ export async function runGemini(
|
|||||||
await streamMessage.flush();
|
await streamMessage.flush();
|
||||||
|
|
||||||
const request: GeminiGenerationRequest = {
|
const request: GeminiGenerationRequest = {
|
||||||
model: config.geminiChatTarget.model,
|
model: model,
|
||||||
contents: messages,
|
contents: messages,
|
||||||
config: {
|
config: {
|
||||||
tools: getGeminiTools(),
|
tools: getGeminiTools(),
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ export type RuntimeConfigSnapshot = {
|
|||||||
ollamaRagMaxArchiveDepth: number;
|
ollamaRagMaxArchiveDepth: number;
|
||||||
|
|
||||||
geminiChatTarget: AiRuntimeTarget;
|
geminiChatTarget: AiRuntimeTarget;
|
||||||
|
geminiImageTarget: AiRuntimeTarget;
|
||||||
|
|
||||||
mistralChatTarget: AiRuntimeTarget;
|
mistralChatTarget: AiRuntimeTarget;
|
||||||
|
|
||||||
@@ -310,6 +311,7 @@ export function snapshotRuntimeConfig(): RuntimeConfigSnapshot {
|
|||||||
ollamaRagMaxArchiveDepth: Environment.OLLAMA_RAG_MAX_ARCHIVE_DEPTH,
|
ollamaRagMaxArchiveDepth: Environment.OLLAMA_RAG_MAX_ARCHIVE_DEPTH,
|
||||||
|
|
||||||
geminiChatTarget: resolveAiRuntimeTarget(AiProvider.GEMINI, "chat"),
|
geminiChatTarget: resolveAiRuntimeTarget(AiProvider.GEMINI, "chat"),
|
||||||
|
geminiImageTarget: resolveAiRuntimeTarget(AiProvider.GEMINI, "vision"),
|
||||||
|
|
||||||
mistralChatTarget: resolveAiRuntimeTarget(AiProvider.MISTRAL, "chat"),
|
mistralChatTarget: resolveAiRuntimeTarget(AiProvider.MISTRAL, "chat"),
|
||||||
|
|
||||||
@@ -641,6 +643,7 @@ export async function rejectUnsupportedAttachments(
|
|||||||
if (!unsupported) return false;
|
if (!unsupported) return false;
|
||||||
|
|
||||||
if (!kinds.has("audio")) {
|
if (!kinds.has("audio")) {
|
||||||
|
// TODO: 13.05.2026, Danil Nikolaev: add "Regenerate" button
|
||||||
await replyToMessage({
|
await replyToMessage({
|
||||||
message: msg,
|
message: msg,
|
||||||
text: unsupportedAttachmentText(provider, effectiveModel, unsupported),
|
text: unsupportedAttachmentText(provider, effectiveModel, unsupported),
|
||||||
|
|||||||
Reference in New Issue
Block a user