@vertesia/client 0.79.0 → 0.80.0-dev-20251118
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/lib/cjs/InteractionCatalogApi.js +64 -0
- package/lib/cjs/InteractionCatalogApi.js.map +1 -0
- package/lib/cjs/InteractionOutput.js +300 -0
- package/lib/cjs/InteractionOutput.js.map +1 -0
- package/lib/cjs/InteractionResult.example.js +57 -0
- package/lib/cjs/InteractionResult.example.js.map +1 -0
- package/lib/cjs/InteractionsApi.js +20 -6
- package/lib/cjs/InteractionsApi.js.map +1 -1
- package/lib/cjs/ProjectsApi.js +2 -1
- package/lib/cjs/ProjectsApi.js.map +1 -1
- package/lib/cjs/RunsApi.js +12 -4
- package/lib/cjs/RunsApi.js.map +1 -1
- package/lib/cjs/client.js +107 -40
- package/lib/cjs/client.js.map +1 -1
- package/lib/cjs/index.js +6 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/store/CollectionsApi.js +21 -0
- package/lib/cjs/store/CollectionsApi.js.map +1 -1
- package/lib/cjs/store/FilesApi.js +9 -8
- package/lib/cjs/store/FilesApi.js.map +1 -1
- package/lib/cjs/store/ObjectsApi.js +5 -4
- package/lib/cjs/store/ObjectsApi.js.map +1 -1
- package/lib/cjs/store/TypesApi.js +1 -1
- package/lib/cjs/store/TypesApi.js.map +1 -1
- package/lib/cjs/store/WorkflowsApi.js +151 -2
- package/lib/cjs/store/WorkflowsApi.js.map +1 -1
- package/lib/cjs/store/client.js.map +1 -1
- package/lib/esm/InteractionCatalogApi.js +60 -0
- package/lib/esm/InteractionCatalogApi.js.map +1 -0
- package/lib/esm/InteractionOutput.js +293 -0
- package/lib/esm/InteractionOutput.js.map +1 -0
- package/lib/esm/InteractionResult.example.js +55 -0
- package/lib/esm/InteractionResult.example.js.map +1 -0
- package/lib/esm/InteractionsApi.js +20 -6
- package/lib/esm/InteractionsApi.js.map +1 -1
- package/lib/esm/ProjectsApi.js +1 -1
- package/lib/esm/ProjectsApi.js.map +1 -1
- package/lib/esm/RunsApi.js +12 -4
- package/lib/esm/RunsApi.js.map +1 -1
- package/lib/esm/client.js +106 -39
- package/lib/esm/client.js.map +1 -1
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/store/CollectionsApi.js +21 -0
- package/lib/esm/store/CollectionsApi.js.map +1 -1
- package/lib/esm/store/FilesApi.js +9 -8
- package/lib/esm/store/FilesApi.js.map +1 -1
- package/lib/esm/store/ObjectsApi.js +5 -4
- package/lib/esm/store/ObjectsApi.js.map +1 -1
- package/lib/esm/store/TypesApi.js +1 -1
- package/lib/esm/store/TypesApi.js.map +1 -1
- package/lib/esm/store/WorkflowsApi.js +151 -2
- package/lib/esm/store/WorkflowsApi.js.map +1 -1
- package/lib/esm/store/client.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/AccountApi.d.ts +1 -0
- package/lib/types/AccountsApi.d.ts +1 -0
- package/lib/types/AnalyticsApi.d.ts +1 -0
- package/lib/types/ApiKeysApi.d.ts +1 -0
- package/lib/types/AppsApi.d.ts +1 -0
- package/lib/types/CommandsApi.d.ts +1 -0
- package/lib/types/EnvironmentsApi.d.ts +1 -0
- package/lib/types/GroupsApi.d.ts +1 -0
- package/lib/types/IamApi.d.ts +1 -0
- package/lib/types/InteractionBase.d.ts +1 -0
- package/lib/types/InteractionCatalogApi.d.ts +37 -0
- package/lib/types/InteractionCatalogApi.d.ts.map +1 -0
- package/lib/types/InteractionOutput.d.ts +175 -0
- package/lib/types/InteractionOutput.d.ts.map +1 -0
- package/lib/types/InteractionResult.example.d.ts +7 -0
- package/lib/types/InteractionResult.example.d.ts.map +1 -0
- package/lib/types/InteractionsApi.d.ts +10 -6
- package/lib/types/InteractionsApi.d.ts.map +1 -1
- package/lib/types/ProjectsApi.d.ts +2 -1
- package/lib/types/ProjectsApi.d.ts.map +1 -1
- package/lib/types/PromptsApi.d.ts +1 -0
- package/lib/types/RefsApi.d.ts +1 -0
- package/lib/types/RunsApi.d.ts +7 -4
- package/lib/types/RunsApi.d.ts.map +1 -1
- package/lib/types/StreamSource.d.ts +1 -0
- package/lib/types/TrainingApi.d.ts +1 -0
- package/lib/types/UsersApi.d.ts +1 -0
- package/lib/types/client.d.ts +10 -5
- package/lib/types/client.d.ts.map +1 -1
- package/lib/types/execute.d.ts +1 -0
- package/lib/types/index.d.ts +6 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/nodejs/NodeStreamSource.d.ts +1 -0
- package/lib/types/nodejs/index.d.ts +1 -0
- package/lib/types/store/AgentsApi.d.ts +1 -0
- package/lib/types/store/AnalyzeDocApi.d.ts +1 -0
- package/lib/types/store/CollectionsApi.d.ts +8 -0
- package/lib/types/store/CollectionsApi.d.ts.map +1 -1
- package/lib/types/store/CommandsApi.d.ts +1 -0
- package/lib/types/store/EmbeddingsApi.d.ts +1 -0
- package/lib/types/store/FilesApi.d.ts +4 -2
- package/lib/types/store/FilesApi.d.ts.map +1 -1
- package/lib/types/store/ObjectsApi.d.ts +7 -11
- package/lib/types/store/ObjectsApi.d.ts.map +1 -1
- package/lib/types/store/TypesApi.d.ts +1 -0
- package/lib/types/store/WorkflowsApi.d.ts +13 -0
- package/lib/types/store/WorkflowsApi.d.ts.map +1 -1
- package/lib/types/store/client.d.ts +2 -0
- package/lib/types/store/client.d.ts.map +1 -1
- package/lib/types/store/errors.d.ts +1 -0
- package/lib/types/store/index.d.ts +1 -0
- package/lib/types/store/version.d.ts +1 -0
- package/lib/vertesia-client.js +1 -1
- package/lib/vertesia-client.js.map +1 -1
- package/package.json +59 -54
- package/src/InteractionCatalogApi.ts +72 -0
- package/src/InteractionOutput.test.ts +305 -0
- package/src/InteractionOutput.ts +328 -0
- package/src/InteractionResult.example.ts +72 -0
- package/src/InteractionsApi.ts +34 -9
- package/src/ProjectsApi.ts +7 -1
- package/src/RunsApi.ts +15 -5
- package/src/client.test.ts +2 -0
- package/src/client.ts +128 -57
- package/src/index.ts +2 -0
- package/src/store/CollectionsApi.ts +39 -2
- package/src/store/FilesApi.ts +10 -8
- package/src/store/ObjectsApi.ts +7 -23
- package/src/store/TypesApi.ts +1 -1
- package/src/store/WorkflowsApi.ts +171 -2
- package/src/store/client.ts +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example usage of InteractionOutput
|
|
3
|
+
* This file demonstrates the Proxy-based approach where the result acts as both
|
|
4
|
+
* an array and has convenience methods.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CompletionResult } from '@llumiverse/common';
|
|
8
|
+
import { InteractionOutput } from './InteractionOutput.js';
|
|
9
|
+
|
|
10
|
+
// Sample data
|
|
11
|
+
const sampleResults: CompletionResult[] = [
|
|
12
|
+
{ type: 'text', value: 'Hello, ' },
|
|
13
|
+
{ type: 'text', value: 'World!' },
|
|
14
|
+
{ type: 'json', value: { name: 'Alice', age: 30 } },
|
|
15
|
+
{ type: 'json', value: { title: 'Engineer', level: 'Senior' } },
|
|
16
|
+
{ type: 'image', value: 'data:image/png;base64,iVBORw0K...' }
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
// Example 1: Using InteractionOutput.from() (Proxy approach - RECOMMENDED)
|
|
20
|
+
console.log('=== Example 1: Proxy Approach ===');
|
|
21
|
+
interface Person { name: string; age: number; }
|
|
22
|
+
const output = InteractionOutput.from<Person>(sampleResults);
|
|
23
|
+
|
|
24
|
+
// Works as an array
|
|
25
|
+
console.log('Array length:', output.length); // 5
|
|
26
|
+
console.log('First item:', output[0]); // { type: 'text', value: 'Hello, ' }
|
|
27
|
+
console.log('Types:', output.map(r => r.type)); // ['text', 'text', 'json', 'json', 'image']
|
|
28
|
+
|
|
29
|
+
// Has convenience methods
|
|
30
|
+
console.log('All text:', output.text); // 'Hello, World!'
|
|
31
|
+
console.log('First object:', output.object()); // { name: 'Alice', age: 30 } (typed as Person)
|
|
32
|
+
console.log('All objects:', output.objects()); // [{ name: 'Alice', age: 30 }, { title: 'Engineer', level: 'Senior' }]
|
|
33
|
+
console.log('First image:', output.image); // 'data:image/png;base64,iVBORw0K...'
|
|
34
|
+
|
|
35
|
+
// Override type for specific objects
|
|
36
|
+
interface Job { title: string; level: string; }
|
|
37
|
+
console.log('Second object:', output.objectAt<Job>(1)); // { title: 'Engineer', level: 'Senior' } (typed as Job)
|
|
38
|
+
|
|
39
|
+
// Example 2: Using InteractionOutput class directly
|
|
40
|
+
console.log('\n=== Example 2: Class Approach ===');
|
|
41
|
+
const wrapper = new InteractionOutput<Person>(sampleResults);
|
|
42
|
+
|
|
43
|
+
// Access through wrapper properties (no array access)
|
|
44
|
+
console.log('All text:', wrapper.text);
|
|
45
|
+
console.log('Raw results:', wrapper.results); // Original array
|
|
46
|
+
console.log('First object:', wrapper.object());
|
|
47
|
+
|
|
48
|
+
// Example 3: Type safety demonstration
|
|
49
|
+
console.log('\n=== Example 3: Type Safety ===');
|
|
50
|
+
|
|
51
|
+
interface Contract { title: string; parties: string[]; }
|
|
52
|
+
const contractResults: CompletionResult[] = [
|
|
53
|
+
{ type: 'json', value: { title: 'Sales Agreement', parties: ['Alice', 'Bob'] } }
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const contractOutput = InteractionOutput.from<Contract>(contractResults);
|
|
57
|
+
const contract = contractOutput.object(); // TypeScript knows this is Contract
|
|
58
|
+
console.log('Contract title:', contract.title);
|
|
59
|
+
console.log('Parties:', contract.parties.join(', '));
|
|
60
|
+
|
|
61
|
+
// Example 4: Mixed content
|
|
62
|
+
console.log('\n=== Example 4: Mixed Content ===');
|
|
63
|
+
const mixedResults: CompletionResult[] = [
|
|
64
|
+
{ type: 'text', value: 'Analysis complete. Results: ' },
|
|
65
|
+
{ type: 'json', value: { score: 0.95, confidence: 'high' } },
|
|
66
|
+
{ type: 'text', value: '\nThank you!' }
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
const mixed = InteractionOutput.from(mixedResults);
|
|
70
|
+
console.log('Full text:', mixed.text); // 'Analysis complete. Results: \nThank you!'
|
|
71
|
+
console.log('Analysis:', mixed.object()); // { score: 0.95, confidence: 'high' }
|
|
72
|
+
console.log('Text parts:', mixed.texts); // ['Analysis complete. Results: ', '\nThank you!']
|
package/src/InteractionsApi.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { ApiTopic, ClientBase, ServerError } from "@vertesia/api-fetch-client";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AsyncExecutionPayload, ComputeInteractionFacetPayload, GenerateInteractionPayload, GenerateTestDataPayload, ImprovePromptPayload,
|
|
4
|
+
ImprovePromptPayloadConfig,
|
|
5
|
+
Interaction, InteractionCreatePayload, InteractionEndpoint, InteractionEndpointQuery,
|
|
6
|
+
InteractionExecutionPayload, InteractionForkPayload,
|
|
7
|
+
InteractionPublishPayload, InteractionRef, InteractionRefWithSchema, InteractionSearchPayload, InteractionSearchQuery,
|
|
8
|
+
InteractionsExportPayload, InteractionUpdatePayload,
|
|
9
|
+
RateLimitRequestPayload, RateLimitRequestResponse
|
|
10
|
+
} from "@vertesia/common";
|
|
3
11
|
import { VertesiaClient } from "./client.js";
|
|
4
12
|
import { checkRateLimit, executeInteraction, executeInteractionAsync, executeInteractionByName } from "./execute.js";
|
|
13
|
+
import { InteractionCatalogApi } from "./InteractionCatalogApi.js";
|
|
14
|
+
import { EnhancedExecutionRun, EnhancedInteractionExecutionResult, enhanceExecutionRun, enhanceInteractionExecutionResult } from "./InteractionOutput.js";
|
|
5
15
|
|
|
6
16
|
export interface ComputeInteractionFacetsResponse {
|
|
7
17
|
tags?: { _id: string, count: number }[];
|
|
@@ -14,8 +24,11 @@ export interface AsyncExecutionResult {
|
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
export default class InteractionsApi extends ApiTopic {
|
|
27
|
+
catalog: InteractionCatalogApi;
|
|
28
|
+
|
|
17
29
|
constructor(parent: ClientBase) {
|
|
18
30
|
super(parent, "/api/v1/interactions");
|
|
31
|
+
this.catalog = new InteractionCatalogApi(parent);
|
|
19
32
|
}
|
|
20
33
|
|
|
21
34
|
/**
|
|
@@ -132,15 +145,16 @@ export default class InteractionsApi extends ApiTopic {
|
|
|
132
145
|
* @throws 500 if interaction execution fails
|
|
133
146
|
* @throws 500 if interaction execution times out
|
|
134
147
|
**/
|
|
135
|
-
execute<
|
|
136
|
-
onChunk?: (chunk: string) => void): Promise<
|
|
137
|
-
|
|
148
|
+
async execute<ResultT = any, ParamsT = any>(id: string, payload: InteractionExecutionPayload = {},
|
|
149
|
+
onChunk?: (chunk: string) => void): Promise<EnhancedInteractionExecutionResult<ResultT, ParamsT>> {
|
|
150
|
+
const r = await executeInteraction<ParamsT>(this.client as VertesiaClient, id, payload, onChunk).catch(err => {
|
|
138
151
|
if (err instanceof ServerError && err.payload?.id) {
|
|
139
152
|
throw err.updateDetails({ run_id: err.payload.id });
|
|
140
153
|
} else {
|
|
141
154
|
throw err;
|
|
142
155
|
}
|
|
143
156
|
});
|
|
157
|
+
return enhanceInteractionExecutionResult<ResultT, ParamsT>(r);
|
|
144
158
|
}
|
|
145
159
|
|
|
146
160
|
/**
|
|
@@ -158,15 +172,16 @@ export default class InteractionsApi extends ApiTopic {
|
|
|
158
172
|
* @param onChunk
|
|
159
173
|
* @returns
|
|
160
174
|
*/
|
|
161
|
-
executeByName<
|
|
162
|
-
onChunk?: (chunk: string) => void): Promise<
|
|
163
|
-
|
|
175
|
+
async executeByName<ResultT = any, ParamsT = any>(nameWithTag: string, payload: InteractionExecutionPayload = {},
|
|
176
|
+
onChunk?: (chunk: string) => void): Promise<EnhancedInteractionExecutionResult<ResultT, ParamsT>> {
|
|
177
|
+
const r = await executeInteractionByName<ParamsT>(this.client as VertesiaClient, nameWithTag, payload, onChunk).catch(err => {
|
|
164
178
|
if (err instanceof ServerError && err.payload?.id) {
|
|
165
179
|
throw err.updateDetails({ run_id: err.payload.id });
|
|
166
180
|
} else {
|
|
167
181
|
throw err;
|
|
168
182
|
}
|
|
169
183
|
});
|
|
184
|
+
return enhanceInteractionExecutionResult<ResultT, ParamsT>(r);
|
|
170
185
|
}
|
|
171
186
|
|
|
172
187
|
/**
|
|
@@ -213,13 +228,23 @@ export default class InteractionsApi extends ApiTopic {
|
|
|
213
228
|
|
|
214
229
|
/**
|
|
215
230
|
* Suggest Improvement for a prompt
|
|
231
|
+
* @deprecated use suggestPromptImprovements instead
|
|
216
232
|
*/
|
|
217
|
-
suggestImprovements(id: string, payload:
|
|
218
|
-
|
|
233
|
+
async suggestImprovements<ResultT = any, ParamsT = any>(id: string, payload: ImprovePromptPayloadConfig): Promise<EnhancedExecutionRun<ResultT, ParamsT>> {
|
|
234
|
+
const r = await this.post(`${id}/suggest-prompt-improvements`, {
|
|
235
|
+
payload
|
|
236
|
+
});
|
|
237
|
+
return enhanceExecutionRun<ResultT, ParamsT>(r);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async suggestPromptImprovements<ResultT = any, ParamsT = any>(payload: ImprovePromptPayload): Promise<EnhancedInteractionExecutionResult<ResultT, ParamsT>> {
|
|
241
|
+
const r = await this.post(`/improve`, {
|
|
219
242
|
payload
|
|
220
243
|
});
|
|
244
|
+
return enhanceInteractionExecutionResult<ResultT, ParamsT>(r);
|
|
221
245
|
}
|
|
222
246
|
|
|
247
|
+
|
|
223
248
|
/**
|
|
224
249
|
* List the versions of the interaction. Returns an empty array if no versions are found
|
|
225
250
|
* @param id
|
package/src/ProjectsApi.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
|
|
2
|
-
import { AwsConfiguration, GithubConfiguration, GladiaConfiguration, ICreateProjectPayload, MagicPdfConfiguration, Project, ProjectIntegrationListEntry, ProjectRef, SupportedIntegrations } from "@vertesia/common";
|
|
2
|
+
import { AwsConfiguration, GithubConfiguration, GladiaConfiguration, ICreateProjectPayload, MagicPdfConfiguration, Project, ProjectConfiguration, ProjectIntegrationListEntry, ProjectRef, SupportedIntegrations } from "@vertesia/common";
|
|
3
3
|
|
|
4
4
|
export default class ProjectsApi extends ApiTopic {
|
|
5
5
|
constructor(parent: ClientBase) {
|
|
@@ -26,6 +26,12 @@ export default class ProjectsApi extends ApiTopic {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
updateConfiguration(projectId: string, payload: Partial<ProjectConfiguration>): Promise<ProjectConfiguration> {
|
|
30
|
+
return this.put(`/${projectId}/configuration`, {
|
|
31
|
+
payload
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
integrations: IntegrationsConfigurationApi = new IntegrationsConfigurationApi(this);
|
|
30
36
|
|
|
31
37
|
}
|
package/src/RunsApi.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ExecutionResponse } from "@llumiverse/common";
|
|
1
2
|
import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
|
|
2
3
|
import {
|
|
3
4
|
CheckpointConversationPayload,
|
|
@@ -5,6 +6,7 @@ import {
|
|
|
5
6
|
ExecutionRun,
|
|
6
7
|
ExecutionRunRef,
|
|
7
8
|
FindPayload,
|
|
9
|
+
PopulatedExecutionRun,
|
|
8
10
|
RunCreatePayload,
|
|
9
11
|
RunListingFilters,
|
|
10
12
|
RunListingQueryOptions,
|
|
@@ -13,7 +15,7 @@ import {
|
|
|
13
15
|
UserMessagePayload,
|
|
14
16
|
} from "@vertesia/common";
|
|
15
17
|
import { VertesiaClient } from "./client.js";
|
|
16
|
-
import
|
|
18
|
+
import { EnhancedExecutionRun, enhanceExecutionRun } from "./InteractionOutput.js";
|
|
17
19
|
|
|
18
20
|
export interface FilterOption {
|
|
19
21
|
id: string;
|
|
@@ -63,8 +65,15 @@ export class RunsApi extends ApiTopic {
|
|
|
63
65
|
* @param id
|
|
64
66
|
* @returns InteractionResult
|
|
65
67
|
**/
|
|
66
|
-
retrieve<
|
|
67
|
-
|
|
68
|
+
async retrieve<ResultT = any, ParamsT = any>(id: string): Promise<EnhancedExecutionRun<ResultT, ParamsT>> {
|
|
69
|
+
const r = await this.get("/" + id);
|
|
70
|
+
return enhanceExecutionRun<ResultT, ParamsT>(r);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
retrievePopulated<P = any>(id: string): Promise<PopulatedExecutionRun<P>> {
|
|
74
|
+
return this.get("/" + id, {
|
|
75
|
+
query: { populate: "true" },
|
|
76
|
+
});
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
/**
|
|
@@ -78,7 +87,7 @@ export class RunsApi extends ApiTopic {
|
|
|
78
87
|
return this.get(`/filter-options/${field}`, { query });
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
create(payload: RunCreatePayload): Promise<
|
|
90
|
+
async create<ResultT = any, ParamsT = any>(payload: RunCreatePayload): Promise<EnhancedExecutionRun<ResultT, ParamsT>> {
|
|
82
91
|
const sessionTags = (this.client as VertesiaClient).sessionTags;
|
|
83
92
|
if (sessionTags) {
|
|
84
93
|
let tags = Array.isArray(sessionTags) ? sessionTags : [sessionTags];
|
|
@@ -89,9 +98,10 @@ export class RunsApi extends ApiTopic {
|
|
|
89
98
|
}
|
|
90
99
|
payload = { ...payload, tags };
|
|
91
100
|
}
|
|
92
|
-
|
|
101
|
+
const r = await this.post("/", {
|
|
93
102
|
payload,
|
|
94
103
|
});
|
|
104
|
+
return enhanceExecutionRun<ResultT, ParamsT>(r);
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
/**
|
package/src/client.test.ts
CHANGED
|
@@ -6,6 +6,7 @@ describe('Test Vertesia Client', () => {
|
|
|
6
6
|
const client = new VertesiaClient({
|
|
7
7
|
serverUrl: 'https://api.vertesia.io',
|
|
8
8
|
storeUrl: 'https://api.vertesia.io',
|
|
9
|
+
tokenServerUrl: 'https://sts.vertesia.io',
|
|
9
10
|
apikey: '1234',
|
|
10
11
|
});
|
|
11
12
|
expect(client).toBeDefined();
|
|
@@ -73,6 +74,7 @@ describe('Test Vertesia Client', () => {
|
|
|
73
74
|
const client = new VertesiaClient({
|
|
74
75
|
serverUrl: 'http://localhost:8091',
|
|
75
76
|
storeUrl: 'http://localhost:8092',
|
|
77
|
+
tokenServerUrl: 'http://localhost:8093',
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
expect(client).toBeDefined();
|
package/src/client.ts
CHANGED
|
@@ -37,18 +37,21 @@ export type VertesiaClientProps = {
|
|
|
37
37
|
* @default api.vertesia.io
|
|
38
38
|
* @since 0.52.0
|
|
39
39
|
*/
|
|
40
|
-
site?:
|
|
40
|
+
site?:
|
|
41
|
+
| "api.vertesia.io"
|
|
42
|
+
| "api-preview.vertesia.io"
|
|
43
|
+
| "api-staging.vertesia.io";
|
|
41
44
|
serverUrl?: string;
|
|
42
45
|
storeUrl?: string;
|
|
46
|
+
tokenServerUrl?: string;
|
|
43
47
|
apikey?: string;
|
|
44
48
|
projectId?: string;
|
|
45
49
|
sessionTags?: string | string[];
|
|
46
50
|
onRequest?: (request: Request) => void;
|
|
47
51
|
onResponse?: (response: Response) => void;
|
|
48
|
-
}
|
|
52
|
+
};
|
|
49
53
|
|
|
50
54
|
export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
51
|
-
|
|
52
55
|
/**
|
|
53
56
|
* The JWT token linked to the API KEY (sk or pk)
|
|
54
57
|
*/
|
|
@@ -64,11 +67,15 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
64
67
|
*/
|
|
65
68
|
sessionTags?: string | string[];
|
|
66
69
|
|
|
70
|
+
/**
|
|
71
|
+
* tokenServerUrl
|
|
72
|
+
*/
|
|
73
|
+
tokenServerUrl: string;
|
|
67
74
|
|
|
68
75
|
/**
|
|
69
|
-
* Create a client from the given token.
|
|
76
|
+
* Create a client from the given token.
|
|
70
77
|
* If you already have the decoded token you can pass it as the second argument to avoid decodinf it again.
|
|
71
|
-
*
|
|
78
|
+
*
|
|
72
79
|
* @param token the raw JWT token
|
|
73
80
|
* @param payload the decoded JWT token as an AuthTokenPayload - optional
|
|
74
81
|
*/
|
|
@@ -76,21 +83,21 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
76
83
|
if (!payload) {
|
|
77
84
|
payload = decodeJWT(token);
|
|
78
85
|
}
|
|
79
|
-
|
|
86
|
+
|
|
87
|
+
const endpoints = decodeEndpoints(payload.endpoints);
|
|
80
88
|
return await new VertesiaClient({
|
|
81
89
|
serverUrl: endpoints.studio,
|
|
82
|
-
storeUrl: endpoints.store
|
|
90
|
+
storeUrl: endpoints.store,
|
|
91
|
+
tokenServerUrl: payload.iss,
|
|
83
92
|
}).withApiKey(token);
|
|
84
93
|
}
|
|
85
94
|
|
|
86
|
-
static decodeEndpoints() {
|
|
87
|
-
|
|
88
|
-
}
|
|
95
|
+
static decodeEndpoints() {}
|
|
89
96
|
|
|
90
97
|
constructor(
|
|
91
98
|
opts: VertesiaClientProps = {
|
|
92
|
-
site:
|
|
93
|
-
}
|
|
99
|
+
site: "api.vertesia.io",
|
|
100
|
+
},
|
|
94
101
|
) {
|
|
95
102
|
let studioServerUrl: string;
|
|
96
103
|
let zenoServerUrl: string;
|
|
@@ -100,7 +107,9 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
100
107
|
} else if (opts.site) {
|
|
101
108
|
studioServerUrl = `https://${opts.site}`;
|
|
102
109
|
} else {
|
|
103
|
-
throw new Error(
|
|
110
|
+
throw new Error(
|
|
111
|
+
"Parameter 'site' or 'serverUrl' is required for VertesiaClient",
|
|
112
|
+
);
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
if (opts.storeUrl) {
|
|
@@ -108,25 +117,67 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
108
117
|
} else if (opts.site) {
|
|
109
118
|
zenoServerUrl = `https://${opts.site}`;
|
|
110
119
|
} else {
|
|
111
|
-
throw new Error(
|
|
120
|
+
throw new Error(
|
|
121
|
+
"Parameter 'site' or 'storeUrl' is required for VertesiaClient",
|
|
122
|
+
);
|
|
112
123
|
}
|
|
113
124
|
|
|
114
125
|
super(studioServerUrl);
|
|
115
126
|
|
|
127
|
+
if (opts.tokenServerUrl) {
|
|
128
|
+
this.tokenServerUrl = opts.tokenServerUrl;
|
|
129
|
+
} else if (opts.site) {
|
|
130
|
+
this.tokenServerUrl = `https://${opts.site.replace(/^api/, "sts")}`;
|
|
131
|
+
} else if (opts.serverUrl || opts.storeUrl) {
|
|
132
|
+
// Determine STS URL based on environment in serverUrl or storeUrl
|
|
133
|
+
const urlToCheck = opts.serverUrl || opts.storeUrl || "";
|
|
134
|
+
try {
|
|
135
|
+
const url = new URL(urlToCheck);
|
|
136
|
+
// Check for environment patterns
|
|
137
|
+
if (url.hostname.includes("-production.")) {
|
|
138
|
+
// zeno-server-production.api.vertesia.io -> sts.vertesia.io
|
|
139
|
+
this.tokenServerUrl = "https://sts.vertesia.io";
|
|
140
|
+
} else if (url.hostname.includes("-preview.")) {
|
|
141
|
+
// zeno-server-preview.api.vertesia.io -> sts-preview.vertesia.io
|
|
142
|
+
this.tokenServerUrl = "https://sts-preview.vertesia.io";
|
|
143
|
+
} else if (url.hostname === "api.vertesia.io") {
|
|
144
|
+
// api.vertesia.io -> sts.vertesia.io
|
|
145
|
+
this.tokenServerUrl = "https://sts.vertesia.io";
|
|
146
|
+
} else if (url.hostname === "api-preview.vertesia.io") {
|
|
147
|
+
// api-preview.vertesia.io -> sts-preview.vertesia.io
|
|
148
|
+
this.tokenServerUrl = "https://sts-preview.vertesia.io";
|
|
149
|
+
} else if (url.hostname === "api-staging.vertesia.io") {
|
|
150
|
+
// api-staging.vertesia.io -> sts-staging.vertesia.io
|
|
151
|
+
this.tokenServerUrl = "https://sts-staging.vertesia.io";
|
|
152
|
+
} else if (url.hostname.startsWith("api")) {
|
|
153
|
+
// Generic api.* pattern replacement
|
|
154
|
+
url.hostname = url.hostname.replace(/^api/, "sts");
|
|
155
|
+
this.tokenServerUrl = url.toString();
|
|
156
|
+
} else {
|
|
157
|
+
// Default to staging for everything else
|
|
158
|
+
this.tokenServerUrl = "https://sts-staging.vertesia.io";
|
|
159
|
+
}
|
|
160
|
+
} catch (e) {
|
|
161
|
+
// Default to staging if URL parsing fails
|
|
162
|
+
this.tokenServerUrl = "https://sts-staging.vertesia.io";
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
// Default to staging if no URL provided
|
|
166
|
+
this.tokenServerUrl = "https://sts-staging.vertesia.io";
|
|
167
|
+
}
|
|
168
|
+
|
|
116
169
|
this.store = new ZenoClient({
|
|
117
170
|
serverUrl: zenoServerUrl,
|
|
171
|
+
tokenServerUrl: this.tokenServerUrl,
|
|
118
172
|
apikey: opts.apikey,
|
|
119
173
|
onRequest: opts.onRequest,
|
|
120
|
-
onResponse: opts.onResponse
|
|
174
|
+
onResponse: opts.onResponse,
|
|
121
175
|
});
|
|
122
176
|
|
|
123
177
|
if (opts.apikey) {
|
|
124
178
|
this.withApiKey(opts.apikey);
|
|
125
179
|
}
|
|
126
|
-
|
|
127
|
-
if (opts.projectId) {
|
|
128
|
-
this.headers["x-project-id"] = opts.projectId;
|
|
129
|
-
}
|
|
180
|
+
|
|
130
181
|
this.onRequest = opts.onRequest;
|
|
131
182
|
this.onResponse = opts.onResponse;
|
|
132
183
|
this.sessionTags = opts.sessionTags;
|
|
@@ -153,25 +204,28 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
153
204
|
|
|
154
205
|
async withApiKey(apiKey: string | null) {
|
|
155
206
|
return this.withAuthCallback(
|
|
156
|
-
apiKey
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
207
|
+
apiKey
|
|
208
|
+
? async () => {
|
|
209
|
+
if (!isApiKey(apiKey)) {
|
|
210
|
+
return `Bearer ${apiKey}`;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (isTokenExpired(this._jwt)) {
|
|
214
|
+
const jwt = await this.getAuthToken(apiKey);
|
|
215
|
+
this._jwt = jwt.token;
|
|
216
|
+
}
|
|
217
|
+
return `Bearer ${this._jwt}`;
|
|
218
|
+
}
|
|
219
|
+
: undefined,
|
|
167
220
|
);
|
|
168
221
|
}
|
|
169
222
|
|
|
170
223
|
async getRawJWT() {
|
|
171
224
|
if (!this._jwt && this._auth) {
|
|
172
225
|
const auth = await this._auth();
|
|
173
|
-
if (!this._jwt) {
|
|
174
|
-
|
|
226
|
+
if (!this._jwt) {
|
|
227
|
+
// the _jwt may be set by the auth callback
|
|
228
|
+
this._jwt = auth.trim().split(" ")[1]; // remove Bearer prefix
|
|
175
229
|
}
|
|
176
230
|
}
|
|
177
231
|
return this._jwt || null;
|
|
@@ -221,21 +275,29 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
221
275
|
return this.store.baseUrl;
|
|
222
276
|
}
|
|
223
277
|
|
|
224
|
-
|
|
225
278
|
/**
|
|
226
279
|
*
|
|
227
|
-
* Generate a token for use with other
|
|
280
|
+
* Generate a token for use with other Vertesia's services
|
|
228
281
|
*
|
|
229
|
-
* @param accountId: selected account to generate the token for
|
|
230
282
|
* @returns AuthTokenResponse
|
|
231
283
|
*/
|
|
232
|
-
async getAuthToken(token?: string
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
284
|
+
async getAuthToken(token?: string): Promise<AuthTokenResponse> {
|
|
285
|
+
return fetch(`${this.tokenServerUrl}/token/issue`, {
|
|
286
|
+
method: "POST",
|
|
287
|
+
headers: {
|
|
288
|
+
"Content-Type": "application/json",
|
|
289
|
+
Authorization: `Bearer ${token}`,
|
|
290
|
+
},
|
|
291
|
+
})
|
|
292
|
+
.then((response) => response.json())
|
|
293
|
+
.then((data) => data as AuthTokenResponse)
|
|
294
|
+
.catch((error) => {
|
|
295
|
+
console.error(
|
|
296
|
+
`Error fetching token from ${this.tokenServerUrl}:`,
|
|
297
|
+
{ error },
|
|
298
|
+
);
|
|
299
|
+
throw error;
|
|
300
|
+
});
|
|
239
301
|
}
|
|
240
302
|
|
|
241
303
|
get initialHeaders() {
|
|
@@ -263,7 +325,7 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
263
325
|
}
|
|
264
326
|
|
|
265
327
|
function isApiKey(apiKey: string) {
|
|
266
|
-
return
|
|
328
|
+
return apiKey.startsWith("pk-") || apiKey.startsWith("sk-");
|
|
267
329
|
}
|
|
268
330
|
|
|
269
331
|
function isTokenExpired(token: string | null) {
|
|
@@ -274,38 +336,45 @@ function isTokenExpired(token: string | null) {
|
|
|
274
336
|
const decoded = decodeJWT(token);
|
|
275
337
|
const exp = decoded.exp;
|
|
276
338
|
const currentTime = Date.now();
|
|
277
|
-
return
|
|
339
|
+
return currentTime <= exp * 1000 - EXPIRATION_THRESHOLD;
|
|
278
340
|
}
|
|
279
341
|
|
|
280
342
|
export function decodeJWT(jwt: string): AuthTokenPayload {
|
|
281
|
-
const payloadBase64 = jwt.split(
|
|
343
|
+
const payloadBase64 = jwt.split(".")[1];
|
|
282
344
|
const decodedJson = base64UrlDecode(payloadBase64);
|
|
283
|
-
return JSON.parse(decodedJson)
|
|
345
|
+
return JSON.parse(decodedJson);
|
|
284
346
|
}
|
|
285
347
|
|
|
286
348
|
function base64UrlDecode(input: string): string {
|
|
287
349
|
// Convert base64url to base64
|
|
288
|
-
const base64 = input
|
|
350
|
+
const base64 = input
|
|
351
|
+
.replace(/-/g, "+")
|
|
352
|
+
.replace(/_/g, "/")
|
|
289
353
|
// Pad with '=' to make length a multiple of 4
|
|
290
|
-
.padEnd(Math.ceil(input.length / 4) * 4,
|
|
354
|
+
.padEnd(Math.ceil(input.length / 4) * 4, "=");
|
|
291
355
|
|
|
292
|
-
if (typeof Buffer !==
|
|
356
|
+
if (typeof Buffer !== "undefined") {
|
|
293
357
|
// Node.js
|
|
294
|
-
return Buffer.from(base64,
|
|
295
|
-
} else if (
|
|
358
|
+
return Buffer.from(base64, "base64").toString("utf-8");
|
|
359
|
+
} else if (
|
|
360
|
+
typeof atob !== "undefined" &&
|
|
361
|
+
typeof TextDecoder !== "undefined"
|
|
362
|
+
) {
|
|
296
363
|
// Browser
|
|
297
364
|
const binary = atob(base64);
|
|
298
|
-
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
|
|
365
|
+
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
299
366
|
// decode to utf8
|
|
300
367
|
return new TextDecoder().decode(bytes);
|
|
301
368
|
} else {
|
|
302
|
-
throw new Error(
|
|
369
|
+
throw new Error("No base64 decoder available");
|
|
303
370
|
}
|
|
304
371
|
}
|
|
305
372
|
|
|
306
|
-
export function decodeEndpoints(
|
|
373
|
+
export function decodeEndpoints(
|
|
374
|
+
endpoints: string | Record<string, string> | undefined,
|
|
375
|
+
): Record<string, string> {
|
|
307
376
|
if (!endpoints) {
|
|
308
|
-
return getEndpointsFromDomain("api.vertesia.io")
|
|
377
|
+
return getEndpointsFromDomain("api.vertesia.io");
|
|
309
378
|
}
|
|
310
379
|
if (typeof endpoints === "string") {
|
|
311
380
|
return getEndpointsFromDomain(endpoints);
|
|
@@ -319,12 +388,14 @@ function getEndpointsFromDomain(domain: string) {
|
|
|
319
388
|
return {
|
|
320
389
|
studio: `http://localhost:8091`,
|
|
321
390
|
store: `http://localhost:8092`,
|
|
322
|
-
|
|
391
|
+
token: process.env.STS_URL ?? "https://sts-staging.vertesia.io",
|
|
392
|
+
};
|
|
323
393
|
} else {
|
|
324
394
|
const url = `https://${domain}`;
|
|
325
395
|
return {
|
|
326
396
|
studio: url,
|
|
327
397
|
store: url,
|
|
328
|
-
|
|
398
|
+
token: url.replace("api", "sts"),
|
|
399
|
+
};
|
|
329
400
|
}
|
|
330
401
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from './client.js';
|
|
2
2
|
export * from './InteractionBase.js';
|
|
3
|
+
export * from './InteractionOutput.js';
|
|
3
4
|
export type { AsyncExecutionResult, ComputeInteractionFacetsResponse } from './InteractionsApi.js';
|
|
4
5
|
export type { ComputePromptFacetsResponse, ListInteractionsResponse } from './PromptsApi.js';
|
|
5
6
|
export type { ComputeRunFacetsResponse, FilterOption } from './RunsApi.js';
|
|
6
7
|
export type { GroupsQueryOptions } from './GroupsApi.js';
|
|
7
8
|
export * from "./store/index.js";
|
|
8
9
|
export * from "./StreamSource.js";
|
|
10
|
+
export type { OrphanedAppInstallation } from "./AppsApi.js";
|
|
@@ -91,6 +91,30 @@ export class CollectionsApi extends ApiTopic {
|
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
addChildren(collectionId: string, children: string[]): Promise<{ count: number }> {
|
|
95
|
+
return this.post(`/${collectionId}/children`, {
|
|
96
|
+
payload: {
|
|
97
|
+
action: 'add',
|
|
98
|
+
children
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
deleteChildren(collectionId: string, children: string[]): Promise<{ count: number }> {
|
|
104
|
+
return this.post(`/${collectionId}/children`, {
|
|
105
|
+
payload: {
|
|
106
|
+
action: 'delete',
|
|
107
|
+
children
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
searchChildren(collectionId: string, query: ComplexCollectionSearchQuery = {}): Promise<CollectionItem[]> {
|
|
113
|
+
return this.post(`/${collectionId}/children/search`, {
|
|
114
|
+
payload: query
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
94
118
|
delete(id: string) {
|
|
95
119
|
return this.del(`/${id}`);
|
|
96
120
|
}
|
|
@@ -104,7 +128,6 @@ export class CollectionsApi extends ApiTopic {
|
|
|
104
128
|
updatePermissions(collectionId: string, permissions: Record<string, string[]>): Promise<{
|
|
105
129
|
id: string;
|
|
106
130
|
security: Record<string, string[]>;
|
|
107
|
-
objectsUpdated: number;
|
|
108
131
|
}> {
|
|
109
132
|
return this.put(`/${collectionId}/permissions`, {
|
|
110
133
|
payload: permissions
|
|
@@ -121,9 +144,23 @@ export class CollectionsApi extends ApiTopic {
|
|
|
121
144
|
id: string;
|
|
122
145
|
message: string;
|
|
123
146
|
security?: Record<string, string[]>;
|
|
124
|
-
objectsUpdated: number;
|
|
125
147
|
}> {
|
|
126
148
|
return this.post(`/${collectionId}/propagate-permissions`);
|
|
127
149
|
}
|
|
128
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Manually trigger shared properties propagation from collection to member objects
|
|
153
|
+
* Useful for debugging and fixing shared properties issues
|
|
154
|
+
* @param collectionId - The collection ID
|
|
155
|
+
* @returns Object with collection id, message, and number of objects updated
|
|
156
|
+
*/
|
|
157
|
+
propagateSharedProperties(collectionId: string): Promise<{
|
|
158
|
+
id: string;
|
|
159
|
+
message: string;
|
|
160
|
+
shared_properties: string[]
|
|
161
|
+
}> {
|
|
162
|
+
return this.post(`/${collectionId}/propagate-shared-props`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
129
166
|
}
|