feat: tabby agent auth (#240)

* feat: Support tabby server auth.

* fix notification toggle command.

* feat: add vscode web support.
improve-workflow
Zhiming Ma 2023-06-15 23:53:21 +08:00 committed by GitHub
parent 008ad75e1f
commit 11e4a5991d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 6623 additions and 23333 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,5 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
type ApiRequestOptions = {
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
readonly url: string;
readonly path?: Record<string, any>;
readonly cookies?: Record<string, any>;
readonly headers?: Record<string, any>;
readonly query?: Record<string, any>;
readonly formData?: Record<string, any>;
readonly body?: any;
readonly mediaType?: string;
readonly responseHeader?: string;
readonly errors?: Record<number, string>;
};
declare class CancelError extends Error {
constructor(message: string);
get isCancelled(): boolean;
}
interface OnCancel { interface OnCancel {
readonly isResolved: boolean; readonly isResolved: boolean;
readonly isRejected: boolean; readonly isRejected: boolean;
@ -54,38 +36,21 @@ type LogEventRequest$1 = {
choice_index: number; choice_index: number;
}; };
type ApiResult = {
readonly url: string;
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly body: any;
};
declare class ApiError extends Error {
readonly url: string;
readonly status: number;
readonly statusText: string;
readonly body: any;
readonly request: ApiRequestOptions;
constructor(request: ApiRequestOptions, response: ApiResult, message: string);
}
type AgentConfig = { type AgentConfig = {
server?: { server: {
endpoint?: string; endpoint: string;
}; };
logs?: { logs: {
level?: "debug" | "error" | "silent"; level: "debug" | "error" | "silent";
}; };
anonymousUsageTracking?: { anonymousUsageTracking: {
disable?: boolean; disable: boolean;
}; };
}; };
type AgentInitOptions = { type AgentInitOptions = {
config?: AgentConfig; config: Partial<AgentConfig>;
client?: string; client: string;
}; };
type CompletionRequest = { type CompletionRequest = {
filepath: string; filepath: string;
@ -95,17 +60,33 @@ type CompletionRequest = {
}; };
type CompletionResponse = CompletionResponse$1; type CompletionResponse = CompletionResponse$1;
type LogEventRequest = LogEventRequest$1; type LogEventRequest = LogEventRequest$1;
type AgentStatus = "notInitialized" | "ready" | "disconnected" | "unauthorized";
interface AgentFunction { interface AgentFunction {
initialize(options?: AgentInitOptions): boolean; initialize(options: Partial<AgentInitOptions>): Promise<boolean>;
updateConfig(config: AgentConfig): boolean; updateConfig(config: Partial<AgentConfig>): Promise<boolean>;
getConfig(): AgentConfig; getConfig(): AgentConfig;
getStatus(): "connecting" | "ready" | "disconnected"; getStatus(): AgentStatus;
/**
* @returns string auth url if AgentStatus is `unauthorized`, null otherwise
* @throws Error if agent is not initialized
*/
startAuth(): CancelablePromise<string | null>;
/**
* @param request
* @returns
* @throws Error if agent is not initialized
*/
getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>; getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>;
/**
* @param event
* @returns
* @throws Error if agent is not initialized
*/
postEvent(event: LogEventRequest): CancelablePromise<boolean>; postEvent(event: LogEventRequest): CancelablePromise<boolean>;
} }
type StatusChangedEvent = { type StatusChangedEvent = {
event: "statusChanged"; event: "statusChanged";
status: "connecting" | "ready" | "disconnected"; status: AgentStatus;
}; };
type ConfigUpdatedEvent = { type ConfigUpdatedEvent = {
event: "configUpdated"; event: "configUpdated";
@ -118,24 +99,51 @@ interface AgentEventEmitter {
} }
type Agent = AgentFunction & AgentEventEmitter; type Agent = AgentFunction & AgentEventEmitter;
type StoredData = {
auth: {
[endpoint: string]: {
jwt: string;
};
};
};
interface DataStore {
data: Partial<StoredData>;
load(): PromiseLike<void>;
save(): PromiseLike<void>;
}
/**
* Different from AgentInitOptions or AgentConfig, this may contain non-serializable objects,
* so it is not suitable for cli, but only used when imported as module by other js project.
*/
type TabbyAgentOptions = {
dataStore: DataStore;
};
declare class TabbyAgent extends EventEmitter implements Agent { declare class TabbyAgent extends EventEmitter implements Agent {
private readonly logger; private readonly logger;
private config; private config;
private status; private status;
private api; private api;
private auth;
private dataStore;
private completionCache; private completionCache;
constructor(); static readonly tryConnectInterval: number;
private onConfigUpdated; private tryingConnectTimer;
private constructor();
static create(options?: Partial<TabbyAgentOptions>): Promise<TabbyAgent>;
private applyConfig;
private onAuthUpdated;
private changeStatus; private changeStatus;
private ping;
private callApi; private callApi;
private healthCheck;
private createSegments; private createSegments;
initialize(params: AgentInitOptions): boolean; initialize(options: Partial<AgentInitOptions>): Promise<boolean>;
updateConfig(config: AgentConfig): boolean; updateConfig(config: Partial<AgentConfig>): Promise<boolean>;
getConfig(): AgentConfig; getConfig(): AgentConfig;
getStatus(): "connecting" | "ready" | "disconnected"; getStatus(): AgentStatus;
startAuth(): CancelablePromise<string | null>;
getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>; getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>;
postEvent(request: LogEventRequest): CancelablePromise<boolean>; postEvent(request: LogEventRequest): CancelablePromise<boolean>;
} }
export { Agent, AgentConfig, AgentEvent, AgentFunction, ApiError, CancelError, CancelablePromise, Choice, CompletionRequest, CompletionResponse, StatusChangedEvent, TabbyAgent, agentEventNames }; export { Agent, AgentConfig, AgentEvent, AgentFunction, AgentStatus, CancelablePromise, CompletionRequest, CompletionResponse, ConfigUpdatedEvent, DataStore, LogEventRequest, StatusChangedEvent, TabbyAgent, TabbyAgentOptions, agentEventNames };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -47,8 +47,6 @@ var __privateSet = (obj, member, value, setter) => {
// src/index.ts // src/index.ts
var src_exports = {}; var src_exports = {};
__export(src_exports, { __export(src_exports, {
ApiError: () => ApiError,
CancelError: () => CancelError,
CancelablePromise: () => CancelablePromise, CancelablePromise: () => CancelablePromise,
TabbyAgent: () => TabbyAgent, TabbyAgent: () => TabbyAgent,
agentEventNames: () => agentEventNames agentEventNames: () => agentEventNames
@ -56,8 +54,7 @@ __export(src_exports, {
module.exports = __toCommonJS(src_exports); module.exports = __toCommonJS(src_exports);
// src/TabbyAgent.ts // src/TabbyAgent.ts
var import_axios2 = __toESM(require("axios")); var import_events2 = require("events");
var import_events = require("events");
var import_uuid = require("uuid"); var import_uuid = require("uuid");
var import_deep_equal2 = __toESM(require("deep-equal")); var import_deep_equal2 = __toESM(require("deep-equal"));
var import_deepmerge = __toESM(require("deepmerge")); var import_deepmerge = __toESM(require("deepmerge"));
@ -246,13 +243,13 @@ var getQueryString = (params) => {
}; };
var getUrl = (config, options) => { var getUrl = (config, options) => {
const encoder = config.ENCODE_PATH || encodeURI; const encoder = config.ENCODE_PATH || encodeURI;
const path2 = options.url.replace("{api-version}", config.VERSION).replace(/{(.*?)}/g, (substring, group) => { const path = options.url.replace("{api-version}", config.VERSION).replace(/{(.*?)}/g, (substring, group) => {
if (options.path?.hasOwnProperty(group)) { if (options.path?.hasOwnProperty(group)) {
return encoder(String(options.path[group])); return encoder(String(options.path[group]));
} }
return substring; return substring;
}); });
const url = `${config.BASE}${path2}`; const url = `${config.BASE}${path}`;
if (options.query) { if (options.query) {
return `${url}${getQueryString(options.query)}`; return `${url}${getQueryString(options.query)}`;
} }
@ -461,13 +458,23 @@ var V1Service = class {
} }
}); });
} }
/**
* @returns any Health
* @throws ApiError
*/
health() {
return this.httpRequest.request({
method: "POST",
url: "/v1/health"
});
}
}; };
// src/generated/TabbyApi.ts // src/generated/TabbyApi.ts
var TabbyApi = class { var TabbyApi = class {
constructor(config, HttpRequest = AxiosHttpRequest) { constructor(config, HttpRequest = AxiosHttpRequest) {
this.request = new HttpRequest({ this.request = new HttpRequest({
BASE: config?.BASE ?? "https://app.tabbyml.com/api/workspace/tabbyml/tabby", BASE: config?.BASE ?? "https://tabbyml.app.tabbyml.com/tabby",
VERSION: config?.VERSION ?? "0.1.0", VERSION: config?.VERSION ?? "0.1.0",
WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false, WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
CREDENTIALS: config?.CREDENTIALS ?? "include", CREDENTIALS: config?.CREDENTIALS ?? "include",
@ -482,9 +489,6 @@ var TabbyApi = class {
}; };
// src/utils.ts // src/utils.ts
function sleep(milliseconds) {
return new Promise((r) => setTimeout(r, milliseconds));
}
function splitLines(input) { function splitLines(input) {
return input.match(/.*(?:$|\r?\n)/g).filter(Boolean); return input.match(/.*(?:$|\r?\n)/g).filter(Boolean);
} }
@ -507,36 +511,79 @@ function cancelable(promise, cancel) {
}); });
} }
// src/AgentConfig.ts // src/Auth.ts
var defaultAgentConfig = { var import_events = require("events");
server: {
endpoint: "http://localhost:8080" // src/cloud/services/ApiService.ts
}, var ApiService = class {
logs: { constructor(httpRequest) {
level: "error" this.httpRequest = httpRequest;
}, }
anonymousUsageTracking: { /**
disable: false * @returns DeviceTokenResponse Success
* @throws ApiError
*/
deviceToken() {
return this.httpRequest.request({
method: "POST",
url: "/device-token"
});
}
/**
* @param code
* @returns DeviceTokenAcceptResponse Success
* @throws ApiError
*/
deviceTokenAccept(query) {
return this.httpRequest.request({
method: "POST",
url: "/device-token/accept",
query
});
} }
}; };
// src/CompletionCache.ts // src/cloud/CloudApi.ts
var import_lru_cache = require("lru-cache"); var CloudApi = class {
var import_object_hash = __toESM(require("object-hash")); constructor(config, HttpRequest = AxiosHttpRequest) {
var import_object_sizeof = __toESM(require("object-sizeof")); this.request = new HttpRequest({
BASE: config?.BASE ?? "https://tabbyml.app.tabbyml.com/tabby",
VERSION: config?.VERSION ?? "0.0.0",
WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
CREDENTIALS: config?.CREDENTIALS ?? "include",
TOKEN: config?.TOKEN,
USERNAME: config?.USERNAME,
PASSWORD: config?.PASSWORD,
HEADERS: config?.HEADERS,
ENCODE_PATH: config?.ENCODE_PATH
});
this.api = new ApiService(this.request);
}
};
// src/dataStore.ts
var dataStore = false ? null : (() => {
const dataFile = require("path").join(require("os").homedir(), ".tabby", "agent", "data.json");
const fs = require("fs-extra");
return {
data: {},
load: async function() {
this.data = await fs.readJson(dataFile, { throws: false }) || {};
},
save: async function() {
await fs.outputJson(dataFile, this.data);
}
};
})();
// src/logger.ts // src/logger.ts
var import_os = __toESM(require("os"));
var import_path = __toESM(require("path"));
var import_browser_or_node = require("browser-or-node");
var rotatingFileStream = __toESM(require("rotating-file-stream"));
var import_pino = __toESM(require("pino")); var import_pino = __toESM(require("pino"));
var stream = import_browser_or_node.isBrowser ? null : ( var stream = false ? null : (
/** /**
* Default rotating file locate at `~/.tabby/agent-logs/`. * Default rotating file locate at `~/.tabby/agent-logs/`.
*/ */
rotatingFileStream.createStream("tabby-agent.log", { require("rotating-file-stream").createStream("tabby-agent.log", {
path: import_path.default.join(import_os.default.homedir(), ".tabby", "agent-logs"), path: require("path").join(require("os").homedir(), ".tabby", "agent-logs"),
size: "10M", size: "10M",
interval: "1d" interval: "1d"
}) })
@ -547,7 +594,150 @@ rootLogger.onChild = (child) => {
allLoggers.push(child); allLoggers.push(child);
}; };
// src/Auth.ts
var _Auth = class extends import_events.EventEmitter {
constructor(options) {
super();
// 3 days
this.logger = rootLogger.child({ component: "Auth" });
this.dataStore = null;
this.pollingTokenTimer = null;
this.refreshTokenTimer = null;
this.authApi = null;
this.jwt = null;
this.endpoint = options.endpoint;
this.dataStore = options.dataStore || dataStore;
const authApiBase = this.endpoint.replace(/\/tabby\/?$/, "/api");
this.authApi = new CloudApi({ BASE: authApiBase });
}
static async create(options) {
const auth = new _Auth(options);
await auth.load();
return auth;
}
get token() {
return this.jwt;
}
async load() {
if (!this.dataStore)
return;
try {
await this.dataStore.load();
const storedJwt = this.dataStore.data["auth"]?.[this.endpoint]?.jwt;
if (typeof storedJwt === "string" && this.jwt !== storedJwt) {
this.logger.debug({ storedJwt }, "Load jwt from data store.");
this.jwt = storedJwt;
this.scheduleRefreshToken();
}
} catch (error) {
this.logger.debug({ error }, "Error when loading auth");
}
}
async save() {
if (!this.dataStore)
return;
try {
if (this.jwt) {
if (this.dataStore.data["auth"]?.[this.endpoint]?.jwt === this.jwt)
return;
this.dataStore.data["auth"] = { ...this.dataStore.data["auth"], [this.endpoint]: { jwt: this.jwt } };
} else {
if (typeof this.dataStore.data["auth"]?.[this.endpoint] === "undefined")
return;
delete this.dataStore.data["auth"][this.endpoint];
}
await this.dataStore.save();
this.logger.debug("Save changes to data store.");
} catch (error) {
this.logger.error({ error }, "Error when saving auth");
}
}
async reset() {
if (this.jwt) {
this.jwt = null;
await this.save();
}
if (this.refreshTokenTimer) {
clearTimeout(this.refreshTokenTimer);
this.refreshTokenTimer = null;
}
if (this.pollingTokenTimer) {
clearInterval(this.pollingTokenTimer);
this.pollingTokenTimer = null;
}
}
async requestToken() {
try {
await this.reset();
const deviceToken = await this.authApi.api.deviceToken();
this.logger.debug({ deviceToken }, "Request device token response");
const authUrl = new URL(_Auth.authPageUrl);
authUrl.searchParams.append("code", deviceToken.data.code);
this.schedulePollingToken(deviceToken.data.code);
return authUrl.toString();
} catch (error) {
this.logger.error({ error }, "Error when requesting token");
throw error;
}
}
async schedulePollingToken(code) {
this.pollingTokenTimer = setInterval(async () => {
try {
const response = await this.authApi.api.deviceTokenAccept({ code });
this.logger.debug({ response }, "Poll jwt response");
this.jwt = response.data.jwt;
await this.save();
this.scheduleRefreshToken();
super.emit("updated", this.jwt);
clearInterval(this.pollingTokenTimer);
this.pollingTokenTimer = null;
} catch (error) {
if (error instanceof ApiError && [401, 403, 405].indexOf(error.status) !== -1) {
this.logger.debug({ error }, "Expected error when polling jwt");
} else {
this.logger.error({ error }, "Error when polling jwt");
}
}
}, _Auth.pollTokenInterval);
}
scheduleRefreshToken() {
if (this.refreshTokenTimer) {
clearTimeout(this.refreshTokenTimer);
this.refreshTokenTimer = null;
}
if (!this.jwt) {
return null;
}
const expireAt = Date.now() / 1e3 + 60 * 60 * 24 * 7;
const refreshDelay = Math.max(0, expireAt * 1e3 - Date.now() - _Auth.refreshTokenInterval);
this.refreshTokenTimer = setTimeout(async () => {
this.logger.debug({ expireAt }, "Refresh token");
}, refreshDelay);
}
};
var Auth = _Auth;
Auth.authPageUrl = "https://app.tabbyml.com/account/device-token";
Auth.pollTokenInterval = 5e3;
// 5 seconds
Auth.refreshTokenInterval = 1e3 * 60 * 60 * 24 * 3;
// src/AgentConfig.ts
var defaultAgentConfig = {
server: {
endpoint: "http://localhost:8080"
},
logs: {
level: "silent"
},
anonymousUsageTracking: {
disable: false
}
};
// src/CompletionCache.ts // src/CompletionCache.ts
var import_lru_cache = require("lru-cache");
var import_object_hash = __toESM(require("object-hash"));
var import_object_sizeof = __toESM(require("object-sizeof"));
var CompletionCache = class { var CompletionCache = class {
constructor() { constructor() {
this.logger = rootLogger.child({ component: "CompletionCache" }); this.logger = rootLogger.child({ component: "CompletionCache" });
@ -695,19 +885,40 @@ async function postprocess(request2, response) {
} }
// src/TabbyAgent.ts // src/TabbyAgent.ts
var TabbyAgent = class extends import_events.EventEmitter { var _TabbyAgent = class extends import_events2.EventEmitter {
constructor() { constructor() {
super(); super();
this.logger = rootLogger.child({ component: "TabbyAgent" }); this.logger = rootLogger.child({ component: "TabbyAgent" });
this.config = defaultAgentConfig; this.config = defaultAgentConfig;
this.status = "connecting"; this.status = "notInitialized";
this.dataStore = null;
this.completionCache = new CompletionCache(); this.completionCache = new CompletionCache();
this.onConfigUpdated(); // 30s
this.tryingConnectTimer = null;
this.tryingConnectTimer = setInterval(async () => {
if (this.status === "disconnected") {
this.logger.debug("Trying to connect...");
await this.healthCheck();
} }
onConfigUpdated() { }, _TabbyAgent.tryConnectInterval);
}
static async create(options) {
const agent = new _TabbyAgent();
agent.dataStore = options?.dataStore;
await agent.applyConfig();
return agent;
}
async applyConfig() {
allLoggers.forEach((logger2) => logger2.level = this.config.logs.level); allLoggers.forEach((logger2) => logger2.level = this.config.logs.level);
this.api = new TabbyApi({ BASE: this.config.server.endpoint }); if (this.config.server.endpoint !== this.auth?.endpoint) {
this.ping(); this.auth = await Auth.create({ endpoint: this.config.server.endpoint, dataStore: this.dataStore });
this.auth.on("updated", this.onAuthUpdated.bind(this));
}
this.api = new TabbyApi({ BASE: this.config.server.endpoint, TOKEN: this.auth.token });
}
async onAuthUpdated() {
this.api = new TabbyApi({ BASE: this.config.server.endpoint, TOKEN: this.auth.token });
await this.healthCheck();
} }
changeStatus(status) { changeStatus(status) {
if (this.status != status) { if (this.status != status) {
@ -717,22 +928,6 @@ var TabbyAgent = class extends import_events.EventEmitter {
super.emit("statusChanged", event); super.emit("statusChanged", event);
} }
} }
async ping(tries = 0) {
try {
await import_axios2.default.get(this.config.server.endpoint);
this.changeStatus("ready");
return true;
} catch (e) {
if (tries > 5) {
this.changeStatus("disconnected");
return false;
}
this.changeStatus("connecting");
const pingRetryDelay = 1e3;
await sleep(pingRetryDelay);
return this.ping(tries + 1);
}
}
callApi(api, request2) { callApi(api, request2) {
this.logger.debug({ api: api.name, request: request2 }, "API request"); this.logger.debug({ api: api.name, request: request2 }, "API request");
const promise = api.call(this.api.v1, request2); const promise = api.call(this.api.v1, request2);
@ -742,11 +937,18 @@ var TabbyAgent = class extends import_events.EventEmitter {
this.changeStatus("ready"); this.changeStatus("ready");
return response; return response;
}).catch((error) => { }).catch((error) => {
this.logger.debug({ api: api.name }, "API request canceled"); if (!!error.isCancelled) {
throw error; this.logger.debug({ api: api.name, error }, "API request canceled");
}).catch((error) => { } else if (error.name === "ApiError" && [401, 403, 405].indexOf(error.status) !== -1) {
this.logger.debug({ api: api.name, error }, "API unauthorized");
this.changeStatus("unauthorized");
} else if (error.name === "ApiError") {
this.logger.error({ api: api.name, error }, "API error"); this.logger.error({ api: api.name, error }, "API error");
this.changeStatus("disconnected"); this.changeStatus("disconnected");
} else {
this.logger.error({ api: api.name, error }, "API request failed with unknown error");
this.changeStatus("disconnected");
}
throw error; throw error;
}), }),
() => { () => {
@ -754,6 +956,10 @@ var TabbyAgent = class extends import_events.EventEmitter {
} }
); );
} }
async healthCheck() {
return this.callApi(this.api.v1.health, {}).catch(() => {
});
}
createSegments(request2) { createSegments(request2) {
const maxLines = 20; const maxLines = 20;
const prefix = request2.text.slice(0, request2.position); const prefix = request2.text.slice(0, request2.position);
@ -765,26 +971,27 @@ var TabbyAgent = class extends import_events.EventEmitter {
suffix: suffixLines.slice(0, maxLines).join("") suffix: suffixLines.slice(0, maxLines).join("")
}; };
} }
initialize(params) { async initialize(options) {
if (params.config) { if (options.client) {
this.updateConfig(params.config); allLoggers.forEach((logger2) => logger2.setBindings && logger2.setBindings({ client: options.client }));
} }
if (params.client) { if (options.config) {
allLoggers.forEach((logger2) => logger2.setBindings && logger2.setBindings({ client: params.client })); await this.updateConfig(options.config);
} }
this.logger.debug({ params }, "Initialized"); this.logger.debug({ options }, "Initialized");
return true; return this.status !== "notInitialized";
} }
updateConfig(config) { async updateConfig(config) {
const mergedConfig = (0, import_deepmerge.default)(this.config, config); const mergedConfig = (0, import_deepmerge.default)(this.config, config);
if (!(0, import_deep_equal2.default)(this.config, mergedConfig)) { if (!(0, import_deep_equal2.default)(this.config, mergedConfig)) {
this.config = mergedConfig; this.config = mergedConfig;
this.onConfigUpdated(); await this.applyConfig();
const event = { event: "configUpdated", config: this.config }; const event = { event: "configUpdated", config: this.config };
this.logger.debug({ event }, "Config updated"); this.logger.debug({ event }, "Config updated");
super.emit("configUpdated", event); super.emit("configUpdated", event);
} }
return true; await this.healthCheck();
return this.status !== "notInitialized";
} }
getConfig() { getConfig() {
return this.config; return this.config;
@ -792,7 +999,25 @@ var TabbyAgent = class extends import_events.EventEmitter {
getStatus() { getStatus() {
return this.status; return this.status;
} }
startAuth() {
return cancelable(
this.healthCheck().then(() => {
if (this.status === "unauthorized") {
return this.auth.requestToken();
}
return null;
}),
() => {
if (this.status === "unauthorized") {
this.auth.reset();
}
}
);
}
getCompletions(request2) { getCompletions(request2) {
if (this.status === "notInitialized") {
throw new Error("Agent is not initialized");
}
if (this.completionCache.has(request2)) { if (this.completionCache.has(request2)) {
this.logger.debug({ request: request2 }, "Completion cache hit"); this.logger.debug({ request: request2 }, "Completion cache hit");
return new CancelablePromise((resolve2) => { return new CancelablePromise((resolve2) => {
@ -826,16 +1051,19 @@ var TabbyAgent = class extends import_events.EventEmitter {
); );
} }
postEvent(request2) { postEvent(request2) {
if (this.status === "notInitialized") {
throw new Error("Agent is not initialized");
}
return this.callApi(this.api.v1.event, request2); return this.callApi(this.api.v1.event, request2);
} }
}; };
var TabbyAgent = _TabbyAgent;
TabbyAgent.tryConnectInterval = 1e3 * 30;
// src/Agent.ts // src/Agent.ts
var agentEventNames = ["statusChanged", "configUpdated"]; var agentEventNames = ["statusChanged", "configUpdated"];
// Annotate the CommonJS export names for ESM import in node: // Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = { 0 && (module.exports = {
ApiError,
CancelError,
CancelablePromise, CancelablePromise,
TabbyAgent, TabbyAgent,
agentEventNames agentEventNames

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@
"build": "tsup" "build": "tsup"
}, },
"devDependencies": { "devDependencies": {
"@types/fs-extra": "^11.0.1",
"@types/node": "^16.18.32", "@types/node": "^16.18.32",
"esbuild-plugin-polyfill-node": "^0.2.0", "esbuild-plugin-polyfill-node": "^0.2.0",
"openapi-typescript-codegen": "^0.24.0", "openapi-typescript-codegen": "^0.24.0",
@ -24,10 +25,10 @@
}, },
"dependencies": { "dependencies": {
"axios": "^1.4.0", "axios": "^1.4.0",
"browser-or-node": "^2.1.1",
"deep-equal": "^2.2.1", "deep-equal": "^2.2.1",
"deepmerge": "^4.3.1", "deepmerge": "^4.3.1",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"fs-extra": "^11.1.1",
"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",

View File

@ -7,8 +7,8 @@ import {
import { AgentConfig } from "./AgentConfig"; import { AgentConfig } from "./AgentConfig";
export type AgentInitOptions = { export type AgentInitOptions = {
config?: AgentConfig; config: Partial<AgentConfig>;
client?: string; client: string;
}; };
export type CompletionRequest = { export type CompletionRequest = {
@ -22,18 +22,38 @@ export type CompletionResponse = ApiCompletionResponse;
export type LogEventRequest = ApiLogEventRequest; export type LogEventRequest = ApiLogEventRequest;
export type AgentStatus = "notInitialized" | "ready" | "disconnected" | "unauthorized";
export interface AgentFunction { export interface AgentFunction {
initialize(options?: AgentInitOptions): boolean; initialize(options: Partial<AgentInitOptions>): Promise<boolean>;
updateConfig(config: AgentConfig): boolean; updateConfig(config: Partial<AgentConfig>): Promise<boolean>;
getConfig(): AgentConfig; getConfig(): AgentConfig;
getStatus(): "connecting" | "ready" | "disconnected"; getStatus(): AgentStatus;
/**
* @returns string auth url if AgentStatus is `unauthorized`, null otherwise
* @throws Error if agent is not initialized
*/
startAuth(): CancelablePromise<string | null>;
/**
* @param request
* @returns
* @throws Error if agent is not initialized
*/
getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>; getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>;
/**
* @param event
* @returns
* @throws Error if agent is not initialized
*/
postEvent(event: LogEventRequest): CancelablePromise<boolean>; postEvent(event: LogEventRequest): CancelablePromise<boolean>;
} }
export type StatusChangedEvent = { export type StatusChangedEvent = {
event: "statusChanged"; event: "statusChanged";
status: "connecting" | "ready" | "disconnected"; status: AgentStatus;
}; };
export type ConfigUpdatedEvent = { export type ConfigUpdatedEvent = {
event: "configUpdated"; event: "configUpdated";

View File

@ -1,12 +1,12 @@
export type AgentConfig = { export type AgentConfig = {
server?: { server: {
endpoint?: string; endpoint: string;
}; };
logs?: { logs: {
level?: "debug" | "error" | "silent"; level: "debug" | "error" | "silent";
}; };
anonymousUsageTracking?: { anonymousUsageTracking: {
disable?: boolean; disable: boolean;
}; };
}; };
@ -15,7 +15,7 @@ export const defaultAgentConfig: AgentConfig = {
endpoint: "http://localhost:8080", endpoint: "http://localhost:8080",
}, },
logs: { logs: {
level: "error", level: "silent",
}, },
anonymousUsageTracking: { anonymousUsageTracking: {
disable: false, disable: false,

View File

@ -0,0 +1,145 @@
import { EventEmitter } from "events";
import { CloudApi } from "./cloud";
import { ApiError } from "./generated";
import { dataStore, DataStore } from "./dataStore";
import { rootLogger } from "./logger";
export type StorageData = {
auth: { [endpoint: string]: { jwt: string } };
};
export class Auth extends EventEmitter {
static readonly authPageUrl = "https://app.tabbyml.com/account/device-token";
static readonly pollTokenInterval = 5000; // 5 seconds
static readonly refreshTokenInterval = 1000 * 60 * 60 * 24 * 3; // 3 days
private readonly logger = rootLogger.child({ component: "Auth" });
readonly endpoint: string;
readonly dataStore: DataStore | null = null;
private pollingTokenTimer: ReturnType<typeof setInterval> | null = null;
private refreshTokenTimer: ReturnType<typeof setTimeout> | null = null;
private authApi: CloudApi | null = null;
private jwt: string | null = null;
static async create(options: { endpoint: string; dataStore?: DataStore }): Promise<Auth> {
const auth = new Auth(options);
await auth.load();
return auth;
}
constructor(options: { endpoint: string; dataStore?: DataStore }) {
super();
this.endpoint = options.endpoint;
this.dataStore = options.dataStore || dataStore;
// From tabby endpoint: http[s]://{namespace}.app.tabbyml.com/tabby[/]
// To auth endpoint: http[s]://{namespace}.app.tabbyml.com/api
const authApiBase = this.endpoint.replace(/\/tabby\/?$/, "/api");
this.authApi = new CloudApi({ BASE: authApiBase });
}
get token(): string | null {
return this.jwt;
}
private async load(): Promise<void> {
if (!this.dataStore) return;
try {
await this.dataStore.load();
const storedJwt = this.dataStore.data["auth"]?.[this.endpoint]?.jwt;
if (typeof storedJwt === "string" && this.jwt !== storedJwt) {
this.logger.debug({ storedJwt }, "Load jwt from data store.");
this.jwt = storedJwt;
this.scheduleRefreshToken();
}
} catch (error: any) {
this.logger.debug({ error }, "Error when loading auth");
}
}
private async save(): Promise<void> {
if (!this.dataStore) return;
try {
if (this.jwt) {
if (this.dataStore.data["auth"]?.[this.endpoint]?.jwt === this.jwt) return;
this.dataStore.data["auth"] = { ...this.dataStore.data["auth"], [this.endpoint]: { jwt: this.jwt } };
} else {
if (typeof this.dataStore.data["auth"]?.[this.endpoint] === "undefined") return;
delete this.dataStore.data["auth"][this.endpoint];
}
await this.dataStore.save();
this.logger.debug("Save changes to data store.");
} catch (error: any) {
this.logger.error({ error }, "Error when saving auth");
}
}
async reset(): Promise<void> {
if (this.jwt) {
this.jwt = null;
await this.save();
}
if (this.refreshTokenTimer) {
clearTimeout(this.refreshTokenTimer);
this.refreshTokenTimer = null;
}
if (this.pollingTokenTimer) {
clearInterval(this.pollingTokenTimer);
this.pollingTokenTimer = null;
}
}
async requestToken(): Promise<string> {
try {
await this.reset();
const deviceToken = await this.authApi.api.deviceToken();
this.logger.debug({ deviceToken }, "Request device token response");
const authUrl = new URL(Auth.authPageUrl);
authUrl.searchParams.append("code", deviceToken.data.code);
this.schedulePollingToken(deviceToken.data.code);
return authUrl.toString();
} catch (error) {
this.logger.error({ error }, "Error when requesting token");
throw error;
}
}
async schedulePollingToken(code: string) {
this.pollingTokenTimer = setInterval(async () => {
try {
const response = await this.authApi.api.deviceTokenAccept({ code });
this.logger.debug({ response }, "Poll jwt response");
this.jwt = response.data.jwt;
await this.save();
this.scheduleRefreshToken();
super.emit("updated", this.jwt);
clearInterval(this.pollingTokenTimer);
this.pollingTokenTimer = null;
} catch (error) {
if (error instanceof ApiError && [401, 403, 405].indexOf(error.status) !== -1) {
this.logger.debug({ error }, "Expected error when polling jwt");
} else {
// unknown error but still keep polling
this.logger.error({ error }, "Error when polling jwt");
}
}
}, Auth.pollTokenInterval);
}
private scheduleRefreshToken() {
if (this.refreshTokenTimer) {
clearTimeout(this.refreshTokenTimer);
this.refreshTokenTimer = null;
}
if (!this.jwt) {
return null;
}
// FIXME: assume jwt expires after 7 days, should get exp from decode jwt payload
const expireAt = Date.now() / 1000 + 60 * 60 * 24 * 7;
const refreshDelay = Math.max(0, expireAt * 1000 - Date.now() - Auth.refreshTokenInterval);
this.refreshTokenTimer = setTimeout(async () => {
this.logger.debug({ expireAt }, "Refresh token");
// FIXME: not implemented
}, refreshDelay);
}
}

View File

@ -47,7 +47,7 @@ export class StdIO {
private readonly logger = rootLogger.child({ component: "StdIO" }); private readonly logger = rootLogger.child({ component: "StdIO" });
private buffer: string = ""; private buffer: string = "";
private ongoingRequests: { [id: number]: CancelablePromise<any> } = {}; private ongoingRequests: { [id: number]: PromiseLike<any> } = {};
private agent: Agent | null = null; private agent: Agent | null = null;
@ -98,7 +98,7 @@ export class StdIO {
throw new Error(`Unknown function: ${funcName}`); throw new Error(`Unknown function: ${funcName}`);
} }
const result = func.apply(this.agent, request[1].args); const result = func.apply(this.agent, request[1].args);
if (result instanceof CancelablePromise) { if (typeof result === "object" && typeof result.then === "function") {
this.ongoingRequests[request[0]] = result; this.ongoingRequests[request[0]] = result;
response[1] = await result; response[1] = await result;
delete this.ongoingRequests[request[0]]; delete this.ongoingRequests[request[0]];
@ -118,7 +118,10 @@ export class StdIO {
if (!ongoing) { if (!ongoing) {
return false; return false;
} }
if (ongoing instanceof CancelablePromise) {
ongoing.cancel(); ongoing.cancel();
}
delete this.ongoingRequests[request[1].args[0]];
return true; return true;
} }

View File

@ -1,35 +1,77 @@
import axios from "axios";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { v4 as uuid } from "uuid"; import { v4 as uuid } from "uuid";
import deepEqual from "deep-equal"; import deepEqual from "deep-equal";
import deepMerge from "deepmerge"; import deepMerge from "deepmerge";
import { TabbyApi, CancelablePromise, ApiError, CancelError } from "./generated"; import { TabbyApi, CancelablePromise } from "./generated";
import { sleep, cancelable, splitLines, isBlank } from "./utils"; import { cancelable, splitLines, isBlank } from "./utils";
import { Agent, AgentEvent, AgentInitOptions, CompletionRequest, CompletionResponse, LogEventRequest } from "./Agent"; import {
Agent,
AgentStatus,
AgentEvent,
AgentInitOptions,
CompletionRequest,
CompletionResponse,
LogEventRequest,
} from "./Agent";
import { Auth } from "./Auth";
import { AgentConfig, defaultAgentConfig } from "./AgentConfig"; import { AgentConfig, defaultAgentConfig } from "./AgentConfig";
import { CompletionCache } from "./CompletionCache"; import { CompletionCache } from "./CompletionCache";
import { DataStore } from "./dataStore";
import { postprocess } from "./postprocess"; import { postprocess } from "./postprocess";
import { rootLogger, allLoggers } from "./logger"; import { rootLogger, allLoggers } from "./logger";
/**
* Different from AgentInitOptions or AgentConfig, this may contain non-serializable objects,
* so it is not suitable for cli, but only used when imported as module by other js project.
*/
export type TabbyAgentOptions = {
dataStore: DataStore;
};
export class TabbyAgent extends EventEmitter implements Agent { export class TabbyAgent extends EventEmitter implements Agent {
private readonly logger = rootLogger.child({ component: "TabbyAgent" }); private readonly logger = rootLogger.child({ component: "TabbyAgent" });
private config: AgentConfig = defaultAgentConfig; private config: AgentConfig = defaultAgentConfig;
private status: "connecting" | "ready" | "disconnected" = "connecting"; private status: AgentStatus = "notInitialized";
private api: TabbyApi; private api: TabbyApi;
private auth: Auth;
private dataStore: DataStore | null = null;
private completionCache: CompletionCache = new CompletionCache(); private completionCache: CompletionCache = new CompletionCache();
static readonly tryConnectInterval = 1000 * 30; // 30s
private tryingConnectTimer: ReturnType<typeof setInterval> | null = null;
constructor() { private constructor() {
super(); super();
this.onConfigUpdated();
this.tryingConnectTimer = setInterval(async () => {
if (this.status === "disconnected") {
this.logger.debug("Trying to connect...");
await this.healthCheck();
}
}, TabbyAgent.tryConnectInterval);
} }
private onConfigUpdated() { static async create(options?: Partial<TabbyAgentOptions>): Promise<TabbyAgent> {
const agent = new TabbyAgent();
agent.dataStore = options?.dataStore;
await agent.applyConfig();
return agent;
}
private async applyConfig() {
allLoggers.forEach((logger) => (logger.level = this.config.logs.level)); allLoggers.forEach((logger) => (logger.level = this.config.logs.level));
this.api = new TabbyApi({ BASE: this.config.server.endpoint }); if (this.config.server.endpoint !== this.auth?.endpoint) {
this.ping(); this.auth = await Auth.create({ endpoint: this.config.server.endpoint, dataStore: this.dataStore });
this.auth.on("updated", this.onAuthUpdated.bind(this));
}
this.api = new TabbyApi({ BASE: this.config.server.endpoint, TOKEN: this.auth.token });
} }
private changeStatus(status: "connecting" | "ready" | "disconnected") { private async onAuthUpdated() {
this.api = new TabbyApi({ BASE: this.config.server.endpoint, TOKEN: this.auth.token });
await this.healthCheck();
}
private changeStatus(status: AgentStatus) {
if (this.status != status) { if (this.status != status) {
this.status = status; this.status = status;
const event: AgentEvent = { event: "statusChanged", status }; const event: AgentEvent = { event: "statusChanged", status };
@ -38,23 +80,6 @@ export class TabbyAgent extends EventEmitter implements Agent {
} }
} }
private async ping(tries: number = 0): Promise<boolean> {
try {
await axios.get(this.config.server.endpoint);
this.changeStatus("ready");
return true;
} catch (e) {
if (tries > 5) {
this.changeStatus("disconnected");
return false;
}
this.changeStatus("connecting");
const pingRetryDelay = 1000;
await sleep(pingRetryDelay);
return this.ping(tries + 1);
}
}
private callApi<Request, Response>( private callApi<Request, Response>(
api: (request: Request) => CancelablePromise<Response>, api: (request: Request) => CancelablePromise<Response>,
request: Request request: Request
@ -68,13 +93,19 @@ export class TabbyAgent extends EventEmitter implements Agent {
this.changeStatus("ready"); this.changeStatus("ready");
return response; return response;
}) })
.catch((error: CancelError) => { .catch((error) => {
this.logger.debug({ api: api.name }, "API request canceled"); if (!!error.isCancelled) {
throw error; this.logger.debug({ api: api.name, error }, "API request canceled");
}) } else if (error.name === "ApiError" && [401, 403, 405].indexOf(error.status) !== -1) {
.catch((error: ApiError) => { this.logger.debug({ api: api.name, error }, "API unauthorized");
this.changeStatus("unauthorized");
} else if (error.name === "ApiError") {
this.logger.error({ api: api.name, error }, "API error"); this.logger.error({ api: api.name, error }, "API error");
this.changeStatus("disconnected"); this.changeStatus("disconnected");
} else {
this.logger.error({ api: api.name, error }, "API request failed with unknown error");
this.changeStatus("disconnected");
}
throw error; throw error;
}), }),
() => { () => {
@ -83,6 +114,10 @@ export class TabbyAgent extends EventEmitter implements Agent {
); );
} }
private async healthCheck(): Promise<void> {
return this.callApi(this.api.v1.health, {}).catch(() => {});
}
private createSegments(request: CompletionRequest): { prefix: string; suffix: string } { private createSegments(request: CompletionRequest): { prefix: string; suffix: string } {
// max to 20 lines in prefix and max to 20 lines in suffix // max to 20 lines in prefix and max to 20 lines in suffix
const maxLines = 20; const maxLines = 20;
@ -96,40 +131,60 @@ export class TabbyAgent extends EventEmitter implements Agent {
}; };
} }
public initialize(params: AgentInitOptions): boolean { public async initialize(options: Partial<AgentInitOptions>): Promise<boolean> {
if (params.config) { if (options.client) {
this.updateConfig(params.config);
}
if (params.client) {
// Client info is only used in logging for now // Client info is only used in logging for now
// `pino.Logger.setBindings` is not present in the browser // `pino.Logger.setBindings` is not present in the browser
allLoggers.forEach((logger) => logger.setBindings && logger.setBindings({ client: params.client })); allLoggers.forEach((logger) => logger.setBindings && logger.setBindings({ client: options.client }));
} }
this.logger.debug({ params }, "Initialized"); if (options.config) {
return true; await this.updateConfig(options.config);
}
this.logger.debug({ options }, "Initialized");
return this.status !== "notInitialized";
} }
public updateConfig(config: AgentConfig): boolean { public async updateConfig(config: Partial<AgentConfig>): Promise<boolean> {
const mergedConfig = deepMerge(this.config, config); const mergedConfig = deepMerge(this.config, config);
if (!deepEqual(this.config, mergedConfig)) { if (!deepEqual(this.config, mergedConfig)) {
this.config = mergedConfig; this.config = mergedConfig;
this.onConfigUpdated(); await this.applyConfig();
const event: AgentEvent = { event: "configUpdated", config: this.config }; const event: AgentEvent = { event: "configUpdated", config: this.config };
this.logger.debug({ event }, "Config updated"); this.logger.debug({ event }, "Config updated");
super.emit("configUpdated", event); super.emit("configUpdated", event);
} }
return true; await this.healthCheck();
return this.status !== "notInitialized";
} }
public getConfig(): AgentConfig { public getConfig(): AgentConfig {
return this.config; return this.config;
} }
public getStatus(): "connecting" | "ready" | "disconnected" { public getStatus(): AgentStatus {
return this.status; return this.status;
} }
public startAuth(): CancelablePromise<string | null> {
return cancelable(
this.healthCheck().then(() => {
if (this.status === "unauthorized") {
return this.auth.requestToken();
}
return null;
}),
() => {
if (this.status === "unauthorized") {
this.auth.reset();
}
}
);
}
public getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse> { public getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse> {
if (this.status === "notInitialized") {
throw new Error("Agent is not initialized");
}
if (this.completionCache.has(request)) { if (this.completionCache.has(request)) {
this.logger.debug({ request }, "Completion cache hit"); this.logger.debug({ request }, "Completion cache hit");
return new CancelablePromise((resolve) => { return new CancelablePromise((resolve) => {
@ -166,6 +221,9 @@ export class TabbyAgent extends EventEmitter implements Agent {
} }
public postEvent(request: LogEventRequest): CancelablePromise<boolean> { public postEvent(request: LogEventRequest): CancelablePromise<boolean> {
if (this.status === "notInitialized") {
throw new Error("Agent is not initialized");
}
return this.callApi(this.api.v1.event, request); return this.callApi(this.api.v1.event, request);
} }
} }

View File

@ -3,7 +3,9 @@
import { TabbyAgent } from "./TabbyAgent"; import { TabbyAgent } from "./TabbyAgent";
import { StdIO } from "./StdIO"; import { StdIO } from "./StdIO";
const agent = new TabbyAgent();
const stdio = new StdIO(); const stdio = new StdIO();
TabbyAgent.create().then((agent) => {
stdio.bind(agent); stdio.bind(agent);
});
stdio.listen(); stdio.listen();

View File

@ -0,0 +1,27 @@
import type { BaseHttpRequest, OpenAPIConfig } from "../generated";
import { AxiosHttpRequest } from "../generated/core/AxiosHttpRequest";
import { ApiService } from "./services/ApiService";
type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest;
export class CloudApi {
public readonly api: ApiService;
public readonly request: BaseHttpRequest;
constructor(config?: Partial<OpenAPIConfig>, HttpRequest: HttpRequestConstructor = AxiosHttpRequest) {
this.request = new HttpRequest({
BASE: config?.BASE ?? 'https://tabbyml.app.tabbyml.com/tabby',
VERSION: config?.VERSION ?? "0.0.0",
WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
CREDENTIALS: config?.CREDENTIALS ?? "include",
TOKEN: config?.TOKEN,
USERNAME: config?.USERNAME,
PASSWORD: config?.PASSWORD,
HEADERS: config?.HEADERS,
ENCODE_PATH: config?.ENCODE_PATH,
});
this.api = new ApiService(this.request);
}
}

View File

@ -0,0 +1,4 @@
export { CloudApi } from "./CloudApi";
export { ApiService } from "./services/ApiService";
export { DeviceTokenResponse } from "./models/DeviceTokenResponse";
export { DeviceTokenAcceptResponse } from "./models/DeviceTokenAcceptResponse";

View File

@ -0,0 +1,5 @@
export type DeviceTokenAcceptResponse = {
data: {
jwt: string;
};
};

View File

@ -0,0 +1,5 @@
export type DeviceTokenResponse = {
data: {
code: string;
};
};

View File

@ -0,0 +1,33 @@
import type { CancelablePromise } from "../../generated/core/CancelablePromise";
import type { BaseHttpRequest } from "../../generated/core/BaseHttpRequest";
import { DeviceTokenResponse } from "../models/DeviceTokenResponse";
import { DeviceTokenAcceptResponse } from "../models/DeviceTokenAcceptResponse";
export class ApiService {
constructor(public readonly httpRequest: BaseHttpRequest) {}
/**
* @returns DeviceTokenResponse Success
* @throws ApiError
*/
public deviceToken(): CancelablePromise<DeviceTokenResponse> {
return this.httpRequest.request({
method: "POST",
url: "/device-token",
});
}
/**
* @param code
* @returns DeviceTokenAcceptResponse Success
* @throws ApiError
*/
public deviceTokenAccept(query: { code: string }): CancelablePromise<DeviceTokenAcceptResponse> {
return this.httpRequest.request({
method: "POST",
url: "/device-token/accept",
query,
});
}
}

View File

@ -0,0 +1,26 @@
export type StoredData = {
auth: { [endpoint: string]: { jwt: string } };
};
export interface DataStore {
data: Partial<StoredData>;
load(): PromiseLike<void>;
save(): PromiseLike<void>;
}
declare var IS_BROWSER: boolean;
export const dataStore: DataStore = IS_BROWSER
? null
: (() => {
const dataFile = require("path").join(require("os").homedir(), ".tabby", "agent", "data.json");
const fs = require("fs-extra");
return {
data: {},
load: async function () {
this.data = (await fs.readJson(dataFile, { throws: false })) || {};
},
save: async function () {
await fs.outputJson(dataFile, this.data);
},
};
})();

View File

@ -1,17 +1,16 @@
export { TabbyAgent } from "./TabbyAgent"; export { TabbyAgent, TabbyAgentOptions } from "./TabbyAgent";
export { export {
Agent, Agent,
AgentStatus,
AgentFunction, AgentFunction,
AgentEvent, AgentEvent,
StatusChangedEvent, StatusChangedEvent,
ConfigUpdatedEvent,
CompletionRequest, CompletionRequest,
CompletionResponse, CompletionResponse,
LogEventRequest,
agentEventNames, agentEventNames,
} from "./Agent"; } from "./Agent";
export { AgentConfig } from "./AgentConfig"; export { AgentConfig } from "./AgentConfig";
export { export { DataStore } from "./dataStore";
CancelablePromise, export { CancelablePromise } from "./generated";
CancelError,
ApiError,
Choice,
} from "./generated";

View File

@ -1,19 +1,17 @@
import os from "os";
import path from "path";
import { isBrowser } from "browser-or-node";
import * as rotatingFileStream from "rotating-file-stream";
import pino from "pino"; import pino from "pino";
declare var IS_BROWSER: boolean;
/** /**
* Stream not available in browser, will use default console output. * Stream not available in browser, will use default console output.
*/ */
const stream = isBrowser const stream = IS_BROWSER
? null ? null
: /** : /**
* Default rotating file locate at `~/.tabby/agent-logs/`. * Default rotating file locate at `~/.tabby/agent-logs/`.
*/ */
rotatingFileStream.createStream("tabby-agent.log", { require("rotating-file-stream").createStream("tabby-agent.log", {
path: path.join(os.homedir(), ".tabby", "agent-logs"), path: require("path").join(require("os").homedir(), ".tabby", "agent-logs"),
size: "10M", size: "10M",
interval: "1d", interval: "1d",
}); });

View File

@ -1,7 +1,3 @@
export function sleep(milliseconds: number) {
return new Promise((r) => setTimeout(r, milliseconds));
}
export function splitLines(input: string) { export function splitLines(input: string) {
return input.match(/.*(?:$|\r?\n)/g).filter(Boolean) // Split lines and keep newline character return input.match(/.*(?:$|\r?\n)/g).filter(Boolean) // Split lines and keep newline character
} }

View File

@ -2,6 +2,11 @@ import { defineConfig } from "tsup";
import { polyfillNode } from "esbuild-plugin-polyfill-node"; import { polyfillNode } from "esbuild-plugin-polyfill-node";
import { dependencies } from "./package.json"; import { dependencies } from "./package.json";
const defineIsBrowser = (targetOptions, isBrowser: boolean) => {
targetOptions["define"] = { ...targetOptions["define"], "IS_BROWSER": isBrowser.toString() };
return targetOptions;
}
export default async () => [ export default async () => [
defineConfig({ defineConfig({
name: "node-cjs", name: "node-cjs",
@ -9,6 +14,9 @@ export default async () => [
platform: "node", platform: "node",
format: ["cjs"], format: ["cjs"],
sourcemap: true, sourcemap: true,
esbuildOptions(options) {
defineIsBrowser(options, false);
},
clean: true, clean: true,
}), }),
defineConfig({ defineConfig({
@ -17,6 +25,7 @@ export default async () => [
platform: "browser", platform: "browser",
format: ["iife"], format: ["iife"],
globalName: "Tabby", globalName: "Tabby",
treeshake: "smallest",
minify: true, minify: true,
sourcemap: true, sourcemap: true,
esbuildPlugins: [ esbuildPlugins: [
@ -24,6 +33,9 @@ export default async () => [
polyfills: { fs: true }, polyfills: { fs: true },
}), }),
], ],
esbuildOptions(options) {
defineIsBrowser(options, true);
},
clean: true, clean: true,
}), }),
defineConfig({ defineConfig({
@ -33,12 +45,16 @@ export default async () => [
format: ["esm"], format: ["esm"],
// FIXME: bundle all dependencies to reduce module resolving problems, not a good solution // FIXME: bundle all dependencies to reduce module resolving problems, not a good solution
noExternal: Object.keys(dependencies), noExternal: Object.keys(dependencies),
treeshake: true,
sourcemap: true, sourcemap: true,
esbuildPlugins: [ esbuildPlugins: [
polyfillNode({ polyfillNode({
polyfills: { fs: true }, polyfills: { fs: true },
}), }),
], ],
esbuildOptions(options) {
defineIsBrowser(options, true);
},
clean: true, clean: true,
}), }),
defineConfig({ defineConfig({
@ -54,8 +70,12 @@ export default async () => [
entry: ["src/cli.ts"], entry: ["src/cli.ts"],
platform: "node", platform: "node",
noExternal: Object.keys(dependencies), noExternal: Object.keys(dependencies),
treeshake: "smallest",
minify: true, minify: true,
sourcemap: true, sourcemap: true,
esbuildOptions(options) {
defineIsBrowser(options, false);
},
clean: true, clean: true,
}), }),
]; ];

View File

@ -207,11 +207,31 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@types/fs-extra@^11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.1.tgz#f542ec47810532a8a252127e6e105f487e0a6ea5"
integrity sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==
dependencies:
"@types/jsonfile" "*"
"@types/node" "*"
"@types/json-schema@^7.0.6": "@types/json-schema@^7.0.6":
version "7.0.11" version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
"@types/jsonfile@*":
version "6.1.1"
resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.1.tgz#ac84e9aefa74a2425a0fb3012bdea44f58970f1b"
integrity sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==
dependencies:
"@types/node" "*"
"@types/node@*":
version "20.3.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe"
integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==
"@types/node@^16.18.32": "@types/node@^16.18.32":
version "16.18.32" version "16.18.32"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.32.tgz#5b5becc5da76fc055b2a601c8a3adbf13891227e" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.32.tgz#5b5becc5da76fc055b2a601c8a3adbf13891227e"
@ -338,11 +358,6 @@ braces@^3.0.2, braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
browser-or-node@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/browser-or-node/-/browser-or-node-2.1.1.tgz#738790b3a86a8fc020193fa581273fbe65eaea0f"
integrity sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==
buffer@^6.0.3: buffer@^6.0.3:
version "6.0.3" version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"

View File

@ -3,4 +3,5 @@ dist
node_modules node_modules
generated generated
.vscode-test/ .vscode-test/
.vscode-test-web/
*.vsix *.vsix

View File

@ -21,9 +21,23 @@
"outFiles": ["${workspaceFolder}/dist/**/*.js"], "outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "${defaultBuildTask}" "preLaunchTask": "${defaultBuildTask}"
}, },
{
"name": "Run Web Extension in Browser",
"type": "node",
"request": "launch",
"runtimeExecutable": "npx",
"runtimeArgs": [
"vscode-test-web",
"--extensionDevelopmentPath=${workspaceFolder}",
"--browserType=chromium",
"--port=3000",
],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "${defaultBuildTask}"
},
{ {
"name": "Run Web Extension in VS Code", "name": "Run Web Extension in VS Code",
"type": "pwa-extensionHost", "type": "extensionHost",
"debugWebWorkerHost": true, "debugWebWorkerHost": true,
"request": "launch", "request": "launch",
"args": [ "args": [

View File

@ -1,5 +1,6 @@
.vscode/** .vscode/**
.vscode-test/** .vscode-test/**
.vscode-test-web/**
out/** out/**
node_modules/** node_modules/**
src/** src/**

View File

@ -82,6 +82,7 @@
"watch": "webpack --watch", "watch": "webpack --watch",
"dev": "code --extensionDevelopmentPath=$PWD --disable-extensions && yarn watch", "dev": "code --extensionDevelopmentPath=$PWD --disable-extensions && yarn watch",
"dev:web": "code --extensionDevelopmentPath=$PWD --extensionDevelopmentKind=web --disable-extensions && yarn watch", "dev:web": "code --extensionDevelopmentPath=$PWD --extensionDevelopmentKind=web --disable-extensions && yarn watch",
"dev:web-browser": "vscode-test-web --extensionDevelopmentPath=$PWD --browserType=chromium --port=3000 && yarn watch",
"package": "webpack --mode production --devtool hidden-source-map", "package": "webpack --mode production --devtool hidden-source-map",
"compile-tests": "tsc -p . --outDir out", "compile-tests": "tsc -p . --outDir out",
"watch-tests": "tsc -p . -w --outDir out", "watch-tests": "tsc -p . -w --outDir out",
@ -99,6 +100,7 @@
"@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0", "@typescript-eslint/parser": "^5.31.0",
"@vscode/test-electron": "^2.1.5", "@vscode/test-electron": "^2.1.5",
"@vscode/test-web": "^0.0.44",
"assert": "^2.0.0", "assert": "^2.0.0",
"eslint": "^8.20.0", "eslint": "^8.20.0",
"glob": "^8.0.3", "glob": "^8.0.3",
@ -113,6 +115,7 @@
}, },
"dependencies": { "dependencies": {
"@sapphire/duration": "^1.1.0", "@sapphire/duration": "^1.1.0",
"@xstate/fsm": "^2.0.1",
"tabby-agent": "file:../tabby-agent" "tabby-agent": "file:../tabby-agent"
} }
} }

View File

@ -1,42 +0,0 @@
import { workspace, env, version, UIKind } from "vscode";
import { TabbyAgent, AgentConfig } from "tabby-agent";
export class Agent extends TabbyAgent {
private static instance: Agent;
static getInstance(): Agent {
if (!Agent.instance) {
Agent.instance = new Agent();
}
return Agent.instance;
}
private constructor() {
super();
const uiKind = Object.keys(UIKind)[Object.values(UIKind).indexOf(env.uiKind)];
super.initialize({
config: this.getWorkspaceConfiguration(),
client: `VSCode ${uiKind} ${version}`,
});
workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration("tabby")) {
const config = this.getWorkspaceConfiguration();
super.updateConfig(config);
}
});
}
private getWorkspaceConfiguration(): AgentConfig {
const configuration = workspace.getConfiguration("tabby");
const serverUrl = configuration.get<string>("serverUrl");
const agentLogs = configuration.get<"debug" | "error" | "silent">("agentLogs");
return {
server: {
endpoint: serverUrl,
},
logs: {
level: agentLogs,
},
};
}
}

View File

@ -11,7 +11,7 @@ import {
workspace, workspace,
} from "vscode"; } from "vscode";
import { CompletionResponse, CancelablePromise } from "tabby-agent"; import { CompletionResponse, CancelablePromise } from "tabby-agent";
import { Agent } from "./Agent"; import { agent } from "./agent";
import { sleep } from "./utils"; import { sleep } from "./utils";
export class TabbyCompletionProvider implements InlineCompletionItemProvider { export class TabbyCompletionProvider implements InlineCompletionItemProvider {
@ -19,7 +19,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
private latestTimestamp: number = 0; private latestTimestamp: number = 0;
private pendingCompletion: CancelablePromise<CompletionResponse> | null = null; private pendingCompletion: CancelablePromise<CompletionResponse> | null = null;
private agent = Agent.getInstance();
// User Settings // User Settings
private enabled: boolean = true; private enabled: boolean = true;
private suggestionDelay: number = 150; private suggestionDelay: number = 150;
@ -62,7 +61,7 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
text: document.getText(), text: document.getText(),
position: document.offsetAt(position), position: document.offsetAt(position),
}; };
this.pendingCompletion = this.agent.getCompletions(request); this.pendingCompletion = agent().getCompletions(request);
const completion = await this.pendingCompletion.catch((_: Error) => { const completion = await this.pendingCompletion.catch((_: Error) => {
return null; return null;
@ -88,7 +87,7 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
choice_index: choice.index, choice_index: choice.index,
}; };
return new InlineCompletionItem(choice.text, range, { return new InlineCompletionItem(choice.text, range, {
title: "Tabby: Emit Event", title: "",
command: "tabby.emitEvent", command: "tabby.emitEvent",
arguments: [event], arguments: [event],
}); });

View File

@ -1,79 +0,0 @@
import { StatusBarAlignment, ThemeColor, window, workspace } from "vscode";
import { Agent } from "./Agent";
const label = "Tabby";
const iconLoading = "$(loading~spin)";
const iconReady = "$(check)";
const iconDisconnected = "$(plug)";
const iconDisabled = "$(x)";
const colorNormal = new ThemeColor("statusBar.foreground");
const colorWarning = new ThemeColor("statusBarItem.warningForeground");
const backgroundColorNormal = new ThemeColor("statusBar.background");
const backgroundColorWarning = new ThemeColor("statusBarItem.warningBackground");
const item = window.createStatusBarItem(StatusBarAlignment.Right);
export const tabbyStatusBarItem = item;
const agent = Agent.getInstance();
agent.on("statusChanged", updateStatusBarItem);
workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration("tabby")) {
updateStatusBarItem();
}
});
updateStatusBarItem();
item.show();
function updateStatusBarItem() {
const enabled = workspace.getConfiguration("tabby").get("enabled", true);
if (!enabled) {
toDisabled();
} else {
const status = agent.getStatus();
switch (status) {
case "connecting":
toLoading();
break;
case "ready":
toReady();
break;
case "disconnected":
toDisconnected();
break;
}
}
}
function toLoading() {
item.color = colorNormal;
item.backgroundColor = backgroundColorNormal;
item.text = `${iconLoading} ${label}`;
item.tooltip = "Connecting to Tabby Server...";
item.command = undefined;
}
function toReady() {
item.color = colorNormal;
item.backgroundColor = backgroundColorNormal;
item.text = `${iconReady} ${label}`;
item.tooltip = "Tabby is providing code suggestions for you.";
item.command = "tabby.toggleEnabled";
}
function toDisconnected() {
item.color = colorWarning;
item.backgroundColor = backgroundColorWarning;
item.text = `${iconDisconnected} ${label}`;
item.tooltip = "Cannot connect to Tabby Server. Click to open settings.";
item.command = "tabby.openSettings";
}
function toDisabled() {
item.color = colorWarning;
item.backgroundColor = backgroundColorWarning;
item.text = `${iconDisabled} ${label}`;
item.tooltip = "Tabby is disabled. Click to enable.";
item.command = "tabby.toggleEnabled";
}

View File

@ -0,0 +1,58 @@
import { ExtensionContext, workspace, env, version } from "vscode";
import { TabbyAgent, AgentConfig, DataStore } from "tabby-agent";
function getWorkspaceConfiguration(): Partial<AgentConfig> {
const configuration = workspace.getConfiguration("tabby");
const config: Partial<AgentConfig> = {};
const serverUrl = configuration.get<string>("serverUrl");
if (serverUrl) {
config.server = {
endpoint: serverUrl,
};
}
const agentLogs = configuration.get<"debug" | "error" | "silent">("agentLogs");
if (agentLogs) {
config.logs = {
level: agentLogs,
};
}
return config;
}
var instance: TabbyAgent;
export function agent(): TabbyAgent {
if (!instance) {
throw new Error("Tabby Agent not initialized");
}
return instance;
}
export async function createAgentInstance(context: ExtensionContext): Promise<TabbyAgent> {
if (!instance) {
// NOTE: env.appHost will be "desktop" when running target "Run Web Extension in VS Code"
// To test data store in the web extension, run target "Run Web Extension in Browser"
const extensionDataStore: DataStore = {
data: {},
load: async function () {
this.data = context.globalState.get("data", {});
},
save: async function () {
context.globalState.update("data", this.data);
},
};
const agent = await TabbyAgent.create({ dataStore: env.appHost === "desktop" ? undefined : extensionDataStore });
agent.initialize({
config: getWorkspaceConfiguration(),
client: `${env.appName} ${env.appHost} ${version}`,
});
workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration("tabby")) {
const config = getWorkspaceConfiguration();
agent.updateConfig(config);
}
});
instance = agent;
}
return instance;
}

View File

@ -3,15 +3,18 @@ import {
InputBoxValidationSeverity, InputBoxValidationSeverity,
QuickPickItem, QuickPickItem,
QuickPickItemKind, QuickPickItemKind,
Uri,
workspace, workspace,
window, window,
env,
commands, commands,
} from "vscode"; } from "vscode";
import { strict as assert } from "assert"; import { strict as assert } from "assert";
import { Duration } from "@sapphire/duration"; import { Duration } from "@sapphire/duration";
import { Agent } from "./Agent"; import { agent } from "./agent";
import { notifications } from "./notifications";
const target = ConfigurationTarget.Global; const configTarget = ConfigurationTarget.Global;
type Command = { type Command = {
command: string; command: string;
@ -19,13 +22,13 @@ type Command = {
thisArg?: any; thisArg?: any;
}; };
const toogleEnabled: Command = { const toggleEnabled: Command = {
command: "tabby.toggleEnabled", command: "tabby.toggleEnabled",
callback: () => { callback: () => {
const configuration = workspace.getConfiguration("tabby"); const configuration = workspace.getConfiguration("tabby");
const enabled = configuration.get("enabled", true); const enabled = configuration.get("enabled", true);
console.debug(`Toggle Enabled: ${enabled} -> ${!enabled}.`); console.debug(`Toggle Enabled: ${enabled} -> ${!enabled}.`);
configuration.update("enabled", !enabled, target, false); configuration.update("enabled", !enabled, configTarget, false);
}, },
}; };
@ -35,9 +38,9 @@ const setSuggestionDelay: Command = {
const configuration = workspace.getConfiguration("tabby"); const configuration = workspace.getConfiguration("tabby");
const current = configuration.get("suggestionDelay", 150); const current = configuration.get("suggestionDelay", 150);
const items = { const items = {
"Immediately": 0, // ms Immediately: 0, // ms
"Default": 150, Default: 150,
"Slowly": 1000, Slowly: 1000,
}; };
const createQuickPickItem = (value: number): QuickPickItem => { const createQuickPickItem = (value: number): QuickPickItem => {
const tags: string[] = []; const tags: string[] = [];
@ -84,7 +87,7 @@ const setSuggestionDelay: Command = {
quickPick.hide(); quickPick.hide();
const delay = new Duration(quickPick.selectedItems[0].label).offset; const delay = new Duration(quickPick.selectedItems[0].label).offset;
console.debug("Set suggestion delay: ", delay); console.debug("Set suggestion delay: ", delay);
configuration.update("suggestionDelay", delay, target, false); configuration.update("suggestionDelay", delay, configTarget, false);
}); });
quickPick.show(); quickPick.show();
}, },
@ -114,7 +117,7 @@ const setServerUrl: Command = {
.then((url) => { .then((url) => {
if (url) { if (url) {
console.debug("Set Tabby Server URL: ", url); console.debug("Set Tabby Server URL: ", url);
configuration.update("serverUrl", url, target, false); configuration.update("serverUrl", url, configTarget, false);
} }
}); });
}, },
@ -127,15 +130,54 @@ const openSettings: Command = {
}, },
}; };
const agent = Agent.getInstance();
const emitEvent: Command = { const emitEvent: Command = {
command: "tabby.emitEvent", command: "tabby.emitEvent",
callback: (event) => { callback: (event) => {
console.debug("Emit Event: ", event); console.debug("Emit Event: ", event);
agent.postEvent(event); agent().postEvent(event);
}, },
}; };
export const tabbyCommands = [toogleEnabled, setServerUrl, setSuggestionDelay, openSettings, emitEvent].map((command) => const openAuthPage: Command = {
commands.registerCommand(command.command, command.callback, command.thisArg) command: "tabby.openAuthPage",
callback: () => {
agent()
.startAuth()
.then((authUrl) => {
if (authUrl) {
env.openExternal(Uri.parse(authUrl));
}
})
.catch((error) => {
console.debug("Error to start auth", { error })
});
},
};
const statusBarItemClicked: Command = {
command: "tabby.statusBarItemClicked",
callback: (status) => {
switch (status) {
case "loading":
notifications.showInformationWhenLoading();
break;
case "ready":
notifications.showInformationWhenReady();
break;
case "disconnected":
notifications.showInformationWhenDisconnected();
break;
case "unauthorized":
notifications.showInformationStartAuth();
break;
case "disabled":
notifications.showInformationWhenDisabled();
break;
}
},
};
export const tabbyCommands = () =>
[toggleEnabled, setServerUrl, setSuggestionDelay, openSettings, emitEvent, openAuthPage, statusBarItemClicked].map(
(command) => commands.registerCommand(command.command, command.callback, command.thisArg)
); );

View File

@ -1,21 +1,23 @@
// The module 'vscode' contains the VS Code extensibility API // The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below // Import the module and reference it with the alias vscode in your code below
import { ExtensionContext, languages } from "vscode"; import { ExtensionContext, languages } from "vscode";
import { tabbyCommands } from "./Commands"; import { createAgentInstance } from "./agent";
import { tabbyCommands } from "./commands";
import { TabbyCompletionProvider } from "./TabbyCompletionProvider"; import { TabbyCompletionProvider } from "./TabbyCompletionProvider";
import { tabbyStatusBarItem } from "./TabbyStatusBarItem"; import { tabbyStatusBarItem } from "./statusBarItem";
// this method is called when your extension is activated // this method is called when your extension is activated
// your extension is activated the very first time the command is executed // your extension is activated the very first time the command is executed
export function activate(context: ExtensionContext) { export async function activate(context: ExtensionContext) {
console.debug("Activating Tabby extension", new Date()); console.debug("Activating Tabby extension", new Date());
await createAgentInstance(context);
context.subscriptions.push( context.subscriptions.push(
languages.registerInlineCompletionItemProvider( languages.registerInlineCompletionItemProvider(
{ pattern: "**" }, { pattern: "**" },
new TabbyCompletionProvider() new TabbyCompletionProvider()
), ),
tabbyStatusBarItem, tabbyStatusBarItem(),
...tabbyCommands ...tabbyCommands(),
); );
} }

View File

@ -0,0 +1,84 @@
import { commands, window, workspace, ConfigurationTarget } from "vscode";
const configTarget = ConfigurationTarget.Global;
function showInformationWhenLoading() {
window.showInformationMessage("Tabby is initializing.", "Settings").then((selection) => {
switch (selection) {
case "Settings":
commands.executeCommand("tabby.openSettings");
break;
}
});
}
function showInformationWhenDisabled() {
window.showInformationMessage("Tabby is disabled. Enable it?", "Enable", "Settings").then((selection) => {
switch (selection) {
case "Enable":
commands.executeCommand("tabby.toggleEnabled");
break;
case "Settings":
commands.executeCommand("tabby.openSettings");
break;
}
});
}
function showInformationWhenReady() {
window
.showInformationMessage("Tabby is providing code suggestions for you. Disable it?", "Disable", "Settings")
.then((selection) => {
switch (selection) {
case "Disable":
commands.executeCommand("tabby.toggleEnabled");
break;
case "Settings":
commands.executeCommand("tabby.openSettings");
break;
}
});
}
function showInformationWhenDisconnected() {
window
.showInformationMessage("Cannot connect to Tabby Server. Please check settings.", "Settings")
.then((selection) => {
switch (selection) {
case "Settings":
commands.executeCommand("tabby.openSettings");
break;
}
});
}
function showInformationStartAuth() {
window
.showInformationMessage(
"Tabby Server requires authentication. Continue to open authentication page in your browser.",
"Continue",
"Settings"
)
.then((selection) => {
switch (selection) {
case "Continue":
commands.executeCommand("tabby.openAuthPage");
break;
case "Settings":
commands.executeCommand("tabby.openSettings");
}
});
}
function showInformationAuthSuccess() {
window.showInformationMessage("Congrats, you're authorized, start to use Tabby now.");
}
export const notifications = {
showInformationWhenLoading,
showInformationWhenDisabled,
showInformationWhenReady,
showInformationWhenDisconnected,
showInformationStartAuth,
showInformationAuthSuccess,
};

View File

@ -0,0 +1,126 @@
import { StatusBarAlignment, ThemeColor, window, workspace } from "vscode";
import { createMachine, interpret } from "@xstate/fsm";
import { agent } from "./agent";
import { notifications } from "./notifications";
const label = "Tabby";
const iconLoading = "$(loading~spin)";
const iconReady = "$(check)";
const iconDisconnected = "$(plug)";
const iconUnauthorized = "$(key)";
const iconDisabled = "$(x)";
const colorNormal = new ThemeColor("statusBar.foreground");
const colorWarning = new ThemeColor("statusBarItem.warningForeground");
const backgroundColorNormal = new ThemeColor("statusBar.background");
const backgroundColorWarning = new ThemeColor("statusBarItem.warningBackground");
const item = window.createStatusBarItem(StatusBarAlignment.Right);
const fsm = createMachine({
id: "statusBarItem",
initial: "loading",
states: {
loading: {
on: { ready: "ready", disconnected: "disconnected", unauthorized: "unauthorized", disabled: "disabled" },
entry: () => toLoading(),
},
ready: {
on: { disconnected: "disconnected", unauthorized: "unauthorized", disabled: "disabled" },
entry: () => toReady(),
},
disconnected: {
on: { ready: "ready", unauthorized: "unauthorized", disabled: "disabled" },
entry: () => toDisconnected(),
},
unauthorized: {
on: { ready: "ready", disconnected: "disconnected", disabled: "disabled" },
entry: () => {
toUnauthorized();
notifications.showInformationStartAuth();
},
exit: (_, event) => {
if (event.type === "ready") {
notifications.showInformationAuthSuccess();
}
},
},
disabled: {
on: { loading: "loading", ready: "ready", disconnected: "disconnected", unauthorized: "unauthorized" },
entry: () => toDisabled(),
},
},
});
const fsmService = interpret(fsm);
function toLoading() {
item.color = colorNormal;
item.backgroundColor = backgroundColorNormal;
item.text = `${iconLoading} ${label}`;
item.tooltip = "Tabby is initializing.";
item.command = { title: "", command: "tabby.statusBarItemClicked", arguments: ["loading"] };
}
function toReady() {
item.color = colorNormal;
item.backgroundColor = backgroundColorNormal;
item.text = `${iconReady} ${label}`;
item.tooltip = "Tabby is providing code suggestions for you.";
item.command = { title: "", command: "tabby.statusBarItemClicked", arguments: ["ready"] };
}
function toDisconnected() {
item.color = colorWarning;
item.backgroundColor = backgroundColorWarning;
item.text = `${iconDisconnected} ${label}`;
item.tooltip = "Cannot connect to Tabby Server. Click to open settings.";
item.command = { title: "", command: "tabby.statusBarItemClicked", arguments: ["disconnected"] };
}
function toUnauthorized() {
item.color = colorWarning;
item.backgroundColor = backgroundColorWarning;
item.text = `${iconUnauthorized} ${label}`;
item.tooltip = "Tabby Server requires authentication. Click to continue.";
item.command = { title: "", command: "tabby.statusBarItemClicked", arguments: ["unauthorized"] };
}
function toDisabled() {
item.color = colorWarning;
item.backgroundColor = backgroundColorWarning;
item.text = `${iconDisabled} ${label}`;
item.tooltip = "Tabby is disabled.";
item.command = { title: "", command: "tabby.statusBarItemClicked", arguments: ["disabled"] };
}
function updateStatusBarItem() {
const enabled = workspace.getConfiguration("tabby").get("enabled", true);
if (!enabled) {
fsmService.send("disabled");
} else {
const status = agent().getStatus();
switch (status) {
case "notInitialized":
fsmService.send("loading");
break;
case "ready":
case "disconnected":
case "unauthorized":
fsmService.send(status);
break;
}
}
}
export const tabbyStatusBarItem = () => {
fsmService.start();
updateStatusBarItem();
workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration("tabby")) {
updateStatusBarItem();
}
});
agent().on("statusChanged", updateStatusBarItem);
item.show();
return item;
};

View File

@ -118,6 +118,23 @@
resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
"@koa/cors@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-4.0.0.tgz#b2d300d7368d2e0ad6faa1d918eff6d0cde0859a"
integrity sha512-Y4RrbvGTlAaa04DBoPBWJqDR5gPj32OOz827ULXfgB1F7piD1MB/zwn8JR2LAnvdILhxUbXbkXGWuNVsFuVFCQ==
dependencies:
vary "^1.1.2"
"@koa/router@^12.0.0":
version "12.0.0"
resolved "https://registry.yarnpkg.com/@koa/router/-/router-12.0.0.tgz#2ae7937093fd392761c0e5833c368379d4a35737"
integrity sha512-cnnxeKHXlt7XARJptflGURdJaO+ITpNkOHmQu7NHmCoRinPbyvFzce/EG/E8Zy81yQ1W9MoSdtklc3nyaDReUw==
dependencies:
http-errors "^2.0.0"
koa-compose "^4.1.0"
methods "^1.1.2"
path-to-regexp "^6.2.1"
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@ -307,6 +324,25 @@
jszip "^3.10.1" jszip "^3.10.1"
semver "^7.3.8" semver "^7.3.8"
"@vscode/test-web@^0.0.44":
version "0.0.44"
resolved "https://registry.yarnpkg.com/@vscode/test-web/-/test-web-0.0.44.tgz#37a9846fd405243d403fa3047817097440d9228c"
integrity sha512-AS/Wuxyx1iFxxn8ljttbsXwOn6jz0qALitC4uXh3cF6Aijx+NnI3dBfWY/6EP5MuAr8mkProdLFal95t17lmnw==
dependencies:
"@koa/cors" "^4.0.0"
"@koa/router" "^12.0.0"
gunzip-maybe "^1.4.2"
http-proxy-agent "^7.0.0"
https-proxy-agent "^7.0.0"
koa "^2.14.2"
koa-morgan "^1.0.1"
koa-mount "^4.0.0"
koa-static "^5.0.0"
minimist "^1.2.8"
playwright "^1.34.3"
tar-fs "^2.1.1"
vscode-uri "^3.0.7"
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
version "1.11.6" version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
@ -445,6 +481,11 @@
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1"
integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==
"@xstate/fsm@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@xstate/fsm/-/fsm-2.0.1.tgz#a5c72cc30dfcf75fd6e65dbf0392f04160dbb0e9"
integrity sha512-fQhs8oWYl0KY4Xn3bvwby7WqXIWhI4+uUx4nOTDrKnayB08qm6t62xN1rnoDQTy621zfpox/lAXvTdZHJeksJw==
"@xtuc/ieee754@^1.2.0": "@xtuc/ieee754@^1.2.0":
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@ -462,6 +503,14 @@ abort-controller@^3.0.0:
dependencies: dependencies:
event-target-shim "^5.0.0" event-target-shim "^5.0.0"
accepts@^1.3.5:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
dependencies:
mime-types "~2.1.34"
negotiator "0.6.3"
acorn-import-assertions@^1.9.0: acorn-import-assertions@^1.9.0:
version "1.9.0" version "1.9.0"
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
@ -484,6 +533,13 @@ agent-base@6:
dependencies: dependencies:
debug "4" debug "4"
agent-base@^7.0.2, agent-base@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434"
integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==
dependencies:
debug "^4.3.4"
ajv-keywords@^3.5.2: ajv-keywords@^3.5.2:
version "3.5.2" version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
@ -601,6 +657,13 @@ base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
basic-auth@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
dependencies:
safe-buffer "5.1.2"
binary-extensions@^2.0.0: binary-extensions@^2.0.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
@ -642,16 +705,18 @@ braces@^3.0.2, braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
browser-or-node@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/browser-or-node/-/browser-or-node-2.1.1.tgz#738790b3a86a8fc020193fa581273fbe65eaea0f"
integrity sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==
browser-stdout@1.3.1: browser-stdout@1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
browserify-zlib@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
integrity sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==
dependencies:
pako "~0.2.0"
browserslist@^4.14.5: browserslist@^4.14.5:
version "4.21.7" version "4.21.7"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.7.tgz#e2b420947e5fb0a58e8f4668ae6e23488127e551" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.7.tgz#e2b420947e5fb0a58e8f4668ae6e23488127e551"
@ -688,6 +753,14 @@ buffer@^6.0.3:
base64-js "^1.3.1" base64-js "^1.3.1"
ieee754 "^1.2.1" ieee754 "^1.2.1"
cache-content-type@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c"
integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==
dependencies:
mime-types "^2.1.18"
ylru "^1.2.0"
call-bind@^1.0.0, call-bind@^1.0.2: call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@ -801,6 +874,11 @@ clone-deep@^4.0.1:
kind-of "^6.0.2" kind-of "^6.0.2"
shallow-clone "^3.0.0" shallow-clone "^3.0.0"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
color-convert@^1.9.0: color-convert@^1.9.0:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@ -862,6 +940,26 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
content-disposition@~0.5.2:
version "0.5.4"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
dependencies:
safe-buffer "5.2.1"
content-type@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
cookies@~0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90"
integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==
dependencies:
depd "~2.0.0"
keygrip "~1.1.0"
core-util-is@~1.0.0: core-util-is@~1.0.0:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
@ -892,13 +990,27 @@ css-what@^6.1.0:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4" version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies: dependencies:
ms "2.1.2" ms "2.1.2"
debug@^3.1.0:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
decamelize@^4.0.0: decamelize@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
@ -935,6 +1047,11 @@ deep-equal@^2.2.1:
which-collection "^1.0.1" which-collection "^1.0.1"
which-typed-array "^1.1.9" which-typed-array "^1.1.9"
deep-equal@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
integrity sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==
deep-extend@^0.6.0: deep-extend@^0.6.0:
version "0.6.0" version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@ -963,6 +1080,26 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
depd@2.0.0, depd@^2.0.0, depd@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
destroy@^1.0.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
detect-libc@^2.0.0: detect-libc@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd"
@ -1017,6 +1154,21 @@ domutils@^3.0.1:
domelementtype "^2.3.0" domelementtype "^2.3.0"
domhandler "^5.0.3" domhandler "^5.0.3"
duplexify@^3.5.0, duplexify@^3.6.0:
version "3.7.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
dependencies:
end-of-stream "^1.0.0"
inherits "^2.0.1"
readable-stream "^2.0.0"
stream-shift "^1.0.0"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.4.411: electron-to-chromium@^1.4.411:
version "1.4.421" version "1.4.421"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.421.tgz#2b8c0ef98ba00d4aef4c664933d570922da52161" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.421.tgz#2b8c0ef98ba00d4aef4c664933d570922da52161"
@ -1027,7 +1179,12 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
end-of-stream@^1.1.0, end-of-stream@^1.4.1: encodeurl@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4" version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@ -1087,6 +1244,11 @@ escalade@^3.1.1:
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-html@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
@ -1335,6 +1497,11 @@ form-data@^4.0.0:
combined-stream "^1.0.8" combined-stream "^1.0.8"
mime-types "^2.1.12" mime-types "^2.1.12"
fresh@~0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
fs-constants@^1.0.0: fs-constants@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
@ -1484,6 +1651,18 @@ graphemer@^1.4.0:
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
gunzip-maybe@^1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz#b913564ae3be0eda6f3de36464837a9cd94b98ac"
integrity sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==
dependencies:
browserify-zlib "^0.1.4"
is-deflate "^1.0.0"
is-gzip "^1.0.0"
peek-stream "^1.1.0"
pumpify "^1.3.3"
through2 "^2.0.3"
handlebars@^4.7.7: handlebars@^4.7.7:
version "4.7.7" version "4.7.7"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
@ -1564,6 +1743,46 @@ htmlparser2@^8.0.1:
domutils "^3.0.1" domutils "^3.0.1"
entities "^4.4.0" entities "^4.4.0"
http-assert@^1.3.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.5.0.tgz#c389ccd87ac16ed2dfa6246fd73b926aa00e6b8f"
integrity sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==
dependencies:
deep-equal "~1.0.1"
http-errors "~1.8.0"
http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.8.0:
version "1.8.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
dependencies:
depd "~1.1.2"
inherits "2.0.4"
setprototypeof "1.2.0"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.1"
http-errors@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
dependencies:
depd "2.0.0"
inherits "2.0.4"
setprototypeof "1.2.0"
statuses "2.0.1"
toidentifier "1.0.1"
http-errors@~1.6.2:
version "1.6.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
http-proxy-agent@^4.0.1: http-proxy-agent@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
@ -1573,6 +1792,14 @@ http-proxy-agent@^4.0.1:
agent-base "6" agent-base "6"
debug "4" debug "4"
http-proxy-agent@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673"
integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==
dependencies:
agent-base "^7.1.0"
debug "^4.3.4"
https-proxy-agent@^5.0.0: https-proxy-agent@^5.0.0:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
@ -1581,6 +1808,14 @@ https-proxy-agent@^5.0.0:
agent-base "6" agent-base "6"
debug "4" debug "4"
https-proxy-agent@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.0.tgz#75cb70d04811685667183b31ab158d006750418a"
integrity sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw==
dependencies:
agent-base "^7.0.2"
debug "4"
ieee754@^1.1.13, ieee754@^1.2.1: ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@ -1625,11 +1860,16 @@ inflight@^1.0.4:
once "^1.3.0" once "^1.3.0"
wrappy "1" wrappy "1"
inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
inherits@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
ini@~1.3.0: ini@~1.3.0:
version "1.3.8" version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
@ -1707,6 +1947,11 @@ is-date-object@^1.0.5:
dependencies: dependencies:
has-tostringtag "^1.0.0" has-tostringtag "^1.0.0"
is-deflate@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14"
integrity sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==
is-extglob@^2.1.1: is-extglob@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@ -1731,6 +1976,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-gzip@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83"
integrity sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==
is-map@^2.0.1, is-map@^2.0.2: is-map@^2.0.1, is-map@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
@ -1913,6 +2163,13 @@ jszip@^3.10.1:
readable-stream "~2.3.6" readable-stream "~2.3.6"
setimmediate "^1.0.5" setimmediate "^1.0.5"
keygrip@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226"
integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==
dependencies:
tsscmp "1.0.6"
keytar@^7.7.0: keytar@^7.7.0:
version "7.9.0" version "7.9.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb"
@ -1926,6 +2183,80 @@ kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
koa-compose@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877"
integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==
koa-convert@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-2.0.0.tgz#86a0c44d81d40551bae22fee6709904573eea4f5"
integrity sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==
dependencies:
co "^4.6.0"
koa-compose "^4.1.0"
koa-morgan@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/koa-morgan/-/koa-morgan-1.0.1.tgz#08052e0ce0d839d3c43178b90a5bb3424bef1f99"
integrity sha512-JOUdCNlc21G50afBXfErUrr1RKymbgzlrO5KURY+wmDG1Uvd2jmxUJcHgylb/mYXy2SjiNZyYim/ptUBGsIi3A==
dependencies:
morgan "^1.6.1"
koa-mount@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/koa-mount/-/koa-mount-4.0.0.tgz#e0265e58198e1a14ef889514c607254ff386329c"
integrity sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==
dependencies:
debug "^4.0.1"
koa-compose "^4.1.0"
koa-send@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-5.0.1.tgz#39dceebfafb395d0d60beaffba3a70b4f543fe79"
integrity sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==
dependencies:
debug "^4.1.1"
http-errors "^1.7.3"
resolve-path "^1.4.0"
koa-static@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/koa-static/-/koa-static-5.0.0.tgz#5e92fc96b537ad5219f425319c95b64772776943"
integrity sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==
dependencies:
debug "^3.1.0"
koa-send "^5.0.0"
koa@^2.14.2:
version "2.14.2"
resolved "https://registry.yarnpkg.com/koa/-/koa-2.14.2.tgz#a57f925c03931c2b4d94b19d2ebf76d3244863fc"
integrity sha512-VFI2bpJaodz6P7x2uyLiX6RLYpZmOJqNmoCst/Yyd7hQlszyPwG/I9CQJ63nOtKSxpt5M7NH67V6nJL2BwCl7g==
dependencies:
accepts "^1.3.5"
cache-content-type "^1.0.0"
content-disposition "~0.5.2"
content-type "^1.0.4"
cookies "~0.8.0"
debug "^4.3.2"
delegates "^1.0.0"
depd "^2.0.0"
destroy "^1.0.4"
encodeurl "^1.0.2"
escape-html "^1.0.3"
fresh "~0.5.2"
http-assert "^1.3.0"
http-errors "^1.6.3"
is-generator-function "^1.0.7"
koa-compose "^4.1.0"
koa-convert "^2.0.0"
on-finished "^2.3.0"
only "~0.0.2"
parseurl "^1.3.2"
statuses "^1.5.0"
type-is "^1.6.16"
vary "^1.1.2"
leven@^3.1.0: leven@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@ -2013,6 +2344,11 @@ mdurl@^1.0.1:
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
merge-stream@^2.0.0: merge-stream@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@ -2023,6 +2359,11 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
methods@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
micromatch@^4.0.0, micromatch@^4.0.4: micromatch@^4.0.0, micromatch@^4.0.4:
version "4.0.5" version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
@ -2036,7 +2377,7 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12, mime-types@^2.1.27: mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35" version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@ -2074,7 +2415,7 @@ minimatch@^5.0.1:
dependencies: dependencies:
brace-expansion "^2.0.1" brace-expansion "^2.0.1"
minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.8:
version "1.2.8" version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@ -2111,12 +2452,28 @@ mocha@^10.0.0:
yargs-parser "20.2.4" yargs-parser "20.2.4"
yargs-unparser "2.0.0" yargs-unparser "2.0.0"
morgan@^1.6.1:
version "1.10.0"
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==
dependencies:
basic-auth "~2.0.1"
debug "2.6.9"
depd "~2.0.0"
on-finished "~2.3.0"
on-headers "~1.0.2"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
ms@2.1.2: ms@2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@2.1.3: ms@2.1.3, ms@^2.1.1:
version "2.1.3" version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@ -2146,6 +2503,11 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
negotiator@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
neo-async@^2.6.0, neo-async@^2.6.2: neo-async@^2.6.0, neo-async@^2.6.2:
version "2.6.2" version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
@ -2225,6 +2587,25 @@ on-exit-leak-free@^2.1.0:
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4"
integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==
on-finished@^2.3.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
dependencies:
ee-first "1.1.1"
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==
dependencies:
ee-first "1.1.1"
on-headers@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
once@^1.3.0, once@^1.3.1, once@^1.4.0: once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@ -2232,6 +2613,11 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies: dependencies:
wrappy "1" wrappy "1"
only@~0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==
openapi-typescript-codegen@^0.24.0: openapi-typescript-codegen@^0.24.0:
version "0.24.0" version "0.24.0"
resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.24.0.tgz#b3e6ade5bae75cd47868e5e3e4dc3bcf899cadab" resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.24.0.tgz#b3e6ade5bae75cd47868e5e3e4dc3bcf899cadab"
@ -2288,6 +2674,11 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
pako@~0.2.0:
version "0.2.9"
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==
pako@~1.0.2: pako@~1.0.2:
version "1.0.11" version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
@ -2322,12 +2713,17 @@ parse5@^7.0.0:
dependencies: dependencies:
entities "^4.4.0" entities "^4.4.0"
parseurl@^1.3.2:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
path-exists@^4.0.0: path-exists@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
path-is-absolute@^1.0.0: path-is-absolute@1.0.1, path-is-absolute@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
@ -2342,11 +2738,25 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-to-regexp@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==
path-type@^4.0.0: path-type@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
peek-stream@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67"
integrity sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==
dependencies:
buffer-from "^1.0.0"
duplexify "^3.5.0"
through2 "^2.0.3"
pend@~1.2.0: pend@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
@ -2399,6 +2809,18 @@ pkg-dir@^4.2.0:
dependencies: dependencies:
find-up "^4.0.0" find-up "^4.0.0"
playwright-core@1.35.0:
version "1.35.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.35.0.tgz#b7871b742b4a5c8714b7fa2f570c280a061cb414"
integrity sha512-muMXyPmIx/2DPrCHOD1H1ePT01o7OdKxKj2ebmCAYvqhUy+Y1bpal7B0rdoxros7YrXI294JT/DWw2LqyiqTPA==
playwright@^1.34.3:
version "1.35.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.35.0.tgz#4e3b3ea2495d6fd671700f77b2f97b3adedf80f1"
integrity sha512-xhFhsoBmKPQfj3dM+HbIiFVlqRCZp2rwdJd/QFd9YBuidabo3TkVv0iuxPQ4vZoMwtSI7qzjY93f5ohdC97hww==
dependencies:
playwright-core "1.35.0"
prebuild-install@^7.0.1: prebuild-install@^7.0.1:
version "7.1.1" version "7.1.1"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45"
@ -2442,6 +2864,14 @@ proxy-from-env@^1.1.0:
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
pump@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
pump@^3.0.0: pump@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
@ -2450,6 +2880,15 @@ pump@^3.0.0:
end-of-stream "^1.1.0" end-of-stream "^1.1.0"
once "^1.3.1" once "^1.3.1"
pumpify@^1.3.3:
version "1.5.1"
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
dependencies:
duplexify "^3.6.0"
inherits "^2.0.3"
pump "^2.0.0"
punycode@^2.1.0: punycode@^2.1.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
@ -2496,6 +2935,19 @@ read@^1.0.7:
dependencies: dependencies:
mute-stream "~0.0.4" mute-stream "~0.0.4"
readable-stream@^2.0.0, readable-stream@~2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^3.1.1, readable-stream@^3.4.0: readable-stream@^3.1.1, readable-stream@^3.4.0:
version "3.6.2" version "3.6.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
@ -2515,19 +2967,6 @@ readable-stream@^4.0.0:
events "^3.3.0" events "^3.3.0"
process "^0.11.10" process "^0.11.10"
readable-stream@~2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readdirp@~3.6.0: readdirp@~3.6.0:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@ -2578,6 +3017,14 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve-path@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7"
integrity sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==
dependencies:
http-errors "~1.6.2"
path-is-absolute "1.0.1"
resolve@^1.9.0: resolve@^1.9.0:
version "1.22.2" version "1.22.2"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
@ -2611,16 +3058,16 @@ run-parallel@^1.1.9:
dependencies: dependencies:
queue-microtask "^1.2.2" queue-microtask "^1.2.2"
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-stable-stringify@^2.3.1: safe-stable-stringify@^2.3.1:
version "2.4.3" version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
@ -2671,6 +3118,16 @@ setimmediate@^1.0.5:
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
setprototypeof@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
shallow-clone@^3.0.0: shallow-clone@^3.0.0:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
@ -2743,6 +3200,16 @@ split2@^4.0.0:
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
statuses@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
stop-iteration-iterator@^1.0.0: stop-iteration-iterator@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
@ -2750,6 +3217,11 @@ stop-iteration-iterator@^1.0.0:
dependencies: dependencies:
internal-slot "^1.0.4" internal-slot "^1.0.4"
stream-shift@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
string-width@^4.1.0, string-width@^4.2.0: string-width@^4.1.0, string-width@^4.2.0:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@ -2820,10 +3292,10 @@ supports-preserve-symlinks-flag@^1.0.0:
version "0.0.1" version "0.0.1"
dependencies: dependencies:
axios "^1.4.0" axios "^1.4.0"
browser-or-node "^2.1.1"
deep-equal "^2.2.1" deep-equal "^2.2.1"
deepmerge "^4.3.1" deepmerge "^4.3.1"
form-data "^4.0.0" form-data "^4.0.0"
fs-extra "^11.1.1"
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"
@ -2836,7 +3308,7 @@ tapable@^2.1.1, tapable@^2.2.0:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
tar-fs@^2.0.0: tar-fs@^2.0.0, tar-fs@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
@ -2890,6 +3362,14 @@ thread-stream@^2.0.0:
dependencies: dependencies:
real-require "^0.2.0" real-require "^0.2.0"
through2@^2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
dependencies:
readable-stream "~2.3.6"
xtend "~4.0.1"
tmp@^0.2.1: tmp@^0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
@ -2904,6 +3384,11 @@ to-regex-range@^5.0.1:
dependencies: dependencies:
is-number "^7.0.0" is-number "^7.0.0"
toidentifier@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
ts-loader@^9.3.1: ts-loader@^9.3.1:
version "9.4.3" version "9.4.3"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.3.tgz#55cfa7c28dd82a2de968ae45c3adb75fb888b27e" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.3.tgz#55cfa7c28dd82a2de968ae45c3adb75fb888b27e"
@ -2919,6 +3404,11 @@ tslib@^1.8.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tsscmp@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==
tsutils@^3.21.0: tsutils@^3.21.0:
version "3.21.0" version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
@ -2950,6 +3440,14 @@ type-fest@^0.20.2:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
type-is@^1.6.16:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
dependencies:
media-typer "0.3.0"
mime-types "~2.1.24"
typed-rest-client@^1.8.4: typed-rest-client@^1.8.4:
version "1.8.9" version "1.8.9"
resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-1.8.9.tgz#e560226bcadfe71b0fb5c416b587f8da3b8f92d8" resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-1.8.9.tgz#e560226bcadfe71b0fb5c416b587f8da3b8f92d8"
@ -3025,6 +3523,11 @@ uuid@^9.0.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
vary@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
vsce@^2.15.0: vsce@^2.15.0:
version "2.15.0" version "2.15.0"
resolved "https://registry.yarnpkg.com/vsce/-/vsce-2.15.0.tgz#4a992e78532092a34a755143c6b6c2cabcb7d729" resolved "https://registry.yarnpkg.com/vsce/-/vsce-2.15.0.tgz#4a992e78532092a34a755143c6b6c2cabcb7d729"
@ -3051,6 +3554,11 @@ vsce@^2.15.0:
yauzl "^2.3.1" yauzl "^2.3.1"
yazl "^2.2.2" yazl "^2.2.2"
vscode-uri@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.7.tgz#6d19fef387ee6b46c479e5fb00870e15e58c1eb8"
integrity sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==
watchpack@^2.4.0: watchpack@^2.4.0:
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
@ -3207,6 +3715,11 @@ xmlbuilder@~11.0.0:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^5.0.5: y18n@^5.0.5:
version "5.0.8" version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
@ -3265,6 +3778,11 @@ yazl@^2.2.2:
dependencies: dependencies:
buffer-crc32 "~0.2.3" buffer-crc32 "~0.2.3"
ylru@^1.2.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.3.2.tgz#0de48017473275a4cbdfc83a1eaf67c01af8a785"
integrity sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==
yocto-queue@^0.1.0: yocto-queue@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"