import { z } from 'zod';
/**
 * Rich per-test envelope returned by both `search_tests_by_text` and `search_tests_by_semantic`.
 *
 * The schema is a UNION shape: some fields are modality-specific (e.g., `text_score` only
 * on text matches, `matched_chunk_context` only on semantic matches). Synthesis uses
 * `annotated_step_summary` and (for semantic) `matched_chunk_context` to make include/exclude
 * decisions without a follow-up fetch.
 *
 * The shared truncation algorithm caps total payload at TOTAL_TOOL_BUDGET_CHARS (80 KB) per
 * tool call so the synthesis context stays bounded regardless of how large individual tests
 * are. See truncateTestResults.ts for the budget allocation strategy.
 */
export const testSearchMatchSchema = z.object({
    test_invariant_id: z.string(),
    test_name: z.string(),
    description: z.string().optional(),
    labels: z.array(z.string()),
    intent: z.string().optional().meta({
        description: 'TAA-generated intent string; often empty until the Dataflow writer fills it.',
    }),
    // Only browser and mobile are supported; api and performance are out of scope (no searchable
    // step content) and rejected at the request boundary. Keep in sync with narrowTestType.
    test_type: z.enum(['browser', 'mobile']).optional(),
    mobile_platform: z.enum(['ios', 'android']).optional(),
    application_id: z.string().optional(),
    last_updated_time: z.string().optional().meta({
        description: 'ISO-8601 timestamp of the last update.',
    }),
    annotated_step_summary: z.string().meta({
        description: 'Concatenated annotated step descriptions for the test, truncated at step boundaries to fit ' +
            'the per-test adaptive-truncation budget. If truncated, the string ends with ' +
            '"... (N more steps omitted, M total)".',
    }),
    truncated: z.boolean().meta({
        description: "True if this row's annotated_step_summary was truncated to fit the budget.",
    }),
    // Modality-specific signals
    text_score: z.number().optional().meta({
        description: 'Spanner SCORE(combined_tokens, query). Higher = better. Text matches only.',
    }),
    matched_field: z.enum(['combined', 'name', 'description', 'intent', 'labels']).optional().meta({
        description: 'Which token column the text match landed in (text matches only).',
    }),
    matched_chunk_context: z
        .string()
        .optional()
        .meta({
        description: 'chunkContext describing what the matched chunk is about. Present on semantic results (the ' +
            'semantic tool is contracted to always populate it, even with an empty string when the matched ' +
            'chunk lacks a context); absent on text-only results.',
    }),
    matched_chunk_step_range: z
        .object({
        start: z.number().int(),
        end: z.number().int(),
    })
        .optional()
        .meta({ description: 'The flow-step range the matched chunk covers (semantic only).' }),
});
export const testSearchResponseSchema = z.object({
    total_candidates: z.number().int(),
    truncated: z.boolean(),
    matches: z.array(testSearchMatchSchema),
});
//# sourceMappingURL=searchTestsSchemas.js.map