Path: blob/main/extensions/copilot/src/extension/prompt/common/toolCallRound.ts
13399 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*--------------------------------------------------------------------------------------------*/4import { FetchSuccess } from '../../../platform/chat/common/commonTypes';5import { OpenAIContextManagementResponse } from '../../../platform/networking/common/openai';6import { isEncryptedThinkingDelta, ThinkingData, ThinkingDelta } from '../../../platform/thinking/common/thinking';7import { generateUuid } from '../../../util/vs/base/common/uuid';8import { IToolCall, IToolCallRound } from './intents';91011/**12* Represents a round of tool calling from the AI assistant.13* Each round contains the assistant's response text, any tool calls it made,14* and retry information if there were input validation issues.15*/16export class ToolCallRound implements IToolCallRound {17public summary: string | undefined;18public phase?: string;19public phaseModelId?: string;2021/**22* Creates a ToolCallRound from an existing IToolCallRound object.23* Prefer this over using a constructor overload to keep construction explicit.24*/25public static create(params: Omit<IToolCallRound, 'id'> & { id?: string }): ToolCallRound {26const round = new ToolCallRound(27params.response,28params.toolCalls,29params.toolInputRetry,30params.id,31params.statefulMarker,32params.thinking,33params.timestamp,34params.compaction,35);36round.summary = params.summary;37round.phase = params.phase;38round.phaseModelId = params.phaseModelId;39return round;40}4142/**43* @param response The text response from the assistant44* @param toolCalls The tool calls made by the assistant45* @param toolInputRetry The number of times this round has been retried due to tool input validation failures46* @param id A stable identifier for this round47* @param statefulMarker Optional stateful marker used with the responses API48* @param thinking Optional thinking/reasoning data49* @param timestamp Epoch millis when this round started (defaults to `Date.now()`)50*/51constructor(52public readonly response: string,53public readonly toolCalls: IToolCall[] = [],54public readonly toolInputRetry: number = 0,55public readonly id: string = ToolCallRound.generateID(),56public readonly statefulMarker?: string,57public readonly thinking?: ThinkingData,58public readonly timestamp: number = Date.now(),59public readonly compaction?: OpenAIContextManagementResponse,60) { }6162private static generateID(): string {63return generateUuid();64}65}6667export class ThinkingDataItem implements ThinkingData {68public text: string | string[] = '';69public metadata?: { [key: string]: any };70public tokens?: number;71public encrypted?: string;7273static createOrUpdate(item: ThinkingDataItem | undefined, delta: ThinkingDelta) {74if (!item) {75item = new ThinkingDataItem(delta.id ?? generateUuid());76}7778item.update(delta);79return item;80}8182constructor(83public id: string84) { }8586public update(delta: ThinkingDelta): void {87if (delta.id && this.id !== delta.id) {88this.id = delta.id;89}90if (isEncryptedThinkingDelta(delta)) {91this.encrypted = delta.encrypted;92}93if (delta.text !== undefined) {9495// handles all possible text states96if (Array.isArray(delta.text)) {97if (Array.isArray(this.text)) {98this.text.push(...delta.text);99} else if (this.text) {100this.text = [this.text, ...delta.text];101} else {102this.text = [...delta.text];103}104} else {105if (Array.isArray(this.text)) {106this.text.push(delta.text);107} else {108this.text += delta.text;109}110}111}112if (delta.metadata) {113this.metadata = delta.metadata;114}115}116117public updateWithFetchResult(fetchResult: FetchSuccess<unknown>): void {118this.tokens = fetchResult.usage?.completion_tokens_details?.reasoning_tokens;119}120}121122