Path: blob/main/extensions/copilot/test/simulation/workbench/utils/utils.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*--------------------------------------------------------------------------------------------*/45import * as fs from 'fs';6import * as mobx from 'mobx';7import { InterceptedRequest } from '../../shared/sharedTypes';89export const REPO_ROOT: string = (globalThis as any).projectRoot;1011export const monacoModule: {12value: typeof import('monaco-editor');13} = {14value: null! // @ulugbekna: this is initialized on workbench startup and must be non-null by the time it's used15};1617export function genericEquals(one: any, other: any): boolean {18if (one === other) {19return true;20}21if (one === null || one === undefined || other === null || other === undefined) {22return false;23}24if (typeof one !== typeof other) {25return false;26}27if (typeof one !== 'object') {28return false;29}30if ((Array.isArray(one)) !== (Array.isArray(other))) {31return false;32}3334let i: number;35let key: string;3637if (Array.isArray(one)) {38if (one.length !== other.length) {39return false;40}41for (i = 0; i < one.length; i++) {42if (!genericEquals(one[i], other[i])) {43return false;44}45}46} else {47const oneKeys: string[] = [];4849for (key in one) {50oneKeys.push(key);51}52oneKeys.sort();53const otherKeys: string[] = [];54for (key in other) {55otherKeys.push(key);56}57otherKeys.sort();58if (!genericEquals(oneKeys, otherKeys)) {59return false;60}61for (i = 0; i < oneKeys.length; i++) {62if (!genericEquals(one[oneKeys[i]], other[oneKeys[i]])) {63return false;64}65}66}67return true;68}6970let pendingRunInAction: (() => void)[] = [];7172/**73* Schedules a function to be run inside a MobX action.74* This will batch multiple callers in a single runInAction MobX call.75*76* @param fn - The function to be scheduled.77*/78export function scheduleRunInAction(fn: () => void) {79pendingRunInAction.push(fn);80if (pendingRunInAction.length === 1) {81process.nextTick(() => {82const updates = pendingRunInAction;83pendingRunInAction = [];84runInAction(updates);85});86}87}8889function runInAction(fns: (() => void)[]) {90mobx.runInAction(() => {91for (const fn of fns) {92try {93fn();94} catch (err) {95console.error(err);96}97}98});99}100101export class ObservablePromise<T> {102103public static resolve<T>(value: T): ObservablePromise<T> {104return new ObservablePromise(Promise.resolve(value), value);105}106107public readonly promise: Promise<T>;108109@mobx.observable.ref110public error: unknown;111112@mobx.observable.ref113public value: T;114115@mobx.observable.ref116public resolved: boolean;117118constructor(promise: Promise<T>, defaultValue: T) {119this.promise = promise;120this.error = null;121this.value = defaultValue;122this.resolved = false;123124mobx.makeObservable(this);125126this.promise.then(127(value: T) => {128scheduleRunInAction(() => {129this.value = value;130this.resolved = true;131});132},133(error: unknown) => {134scheduleRunInAction(() => {135console.error(error);136this.error = error;137this.resolved = true;138});139}140);141}142}143144export async function fileExists(filePath: string): Promise<boolean> {145try {146await fs.promises.access(filePath);147return true;148} catch (_) {149return false;150}151}152153export function isToolCall(request: InterceptedRequest) {154return Boolean(request.response.copilotFunctionCalls?.length);155}156157158