feat: tabby agent auth (#240)
* feat: Support tabby server auth. * fix notification toggle command. * feat: add vscode web support.improve-workflow
parent
008ad75e1f
commit
11e4a5991d
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,23 +1,5 @@
|
|||
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 {
|
||||
readonly isResolved: boolean;
|
||||
readonly isRejected: boolean;
|
||||
|
|
@ -54,38 +36,21 @@ type LogEventRequest$1 = {
|
|||
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 = {
|
||||
server?: {
|
||||
endpoint?: string;
|
||||
server: {
|
||||
endpoint: string;
|
||||
};
|
||||
logs?: {
|
||||
level?: "debug" | "error" | "silent";
|
||||
logs: {
|
||||
level: "debug" | "error" | "silent";
|
||||
};
|
||||
anonymousUsageTracking?: {
|
||||
disable?: boolean;
|
||||
anonymousUsageTracking: {
|
||||
disable: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
type AgentInitOptions = {
|
||||
config?: AgentConfig;
|
||||
client?: string;
|
||||
config: Partial<AgentConfig>;
|
||||
client: string;
|
||||
};
|
||||
type CompletionRequest = {
|
||||
filepath: string;
|
||||
|
|
@ -95,17 +60,33 @@ type CompletionRequest = {
|
|||
};
|
||||
type CompletionResponse = CompletionResponse$1;
|
||||
type LogEventRequest = LogEventRequest$1;
|
||||
type AgentStatus = "notInitialized" | "ready" | "disconnected" | "unauthorized";
|
||||
interface AgentFunction {
|
||||
initialize(options?: AgentInitOptions): boolean;
|
||||
updateConfig(config: AgentConfig): boolean;
|
||||
initialize(options: Partial<AgentInitOptions>): Promise<boolean>;
|
||||
updateConfig(config: Partial<AgentConfig>): Promise<boolean>;
|
||||
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>;
|
||||
/**
|
||||
* @param event
|
||||
* @returns
|
||||
* @throws Error if agent is not initialized
|
||||
*/
|
||||
postEvent(event: LogEventRequest): CancelablePromise<boolean>;
|
||||
}
|
||||
type StatusChangedEvent = {
|
||||
event: "statusChanged";
|
||||
status: "connecting" | "ready" | "disconnected";
|
||||
status: AgentStatus;
|
||||
};
|
||||
type ConfigUpdatedEvent = {
|
||||
event: "configUpdated";
|
||||
|
|
@ -118,24 +99,51 @@ interface 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 {
|
||||
private readonly logger;
|
||||
private config;
|
||||
private status;
|
||||
private api;
|
||||
private auth;
|
||||
private dataStore;
|
||||
private completionCache;
|
||||
constructor();
|
||||
private onConfigUpdated;
|
||||
static readonly tryConnectInterval: number;
|
||||
private tryingConnectTimer;
|
||||
private constructor();
|
||||
static create(options?: Partial<TabbyAgentOptions>): Promise<TabbyAgent>;
|
||||
private applyConfig;
|
||||
private onAuthUpdated;
|
||||
private changeStatus;
|
||||
private ping;
|
||||
private callApi;
|
||||
private healthCheck;
|
||||
private createSegments;
|
||||
initialize(params: AgentInitOptions): boolean;
|
||||
updateConfig(config: AgentConfig): boolean;
|
||||
initialize(options: Partial<AgentInitOptions>): Promise<boolean>;
|
||||
updateConfig(config: Partial<AgentConfig>): Promise<boolean>;
|
||||
getConfig(): AgentConfig;
|
||||
getStatus(): "connecting" | "ready" | "disconnected";
|
||||
getStatus(): AgentStatus;
|
||||
startAuth(): CancelablePromise<string | null>;
|
||||
getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse>;
|
||||
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
|
|
@ -47,8 +47,6 @@ var __privateSet = (obj, member, value, setter) => {
|
|||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
ApiError: () => ApiError,
|
||||
CancelError: () => CancelError,
|
||||
CancelablePromise: () => CancelablePromise,
|
||||
TabbyAgent: () => TabbyAgent,
|
||||
agentEventNames: () => agentEventNames
|
||||
|
|
@ -56,8 +54,7 @@ __export(src_exports, {
|
|||
module.exports = __toCommonJS(src_exports);
|
||||
|
||||
// src/TabbyAgent.ts
|
||||
var import_axios2 = __toESM(require("axios"));
|
||||
var import_events = require("events");
|
||||
var import_events2 = require("events");
|
||||
var import_uuid = require("uuid");
|
||||
var import_deep_equal2 = __toESM(require("deep-equal"));
|
||||
var import_deepmerge = __toESM(require("deepmerge"));
|
||||
|
|
@ -246,13 +243,13 @@ var getQueryString = (params) => {
|
|||
};
|
||||
var getUrl = (config, options) => {
|
||||
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)) {
|
||||
return encoder(String(options.path[group]));
|
||||
}
|
||||
return substring;
|
||||
});
|
||||
const url = `${config.BASE}${path2}`;
|
||||
const url = `${config.BASE}${path}`;
|
||||
if (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
|
||||
var TabbyApi = class {
|
||||
constructor(config, HttpRequest = AxiosHttpRequest) {
|
||||
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",
|
||||
WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
|
||||
CREDENTIALS: config?.CREDENTIALS ?? "include",
|
||||
|
|
@ -482,9 +489,6 @@ var TabbyApi = class {
|
|||
};
|
||||
|
||||
// src/utils.ts
|
||||
function sleep(milliseconds) {
|
||||
return new Promise((r) => setTimeout(r, milliseconds));
|
||||
}
|
||||
function splitLines(input) {
|
||||
return input.match(/.*(?:$|\r?\n)/g).filter(Boolean);
|
||||
}
|
||||
|
|
@ -507,36 +511,79 @@ function cancelable(promise, cancel) {
|
|||
});
|
||||
}
|
||||
|
||||
// src/AgentConfig.ts
|
||||
var defaultAgentConfig = {
|
||||
server: {
|
||||
endpoint: "http://localhost:8080"
|
||||
},
|
||||
logs: {
|
||||
level: "error"
|
||||
},
|
||||
anonymousUsageTracking: {
|
||||
disable: false
|
||||
// src/Auth.ts
|
||||
var import_events = require("events");
|
||||
|
||||
// src/cloud/services/ApiService.ts
|
||||
var ApiService = class {
|
||||
constructor(httpRequest) {
|
||||
this.httpRequest = httpRequest;
|
||||
}
|
||||
/**
|
||||
* @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
|
||||
var import_lru_cache = require("lru-cache");
|
||||
var import_object_hash = __toESM(require("object-hash"));
|
||||
var import_object_sizeof = __toESM(require("object-sizeof"));
|
||||
// src/cloud/CloudApi.ts
|
||||
var CloudApi = class {
|
||||
constructor(config, HttpRequest = 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);
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
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 stream = import_browser_or_node.isBrowser ? null : (
|
||||
var stream = false ? null : (
|
||||
/**
|
||||
* Default rotating file locate at `~/.tabby/agent-logs/`.
|
||||
*/
|
||||
rotatingFileStream.createStream("tabby-agent.log", {
|
||||
path: import_path.default.join(import_os.default.homedir(), ".tabby", "agent-logs"),
|
||||
require("rotating-file-stream").createStream("tabby-agent.log", {
|
||||
path: require("path").join(require("os").homedir(), ".tabby", "agent-logs"),
|
||||
size: "10M",
|
||||
interval: "1d"
|
||||
})
|
||||
|
|
@ -547,7 +594,150 @@ rootLogger.onChild = (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
|
||||
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 {
|
||||
constructor() {
|
||||
this.logger = rootLogger.child({ component: "CompletionCache" });
|
||||
|
|
@ -695,19 +885,40 @@ async function postprocess(request2, response) {
|
|||
}
|
||||
|
||||
// src/TabbyAgent.ts
|
||||
var TabbyAgent = class extends import_events.EventEmitter {
|
||||
var _TabbyAgent = class extends import_events2.EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.logger = rootLogger.child({ component: "TabbyAgent" });
|
||||
this.config = defaultAgentConfig;
|
||||
this.status = "connecting";
|
||||
this.status = "notInitialized";
|
||||
this.dataStore = null;
|
||||
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);
|
||||
this.api = new TabbyApi({ BASE: this.config.server.endpoint });
|
||||
this.ping();
|
||||
if (this.config.server.endpoint !== this.auth?.endpoint) {
|
||||
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) {
|
||||
if (this.status != status) {
|
||||
|
|
@ -717,22 +928,6 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
|||
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) {
|
||||
this.logger.debug({ api: api.name, request: request2 }, "API request");
|
||||
const promise = api.call(this.api.v1, request2);
|
||||
|
|
@ -742,11 +937,18 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
|||
this.changeStatus("ready");
|
||||
return response;
|
||||
}).catch((error) => {
|
||||
this.logger.debug({ api: api.name }, "API request canceled");
|
||||
throw error;
|
||||
}).catch((error) => {
|
||||
if (!!error.isCancelled) {
|
||||
this.logger.debug({ api: api.name, error }, "API request canceled");
|
||||
} 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.changeStatus("disconnected");
|
||||
} else {
|
||||
this.logger.error({ api: api.name, error }, "API request failed with unknown error");
|
||||
this.changeStatus("disconnected");
|
||||
}
|
||||
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) {
|
||||
const maxLines = 20;
|
||||
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("")
|
||||
};
|
||||
}
|
||||
initialize(params) {
|
||||
if (params.config) {
|
||||
this.updateConfig(params.config);
|
||||
async initialize(options) {
|
||||
if (options.client) {
|
||||
allLoggers.forEach((logger2) => logger2.setBindings && logger2.setBindings({ client: options.client }));
|
||||
}
|
||||
if (params.client) {
|
||||
allLoggers.forEach((logger2) => logger2.setBindings && logger2.setBindings({ client: params.client }));
|
||||
if (options.config) {
|
||||
await this.updateConfig(options.config);
|
||||
}
|
||||
this.logger.debug({ params }, "Initialized");
|
||||
return true;
|
||||
this.logger.debug({ options }, "Initialized");
|
||||
return this.status !== "notInitialized";
|
||||
}
|
||||
updateConfig(config) {
|
||||
async updateConfig(config) {
|
||||
const mergedConfig = (0, import_deepmerge.default)(this.config, config);
|
||||
if (!(0, import_deep_equal2.default)(this.config, mergedConfig)) {
|
||||
this.config = mergedConfig;
|
||||
this.onConfigUpdated();
|
||||
await this.applyConfig();
|
||||
const event = { event: "configUpdated", config: this.config };
|
||||
this.logger.debug({ event }, "Config updated");
|
||||
super.emit("configUpdated", event);
|
||||
}
|
||||
return true;
|
||||
await this.healthCheck();
|
||||
return this.status !== "notInitialized";
|
||||
}
|
||||
getConfig() {
|
||||
return this.config;
|
||||
|
|
@ -792,7 +999,25 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
|||
getStatus() {
|
||||
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) {
|
||||
if (this.status === "notInitialized") {
|
||||
throw new Error("Agent is not initialized");
|
||||
}
|
||||
if (this.completionCache.has(request2)) {
|
||||
this.logger.debug({ request: request2 }, "Completion cache hit");
|
||||
return new CancelablePromise((resolve2) => {
|
||||
|
|
@ -826,16 +1051,19 @@ var TabbyAgent = class extends import_events.EventEmitter {
|
|||
);
|
||||
}
|
||||
postEvent(request2) {
|
||||
if (this.status === "notInitialized") {
|
||||
throw new Error("Agent is not initialized");
|
||||
}
|
||||
return this.callApi(this.api.v1.event, request2);
|
||||
}
|
||||
};
|
||||
var TabbyAgent = _TabbyAgent;
|
||||
TabbyAgent.tryConnectInterval = 1e3 * 30;
|
||||
|
||||
// src/Agent.ts
|
||||
var agentEventNames = ["statusChanged", "configUpdated"];
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
ApiError,
|
||||
CancelError,
|
||||
CancelablePromise,
|
||||
TabbyAgent,
|
||||
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
|
|
@ -15,6 +15,7 @@
|
|||
"build": "tsup"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@types/node": "^16.18.32",
|
||||
"esbuild-plugin-polyfill-node": "^0.2.0",
|
||||
"openapi-typescript-codegen": "^0.24.0",
|
||||
|
|
@ -24,10 +25,10 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"browser-or-node": "^2.1.1",
|
||||
"deep-equal": "^2.2.1",
|
||||
"deepmerge": "^4.3.1",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"lru-cache": "^9.1.1",
|
||||
"object-hash": "^3.0.0",
|
||||
"object-sizeof": "^2.6.1",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import {
|
|||
import { AgentConfig } from "./AgentConfig";
|
||||
|
||||
export type AgentInitOptions = {
|
||||
config?: AgentConfig;
|
||||
client?: string;
|
||||
config: Partial<AgentConfig>;
|
||||
client: string;
|
||||
};
|
||||
|
||||
export type CompletionRequest = {
|
||||
|
|
@ -22,18 +22,38 @@ export type CompletionResponse = ApiCompletionResponse;
|
|||
|
||||
export type LogEventRequest = ApiLogEventRequest;
|
||||
|
||||
export type AgentStatus = "notInitialized" | "ready" | "disconnected" | "unauthorized";
|
||||
|
||||
export interface AgentFunction {
|
||||
initialize(options?: AgentInitOptions): boolean;
|
||||
updateConfig(config: AgentConfig): boolean;
|
||||
initialize(options: Partial<AgentInitOptions>): Promise<boolean>;
|
||||
updateConfig(config: Partial<AgentConfig>): Promise<boolean>;
|
||||
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>;
|
||||
|
||||
/**
|
||||
* @param event
|
||||
* @returns
|
||||
* @throws Error if agent is not initialized
|
||||
*/
|
||||
postEvent(event: LogEventRequest): CancelablePromise<boolean>;
|
||||
}
|
||||
|
||||
export type StatusChangedEvent = {
|
||||
event: "statusChanged";
|
||||
status: "connecting" | "ready" | "disconnected";
|
||||
status: AgentStatus;
|
||||
};
|
||||
export type ConfigUpdatedEvent = {
|
||||
event: "configUpdated";
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
export type AgentConfig = {
|
||||
server?: {
|
||||
endpoint?: string;
|
||||
server: {
|
||||
endpoint: string;
|
||||
};
|
||||
logs?: {
|
||||
level?: "debug" | "error" | "silent";
|
||||
logs: {
|
||||
level: "debug" | "error" | "silent";
|
||||
};
|
||||
anonymousUsageTracking?: {
|
||||
disable?: boolean;
|
||||
anonymousUsageTracking: {
|
||||
disable: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ export const defaultAgentConfig: AgentConfig = {
|
|||
endpoint: "http://localhost:8080",
|
||||
},
|
||||
logs: {
|
||||
level: "error",
|
||||
level: "silent",
|
||||
},
|
||||
anonymousUsageTracking: {
|
||||
disable: false,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ export class StdIO {
|
|||
private readonly logger = rootLogger.child({ component: "StdIO" });
|
||||
|
||||
private buffer: string = "";
|
||||
private ongoingRequests: { [id: number]: CancelablePromise<any> } = {};
|
||||
private ongoingRequests: { [id: number]: PromiseLike<any> } = {};
|
||||
|
||||
private agent: Agent | null = null;
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ export class StdIO {
|
|||
throw new Error(`Unknown function: ${funcName}`);
|
||||
}
|
||||
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;
|
||||
response[1] = await result;
|
||||
delete this.ongoingRequests[request[0]];
|
||||
|
|
@ -118,7 +118,10 @@ export class StdIO {
|
|||
if (!ongoing) {
|
||||
return false;
|
||||
}
|
||||
if (ongoing instanceof CancelablePromise) {
|
||||
ongoing.cancel();
|
||||
}
|
||||
delete this.ongoingRequests[request[1].args[0]];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +1,77 @@
|
|||
import axios from "axios";
|
||||
import { EventEmitter } from "events";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import deepEqual from "deep-equal";
|
||||
import deepMerge from "deepmerge";
|
||||
import { TabbyApi, CancelablePromise, ApiError, CancelError } from "./generated";
|
||||
import { sleep, cancelable, splitLines, isBlank } from "./utils";
|
||||
import { Agent, AgentEvent, AgentInitOptions, CompletionRequest, CompletionResponse, LogEventRequest } from "./Agent";
|
||||
import { TabbyApi, CancelablePromise } from "./generated";
|
||||
import { cancelable, splitLines, isBlank } from "./utils";
|
||||
import {
|
||||
Agent,
|
||||
AgentStatus,
|
||||
AgentEvent,
|
||||
AgentInitOptions,
|
||||
CompletionRequest,
|
||||
CompletionResponse,
|
||||
LogEventRequest,
|
||||
} from "./Agent";
|
||||
import { Auth } from "./Auth";
|
||||
import { AgentConfig, defaultAgentConfig } from "./AgentConfig";
|
||||
import { CompletionCache } from "./CompletionCache";
|
||||
import { DataStore } from "./dataStore";
|
||||
import { postprocess } from "./postprocess";
|
||||
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 {
|
||||
private readonly logger = rootLogger.child({ component: "TabbyAgent" });
|
||||
private config: AgentConfig = defaultAgentConfig;
|
||||
private status: "connecting" | "ready" | "disconnected" = "connecting";
|
||||
private status: AgentStatus = "notInitialized";
|
||||
private api: TabbyApi;
|
||||
private auth: Auth;
|
||||
private dataStore: DataStore | null = null;
|
||||
private completionCache: CompletionCache = new CompletionCache();
|
||||
static readonly tryConnectInterval = 1000 * 30; // 30s
|
||||
private tryingConnectTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
constructor() {
|
||||
private constructor() {
|
||||
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));
|
||||
this.api = new TabbyApi({ BASE: this.config.server.endpoint });
|
||||
this.ping();
|
||||
if (this.config.server.endpoint !== this.auth?.endpoint) {
|
||||
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) {
|
||||
this.status = 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>(
|
||||
api: (request: Request) => CancelablePromise<Response>,
|
||||
request: Request
|
||||
|
|
@ -68,13 +93,19 @@ export class TabbyAgent extends EventEmitter implements Agent {
|
|||
this.changeStatus("ready");
|
||||
return response;
|
||||
})
|
||||
.catch((error: CancelError) => {
|
||||
this.logger.debug({ api: api.name }, "API request canceled");
|
||||
throw error;
|
||||
})
|
||||
.catch((error: ApiError) => {
|
||||
.catch((error) => {
|
||||
if (!!error.isCancelled) {
|
||||
this.logger.debug({ api: api.name, error }, "API request canceled");
|
||||
} 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.changeStatus("disconnected");
|
||||
} else {
|
||||
this.logger.error({ api: api.name, error }, "API request failed with unknown error");
|
||||
this.changeStatus("disconnected");
|
||||
}
|
||||
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 } {
|
||||
// max to 20 lines in prefix and max to 20 lines in suffix
|
||||
const maxLines = 20;
|
||||
|
|
@ -96,40 +131,60 @@ export class TabbyAgent extends EventEmitter implements Agent {
|
|||
};
|
||||
}
|
||||
|
||||
public initialize(params: AgentInitOptions): boolean {
|
||||
if (params.config) {
|
||||
this.updateConfig(params.config);
|
||||
}
|
||||
if (params.client) {
|
||||
public async initialize(options: Partial<AgentInitOptions>): Promise<boolean> {
|
||||
if (options.client) {
|
||||
// Client info is only used in logging for now
|
||||
// `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");
|
||||
return true;
|
||||
if (options.config) {
|
||||
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);
|
||||
if (!deepEqual(this.config, mergedConfig)) {
|
||||
this.config = mergedConfig;
|
||||
this.onConfigUpdated();
|
||||
await this.applyConfig();
|
||||
const event: AgentEvent = { event: "configUpdated", config: this.config };
|
||||
this.logger.debug({ event }, "Config updated");
|
||||
super.emit("configUpdated", event);
|
||||
}
|
||||
return true;
|
||||
await this.healthCheck();
|
||||
return this.status !== "notInitialized";
|
||||
}
|
||||
|
||||
public getConfig(): AgentConfig {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public getStatus(): "connecting" | "ready" | "disconnected" {
|
||||
public getStatus(): AgentStatus {
|
||||
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> {
|
||||
if (this.status === "notInitialized") {
|
||||
throw new Error("Agent is not initialized");
|
||||
}
|
||||
if (this.completionCache.has(request)) {
|
||||
this.logger.debug({ request }, "Completion cache hit");
|
||||
return new CancelablePromise((resolve) => {
|
||||
|
|
@ -166,6 +221,9 @@ export class TabbyAgent extends EventEmitter implements Agent {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
import { TabbyAgent } from "./TabbyAgent";
|
||||
import { StdIO } from "./StdIO";
|
||||
|
||||
const agent = new TabbyAgent();
|
||||
const stdio = new StdIO();
|
||||
stdio.bind(agent);
|
||||
TabbyAgent.create().then((agent) => {
|
||||
stdio.bind(agent);
|
||||
});
|
||||
|
||||
stdio.listen();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
export { CloudApi } from "./CloudApi";
|
||||
export { ApiService } from "./services/ApiService";
|
||||
export { DeviceTokenResponse } from "./models/DeviceTokenResponse";
|
||||
export { DeviceTokenAcceptResponse } from "./models/DeviceTokenAcceptResponse";
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export type DeviceTokenAcceptResponse = {
|
||||
data: {
|
||||
jwt: string;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export type DeviceTokenResponse = {
|
||||
data: {
|
||||
code: string;
|
||||
};
|
||||
};
|
||||
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
|
@ -1,17 +1,16 @@
|
|||
export { TabbyAgent } from "./TabbyAgent";
|
||||
export { TabbyAgent, TabbyAgentOptions } from "./TabbyAgent";
|
||||
export {
|
||||
Agent,
|
||||
AgentStatus,
|
||||
AgentFunction,
|
||||
AgentEvent,
|
||||
StatusChangedEvent,
|
||||
ConfigUpdatedEvent,
|
||||
CompletionRequest,
|
||||
CompletionResponse,
|
||||
LogEventRequest,
|
||||
agentEventNames,
|
||||
} from "./Agent";
|
||||
export { AgentConfig } from "./AgentConfig";
|
||||
export {
|
||||
CancelablePromise,
|
||||
CancelError,
|
||||
ApiError,
|
||||
Choice,
|
||||
} from "./generated";
|
||||
export { DataStore } from "./dataStore";
|
||||
export { CancelablePromise } from "./generated";
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
declare var IS_BROWSER: boolean;
|
||||
|
||||
/**
|
||||
* Stream not available in browser, will use default console output.
|
||||
*/
|
||||
const stream = isBrowser
|
||||
const stream = IS_BROWSER
|
||||
? null
|
||||
: /**
|
||||
* Default rotating file locate at `~/.tabby/agent-logs/`.
|
||||
*/
|
||||
rotatingFileStream.createStream("tabby-agent.log", {
|
||||
path: path.join(os.homedir(), ".tabby", "agent-logs"),
|
||||
require("rotating-file-stream").createStream("tabby-agent.log", {
|
||||
path: require("path").join(require("os").homedir(), ".tabby", "agent-logs"),
|
||||
size: "10M",
|
||||
interval: "1d",
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
export function sleep(milliseconds: number) {
|
||||
return new Promise((r) => setTimeout(r, milliseconds));
|
||||
}
|
||||
|
||||
export function splitLines(input: string) {
|
||||
return input.match(/.*(?:$|\r?\n)/g).filter(Boolean) // Split lines and keep newline character
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ import { defineConfig } from "tsup";
|
|||
import { polyfillNode } from "esbuild-plugin-polyfill-node";
|
||||
import { dependencies } from "./package.json";
|
||||
|
||||
const defineIsBrowser = (targetOptions, isBrowser: boolean) => {
|
||||
targetOptions["define"] = { ...targetOptions["define"], "IS_BROWSER": isBrowser.toString() };
|
||||
return targetOptions;
|
||||
}
|
||||
|
||||
export default async () => [
|
||||
defineConfig({
|
||||
name: "node-cjs",
|
||||
|
|
@ -9,6 +14,9 @@ export default async () => [
|
|||
platform: "node",
|
||||
format: ["cjs"],
|
||||
sourcemap: true,
|
||||
esbuildOptions(options) {
|
||||
defineIsBrowser(options, false);
|
||||
},
|
||||
clean: true,
|
||||
}),
|
||||
defineConfig({
|
||||
|
|
@ -17,6 +25,7 @@ export default async () => [
|
|||
platform: "browser",
|
||||
format: ["iife"],
|
||||
globalName: "Tabby",
|
||||
treeshake: "smallest",
|
||||
minify: true,
|
||||
sourcemap: true,
|
||||
esbuildPlugins: [
|
||||
|
|
@ -24,6 +33,9 @@ export default async () => [
|
|||
polyfills: { fs: true },
|
||||
}),
|
||||
],
|
||||
esbuildOptions(options) {
|
||||
defineIsBrowser(options, true);
|
||||
},
|
||||
clean: true,
|
||||
}),
|
||||
defineConfig({
|
||||
|
|
@ -33,12 +45,16 @@ export default async () => [
|
|||
format: ["esm"],
|
||||
// FIXME: bundle all dependencies to reduce module resolving problems, not a good solution
|
||||
noExternal: Object.keys(dependencies),
|
||||
treeshake: true,
|
||||
sourcemap: true,
|
||||
esbuildPlugins: [
|
||||
polyfillNode({
|
||||
polyfills: { fs: true },
|
||||
}),
|
||||
],
|
||||
esbuildOptions(options) {
|
||||
defineIsBrowser(options, true);
|
||||
},
|
||||
clean: true,
|
||||
}),
|
||||
defineConfig({
|
||||
|
|
@ -54,8 +70,12 @@ export default async () => [
|
|||
entry: ["src/cli.ts"],
|
||||
platform: "node",
|
||||
noExternal: Object.keys(dependencies),
|
||||
treeshake: "smallest",
|
||||
minify: true,
|
||||
sourcemap: true,
|
||||
esbuildOptions(options) {
|
||||
defineIsBrowser(options, false);
|
||||
},
|
||||
clean: true,
|
||||
}),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -207,11 +207,31 @@
|
|||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
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":
|
||||
version "7.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||
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":
|
||||
version "16.18.32"
|
||||
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:
|
||||
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:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ dist
|
|||
node_modules
|
||||
generated
|
||||
.vscode-test/
|
||||
.vscode-test-web/
|
||||
*.vsix
|
||||
|
|
|
|||
|
|
@ -21,9 +21,23 @@
|
|||
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
|
||||
"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",
|
||||
"type": "pwa-extensionHost",
|
||||
"type": "extensionHost",
|
||||
"debugWebWorkerHost": true,
|
||||
"request": "launch",
|
||||
"args": [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
.vscode/**
|
||||
.vscode-test/**
|
||||
.vscode-test-web/**
|
||||
out/**
|
||||
node_modules/**
|
||||
src/**
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@
|
|||
"watch": "webpack --watch",
|
||||
"dev": "code --extensionDevelopmentPath=$PWD --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",
|
||||
"compile-tests": "tsc -p . --outDir out",
|
||||
"watch-tests": "tsc -p . -w --outDir out",
|
||||
|
|
@ -99,6 +100,7 @@
|
|||
"@typescript-eslint/eslint-plugin": "^5.31.0",
|
||||
"@typescript-eslint/parser": "^5.31.0",
|
||||
"@vscode/test-electron": "^2.1.5",
|
||||
"@vscode/test-web": "^0.0.44",
|
||||
"assert": "^2.0.0",
|
||||
"eslint": "^8.20.0",
|
||||
"glob": "^8.0.3",
|
||||
|
|
@ -113,6 +115,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@sapphire/duration": "^1.1.0",
|
||||
"@xstate/fsm": "^2.0.1",
|
||||
"tabby-agent": "file:../tabby-agent"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import {
|
|||
workspace,
|
||||
} from "vscode";
|
||||
import { CompletionResponse, CancelablePromise } from "tabby-agent";
|
||||
import { Agent } from "./Agent";
|
||||
import { agent } from "./agent";
|
||||
import { sleep } from "./utils";
|
||||
|
||||
export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
||||
|
|
@ -19,7 +19,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
|||
private latestTimestamp: number = 0;
|
||||
private pendingCompletion: CancelablePromise<CompletionResponse> | null = null;
|
||||
|
||||
private agent = Agent.getInstance();
|
||||
// User Settings
|
||||
private enabled: boolean = true;
|
||||
private suggestionDelay: number = 150;
|
||||
|
|
@ -62,7 +61,7 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
|||
text: document.getText(),
|
||||
position: document.offsetAt(position),
|
||||
};
|
||||
this.pendingCompletion = this.agent.getCompletions(request);
|
||||
this.pendingCompletion = agent().getCompletions(request);
|
||||
|
||||
const completion = await this.pendingCompletion.catch((_: Error) => {
|
||||
return null;
|
||||
|
|
@ -88,7 +87,7 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
|
|||
choice_index: choice.index,
|
||||
};
|
||||
return new InlineCompletionItem(choice.text, range, {
|
||||
title: "Tabby: Emit Event",
|
||||
title: "",
|
||||
command: "tabby.emitEvent",
|
||||
arguments: [event],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -3,15 +3,18 @@ import {
|
|||
InputBoxValidationSeverity,
|
||||
QuickPickItem,
|
||||
QuickPickItemKind,
|
||||
Uri,
|
||||
workspace,
|
||||
window,
|
||||
env,
|
||||
commands,
|
||||
} from "vscode";
|
||||
import { strict as assert } from "assert";
|
||||
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 = {
|
||||
command: string;
|
||||
|
|
@ -19,13 +22,13 @@ type Command = {
|
|||
thisArg?: any;
|
||||
};
|
||||
|
||||
const toogleEnabled: Command = {
|
||||
const toggleEnabled: Command = {
|
||||
command: "tabby.toggleEnabled",
|
||||
callback: () => {
|
||||
const configuration = workspace.getConfiguration("tabby");
|
||||
const enabled = configuration.get("enabled", true);
|
||||
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 current = configuration.get("suggestionDelay", 150);
|
||||
const items = {
|
||||
"Immediately": 0, // ms
|
||||
"Default": 150,
|
||||
"Slowly": 1000,
|
||||
Immediately: 0, // ms
|
||||
Default: 150,
|
||||
Slowly: 1000,
|
||||
};
|
||||
const createQuickPickItem = (value: number): QuickPickItem => {
|
||||
const tags: string[] = [];
|
||||
|
|
@ -84,7 +87,7 @@ const setSuggestionDelay: Command = {
|
|||
quickPick.hide();
|
||||
const delay = new Duration(quickPick.selectedItems[0].label).offset;
|
||||
console.debug("Set suggestion delay: ", delay);
|
||||
configuration.update("suggestionDelay", delay, target, false);
|
||||
configuration.update("suggestionDelay", delay, configTarget, false);
|
||||
});
|
||||
quickPick.show();
|
||||
},
|
||||
|
|
@ -114,7 +117,7 @@ const setServerUrl: Command = {
|
|||
.then((url) => {
|
||||
if (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 = {
|
||||
command: "tabby.emitEvent",
|
||||
callback: (event) => {
|
||||
console.debug("Emit Event: ", event);
|
||||
agent.postEvent(event);
|
||||
agent().postEvent(event);
|
||||
},
|
||||
};
|
||||
|
||||
export const tabbyCommands = [toogleEnabled, setServerUrl, setSuggestionDelay, openSettings, emitEvent].map((command) =>
|
||||
commands.registerCommand(command.command, command.callback, command.thisArg)
|
||||
);
|
||||
const openAuthPage: Command = {
|
||||
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)
|
||||
);
|
||||
|
|
@ -1,21 +1,23 @@
|
|||
// The module 'vscode' contains the VS Code extensibility API
|
||||
// Import the module and reference it with the alias vscode in your code below
|
||||
import { ExtensionContext, languages } from "vscode";
|
||||
import { tabbyCommands } from "./Commands";
|
||||
import { createAgentInstance } from "./agent";
|
||||
import { tabbyCommands } from "./commands";
|
||||
import { TabbyCompletionProvider } from "./TabbyCompletionProvider";
|
||||
import { tabbyStatusBarItem } from "./TabbyStatusBarItem";
|
||||
import { tabbyStatusBarItem } from "./statusBarItem";
|
||||
|
||||
// this method is called when your extension is activated
|
||||
// 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());
|
||||
await createAgentInstance(context);
|
||||
context.subscriptions.push(
|
||||
languages.registerInlineCompletionItemProvider(
|
||||
{ pattern: "**" },
|
||||
new TabbyCompletionProvider()
|
||||
),
|
||||
tabbyStatusBarItem,
|
||||
...tabbyCommands
|
||||
tabbyStatusBarItem(),
|
||||
...tabbyCommands(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -118,6 +118,23 @@
|
|||
resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
|
||||
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":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
|
|
@ -307,6 +324,25 @@
|
|||
jszip "^3.10.1"
|
||||
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":
|
||||
version "1.11.6"
|
||||
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"
|
||||
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":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||
|
|
@ -462,6 +503,14 @@ abort-controller@^3.0.0:
|
|||
dependencies:
|
||||
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:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
|
||||
|
|
@ -484,6 +533,13 @@ agent-base@6:
|
|||
dependencies:
|
||||
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:
|
||||
version "3.5.2"
|
||||
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"
|
||||
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:
|
||||
version "2.2.0"
|
||||
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:
|
||||
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:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
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:
|
||||
version "4.21.7"
|
||||
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"
|
||||
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:
|
||||
version "1.0.2"
|
||||
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"
|
||||
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:
|
||||
version "1.9.3"
|
||||
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"
|
||||
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:
|
||||
version "1.0.3"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
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:
|
||||
version "4.0.0"
|
||||
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-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:
|
||||
version "0.6.0"
|
||||
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"
|
||||
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:
|
||||
version "2.0.1"
|
||||
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"
|
||||
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:
|
||||
version "1.4.421"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
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"
|
||||
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:
|
||||
version "4.0.0"
|
||||
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"
|
||||
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:
|
||||
version "1.0.0"
|
||||
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"
|
||||
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:
|
||||
version "4.7.7"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
|
||||
|
|
@ -1564,6 +1743,46 @@ htmlparser2@^8.0.1:
|
|||
domutils "^3.0.1"
|
||||
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:
|
||||
version "4.0.1"
|
||||
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"
|
||||
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:
|
||||
version "5.0.1"
|
||||
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"
|
||||
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:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
|
|
@ -1625,11 +1860,16 @@ inflight@^1.0.4:
|
|||
once "^1.3.0"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
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:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||
|
|
@ -1707,6 +1947,11 @@ is-date-object@^1.0.5:
|
|||
dependencies:
|
||||
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:
|
||||
version "2.1.1"
|
||||
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:
|
||||
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:
|
||||
version "2.0.2"
|
||||
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"
|
||||
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:
|
||||
version "7.9.0"
|
||||
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"
|
||||
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:
|
||||
version "3.1.0"
|
||||
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"
|
||||
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:
|
||||
version "2.0.0"
|
||||
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"
|
||||
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:
|
||||
version "4.0.5"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
|
|
@ -2074,7 +2415,7 @@ minimatch@^5.0.1:
|
|||
dependencies:
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
|
@ -2111,12 +2452,28 @@ mocha@^10.0.0:
|
|||
yargs-parser "20.2.4"
|
||||
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:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@2.1.3:
|
||||
ms@2.1.3, ms@^2.1.1:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
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"
|
||||
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:
|
||||
version "2.6.2"
|
||||
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"
|
||||
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:
|
||||
version "1.4.0"
|
||||
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:
|
||||
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:
|
||||
version "0.24.0"
|
||||
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"
|
||||
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:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||
|
|
@ -2322,12 +2713,17 @@ parse5@^7.0.0:
|
|||
dependencies:
|
||||
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:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
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"
|
||||
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:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
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:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
|
|
@ -2399,6 +2809,18 @@ pkg-dir@^4.2.0:
|
|||
dependencies:
|
||||
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:
|
||||
version "7.1.1"
|
||||
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"
|
||||
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:
|
||||
version "3.0.0"
|
||||
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"
|
||||
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:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
|
|
@ -2496,6 +2935,19 @@ read@^1.0.7:
|
|||
dependencies:
|
||||
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:
|
||||
version "3.6.2"
|
||||
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"
|
||||
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:
|
||||
version "3.6.0"
|
||||
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"
|
||||
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:
|
||||
version "1.22.2"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
|
||||
|
|
@ -2611,16 +3058,16 @@ run-parallel@^1.1.9:
|
|||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
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-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
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:
|
||||
version "2.4.3"
|
||||
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"
|
||||
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:
|
||||
version "3.0.1"
|
||||
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"
|
||||
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:
|
||||
version "1.0.0"
|
||||
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:
|
||||
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:
|
||||
version "4.2.3"
|
||||
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"
|
||||
dependencies:
|
||||
axios "^1.4.0"
|
||||
browser-or-node "^2.1.1"
|
||||
deep-equal "^2.2.1"
|
||||
deepmerge "^4.3.1"
|
||||
form-data "^4.0.0"
|
||||
fs-extra "^11.1.1"
|
||||
lru-cache "^9.1.1"
|
||||
object-hash "^3.0.0"
|
||||
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"
|
||||
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
||||
|
||||
tar-fs@^2.0.0:
|
||||
tar-fs@^2.0.0, tar-fs@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
|
||||
integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
|
||||
|
|
@ -2890,6 +3362,14 @@ thread-stream@^2.0.0:
|
|||
dependencies:
|
||||
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:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
|
||||
|
|
@ -2904,6 +3384,11 @@ to-regex-range@^5.0.1:
|
|||
dependencies:
|
||||
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:
|
||||
version "9.4.3"
|
||||
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"
|
||||
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:
|
||||
version "3.21.0"
|
||||
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"
|
||||
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:
|
||||
version "1.8.9"
|
||||
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"
|
||||
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:
|
||||
version "2.15.0"
|
||||
resolved "https://registry.yarnpkg.com/vsce/-/vsce-2.15.0.tgz#4a992e78532092a34a755143c6b6c2cabcb7d729"
|
||||
|
|
@ -3051,6 +3554,11 @@ vsce@^2.15.0:
|
|||
yauzl "^2.3.1"
|
||||
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:
|
||||
version "2.4.0"
|
||||
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"
|
||||
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:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
|
|
@ -3265,6 +3778,11 @@ yazl@^2.2.2:
|
|||
dependencies:
|
||||
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:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
|
|
|
|||
Loading…
Reference in New Issue