import { z } from 'zod';
import { startWda } from '../executor/wda-runner.js';
import { WdaStartError } from '../types/wda.js';
export const wdaStartSchema = z.object({
device: z
.string()
.describe('Device name (e.g., "iPhone 16 Pro") or UDID. Device must be booted.'),
project_path: z
.string()
.optional()
.describe('Path to WebDriverAgent.xcodeproj (default: ~/Projects/WebDriverAgent/WebDriverAgent.xcodeproj)'),
scheme: z
.string()
.optional()
.describe('Xcode scheme to run (default: WebDriverAgentRunner)'),
port: z
.number()
.optional()
.describe('WDA server port (default: 8100)'),
timeout: z
.number()
.optional()
.describe('Timeout in seconds to wait for WDA to be ready (default: 180)'),
force: z
.boolean()
.optional()
.describe('Kill existing WDA on the port before starting (default: false)'),
});
export type WdaStartInput = z.infer<typeof wdaStartSchema>;
export const wdaStartTool = {
name: 'wda_start',
description:
'Start WebDriverAgent on a simulator and wait until the HTTP server is ready. ' +
'This builds and runs WDA in the background, returning when the server is accepting connections. ' +
'Use wda_stop to terminate the server when done.',
inputSchema: wdaStartSchema,
handler: async (input: WdaStartInput) => {
try {
const result = await startWda({
device: input.device,
projectPath: input.project_path,
scheme: input.scheme,
port: input.port,
timeout: input.timeout,
force: input.force,
});
const lines = [
'WebDriverAgent started successfully',
'',
`URL: ${result.url}`,
`Device: ${result.deviceName} (${result.device})`,
`Startup time: ${result.startupTime.toFixed(1)}s`,
'',
'Ready for automation.',
];
return {
content: [
{
type: 'text' as const,
text: lines.join('\n'),
},
],
};
} catch (error) {
if (error instanceof WdaStartError) {
const lines = [
`WebDriverAgent failed to start (${error.phase})`,
'',
error.message,
];
if (error.output) {
// Include last 50 lines of output for debugging
const outputLines = error.output.split('\n');
const lastLines = outputLines.slice(-50);
if (lastLines.length > 0) {
lines.push('', 'Last output:', '---', ...lastLines);
}
}
return {
content: [
{
type: 'text' as const,
text: lines.join('\n'),
},
],
isError: true,
};
}
throw error;
}
},
};