feat: add tabby-agent loggers. (#210)

support-stop-sequences
Zhiming Ma 2023-06-06 22:25:31 +08:00 committed by GitHub
parent bc90ff4b7e
commit e8a1688fce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 33787 additions and 14525 deletions

File diff suppressed because one or more lines are too long

1
clients/tabby-agent/dist/cli.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -111,6 +111,7 @@ type AgentConfig = {
type AgentInitOptions = {
config?: AgentConfig;
client?: string;
};
type CompletionRequest = {
filepath: string;
@ -143,6 +144,7 @@ interface AgentEventEmitter {
type Agent = AgentFunction & AgentEventEmitter;
declare class TabbyAgent extends EventEmitter implements Agent {
private readonly logger;
private config;
private status;
private api;
@ -151,7 +153,7 @@ declare class TabbyAgent extends EventEmitter implements Agent {
private onConfigUpdated;
private changeStatus;
private ping;
private wrapApiPromise;
private callApi;
private createPrompt;
initialize(params: AgentInitOptions): boolean;
updateConfig(config: AgentConfig): boolean;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -247,13 +247,13 @@ var getQueryString = (params) => {
};
var getUrl = (config, options) => {
const encoder = config.ENCODE_PATH || encodeURI;
const path = options.url.replace("{api-version}", config.VERSION).replace(/{(.*?)}/g, (substring, group) => {
const path2 = 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}${path}`;
const url = `${config.BASE}${path2}`;
if (options.query) {
return `${url}${getQueryString(options.query)}`;
}
@ -524,7 +524,7 @@ var defaultAgentConfig = {
endpoint: "http://localhost:8080"
},
logs: {
level: "silent"
level: "error"
},
anonymousUsageTracking: {
disable: false
@ -535,8 +535,33 @@ var defaultAgentConfig = {
var import_lru_cache = require("lru-cache");
var import_object_hash = __toESM(require("object-hash"));
var import_object_sizeof = __toESM(require("object-sizeof"));
// 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 : (
/**
* 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"),
size: "10M",
interval: "1d"
})
);
var rootLogger = !!stream ? (0, import_pino.default)(stream) : (0, import_pino.default)();
var allLoggers = [rootLogger];
rootLogger.onChild = (child) => {
allLoggers.push(child);
};
// src/CompletionCache.ts
var CompletionCache = class {
constructor() {
this.logger = rootLogger.child({ component: "CompletionCache" });
this.options = {
maxSize: 1 * 1024 * 1024,
// 1MB
@ -566,8 +591,10 @@ var CompletionCache = class {
}
set(key, value) {
for (const entry of this.createCacheEntries(key, value)) {
this.logger.debug({ entry }, "Setting cache entry");
this.cache.set(this.hash(entry.key), entry.value);
}
this.logger.debug({ size: this.cache.calculatedSize }, "Cache size");
}
get(key) {
return this.cache.get(this.hash(key));
@ -647,12 +674,14 @@ var CompletionCache = class {
var TabbyAgent = class extends import_events.EventEmitter {
constructor() {
super();
this.logger = rootLogger.child({ component: "TabbyAgent" });
this.config = defaultAgentConfig;
this.status = "connecting";
this.completionCache = new CompletionCache();
this.onConfigUpdated();
}
onConfigUpdated() {
allLoggers.forEach((logger) => logger.level = this.config.logs.level);
this.api = new TabbyApi({ BASE: this.config.server.endpoint });
this.ping();
}
@ -660,6 +689,7 @@ var TabbyAgent = class extends import_events.EventEmitter {
if (this.status != status) {
this.status = status;
const event = { event: "statusChanged", status };
this.logger.debug({ event }, "Status changed");
super.emit("statusChanged", event);
}
}
@ -679,14 +709,18 @@ var TabbyAgent = class extends import_events.EventEmitter {
return this.ping(tries + 1);
}
}
wrapApiPromise(promise) {
callApi(api, request2) {
this.logger.debug({ api: api.name, request: request2 }, "API request");
const promise = api.call(this.api.default, request2);
return cancelable(
promise.then((resolved) => {
promise.then((response) => {
this.logger.debug({ api: api.name, response }, "API response");
this.changeStatus("ready");
return resolved;
}).catch((err) => {
return response;
}).catch((error) => {
this.logger.error({ api: api.name, error }, "API error");
this.changeStatus("disconnected");
throw err;
throw error;
}),
() => {
promise.cancel();
@ -705,13 +739,19 @@ var TabbyAgent = class extends import_events.EventEmitter {
if (params.config) {
this.updateConfig(params.config);
}
if (params.client) {
allLoggers.forEach((logger) => logger.setBindings && logger.setBindings({ client: params.client }));
}
this.logger.debug({ params }, "Initialized");
return true;
}
updateConfig(config) {
if (!(0, import_deep_equal.default)(this.config, config)) {
this.config = (0, import_deepmerge.default)(this.config, config);
const mergedConfig = (0, import_deepmerge.default)(this.config, config);
if (!(0, import_deep_equal.default)(this.config, mergedConfig)) {
this.config = mergedConfig;
this.onConfigUpdated();
const event = { event: "configUpdated", config: this.config };
this.logger.debug({ event }, "Config updated");
super.emit("configUpdated", event);
}
return true;
@ -724,12 +764,14 @@ var TabbyAgent = class extends import_events.EventEmitter {
}
getCompletions(request2) {
if (this.completionCache.has(request2)) {
this.logger.debug({ request: request2 }, "Completion cache hit");
return new CancelablePromise((resolve2) => {
resolve2(this.completionCache.get(request2));
});
}
const prompt = this.createPrompt(request2);
if (isBlank(prompt)) {
this.logger.debug("Prompt is blank, returning empty completion response");
return new CancelablePromise((resolve2) => {
resolve2({
id: "agent-" + (0, import_uuid.v4)(),
@ -738,12 +780,10 @@ var TabbyAgent = class extends import_events.EventEmitter {
});
});
}
const promise = this.wrapApiPromise(
this.api.default.completionsV1CompletionsPost({
prompt,
language: request2.language
})
);
const promise = this.callApi(this.api.default.completionsV1CompletionsPost, {
prompt,
language: request2.language
});
return cancelable(
promise.then((response) => {
this.completionCache.set(request2, response);
@ -755,7 +795,7 @@ var TabbyAgent = class extends import_events.EventEmitter {
);
}
postEvent(request2) {
return this.wrapApiPromise(this.api.default.eventsV1EventsPost(request2));
return this.callApi(this.api.default.eventsV1EventsPost, request2);
}
};

File diff suppressed because one or more lines are too long

32516
clients/tabby-agent/dist/index.mjs vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -7,12 +7,8 @@
"dist"
],
"main": "./dist/index.js",
"browser": "./dist/index.global.js",
"browser": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"scripts": {
"openapi-codegen": "rimraf ./src/generated && openapi --input ../../docs/openapi.json --output ./src/generated --client axios --name TabbyApi --indent 2",
"dev": "tsup --watch",
@ -28,12 +24,15 @@
},
"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",
"lru-cache": "^9.1.1",
"object-hash": "^3.0.0",
"object-sizeof": "^2.6.1",
"pino": "^8.14.1",
"rotating-file-stream": "^3.1.0",
"uuid": "^9.0.0"
}
}

View File

@ -9,6 +9,7 @@ import { AgentConfig } from "./AgentConfig";
export type AgentInitOptions = {
config?: AgentConfig;
client?: string;
};
export type CompletionRequest = {

View File

@ -15,7 +15,7 @@ export const defaultAgentConfig: AgentConfig = {
endpoint: "http://localhost:8080",
},
logs: {
level: "silent",
level: "error",
},
anonymousUsageTracking: {
disable: false,

View File

@ -2,12 +2,14 @@ import { LRUCache } from "lru-cache";
import hashObject from "object-hash";
import sizeOfObject from "object-sizeof";
import { CompletionRequest, CompletionResponse } from "./Agent";
import { rootLogger } from "./logger";
import { splitLines, splitWords } from "./utils";
type CompletionCacheKey = CompletionRequest;
type CompletionCacheValue = CompletionResponse;
export class CompletionCache {
private readonly logger = rootLogger.child({ component: "CompletionCache" });
private cache: LRUCache<string, CompletionCacheValue>;
private options = {
maxSize: 1 * 1024 * 1024, // 1MB
@ -41,8 +43,10 @@ export class CompletionCache {
set(key: CompletionCacheKey, value: CompletionCacheValue): void {
for (const entry of this.createCacheEntries(key, value)) {
this.logger.debug({ entry }, "Setting cache entry");
this.cache.set(this.hash(entry.key), entry.value);
}
this.logger.debug({ size: this.cache.calculatedSize }, "Cache size");
}
get(key: CompletionCacheKey): CompletionCacheValue | undefined {
@ -79,7 +83,7 @@ export class CompletionCache {
const cacheKey = {
...key,
text: key.text.slice(0, key.position) + prefix + key.text.slice(key.position),
position: key.position + prefix.length
position: key.position + prefix.length,
};
const cacheValue = {
...value,

View File

@ -1,5 +1,6 @@
import { CancelablePromise } from "./generated";
import { AgentFunction, AgentEvent, Agent, agentEventNames } from "./Agent";
import { rootLogger } from "./logger";
import { splitLines } from "./utils";
type AgentFunctionRequest<T extends keyof AgentFunction> = [
@ -8,7 +9,7 @@ type AgentFunctionRequest<T extends keyof AgentFunction> = [
func: T;
args: Parameters<AgentFunction[T]>;
}
]
];
type CancellationRequest = [
id: number,
@ -16,24 +17,24 @@ type CancellationRequest = [
func: "cancelRequest";
args: [id: number];
}
]
];
type Request = AgentFunctionRequest<any> | CancellationRequest;
type AgentFunctionResponse<T extends keyof AgentFunction> = [
id: number, // Matched request id
data: ReturnType<AgentFunction[T]>,
]
data: ReturnType<AgentFunction[T]>
];
type AgentEventNotification = {
id: 0,
data: AgentEvent,
}
id: 0;
data: AgentEvent;
};
type CancellationResponse = [
id: number, // Matched request id
data: boolean,
]
data: boolean
];
type Response = AgentFunctionResponse<any> | AgentEventNotification | CancellationResponse;
@ -43,15 +44,14 @@ type Response = AgentFunctionResponse<any> | AgentEventNotification | Cancellati
export class StdIO {
private readonly inStream: NodeJS.ReadStream = process.stdin;
private readonly outStream: NodeJS.WriteStream = process.stdout;
private readonly errLogger: NodeJS.WriteStream = process.stderr;
private readonly logger = rootLogger.child({ component: "StdIO" });
private buffer: string = "";
private ongoingRequests: { [id: number]: CancelablePromise<any> } = {};
private agent: Agent | null = null;
constructor() {
}
constructor() {}
private handleInput(data: Buffer): void {
const input = data.toString();
@ -69,12 +69,14 @@ export class StdIO {
let request: Request | null = null;
try {
request = JSON.parse(line) as Request;
} catch (e) {
this.errLogger.write(JSON.stringify(e, Object.getOwnPropertyNames(e)) + "\n");
} catch (error) {
this.logger.error({ error }, `Failed to parse request: ${line}`);
continue;
}
this.logger.debug({ request }, "Received request");
this.handleRequest(request).then((response) => {
this.sendResponse(response);
this.logger.debug({ response }, "Sent response");
});
}
}
@ -104,8 +106,8 @@ export class StdIO {
response[1] = result;
}
}
} catch (e) {
this.errLogger.write(JSON.stringify(e, Object.getOwnPropertyNames(e)) + "\n");
} catch (error) {
this.logger.error({ error }, `Failed to handle request: ${JSON.stringify(request)}`);
} finally {
return response;
}
@ -129,7 +131,7 @@ export class StdIO {
for (const eventName of agentEventNames) {
this.agent.on(eventName, (event) => {
this.sendResponse([0, event]);
})
});
}
}

View File

@ -8,8 +8,10 @@ import { sleep, cancelable, splitLines, isBlank } from "./utils";
import { Agent, AgentEvent, AgentInitOptions, CompletionRequest, CompletionResponse } from "./Agent";
import { AgentConfig, defaultAgentConfig } from "./AgentConfig";
import { CompletionCache } from "./CompletionCache";
import { rootLogger, allLoggers } from "./logger";
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 api: TabbyApi;
@ -21,6 +23,7 @@ export class TabbyAgent extends EventEmitter implements Agent {
}
private onConfigUpdated() {
allLoggers.forEach((logger) => (logger.level = this.config.logs.level));
this.api = new TabbyApi({ BASE: this.config.server.endpoint });
this.ping();
}
@ -29,6 +32,7 @@ export class TabbyAgent extends EventEmitter implements Agent {
if (this.status != status) {
this.status = status;
const event: AgentEvent = { event: "statusChanged", status };
this.logger.debug({ event }, "Status changed");
super.emit("statusChanged", event);
}
}
@ -50,16 +54,23 @@ export class TabbyAgent extends EventEmitter implements Agent {
}
}
private wrapApiPromise<T>(promise: CancelablePromise<T>): CancelablePromise<T> {
private callApi<Request, Response>(
api: (request: Request) => CancelablePromise<Response>,
request: Request
): CancelablePromise<Response> {
this.logger.debug({ api: api.name, request }, "API request");
const promise = api.call(this.api.default, request);
return cancelable(
promise
.then((resolved: T) => {
.then((response: Response) => {
this.logger.debug({ api: api.name, response }, "API response");
this.changeStatus("ready");
return resolved;
return response;
})
.catch((err: ApiError) => {
.catch((error: ApiError) => {
this.logger.error({ api: api.name, error }, "API error");
this.changeStatus("disconnected");
throw err;
throw error;
}),
() => {
promise.cancel();
@ -80,14 +91,22 @@ export class TabbyAgent extends EventEmitter implements Agent {
if (params.config) {
this.updateConfig(params.config);
}
if (params.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 }));
}
this.logger.debug({ params }, "Initialized");
return true;
}
public updateConfig(config: AgentConfig): boolean {
if (!deepEqual(this.config, config)) {
this.config = deepMerge(this.config, config);
const mergedConfig = deepMerge(this.config, config);
if (!deepEqual(this.config, mergedConfig)) {
this.config = mergedConfig;
this.onConfigUpdated();
const event: AgentEvent = { event: "configUpdated", config: this.config };
this.logger.debug({ event }, "Config updated");
super.emit("configUpdated", event);
}
return true;
@ -103,13 +122,14 @@ export class TabbyAgent extends EventEmitter implements Agent {
public getCompletions(request: CompletionRequest): CancelablePromise<CompletionResponse> {
if (this.completionCache.has(request)) {
this.logger.debug({ request }, "Completion cache hit");
return new CancelablePromise((resolve) => {
resolve(this.completionCache.get(request));
});
}
const prompt = this.createPrompt(request);
if (isBlank(prompt)) {
// Create a empty completion response
this.logger.debug("Prompt is blank, returning empty completion response");
return new CancelablePromise((resolve) => {
resolve({
id: "agent-" + uuid(),
@ -118,12 +138,10 @@ export class TabbyAgent extends EventEmitter implements Agent {
});
});
}
const promise = this.wrapApiPromise(
this.api.default.completionsV1CompletionsPost({
prompt,
language: request.language,
})
);
const promise = this.callApi(this.api.default.completionsV1CompletionsPost, {
prompt,
language: request.language,
});
return cancelable(
promise.then((response: CompletionResponse) => {
this.completionCache.set(request, response);
@ -136,6 +154,6 @@ export class TabbyAgent extends EventEmitter implements Agent {
}
public postEvent(request: ChoiceEvent | CompletionEvent): CancelablePromise<boolean> {
return this.wrapApiPromise(this.api.default.eventsV1EventsPost(request));
return this.callApi(this.api.default.eventsV1EventsPost, request);
}
}

View File

@ -0,0 +1,26 @@
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";
/**
* Stream not available in browser, will use default console output.
*/
const stream = isBrowser
? null
: /**
* Default rotating file locate at `~/.tabby/agent-logs/`.
*/
rotatingFileStream.createStream("tabby-agent.log", {
path: path.join(os.homedir(), ".tabby", "agent-logs"),
size: "10M",
interval: "1d",
});
export const rootLogger = !!stream ? pino(stream) : pino();
export const allLoggers = [rootLogger];
rootLogger.onChild = (child) => {
allLoggers.push(child);
};

View File

@ -4,7 +4,7 @@ import { dependencies } from "./package.json";
export default async () => [
defineConfig({
name: "lib-node",
name: "node-cjs",
entry: ["src/index.ts"],
platform: "node",
format: ["cjs"],
@ -12,17 +12,37 @@ export default async () => [
clean: true,
}),
defineConfig({
name: "lib-browser",
name: "browser-iife",
entry: ["src/index.ts"],
platform: "browser",
format: ["iife"],
globalName: "Tabby",
minify: true,
sourcemap: true,
esbuildPlugins: [polyfillNode()],
esbuildPlugins: [
polyfillNode({
polyfills: { fs: true },
}),
],
clean: true,
}),
defineConfig({
name: "lib-typedefs",
name: "browser-esm",
entry: ["src/index.ts"],
platform: "browser",
format: ["esm"],
// FIXME: bundle all dependencies to reduce module resolving problems, not a good solution
noExternal: Object.keys(dependencies),
sourcemap: true,
esbuildPlugins: [
polyfillNode({
polyfills: { fs: true },
}),
],
clean: true,
}),
defineConfig({
name: "type-defs",
entry: ["src/index.ts"],
dts: {
only: true,
@ -35,6 +55,7 @@ export default async () => [
platform: "node",
noExternal: Object.keys(dependencies),
minify: true,
sourcemap: true,
clean: true,
}),
];

View File

@ -217,6 +217,13 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.32.tgz#5b5becc5da76fc055b2a601c8a3adbf13891227e"
integrity sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
dependencies:
event-target-shim "^5.0.0"
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
@ -275,6 +282,11 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
atomic-sleep@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==
available-typed-arrays@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
@ -326,6 +338,11 @@ 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"
@ -544,6 +561,16 @@ esbuild@^0.17.6:
"@esbuild/win32-ia32" "0.17.19"
"@esbuild/win32-x64" "0.17.19"
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@ -570,6 +597,11 @@ fast-glob@^3.2.9:
merge2 "^1.3.0"
micromatch "^4.0.4"
fast-redact@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.2.0.tgz#b1e2d39bc731376d28bde844454fa23e26919987"
integrity sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==
fastq@^1.6.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
@ -1156,6 +1188,11 @@ object.assign@^4.1.4:
has-symbols "^1.0.3"
object-keys "^1.1.1"
on-exit-leak-free@^2.1.0:
version "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==
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@ -1209,6 +1246,36 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pino-abstract-transport@v1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
dependencies:
readable-stream "^4.0.0"
split2 "^4.0.0"
pino-std-serializers@^6.0.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.1.tgz#369f4ae2a19eb6d769ddf2c88a2164b76879a284"
integrity sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ==
pino@^8.14.1:
version "8.14.1"
resolved "https://registry.yarnpkg.com/pino/-/pino-8.14.1.tgz#bb38dcda8b500dd90c1193b6c9171eb777a47ac8"
integrity sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.1.1"
on-exit-leak-free "^2.1.0"
pino-abstract-transport v1.0.0
pino-std-serializers "^6.0.0"
process-warning "^2.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.2.0"
safe-stable-stringify "^2.3.1"
sonic-boom "^3.1.0"
thread-stream "^2.0.0"
pirates@^4.0.1:
version "4.0.5"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
@ -1222,6 +1289,16 @@ postcss-load-config@^3.0.1:
lilconfig "^2.0.5"
yaml "^1.10.2"
process-warning@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626"
integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
@ -1237,6 +1314,21 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
quick-format-unescaped@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
readable-stream@^4.0.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.4.0.tgz#55ce132d60a988c460d75c631e9ccf6a7229b468"
integrity sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==
dependencies:
abort-controller "^3.0.0"
buffer "^6.0.3"
events "^3.3.0"
process "^0.11.10"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@ -1244,6 +1336,11 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
real-require@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
regexp.prototype.flags@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
@ -1277,6 +1374,11 @@ rollup@^3.2.5:
optionalDependencies:
fsevents "~2.3.2"
rotating-file-stream@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/rotating-file-stream/-/rotating-file-stream-3.1.0.tgz#6cf50e1671de82a396de6d31d39a6f2445f45fba"
integrity sha512-TkMF6cP1/QDcon9D71mjxHoflNuznNOrY5JJQfuxkKklZRmoow/lWBLNxXVjb6KcjAU8BDCV145buLgOx9Px1Q==
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
@ -1284,6 +1386,11 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
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"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@ -1320,6 +1427,13 @@ slash@^3.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
sonic-boom@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.3.0.tgz#cffab6dafee3b2bcb88d08d589394198bee1838c"
integrity sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==
dependencies:
atomic-sleep "^1.0.0"
source-map@0.8.0-beta.0:
version "0.8.0-beta.0"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11"
@ -1332,6 +1446,11 @@ source-map@^0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
split2@^4.0.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
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"
@ -1405,6 +1524,13 @@ thenify-all@^1.0.0:
dependencies:
any-promise "^1.0.0"
thread-stream@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33"
integrity sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==
dependencies:
real-require "^0.2.0"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"

View File

@ -62,6 +62,16 @@
"default": 150,
"minimum": 0,
"description": "Specifies the delay in milliseconds after which the request is sent to the tabby."
},
"tabby.agentLogs": {
"type": "string",
"enum": [
"debug",
"error",
"silent"
],
"default": "error",
"markdownDescription": "Specifies the log level of tabby-agent for debugging purpose. \n * If VSCode is running as desktop application, you can find log files in `$HOME/.tabby/agent-logs/`. It's recommend using `tail -f ~/.tabby/agent-logs/tabby-agent.log | npx pino-pretty` to monitor logs. \n * If VSCode is running in browser, you can find logs in debug console. "
}
}
}

View File

@ -1,4 +1,4 @@
import { workspace } from "vscode";
import { workspace, env, version, UIKind } from "vscode";
import { TabbyAgent, AgentConfig } from "tabby-agent";
export class Agent extends TabbyAgent {
@ -12,8 +12,10 @@ export class Agent extends TabbyAgent {
private constructor() {
super();
const uiKind = Object.keys(UIKind)[Object.values(UIKind).indexOf(env.uiKind)];
super.initialize({
config: this.getWorkspaceConfiguration()
config: this.getWorkspaceConfiguration(),
client: `VSCode ${uiKind} ${version}`,
});
workspace.onDidChangeConfiguration((event) => {
@ -27,10 +29,14 @@ export class Agent extends TabbyAgent {
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
}
}
endpoint: serverUrl,
},
logs: {
level: agentLogs,
},
};
}
}

View File

@ -62,7 +62,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
text: document.getText(),
position: document.offsetAt(position),
};
console.debug("Request: ", request)
this.pendingCompletion = this.agent.getCompletions(request);
const completion = await this.pendingCompletion.catch((_: Error) => {
@ -71,7 +70,6 @@ export class TabbyCompletionProvider implements InlineCompletionItemProvider {
this.pendingCompletion = null;
const completions = this.toInlineCompletions(completion, replaceRange);
console.debug("Result completions: ", completions);
return Promise.resolve(completions);
}

File diff suppressed because it is too large Load Diff