fix: resolve Antigravity token definition error and add validation
Some checks failed
Release Binaries / release (push) Has been cancelled
Some checks failed
Release Binaries / release (push) Has been cancelled
Changes: 1. Exported getStoredAntigravityToken and isAntigravityTokenValid from session-api.ts 2. Imported token helpers into session-actions.ts 3. Added token validation and user notifications to streamAntigravityChat 4. Fixed TypeScript implicit any error in fetchAntigravityProvider
This commit is contained in:
@@ -181,6 +181,14 @@ export const ANTIGRAVITY_MODELS: AntigravityModel[] = [
|
|||||||
tool_call: true,
|
tool_call: true,
|
||||||
limit: { context: 200000, output: 64000 }
|
limit: { context: 200000, output: 64000 }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "claude-opus-4-5",
|
||||||
|
name: "Claude Opus 4.5 (Antigravity)",
|
||||||
|
family: "claude",
|
||||||
|
reasoning: false,
|
||||||
|
tool_call: true,
|
||||||
|
limit: { context: 200000, output: 64000 }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "claude-opus-4-5-thinking-low",
|
id: "claude-opus-4-5-thinking-low",
|
||||||
name: "Claude Opus 4.5 Thinking Low (Antigravity)",
|
name: "Claude Opus 4.5 Thinking Low (Antigravity)",
|
||||||
@@ -539,11 +547,8 @@ export class AntigravityClient {
|
|||||||
* Get available Antigravity models
|
* Get available Antigravity models
|
||||||
*/
|
*/
|
||||||
async getModels(accessToken?: string): Promise<AntigravityModel[]> {
|
async getModels(accessToken?: string): Promise<AntigravityModel[]> {
|
||||||
if (!this.isAuthenticated(accessToken)) {
|
// Return full model list even if not authenticated, so they appear in selectors
|
||||||
return []
|
// Authenticaton is checked during actual chat requests
|
||||||
}
|
|
||||||
|
|
||||||
// Return cached models if still valid
|
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
if (this.modelsCache && (now - this.modelsCacheTime) < this.CACHE_TTL_MS) {
|
if (this.modelsCache && (now - this.modelsCacheTime) < this.CACHE_TTL_MS) {
|
||||||
return this.modelsCache
|
return this.modelsCache
|
||||||
|
|||||||
@@ -412,6 +412,7 @@ export async function registerQwenRoutes(
|
|||||||
'Connection': 'keep-alive',
|
'Connection': 'keep-alive',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
await streamWithToolLoop(
|
await streamWithToolLoop(
|
||||||
accessToken,
|
accessToken,
|
||||||
chatUrl,
|
chatUrl,
|
||||||
@@ -421,6 +422,12 @@ export async function registerQwenRoutes(
|
|||||||
reply.raw,
|
reply.raw,
|
||||||
logger
|
logger
|
||||||
)
|
)
|
||||||
|
reply.raw.end()
|
||||||
|
} catch (streamError) {
|
||||||
|
logger.error({ error: streamError }, "Qwen streaming failed")
|
||||||
|
reply.raw.write(`data: ${JSON.stringify({ error: String(streamError) })}\n\n`)
|
||||||
|
reply.raw.end()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const response = await fetch(chatUrl, {
|
const response = await fetch(chatUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -439,6 +446,11 @@ export async function registerQwenRoutes(
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error({ error }, "Qwen chat proxy failed")
|
logger.error({ error }, "Qwen chat proxy failed")
|
||||||
|
if (reply.raw.headersSent) {
|
||||||
|
reply.raw.write(`data: ${JSON.stringify({ error: String(error) })}\n\n`)
|
||||||
|
reply.raw.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
return reply.status(500).send({ error: "Chat request failed" })
|
return reply.status(500).send({ error: "Chat request failed" })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
clearCompactionSuggestion,
|
clearCompactionSuggestion,
|
||||||
type CompactionResult,
|
type CompactionResult,
|
||||||
} from "./session-compaction"
|
} from "./session-compaction"
|
||||||
import { createSession, loadMessages } from "./session-api"
|
import { createSession, loadMessages, getStoredAntigravityToken, isAntigravityTokenValid } 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"
|
||||||
@@ -1144,9 +1144,41 @@ async function streamAntigravityChat(
|
|||||||
const instance = instances().get(instanceId)
|
const instance = instances().get(instanceId)
|
||||||
const workspacePath = instance?.folder || ""
|
const workspacePath = instance?.folder || ""
|
||||||
|
|
||||||
|
const token = getStoredAntigravityToken()
|
||||||
|
if (!token?.access_token || !isAntigravityTokenValid(token)) {
|
||||||
|
showToastNotification({
|
||||||
|
title: "Antigravity Unavailable",
|
||||||
|
message: "Please sign in with Google OAuth to use Antigravity models.",
|
||||||
|
variant: "warning",
|
||||||
|
duration: 8000,
|
||||||
|
})
|
||||||
|
const store = messageStoreBus.getOrCreate(instanceId)
|
||||||
|
store.upsertMessage({
|
||||||
|
id: messageId,
|
||||||
|
sessionId,
|
||||||
|
role: "user",
|
||||||
|
status: "error",
|
||||||
|
updatedAt: Date.now(),
|
||||||
|
})
|
||||||
|
store.upsertMessage({
|
||||||
|
id: assistantMessageId,
|
||||||
|
sessionId,
|
||||||
|
role: "assistant",
|
||||||
|
status: "error",
|
||||||
|
updatedAt: Date.now(),
|
||||||
|
isEphemeral: false,
|
||||||
|
})
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${token.access_token}`,
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch("/api/antigravity/chat", {
|
const response = await fetch("/api/antigravity/chat", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers,
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: modelId,
|
model: modelId,
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ async function fetchZAIProvider(): Promise<Provider | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStoredAntigravityToken():
|
export function getStoredAntigravityToken():
|
||||||
| { access_token: string; expires_in: number; created_at: number }
|
| { access_token: string; expires_in: number; created_at: number }
|
||||||
| null {
|
| null {
|
||||||
if (typeof window === "undefined") return null
|
if (typeof window === "undefined") return null
|
||||||
@@ -264,7 +264,7 @@ function getStoredAntigravityToken():
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAntigravityTokenValid(token: { expires_in: number; created_at: number } | null): boolean {
|
export function isAntigravityTokenValid(token: { expires_in: number; created_at: number } | null): boolean {
|
||||||
if (!token) return false
|
if (!token) return false
|
||||||
const createdAt = token.created_at > 1e12 ? Math.floor(token.created_at / 1000) : token.created_at
|
const createdAt = token.created_at > 1e12 ? Math.floor(token.created_at / 1000) : token.created_at
|
||||||
const expiresAt = (createdAt + token.expires_in) * 1000 - 300000
|
const expiresAt = (createdAt + token.expires_in) * 1000 - 300000
|
||||||
@@ -272,38 +272,25 @@ function isAntigravityTokenValid(token: { expires_in: number; created_at: number
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchAntigravityProvider(): Promise<Provider | null> {
|
async function fetchAntigravityProvider(): Promise<Provider | null> {
|
||||||
// Check if user is authenticated with Antigravity (Google OAuth)
|
|
||||||
const token = getStoredAntigravityToken()
|
const token = getStoredAntigravityToken()
|
||||||
if (!isAntigravityTokenValid(token)) {
|
const headers: Record<string, string> = { "Content-Type": "application/json" }
|
||||||
// Not authenticated - try to fetch models anyway (they show as available but require auth)
|
if (token?.access_token) {
|
||||||
try {
|
headers["Authorization"] = `Bearer ${token.access_token}`
|
||||||
const data = await fetchJson<{ models?: Array<{ id: string; name: string; limit?: Model["limit"] }> }>(
|
|
||||||
"/api/antigravity/models",
|
|
||||||
)
|
|
||||||
const models = Array.isArray(data?.models) ? data?.models ?? [] : []
|
|
||||||
if (models.length === 0) return null
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: "antigravity",
|
|
||||||
name: "Antigravity (Google OAuth)",
|
|
||||||
models: models.map((model) => ({
|
|
||||||
id: model.id,
|
|
||||||
name: model.name,
|
|
||||||
providerId: "antigravity",
|
|
||||||
limit: model.limit,
|
|
||||||
})),
|
|
||||||
defaultModelId: "gemini-3-pro-high",
|
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/antigravity/models", { headers })
|
||||||
|
if (!response.ok) {
|
||||||
|
// If server is down, return null to not show broken provider
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// User is authenticated - fetch full model list
|
const data = (await response.json()) as { models?: Array<{ id: string; name: string; limit?: Model["limit"] }> }
|
||||||
const data = await fetchJson<{ models?: Array<{ id: string; name: string; limit?: Model["limit"] }> }>(
|
const models = Array.isArray(data?.models) ? data.models : []
|
||||||
"/api/antigravity/models",
|
|
||||||
)
|
// If no models returned from server (unlikely now with backend fix),
|
||||||
const models = Array.isArray(data?.models) ? data?.models ?? [] : []
|
// but we can still return the provider with 0 models if we want it to show up.
|
||||||
|
// However, LiteModelSelector typically hides providers with empty models.
|
||||||
if (models.length === 0) return null
|
if (models.length === 0) return null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -317,6 +304,10 @@ async function fetchAntigravityProvider(): Promise<Provider | null> {
|
|||||||
})),
|
})),
|
||||||
defaultModelId: "gemini-3-pro-high",
|
defaultModelId: "gemini-3-pro-high",
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error("Failed to fetch Antigravity models", error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchExtraProviders(): Promise<Provider[]> {
|
async function fetchExtraProviders(): Promise<Provider[]> {
|
||||||
|
|||||||
Reference in New Issue
Block a user