Skip to content

Commit 5e6c10c

Browse files
committed
prefer gemini over gpt
1 parent 7f2fffa commit 5e6c10c

2 files changed

Lines changed: 48 additions & 49 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ browser-agent-cli replay ./yc.plan.json --ai-fallback
115115
browser-agent-cli replay ./yc.plan.json --url https://staging.example.com/
116116
```
117117

118-
LLM auto-detected from `OPENAI_API_KEY``GOOGLE_API_KEY` / `GEMINI_API_KEY``ANTHROPIC_API_KEY`. Override the model with `--llm-model` or `OPENAI_MODEL` / `GEMINI_MODEL` / `ANTHROPIC_MODEL`. `replay` only needs an LLM with `--ai-fallback`. Interactive: `ctrl+p` pause, `ctrl+r` resume.
118+
LLM auto-detected from `GOOGLE_API_KEY` / `GEMINI_API_KEY``OPENAI_API_KEY``ANTHROPIC_API_KEY`. Override the model with `--llm-model` or `GEMINI_MODEL` / `OPENAI_MODEL` / `ANTHROPIC_MODEL`. `replay` only needs an LLM with `--ai-fallback`. Interactive: `ctrl+p` pause, `ctrl+r` resume.
119119

120120
## Browser providers
121121

src/cli/index.ts

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { BrowserAgentError } from "@/agent/error";
3333
*/
3434
async function loadProvider<T>(
3535
packageName: string,
36-
providerLabel: string
36+
providerLabel: string,
3737
): Promise<T> {
3838
try {
3939
return (await import(packageName)) as T;
@@ -45,8 +45,8 @@ async function loadProvider<T>(
4545
chalk.red(
4646
`${providerLabel} provider is not installed.\n` +
4747
`Install it and retry:\n\n` +
48-
` npm install -g ${packageName}\n`
49-
)
48+
` npm install -g ${packageName}\n`,
49+
),
5050
);
5151
process.exit(1);
5252
}
@@ -56,21 +56,11 @@ async function loadProvider<T>(
5656

5757
/**
5858
* Select an LLM based on environment variables. Providers are checked in
59-
* priority order: OpenAI, Google, Anthropic. Per-provider model is
59+
* priority order: Google, OpenAI, Anthropic. Per-provider model is
6060
* configurable via `*_MODEL` env vars. Dynamic imports keep unused provider
6161
* SDKs out of the CLI startup path.
6262
*/
6363
async function createDefaultLlm(): Promise<BaseChatModel | undefined> {
64-
if (process.env.OPENAI_API_KEY) {
65-
const { ChatOpenAI } = await loadProvider<
66-
typeof import("@langchain/openai")
67-
>("@langchain/openai", "OpenAI");
68-
return new ChatOpenAI({
69-
apiKey: process.env.OPENAI_API_KEY,
70-
model: process.env.OPENAI_MODEL ?? "gpt-4.1-mini",
71-
temperature: 0,
72-
}) as unknown as BaseChatModel;
73-
}
7464
if (process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY) {
7565
const { ChatGoogleGenerativeAI } = await loadProvider<
7666
typeof import("@langchain/google-genai")
@@ -81,14 +71,23 @@ async function createDefaultLlm(): Promise<BaseChatModel | undefined> {
8171
temperature: 0,
8272
}) as unknown as BaseChatModel;
8373
}
74+
if (process.env.OPENAI_API_KEY) {
75+
const { ChatOpenAI } = await loadProvider<
76+
typeof import("@langchain/openai")
77+
>("@langchain/openai", "OpenAI");
78+
return new ChatOpenAI({
79+
apiKey: process.env.OPENAI_API_KEY,
80+
model: process.env.OPENAI_MODEL ?? "gpt-4.1-mini",
81+
temperature: 0,
82+
}) as unknown as BaseChatModel;
83+
}
8484
if (process.env.ANTHROPIC_API_KEY) {
8585
const { ChatAnthropic } = await loadProvider<
8686
typeof import("@langchain/anthropic")
8787
>("@langchain/anthropic", "Anthropic");
8888
return new ChatAnthropic({
8989
apiKey: process.env.ANTHROPIC_API_KEY,
90-
model:
91-
process.env.ANTHROPIC_MODEL ?? "claude-3-5-sonnet-20241022",
90+
model: process.env.ANTHROPIC_MODEL ?? "claude-3-5-sonnet-20241022",
9291
temperature: 0,
9392
}) as unknown as BaseChatModel;
9493
}
@@ -112,11 +111,11 @@ program
112111
.option("-f, --file <file path>", "Path to a file containing a command")
113112
.option(
114113
"-s, --save-plan <file path>",
115-
"Persist the recorded plan to <file path> on task completion for later replay"
114+
"Persist the recorded plan to <file path> on task completion for later replay",
116115
)
117116
.option(
118117
"--llm-model <model>",
119-
"Override the LLM model (applied to whichever provider is auto-detected from env vars)"
118+
"Override the LLM model (applied to whichever provider is auto-detected from env vars)",
120119
)
121120
.action(async function () {
122121
const options = this.opts();
@@ -128,13 +127,14 @@ program
128127

129128
console.log(chalk.blue("BrowserAgent CLI"));
130129
currentSpinner.info(
131-
`Pause using ${chalk.bold("ctrl + p")} and resume using ${chalk.bold("ctrl + r")}\n`
130+
`Pause using ${chalk.bold("ctrl + p")} and resume using ${chalk.bold("ctrl + r")}\n`,
132131
);
133132

134133
if (llmModelOverride) {
135-
if (process.env.OPENAI_API_KEY) process.env.OPENAI_MODEL = llmModelOverride;
136-
else if (process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY)
134+
if (process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY)
137135
process.env.GEMINI_MODEL = llmModelOverride;
136+
else if (process.env.OPENAI_API_KEY)
137+
process.env.OPENAI_MODEL = llmModelOverride;
138138
else if (process.env.ANTHROPIC_API_KEY)
139139
process.env.ANTHROPIC_MODEL = llmModelOverride;
140140
}
@@ -143,8 +143,8 @@ program
143143
if (!llm) {
144144
console.error(
145145
chalk.red(
146-
"No LLM provider configured. Set one of OPENAI_API_KEY, GOOGLE_API_KEY (or GEMINI_API_KEY), or ANTHROPIC_API_KEY."
147-
)
146+
"No LLM provider configured. Set one of GOOGLE_API_KEY (or GEMINI_API_KEY), OPENAI_API_KEY, or ANTHROPIC_API_KEY.",
147+
),
148148
);
149149
process.exit(1);
150150
}
@@ -181,8 +181,8 @@ program
181181
} else if (kind === "password") {
182182
console.warn(
183183
chalk.red(
184-
"Providing passwords to LLMs can be dangerous. Passwords are passed in plain-text to the LLM and can be read by other people."
185-
)
184+
"Providing passwords to LLMs can be dangerous. Passwords are passed in plain-text to the LLM and can be read by other people.",
185+
),
186186
);
187187
const response = await inquirer.password({
188188
message,
@@ -215,7 +215,7 @@ program
215215
} finally {
216216
currentSpinner.start(currentText);
217217
}
218-
}
218+
},
219219
),
220220
],
221221
});
@@ -231,8 +231,8 @@ program
231231
}
232232
currentSpinner.start(
233233
chalk.blue(
234-
"BrowserAgent will pause after completing this operation. Press Ctrl+r again to resume."
235-
)
234+
"BrowserAgent will pause after completing this operation. Press Ctrl+r again to resume.",
235+
),
236236
);
237237
currentSpinner.stopAndPersist({ symbol: "⏸" });
238238
currentSpinner = ora();
@@ -272,19 +272,19 @@ program
272272
(output, action) => ({
273273
output,
274274
action,
275-
})
275+
}),
276276
);
277277

278278
const actions = actionsList
279279
.map((action, index, array) =>
280280
index < array.length - 1
281281
? ` ├── [${action.output.success ? chalk.yellow(action.action.type) : chalk.red(action.action.type)}] ${action.output.success ? agent.pprintAction(action.action as ActionType) : chalk.red(action.output.message)}`
282-
: ` └── [${action.output.success ? chalk.yellow(action.action.type) : chalk.red(action.action.type)}] ${action.output.success ? agent.pprintAction(action.action as ActionType) : chalk.red(action.output.message)}`
282+
: ` └── [${action.output.success ? chalk.yellow(action.action.type) : chalk.red(action.action.type)}] ${action.output.success ? agent.pprintAction(action.action as ActionType) : chalk.red(action.output.message)}`,
283283
)
284284
.join("\n");
285285

286286
currentSpinner.succeed(
287-
`[${chalk.yellow("task")}]: ${params.agentOutput.nextGoal}\n${actions}`
287+
`[${chalk.yellow("task")}]: ${params.agentOutput.nextGoal}\n${actions}`,
288288
);
289289
currentSpinner = ora();
290290
process.stdin.setRawMode(true);
@@ -295,10 +295,10 @@ program
295295
const actions = params.actions.map((action, index, array) =>
296296
index < array.length - 1
297297
? ` ├── [${chalk.yellow(action.type)}] ${agent.pprintAction(action as ActionType)}`
298-
: ` └── [${chalk.yellow(action.type)}] ${agent.pprintAction(action as ActionType)}`
298+
: ` └── [${chalk.yellow(action.type)}] ${agent.pprintAction(action as ActionType)}`,
299299
);
300300
currentSpinner.start(
301-
`[${chalk.yellow("task")}]: ${params.nextGoal}\n${actions.join("\n")}`
301+
`[${chalk.yellow("task")}]: ${params.nextGoal}\n${actions.join("\n")}`,
302302
);
303303
process.stdin.setRawMode(true);
304304
process.stdin.resume();
@@ -312,19 +312,17 @@ program
312312
float: "center",
313313
padding: 1,
314314
margin: { top: 2, left: 0, right: 0, bottom: 0 },
315-
})
315+
}),
316316
);
317317
if (savePlanPath && taskDescription) {
318318
try {
319319
await agent.savePlan(taskDescription, params, savePlanPath);
320-
console.log(
321-
chalk.green(`\nSaved plan to ${savePlanPath}`)
322-
);
320+
console.log(chalk.green(`\nSaved plan to ${savePlanPath}`));
323321
} catch (err) {
324322
console.log(
325323
chalk.red(
326-
`\nFailed to save plan: ${err instanceof Error ? err.message : String(err)}`
327-
)
324+
`\nFailed to save plan: ${err instanceof Error ? err.message : String(err)}`,
325+
),
328326
);
329327
}
330328
}
@@ -396,15 +394,18 @@ program
396394
program
397395
.command("replay")
398396
.description("Replay a saved plan without calling the LLM")
399-
.argument("<file>", "Path to a plan JSON file previously saved with --save-plan")
397+
.argument(
398+
"<file>",
399+
"Path to a plan JSON file previously saved with --save-plan",
400+
)
400401
.option("-d, --debug", "Enable debug mode")
401402
.option(
402403
"--ai-fallback",
403-
"Fall back to .ai() for individual steps that fail (requires an LLM to be configured)"
404+
"Fall back to .ai() for individual steps that fail (requires an LLM to be configured)",
404405
)
405406
.option(
406407
"-u, --url <url>",
407-
"Starting URL to navigate to before running the plan (overrides the plan's recorded startingUrl)"
408+
"Starting URL to navigate to before running the plan (overrides the plan's recorded startingUrl)",
408409
)
409410
.action(async function (file: string) {
410411
const options = this.opts();
@@ -420,8 +421,8 @@ program
420421
if (aiFallback && !llm) {
421422
console.error(
422423
chalk.red(
423-
"--ai-fallback requires an LLM. Set one of OPENAI_API_KEY, GOOGLE_API_KEY (or GEMINI_API_KEY), or ANTHROPIC_API_KEY."
424-
)
424+
"--ai-fallback requires an LLM. Set one of GOOGLE_API_KEY (or GEMINI_API_KEY), OPENAI_API_KEY, or ANTHROPIC_API_KEY.",
425+
),
425426
);
426427
process.exit(1);
427428
}
@@ -445,14 +446,12 @@ program
445446
params: action.params as object,
446447
});
447448
spinner.succeed(
448-
`[${chalk.yellow(action.type)}] ${label || output.message}`
449+
`[${chalk.yellow(action.type)}] ${label || output.message}`,
449450
);
450451
spinner.start("Continuing replay...");
451452
},
452453
onError: (action, err) => {
453-
spinner.fail(
454-
`[${chalk.red(action.type)}] ${err.message}`
455-
);
454+
spinner.fail(`[${chalk.red(action.type)}] ${err.message}`);
456455
return "abort";
457456
},
458457
});

0 commit comments

Comments
 (0)