@vertesia/client 0.42.2

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.
Files changed (193) hide show
  1. package/LICENSE +13 -0
  2. package/lib/cjs/AccountApi.js +66 -0
  3. package/lib/cjs/AccountApi.js.map +1 -0
  4. package/lib/cjs/AccountsApi.js +13 -0
  5. package/lib/cjs/AccountsApi.js.map +1 -0
  6. package/lib/cjs/AnalyticsApi.js +13 -0
  7. package/lib/cjs/AnalyticsApi.js.map +1 -0
  8. package/lib/cjs/ApiKeysApi.js +63 -0
  9. package/lib/cjs/ApiKeysApi.js.map +1 -0
  10. package/lib/cjs/CommandsApi.js +19 -0
  11. package/lib/cjs/CommandsApi.js.map +1 -0
  12. package/lib/cjs/EnvironmentsApi.js +58 -0
  13. package/lib/cjs/EnvironmentsApi.js.map +1 -0
  14. package/lib/cjs/IamApi.js +51 -0
  15. package/lib/cjs/IamApi.js.map +1 -0
  16. package/lib/cjs/InteractionBase.js +44 -0
  17. package/lib/cjs/InteractionBase.js.map +1 -0
  18. package/lib/cjs/InteractionsApi.js +184 -0
  19. package/lib/cjs/InteractionsApi.js.map +1 -0
  20. package/lib/cjs/ProjectsApi.js +48 -0
  21. package/lib/cjs/ProjectsApi.js.map +1 -0
  22. package/lib/cjs/PromptsApi.js +133 -0
  23. package/lib/cjs/PromptsApi.js.map +1 -0
  24. package/lib/cjs/RefsApi.js +14 -0
  25. package/lib/cjs/RefsApi.js.map +1 -0
  26. package/lib/cjs/RunsApi.js +79 -0
  27. package/lib/cjs/RunsApi.js.map +1 -0
  28. package/lib/cjs/StreamSource.js +17 -0
  29. package/lib/cjs/StreamSource.js.map +1 -0
  30. package/lib/cjs/TrainingApi.js +54 -0
  31. package/lib/cjs/TrainingApi.js.map +1 -0
  32. package/lib/cjs/UsersApi.js +13 -0
  33. package/lib/cjs/UsersApi.js.map +1 -0
  34. package/lib/cjs/client.js +161 -0
  35. package/lib/cjs/client.js.map +1 -0
  36. package/lib/cjs/execute.js +146 -0
  37. package/lib/cjs/execute.js.map +1 -0
  38. package/lib/cjs/index.js +22 -0
  39. package/lib/cjs/index.js.map +1 -0
  40. package/lib/cjs/package.json +3 -0
  41. package/lib/cjs/store/CommandsApi.js +33 -0
  42. package/lib/cjs/store/CommandsApi.js.map +1 -0
  43. package/lib/cjs/store/FilesApi.js +122 -0
  44. package/lib/cjs/store/FilesApi.js.map +1 -0
  45. package/lib/cjs/store/ObjectsApi.js +185 -0
  46. package/lib/cjs/store/ObjectsApi.js.map +1 -0
  47. package/lib/cjs/store/TypesApi.js +52 -0
  48. package/lib/cjs/store/TypesApi.js.map +1 -0
  49. package/lib/cjs/store/WorkflowsApi.js +92 -0
  50. package/lib/cjs/store/WorkflowsApi.js.map +1 -0
  51. package/lib/cjs/store/client.js +49 -0
  52. package/lib/cjs/store/client.js.map +1 -0
  53. package/lib/cjs/store/errors.js +11 -0
  54. package/lib/cjs/store/errors.js.map +1 -0
  55. package/lib/cjs/store/index.js +22 -0
  56. package/lib/cjs/store/index.js.map +1 -0
  57. package/lib/esm/AccountApi.js +63 -0
  58. package/lib/esm/AccountApi.js.map +1 -0
  59. package/lib/esm/AccountsApi.js +10 -0
  60. package/lib/esm/AccountsApi.js.map +1 -0
  61. package/lib/esm/AnalyticsApi.js +10 -0
  62. package/lib/esm/AnalyticsApi.js.map +1 -0
  63. package/lib/esm/ApiKeysApi.js +59 -0
  64. package/lib/esm/ApiKeysApi.js.map +1 -0
  65. package/lib/esm/CommandsApi.js +16 -0
  66. package/lib/esm/CommandsApi.js.map +1 -0
  67. package/lib/esm/EnvironmentsApi.js +55 -0
  68. package/lib/esm/EnvironmentsApi.js.map +1 -0
  69. package/lib/esm/IamApi.js +45 -0
  70. package/lib/esm/IamApi.js.map +1 -0
  71. package/lib/esm/InteractionBase.js +40 -0
  72. package/lib/esm/InteractionBase.js.map +1 -0
  73. package/lib/esm/InteractionsApi.js +181 -0
  74. package/lib/esm/InteractionsApi.js.map +1 -0
  75. package/lib/esm/ProjectsApi.js +45 -0
  76. package/lib/esm/ProjectsApi.js.map +1 -0
  77. package/lib/esm/PromptsApi.js +130 -0
  78. package/lib/esm/PromptsApi.js.map +1 -0
  79. package/lib/esm/RefsApi.js +10 -0
  80. package/lib/esm/RefsApi.js.map +1 -0
  81. package/lib/esm/RunsApi.js +75 -0
  82. package/lib/esm/RunsApi.js.map +1 -0
  83. package/lib/esm/StreamSource.js +13 -0
  84. package/lib/esm/StreamSource.js.map +1 -0
  85. package/lib/esm/TrainingApi.js +51 -0
  86. package/lib/esm/TrainingApi.js.map +1 -0
  87. package/lib/esm/UsersApi.js +10 -0
  88. package/lib/esm/UsersApi.js.map +1 -0
  89. package/lib/esm/client.js +154 -0
  90. package/lib/esm/client.js.map +1 -0
  91. package/lib/esm/execute.js +108 -0
  92. package/lib/esm/execute.js.map +1 -0
  93. package/lib/esm/index.js +6 -0
  94. package/lib/esm/index.js.map +1 -0
  95. package/lib/esm/store/CommandsApi.js +28 -0
  96. package/lib/esm/store/CommandsApi.js.map +1 -0
  97. package/lib/esm/store/FilesApi.js +117 -0
  98. package/lib/esm/store/FilesApi.js.map +1 -0
  99. package/lib/esm/store/ObjectsApi.js +181 -0
  100. package/lib/esm/store/ObjectsApi.js.map +1 -0
  101. package/lib/esm/store/TypesApi.js +48 -0
  102. package/lib/esm/store/TypesApi.js.map +1 -0
  103. package/lib/esm/store/WorkflowsApi.js +86 -0
  104. package/lib/esm/store/WorkflowsApi.js.map +1 -0
  105. package/lib/esm/store/client.js +45 -0
  106. package/lib/esm/store/client.js.map +1 -0
  107. package/lib/esm/store/errors.js +7 -0
  108. package/lib/esm/store/errors.js.map +1 -0
  109. package/lib/esm/store/index.js +6 -0
  110. package/lib/esm/store/index.js.map +1 -0
  111. package/lib/tsconfig.tsbuildinfo +1 -0
  112. package/lib/types/AccountApi.d.ts +43 -0
  113. package/lib/types/AccountApi.d.ts.map +1 -0
  114. package/lib/types/AccountsApi.d.ts +6 -0
  115. package/lib/types/AccountsApi.d.ts.map +1 -0
  116. package/lib/types/AnalyticsApi.d.ts +6 -0
  117. package/lib/types/AnalyticsApi.d.ts.map +1 -0
  118. package/lib/types/ApiKeysApi.d.ts +42 -0
  119. package/lib/types/ApiKeysApi.d.ts.map +1 -0
  120. package/lib/types/CommandsApi.d.ts +10 -0
  121. package/lib/types/CommandsApi.d.ts.map +1 -0
  122. package/lib/types/EnvironmentsApi.d.ts +30 -0
  123. package/lib/types/EnvironmentsApi.d.ts.map +1 -0
  124. package/lib/types/IamApi.d.ts +39 -0
  125. package/lib/types/IamApi.d.ts.map +1 -0
  126. package/lib/types/InteractionBase.d.ts +22 -0
  127. package/lib/types/InteractionBase.d.ts.map +1 -0
  128. package/lib/types/InteractionsApi.d.ts +129 -0
  129. package/lib/types/InteractionsApi.d.ts.map +1 -0
  130. package/lib/types/ProjectsApi.d.ts +17 -0
  131. package/lib/types/ProjectsApi.d.ts.map +1 -0
  132. package/lib/types/PromptsApi.d.ts +106 -0
  133. package/lib/types/PromptsApi.d.ts.map +1 -0
  134. package/lib/types/RefsApi.d.ts +6 -0
  135. package/lib/types/RefsApi.d.ts.map +1 -0
  136. package/lib/types/RunsApi.d.ts +62 -0
  137. package/lib/types/RunsApi.d.ts.map +1 -0
  138. package/lib/types/StreamSource.d.ts +7 -0
  139. package/lib/types/StreamSource.d.ts.map +1 -0
  140. package/lib/types/TrainingApi.d.ts +27 -0
  141. package/lib/types/TrainingApi.d.ts.map +1 -0
  142. package/lib/types/UsersApi.d.ts +6 -0
  143. package/lib/types/UsersApi.d.ts.map +1 -0
  144. package/lib/types/client.d.ts +85 -0
  145. package/lib/types/client.d.ts.map +1 -0
  146. package/lib/types/execute.d.ts +32 -0
  147. package/lib/types/execute.d.ts.map +1 -0
  148. package/lib/types/index.d.ts +8 -0
  149. package/lib/types/index.d.ts.map +1 -0
  150. package/lib/types/store/CommandsApi.d.ts +13 -0
  151. package/lib/types/store/CommandsApi.d.ts.map +1 -0
  152. package/lib/types/store/FilesApi.d.ts +41 -0
  153. package/lib/types/store/FilesApi.d.ts.map +1 -0
  154. package/lib/types/store/ObjectsApi.d.ts +76 -0
  155. package/lib/types/store/ObjectsApi.d.ts.map +1 -0
  156. package/lib/types/store/TypesApi.d.ts +13 -0
  157. package/lib/types/store/TypesApi.d.ts.map +1 -0
  158. package/lib/types/store/WorkflowsApi.d.ts +39 -0
  159. package/lib/types/store/WorkflowsApi.d.ts.map +1 -0
  160. package/lib/types/store/client.d.ts +23 -0
  161. package/lib/types/store/client.d.ts.map +1 -0
  162. package/lib/types/store/errors.d.ts +4 -0
  163. package/lib/types/store/errors.d.ts.map +1 -0
  164. package/lib/types/store/index.d.ts +5 -0
  165. package/lib/types/store/index.d.ts.map +1 -0
  166. package/package.json +36 -0
  167. package/src/AccountApi.ts +75 -0
  168. package/src/AccountsApi.ts +18 -0
  169. package/src/AnalyticsApi.ts +20 -0
  170. package/src/ApiKeysApi.ts +67 -0
  171. package/src/CommandsApi.ts +23 -0
  172. package/src/EnvironmentsApi.ts +70 -0
  173. package/src/IamApi.ts +68 -0
  174. package/src/InteractionBase.ts +44 -0
  175. package/src/InteractionsApi.ts +210 -0
  176. package/src/ProjectsApi.ts +58 -0
  177. package/src/PromptsApi.ts +160 -0
  178. package/src/RefsApi.ts +18 -0
  179. package/src/RunsApi.ts +103 -0
  180. package/src/StreamSource.ts +3 -0
  181. package/src/TrainingApi.ts +71 -0
  182. package/src/UsersApi.ts +18 -0
  183. package/src/client.ts +191 -0
  184. package/src/execute.ts +114 -0
  185. package/src/index.ts +8 -0
  186. package/src/store/CommandsApi.ts +42 -0
  187. package/src/store/FilesApi.ts +139 -0
  188. package/src/store/ObjectsApi.ts +245 -0
  189. package/src/store/TypesApi.ts +61 -0
  190. package/src/store/WorkflowsApi.ts +121 -0
  191. package/src/store/client.ts +61 -0
  192. package/src/store/errors.ts +7 -0
  193. package/src/store/index.ts +6 -0
