feat(skills): add agent-browser option for browser automation (#1090)
Add configurable browser automation allowing users to choose between Playwright MCP (default) and Vercel's agent-browser CLI. Changes: - Add browser_automation_engine.provider config option - Dynamic skill loading based on provider selection - Comprehensive agent-browser CLI reference (inline in skills.ts) - Propagate browserProvider to delegate_task and buildAgent - Update documentation with provider comparison Co-authored-by: Suyeol Jeon <devxoul@gmail.com> Co-authored-by: YeonGyu Kim <code.yeongyu@gmail.com>
This commit is contained in:
@@ -3,24 +3,27 @@ import { discoverSkills } from "./loader"
|
||||
import type { LoadedSkill } from "./types"
|
||||
import { parseFrontmatter } from "../../shared/frontmatter"
|
||||
import { readFileSync } from "node:fs"
|
||||
import type { GitMasterConfig } from "../../config/schema"
|
||||
import type { GitMasterConfig, BrowserAutomationProvider } from "../../config/schema"
|
||||
|
||||
export interface SkillResolutionOptions {
|
||||
gitMasterConfig?: GitMasterConfig
|
||||
browserProvider?: BrowserAutomationProvider
|
||||
}
|
||||
|
||||
let cachedSkills: LoadedSkill[] | null = null
|
||||
const cachedSkillsByProvider = new Map<string, LoadedSkill[]>()
|
||||
|
||||
function clearSkillCache(): void {
|
||||
cachedSkills = null
|
||||
cachedSkillsByProvider.clear()
|
||||
}
|
||||
|
||||
async function getAllSkills(): Promise<LoadedSkill[]> {
|
||||
if (cachedSkills) return cachedSkills
|
||||
async function getAllSkills(options?: SkillResolutionOptions): Promise<LoadedSkill[]> {
|
||||
const cacheKey = options?.browserProvider ?? "playwright"
|
||||
const cached = cachedSkillsByProvider.get(cacheKey)
|
||||
if (cached) return cached
|
||||
|
||||
const [discoveredSkills, builtinSkillDefs] = await Promise.all([
|
||||
discoverSkills({ includeClaudeCodePaths: true }),
|
||||
Promise.resolve(createBuiltinSkills()),
|
||||
Promise.resolve(createBuiltinSkills({ browserProvider: options?.browserProvider })),
|
||||
])
|
||||
|
||||
const builtinSkillsAsLoaded: LoadedSkill[] = builtinSkillDefs.map((skill) => ({
|
||||
@@ -44,8 +47,9 @@ async function getAllSkills(): Promise<LoadedSkill[]> {
|
||||
const discoveredNames = new Set(discoveredSkills.map((s) => s.name))
|
||||
const uniqueBuiltins = builtinSkillsAsLoaded.filter((s) => !discoveredNames.has(s.name))
|
||||
|
||||
cachedSkills = [...discoveredSkills, ...uniqueBuiltins]
|
||||
return cachedSkills
|
||||
const allSkills = [...discoveredSkills, ...uniqueBuiltins]
|
||||
cachedSkillsByProvider.set(cacheKey, allSkills)
|
||||
return allSkills
|
||||
}
|
||||
|
||||
async function extractSkillTemplate(skill: LoadedSkill): Promise<string> {
|
||||
@@ -118,7 +122,7 @@ export function injectGitMasterConfig(template: string, config?: GitMasterConfig
|
||||
}
|
||||
|
||||
export function resolveSkillContent(skillName: string, options?: SkillResolutionOptions): string | null {
|
||||
const skills = createBuiltinSkills()
|
||||
const skills = createBuiltinSkills({ browserProvider: options?.browserProvider })
|
||||
const skill = skills.find((s) => s.name === skillName)
|
||||
if (!skill) return null
|
||||
|
||||
@@ -133,7 +137,7 @@ export function resolveMultipleSkills(skillNames: string[], options?: SkillResol
|
||||
resolved: Map<string, string>
|
||||
notFound: string[]
|
||||
} {
|
||||
const skills = createBuiltinSkills()
|
||||
const skills = createBuiltinSkills({ browserProvider: options?.browserProvider })
|
||||
const skillMap = new Map(skills.map((s) => [s.name, s.template]))
|
||||
|
||||
const resolved = new Map<string, string>()
|
||||
@@ -159,7 +163,7 @@ export async function resolveSkillContentAsync(
|
||||
skillName: string,
|
||||
options?: SkillResolutionOptions
|
||||
): Promise<string | null> {
|
||||
const allSkills = await getAllSkills()
|
||||
const allSkills = await getAllSkills(options)
|
||||
const skill = allSkills.find((s) => s.name === skillName)
|
||||
if (!skill) return null
|
||||
|
||||
@@ -179,7 +183,7 @@ export async function resolveMultipleSkillsAsync(
|
||||
resolved: Map<string, string>
|
||||
notFound: string[]
|
||||
}> {
|
||||
const allSkills = await getAllSkills()
|
||||
const allSkills = await getAllSkills(options)
|
||||
const skillMap = new Map<string, LoadedSkill>()
|
||||
for (const skill of allSkills) {
|
||||
skillMap.set(skill.name, skill)
|
||||
|
||||
Reference in New Issue
Block a user