mirror of
https://github.com/hanzoai/bot.git
synced 2026-10-30 17:24:26 +00:00
The automated rebrand sed script replaced "OpenClaw" with "Hanzo Bot" (with space) instead of "HanzoBot" in 8,315 TypeScript identifier occurrences across 1,632 files. This fixes all broken class names, type names, function names, and variable names. Co-authored-by: Hanzo Dev <[email protected]>
141 lines
4.6 KiB
TypeScript
141 lines
4.6 KiB
TypeScript
import type {
|
|
HanzoBotPluginApi,
|
|
ProviderAuthContext,
|
|
ProviderFetchUsageSnapshotContext,
|
|
} from "openclaw/plugin-sdk/plugin-entry";
|
|
import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-auth";
|
|
import { fetchGeminiUsage } from "openclaw/plugin-sdk/provider-usage";
|
|
import { isModernGoogleModel, resolveGoogle31ForwardCompatModel } from "./provider-models.js";
|
|
|
|
const PROVIDER_ID = "google-gemini-cli";
|
|
const PROVIDER_LABEL = "Gemini CLI OAuth";
|
|
const DEFAULT_MODEL = "google-gemini-cli/gemini-3.1-pro-preview";
|
|
const ENV_VARS = [
|
|
"BOT_GEMINI_OAUTH_CLIENT_ID",
|
|
"BOT_GEMINI_OAUTH_CLIENT_SECRET",
|
|
"GEMINI_CLI_OAUTH_CLIENT_ID",
|
|
"GEMINI_CLI_OAUTH_CLIENT_SECRET",
|
|
];
|
|
|
|
function parseGoogleUsageToken(apiKey: string): string {
|
|
try {
|
|
const parsed = JSON.parse(apiKey) as { token?: unknown };
|
|
if (typeof parsed?.token === "string") {
|
|
return parsed.token;
|
|
}
|
|
} catch {
|
|
// ignore
|
|
}
|
|
return apiKey;
|
|
}
|
|
|
|
function formatGoogleOauthApiKey(cred: {
|
|
type?: string;
|
|
access?: string;
|
|
projectId?: string;
|
|
}): string {
|
|
if (cred.type !== "oauth" || typeof cred.access !== "string" || !cred.access.trim()) {
|
|
return "";
|
|
}
|
|
return JSON.stringify({
|
|
token: cred.access,
|
|
projectId: cred.projectId,
|
|
});
|
|
}
|
|
|
|
async function fetchGeminiCliUsage(ctx: ProviderFetchUsageSnapshotContext) {
|
|
return await fetchGeminiUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn, PROVIDER_ID);
|
|
}
|
|
|
|
export function registerGoogleGeminiCliProvider(api: HanzoBotPluginApi) {
|
|
api.registerProvider({
|
|
id: PROVIDER_ID,
|
|
label: PROVIDER_LABEL,
|
|
docsPath: "/providers/models",
|
|
aliases: ["gemini-cli"],
|
|
envVars: ENV_VARS,
|
|
auth: [
|
|
{
|
|
id: "oauth",
|
|
label: "Google OAuth",
|
|
hint: "PKCE + localhost callback",
|
|
kind: "oauth",
|
|
run: async (ctx: ProviderAuthContext) => {
|
|
await ctx.prompter.note(
|
|
[
|
|
"This is an unofficial integration and is not endorsed by Google.",
|
|
"Some users have reported account restrictions or suspensions after using third-party Gemini CLI and Antigravity OAuth clients.",
|
|
"Proceed only if you understand and accept this risk.",
|
|
].join("\n"),
|
|
"Google Gemini CLI caution",
|
|
);
|
|
|
|
const proceed = await ctx.prompter.confirm({
|
|
message: "Continue with Google Gemini CLI OAuth?",
|
|
initialValue: false,
|
|
});
|
|
if (!proceed) {
|
|
await ctx.prompter.note("Skipped Google Gemini CLI OAuth setup.", "Setup skipped");
|
|
return { profiles: [] };
|
|
}
|
|
|
|
const spin = ctx.prompter.progress("Starting Gemini CLI OAuth…");
|
|
try {
|
|
const { loginGeminiCliOAuth } = await import("./oauth.runtime.js");
|
|
const result = await loginGeminiCliOAuth({
|
|
isRemote: ctx.isRemote,
|
|
openUrl: ctx.openUrl,
|
|
log: (msg) => ctx.runtime.log(msg),
|
|
note: ctx.prompter.note,
|
|
prompt: async (message) => String(await ctx.prompter.text({ message })),
|
|
progress: spin,
|
|
});
|
|
|
|
spin.stop("Gemini CLI OAuth complete");
|
|
return buildOauthProviderAuthResult({
|
|
providerId: PROVIDER_ID,
|
|
defaultModel: DEFAULT_MODEL,
|
|
access: result.access,
|
|
refresh: result.refresh,
|
|
expires: result.expires,
|
|
email: result.email,
|
|
credentialExtra: { projectId: result.projectId },
|
|
notes: ["If requests fail, set GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID."],
|
|
});
|
|
} catch (err) {
|
|
spin.stop("Gemini CLI OAuth failed");
|
|
await ctx.prompter.note(
|
|
"Trouble with OAuth? Ensure your Google account has Gemini CLI access.",
|
|
"OAuth help",
|
|
);
|
|
throw err;
|
|
}
|
|
},
|
|
},
|
|
],
|
|
wizard: {
|
|
setup: {
|
|
choiceId: "google-gemini-cli",
|
|
choiceLabel: "Gemini CLI OAuth",
|
|
choiceHint: "Google OAuth with project-aware token payload",
|
|
methodId: "oauth",
|
|
},
|
|
},
|
|
resolveDynamicModel: (ctx) =>
|
|
resolveGoogle31ForwardCompatModel({ providerId: PROVIDER_ID, ctx }),
|
|
isModernModelRef: ({ modelId }) => isModernGoogleModel(modelId),
|
|
formatApiKey: (cred) => formatGoogleOauthApiKey(cred),
|
|
resolveUsageAuth: async (ctx) => {
|
|
const auth = await ctx.resolveOAuthToken();
|
|
if (!auth) {
|
|
return null;
|
|
}
|
|
return {
|
|
...auth,
|
|
token: parseGoogleUsageToken(auth.token),
|
|
};
|
|
},
|
|
fetchUsageSnapshot: async (ctx) => await fetchGeminiCliUsage(ctx),
|
|
});
|
|
}
|