oh-my-opencode/src/auth/antigravity/thought-signature-store.ts
YeonGyu-Kim 5fd59afacf feat(antigravity): add thought signature support for multi-turn conversations
Gemini 3 Pro requires thoughtSignature on function call blocks in
subsequent requests. This commit:

- Add thought-signature-store for session-based signature storage
- Extract signature from both streaming (SSE) and non-streaming responses
- Inject signature into functionCall parts on subsequent requests
- Maintain consistent sessionId per fetch instance

Debug logging available via ANTIGRAVITY_DEBUG=1

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
2025-12-13 01:16:53 +09:00

98 lines
2.8 KiB
TypeScript

/**
* Thought Signature Store
*
* Stores and retrieves thought signatures for multi-turn conversations.
* Gemini 3 Pro requires thought_signature on function call content blocks
* in subsequent requests to maintain reasoning continuity.
*
* Key responsibilities:
* - Store the latest thought signature per session
* - Provide signature for injection into function call requests
* - Clear signatures when sessions end
*/
/**
* In-memory store for thought signatures indexed by session ID
*/
const signatureStore = new Map<string, string>()
/**
* In-memory store for session IDs per fetch instance
* Used to maintain consistent sessionId across multi-turn conversations
*/
const sessionIdStore = new Map<string, string>()
/**
* Store a thought signature for a session
*
* @param sessionKey - Unique session identifier (typically fetch instance ID)
* @param signature - The thought signature from model response
*/
export function setThoughtSignature(sessionKey: string, signature: string): void {
if (sessionKey && signature) {
signatureStore.set(sessionKey, signature)
}
}
/**
* Retrieve the stored thought signature for a session
*
* @param sessionKey - Unique session identifier
* @returns The stored signature or undefined if not found
*/
export function getThoughtSignature(sessionKey: string): string | undefined {
return signatureStore.get(sessionKey)
}
/**
* Clear the thought signature for a session
*
* @param sessionKey - Unique session identifier
*/
export function clearThoughtSignature(sessionKey: string): void {
signatureStore.delete(sessionKey)
}
/**
* Store or retrieve a persistent session ID for a fetch instance
*
* @param fetchInstanceId - Unique identifier for the fetch instance
* @param sessionId - Optional session ID to store (if not provided, returns existing or generates new)
* @returns The session ID for this fetch instance
*/
export function getOrCreateSessionId(fetchInstanceId: string, sessionId?: string): string {
if (sessionId) {
sessionIdStore.set(fetchInstanceId, sessionId)
return sessionId
}
const existing = sessionIdStore.get(fetchInstanceId)
if (existing) {
return existing
}
const n = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)
const newSessionId = `-${n}`
sessionIdStore.set(fetchInstanceId, newSessionId)
return newSessionId
}
/**
* Clear the session ID for a fetch instance
*
* @param fetchInstanceId - Unique identifier for the fetch instance
*/
export function clearSessionId(fetchInstanceId: string): void {
sessionIdStore.delete(fetchInstanceId)
}
/**
* Clear all stored data for a fetch instance (signature + session ID)
*
* @param fetchInstanceId - Unique identifier for the fetch instance
*/
export function clearFetchInstanceData(fetchInstanceId: string): void {
signatureStore.delete(fetchInstanceId)
sessionIdStore.delete(fetchInstanceId)
}