mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 02:04:32 +00:00
fix(coding-agent): fix Google Cloud project discovery
Use correct API response format (cloudaicompanionProject) and proper onboarding flow with tierId and metadata. Add retry logic for project provisioning which may take time.
This commit is contained in:
parent
b6fe07b618
commit
1294239a7a
1 changed files with 90 additions and 33 deletions
|
|
@ -90,50 +90,108 @@ function startCallbackServer(): Promise<{ server: Server; getCode: () => Promise
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LoadCodeAssistPayload {
|
||||||
|
cloudaicompanionProject?: string;
|
||||||
|
currentTier?: { id?: string };
|
||||||
|
allowedTiers?: Array<{ id?: string; isDefault?: boolean }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnboardUserPayload {
|
||||||
|
done?: boolean;
|
||||||
|
response?: {
|
||||||
|
cloudaicompanionProject?: { id?: string };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait helper for onboarding retries
|
||||||
|
*/
|
||||||
|
function wait(ms: number): Promise<void> {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default tier ID from allowed tiers
|
||||||
|
*/
|
||||||
|
function getDefaultTierId(allowedTiers?: Array<{ id?: string; isDefault?: boolean }>): string | undefined {
|
||||||
|
if (!allowedTiers || allowedTiers.length === 0) return undefined;
|
||||||
|
const defaultTier = allowedTiers.find((t) => t.isDefault);
|
||||||
|
return defaultTier?.id ?? allowedTiers[0]?.id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discover or provision a Google Cloud project for the user
|
* Discover or provision a Google Cloud project for the user
|
||||||
*/
|
*/
|
||||||
async function discoverProject(accessToken: string): Promise<string> {
|
async function discoverProject(accessToken: string, onProgress?: (message: string) => void): Promise<string> {
|
||||||
// Try to load existing projects via loadCodeAssist
|
const headers = {
|
||||||
const response = await fetch(`${CODE_ASSIST_ENDPOINT}/v1internal:loadCodeAssist`, {
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"User-Agent": "google-api-nodejs-client/9.15.1",
|
||||||
|
"X-Goog-Api-Client": "gl-node/22.17.0",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to load existing project via loadCodeAssist
|
||||||
|
onProgress?.("Checking for existing Cloud Code Assist project...");
|
||||||
|
const loadResponse = await fetch(`${CODE_ASSIST_ENDPOINT}/v1internal:loadCodeAssist`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers,
|
||||||
Authorization: `Bearer ${accessToken}`,
|
body: JSON.stringify({
|
||||||
"Content-Type": "application/json",
|
metadata: {
|
||||||
"User-Agent": "google-api-nodejs-client/9.15.1",
|
ideType: "IDE_UNSPECIFIED",
|
||||||
"X-Goog-Api-Client": "gl-node/22.17.0",
|
platform: "PLATFORM_UNSPECIFIED",
|
||||||
},
|
pluginType: "GEMINI",
|
||||||
body: JSON.stringify({}),
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (loadResponse.ok) {
|
||||||
const data = (await response.json()) as { projects?: Array<{ projectId: string }> };
|
const data = (await loadResponse.json()) as LoadCodeAssistPayload;
|
||||||
if (data.projects && data.projects.length > 0) {
|
|
||||||
return data.projects[0].projectId;
|
// If we have an existing project, use it
|
||||||
|
if (data.cloudaicompanionProject) {
|
||||||
|
return data.cloudaicompanionProject;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Try to onboard the user if no projects found
|
// Otherwise, try to onboard with the FREE tier
|
||||||
const onboardResponse = await fetch(`${CODE_ASSIST_ENDPOINT}/v1internal:onboardUser`, {
|
const tierId = getDefaultTierId(data.allowedTiers) ?? "FREE";
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"User-Agent": "google-api-nodejs-client/9.15.1",
|
|
||||||
"X-Goog-Api-Client": "gl-node/22.17.0",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (onboardResponse.ok) {
|
onProgress?.("Provisioning Cloud Code Assist project (this may take a moment)...");
|
||||||
const data = (await onboardResponse.json()) as { projectId?: string };
|
|
||||||
if (data.projectId) {
|
// Onboard with retries (the API may take time to provision)
|
||||||
return data.projectId;
|
for (let attempt = 0; attempt < 10; attempt++) {
|
||||||
|
const onboardResponse = await fetch(`${CODE_ASSIST_ENDPOINT}/v1internal:onboardUser`, {
|
||||||
|
method: "POST",
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
tierId,
|
||||||
|
metadata: {
|
||||||
|
ideType: "IDE_UNSPECIFIED",
|
||||||
|
platform: "PLATFORM_UNSPECIFIED",
|
||||||
|
pluginType: "GEMINI",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (onboardResponse.ok) {
|
||||||
|
const onboardData = (await onboardResponse.json()) as OnboardUserPayload;
|
||||||
|
const projectId = onboardData.response?.cloudaicompanionProject?.id;
|
||||||
|
|
||||||
|
if (onboardData.done && projectId) {
|
||||||
|
return projectId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait before retrying
|
||||||
|
if (attempt < 9) {
|
||||||
|
onProgress?.(`Waiting for project provisioning (attempt ${attempt + 2}/10)...`);
|
||||||
|
await wait(3000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Could not discover or provision a Google Cloud project. Please ensure you have access to Google Cloud Code Assist.",
|
"Could not discover or provision a Google Cloud project. " +
|
||||||
|
"Please ensure you have access to Google Cloud Code Assist (Gemini CLI).",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,8 +297,7 @@ export async function loginGoogleCloud(
|
||||||
const email = await getUserEmail(tokenData.access_token);
|
const email = await getUserEmail(tokenData.access_token);
|
||||||
|
|
||||||
// Discover project
|
// Discover project
|
||||||
onProgress?.("Discovering Google Cloud project...");
|
const projectId = await discoverProject(tokenData.access_token, onProgress);
|
||||||
const projectId = await discoverProject(tokenData.access_token);
|
|
||||||
|
|
||||||
// Calculate expiry time (current time + expires_in seconds - 5 min buffer)
|
// Calculate expiry time (current time + expires_in seconds - 5 min buffer)
|
||||||
const expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;
|
const expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue