feat: Update agent completion api user field. (#246)

improve-workflow
Zhiming Ma 2023-06-17 01:50:47 +08:00 committed by GitHub
parent 6f7a6afcd1
commit 7f607f2f30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1047 additions and 946 deletions

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

File diff suppressed because one or more lines are too long

View File

@ -459,7 +459,7 @@ var V1Service = class {
});
}
/**
* @returns any Health
* @returns HealthState Success
* @throws ApiError
*/
health() {
@ -474,7 +474,7 @@ var V1Service = class {
var TabbyApi = class {
constructor(config, HttpRequest = AxiosHttpRequest) {
this.request = new HttpRequest({
BASE: config?.BASE ?? "https://tabbyml.app.tabbyml.com/tabby",
BASE: config?.BASE ?? "https://playground.app.tabbyml.com/tabby",
VERSION: config?.VERSION ?? "0.1.0",
WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
CREDENTIALS: config?.CREDENTIALS ?? "include",
@ -514,6 +514,7 @@ function cancelable(promise, cancel) {
// src/Auth.ts
var import_events = require("events");
var import_jwt_decode = __toESM(require("jwt-decode"));
// src/cloud/services/ApiService.ts
var ApiService = class {
@ -628,7 +629,10 @@ var _Auth = class extends import_events.EventEmitter {
return auth;
}
get token() {
return this.jwt;
return this.jwt?.token;
}
get user() {
return this.jwt?.payload.email;
}
async load() {
if (!this.dataStore)
@ -636,9 +640,12 @@ var _Auth = class extends import_events.EventEmitter {
try {
await this.dataStore.load();
const storedJwt = this.dataStore.data["auth"]?.[this.endpoint]?.jwt;
if (typeof storedJwt === "string" && this.jwt !== storedJwt) {
if (typeof storedJwt === "string" && this.jwt?.token !== storedJwt) {
this.logger.debug({ storedJwt }, "Load jwt from data store.");
this.jwt = storedJwt;
this.jwt = {
token: storedJwt,
payload: (0, import_jwt_decode.default)(storedJwt)
};
this.scheduleRefreshToken();
}
} catch (error) {
@ -650,9 +657,9 @@ var _Auth = class extends import_events.EventEmitter {
return;
try {
if (this.jwt) {
if (this.dataStore.data["auth"]?.[this.endpoint]?.jwt === this.jwt)
if (this.dataStore.data["auth"]?.[this.endpoint]?.jwt === this.jwt.token)
return;
this.dataStore.data["auth"] = { ...this.dataStore.data["auth"], [this.endpoint]: { jwt: this.jwt } };
this.dataStore.data["auth"] = { ...this.dataStore.data["auth"], [this.endpoint]: { jwt: this.jwt.token } };
} else {
if (typeof this.dataStore.data["auth"]?.[this.endpoint] === "undefined")
return;
@ -697,7 +704,10 @@ var _Auth = class extends import_events.EventEmitter {
try {
const response = await this.authApi.api.deviceTokenAccept({ code });
this.logger.debug({ response }, "Poll jwt response");
this.jwt = response.data.jwt;
this.jwt = {
token: response.data.jwt,
payload: (0, import_jwt_decode.default)(response.data.jwt)
};
await this.save();
this.scheduleRefreshToken();
super.emit("updated", this.jwt);
@ -720,10 +730,9 @@ var _Auth = class extends import_events.EventEmitter {
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);
const refreshDelay = Math.max(0, this.jwt.payload.exp * 1e3 - Date.now() - _Auth.refreshTokenInterval);
this.refreshTokenTimer = setTimeout(async () => {
this.logger.debug({ expireAt }, "Refresh token");
this.logger.debug({ expireAt: this.jwt.payload.exp }, "Refresh token");
}, refreshDelay);
}
};
@ -1115,7 +1124,8 @@ var _TabbyAgent = class extends import_events2.EventEmitter {
}
const promise = this.callApi(this.api.v1.completion, {
language: request2.language,
segments
segments,
user: this.auth?.user
});
return cancelable(
promise.then((response) => {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -29,6 +29,7 @@
"deepmerge": "^4.3.1",
"form-data": "^4.0.0",
"fs-extra": "^11.1.1",
"jwt-decode": "^3.1.2",
"lru-cache": "^9.1.1",
"object-hash": "^3.0.0",
"object-sizeof": "^2.6.1",

View File

@ -1,4 +1,5 @@
import { EventEmitter } from "events";
import decodeJwt from "jwt-decode";
import { CloudApi } from "./cloud";
import { ApiError } from "./generated";
import { dataStore, DataStore } from "./dataStore";
@ -19,7 +20,7 @@ export class Auth extends EventEmitter {
private pollingTokenTimer: ReturnType<typeof setInterval> | null = null;
private refreshTokenTimer: ReturnType<typeof setTimeout> | null = null;
private authApi: CloudApi | null = null;
private jwt: string | null = null;
private jwt: { token: string; payload: { email: string; exp: number } } | null = null;
static async create(options: { endpoint: string; dataStore?: DataStore }): Promise<Auth> {
const auth = new Auth(options);
@ -39,7 +40,11 @@ export class Auth extends EventEmitter {
}
get token(): string | null {
return this.jwt;
return this.jwt?.token;
}
get user(): string | null {
return this.jwt?.payload.email;
}
private async load(): Promise<void> {
@ -47,9 +52,12 @@ export class Auth extends EventEmitter {
try {
await this.dataStore.load();
const storedJwt = this.dataStore.data["auth"]?.[this.endpoint]?.jwt;
if (typeof storedJwt === "string" && this.jwt !== storedJwt) {
if (typeof storedJwt === "string" && this.jwt?.token !== storedJwt) {
this.logger.debug({ storedJwt }, "Load jwt from data store.");
this.jwt = storedJwt;
this.jwt = {
token: storedJwt,
payload: decodeJwt(storedJwt),
};
this.scheduleRefreshToken();
}
} catch (error: any) {
@ -61,8 +69,8 @@ export class Auth extends EventEmitter {
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 } };
if (this.dataStore.data["auth"]?.[this.endpoint]?.jwt === this.jwt.token) return;
this.dataStore.data["auth"] = { ...this.dataStore.data["auth"], [this.endpoint]: { jwt: this.jwt.token } };
} else {
if (typeof this.dataStore.data["auth"]?.[this.endpoint] === "undefined") return;
delete this.dataStore.data["auth"][this.endpoint];
@ -109,7 +117,10 @@ export class Auth extends EventEmitter {
try {
const response = await this.authApi.api.deviceTokenAccept({ code });
this.logger.debug({ response }, "Poll jwt response");
this.jwt = response.data.jwt;
this.jwt = {
token: response.data.jwt,
payload: decodeJwt(response.data.jwt),
};
await this.save();
this.scheduleRefreshToken();
super.emit("updated", this.jwt);
@ -134,11 +145,10 @@ export class Auth extends EventEmitter {
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);
const refreshDelay = Math.max(0, this.jwt.payload.exp * 1000 - Date.now() - Auth.refreshTokenInterval);
this.refreshTokenTimer = setTimeout(async () => {
this.logger.debug({ expireAt }, "Refresh token");
this.logger.debug({ expireAt: this.jwt.payload.exp }, "Refresh token");
// FIXME: not implemented
}, refreshDelay);
}

View File

@ -118,7 +118,7 @@ export class TabbyAgent extends EventEmitter implements Agent {
);
}
private async healthCheck(): Promise<void> {
private async healthCheck(): Promise<any> {
return this.callApi(this.api.v1.health, {}).catch(() => {});
}
@ -211,6 +211,7 @@ export class TabbyAgent extends EventEmitter implements Agent {
const promise = this.callApi(this.api.v1.completion, {
language: request.language,
segments,
user: this.auth?.user,
});
return cancelable(
promise

View File

@ -1043,6 +1043,11 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"
jwt-decode@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
lilconfig@^2.0.5:
version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"

View File

@ -2163,6 +2163,11 @@ jszip@^3.10.1:
readable-stream "~2.3.6"
setimmediate "^1.0.5"
jwt-decode@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
keygrip@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226"
@ -3296,6 +3301,7 @@ supports-preserve-symlinks-flag@^1.0.0:
deepmerge "^4.3.1"
form-data "^4.0.0"
fs-extra "^11.1.1"
jwt-decode "^3.1.2"
lru-cache "^9.1.1"
object-hash "^3.0.0"
object-sizeof "^2.6.1"