chore: minor fixes in session-actions and session-api

This commit is contained in:
Gemini AI
2025-12-28 11:19:39 +04:00
Unverified
parent c66bd68a13
commit 41f38fe4bf
2 changed files with 99 additions and 18 deletions

View File

@@ -19,7 +19,14 @@ import {
clearCompactionSuggestion, clearCompactionSuggestion,
type CompactionResult, type CompactionResult,
} from "./session-compaction" } from "./session-compaction"
import { createSession, loadMessages, getStoredAntigravityToken, isAntigravityTokenValid } from "./session-api" import {
ANTIGRAVITY_MODEL_IDS,
createSession,
getStoredAntigravityProjectId,
getStoredAntigravityToken,
isAntigravityTokenValid,
loadMessages,
} from "./session-api"
import { showToastNotification } from "../lib/notifications" import { showToastNotification } from "../lib/notifications"
import { QwenOAuthManager } from "../lib/integrations/qwen-oauth" import { QwenOAuthManager } from "../lib/integrations/qwen-oauth"
import { getUserScopedKey } from "../lib/user-storage" import { getUserScopedKey } from "../lib/user-storage"
@@ -496,6 +503,7 @@ async function readSseStream(
if (idleTimer) clearTimeout(idleTimer) if (idleTimer) clearTimeout(idleTimer)
idleTimer = setTimeout(() => { idleTimer = setTimeout(() => {
timedOut = true timedOut = true
shouldStop = true
reader.cancel().catch(() => { }) reader.cancel().catch(() => { })
}, idleTimeoutMs) }, idleTimeoutMs)
} }
@@ -505,9 +513,15 @@ async function readSseStream(
let chunkCount = 0 let chunkCount = 0
let lastYieldTime = performance.now() let lastYieldTime = performance.now()
while (!shouldStop) { while (!shouldStop) {
const { done, value } = await reader.read() let readResult: ReadableStreamReadResult<Uint8Array>
try {
readResult = await reader.read()
} catch (error) {
if (timedOut) break
throw error
}
const { done, value } = readResult
if (done) break if (done) break
resetIdleTimer()
buffer += decoder.decode(value, { stream: true }) buffer += decoder.decode(value, { stream: true })
const lines = buffer.split("\n") const lines = buffer.split("\n")
buffer = lines.pop() || "" buffer = lines.pop() || ""
@@ -517,6 +531,7 @@ async function readSseStream(
if (!trimmed.startsWith("data:")) continue if (!trimmed.startsWith("data:")) continue
const data = trimmed.slice(5).trim() const data = trimmed.slice(5).trim()
if (!data) continue if (!data) continue
resetIdleTimer()
if (data === "[DONE]") { if (data === "[DONE]") {
shouldStop = true shouldStop = true
break break
@@ -1175,6 +1190,10 @@ async function streamAntigravityChat(
"Content-Type": "application/json", "Content-Type": "application/json",
Authorization: `Bearer ${token.access_token}`, Authorization: `Bearer ${token.access_token}`,
} }
const projectId = getStoredAntigravityProjectId()
if (projectId) {
headers["X-Antigravity-Project"] = projectId
}
const response = await fetch("/api/antigravity/chat", { const response = await fetch("/api/antigravity/chat", {
method: "POST", method: "POST",
@@ -1491,6 +1510,10 @@ async function sendMessage(
}) })
const providerId = effectiveModel.providerId const providerId = effectiveModel.providerId
const useAntigravity =
providerId === "antigravity" ||
(providerId === "google" && ANTIGRAVITY_MODEL_IDS.has(effectiveModel.modelId))
const routingProviderId = useAntigravity ? "antigravity" : providerId
const tPre1 = performance.now() const tPre1 = performance.now()
const systemMessage = await untrack(() => mergeSystemInstructions(instanceId, sessionId, prompt)) const systemMessage = await untrack(() => mergeSystemInstructions(instanceId, sessionId, prompt))
const tPre2 = performance.now() const tPre2 = performance.now()
@@ -1498,7 +1521,7 @@ async function sendMessage(
addDebugLog(`Merge System Instructions: ${Math.round(tPre2 - tPre1)}ms`, "warn") addDebugLog(`Merge System Instructions: ${Math.round(tPre2 - tPre1)}ms`, "warn")
} }
if (providerId === "ollama-cloud" || providerId === "qwen-oauth" || providerId === "opencode-zen" || providerId === "zai" || providerId === "antigravity") { if (providerId === "ollama-cloud" || providerId === "qwen-oauth" || providerId === "opencode-zen" || providerId === "zai" || useAntigravity) {
const store = messageStoreBus.getOrCreate(instanceId) const store = messageStoreBus.getOrCreate(instanceId)
const now = Date.now() const now = Date.now()
const assistantMessageId = createId("msg") const assistantMessageId = createId("msg")
@@ -1530,7 +1553,7 @@ async function sendMessage(
store.setMessageInfo(assistantMessageId, { store.setMessageInfo(assistantMessageId, {
id: assistantMessageId, id: assistantMessageId,
role: "assistant", role: "assistant",
providerID: effectiveModel.providerId, providerID: routingProviderId,
modelID: effectiveModel.modelId, modelID: effectiveModel.modelId,
time: { created: now, completed: 0 }, time: { created: now, completed: 0 },
} as any) } as any)
@@ -1582,11 +1605,11 @@ async function sendMessage(
assistantMessageId, assistantMessageId,
assistantPartId, assistantPartId,
) )
} else if (providerId === "antigravity") { } else if (useAntigravity) {
assistantText = await streamAntigravityChat( assistantText = await streamAntigravityChat(
instanceId, instanceId,
sessionId, sessionId,
providerId, routingProviderId,
effectiveModel.modelId, effectiveModel.modelId,
externalMessages, externalMessages,
messageId, messageId,
@@ -1695,26 +1718,33 @@ async function sendMessage(
updatedAt: Date.now(), updatedAt: Date.now(),
isEphemeral: false, isEphemeral: false,
}) })
const rawErrorMessage = error?.message || "Request failed"
const normalizedErrorMessage = /aborted|abort/i.test(rawErrorMessage)
? "Request timed out. The provider may be unavailable."
: rawErrorMessage
store.setMessageInfo(assistantMessageId, { store.setMessageInfo(assistantMessageId, {
id: assistantMessageId, id: assistantMessageId,
role: "assistant", role: "assistant",
providerID: effectiveModel.providerId, providerID: routingProviderId,
modelID: effectiveModel.modelId, modelID: effectiveModel.modelId,
time: { created: now, completed: Date.now() }, time: { created: now, completed: Date.now() },
error: { name: "UnknownError", message: error?.message || "Request failed" }, error: { name: "UnknownError", message: normalizedErrorMessage },
} as any) } as any)
const failedProvider = useAntigravity ? "antigravity" : providerId
showToastNotification({ showToastNotification({
title: title:
providerId === "ollama-cloud" failedProvider === "ollama-cloud"
? "Ollama request failed" ? "Ollama request failed"
: providerId === "zai" : failedProvider === "zai"
? "Z.AI request failed" ? "Z.AI request failed"
: providerId === "opencode-zen" : failedProvider === "opencode-zen"
? "OpenCode Zen request failed" ? "OpenCode Zen request failed"
: providerId === "antigravity" : failedProvider === "antigravity"
? "Antigravity request failed" ? "Antigravity request failed"
: "Qwen request failed", : failedProvider === "qwen-oauth"
message: error?.message || "Request failed", ? "Qwen request failed"
: "Request failed",
message: normalizedErrorMessage,
variant: "error", variant: "error",
duration: 8000, duration: 8000,
}) })

View File

@@ -40,6 +40,20 @@ import { getUserScopedKey } from "../lib/user-storage"
const log = getLogger("api") const log = getLogger("api")
type ProviderMap = Map<string, Provider> type ProviderMap = Map<string, Provider>
export const ANTIGRAVITY_MODEL_IDS = new Set([
"gemini-3-pro-low",
"gemini-3-pro-high",
"gemini-3-flash",
"claude-sonnet-4-5",
"claude-sonnet-4-5-thinking-low",
"claude-sonnet-4-5-thinking-medium",
"claude-sonnet-4-5-thinking-high",
"claude-opus-4-5-thinking-low",
"claude-opus-4-5-thinking-medium",
"claude-opus-4-5-thinking-high",
"gpt-oss-120b-medium",
])
const ANTIGRAVITY_PROJECT_KEY = "antigravity_project_id"
async function fetchJson<T>(url: string): Promise<T | null> { async function fetchJson<T>(url: string): Promise<T | null> {
try { try {
@@ -271,12 +285,26 @@ export function isAntigravityTokenValid(token: { expires_in: number; created_at:
return Date.now() < expiresAt return Date.now() < expiresAt
} }
export function getStoredAntigravityProjectId(): string | undefined {
if (typeof window === "undefined") return undefined
try {
const value = window.localStorage.getItem(getUserScopedKey(ANTIGRAVITY_PROJECT_KEY))
return value && value.trim().length > 0 ? value.trim() : undefined
} catch {
return undefined
}
}
async function fetchAntigravityProvider(): Promise<Provider | null> { async function fetchAntigravityProvider(): Promise<Provider | null> {
const token = getStoredAntigravityToken() const token = getStoredAntigravityToken()
const projectId = getStoredAntigravityProjectId()
const headers: Record<string, string> = { "Content-Type": "application/json" } const headers: Record<string, string> = { "Content-Type": "application/json" }
if (token?.access_token) { if (token?.access_token) {
headers["Authorization"] = `Bearer ${token.access_token}` headers["Authorization"] = `Bearer ${token.access_token}`
} }
if (projectId) {
headers["X-Antigravity-Project"] = projectId
}
try { try {
const response = await fetch("/api/antigravity/models", { headers }) const response = await fetch("/api/antigravity/models", { headers })
@@ -295,7 +323,7 @@ async function fetchAntigravityProvider(): Promise<Provider | null> {
return { return {
id: "antigravity", id: "antigravity",
name: "Antigravity (Google OAuth)", name: "Antigravity",
models: models.map((model) => ({ models: models.map((model) => ({
id: model.id, id: model.id,
name: model.name, name: model.name,
@@ -994,14 +1022,37 @@ async function fetchProviders(instanceId: string): Promise<void> {
} }
} }
const normalizedProviders = providerList
.map((provider) => {
if (provider.id !== "google") return provider
const filteredModels = provider.models.filter((model: Model) => ANTIGRAVITY_MODEL_IDS.has(model.id))
if (filteredModels.length === 0) return null
const defaultModelId = filteredModels.some((model: Model) => model.id === provider.defaultModelId)
? provider.defaultModelId
: filteredModels[0]?.id
return {
...provider,
name: "Antigravity",
defaultModelId,
models: filteredModels,
}
})
.filter(Boolean) as typeof providerList
// Filter out Z.AI providers from SDK to use our custom routing with full message history // Filter out Z.AI providers from SDK to use our custom routing with full message history
const filteredBaseProviders = providerList.filter((provider) => const filteredBaseProviders = normalizedProviders.filter((provider) =>
!provider.id.toLowerCase().includes("zai") && !provider.id.toLowerCase().includes("zai") &&
!provider.id.toLowerCase().includes("z.ai") && !provider.id.toLowerCase().includes("z.ai") &&
!provider.id.toLowerCase().includes("glm") !provider.id.toLowerCase().includes("glm")
) )
const extraProviders = await fetchExtraProviders() let extraProviders = await fetchExtraProviders()
if (!isNative) {
const hasSdkAntigravity = normalizedProviders.some((provider) => provider.id === "google")
if (hasSdkAntigravity) {
extraProviders = extraProviders.filter((provider) => provider.id !== "antigravity")
}
}
const baseProviders = removeDuplicateProviders(filteredBaseProviders, extraProviders) const baseProviders = removeDuplicateProviders(filteredBaseProviders, extraProviders)
const mergedProviders = mergeProviders(baseProviders, extraProviders) const mergedProviders = mergeProviders(baseProviders, extraProviders)