refactor: Update agent getCompletion interface. (#176)
parent
b4eaf543b1
commit
e3eae370be
File diff suppressed because one or more lines are too long
|
|
@ -64,18 +64,7 @@ type CompletionEvent = {
|
||||||
choices: Array<Choice>;
|
choices: Array<Choice>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type CompletionRequest = {
|
type CompletionResponse$1 = {
|
||||||
/**
|
|
||||||
* Language for completion request
|
|
||||||
*/
|
|
||||||
language?: string;
|
|
||||||
/**
|
|
||||||
* The context to generate completions for, encoded as a string.
|
|
||||||
*/
|
|
||||||
prompt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type CompletionResponse = {
|
|
||||||
id: string;
|
id: string;
|
||||||
created: number;
|
created: number;
|
||||||
choices: Array<Choice>;
|
choices: Array<Choice>;
|
||||||
|
|
@ -108,6 +97,13 @@ type HTTPValidationError = {
|
||||||
detail?: Array<ValidationError>;
|
detail?: Array<ValidationError>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CompletionRequest = {
|
||||||
|
filepath: string;
|
||||||
|
language: string;
|
||||||
|
text: string;
|
||||||
|
position: number;
|
||||||
|
};
|
||||||
|
type CompletionResponse = CompletionResponse$1;
|
||||||
interface AgentFunction {
|
interface AgentFunction {
|
||||||
setServerUrl(url: string): string;
|
setServerUrl(url: string): string;
|
||||||
getServerUrl(): string;
|
getServerUrl(): string;
|
||||||
|
|
@ -120,7 +116,7 @@ type StatusChangedEvent = {
|
||||||
status: "connecting" | "ready" | "disconnected";
|
status: "connecting" | "ready" | "disconnected";
|
||||||
};
|
};
|
||||||
type AgentEvent = StatusChangedEvent;
|
type AgentEvent = StatusChangedEvent;
|
||||||
declare const agentEventNames: AgentEvent['event'][];
|
declare const agentEventNames: AgentEvent["event"][];
|
||||||
interface AgentEventEmitter {
|
interface AgentEventEmitter {
|
||||||
on<T extends AgentEvent>(eventName: T["event"], callback: (event: T) => void): this;
|
on<T extends AgentEvent>(eventName: T["event"], callback: (event: T) => void): this;
|
||||||
}
|
}
|
||||||
|
|
@ -135,6 +131,7 @@ declare class TabbyAgent extends EventEmitter implements Agent {
|
||||||
private changeStatus;
|
private changeStatus;
|
||||||
private ping;
|
private ping;
|
||||||
private wrapApiPromise;
|
private wrapApiPromise;
|
||||||
|
private createPrompt;
|
||||||
setServerUrl(serverUrl: string): string;
|
setServerUrl(serverUrl: string): string;
|
||||||
getServerUrl(): string;
|
getServerUrl(): string;
|
||||||
getStatus(): "connecting" | "ready" | "disconnected";
|
getStatus(): "connecting" | "ready" | "disconnected";
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -59,7 +59,7 @@ module.exports = __toCommonJS(src_exports);
|
||||||
// src/TabbyAgent.ts
|
// src/TabbyAgent.ts
|
||||||
var import_axios2 = __toESM(require("axios"));
|
var import_axios2 = __toESM(require("axios"));
|
||||||
var import_events = require("events");
|
var import_events = require("events");
|
||||||
var import_assert = require("assert");
|
var import_uuid = require("uuid");
|
||||||
|
|
||||||
// src/CompletionCache.ts
|
// src/CompletionCache.ts
|
||||||
var import_lru_cache = require("lru-cache");
|
var import_lru_cache = require("lru-cache");
|
||||||
|
|
@ -505,6 +505,9 @@ function splitLines(input) {
|
||||||
function splitWords(input) {
|
function splitWords(input) {
|
||||||
return input.match(/\w+|\W+/g).filter(Boolean);
|
return input.match(/\w+|\W+/g).filter(Boolean);
|
||||||
}
|
}
|
||||||
|
function isBlank(input) {
|
||||||
|
return input.trim().length === 0;
|
||||||
|
}
|
||||||
function cancelable(promise, cancel) {
|
function cancelable(promise, cancel) {
|
||||||
return new CancelablePromise((resolve2, reject, onCancel) => {
|
return new CancelablePromise((resolve2, reject, onCancel) => {
|
||||||
promise.then((resp) => {
|
promise.then((resp) => {
|
||||||
|
|
@ -576,7 +579,11 @@ var CompletionCache = class {
|
||||||
return grouped;
|
return grouped;
|
||||||
}, {});
|
}, {});
|
||||||
for (const prefix in entries) {
|
for (const prefix in entries) {
|
||||||
const cacheKey = { ...key, prompt: key.prompt + prefix };
|
const cacheKey = {
|
||||||
|
...key,
|
||||||
|
text: key.text.slice(0, key.position) + prefix + key.text.slice(key.position),
|
||||||
|
position: key.position + prefix.length
|
||||||
|
};
|
||||||
const cacheValue = {
|
const cacheValue = {
|
||||||
...value,
|
...value,
|
||||||
choices: entries[prefix].map((choice) => {
|
choices: entries[prefix].map((choice) => {
|
||||||
|
|
@ -642,8 +649,7 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
||||||
}
|
}
|
||||||
async ping(tries = 0) {
|
async ping(tries = 0) {
|
||||||
try {
|
try {
|
||||||
const response = await import_axios2.default.get(`${this.serverUrl}/`);
|
const response = await import_axios2.default.get(this.serverUrl);
|
||||||
(0, import_assert.strict)(response.status == 200);
|
|
||||||
this.changeStatus("ready");
|
this.changeStatus("ready");
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -671,6 +677,14 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
createPrompt(request2) {
|
||||||
|
const maxLines = 20;
|
||||||
|
const prefix = request2.text.slice(0, request2.position);
|
||||||
|
const lines = splitLines(prefix);
|
||||||
|
const cutoff = Math.max(lines.length - maxLines, 0);
|
||||||
|
const prompt = lines.slice(cutoff).join("");
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
setServerUrl(serverUrl) {
|
setServerUrl(serverUrl) {
|
||||||
this.serverUrl = serverUrl.replace(/\/$/, "");
|
this.serverUrl = serverUrl.replace(/\/$/, "");
|
||||||
this.ping();
|
this.ping();
|
||||||
|
|
@ -689,7 +703,20 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
||||||
resolve2(this.completionCache.get(request2));
|
resolve2(this.completionCache.get(request2));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const promise = this.wrapApiPromise(this.api.default.completionsV1CompletionsPost(request2));
|
const prompt = this.createPrompt(request2);
|
||||||
|
if (isBlank(prompt)) {
|
||||||
|
return new CancelablePromise((resolve2) => {
|
||||||
|
resolve2({
|
||||||
|
id: "agent-" + (0, import_uuid.v4)(),
|
||||||
|
created: (/* @__PURE__ */ new Date()).getTime(),
|
||||||
|
choices: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const promise = this.wrapApiPromise(this.api.default.completionsV1CompletionsPost({
|
||||||
|
prompt,
|
||||||
|
language: request2.language
|
||||||
|
}));
|
||||||
return cancelable(
|
return cancelable(
|
||||||
promise.then((response) => {
|
promise.then((response) => {
|
||||||
this.completionCache.set(request2, response);
|
this.completionCache.set(request2, response);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -31,6 +31,7 @@
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"lru-cache": "^9.1.1",
|
"lru-cache": "^9.1.1",
|
||||||
"object-hash": "^3.0.0",
|
"object-hash": "^3.0.0",
|
||||||
"object-sizeof": "^2.6.1"
|
"object-sizeof": "^2.6.1",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { LRUCache } from "lru-cache";
|
import { LRUCache } from "lru-cache";
|
||||||
import hashObject from "object-hash";
|
import hashObject from "object-hash";
|
||||||
import sizeOfObject from "object-sizeof";
|
import sizeOfObject from "object-sizeof";
|
||||||
import { CompletionRequest, CompletionResponse } from "./generated";
|
import { CompletionRequest, CompletionResponse } from "./types";
|
||||||
import { splitLines, splitWords } from "./utils";
|
import { splitLines, splitWords } from "./utils";
|
||||||
|
|
||||||
type CompletionCacheKey = CompletionRequest;
|
type CompletionCacheKey = CompletionRequest;
|
||||||
|
|
@ -76,7 +76,11 @@ export class CompletionCache {
|
||||||
return grouped;
|
return grouped;
|
||||||
}, {});
|
}, {});
|
||||||
for (const prefix in entries) {
|
for (const prefix in entries) {
|
||||||
const cacheKey = { ...key, prompt: key.prompt + prefix };
|
const cacheKey = {
|
||||||
|
...key,
|
||||||
|
text: key.text.slice(0, key.position) + prefix + key.text.slice(key.position),
|
||||||
|
position: key.position + prefix.length
|
||||||
|
};
|
||||||
const cacheValue = {
|
const cacheValue = {
|
||||||
...value,
|
...value,
|
||||||
choices: entries[prefix].map((choice) => {
|
choices: entries[prefix].map((choice) => {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,10 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { strict as assert } from "assert";
|
import { v4 as uuid } from "uuid";
|
||||||
import { CompletionCache } from "./CompletionCache";
|
import { CompletionCache } from "./CompletionCache";
|
||||||
import { sleep, cancelable } from "./utils";
|
import { sleep, cancelable, splitLines, isBlank } from "./utils";
|
||||||
import { Agent, AgentEvent } from "./types";
|
import { Agent, AgentEvent, CompletionRequest, CompletionResponse } from "./types";
|
||||||
import {
|
import { TabbyApi, CancelablePromise, ApiError, ChoiceEvent, CompletionEvent } from "./generated";
|
||||||
TabbyApi,
|
|
||||||
CancelablePromise,
|
|
||||||
ApiError,
|
|
||||||
CompletionRequest,
|
|
||||||
CompletionResponse,
|
|
||||||
ChoiceEvent,
|
|
||||||
CompletionEvent,
|
|
||||||
} from "./generated";
|
|
||||||
|
|
||||||
export class TabbyAgent extends EventEmitter implements Agent {
|
export class TabbyAgent extends EventEmitter implements Agent {
|
||||||
private serverUrl: string = "http://127.0.0.1:5000";
|
private serverUrl: string = "http://127.0.0.1:5000";
|
||||||
|
|
@ -69,6 +61,15 @@ export class TabbyAgent extends EventEmitter implements Agent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createPrompt(request: CompletionRequest): string {
|
||||||
|
const maxLines = 20;
|
||||||
|
const prefix = request.text.slice(0, request.position);
|
||||||
|
const lines = splitLines(prefix);
|
||||||
|
const cutoff = Math.max(lines.length - maxLines, 0);
|
||||||
|
const prompt = lines.slice(cutoff).join("");
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
public setServerUrl(serverUrl: string): string {
|
public setServerUrl(serverUrl: string): string {
|
||||||
this.serverUrl = serverUrl.replace(/\/$/, ""); // Remove trailing slash
|
this.serverUrl = serverUrl.replace(/\/$/, ""); // Remove trailing slash
|
||||||
this.ping();
|
this.ping();
|
||||||
|
|
@ -90,7 +91,21 @@ export class TabbyAgent extends EventEmitter implements Agent {
|
||||||
resolve(this.completionCache.get(request));
|
resolve(this.completionCache.get(request));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const promise = this.wrapApiPromise(this.api.default.completionsV1CompletionsPost(request));
|
const prompt = this.createPrompt(request);
|
||||||
|
if (isBlank(prompt)) {
|
||||||
|
// Create a empty completion response
|
||||||
|
return new CancelablePromise((resolve) => {
|
||||||
|
resolve({
|
||||||
|
id: "agent-" + uuid(),
|
||||||
|
created: new Date().getTime(),
|
||||||
|
choices: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const promise = this.wrapApiPromise(this.api.default.completionsV1CompletionsPost({
|
||||||
|
prompt,
|
||||||
|
language: request.language,
|
||||||
|
}));
|
||||||
return cancelable(
|
return cancelable(
|
||||||
promise.then((response: CompletionResponse) => {
|
promise.then((response: CompletionResponse) => {
|
||||||
this.completionCache.set(request, response);
|
this.completionCache.set(request, response);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
export { TabbyAgent } from "./TabbyAgent";
|
export { TabbyAgent } from "./TabbyAgent";
|
||||||
export { Agent, AgentFunction, AgentEvent, StatusChangedEvent, agentEventNames } from "./types";
|
export {
|
||||||
|
Agent,
|
||||||
|
AgentFunction,
|
||||||
|
AgentEvent,
|
||||||
|
StatusChangedEvent,
|
||||||
|
CompletionRequest,
|
||||||
|
CompletionResponse,
|
||||||
|
agentEventNames,
|
||||||
|
} from "./types";
|
||||||
export {
|
export {
|
||||||
CancelablePromise,
|
CancelablePromise,
|
||||||
CancelError,
|
CancelError,
|
||||||
ApiError,
|
ApiError,
|
||||||
HTTPValidationError,
|
HTTPValidationError,
|
||||||
ValidationError,
|
ValidationError,
|
||||||
CompletionRequest,
|
|
||||||
CompletionResponse,
|
|
||||||
Choice,
|
Choice,
|
||||||
ChoiceEvent,
|
ChoiceEvent,
|
||||||
CompletionEvent,
|
CompletionEvent,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,18 @@
|
||||||
import { CancelablePromise, ChoiceEvent, CompletionEvent, CompletionRequest, CompletionResponse } from "./generated";
|
import {
|
||||||
|
CancelablePromise,
|
||||||
|
ChoiceEvent,
|
||||||
|
CompletionEvent,
|
||||||
|
CompletionResponse as ApiCompletionResponse,
|
||||||
|
} from "./generated";
|
||||||
|
|
||||||
|
export type CompletionRequest = {
|
||||||
|
filepath: string;
|
||||||
|
language: string;
|
||||||
|
text: string;
|
||||||
|
position: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CompletionResponse = ApiCompletionResponse;
|
||||||
|
|
||||||
export interface AgentFunction {
|
export interface AgentFunction {
|
||||||
setServerUrl(url: string): string;
|
setServerUrl(url: string): string;
|
||||||
|
|
@ -11,10 +25,10 @@ export interface AgentFunction {
|
||||||
export type StatusChangedEvent = {
|
export type StatusChangedEvent = {
|
||||||
event: "statusChanged";
|
event: "statusChanged";
|
||||||
status: "connecting" | "ready" | "disconnected";
|
status: "connecting" | "ready" | "disconnected";
|
||||||
}
|
};
|
||||||
|
|
||||||
export type AgentEvent = StatusChangedEvent;
|
export type AgentEvent = StatusChangedEvent;
|
||||||
export const agentEventNames: AgentEvent['event'][] = ["statusChanged"];
|
export const agentEventNames: AgentEvent["event"][] = ["statusChanged"];
|
||||||
|
|
||||||
export interface AgentEventEmitter {
|
export interface AgentEventEmitter {
|
||||||
on<T extends AgentEvent>(eventName: T["event"], callback: (event: T) => void): this;
|
on<T extends AgentEvent>(eventName: T["event"], callback: (event: T) => void): this;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ export function splitWords(input: string) {
|
||||||
return input.match(/\w+|\W+/g).filter(Boolean); // Split consecutive words and non-words
|
return input.match(/\w+|\W+/g).filter(Boolean); // Split consecutive words and non-words
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isBlank(input: string) {
|
||||||
|
return input.trim().length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
import { CancelablePromise } from "./generated";
|
import { CancelablePromise } from "./generated";
|
||||||
export function cancelable<T>(promise: Promise<T>, cancel: () => void): CancelablePromise<T> {
|
export function cancelable<T>(promise: Promise<T>, cancel: () => void): CancelablePromise<T> {
|
||||||
return new CancelablePromise((resolve, reject, onCancel) => {
|
return new CancelablePromise((resolve, reject, onCancel) => {
|
||||||
|
|
|
||||||
|
|
@ -1140,6 +1140,11 @@ universalify@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||||
|
|
||||||
|
uuid@^9.0.0:
|
||||||
|
version "9.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||||
|
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||||
|
|
||||||
webidl-conversions@^4.0.2:
|
webidl-conversions@^4.0.2:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
||||||
return emptyResponse;
|
return emptyResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const promptRange = this.calculatePromptRange(position);
|
|
||||||
const prompt = document.getText(promptRange);
|
|
||||||
if (this.isNil(prompt)) {
|
|
||||||
console.debug("Prompt is empty, skipping");
|
|
||||||
return emptyResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentTimestamp = Date.now();
|
const currentTimestamp = Date.now();
|
||||||
this.latestTimestamp = currentTimestamp;
|
this.latestTimestamp = currentTimestamp;
|
||||||
|
|
||||||
|
|
@ -59,23 +52,18 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
||||||
|
|
||||||
const replaceRange = this.calculateReplaceRange(document, position);
|
const replaceRange = this.calculateReplaceRange(document, position);
|
||||||
|
|
||||||
console.debug(
|
|
||||||
"Requesting: ",
|
|
||||||
{
|
|
||||||
uuid: this.uuid,
|
|
||||||
timestamp: currentTimestamp,
|
|
||||||
prompt,
|
|
||||||
language: document.languageId
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.pendingCompletion) {
|
if (this.pendingCompletion) {
|
||||||
this.pendingCompletion.cancel();
|
this.pendingCompletion.cancel();
|
||||||
}
|
}
|
||||||
this.pendingCompletion = this.agent.getCompletions({
|
|
||||||
prompt: prompt as string, // Prompt is already nil-checked
|
const request = {
|
||||||
|
filepath: document.uri.fsPath,
|
||||||
language: document.languageId, // https://code.visualstudio.com/docs/languages/identifiers
|
language: document.languageId, // https://code.visualstudio.com/docs/languages/identifiers
|
||||||
});
|
text: document.getText(),
|
||||||
|
position: document.offsetAt(position),
|
||||||
|
};
|
||||||
|
console.debug("Request: ", request)
|
||||||
|
this.pendingCompletion = this.agent.getCompletions(request);
|
||||||
|
|
||||||
const completion = await this.pendingCompletion.catch((_: Error) => {
|
const completion = await this.pendingCompletion.catch((_: Error) => {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -93,10 +81,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
||||||
this.suggestionDelay = configuration.get("suggestionDelay", 150);
|
this.suggestionDelay = configuration.get("suggestionDelay", 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isNil(value: string | undefined | null): boolean {
|
|
||||||
return value === undefined || value === null || value.length === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private toInlineCompletions(tabbyCompletion: CompletionResponse | null, range: Range): InlineCompletionItem[] {
|
private toInlineCompletions(tabbyCompletion: CompletionResponse | null, range: Range): InlineCompletionItem[] {
|
||||||
return (
|
return (
|
||||||
tabbyCompletion?.choices?.map((choice: any) => {
|
tabbyCompletion?.choices?.map((choice: any) => {
|
||||||
|
|
@ -121,12 +105,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
||||||
return ")]}".indexOf(suffix) > -1;
|
return ")]}".indexOf(suffix) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculatePromptRange(position: Position): Range {
|
|
||||||
const maxLines = 20;
|
|
||||||
const firstLine = Math.max(position.line - maxLines, 0);
|
|
||||||
return new Range(firstLine, 0, position.line, position.character);
|
|
||||||
}
|
|
||||||
|
|
||||||
private calculateReplaceRange(document: TextDocument, position: Position): Range {
|
private calculateReplaceRange(document: TextDocument, position: Position): Range {
|
||||||
const hasSuffixParen = this.hasSuffixParen(document, position);
|
const hasSuffixParen = this.hasSuffixParen(document, position);
|
||||||
if (hasSuffixParen) {
|
if (hasSuffixParen) {
|
||||||
|
|
|
||||||
|
|
@ -2533,6 +2533,7 @@ supports-preserve-symlinks-flag@^1.0.0:
|
||||||
lru-cache "^9.1.1"
|
lru-cache "^9.1.1"
|
||||||
object-hash "^3.0.0"
|
object-hash "^3.0.0"
|
||||||
object-sizeof "^2.6.1"
|
object-sizeof "^2.6.1"
|
||||||
|
uuid "^9.0.0"
|
||||||
|
|
||||||
tapable@^2.1.1, tapable@^2.2.0:
|
tapable@^2.1.1, tapable@^2.2.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
|
|
@ -2716,6 +2717,11 @@ util@^0.12.0:
|
||||||
is-typed-array "^1.1.3"
|
is-typed-array "^1.1.3"
|
||||||
which-typed-array "^1.1.2"
|
which-typed-array "^1.1.2"
|
||||||
|
|
||||||
|
uuid@^9.0.0:
|
||||||
|
version "9.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||||
|
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||||
|
|
||||||
vsce@^2.15.0:
|
vsce@^2.15.0:
|
||||||
version "2.15.0"
|
version "2.15.0"
|
||||||
resolved "https://registry.npmmirror.com/vsce/-/vsce-2.15.0.tgz#4a992e78532092a34a755143c6b6c2cabcb7d729"
|
resolved "https://registry.npmmirror.com/vsce/-/vsce-2.15.0.tgz#4a992e78532092a34a755143c6b6c2cabcb7d729"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue