gemini retries
This commit is contained in:
+2
-2
@@ -144,12 +144,12 @@ const messageHandlers = {
|
|||||||
|
|
||||||
export const gemini = agent({
|
export const gemini = agent({
|
||||||
name: "gemini",
|
name: "gemini",
|
||||||
install: async () => {
|
install: async (githubInstallationToken?: string) => {
|
||||||
return await installFromGithub({
|
return await installFromGithub({
|
||||||
owner: "google-gemini",
|
owner: "google-gemini",
|
||||||
repo: "gemini-cli",
|
repo: "gemini-cli",
|
||||||
tag: "v0.16.0",
|
|
||||||
assetName: "gemini.js",
|
assetName: "gemini.js",
|
||||||
|
...(githubInstallationToken && { githubInstallationToken }),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
run: async ({ payload, apiKey, mcpServers, githubInstallationToken, cliPath }) => {
|
run: async ({ payload, apiKey, mcpServers, githubInstallationToken, cliPath }) => {
|
||||||
|
|||||||
+41
-17
@@ -62,9 +62,9 @@ export interface InstallFromCurlParams {
|
|||||||
export interface InstallFromGithubParams {
|
export interface InstallFromGithubParams {
|
||||||
owner: string;
|
owner: string;
|
||||||
repo: string;
|
repo: string;
|
||||||
tag?: string;
|
|
||||||
assetName?: string;
|
assetName?: string;
|
||||||
executablePath?: string;
|
executablePath?: string;
|
||||||
|
githubInstallationToken?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,6 +180,36 @@ export async function installFromNpmTarball({
|
|||||||
return cliPath;
|
return cliPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch with retry logic if Retry-After header is present
|
||||||
|
*/
|
||||||
|
async function fetchWithRetry(
|
||||||
|
url: string,
|
||||||
|
headers: Record<string, string>,
|
||||||
|
errorMessage: string
|
||||||
|
): Promise<Response> {
|
||||||
|
const response = await fetch(url, { headers });
|
||||||
|
if (!response.ok) {
|
||||||
|
const retryAfter = response.headers.get("Retry-After") || response.headers.get("retry-after");
|
||||||
|
if (retryAfter) {
|
||||||
|
const waitSeconds = parseInt(retryAfter, 10);
|
||||||
|
if (!Number.isNaN(waitSeconds) && waitSeconds > 0) {
|
||||||
|
log.info(`Rate limited, waiting ${waitSeconds} seconds before retry...`);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
|
||||||
|
const retryResponse = await fetch(url, { headers });
|
||||||
|
if (!retryResponse.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`${errorMessage}: ${retryResponse.status} ${retryResponse.statusText} (retry failed)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return retryResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`${errorMessage}: ${response.status} ${response.statusText}`);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a CLI tool from GitHub releases
|
* Install a CLI tool from GitHub releases
|
||||||
* Downloads the latest release asset from GitHub and returns the path to the executable
|
* Downloads the latest release asset from GitHub and returns the path to the executable
|
||||||
@@ -188,24 +218,23 @@ export async function installFromNpmTarball({
|
|||||||
export async function installFromGithub({
|
export async function installFromGithub({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
tag,
|
|
||||||
assetName,
|
assetName,
|
||||||
executablePath,
|
executablePath,
|
||||||
|
githubInstallationToken,
|
||||||
}: InstallFromGithubParams): Promise<string> {
|
}: InstallFromGithubParams): Promise<string> {
|
||||||
log.info(`📦 Installing ${owner}/${repo} from GitHub releases...`);
|
log.info(`📦 Installing ${owner}/${repo} from GitHub releases...`);
|
||||||
|
|
||||||
// fetch release from GitHub API (specific tag or latest)
|
// fetch release from GitHub API (latest)
|
||||||
const releaseUrl = tag
|
const releaseUrl = `https://api.github.com/repos/${owner}/${repo}/releases/latest`;
|
||||||
? `https://api.github.com/repos/${owner}/${repo}/releases/tags/${tag}`
|
|
||||||
: `https://api.github.com/repos/${owner}/${repo}/releases/latest`;
|
|
||||||
log.info(`Fetching release from ${releaseUrl}...`);
|
log.info(`Fetching release from ${releaseUrl}...`);
|
||||||
const releaseResponse = await fetch(releaseUrl);
|
|
||||||
if (!releaseResponse.ok) {
|
const headers: Record<string, string> = {};
|
||||||
throw new Error(
|
if (githubInstallationToken) {
|
||||||
`Failed to fetch release: ${releaseResponse.status} ${releaseResponse.statusText}`
|
headers.Authorization = `Bearer ${githubInstallationToken}`;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const releaseResponse = await fetchWithRetry(releaseUrl, headers, "Failed to fetch release");
|
||||||
|
|
||||||
const releaseData = (await releaseResponse.json()) as {
|
const releaseData = (await releaseResponse.json()) as {
|
||||||
tag_name: string;
|
tag_name: string;
|
||||||
assets: Array<{
|
assets: Array<{
|
||||||
@@ -234,12 +263,7 @@ export async function installFromGithub({
|
|||||||
const downloadPath = join(tempDir, fileName);
|
const downloadPath = join(tempDir, fileName);
|
||||||
|
|
||||||
// download the asset
|
// download the asset
|
||||||
const assetResponse = await fetch(assetUrl);
|
const assetResponse = await fetchWithRetry(assetUrl, headers, "Failed to download asset");
|
||||||
if (!assetResponse.ok) {
|
|
||||||
throw new Error(
|
|
||||||
`Failed to download asset: ${assetResponse.status} ${assetResponse.statusText}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!assetResponse.body) throw new Error("Response body is null");
|
if (!assetResponse.body) throw new Error("Response body is null");
|
||||||
const fileStream = createWriteStream(downloadPath);
|
const fileStream = createWriteStream(downloadPath);
|
||||||
|
|||||||
@@ -300,7 +300,12 @@ function setupMcpServers(ctx: MainContext): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function installAgentCli(ctx: MainContext): Promise<void> {
|
async function installAgentCli(ctx: MainContext): Promise<void> {
|
||||||
ctx.cliPath = await ctx.agent.install();
|
// gemini is the only agent that needs githubInstallationToken for install
|
||||||
|
if (ctx.agentName === "gemini") {
|
||||||
|
ctx.cliPath = await ctx.agent.install(ctx.githubInstallationToken);
|
||||||
|
} else {
|
||||||
|
ctx.cliPath = await ctx.agent.install();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateApiKey(ctx: MainContext): void {
|
function validateApiKey(ctx: MainContext): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user