package/src/execute.ts ADDED
@@ -0,0 +1,114 @@
1
+ import { ExecutionRun, ExecutionRunStatus, InteractionExecutionPayload, NamedInteractionExecutionPayload } from '@vertesia/common';
2
+ import { ComposableClient } from './client.js';
3
+
4
+ export function EventSourceProvider(): Promise<typeof EventSource> {
5
+ if (typeof globalThis.EventSource === 'function') {
6
+ return Promise.resolve(globalThis.EventSource)
7
+ } else {
8
+ return import('eventsource').then(module => module.default as unknown as typeof EventSource);
9
+ }
10
+ }
11
+ /**
12
+ *
13
+ * Execute an interaction and return a promise which will be resolved with the executed run when
14
+ * the run completes or fails.
15
+ * If the onChunk callback is passed then the streaming of the result is enabled.
16
+ * The onChunk callback with be called with the next chunk of the result as soon as it is available.
17
+ * When all chunks are received the fucntion will return the resolved promise
18
+ * @param id of the interaction to execute
19
+ * @param payload InteractionExecutionPayload
20
+ * @param onChunk callback to be called when the next chunk of the response is available
21
+ */
22
+ export async function executeInteraction<P = any, R = any>(client: ComposableClient,
23
+ interactionId: string,
24
+ payload: InteractionExecutionPayload = {},
25
+ onChunk?: (chunk: string) => void): Promise<ExecutionRun<P, R>> {
26
+ const stream = !!onChunk;
27
+ const response = await client.runs.create({
28
+ ...payload, interaction: interactionId, stream
29
+ });
30
+ if (stream) {
31
+ if (response.status === ExecutionRunStatus.failed) {
32
+ return response;
33
+ }
34
+ await handleStreaming(client, response.id, onChunk);
35
+ }
36
+ return response;
37
+ }
38
+
39
+ /**
40
+ * Same as executeInteraction but uses the interaction name selector instead of the id.
41
+ * A name selector is the interaction endpoint name suffuxed with an optional tag or version wich is starting with a `@` character.
42
+ * The special `draft` tag is used to select the draft version of the interaction. If no tag or version is specified then the latest version is selected.
43
+ * Examples of selectors:
44
+ * - `ReviewContract` - select the latest version of the ReviewContract interaction
45
+ * - `ReviewContract@1` - select the version 1 of the ReviewContract interaction
46
+ * - `ReviewContract@draft` - select the draft version of the ReviewContract interaction
47
+ * - `ReviewContract@fixed` - select the ReviewContract interaction which is tagged with 'fixed' tag.
48
+ *
49
+ * @param client
50
+ * @param interaction
51
+ * @param payload
52
+ * @param onChunk
53
+ * @returns
54
+ */
55
+ export async function executeInteractionByName<P = any, R = any>(client: ComposableClient,
56
+ interaction: string,
57
+ payload: InteractionExecutionPayload = {},
58
+ onChunk?: (chunk: string) => void): Promise<ExecutionRun<P, R>> {
59
+ const stream = !!onChunk;
60
+ const response = await client.post('/api/v1/execute', {
61
+ payload: {
62
+ ...payload,
63
+ interaction,
64
+ stream
65
+ } as NamedInteractionExecutionPayload,
66
+ });
67
+ if (stream) {
68
+ if (response.status === ExecutionRunStatus.failed) {
69
+ return response;
70
+ }
71
+ await handleStreaming(client, response.id, onChunk);
72
+ }
73
+ return response;
74
+ }
75
+
76
+ function handleStreaming(client: ComposableClient, runId: string, onChunk: (chunk: string) => void) {
77
+ return new Promise(async (resolve, reject) => {
78
+ try {
79
+ const EventSourceImpl = await EventSourceProvider();
80
+ const streamUrl = new URL(client.runs.baseUrl + '/' + runId + '/stream');
81
+ const bearerToken = client._auth ? await client._auth() : undefined;
82
+
83
+ if (bearerToken) {
84
+ const token = bearerToken.split(' ')[1];
85
+ streamUrl.searchParams.set('access_token', token);
86
+ } else {
87
+ throw new Error('No auth token available');
88
+ }
89
+
90
+ const sse = new EventSourceImpl(streamUrl.href);
91
+ sse.addEventListener("message", ev => {
92
+ try {
93
+ const data = JSON.parse(ev.data);
94
+ if (data) {
95
+ onChunk && onChunk(data);
96
+ }
97
+ } catch (err) {
98
+ reject(err);
99
+ }
100
+ });
101
+ sse.addEventListener("close", (ev) => {
102
+ try {
103
+ sse.close();
104
+ const msg = JSON.parse(ev.data)
105
+ resolve(msg);
106
+ } catch (err) {
107
+ reject(err);
108
+ }
109
+ });
110
+ } catch (err) {
111
+ reject(err);
112
+ }
113
+ });
114
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './InteractionBase.js';
2
+ export type { ComputePromptFacetsResponse, ListInteractionsResponse } from './PromptsApi.js';
3
+ export type { ComputeInteractionFacetsResponse } from './InteractionsApi.js';
4
+ export type { ComputeRunFacetsResponse, FilterOption } from './RunsApi.js';
5
+ export * from './client.js';
6
+ export * from './InteractionBase.js';
7
+ export * from "./store/index.js";
8
+ export * from "./StreamSource.js";
@@ -0,0 +1,42 @@
1
+ import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
+ import { EmbeddingsStatusResponse, GenericCommandResponse, ProjectConfigurationEmbeddings, SupportedEmbeddingTypes } from "@vertesia/common";
3
+
4
+
5
+ export class CommandsApi extends ApiTopic {
6
+
7
+ constructor(parent: ClientBase) {
8
+ super(parent, "/api/v1/commands");
9
+ }
10
+
11
+ embeddings = new EmbeddingsApi(this);
12
+
13
+ }
14
+
15
+ export class EmbeddingsApi extends ApiTopic {
16
+
17
+ constructor(parent: ClientBase) {
18
+ super(parent, "/embeddings");
19
+ }
20
+
21
+ async status(type: SupportedEmbeddingTypes): Promise<EmbeddingsStatusResponse> {
22
+ return this.get(type + "/status");
23
+ }
24
+
25
+ async activate(type: SupportedEmbeddingTypes, config: Partial<ProjectConfigurationEmbeddings>): Promise<GenericCommandResponse> {
26
+
27
+ if (!config.environment) {
28
+ throw new Error("Invalid configuration: select environment");
29
+ }
30
+
31
+ return this.post(type + "/enable", { payload: config });
32
+ }
33
+
34
+ async disable(type: SupportedEmbeddingTypes): Promise<GenericCommandResponse> {
35
+ return this.post(type + "/disable");
36
+ }
37
+
38
+ async recalculate(type: SupportedEmbeddingTypes): Promise<GenericCommandResponse> {
39
+ return this.post(type + "/recalculate");
40
+ }
41
+
42
+ }
@@ -0,0 +1,139 @@
1
+ import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
+ import { GetFileUrlPayload, GetFileUrlResponse, GetUploadUrlPayload } from "@vertesia/common";
3
+ import { StreamSource } from "../StreamSource.js";
4
+
5
+ export const MEMORIES_PREFIX = 'memories';
6
+
7
+ export function getMemoryFilePath(name: string) {
8
+ const nameWithExt = name.endsWith(".tar.gz") ? name : name + ".tar.gz";
9
+ return `${MEMORIES_PREFIX}/${nameWithExt}`;
10
+ }
11
+
12
+
13
+ export class FilesApi extends ApiTopic {
14
+
15
+ constructor(parent: ClientBase) {
16
+ super(parent, "/api/v1/files");
17
+ }
18
+
19
+ /**
20
+ * get the metadata of a blob given its URI. Supported URI are:
21
+ * starting with s3:// and gs://.
22
+ * For s3 blobs use #region to specify the region. Ex: s3://bucket/key#us-west-2
23
+ * @param uri
24
+ * @returns
25
+ */
26
+ getMetadata(uri: string): Promise<{
27
+ name: string,
28
+ size: number,
29
+ contentType: string,
30
+ contentDisposition?:
31
+ string,
32
+ etag?: string
33
+ }> {
34
+ return this.get("/metadata", {
35
+ query: {
36
+ file: uri
37
+ }
38
+ });
39
+ }
40
+
41
+ /**
42
+ * Get or create a bucket for the project. If the bucket already exists, it does nothing.
43
+ * The bucket URI is returned.
44
+ * @returns
45
+ */
46
+ getOrCreateBucket(): Promise<{ bucket: string }> {
47
+ return this.post('/bucket');
48
+ }
49
+
50
+ getUploadUrl(payload: GetUploadUrlPayload): Promise<GetFileUrlResponse> {
51
+ return this.post('/upload-url', {
52
+ payload
53
+ })
54
+ }
55
+
56
+ getDownloadUrl(file: string): Promise<GetFileUrlResponse> {
57
+ return this.post('/download-url', {
58
+ payload: {
59
+ file
60
+ } satisfies GetFileUrlPayload
61
+ })
62
+ }
63
+
64
+ /**
65
+ * Upload content to a file and return the full path (including bucket name) of the uploaded file
66
+ * @param source
67
+ * @returns
68
+ */
69
+ async uploadFile(source: StreamSource | File): Promise<string> {
70
+ const isStream = source instanceof StreamSource;
71
+ const { url, path } = await this.getUploadUrl(source);
72
+
73
+ await fetch(url, {
74
+ method: 'PUT',
75
+ body: isStream ? source.stream : source,
76
+ //@ts-ignore: duplex is not in the types. See https://github.com/node-fetch/node-fetch/issues/1769
77
+ duplex: isStream ? "half" : undefined,
78
+ headers: {
79
+ 'Content-Type': source.type || 'application/gzip'
80
+ }
81
+ }).then((res: Response) => {
82
+ if (res.ok) {
83
+ return res;
84
+ } else {
85
+ console.log(res);
86
+ throw new Error(`Failed to upload file: ${res.statusText}`);
87
+ }
88
+ }).catch(err => {
89
+ console.error('Failed to upload file', err);
90
+ throw err;
91
+ });
92
+
93
+ return path;
94
+ }
95
+
96
+ async downloadFile(name: string): Promise<ReadableStream<Uint8Array>> {
97
+ const { url } = await this.getDownloadUrl(name);
98
+
99
+ const res = await fetch(url, {
100
+ method: 'GET',
101
+ }).then((res: Response) => {
102
+ if (res.ok) {
103
+ return res;
104
+ } else {
105
+ console.log(res);
106
+ throw new Error(`Failed to download file ${name}: ${res.statusText}`);
107
+ }
108
+ }).catch(err => {
109
+ console.error(`Failed to download file ${name}.`, err);
110
+ throw err;
111
+ });
112
+
113
+ if (!res.body) {
114
+ throw new Error(`No body in response while downloading memory pack ${name}`);
115
+ }
116
+
117
+ return res.body;
118
+ }
119
+
120
+ async uploadMemoryPack(source: StreamSource | File): Promise<string> {
121
+ const fileId = getMemoryFilePath(source.name);
122
+ const nameWithExt = source.name.endsWith(".tar.gz") ? source.name : source.name + ".tar.gz";
123
+ if (source instanceof File) {
124
+ let file = source as File;
125
+ return this.uploadFile(new StreamSource(file.stream(), nameWithExt, file.type, fileId));
126
+ } else {
127
+ return this.uploadFile(new StreamSource(source.stream, nameWithExt, source.type, fileId));
128
+ }
129
+ }
130
+
131
+ async downloadMemoryPack(name: string, gunzip: boolean = false): Promise<ReadableStream<Uint8Array>> {
132
+ let stream = await this.downloadFile(getMemoryFilePath(name));
133
+ if (gunzip) {
134
+ const ds = new DecompressionStream("gzip");
135
+ stream = stream.pipeThrough(ds);
136
+ }
137
+ return stream;
138
+ }
139
+ }
@@ -0,0 +1,245 @@
1
+ import { ApiTopic, ClientBase } from '@vertesia/api-fetch-client';
2
+ import { ComplexSearchPayload, ComputeObjectFacetPayload, ContentObject, ContentObjectItem, ContentSource, CreateContentObjectPayload, Embedding, ExportPropertiesPayload, ExportPropertiesResponse, FindPayload, GetFileUrlPayload, GetFileUrlResponse, GetRenditionResponse, GetUploadUrlPayload, ListWorkflowRunsResponse, ObjectSearchPayload, ObjectSearchQuery, SupportedEmbeddingTypes } from '@vertesia/common';
3
+
4
+ import { StreamSource } from '../StreamSource.js';
5
+ import { ZenoClient } from './client.js';
6
+
7
+ export interface UploadContentObjectPayload extends Omit<CreateContentObjectPayload, 'content'> {
8
+ content?: StreamSource | File | {
9
+
10
+ // the source URI
11
+ source: string,
12
+ // the original name of the input file if any
13
+ name?: string,
14
+ // the mime type of the content source.
15
+ type?: string
16
+
17
+ // the target id in the content store
18
+ id?: string
19
+
20
+ }
21
+ }
22
+
23
+ export interface ComputeFacetsResponse {
24
+ type?: { _id: string, count: number }[];
25
+ location?: { _id: string, count: number }[];
26
+ status?: { _id: string, count: number }[];
27
+ total?: { count: number }[];
28
+ }
29
+
30
+ export class ObjectsApi extends ApiTopic {
31
+
32
+ constructor(parent: ClientBase) {
33
+ super(parent, "/api/v1/objects");
34
+ }
35
+
36
+ getUploadUrl(payload: GetUploadUrlPayload): Promise<GetFileUrlResponse> {
37
+ return this.post('/upload-url', {
38
+ payload
39
+ })
40
+ }
41
+
42
+ getDownloadUrl(fileUri: string): Promise<{ url: string }> {
43
+ return this.post('/download-url', {
44
+ payload: {
45
+ file: fileUri
46
+ } satisfies GetFileUrlPayload
47
+ })
48
+ }
49
+
50
+ getContentSource(objectId: string): Promise<ContentSource> {
51
+ return this.get(`/${objectId}/content-source`);
52
+ }
53
+
54
+ list(payload: ObjectSearchPayload = {}): Promise<ContentObjectItem[]> {
55
+ const limit = payload.limit || 100;
56
+ const offset = payload.offset || 0;
57
+ const query = payload.query || {} as ObjectSearchQuery;
58
+
59
+ return this.get("/", {
60
+ query: {
61
+ limit,
62
+ offset,
63
+ ...query
64
+ }
65
+ });
66
+ }
67
+
68
+ computeFacets(query: ComputeObjectFacetPayload): Promise<ComputeFacetsResponse> {
69
+ return this.post("/facets", {
70
+ payload: query
71
+ });
72
+ }
73
+
74
+ listFolders(path: string = '/') {
75
+ path;//TODO
76
+ }
77
+
78
+ find(payload: FindPayload): Promise<ContentObject[]> {
79
+ return this.post("/find", {
80
+ payload
81
+ });
82
+ }
83
+
84
+ search(payload: ComplexSearchPayload): Promise<ContentObjectItem[]> {
85
+ return this.post("/search", {
86
+ payload
87
+ });
88
+ }
89
+
90
+ retrieve(id: string, select?: string): Promise<ContentObject> {
91
+ return this.get(`/${id}`, {
92
+ query: {
93
+ select
94
+ }
95
+ });
96
+ }
97
+
98
+ getObjectText(id: string): Promise<{ text: string }> {
99
+ return this.get(`/${id}/text`);
100
+ }
101
+
102
+ async upload(source: StreamSource | File) {
103
+ const isStream = source instanceof StreamSource;
104
+ // get a signed URL to upload the file a computed mimeType and the file object id.
105
+ const { url, id, mime_type } = await this.getUploadUrl({
106
+ id: isStream ? source.id : undefined,
107
+ name: source.name,
108
+ mime_type: source.type
109
+ });
110
+
111
+ console.log(`Uploading file to ${url}`, { id, mime_type, isStream, source })
112
+
113
+ // upload the file content to the signed URL
114
+ /*const res = await this.fetch(url, {
115
+ method: 'PUT',
116
+ //@ts-ignore: duplex is not in the types. See https://github.com/node-fetch/node-fetch/issues/1769
117
+ duplex: isStream ? "half" : undefined,
118
+ body: isStream ? source.stream : source,
119
+ headers: {
120
+ 'Content-Type': mime_type || 'application/octet-stream'
121
+ }
122
+ }).then((res: Response) => {
123
+ if (res.ok) {
124
+ return res;
125
+ } else {
126
+ console.log(res);
127
+ throw new Error(`Failed to upload file: ${res.statusText}`);
128
+ }
129
+ });*/
130
+
131
+ const res = await fetch(url, {
132
+ method: 'PUT',
133
+ body: isStream ? source.stream : source,
134
+ //@ts-ignore: duplex is not in the types. See https://github.com/node-fetch/node-fetch/issues/1769
135
+ duplex: isStream ? "half" : undefined,
136
+ headers: {
137
+ 'Content-Type': mime_type || 'application/octet-stream'
138
+ }
139
+ }).then((res: Response) => {
140
+ if (res.ok) {
141
+ return res;
142
+ } else {
143
+ console.log(res);
144
+ throw new Error(`Failed to upload file: ${res.statusText}`);
145
+ }
146
+ }).catch(err => {
147
+ console.error('Failed to upload file', err);
148
+ throw err;
149
+ });
150
+
151
+
152
+ return {
153
+ source: id,
154
+ name: source.name,
155
+ type: mime_type,
156
+ etag: res.headers.get('etag') ?? undefined
157
+ }
158
+ }
159
+
160
+ async create(payload: UploadContentObjectPayload): Promise<ContentObject> {
161
+
162
+ const createPayload: CreateContentObjectPayload = {
163
+ ...payload
164
+ };
165
+ if (payload.content instanceof StreamSource || payload.content instanceof File) {
166
+ createPayload.content = await this.upload(payload.content);
167
+ }
168
+ return await this.post('/', {
169
+ payload: createPayload
170
+ });
171
+ }
172
+
173
+ /**
174
+ * Create an object which holds a reference to an external blob (i.e. not in the project bucket)
175
+ * The uri should starts either with gs:// or s3://. Not other protocols are supported yet.
176
+ * For the s3 blobs you must use a hash with the blob #region. Ex: s3://bucket/path/to/file#us-east-1
177
+ * @param uri
178
+ * @param payload
179
+ * @returns
180
+ */
181
+ async createFromExternalSource(uri: string, payload: CreateContentObjectPayload = {}): Promise<ContentObject> {
182
+ const metadata = await ((this.client as ZenoClient).files.getMetadata(uri));
183
+ const createPayload: CreateContentObjectPayload = {
184
+ ...payload,
185
+ content: {
186
+ source: uri,
187
+ name: metadata.name,
188
+ type: metadata.contentType,
189
+ etag: metadata.etag
190
+ }
191
+ };
192
+ return await this.post('/', {
193
+ payload: createPayload
194
+ });
195
+ }
196
+
197
+ update(id: string, payload: Partial<CreateContentObjectPayload>): Promise<ContentObject> {
198
+ return this.put(`/${id}`, {
199
+ payload
200
+ });
201
+ }
202
+
203
+ delete(id: string): Promise<{ id: string }> {
204
+ return this.del(`/${id}`);
205
+ }
206
+
207
+ listWorkflowRuns(documentId: string): Promise<ListWorkflowRunsResponse> {
208
+
209
+ return this.get(`/${documentId}/workflow-runs`)
210
+
211
+ }
212
+
213
+ listRenditions(documentId: string): Promise<ContentObjectItem[]> {
214
+ return this.get(`/${documentId}/renditions`);
215
+ }
216
+
217
+ getRendition(documentId: string, options: GetRenditionParams): Promise<GetRenditionResponse> {
218
+
219
+ const query = {
220
+ max_hw: options.max_hw,
221
+ generate_if_missing: options.generate_if_missing
222
+ }
223
+
224
+ return this.get(`/${documentId}/renditions/${options.format}`, { query });
225
+ }
226
+
227
+ exportProperties(payload: ExportPropertiesPayload): Promise<ExportPropertiesResponse> {
228
+ return this.post("/export", {
229
+ payload
230
+ });
231
+ }
232
+
233
+ setEmbedding(id: string, type: SupportedEmbeddingTypes, payload: Embedding): Promise<Record<SupportedEmbeddingTypes, Embedding>> {
234
+ return this.put(`/${id}/embeddings/${type}`, {
235
+ payload
236
+ });
237
+ }
238
+
239
+ }
240
+
241
+ interface GetRenditionParams {
242
+ format: string;
243
+ max_hw?: number;
244
+ generate_if_missing?: boolean;
245
+ }
@@ -0,0 +1,61 @@
1
+ import { ContentObjectType, ContentObjectTypeItem, ContentObjectTypeLayout, CreateContentObjectTypePayload, FindPayload, ObjectTypeSearchQuery, ObjectTypeSearchPayload } from "@vertesia/common";
2
+ import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
3
+
4
+
5
+ export class TypesApi extends ApiTopic {
6
+
7
+ constructor(parent: ClientBase) {
8
+ super(parent, "/api/v1/types");
9
+ }
10
+
11
+ list(payload: ObjectTypeSearchPayload = {}): Promise<ContentObjectTypeItem[]> {
12
+ const limit = payload.limit || 100;
13
+ const offset = payload.offset || 0;
14
+ const query = payload.query || {} as ObjectTypeSearchQuery;
15
+
16
+ return this.get("/", {
17
+ query: {
18
+ limit,
19
+ offset,
20
+ ...query
21
+ }
22
+ });
23
+ }
24
+
25
+ find(payload: FindPayload): Promise<ContentObjectType[]> {
26
+ return this.post("/find", {
27
+ payload
28
+ });
29
+ }
30
+
31
+ layouts(): Promise<ContentObjectTypeLayout[]> {
32
+ return this.get('/', {
33
+ query: { layout: true }
34
+ });
35
+ }
36
+
37
+ retrieve(typeId: string): Promise<ContentObjectType> {
38
+ return this.get(`/${typeId}`);
39
+ }
40
+
41
+ getTypeByName(typeName: string): Promise<ContentObjectType> {
42
+ return this.get(`/name/${typeName}`);
43
+ }
44
+
45
+ update(typeId: string, payload: Partial<CreateContentObjectTypePayload>): Promise<ContentObjectType> {
46
+ return this.put(`/${typeId}`, {
47
+ payload
48
+ });
49
+ }
50
+
51
+ create(payload: CreateContentObjectTypePayload): Promise<ContentObjectType> {
52
+ return this.post(`/`, {
53
+ payload
54
+ });
55
+ }
56
+
57
+ delete(id: string) {
58
+ return this.del(`/${id}`);
59
+ }
60
+
61
+ }