@neuralinnovations/dataisland-sdk 0.0.1-dev1 → 0.0.1-dev10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +174 -1
- package/dist/dataisland-sdk.d.ts +1594 -0
- package/dist/dataisland-sdk.js +2890 -0
- package/dist/dataisland-sdk.js.map +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +41 -3
- package/src/appBuilder.ts +24 -5
- package/src/commands/startCommandHandler.ts +14 -0
- package/src/context.ts +31 -0
- package/src/credentials.ts +31 -9
- package/src/dataIslandApp.ts +59 -0
- package/src/disposable.ts +4 -5
- package/src/dto/accessGroupResponse.ts +35 -0
- package/src/dto/chatResponse.ts +103 -0
- package/src/dto/userInfoResponse.ts +47 -0
- package/src/dto/workspacesResponse.ts +49 -0
- package/src/events.ts +13 -17
- package/src/index.ts +44 -18
- package/src/internal/app.impl.ts +97 -32
- package/src/internal/appBuilder.impl.ts +39 -12
- package/src/internal/createApp.impl.ts +5 -5
- package/src/middleware.ts +1 -1
- package/src/services/commandService.ts +44 -0
- package/src/services/credentialService.ts +3 -3
- package/src/services/middlewareService.ts +8 -6
- package/src/services/organizationService.ts +28 -0
- package/src/services/requestBuilder.ts +127 -0
- package/src/services/responseUtils.ts +32 -0
- package/src/services/rpcService.ts +129 -52
- package/src/services/service.ts +10 -8
- package/src/services/userProfileService.ts +38 -0
- package/src/storages/chats/answer.impl.ts +163 -0
- package/src/storages/chats/answer.ts +42 -0
- package/src/storages/chats/chat.impl.ts +87 -0
- package/src/storages/chats/chat.ts +38 -0
- package/src/storages/chats/chats.impl.ts +142 -0
- package/src/storages/chats/chats.ts +47 -0
- package/src/storages/files/file.impl.ts +69 -0
- package/src/storages/files/file.ts +28 -0
- package/src/storages/files/files.impl.ts +213 -0
- package/src/storages/files/files.ts +38 -0
- package/src/storages/files/filesPage.ts +27 -0
- package/src/storages/groups/groups.impl.ts +326 -0
- package/src/storages/groups/groups.ts +101 -0
- package/src/storages/organizations/organization.impl.ts +95 -0
- package/src/storages/organizations/organization.ts +44 -0
- package/src/storages/organizations/organizations.impl.ts +197 -0
- package/src/storages/organizations/organizations.ts +56 -0
- package/src/storages/user/userProfile.impl.ts +56 -0
- package/src/storages/user/userProfile.ts +42 -0
- package/src/storages/workspaces/workspace.impl.ts +109 -0
- package/src/storages/workspaces/workspace.ts +49 -0
- package/src/storages/workspaces/workspaces.impl.ts +212 -0
- package/src/storages/workspaces/workspaces.ts +53 -0
- package/src/unitTest.ts +53 -0
- package/.browserslistrc +0 -5
- package/.editorconfig +0 -22
- package/.eslintrc.json +0 -44
- package/.github/workflows/publish-npm.yml +0 -28
- package/.prettierignore +0 -1
- package/.prettierrc +0 -11
- package/.yarnrc +0 -2
- package/babel.config.js +0 -6
- package/jest.config.ts +0 -199
- package/src/appSdk.ts +0 -40
- package/src/internal/context.ts +0 -13
- package/src/types.ts +0 -110
- package/test/disposable.test.ts +0 -39
- package/test/events.test.ts +0 -151
- package/test/index.test.ts +0 -83
- package/test/registry.test.ts +0 -44
- package/tsconfig.json +0 -31
@@ -0,0 +1,28 @@
|
|
1
|
+
import { Service } from "./service"
|
2
|
+
import { Organizations } from "../storages/organizations/organizations"
|
3
|
+
import { OrganizationDto, UserSettings } from "../dto/userInfoResponse"
|
4
|
+
import { OrganizationsImpl } from "../storages/organizations/organizations.impl"
|
5
|
+
|
6
|
+
export class OrganizationService extends Service {
|
7
|
+
private _impl?: OrganizationsImpl
|
8
|
+
|
9
|
+
private get impl(): OrganizationsImpl {
|
10
|
+
return this._impl ?? (this._impl = new OrganizationsImpl(this.context))
|
11
|
+
}
|
12
|
+
|
13
|
+
get organizations(): Organizations {
|
14
|
+
return this.impl
|
15
|
+
}
|
16
|
+
|
17
|
+
async initFrom(
|
18
|
+
adminInOrganization: string[],
|
19
|
+
organizations: OrganizationDto[],
|
20
|
+
settings?: UserSettings | null
|
21
|
+
): Promise<void> {
|
22
|
+
await this.impl.internalInitFrom(
|
23
|
+
adminInOrganization,
|
24
|
+
organizations,
|
25
|
+
settings
|
26
|
+
)
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,127 @@
|
|
1
|
+
export class RequestBuilder {
|
2
|
+
private readonly _headers: Headers
|
3
|
+
private readonly _searchParams: URLSearchParams
|
4
|
+
|
5
|
+
constructor(
|
6
|
+
private readonly _url: URL,
|
7
|
+
private readonly _request: (req: Request) => Promise<Response>
|
8
|
+
) {
|
9
|
+
this._headers = new Headers()
|
10
|
+
this._searchParams = new URLSearchParams()
|
11
|
+
}
|
12
|
+
|
13
|
+
public header(name: string, value: string): RequestBuilder {
|
14
|
+
this._headers.set(name, value)
|
15
|
+
return this
|
16
|
+
}
|
17
|
+
|
18
|
+
public headers(
|
19
|
+
headers?: [string, string][] | Record<string, string> | Headers
|
20
|
+
): RequestBuilder {
|
21
|
+
if (headers === undefined) {
|
22
|
+
return this
|
23
|
+
}
|
24
|
+
if (headers instanceof Headers) {
|
25
|
+
headers.forEach((value, name) => {
|
26
|
+
this._headers.set(name, value)
|
27
|
+
})
|
28
|
+
} else {
|
29
|
+
Object.entries(headers).forEach(([name, value]) => {
|
30
|
+
this._headers.set(name, value)
|
31
|
+
})
|
32
|
+
}
|
33
|
+
return this
|
34
|
+
}
|
35
|
+
|
36
|
+
public searchParam(name: string, value: string): RequestBuilder {
|
37
|
+
this._searchParams.set(name, value)
|
38
|
+
return this
|
39
|
+
}
|
40
|
+
|
41
|
+
public searchParams(searchParams?: Map<string, string>): RequestBuilder {
|
42
|
+
if (searchParams === undefined) {
|
43
|
+
return this
|
44
|
+
}
|
45
|
+
searchParams.forEach((value, name) => {
|
46
|
+
this._searchParams.set(name, value)
|
47
|
+
})
|
48
|
+
return this
|
49
|
+
}
|
50
|
+
|
51
|
+
public async sendPostFormData(body: FormData): Promise<Response> {
|
52
|
+
const url = this._url
|
53
|
+
|
54
|
+
// set search params
|
55
|
+
url.search = this._searchParams.toString()
|
56
|
+
|
57
|
+
// create request
|
58
|
+
const req = new Request(url, {
|
59
|
+
method: "POST",
|
60
|
+
headers: this._headers,
|
61
|
+
body
|
62
|
+
})
|
63
|
+
|
64
|
+
// discard content type
|
65
|
+
const reqAny = req as any
|
66
|
+
reqAny.discardContentType = true
|
67
|
+
|
68
|
+
return await this._request(
|
69
|
+
req
|
70
|
+
)
|
71
|
+
}
|
72
|
+
|
73
|
+
public async sendPostJson(body: object | null | undefined): Promise<Response> {
|
74
|
+
const url = this._url
|
75
|
+
url.search = this._searchParams.toString()
|
76
|
+
let json: string | null | undefined = null
|
77
|
+
if (body !== undefined && body !== null && typeof body === "object") {
|
78
|
+
json = JSON.stringify(body)
|
79
|
+
}
|
80
|
+
const request = new Request(url, {
|
81
|
+
method: "POST",
|
82
|
+
headers: this._headers,
|
83
|
+
body: json
|
84
|
+
})
|
85
|
+
return await this._request(
|
86
|
+
request
|
87
|
+
)
|
88
|
+
}
|
89
|
+
|
90
|
+
public async sendGet(): Promise<Response> {
|
91
|
+
const url = this._url
|
92
|
+
url.search = this._searchParams.toString()
|
93
|
+
return await this._request(
|
94
|
+
new Request(url, {
|
95
|
+
method: "GET",
|
96
|
+
headers: this._headers
|
97
|
+
})
|
98
|
+
)
|
99
|
+
}
|
100
|
+
|
101
|
+
public async sendDelete(): Promise<Response> {
|
102
|
+
const url = this._url
|
103
|
+
url.search = this._searchParams.toString()
|
104
|
+
return await this._request(
|
105
|
+
new Request(url, {
|
106
|
+
method: "DELETE",
|
107
|
+
headers: this._headers
|
108
|
+
})
|
109
|
+
)
|
110
|
+
}
|
111
|
+
|
112
|
+
public async sendPutJson(body: object | null | undefined): Promise<Response> {
|
113
|
+
const url = this._url
|
114
|
+
url.search = this._searchParams.toString()
|
115
|
+
let json: string | null | undefined = null
|
116
|
+
if (body !== undefined && body !== null && typeof body === "object") {
|
117
|
+
json = JSON.stringify(body)
|
118
|
+
}
|
119
|
+
return await this._request(
|
120
|
+
new Request(url, {
|
121
|
+
method: "PUT",
|
122
|
+
headers: this._headers,
|
123
|
+
body: json
|
124
|
+
})
|
125
|
+
)
|
126
|
+
}
|
127
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
export class ResponseUtils {
|
2
|
+
public static isOk(response?: Response | null): boolean {
|
3
|
+
return response !== undefined && response !== null && response.ok
|
4
|
+
}
|
5
|
+
|
6
|
+
public static isFail(response?: Response | null): boolean {
|
7
|
+
return !ResponseUtils.isOk(response)
|
8
|
+
}
|
9
|
+
|
10
|
+
public static async throwError(
|
11
|
+
message: string,
|
12
|
+
response: Response | undefined | null
|
13
|
+
): Promise<void> {
|
14
|
+
if (response === undefined) {
|
15
|
+
throw new Error(`${message}. Response is undefined`)
|
16
|
+
}
|
17
|
+
if (response === null) {
|
18
|
+
throw new Error(`${message}. Response is null`)
|
19
|
+
}
|
20
|
+
let errorBody: string = ""
|
21
|
+
if (response) {
|
22
|
+
try {
|
23
|
+
errorBody = (await response.text()) ?? ""
|
24
|
+
} catch (e) {
|
25
|
+
console.error(e)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
throw new Error(
|
29
|
+
`${message}. Response fail. Status: ${response?.status},${response?.statusText}, body: ${errorBody}`
|
30
|
+
)
|
31
|
+
}
|
32
|
+
}
|
@@ -1,72 +1,149 @@
|
|
1
|
-
import { Service, type ServiceContext } from
|
2
|
-
import { MiddlewareService } from
|
1
|
+
import { Service, type ServiceContext } from "./service"
|
2
|
+
import { MiddlewareService } from "./middlewareService"
|
3
|
+
import { RequestBuilder } from "./requestBuilder"
|
3
4
|
|
5
|
+
/**
|
6
|
+
* Options for the RpcService.
|
7
|
+
*/
|
8
|
+
export interface RequestOptions {
|
9
|
+
searchParams?: Map<string, string>
|
10
|
+
headers?: [string, string][] | Record<string, string> | Headers
|
11
|
+
}
|
12
|
+
|
13
|
+
/**
|
14
|
+
* RPC service.
|
15
|
+
*/
|
4
16
|
export class RpcService extends Service {
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
6
|
-
async request(req: Request): Promise<Response> {
|
7
|
-
throw new Error('Not implemented')
|
8
|
-
}
|
9
17
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
18
|
+
constructor(
|
19
|
+
serviceContext: ServiceContext,
|
20
|
+
/**
|
21
|
+
* Host of the RPC service.
|
22
|
+
* It is not used if you use the `urlBuilder` option.
|
23
|
+
*/
|
24
|
+
public readonly host: string,
|
25
|
+
/**
|
26
|
+
* Options for the RpcService.
|
27
|
+
*/
|
28
|
+
private readonly options?: {
|
29
|
+
// make it possible to override the url builder
|
30
|
+
urlBuilder?: (path: string) => URL
|
31
|
+
// make it possible to override the fetch method
|
32
|
+
fetchMethod?: (uri: Request) => Promise<Response>
|
33
|
+
}
|
34
|
+
) {
|
35
|
+
super(serviceContext)
|
36
|
+
|
37
|
+
serviceContext.onRegister = async () => {
|
38
|
+
serviceContext.resolve(MiddlewareService)?.useMiddleware((req, next) => {
|
39
|
+
if (!req.headers.has("accept")) {
|
40
|
+
req.headers.set("accept", "text/plain")
|
41
|
+
}
|
14
42
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
43
|
+
if ((req as any).discardContentType) {
|
44
|
+
delete (req as any).discardContentType
|
45
|
+
} else {
|
46
|
+
req.headers.set("content-type", "application/json")
|
47
|
+
}
|
48
|
+
|
49
|
+
return next(req)
|
19
50
|
})
|
20
|
-
|
51
|
+
}
|
21
52
|
}
|
22
53
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
54
|
+
/**
|
55
|
+
* Request method.
|
56
|
+
*/
|
57
|
+
async request(req: Request): Promise<Response> {
|
58
|
+
const middlewareService = this.resolve(MiddlewareService)
|
59
|
+
if (middlewareService !== undefined) {
|
60
|
+
return await middlewareService.process(req, async req => {
|
61
|
+
return (await this.options?.fetchMethod?.(req)) ?? (await fetch(req))
|
28
62
|
})
|
29
|
-
|
63
|
+
}
|
64
|
+
return (await this.options?.fetchMethod?.(req)) ?? (await fetch(req))
|
30
65
|
}
|
31
66
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
67
|
+
/**
|
68
|
+
* Build URL.
|
69
|
+
* @param path
|
70
|
+
*/
|
71
|
+
buildUrl(path: string): URL {
|
72
|
+
if (this.options !== undefined && this.options.urlBuilder !== undefined) {
|
73
|
+
return this.options.urlBuilder(path)
|
74
|
+
}
|
75
|
+
if (this.host.endsWith("/") && path.startsWith("/")) {
|
76
|
+
return new URL(`${this.host}${path.slice(1)}`)
|
77
|
+
}
|
78
|
+
if (!this.host.endsWith("/") && !path.startsWith("/")) {
|
79
|
+
return new URL(`${this.host}/${path}`)
|
80
|
+
}
|
81
|
+
return new URL(`${this.host}${path}`)
|
39
82
|
}
|
40
83
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
)
|
84
|
+
/**
|
85
|
+
* Create a request builder.
|
86
|
+
* @param path
|
87
|
+
*/
|
88
|
+
requestBuilder(path: string): RequestBuilder {
|
89
|
+
return new RequestBuilder(this.buildUrl(path), this.request.bind(this))
|
47
90
|
}
|
48
|
-
}
|
49
91
|
|
50
|
-
|
51
|
-
|
52
|
-
|
92
|
+
/**
|
93
|
+
* Send a GET request.
|
94
|
+
* @param path
|
95
|
+
* @param options
|
96
|
+
*/
|
97
|
+
async get(path: string, options?: RequestOptions): Promise<Response> {
|
98
|
+
return this.requestBuilder(path)
|
99
|
+
.searchParams(options?.searchParams)
|
100
|
+
.headers(options?.headers)
|
101
|
+
.sendGet()
|
53
102
|
}
|
54
103
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
104
|
+
/**
|
105
|
+
* Send a POST request.
|
106
|
+
* @param path
|
107
|
+
* @param body JSON object
|
108
|
+
* @param options
|
109
|
+
*/
|
110
|
+
async post(
|
111
|
+
path: string,
|
112
|
+
body: object | null | undefined,
|
113
|
+
options?: RequestOptions
|
114
|
+
): Promise<Response> {
|
115
|
+
return this.requestBuilder(path)
|
116
|
+
.searchParams(options?.searchParams)
|
117
|
+
.headers(options?.headers)
|
118
|
+
.sendPostJson(body)
|
64
119
|
}
|
65
120
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
121
|
+
/**
|
122
|
+
* Send a PUT request.
|
123
|
+
* @param path
|
124
|
+
* @param body JSON object
|
125
|
+
* @param options
|
126
|
+
*/
|
127
|
+
async put(
|
128
|
+
path: string,
|
129
|
+
body: object | null | undefined,
|
130
|
+
options?: RequestOptions
|
131
|
+
): Promise<Response> {
|
132
|
+
return this.requestBuilder(path)
|
133
|
+
.searchParams(options?.searchParams)
|
134
|
+
.headers(options?.headers)
|
135
|
+
.sendPutJson(body)
|
136
|
+
}
|
137
|
+
|
138
|
+
/**
|
139
|
+
* Send a DELETE request.
|
140
|
+
* @param path
|
141
|
+
* @param options
|
142
|
+
*/
|
143
|
+
async delete(path: string, options?: RequestOptions): Promise<Response> {
|
144
|
+
return this.requestBuilder(path)
|
145
|
+
.searchParams(options?.searchParams)
|
146
|
+
.headers(options?.headers)
|
147
|
+
.sendDelete()
|
71
148
|
}
|
72
149
|
}
|
package/src/services/service.ts
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
import { type Context } from
|
2
|
-
import { type Constructor } from
|
3
|
-
import { type DisposableContainer, type Lifetime } from
|
1
|
+
import { type Context } from "../context"
|
2
|
+
import { type Constructor } from "../internal/registry"
|
3
|
+
import { type DisposableContainer, type Lifetime } from "../disposable"
|
4
4
|
|
5
5
|
export class ServiceContext {
|
6
6
|
constructor(
|
7
7
|
public readonly context: Context,
|
8
8
|
private readonly disposableContainer: DisposableContainer
|
9
|
-
) {
|
9
|
+
) {
|
10
|
+
}
|
10
11
|
|
11
12
|
public get lifetime(): Lifetime {
|
12
13
|
return this.disposableContainer.lifetime
|
@@ -16,15 +17,15 @@ export class ServiceContext {
|
|
16
17
|
return this.context.resolve(type)
|
17
18
|
}
|
18
19
|
|
19
|
-
public async
|
20
|
+
public onRegister: () => Promise<void> = async (): Promise<void> => {
|
20
21
|
await Promise.resolve()
|
21
22
|
}
|
22
23
|
|
23
|
-
public async
|
24
|
+
public onStart: () => Promise<void> = async (): Promise<void> => {
|
24
25
|
await Promise.resolve()
|
25
26
|
}
|
26
27
|
|
27
|
-
public onUnregister(): void {
|
28
|
+
public onUnregister: () => void = (): void => {
|
28
29
|
// do nothing
|
29
30
|
}
|
30
31
|
}
|
@@ -42,5 +43,6 @@ export abstract class Service {
|
|
42
43
|
return this.serviceContext.context
|
43
44
|
}
|
44
45
|
|
45
|
-
public constructor(private readonly serviceContext: ServiceContext) {
|
46
|
+
public constructor(private readonly serviceContext: ServiceContext) {
|
47
|
+
}
|
46
48
|
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { Service } from "./service"
|
2
|
+
import { RpcService } from "./rpcService"
|
3
|
+
import { UserProfile } from "../storages/user/userProfile"
|
4
|
+
import { UserInfoResponse } from "../dto/userInfoResponse"
|
5
|
+
import { OrganizationService } from "./organizationService"
|
6
|
+
import { UserProfileImpl } from "../storages/user/userProfile.impl"
|
7
|
+
import { ResponseUtils } from "./responseUtils"
|
8
|
+
|
9
|
+
export class UserProfileService extends Service {
|
10
|
+
private readonly impl: UserProfileImpl = new UserProfileImpl()
|
11
|
+
|
12
|
+
get userProfile(): UserProfile {
|
13
|
+
return this.impl
|
14
|
+
}
|
15
|
+
|
16
|
+
async fetch() {
|
17
|
+
const rpc = this.resolve(RpcService) as RpcService
|
18
|
+
const response = await rpc.requestBuilder("api/v1/Users/self2").sendGet()
|
19
|
+
if (ResponseUtils.isFail(response)) {
|
20
|
+
await ResponseUtils.throwError("Failed to fetch user profile", response)
|
21
|
+
}
|
22
|
+
const content = (await response.json()) as UserInfoResponse
|
23
|
+
|
24
|
+
// init user profile from the server's response
|
25
|
+
this.impl.initFrom(content)
|
26
|
+
|
27
|
+
const organizationService = this.resolve(
|
28
|
+
OrganizationService
|
29
|
+
) as OrganizationService
|
30
|
+
|
31
|
+
// init organization service from user profile
|
32
|
+
await organizationService.initFrom(
|
33
|
+
content.adminInOrganization,
|
34
|
+
content.organizations,
|
35
|
+
content.user.settings
|
36
|
+
)
|
37
|
+
}
|
38
|
+
}
|
@@ -0,0 +1,163 @@
|
|
1
|
+
import { Context } from "../../context"
|
2
|
+
import {
|
3
|
+
AnswerDto,
|
4
|
+
AnswerStatus,
|
5
|
+
AnswerStepDto,
|
6
|
+
FetchAnswerResponse,
|
7
|
+
FetchTokensResponse,
|
8
|
+
SourceDto,
|
9
|
+
StepType
|
10
|
+
} from "../../dto/chatResponse"
|
11
|
+
import { ResponseUtils } from "../../services/responseUtils"
|
12
|
+
import { RpcService } from "../../services/rpcService"
|
13
|
+
import { Answer, AnswerId } from "./answer"
|
14
|
+
import { Chat } from "./chat"
|
15
|
+
|
16
|
+
export class AnswerImpl extends Answer {
|
17
|
+
private _content?: AnswerDto
|
18
|
+
|
19
|
+
private _steps?: AnswerStepDto[]
|
20
|
+
private _status?: AnswerStatus
|
21
|
+
private _id?: AnswerId
|
22
|
+
|
23
|
+
constructor(
|
24
|
+
private readonly chat: Chat,
|
25
|
+
private readonly context: Context) {
|
26
|
+
super()
|
27
|
+
}
|
28
|
+
|
29
|
+
async initFromData(answer: AnswerDto): Promise<AnswerImpl> {
|
30
|
+
this._content = answer
|
31
|
+
this._id = answer.id
|
32
|
+
|
33
|
+
// fetch answer
|
34
|
+
await this.fetch()
|
35
|
+
|
36
|
+
return this
|
37
|
+
}
|
38
|
+
|
39
|
+
async initFromId(id: AnswerId): Promise<AnswerImpl> {
|
40
|
+
this._id = id
|
41
|
+
|
42
|
+
// fetch answer
|
43
|
+
await this.fetch()
|
44
|
+
|
45
|
+
return this
|
46
|
+
}
|
47
|
+
|
48
|
+
get id(): string {
|
49
|
+
return <string>this._id
|
50
|
+
}
|
51
|
+
|
52
|
+
get status(): AnswerStatus {
|
53
|
+
return <AnswerStatus>this._status
|
54
|
+
}
|
55
|
+
|
56
|
+
private getStep(type: StepType): AnswerStepDto | undefined {
|
57
|
+
return this._steps?.find(step => step.type === type)
|
58
|
+
}
|
59
|
+
|
60
|
+
async sources(type: StepType): Promise<SourceDto[]> {
|
61
|
+
// fetch answer
|
62
|
+
await this.fetch()
|
63
|
+
// get step
|
64
|
+
const step = this.getStep(type)
|
65
|
+
|
66
|
+
// check step
|
67
|
+
if (!step) {
|
68
|
+
throw new Error(`Step with type ${type.toString()} is not found, answer: ${this.id}, organization: ${this.chat.organization.id}`)
|
69
|
+
}
|
70
|
+
|
71
|
+
// get sources
|
72
|
+
const response = await this.context
|
73
|
+
.resolve(RpcService)
|
74
|
+
?.requestBuilder("api/v1/Chats/answer/sources")
|
75
|
+
.searchParam("chat_uid", this.chat.id)
|
76
|
+
.searchParam("uid", this.id)
|
77
|
+
.searchParam("step_id", step.id)
|
78
|
+
.sendGet()
|
79
|
+
|
80
|
+
// check response status
|
81
|
+
if (ResponseUtils.isFail(response)) {
|
82
|
+
await ResponseUtils.throwError(`Failed to get sources for ${type.toString()}, answer: ${this.id}, organization: ${this.chat.organization.id}`, response)
|
83
|
+
}
|
84
|
+
|
85
|
+
// parse sources from the server's response
|
86
|
+
const sources = (await response!.json()).sources as SourceDto[]
|
87
|
+
|
88
|
+
return sources
|
89
|
+
}
|
90
|
+
|
91
|
+
async fetch(): Promise<void> {
|
92
|
+
// fetch answer from position 0
|
93
|
+
const position = 0
|
94
|
+
// fetch answer
|
95
|
+
const response = await this.context
|
96
|
+
.resolve(RpcService)
|
97
|
+
?.requestBuilder("api/v1/Chats/answer/fetch")
|
98
|
+
.searchParam("chatId", this.chat.id)
|
99
|
+
.searchParam("questionId", this.id)
|
100
|
+
.searchParam("position", position.toString())
|
101
|
+
.sendGet()
|
102
|
+
|
103
|
+
// check response status
|
104
|
+
if (ResponseUtils.isFail(response)) {
|
105
|
+
await ResponseUtils.throwError(`Failed to fetch answer ${this.id}`, response)
|
106
|
+
}
|
107
|
+
|
108
|
+
// parse answer from the server's response
|
109
|
+
const answer = (await response!.json()) as FetchAnswerResponse
|
110
|
+
|
111
|
+
// update answer
|
112
|
+
this._status = <AnswerStatus>answer.status
|
113
|
+
this._steps = <AnswerStepDto[]>answer.steps
|
114
|
+
}
|
115
|
+
|
116
|
+
async fetchTokens(type: StepType, token_start_at: number): Promise<FetchTokensResponse> {
|
117
|
+
// fetch answer
|
118
|
+
await this.fetch()
|
119
|
+
// get step
|
120
|
+
const step = this.getStep(type)
|
121
|
+
|
122
|
+
// check step
|
123
|
+
if (!step) {
|
124
|
+
throw new Error(`Step with type ${type.toString()} is not found`)
|
125
|
+
}
|
126
|
+
|
127
|
+
// get tokens
|
128
|
+
const response = await this.context
|
129
|
+
.resolve(RpcService)
|
130
|
+
?.requestBuilder("api/v1/Chats/answer/fetch/tokens")
|
131
|
+
.searchParam("chat_uid", this.chat.id)
|
132
|
+
.searchParam("uid", this.id)
|
133
|
+
.searchParam("step_id", step.id)
|
134
|
+
.searchParam("token_start_at", token_start_at.toString())
|
135
|
+
.sendGet()
|
136
|
+
|
137
|
+
// check response status
|
138
|
+
if (ResponseUtils.isFail(response)) {
|
139
|
+
await ResponseUtils.throwError(`Failed to get sources for ${type.toString()}`, response)
|
140
|
+
}
|
141
|
+
|
142
|
+
// parse tokens from the server's response
|
143
|
+
const tokens = (await response!.json()) as FetchTokensResponse
|
144
|
+
|
145
|
+
return tokens
|
146
|
+
}
|
147
|
+
|
148
|
+
async cancel(): Promise<void> {
|
149
|
+
// send request to the server
|
150
|
+
const response = await this.context
|
151
|
+
.resolve(RpcService)
|
152
|
+
?.requestBuilder("api/v1/Chats/answer/cancel")
|
153
|
+
.sendPutJson({
|
154
|
+
chat_id: this.chat.id,
|
155
|
+
uid: this.id
|
156
|
+
})
|
157
|
+
|
158
|
+
// check response status
|
159
|
+
if (ResponseUtils.isFail(response)) {
|
160
|
+
await ResponseUtils.throwError("Failed to cancel a question", response)
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import {
|
2
|
+
AnswerStatus,
|
3
|
+
FetchTokensResponse,
|
4
|
+
SourceDto,
|
5
|
+
StepType
|
6
|
+
} from "../../dto/chatResponse"
|
7
|
+
|
8
|
+
export type AnswerId = string
|
9
|
+
export type StepId = string
|
10
|
+
|
11
|
+
export abstract class Answer {
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Answer id.
|
15
|
+
*/
|
16
|
+
abstract get id(): AnswerId
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Answer status.
|
20
|
+
*/
|
21
|
+
abstract get status(): AnswerStatus
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Answer sources.
|
25
|
+
*/
|
26
|
+
abstract sources(type: StepType): Promise<SourceDto[]>
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Fetch answer.
|
30
|
+
*/
|
31
|
+
abstract fetch(): Promise<void>
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Fetch answer.
|
35
|
+
*/
|
36
|
+
abstract fetchTokens(type: StepType, tokenStartAt: number): Promise<FetchTokensResponse>
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Cancel answer
|
40
|
+
*/
|
41
|
+
abstract cancel(): Promise<void>
|
42
|
+
}
|