feat(builtin-skills): add playwright skill with MCP config and disabled_skills option

- Add playwright as builtin skill with MCP server configuration
- Add disabled_skills config option to disable specific builtin skills
- Update BuiltinSkill type to include mcpConfig field
- Update skill merger to handle mcpConfig from builtin to loaded skills
- Merge disabled_skills config and filter unavailable builtin skills at plugin init
- Update README with Built-in Skills documentation
- Regenerate JSON schema

🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-01-02 00:01:44 +09:00
parent bd05f5b434
commit b0c39e222a
7 changed files with 62 additions and 4 deletions

View File

@@ -846,6 +846,22 @@ Or disable via `disabled_agents` in `~/.config/opencode/oh-my-opencode.json` or
Available agents: `oracle`, `librarian`, `explore`, `frontend-ui-ux-engineer`, `document-writer`, `multimodal-looker` Available agents: `oracle`, `librarian`, `explore`, `frontend-ui-ux-engineer`, `document-writer`, `multimodal-looker`
### Built-in Skills
Oh My OpenCode includes built-in skills that provide additional capabilities:
- **playwright**: Browser automation with Playwright MCP. Use for web scraping, testing, screenshots, and browser interactions.
Disable built-in skills via `disabled_skills` in `~/.config/opencode/oh-my-opencode.json` or `.opencode/oh-my-opencode.json`:
```json
{
"disabled_skills": ["playwright"]
}
```
Available built-in skills: `playwright`
### Sisyphus Agent ### Sisyphus Agent
When enabled (default), Sisyphus provides a powerful orchestrator with optional specialized agents: When enabled (default), Sisyphus provides a powerful orchestrator with optional specialized agents:

View File

@@ -34,6 +34,15 @@
] ]
} }
}, },
"disabled_skills": {
"type": "array",
"items": {
"type": "string",
"enum": [
"playwright"
]
}
},
"disabled_hooks": { "disabled_hooks": {
"type": "array", "type": "array",
"items": { "items": {

View File

@@ -26,6 +26,10 @@ export const BuiltinAgentNameSchema = z.enum([
"multimodal-looker", "multimodal-looker",
]) ])
export const BuiltinSkillNameSchema = z.enum([
"playwright",
])
export const OverridableAgentNameSchema = z.enum([ export const OverridableAgentNameSchema = z.enum([
"build", "build",
"plan", "plan",
@@ -231,6 +235,7 @@ export const OhMyOpenCodeConfigSchema = z.object({
$schema: z.string().optional(), $schema: z.string().optional(),
disabled_mcps: z.array(McpNameSchema).optional(), disabled_mcps: z.array(McpNameSchema).optional(),
disabled_agents: z.array(BuiltinAgentNameSchema).optional(), disabled_agents: z.array(BuiltinAgentNameSchema).optional(),
disabled_skills: z.array(BuiltinSkillNameSchema).optional(),
disabled_hooks: z.array(HookNameSchema).optional(), disabled_hooks: z.array(HookNameSchema).optional(),
disabled_commands: z.array(BuiltinCommandNameSchema).optional(), disabled_commands: z.array(BuiltinCommandNameSchema).optional(),
agents: AgentOverridesSchema.optional(), agents: AgentOverridesSchema.optional(),
@@ -250,6 +255,7 @@ export type AgentOverrides = z.infer<typeof AgentOverridesSchema>
export type AgentName = z.infer<typeof AgentNameSchema> export type AgentName = z.infer<typeof AgentNameSchema>
export type HookName = z.infer<typeof HookNameSchema> export type HookName = z.infer<typeof HookNameSchema>
export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema> export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>
export type BuiltinSkillName = z.infer<typeof BuiltinSkillNameSchema>
export type SisyphusAgentConfig = z.infer<typeof SisyphusAgentConfigSchema> export type SisyphusAgentConfig = z.infer<typeof SisyphusAgentConfigSchema>
export type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema> export type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema>
export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema> export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>

View File

@@ -1,5 +1,19 @@
import type { BuiltinSkill } from "./types" import type { BuiltinSkill } from "./types"
export function createBuiltinSkills(): BuiltinSkill[] { const playwrightSkill: BuiltinSkill = {
return [] name: "playwright",
description: "Browser automation with Playwright MCP. Use for web scraping, testing, screenshots, and browser interactions.",
template: `# Playwright Browser Automation
This skill provides browser automation capabilities via the Playwright MCP server.`,
mcpConfig: {
playwright: {
command: "npx",
args: ["@playwright/mcp@latest"],
},
},
}
export function createBuiltinSkills(): BuiltinSkill[] {
return [playwrightSkill]
} }

View File

@@ -1,3 +1,5 @@
import type { SkillMcpConfig } from "../skill-mcp-manager/types"
export interface BuiltinSkill { export interface BuiltinSkill {
name: string name: string
description: string description: string
@@ -10,4 +12,5 @@ export interface BuiltinSkill {
model?: string model?: string
subtask?: boolean subtask?: boolean
argumentHint?: string argumentHint?: string
mcpConfig?: SkillMcpConfig
} }

View File

@@ -21,7 +21,7 @@ const SCOPE_PRIORITY: Record<SkillScope, number> = {
function builtinToLoaded(builtin: BuiltinSkill): LoadedSkill { function builtinToLoaded(builtin: BuiltinSkill): LoadedSkill {
const definition: CommandDefinition = { const definition: CommandDefinition = {
name: builtin.name, name: builtin.name,
description: `(builtin - Skill) ${builtin.description}`, description: `(opencode - Skill) ${builtin.description}`,
template: builtin.template, template: builtin.template,
model: builtin.model, model: builtin.model,
agent: builtin.agent, agent: builtin.agent,
@@ -37,6 +37,7 @@ function builtinToLoaded(builtin: BuiltinSkill): LoadedSkill {
compatibility: builtin.compatibility, compatibility: builtin.compatibility,
metadata: builtin.metadata as Record<string, string> | undefined, metadata: builtin.metadata as Record<string, string> | undefined,
allowedTools: builtin.allowedTools, allowedTools: builtin.allowedTools,
mcpConfig: builtin.mcpConfig,
} }
} }

View File

@@ -128,6 +128,12 @@ function mergeConfigs(
...(override.disabled_commands ?? []), ...(override.disabled_commands ?? []),
]), ]),
], ],
disabled_skills: [
...new Set([
...(base.disabled_skills ?? []),
...(override.disabled_skills ?? []),
]),
],
claude_code: deepMerge(base.claude_code, override.claude_code), claude_code: deepMerge(base.claude_code, override.claude_code),
}; };
} }
@@ -283,7 +289,10 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const callOmoAgent = createCallOmoAgent(ctx, backgroundManager); const callOmoAgent = createCallOmoAgent(ctx, backgroundManager);
const lookAt = createLookAt(ctx); const lookAt = createLookAt(ctx);
const builtinSkills = createBuiltinSkills(); const disabledSkills = new Set(pluginConfig.disabled_skills ?? []);
const builtinSkills = createBuiltinSkills().filter(
(skill) => !disabledSkills.has(skill.name as any)
);
const includeClaudeSkills = pluginConfig.claude_code?.skills !== false; const includeClaudeSkills = pluginConfig.claude_code?.skills !== false;
const mergedSkills = mergeSkills( const mergedSkills = mergeSkills(
builtinSkills, builtinSkills,