Path: blob/main/extensions/copilot/src/platform/nesFetch/common/completionHelpers.ts
13401 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 { AsyncIterableEmitter, AsyncIterableObject } from '../../../util/vs/base/common/async';6import { assertType } from '../../../util/vs/base/common/types';7import { Completion } from './completionsAPI';8910namespace LineOfText {11export type LineOfText = string & { _brand: 'LineOfText' };1213export function make(s: string) {14return s as LineOfText;15}16}1718/**19* Split an incoming stream of text to a stream of lines.20*/21export function streamLines(completions: AsyncIterable<Completion>, initialBuffer = ''): AsyncIterableObject<{22line: LineOfText.LineOfText;23finishReason: Completion.FinishReason | null;24}> {2526async function splitLines(emitter: AsyncIterableEmitter<{27line: LineOfText.LineOfText;28finishReason: Completion.FinishReason | null;29}>) {3031let buffer = initialBuffer;32let finishReason: Completion.FinishReason | null = null;3334for await (const completion of completions) {3536const choice = completion.choices.at(0);37assertType(choice !== undefined, 'we should have choices[0] to be defined');3839buffer += choice.text ?? '';40finishReason = choice.finish_reason;4142do {43const newlineIndex = buffer.indexOf('\n');44if (newlineIndex === -1) {45break;46}4748// take the first line49const line = buffer.substring(0, newlineIndex);50buffer = buffer.substring(newlineIndex + 1);5152emitter.emitOne({ line: LineOfText.make(line), finishReason });53} while (true);54}5556if (buffer.length > 0) {57// last line which doesn't end with \n58emitter.emitOne({ line: LineOfText.make(buffer), finishReason });59}60}6162return new AsyncIterableObject(splitLines);63}646566