Add Google Gemini CLI and Antigravity OAuth providers
- Add google-gemini-cli provider: free Gemini 2.0/2.5 via Cloud Code Assist - Add google-antigravity provider: free Gemini 3, Claude, GPT-OSS via sandbox - Move OAuth infrastructure from coding-agent to ai package - Fix thinking signature handling for cross-model handoff - Fix OpenAI message ID length limit (max 64 chars) - Add GitHub Copilot overflow pattern detection - Add OAuth provider tests for context overflow and streaming
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* OAuth credential storage for ~/.pi/agent/oauth.json
|
||||
*/
|
||||
|
||||
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
||||
import { homedir } from "os";
|
||||
import { dirname, join } from "path";
|
||||
|
||||
export interface OAuthCredentials {
|
||||
type: "oauth";
|
||||
refresh: string;
|
||||
access: string;
|
||||
expires: number;
|
||||
enterpriseUrl?: string;
|
||||
projectId?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
export interface OAuthStorage {
|
||||
[provider: string]: OAuthCredentials;
|
||||
}
|
||||
|
||||
export type OAuthProvider = "anthropic" | "github-copilot" | "google-gemini-cli" | "google-antigravity";
|
||||
|
||||
/**
|
||||
* Get the path to the OAuth credentials file
|
||||
*/
|
||||
export function getOAuthPath(): string {
|
||||
return join(homedir(), ".pi", "agent", "oauth.json");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the config directory exists
|
||||
*/
|
||||
function ensureConfigDir(): void {
|
||||
const configDir = dirname(getOAuthPath());
|
||||
if (!existsSync(configDir)) {
|
||||
mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all OAuth credentials from ~/.pi/agent/oauth.json
|
||||
*/
|
||||
export function loadOAuthStorage(): OAuthStorage {
|
||||
const filePath = getOAuthPath();
|
||||
if (!existsSync(filePath)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
try {
|
||||
const content = readFileSync(filePath, "utf-8");
|
||||
return JSON.parse(content);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all OAuth credentials to ~/.pi/agent/oauth.json
|
||||
*/
|
||||
function saveOAuthStorage(storage: OAuthStorage): void {
|
||||
ensureConfigDir();
|
||||
const filePath = getOAuthPath();
|
||||
writeFileSync(filePath, JSON.stringify(storage, null, 2), "utf-8");
|
||||
chmodSync(filePath, 0o600);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load OAuth credentials for a specific provider
|
||||
*/
|
||||
export function loadOAuthCredentials(provider: string): OAuthCredentials | null {
|
||||
const storage = loadOAuthStorage();
|
||||
return storage[provider] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save OAuth credentials for a specific provider
|
||||
*/
|
||||
export function saveOAuthCredentials(provider: string, creds: OAuthCredentials): void {
|
||||
const storage = loadOAuthStorage();
|
||||
storage[provider] = creds;
|
||||
saveOAuthStorage(storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove OAuth credentials for a specific provider
|
||||
*/
|
||||
export function removeOAuthCredentials(provider: string): void {
|
||||
const storage = loadOAuthStorage();
|
||||
delete storage[provider];
|
||||
saveOAuthStorage(storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if OAuth credentials exist for a provider
|
||||
*/
|
||||
export function hasOAuthCredentials(provider: string): boolean {
|
||||
return loadOAuthCredentials(provider) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all providers with OAuth credentials
|
||||
*/
|
||||
export function listOAuthProviders(): string[] {
|
||||
const storage = loadOAuthStorage();
|
||||
return Object.keys(storage);
|
||||
}
|
||||
Reference in New Issue
Block a user