feat: add Gemini API key onboarding
This commit is contained in:
committed by
Peter Steinberger
parent
340d5d03f2
commit
302d51fd40
@@ -165,8 +165,9 @@ Options:
|
||||
- `--workspace <dir>`
|
||||
- `--non-interactive`
|
||||
- `--mode <local|remote>`
|
||||
- `--auth-choice <oauth|claude-cli|openai-codex|codex-cli|antigravity|apiKey|minimax|skip>`
|
||||
- `--auth-choice <oauth|claude-cli|openai-codex|codex-cli|antigravity|gemini-api-key|apiKey|minimax|skip>`
|
||||
- `--anthropic-api-key <key>`
|
||||
- `--gemini-api-key <key>`
|
||||
- `--gateway-port <port>`
|
||||
- `--gateway-bind <loopback|lan|tailnet|auto>`
|
||||
- `--gateway-auth <off|token|password>`
|
||||
|
||||
@@ -170,6 +170,17 @@ clawdbot onboard --non-interactive \
|
||||
|
||||
Add `--json` for a machine‑readable summary.
|
||||
|
||||
Gemini example:
|
||||
|
||||
```bash
|
||||
clawdbot onboard --non-interactive \
|
||||
--mode local \
|
||||
--auth-choice gemini-api-key \
|
||||
--gemini-api-key "$GEMINI_API_KEY" \
|
||||
--gateway-port 18789 \
|
||||
--gateway-bind loopback
|
||||
```
|
||||
|
||||
Add agent (non‑interactive) example:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -232,9 +232,10 @@ export function buildProgram() {
|
||||
.option("--mode <mode>", "Wizard mode: local|remote")
|
||||
.option(
|
||||
"--auth-choice <choice>",
|
||||
"Auth: oauth|claude-cli|openai-codex|codex-cli|antigravity|apiKey|minimax|skip",
|
||||
"Auth: oauth|claude-cli|openai-codex|codex-cli|antigravity|gemini-api-key|apiKey|minimax|skip",
|
||||
)
|
||||
.option("--anthropic-api-key <key>", "Anthropic API key")
|
||||
.option("--gemini-api-key <key>", "Gemini API key")
|
||||
.option("--gateway-port <port>", "Gateway port")
|
||||
.option("--gateway-bind <mode>", "Gateway bind: loopback|lan|tailnet|auto")
|
||||
.option("--gateway-auth <mode>", "Gateway auth: off|token|password")
|
||||
@@ -263,11 +264,13 @@ export function buildProgram() {
|
||||
| "openai-codex"
|
||||
| "codex-cli"
|
||||
| "antigravity"
|
||||
| "gemini-api-key"
|
||||
| "apiKey"
|
||||
| "minimax"
|
||||
| "skip"
|
||||
| undefined,
|
||||
anthropicApiKey: opts.anthropicApiKey as string | undefined,
|
||||
geminiApiKey: opts.geminiApiKey as string | undefined,
|
||||
gatewayPort:
|
||||
typeof opts.gatewayPort === "string"
|
||||
? Number.parseInt(opts.gatewayPort, 10)
|
||||
|
||||
@@ -85,6 +85,7 @@ export function buildAuthChoiceOptions(params: {
|
||||
value: "antigravity",
|
||||
label: "Google Antigravity (Claude Opus 4.5, Gemini 3, etc.)",
|
||||
});
|
||||
options.push({ value: "gemini-api-key", label: "Google Gemini API key" });
|
||||
options.push({ value: "apiKey", label: "Anthropic API key" });
|
||||
options.push({ value: "minimax", label: "Minimax M2.1 (LM Studio)" });
|
||||
if (params.includeSkip) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
applyMinimaxConfig,
|
||||
applyMinimaxProviderConfig,
|
||||
setAnthropicApiKey,
|
||||
setGeminiApiKey,
|
||||
writeOAuthCredentials,
|
||||
} from "./onboard-auth.js";
|
||||
import { openUrl } from "./onboard-helpers.js";
|
||||
@@ -415,6 +416,17 @@ export async function applyAuthChoice(params: {
|
||||
"OAuth help",
|
||||
);
|
||||
}
|
||||
} else if (params.authChoice === "gemini-api-key") {
|
||||
const key = await params.prompter.text({
|
||||
message: "Enter Gemini API key",
|
||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
||||
});
|
||||
await setGeminiApiKey(String(key).trim(), params.agentDir);
|
||||
nextConfig = applyAuthProfileConfig(nextConfig, {
|
||||
profileId: "google:default",
|
||||
provider: "google",
|
||||
mode: "api_key",
|
||||
});
|
||||
} else if (params.authChoice === "apiKey") {
|
||||
const key = await params.prompter.text({
|
||||
message: "Enter Anthropic API key",
|
||||
|
||||
@@ -55,6 +55,7 @@ import {
|
||||
applyAuthProfileConfig,
|
||||
applyMinimaxConfig,
|
||||
setAnthropicApiKey,
|
||||
setGeminiApiKey,
|
||||
writeOAuthCredentials,
|
||||
} from "./onboard-auth.js";
|
||||
import {
|
||||
@@ -300,6 +301,7 @@ async function promptAuthConfig(
|
||||
| "openai-codex"
|
||||
| "codex-cli"
|
||||
| "antigravity"
|
||||
| "gemini-api-key"
|
||||
| "apiKey"
|
||||
| "minimax"
|
||||
| "skip";
|
||||
@@ -513,6 +515,20 @@ async function promptAuthConfig(
|
||||
runtime.error(String(err));
|
||||
note("Trouble with OAuth? See https://docs.clawd.bot/start/faq", "OAuth");
|
||||
}
|
||||
} else if (authChoice === "gemini-api-key") {
|
||||
const key = guardCancel(
|
||||
await text({
|
||||
message: "Enter Gemini API key",
|
||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
||||
}),
|
||||
runtime,
|
||||
);
|
||||
await setGeminiApiKey(String(key).trim());
|
||||
next = applyAuthProfileConfig(next, {
|
||||
profileId: "google:default",
|
||||
provider: "google",
|
||||
mode: "api_key",
|
||||
});
|
||||
} else if (authChoice === "apiKey") {
|
||||
const key = guardCancel(
|
||||
await text({
|
||||
|
||||
@@ -33,6 +33,19 @@ export async function setAnthropicApiKey(key: string, agentDir?: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function setGeminiApiKey(key: string, agentDir?: string) {
|
||||
// Write to the multi-agent path so gateway finds credentials on startup
|
||||
upsertAuthProfile({
|
||||
profileId: "google:default",
|
||||
credential: {
|
||||
type: "api_key",
|
||||
provider: "google",
|
||||
key,
|
||||
},
|
||||
agentDir: agentDir ?? resolveDefaultAgentDir(),
|
||||
});
|
||||
}
|
||||
|
||||
export function applyAuthProfileConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
params: {
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
applyAuthProfileConfig,
|
||||
applyMinimaxConfig,
|
||||
setAnthropicApiKey,
|
||||
setGeminiApiKey,
|
||||
} from "./onboard-auth.js";
|
||||
import {
|
||||
applyWizardMetadata,
|
||||
@@ -119,6 +120,19 @@ export async function runNonInteractiveOnboarding(
|
||||
provider: "anthropic",
|
||||
mode: "api_key",
|
||||
});
|
||||
} else if (authChoice === "gemini-api-key") {
|
||||
const key = opts.geminiApiKey?.trim();
|
||||
if (!key) {
|
||||
runtime.error("Missing --gemini-api-key");
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
await setGeminiApiKey(key);
|
||||
nextConfig = applyAuthProfileConfig(nextConfig, {
|
||||
profileId: "google:default",
|
||||
provider: "google",
|
||||
mode: "api_key",
|
||||
});
|
||||
} else if (authChoice === "claude-cli") {
|
||||
const store = ensureAuthProfileStore(undefined, {
|
||||
allowKeychainPrompt: false,
|
||||
|
||||
@@ -9,6 +9,7 @@ export type AuthChoice =
|
||||
| "codex-cli"
|
||||
| "antigravity"
|
||||
| "apiKey"
|
||||
| "gemini-api-key"
|
||||
| "minimax"
|
||||
| "skip";
|
||||
export type GatewayAuthChoice = "off" | "token" | "password";
|
||||
@@ -24,6 +25,7 @@ export type OnboardOptions = {
|
||||
nonInteractive?: boolean;
|
||||
authChoice?: AuthChoice;
|
||||
anthropicApiKey?: string;
|
||||
geminiApiKey?: string;
|
||||
gatewayPort?: number;
|
||||
gatewayBind?: GatewayBind;
|
||||
gatewayAuth?: GatewayAuthChoice;
|
||||
|
||||
Reference in New Issue
Block a user