Path: blob/main/extensions/copilot/test/pipeline/parseInput.ts
13388 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as fs from 'fs/promises';6import { IAlternativeAction } from '../../src/extension/inlineEdits/node/nextEditProviderTelemetry';78/**9* A single row from the JSON input.10*/11export interface IInputRow {12readonly originalRowIndex: number;13readonly suggestionStatus: string;14readonly alternativeAction: IAlternativeAction;15readonly prompt: unknown[];16readonly modelResponse: string;17readonly postProcessingOutcome: {18suggestedEdit: string;19isInlineCompletion: boolean;20};21readonly activeDocumentLanguageId: string;22}2324const requiredKeys = [25'status',26'action',27'input',28'response',29'outcome',30'language',31] as const;3233/**34* Parse a JSON array of input entries into structured rows.35*/36function parseInputJson(jsonContents: string): {37rows: IInputRow[];38errors: { rowIndex: number; error: string }[];39} {40const records = JSON.parse(jsonContents) as Record<string, string>[];4142const rows: IInputRow[] = [];43const errors: { rowIndex: number; error: string }[] = [];4445for (let i = 0; i < records.length; i++) {46const record = records[i];47try {48for (const key of requiredKeys) {49if (!(key in record)) {50throw new Error(`Missing key: ${key}`);51}52}5354const alternativeAction = JSON.parse(record['action']) as IAlternativeAction;55const prompt = JSON.parse(record['input']) as unknown[];56const postProcessingOutcome = JSON.parse(record['outcome']) as {57suggestedEdit: string;58isInlineCompletion: boolean;59};6061if (!alternativeAction.recording) {62throw new Error('action.recording is missing');63}64if (!alternativeAction.recording.entries || alternativeAction.recording.entries.length === 0) {65throw new Error('action.recording.entries is empty');66}67if (!postProcessingOutcome.suggestedEdit) {68throw new Error('outcome.suggestedEdit is missing');69}7071rows.push({72originalRowIndex: i,73suggestionStatus: record['status'],74alternativeAction,75prompt,76modelResponse: record['response'],77postProcessingOutcome,78activeDocumentLanguageId: record['language'],79});80} catch (e) {81errors.push({82rowIndex: i,83error: e instanceof Error ? e.message : String(e),84});85}86}8788return { rows, errors };89}9091export async function loadAndParseInput(inputPath: string, verbose = false): Promise<{92rows: IInputRow[];93errors: { rowIndex: number; error: string }[];94}> {95const contents = await fs.readFile(inputPath, 'utf8');96if (verbose) {97console.log(`Read ${contents.length} chars from ${inputPath}`);98}99return parseInputJson(contents);100}101102103