Repository: microsoft/playwright
File: packages/playwright/src/agents/generateAgents.ts (TypeScript)

Code before:
          tools[tool] = true;
      } else {
        tools[`${first}*${second}`] = true;
      }
    };

    const result: Record<string, any> = {};
    result['$schema'] = 'https://opencode.ai/config.json';
    result['mcp'] = {};
    result['tools'] = {
      'playwright*': false,
    };
    result['agent'] = {};
    for (const agent of agents) {
      const tools: Record<string, boolean> = {};
      result['agent'][agent.name] = {
        description: agent.description,
        mode: 'subagent',
        prompt: `{file:.opencode/prompts/${agent.name}.md}`,
        tools,
      };
      for (const tool of agent.tools)
        asOpencodeTool(tools, tool);
    }

    const { command, args } = npxCommand(['playwright', 'run-test-mcp-server']);
    result['mcp']['playwright-test'] = {
      type: 'local',
      command: [command, ...args],
      enabled: true,
    };

    return JSON.stringify(result, null, 2);
  }
}
export class CopilotGenerator {
  static async init(config: FullConfigInternal, projectName: string, prompts: boolean) {

    await initRepo(config, projectName, {
      defaultAgentName: 'agent',
      promptsFolder: prompts ? '.github/prompts' : undefined,
      promptSuffix: 'prompt'
    });

    const agents = await loadAgentSpecs();

    await fs.promises.mkdir('.github/agents', { recursive: true });
    for (const agent of agents)
      await writeFile(`.github/agents/${agent.name}.agent.md`, CopilotGenerator.agentSpec(agent), '🤖', 'agent definition');

    await deleteFile(`.github/chatmodes/ 🎭 planner.chatmode.md`, 'legacy planner chatmode');

Review comment (refactor):
opencode seems to spawn a shell, so we should also pick 'npx' here. maybe let's not use the abstraction?

Code after:
      } else {
        tools[`${first}*${second}`] = true;
      }
    };

    const result: Record<string, any> = {};
    result['$schema'] = 'https://opencode.ai/config.json';
    result['mcp'] = {};
    result['tools'] = {
      'playwright*': false,
    };
    result['agent'] = {};
    for (const agent of agents) {
      const tools: Record<string, boolean> = {};
      result['agent'][agent.name] = {
        description: agent.description,
        mode: 'subagent',
        prompt: `{file:.opencode/prompts/${agent.name}.md}`,
        tools,
      };
      for (const tool of agent.tools)
        asOpencodeTool(tools, tool);
    }

    result['mcp']['playwright-test'] = {
      type: 'local',
      command: ['npx', 'playwright', 'run-test-mcp-server'],
      enabled: true,
    };

    return JSON.stringify(result, null, 2);
  }
}
export class CopilotGenerator {
  static async init(config: FullConfigInternal, projectName: string, prompts: boolean) {

    await initRepo(config, projectName, {
      defaultAgentName: 'agent',
      promptsFolder: prompts ? '.github/prompts' : undefined,
      promptSuffix: 'prompt'
    });

    const agents = await loadAgentSpecs();

    await fs.promises.mkdir('.github/agents', { recursive: true });
    for (const agent of agents)
      await writeFile(`.github/agents/${agent.name}.agent.md`, CopilotGenerator.agentSpec(agent), '🤖', 'agent definition');

    await deleteFile(`.github/chatmodes/ 🎭 planner.chatmode.md`, 'legacy planner chatmode');
    await deleteFile(`.github/chatmodes/🎭 generator.chatmode.md`, 'legacy generator chatmode');
    await deleteFile(`.github/chatmodes/🎭 healer.chatmode.md`, 'legacy healer chatmode');