import { z } from 'zod';
import { defineTool, } from '../toolDefinition.js';
import { AgentToolNames } from './agentToolNames.js';
import { sourceControlContextSchema } from '../shared/schemas.js';
/**
 * GetTestRunInfoDefinition - Tool definition for fetching comprehensive test run information.
 */
export const getTestRunInfoParamsSchema = z.object({
    test_run_id: z.string().meta({
        description: 'Required. Test run ID to fetch info for.',
    }),
    include_steps: z.boolean().optional().meta({
        description: 'Whether to include detailed step information. Default: true',
    }),
    step_start_index: z.number().optional().meta({
        description: 'Start index for step range (0-based, inclusive). If not specified, starts from beginning. Only used if include_steps is true.',
    }),
    step_end_index: z.number().optional().meta({
        description: 'End index for step range (0-based, inclusive). If not specified, includes all steps to the end. Only used if include_steps is true.',
    }),
    step_run_ids: z.array(z.string()).optional().meta({
        description: 'Filter to specific step executions by step_run_id. Takes precedence over step_start_index/step_end_index.',
    }),
    include_context: z.boolean().optional().meta({
        description: 'Whether to include detailed context about application, environment, plan, and datatables. Default: true',
    }),
    include_flow_breakdown: z.boolean().optional().meta({
        description: 'Whether to include flow-level breakdown showing execution summary per flow (pass/fail counts, duration). Useful for tests with nested flows or step groups. Default: false',
    }),
});
const testStepInfoSchema = z.object({
    index: z.number().meta({ description: 'Step index (0-based, cumulative across the entire journey/test)' }),
    stepNumber: z.string().meta({
        description: 'Human-readable step number with dotted notation for nested steps (1-based). ' +
            'Examples: "5" for step 5, "3.2" for step 2 inside step group at position 3, "3.2.1" for deeply nested steps. ' +
            'Use this for display purposes instead of computing from index/nestedStepPath.',
    }),
    nestedStepPath: z
        .array(z.number())
        .optional()
        .meta({
        description: 'Path of step indices for nested steps. Format: [flow_index, step_index_in_flow, ...]. ' +
            'Example: [2, 1] means this step is within flow at index 2, and is step 1 within that flow. ' +
            'For step groups: [flow_index, step_group_index, step_in_group]. ' +
            'Empty or undefined for top-level steps in the main flow.',
    }),
    description: z.string().meta({ description: 'Human-readable step description' }),
    status: z.enum(['passed', 'failed', 'skipped', 'warning', 'disabled']).meta({
        description: 'Status of the step execution. ' +
            '"disabled" indicates the step was explicitly disabled by the user and not executed.',
    }),
    durationMs: z.number().optional().meta({ description: 'Duration in milliseconds' }),
    errorMessage: z.string().optional().meta({ description: 'Error message if the step failed' }),
    hasScreenshot: z.boolean().meta({ description: 'Whether this step has a screenshot available' }),
    url: z.string().optional().meta({ description: 'Page URL at the time of this step execution' }),
    flowId: z.string().optional().meta({
        description: 'ID of the flow this step belongs to. Format: "invariant_id:version". The invariant_id portion is stable across flow versions.',
    }),
    flowIndex: z.number().optional().meta({
        description: 'Index of the flow in the test (0 = main flow, 1+ = nested flows in order of first execution)',
    }),
    stepLoop: z
        .number()
        .optional()
        .meta({
        description: 'For steps that loop (retry logic, etc.), the 1-based loop iteration number (1, 2, 3...). ' +
            'Undefined if step only executed once. This is step-level looping, distinct from flow-level looping.',
    }),
    isInNestedFlow: z.boolean().optional().meta({
        description: 'True if this step is executing inside a nested flow (a flow called by another flow). Helps identify steps that are part of reusable flows.',
    }),
    isInStepGroup: z.boolean().optional().meta({
        description: 'True if this step is inside a step group. Step groups are collections of steps that are grouped together for organization.',
    }),
    flowName: z.string().optional().meta({
        description: 'Human-readable name of the flow this step belongs to, if available.',
    }),
    stepId: z.string().optional().meta({
        description: 'Stable step identifier within the flow (step_id_in_flow). Consistent across test runs of the same test version.',
    }),
    stepRunId: z.string().optional().meta({
        description: 'Unique identifier for this specific step execution instance. Different for each run, including loop iterations.',
    }),
    traSessionId: z
        .string()
        .optional()
        .meta({
        description: 'Test Recovery Agent session ID, if TRA ran on this step. ' +
            'Use get_test_recovery_session to fetch what the TRA did.',
    }),
});
// Schema for plan context (extracted from execution logs and plan run)
const planContextSchema = z.object({
    id: z.string().meta({ description: 'Plan ID' }),
    planRunId: z.string().optional().meta({ description: 'Plan run ID' }),
    name: z.string().optional().meta({ description: 'Plan name (fetched when relevant)' }),
    triggerType: z
        .enum(['manual', 'retry', 'schedule', 'customer_event', 'insight', 'external'])
        .optional()
        .meta({ description: 'How the plan run was triggered' }),
    retryCount: z
        .number()
        .optional()
        .meta({ description: 'Retry attempt number (0 = initial run, 1 = first retry, etc.)' }),
    retryOfId: z.string().optional().meta({ description: 'ID of the plan run this is a retry of' }),
    retryType: z
        .enum(['all', 'failed', 'failed_and_skipped'])
        .optional()
        .meta({ description: 'For retries: which tests were retried' }),
    willRetry: z.boolean().optional().meta({ description: 'Whether this plan run will automatically retry on failure' }),
});
// Schema for application context
const applicationContextSchema = z.object({
    id: z.string().meta({ description: 'Application ID' }),
    name: z.string().optional().meta({ description: 'Application name (fetched when relevant)' }),
});
// Schema for environment context
const environmentContextSchema = z.object({
    id: z.string().meta({ description: 'Environment ID' }),
    name: z.string().optional().meta({ description: 'Environment name (fetched when relevant)' }),
});
// Schema for credentials context
const credentialsContextSchema = z.object({
    credentialsId: z.string().optional().meta({ description: 'Login credentials ID used for this run' }),
    httpAuthCredentialsId: z.string().optional().meta({ description: 'HTTP Basic Auth credentials ID used for this run' }),
});
// Schema for scenario/datatable context (from journey_parameters)
const scenarioContextSchema = z.object({
    scenarioIds: z.array(z.string()).optional().meta({ description: 'Specific scenario IDs run' }),
    datatableId: z.string().optional().meta({ description: 'Datatable/Variable table ID' }),
    datatableRowId: z.string().optional().meta({ description: 'Datatable row ID (specific scenario)' }),
    scenarioId: z.string().optional().meta({ description: 'Scenario ID from the datatable row' }),
});
// Schema for URL context (extracted from execution logs)
const urlContextSchema = z.object({
    startUrl: z.string().optional().meta({ description: 'Initial URL the test started on' }),
    uniqueUrls: z.array(z.string()).optional().meta({ description: 'List of unique URLs visited during the test' }),
});
// Schema for device emulation info (for web tests with device emulation)
const deviceEmulationContextSchema = z.object({
    deviceName: z.string().optional().meta({ description: 'Emulated device name (e.g., "iPhone 12", "iPad Pro")' }),
    orientation: z
        .string()
        .optional()
        .meta({ description: 'Device orientation (portrait_primary, landscape_primary, etc.)' }),
});
// Schema for mobile device info (for mobile tests)
const mobileDeviceContextSchema = z.object({
    platform: z.string().optional().meta({ description: 'Mobile platform (ios, android)' }),
    deviceName: z.string().optional().meta({ description: 'Device name (e.g., "iPhone 14", "Pixel 7")' }),
    deviceManufacturer: z
        .string()
        .optional()
        .meta({ description: 'Device manufacturer (e.g., "Apple", "Google", "Samsung")' }),
    osVersion: z.string().optional().meta({ description: 'Operating system version' }),
});
// Schema for localization settings
const localizationContextSchema = z.object({
    locale: z.string().optional().meta({ description: 'Language locale identifier (e.g., en-US, jp)' }),
    timezoneIdentifier: z.string().optional().meta({ description: 'Timezone identifier (e.g., America/Los_Angeles, UTC)' }),
});
// Schema for deployment info
const deploymentContextSchema = z.object({
    deploymentId: z.string().optional().meta({ description: 'Deployment ID' }),
    applicationId: z.string().optional().meta({ description: 'Application ID' }),
    environmentId: z.string().optional().meta({ description: 'Environment ID' }),
    deploymentType: z
        .enum(['web_application', 'api', 'mobile_application'])
        .optional()
        .meta({ description: 'Type of deployment' }),
});
// Schema for timing summary
const timingSummaryContextSchema = z.object({
    findTimeMs: z.number().optional().meta({ description: 'Total time spent finding elements (ms)' }),
    findExtraWaitTimeMs: z.number().optional().meta({ description: 'Extra wait time added by intelligent waiting (ms)' }),
});
// Schema for assert failure details
const assertFailureSchema = z.object({
    reason: z.string().optional().meta({ description: 'Assert failure description' }),
    expected: z.string().optional().meta({ description: 'Expected value' }),
    found: z.string().optional().meta({ description: 'Actual value found' }),
});
// Schema for link checker results
const linkCheckerResultsSchema = z.object({
    checkedLinks: z.number().optional().meta({ description: 'Total number of links checked' }),
    brokenLinks: z.number().optional().meta({ description: 'Number of broken links found' }),
    checkedPages: z.number().optional().meta({ description: 'Number of pages checked for links' }),
});
// Schema for HAR (HTTP Archive) summary - aggregated HTTP status codes from network requests
const harSummarySchema = z.object({
    totalRequests: z.number().meta({ description: 'Total number of HTTP requests' }),
    statusCodeCounts: z
        .record(z.string(), z.number())
        .meta({ description: 'Count of requests by HTTP status code (e.g., {"200": 45, "404": 2})' }),
    errorCount: z.number().optional().meta({ description: 'Number of requests with error status codes (4xx, 5xx)' }),
});
// Schema for the test run context (plan, scenario, etc. - from journey_parameters and plan run)
export const testRunContextSchema = z.object({
    application: applicationContextSchema.optional().meta({ description: 'Application this test ran against' }),
    environment: environmentContextSchema.optional().meta({ description: 'Environment this test ran in' }),
    plan: planContextSchema.optional().meta({ description: 'Plan that triggered this test run' }),
    credentials: credentialsContextSchema.optional().meta({ description: 'Credentials used for this test run' }),
    scenario: scenarioContextSchema.optional().meta({ description: 'Scenario/datatable info used in this run' }),
    urls: urlContextSchema.optional().meta({ description: 'URL information from the test run' }),
    triggeredBy: z.string().optional().meta({ description: 'How the test run was triggered (e.g., plan, ad-hoc)' }),
    browserVersion: z.string().optional().meta({ description: 'Browser version used' }),
    deviceEmulation: deviceEmulationContextSchema
        .optional()
        .meta({ description: 'Device emulation settings (for web tests with device emulation like iPad, iPhone)' }),
    mobileDevice: mobileDeviceContextSchema
        .optional()
        .meta({ description: 'Mobile device configuration (for mobile tests)' }),
    localization: localizationContextSchema.optional().meta({ description: 'Localization settings (locale and timezone)' }),
    pageLoadWait: z
        .enum(['FAST', 'NORMAL', 'SLOW', 'SLOWER'])
        .optional()
        .meta({ description: 'Page load wait setting that affects timing' }),
    linkServerIds: z.array(z.string()).optional().meta({ description: 'Link server IDs used for network tunneling' }),
    relatedDeployments: z
        .array(deploymentContextSchema)
        .optional()
        .meta({ description: 'Related deployments (e.g., API deployment for browser tests)' }),
    sourceControl: sourceControlContextSchema
        .optional()
        .meta({ description: 'Source control context (revision, branch, PR info) from CI/CD integration' }),
    timingSummary: timingSummaryContextSchema
        .optional()
        .meta({ description: 'Timing metrics for element finding operations' }),
    linkCheckerResults: linkCheckerResultsSchema.optional().meta({ description: 'Link checker results if enabled' }),
    stepFeatures: z
        .array(z.string())
        .optional()
        .meta({ description: 'List of advanced step features used in this test (e.g., ai_assertion, visual_change)' }),
    harSummary: harSummarySchema
        .optional()
        .meta({ description: 'Aggregated HTTP status code summary from network requests during test execution' }),
    exportedVariables: z
        .record(z.string(), z.unknown())
        .optional()
        .meta({
        description: 'Variables exported from this test run. These can be passed to subsequent tests in a plan. ' +
            'Keys are variable names, values are the exported values.',
    }),
});
const testRunSummarySchema = z.object({
    testRunId: z.string().meta({ description: 'Test run ID' }),
    testId: z.string().optional().meta({ description: 'Test ID (journey_id)' }),
    testInvariantId: z.string().optional().meta({ description: 'Test invariant ID (stable across versions)' }),
    testVariantId: z.string().optional().meta({ description: 'Test variant ID (changes when test is modified)' }),
    testName: z.string().meta({ description: 'Test name' }),
    testType: z.enum(['browser', 'api', 'mobile', 'performance', 'unknown']).optional().meta({
        description: 'Type of test (browser, api, mobile, performance). Affects available data (e.g., API tests have no screenshots).',
    }),
    status: z.enum(['passed', 'failed', 'skipped', 'terminated']).meta({ description: 'Overall status' }),
    startTime: z.string().meta({ description: 'Start time as ISO string' }),
    endTime: z.string().optional().meta({ description: 'End time as ISO string' }),
    durationMs: z.number().optional().meta({ description: 'Total duration in milliseconds' }),
    totalSteps: z.number().meta({ description: 'Total number of steps' }),
    passedSteps: z.number().meta({ description: 'Number of passed steps' }),
    failedSteps: z.number().meta({ description: 'Number of failed steps' }),
    browser: z
        .string()
        .optional()
        .meta({ description: 'Browser used for the test (browser tests only, not included for API/mobile)' }),
    failureReason: z.string().optional().meta({ description: 'Failure reason if test failed' }),
    assertFailure: assertFailureSchema
        .optional()
        .meta({ description: 'Structured assertion failure details with expected/found values' }),
    terminationReason: z
        .enum(['cancelled', 'timeout', 'exceeded_max_steps', 'exceeded_max_time', 'error', 'unknown'])
        .optional()
        .meta({ description: 'Why the test was terminated (only present if status is terminated)' }),
    statusCause: z
        .string()
        .optional()
        .meta({ description: 'Additional context for the status (e.g., termination reason)' }),
    failureCategoryId: z
        .string()
        .optional()
        .meta({ description: 'Failure category ID if categorized (informational, may be user-assigned or AI-suggested)' }),
    firstFailedStepIndex: z.number().optional().meta({ description: 'Index of the first failed step' }),
});
// Base schema for flow step fields (used by both regular steps and nested steps)
const flowStepBaseSchema = z.object({
    index: z.number().meta({ description: 'Step index (execution order across journey)' }),
    stepNumber: z.string().meta({
        description: 'Human-readable step number with dotted notation for nested steps (1-based). ' +
            'Examples: "5" for step 5, "3.2" for step 2 inside step group at position 3.',
    }),
    stepIndexInFlow: z.number().meta({ description: 'Step index within this flow or step group (0-based)' }),
    description: z.string().meta({ description: 'Human-readable step description' }),
    status: z.enum(['passed', 'failed', 'skipped', 'warning', 'disabled']).meta({
        description: 'Status of the step execution. ' +
            '"disabled" indicates the step was explicitly disabled by the user and not executed.',
    }),
    durationMs: z.number().optional().meta({ description: 'Duration in milliseconds' }),
    errorMessage: z.string().optional().meta({ description: 'Error message if the step failed' }),
    hasScreenshot: z.boolean().meta({ description: 'Whether this step has a screenshot available' }),
    isStepGroup: z.boolean().optional().meta({ description: 'True if this is a step group containing nested steps' }),
    stepGroupName: z.string().optional().meta({ description: 'Name of the step group if this is a step group' }),
    nestingDepth: z.number().optional().meta({ description: 'How deep this step is nested (0 = top level in flow)' }),
});
const flowStepSchema = flowStepBaseSchema.extend({
    nestedSteps: z
        .lazy(() => z.array(flowStepSchema))
        .optional()
        .meta({
        description: 'Nested steps if this is a step group. Step groups can contain other step groups (recursive nesting up to 5 levels). ' +
            'Each nested step has the same structure as top-level steps.',
    }),
});
// Schema for flow execution summary (when include_flow_breakdown is true)
const flowExecutionSummarySchema = z.object({
    flowId: z.string().meta({
        description: 'Flow ID in format "invariant_id:version". Use the invariant_id portion for stable identification across versions.',
    }),
    flowIndex: z.number().meta({ description: 'Index of this flow in execution order (0 = main flow)' }),
    flowName: z.string().optional().meta({ description: 'Human-readable flow name if available' }),
    isMainFlow: z.boolean().meta({ description: 'True if this is the main test flow (not a nested flow)' }),
    loopNumber: z.number().optional().meta({
        description: 'For flows that execute multiple times (loops), the 1-based loop iteration number (1, 2, 3...). Undefined if flow only ran once.',
    }),
    totalLoops: z.number().optional().meta({
        description: 'Total number of times this flow executed. Only present if flow ran more than once.',
    }),
    calledFromStepIndex: z
        .number()
        .optional()
        .meta({
        description: 'For nested flows: the step index in the journey that triggered this flow call. ' +
            'This allows linking a nested flow back to the EvaluateFlow step in the parent flow. ' +
            'Only present for nested flows (isMainFlow=false).',
    }),
    parentFlowId: z
        .string()
        .optional()
        .meta({
        description: 'For nested flows: the flowId of the parent flow that called this flow. ' +
            'Use this to build the flow call tree (which flow called which). ' +
            'Only present for nested flows (isMainFlow=false).',
    }),
    totalSteps: z.number().meta({ description: 'Total number of steps in this flow execution' }),
    passedSteps: z.number().meta({ description: 'Number of passed steps in this flow execution' }),
    failedSteps: z.number().meta({ description: 'Number of failed steps in this flow execution' }),
    skippedSteps: z.number().meta({ description: 'Number of skipped steps in this flow execution' }),
    disabledSteps: z.number().meta({ description: 'Number of disabled steps in this flow execution' }),
    status: z.enum(['passed', 'failed', 'skipped', 'disabled']).meta({
        description: 'Overall status of this flow execution. ' +
            'failed if any step failed, skipped if all skipped, disabled if all disabled, passed otherwise.',
    }),
    durationMs: z.number().optional().meta({ description: 'Total duration of this flow execution in milliseconds' }),
    firstStepIndex: z.number().meta({ description: 'Index of the first step of this flow in the flattened step list' }),
    lastStepIndex: z.number().meta({ description: 'Index of the last step of this flow in the flattened step list' }),
    flowSteps: z
        .array(flowStepSchema)
        .optional()
        .meta({
        description: 'Steps within this flow execution, organized hierarchically. Step groups show their nested steps. ' +
            'Each step includes its position in the flow (stepIndexInFlow) and execution index.',
    }),
});
export const getTestRunInfoResponseSchema = z.object({
    summary: testRunSummarySchema.meta({ description: 'Summary information about the test run' }),
    context: testRunContextSchema.optional().meta({ description: 'Contextual information about the test run' }),
    steps: z
        .array(testStepInfoSchema)
        .optional()
        .meta({ description: 'Detailed step information (if include_steps is true)' }),
    stepRange: z
        .object({
        start: z.number(),
        end: z.number(),
        total: z.number(),
    })
        .optional()
        .meta({ description: 'Range of steps included in the response' }),
    flowBreakdown: z
        .array(flowExecutionSummarySchema)
        .optional()
        .meta({
        description: 'Flow-level execution breakdown (if include_flow_breakdown is true). Shows summary per flow including step counts, status, and duration. ' +
            'Useful for understanding which nested flows passed/failed and identifying problems in specific reusable flows.',
    }),
    formattedStepList: z
        .string()
        .optional()
        .meta({
        description: 'Pre-formatted step list with each step on its own line, proper indentation for nested flows, and status indicators. ' +
            'ALWAYS use this for displaying steps to users - it ensures correct formatting with newlines and indentation.',
    }),
});
export const GetTestRunInfoToolDefinition = defineTool({
    name: AgentToolNames.GetTestRunInfo,
    description: `Retrieves comprehensive information about a test run including status, steps, timing, configuration, and contextual details.

Use this tool to:
- Understand the overall test run result and status
- Get a list of all test steps with their execution status
- Find which steps failed and why
- Get timing information about the test execution
- Learn about the test configuration (browser, environment, etc.)
- Understand the context: which application, environment, plan, and datatables were used
- See URLs visited during the test
- Identify how the test was triggered (plan, API, manual, etc.)
- Analyze nested flows and step groups (use include_flow_breakdown=true)

You can filter to specific steps using step_run_ids (preferred for precise targeting) or step_start_index/step_end_index for ranges.
Set include_context=false if you only need basic summary information without detailed context.

For tests with nested flows or step groups, use include_flow_breakdown=true to get a flow-level summary showing:
- Which flows passed or failed
- Step counts and duration per flow
- Step groups within each flow`,
    argumentsSchema: getTestRunInfoParamsSchema,
    responseSchema: getTestRunInfoResponseSchema,
});
//# sourceMappingURL=GetTestRunInfoDefinition.js.map