Playwright で取得したスクリーンショットと、Computer Use で使用する座標のマッピング:
interface BoundingBox { x: number; y: number; width: number; height: number;}async function getElementCoordinates(selector: string): Promise<[number, number]> { const box = await page.locator(selector).boundingBox(); if (!box) { throw new Error(`Element not found: ${selector}`); } // ボックスの中心座標 const x = Math.round(box.x + box.width / 2); const y = Math.round(box.y + box.height / 2); return [x, y];}async function fillFormField(selector: string, value: string): Promise<void> { await page.locator(selector).fill(value); // 入力後のバリデーションイベント待機 await page.waitForTimeout(500);}async function clickButton(selector: string): Promise<void> { await page.locator(selector).click(); // ナビゲーション完了待機 await page.waitForNavigation({ waitUntil: "networkidle" });}
エンタープライズユースケース
ユースケース 1:経費精算フロー自動化
従業員の経費報告書を自動で生成・提出するシステム:
interface ExpenseReport { employeeId: string; date: string; items: { description: string; amount: number; category: string; }[]; totalAmount: number;}async function automateExpenseSubmission(report: ExpenseReport): Promise<void> { console.log(`Processing expense report for employee ${report.employeeId}`); const instruction = `You are an enterprise automation agent. Complete the following task:1. Navigate to the expense reporting system at https://expenses.company.internal/2. Log in with the provided credentials (use environment variables EXPENSE_USER and EXPENSE_PASS)3. Click "New Expense Report"4. Fill in the following details: - Employee ID: ${report.employeeId} - Report Date: ${report.date}5. For each of the following expense items, add a row:${report.items .map( (item) => ` - Description: ${item.description}, Amount: ${item.amount}, Category: ${item.category}` ) .join("\n")}6. Verify the total matches ${report.totalAmount}7. Click "Submit for Approval"8. Confirm submission and take a final screenshotAfter completing each step, explain what you've done and any observations. `; const result = await executeComputerUseAgent(instruction); console.log("Automation result:", result);}// 使用例const testReport: ExpenseReport = { employeeId: "EMP12345", date: "2026-03-30", items: [ { description: "Client meeting lunch", amount: 45.50, category: "meals" }, { description: "Flight to NYC", amount: 350.00, category: "travel" }, { description: "Hotel 2 nights", amount: 280.00, category: "lodging" } ], totalAmount: 675.50};await automateExpenseSubmission(testReport);
ユースケース 2:Webダッシュボードからのデータ収集
複数のデータソースから情報を自動収集し、統合レポートを生成:
interface DataCollectionTask { sourceUrl: string; dataPoints: { name: string; selector: string; }[];}async function collectDashboardData(tasks: DataCollectionTask[]): Promise<Record<string, any>> { const collectedData: Record<string, any> = {}; for (const task of tasks) { console.log(`Collecting data from ${task.sourceUrl}`); const instruction = `You are a data collection agent. Complete this task:1. Navigate to: ${task.sourceUrl}2. Take a screenshot to see the current page3. Locate and extract the following data points:${task.dataPoints.map((point) => ` - ${point.name}: Use selector "${point.selector}" if available`).join("\n")}4. If any data point requires scrolling or clicking to reveal, do so5. Return the extracted data in JSON format with keys matching the data point namesEnsure all values are accurate and handle any authentication popups that may appear. `; const result = await executeComputerUseAgent(instruction); // 結果をパース(モデルが JSON 形式で返すことを期待) const jsonMatch = result.match(/\{[\s\S]*\}/); if (jsonMatch) { collectedData[task.sourceUrl] = JSON.parse(jsonMatch[0]); } } return collectedData;}// 使用例const dashboardTasks: DataCollectionTask[] = [ { sourceUrl: "https://analytics.example.com/dashboard", dataPoints: [ { name: "totalRevenue", selector: ".revenue-metric" }, { name: "activeUsers", selector: ".users-metric" }, { name: "conversionRate", selector: ".conversion-metric" } ] }];const data = await collectDashboardData(dashboardTasks);console.log("Collected data:", data);
ユースケース 3:UI テストの自動化
ビジネスロジックの変更時に自動でUI テストを実行:
interface UITestCase { name: string; steps: { action: "click" | "type" | "navigate" | "assert"; target?: string; value?: string; expectedText?: string; }[];}async function runUITest(testCase: UITestCase): Promise<boolean> { console.log(`Running test: ${testCase.name}`); const stepsDescription = testCase.steps .map((step, index) => { switch (step.action) { case "navigate": return `${index + 1}. Navigate to: ${step.target}`; case "click": return `${index + 1}. Click on element: ${step.target}`; case "type": return `${index + 1}. Type "${step.value}" into: ${step.target}`; case "assert": return `${index + 1}. Verify text "${step.expectedText}" appears on the page`; default: return `${index + 1}. Unknown action`; } }) .join("\n"); const instruction = `You are a UI testing agent. Execute the following test case and verify each step:Test: ${testCase.name}Steps to execute:${stepsDescription}After each step, take a screenshot and verify the expected outcome.If any step fails, explain what went wrong.At the end, provide a PASS or FAIL result. `; const result = await executeComputerUseAgent(instruction); // PASS/FAIL を判定 const passed = result.toLowerCase().includes("pass"); return passed;}// 使用例const testCases: UITestCase[] = [ { name: "User Login Flow", steps: [ { action: "navigate", target: "https://app.example.com/login" }, { action: "type", target: "#email-input", value: "test@example.com" }, { action: "type", target: "#password-input", value: "password123" }, { action: "click", target: "#login-button" }, { action: "assert", expectedText: "Welcome to Dashboard" } ] }, { name: "Create New Project", steps: [ { action: "click", target: "#new-project-btn" }, { action: "type", target: "#project-name", value: "Test Project" }, { action: "type", target: "#project-description", value: "A test project" }, { action: "click", target: "#create-btn" }, { action: "assert", expectedText: "Project created successfully" } ] }];for (const test of testCases) { const passed = await runUITest(test); console.log(`${test.name}: ${passed ? "✓ PASS" : "✗ FAIL"}`);}