@vertesia/client 1.5.0-dev.20260717.131047Z → 1.5.0-dev.20260722.120446Z
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/AppsApi.d.ts +34 -6
- package/lib/AppsApi.d.ts.map +1 -1
- package/lib/AppsApi.js +60 -7
- package/lib/AppsApi.js.map +1 -1
- package/lib/AuditTrailApi.d.ts +2 -1
- package/lib/AuditTrailApi.d.ts.map +1 -1
- package/lib/AuditTrailApi.js +3 -0
- package/lib/AuditTrailApi.js.map +1 -1
- package/lib/ProjectsApi.d.ts +3 -1
- package/lib/ProjectsApi.d.ts.map +1 -1
- package/lib/ProjectsApi.js +16 -8
- package/lib/ProjectsApi.js.map +1 -1
- package/lib/ViewsApi.d.ts +21 -0
- package/lib/ViewsApi.d.ts.map +1 -0
- package/lib/ViewsApi.js +41 -0
- package/lib/ViewsApi.js.map +1 -0
- package/lib/client.d.ts +3 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +4 -1
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/store/AnalyzeDocApi.d.ts +9 -11
- package/lib/store/AnalyzeDocApi.d.ts.map +1 -1
- package/lib/store/AnalyzeDocApi.js +12 -36
- package/lib/store/AnalyzeDocApi.js.map +1 -1
- package/lib/store/ViewsApi.d.ts +12 -0
- package/lib/store/ViewsApi.d.ts.map +1 -0
- package/lib/store/ViewsApi.js +17 -0
- package/lib/store/ViewsApi.js.map +1 -0
- package/lib/store/client.d.ts +2 -0
- package/lib/store/client.d.ts.map +1 -1
- package/lib/store/client.js +2 -0
- package/lib/store/client.js.map +1 -1
- package/lib/store/index.d.ts +1 -0
- package/lib/store/index.d.ts.map +1 -1
- package/lib/store/index.js +1 -0
- package/lib/store/index.js.map +1 -1
- package/lib/vertesia-client.js +5 -5
- package/lib/vertesia-client.js.map +1 -1
- package/package.json +8 -8
- package/src/AppsApi.test.ts +124 -0
- package/src/AppsApi.ts +81 -9
- package/src/AuditTrailApi.ts +10 -1
- package/src/ProjectsApi.test.ts +33 -0
- package/src/ProjectsApi.ts +19 -8
- package/src/ViewsApi.test.ts +36 -0
- package/src/ViewsApi.ts +60 -0
- package/src/client.ts +4 -1
- package/src/index.ts +1 -0
- package/src/store/AnalyzeDocApi.ts +16 -54
- package/src/store/ViewsApi.test.ts +33 -0
- package/src/store/ViewsApi.ts +20 -0
- package/src/store/client.ts +2 -0
- package/src/store/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/client",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.20260722.120446Z",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
],
|
|
12
12
|
"license": "Apache-2.0",
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@types/node": "^24.13.
|
|
15
|
-
"rolldown": "1.1.
|
|
14
|
+
"@types/node": "^24.13.3",
|
|
15
|
+
"rolldown": "1.1.5",
|
|
16
16
|
"typescript": "^6.0.3",
|
|
17
|
-
"vitest": "^4.1.
|
|
17
|
+
"vitest": "^4.1.10",
|
|
18
18
|
"@vertesia/tsconfig": "0.1.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"eventsource": "^4.1.0",
|
|
22
|
-
"@llumiverse/common": "1.5.0-dev.
|
|
23
|
-
"@vertesia/common": "1.5.0-dev.
|
|
24
|
-
"@vertesia/api-fetch-client": "1.5.0-dev.
|
|
22
|
+
"@llumiverse/common": "1.5.0-dev.20260722.112223Z",
|
|
23
|
+
"@vertesia/common": "1.5.0-dev.20260722.120446Z",
|
|
24
|
+
"@vertesia/api-fetch-client": "1.5.0-dev.20260722.120446Z"
|
|
25
25
|
},
|
|
26
26
|
"exports": {
|
|
27
27
|
".": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"ai",
|
|
49
49
|
"typescript"
|
|
50
50
|
],
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "203c30e5a8ddc583ac9f1acce0f5445eb38a9551",
|
|
52
52
|
"scripts": {
|
|
53
53
|
"lint": "biome lint src",
|
|
54
54
|
"clean:lib": "rimraf ./lib ./tsconfig.tsbuildinfo",
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { VertesiaClient } from './client.js';
|
|
3
|
+
|
|
4
|
+
describe('AppsApi', () => {
|
|
5
|
+
it('starts an in-place version rebuild without a caller-controlled payload', async () => {
|
|
6
|
+
const requests: Request[] = [];
|
|
7
|
+
const fetchMock = vi.fn(async () =>
|
|
8
|
+
Response.json({
|
|
9
|
+
workflow_id: 'workflow-1',
|
|
10
|
+
run_id: 'run-1',
|
|
11
|
+
app_id: 'sample-app',
|
|
12
|
+
version_id: 'version-1',
|
|
13
|
+
rebuild_version_record_id: 'record-1',
|
|
14
|
+
}),
|
|
15
|
+
);
|
|
16
|
+
const client = new VertesiaClient({
|
|
17
|
+
serverUrl: 'https://studio.example.com',
|
|
18
|
+
storeUrl: 'https://zeno.example.com',
|
|
19
|
+
fetch: fetchMock,
|
|
20
|
+
onRequest: (request) => requests.push(request),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const result = await client.apps.rebuildVersion('record-1');
|
|
24
|
+
|
|
25
|
+
expect(result.version_id).toBe('version-1');
|
|
26
|
+
expect(requests[0]?.method).toBe('POST');
|
|
27
|
+
expect(requests[0]?.url).toBe('https://studio.example.com/api/v1/apps/versions/record-1/rebuild');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('deletes a version through its dedicated endpoint', async () => {
|
|
31
|
+
const requests: Request[] = [];
|
|
32
|
+
const fetchMock = vi.fn(async () =>
|
|
33
|
+
Response.json({
|
|
34
|
+
id: 'record-1',
|
|
35
|
+
app_id: 'sample-app',
|
|
36
|
+
version_id: 'version-1',
|
|
37
|
+
deleted: true,
|
|
38
|
+
warnings: [],
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
const client = new VertesiaClient({
|
|
42
|
+
serverUrl: 'https://studio.example.com',
|
|
43
|
+
storeUrl: 'https://zeno.example.com',
|
|
44
|
+
fetch: fetchMock,
|
|
45
|
+
onRequest: (request) => requests.push(request),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const result = await client.apps.deleteVersion('record-1');
|
|
49
|
+
|
|
50
|
+
expect(result.deleted).toBe(true);
|
|
51
|
+
expect(requests[0]?.method).toBe('DELETE');
|
|
52
|
+
expect(requests[0]?.url).toBe('https://studio.example.com/api/v1/apps/versions/record-1');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('returns the original response bytes and content type', async () => {
|
|
56
|
+
const requests: Request[] = [];
|
|
57
|
+
const bytes = new Uint8Array([0, 255, 10, 42]);
|
|
58
|
+
const fetchMock = vi.fn(
|
|
59
|
+
async () =>
|
|
60
|
+
new Response(bytes, {
|
|
61
|
+
status: 200,
|
|
62
|
+
headers: { 'content-type': 'application/octet-stream' },
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
const client = new VertesiaClient({
|
|
66
|
+
serverUrl: 'https://studio.example.com',
|
|
67
|
+
storeUrl: 'https://zeno.example.com',
|
|
68
|
+
fetch: fetchMock,
|
|
69
|
+
onRequest: (request) => requests.push(request),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const response = await client.apps.getRepoFile('sample-app', 'docs/file.bin', { ref: 'feature/demo' });
|
|
73
|
+
|
|
74
|
+
expect(response.headers.get('content-type')).toBe('application/octet-stream');
|
|
75
|
+
expect(new Uint8Array(await response.arrayBuffer())).toEqual(bytes);
|
|
76
|
+
expect(requests[0]?.url).toBe(
|
|
77
|
+
'https://studio.example.com/api/v1/apps/sample-app/repo/file?path=docs%2Ffile.bin&ref=feature%2Fdemo',
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('uploads multiple documents as one multipart commit request', async () => {
|
|
82
|
+
const requests: Request[] = [];
|
|
83
|
+
const fetchMock = vi.fn(async () =>
|
|
84
|
+
Response.json({
|
|
85
|
+
ref: 'main',
|
|
86
|
+
previous_commit: '1'.repeat(40),
|
|
87
|
+
commit: '2'.repeat(40),
|
|
88
|
+
paths: ['docs/guide.md', 'docs/diagram.png'],
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
const client = new VertesiaClient({
|
|
92
|
+
serverUrl: 'https://studio.example.com',
|
|
93
|
+
storeUrl: 'https://zeno.example.com',
|
|
94
|
+
fetch: fetchMock,
|
|
95
|
+
onRequest: (request) => requests.push(request),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const result = await client.apps.commitRepoDocuments(
|
|
99
|
+
'sample-app',
|
|
100
|
+
[
|
|
101
|
+
{ path: 'docs/guide.md', content: new Blob(['# Guide']), fileName: 'guide.md' },
|
|
102
|
+
{ path: 'docs/diagram.png', content: new Blob([new Uint8Array([1, 2, 3])]), fileName: 'diagram.png' },
|
|
103
|
+
],
|
|
104
|
+
{ ref: 'main', expectedHead: '1'.repeat(40), message: 'Add docs' },
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
expect(result.commit).toBe('2'.repeat(40));
|
|
108
|
+
const request = requests[0];
|
|
109
|
+
expect(request?.url).toBe('https://studio.example.com/api/v1/apps/sample-app/repo/documents');
|
|
110
|
+
expect(request?.headers.get('content-type')).toContain('multipart/form-data; boundary=');
|
|
111
|
+
const form = await request?.formData();
|
|
112
|
+
expect(JSON.parse(String(form?.get('metadata')))).toEqual({
|
|
113
|
+
ref: 'main',
|
|
114
|
+
expected_head: '1'.repeat(40),
|
|
115
|
+
message: 'Add docs',
|
|
116
|
+
files: [
|
|
117
|
+
{ field: 'file_0', path: 'docs/guide.md' },
|
|
118
|
+
{ field: 'file_1', path: 'docs/diagram.png' },
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
expect((form?.get('file_0') as File).name).toBe('guide.md');
|
|
122
|
+
expect((form?.get('file_1') as File).size).toBe(3);
|
|
123
|
+
});
|
|
124
|
+
});
|
package/src/AppsApi.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ApiTopic, type ClientBase, type ServerError } from '@vertesia/api-fetch-client';
|
|
2
2
|
import type {
|
|
3
|
-
ActivateAppVersionResponse,
|
|
4
3
|
AppBuildProgress,
|
|
5
4
|
AppDeleteSummary,
|
|
6
5
|
AppInspectionResult,
|
|
@@ -13,17 +12,23 @@ import type {
|
|
|
13
12
|
AppManifestData,
|
|
14
13
|
AppPackage,
|
|
15
14
|
AppPackageScope,
|
|
16
|
-
|
|
15
|
+
AppRepoCommits,
|
|
16
|
+
AppRepoDocumentCommit,
|
|
17
17
|
AppRepoRefs,
|
|
18
18
|
AppRepoTree,
|
|
19
|
+
AppScaffoldProgress,
|
|
19
20
|
AppToolCollection,
|
|
20
21
|
AppVersionListQuery,
|
|
21
22
|
AppVersionRecord,
|
|
22
23
|
CountResult,
|
|
24
|
+
DeleteAppVersionResponse,
|
|
23
25
|
ProjectRef,
|
|
26
|
+
PromoteAppVersionResponse,
|
|
24
27
|
RequireAtLeastOne,
|
|
25
28
|
StartAppBuildRequest,
|
|
26
29
|
StartAppBuildResponse,
|
|
30
|
+
StartAppScaffoldRequest,
|
|
31
|
+
StartAppScaffoldResponse,
|
|
27
32
|
UpdateAppInstallationToolAllowlistPayload,
|
|
28
33
|
UpsertAppVersionRequest,
|
|
29
34
|
ValidateUrlRequest,
|
|
@@ -83,8 +88,16 @@ export default class AppsApi extends ApiTopic {
|
|
|
83
88
|
return this.get(`/versions/${recordId}`);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
return this.post(`/versions/${recordId}/
|
|
91
|
+
promoteVersion(recordId: string): Promise<PromoteAppVersionResponse> {
|
|
92
|
+
return this.post(`/versions/${recordId}/promote`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
rebuildVersion(recordId: string): Promise<StartAppBuildResponse> {
|
|
96
|
+
return this.post(`/versions/${recordId}/rebuild`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
deleteVersion(recordId: string): Promise<DeleteAppVersionResponse> {
|
|
100
|
+
return this.del(`/versions/${recordId}`);
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
startBuild(appIdOrRecordId: string, payload: StartAppBuildRequest): Promise<StartAppBuildResponse> {
|
|
@@ -97,6 +110,14 @@ export default class AppsApi extends ApiTopic {
|
|
|
97
110
|
);
|
|
98
111
|
}
|
|
99
112
|
|
|
113
|
+
startScaffold(payload: StartAppScaffoldRequest): Promise<StartAppScaffoldResponse> {
|
|
114
|
+
return this.post('/scaffolds', { payload });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
getScaffoldProgress(workflowId: string, runId: string): Promise<AppScaffoldProgress> {
|
|
118
|
+
return this.get(`/scaffolds/${encodeURIComponent(workflowId)}/${encodeURIComponent(runId)}/progress`);
|
|
119
|
+
}
|
|
120
|
+
|
|
100
121
|
/**
|
|
101
122
|
* Get the list if tools provided by the given app.
|
|
102
123
|
* @param appId
|
|
@@ -128,12 +149,63 @@ export default class AppsApi extends ApiTopic {
|
|
|
128
149
|
}
|
|
129
150
|
|
|
130
151
|
/**
|
|
131
|
-
* Read the
|
|
132
|
-
* branch unless `ref` is given).
|
|
152
|
+
* Read the original bytes of a single file in the app's git repository (default
|
|
153
|
+
* branch unless `ref` is given). The caller decides whether to consume the
|
|
154
|
+
* successful response as text, a Blob, or an ArrayBuffer.
|
|
133
155
|
*/
|
|
134
|
-
getRepoFile(appIdOrName: string, path: string, options?: { ref?: string }): Promise<
|
|
135
|
-
|
|
156
|
+
async getRepoFile(appIdOrName: string, path: string, options?: { ref?: string }): Promise<Response> {
|
|
157
|
+
const endpoint = `/${encodeURIComponent(appIdOrName)}/repo/file`;
|
|
158
|
+
const response = await this.get<Response>(endpoint, {
|
|
136
159
|
query: { path, ref: options?.ref },
|
|
160
|
+
reader: (rawResponse) => rawResponse,
|
|
161
|
+
});
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
const payload = await this.readJSONPayload(response);
|
|
164
|
+
const request = await this.createRequest(response.url || this.getUrl(endpoint), { method: 'GET' });
|
|
165
|
+
throw this.createServerError(request, response, payload);
|
|
166
|
+
}
|
|
167
|
+
return response;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Commit one or more files under the repository's allowed document roots.
|
|
172
|
+
* The Git service currently permits only `docs/`. All files are written in
|
|
173
|
+
* one commit and `expectedHead` prevents overwriting a concurrent push.
|
|
174
|
+
*/
|
|
175
|
+
commitRepoDocuments(
|
|
176
|
+
appIdOrName: string,
|
|
177
|
+
files: Array<{ path: string; content: Blob; fileName?: string }>,
|
|
178
|
+
options: { ref: string; expectedHead: string; message?: string },
|
|
179
|
+
): Promise<AppRepoDocumentCommit> {
|
|
180
|
+
const form = new FormData();
|
|
181
|
+
const metadata = {
|
|
182
|
+
ref: options.ref,
|
|
183
|
+
expected_head: options.expectedHead,
|
|
184
|
+
message: options.message || 'Upload documentation',
|
|
185
|
+
files: files.map((file, index) => ({ field: `file_${index}`, path: file.path })),
|
|
186
|
+
};
|
|
187
|
+
form.append('metadata', JSON.stringify(metadata));
|
|
188
|
+
files.forEach((file, index) => {
|
|
189
|
+
form.append(`file_${index}`, file.content, file.fileName || file.path.split('/').pop() || 'document');
|
|
190
|
+
});
|
|
191
|
+
return this.post(`/${encodeURIComponent(appIdOrName)}/repo/documents`, {
|
|
192
|
+
payload: form,
|
|
193
|
+
jsonPayload: false,
|
|
194
|
+
timeoutMs: 120_000,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* List repository commits newest first, optionally filtered to commits that changed a file.
|
|
200
|
+
* History starts at the default branch unless a branch, tag, or commit SHA is supplied as `ref`.
|
|
201
|
+
*/
|
|
202
|
+
getRepoCommits(
|
|
203
|
+
appIdOrName: string,
|
|
204
|
+
path?: string,
|
|
205
|
+
options?: { ref?: string; limit?: number; cursor?: string },
|
|
206
|
+
): Promise<AppRepoCommits> {
|
|
207
|
+
return this.get(`/${encodeURIComponent(appIdOrName)}/repo/commits`, {
|
|
208
|
+
query: { path, ref: options?.ref, limit: options?.limit, cursor: options?.cursor },
|
|
137
209
|
});
|
|
138
210
|
}
|
|
139
211
|
|
|
@@ -147,7 +219,7 @@ export default class AppsApi extends ApiTopic {
|
|
|
147
219
|
}
|
|
148
220
|
|
|
149
221
|
/**
|
|
150
|
-
* Get the
|
|
222
|
+
* Get the promoted package an app exposes, filtered by scope. App-owned (in-code) artifacts are
|
|
151
223
|
* package-resolved (no per-id route), so this is how a client reads the full definition — type
|
|
152
224
|
* schema, interaction prompt, process definition, dashboard spec — to visualize an exposed id.
|
|
153
225
|
*/
|
package/src/AuditTrailApi.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AuditAggregationQuery,
|
|
4
|
+
AuditAggregationResponse,
|
|
5
|
+
AuditTrailQuery,
|
|
6
|
+
AuditTrailResponse,
|
|
7
|
+
} from '@vertesia/common';
|
|
3
8
|
|
|
4
9
|
export default class AuditTrailApi extends ApiTopic {
|
|
5
10
|
constructor(parent: ClientBase) {
|
|
@@ -24,4 +29,8 @@ export default class AuditTrailApi extends ApiTopic {
|
|
|
24
29
|
const qs = params.toString();
|
|
25
30
|
return this.get(`/${qs ? `?${qs}` : ''}`);
|
|
26
31
|
}
|
|
32
|
+
|
|
33
|
+
aggregate(query: AuditAggregationQuery): Promise<AuditAggregationResponse> {
|
|
34
|
+
return this.post('/aggregate', { payload: query });
|
|
35
|
+
}
|
|
27
36
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { VertesiaClient } from './client.js';
|
|
3
|
+
|
|
4
|
+
describe('ProjectsApi', () => {
|
|
5
|
+
it('encodes app View ids as one path segment', async () => {
|
|
6
|
+
const requests: Request[] = [];
|
|
7
|
+
const fetchMock = vi.fn(async () => {
|
|
8
|
+
return new Response(
|
|
9
|
+
JSON.stringify({
|
|
10
|
+
id: 'app:content:document-lib',
|
|
11
|
+
name: 'document-lib',
|
|
12
|
+
definition: { name: 'Document library' },
|
|
13
|
+
}),
|
|
14
|
+
{
|
|
15
|
+
status: 200,
|
|
16
|
+
headers: { 'content-type': 'application/json' },
|
|
17
|
+
},
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
const client = new VertesiaClient({
|
|
21
|
+
serverUrl: 'https://api.example.com',
|
|
22
|
+
storeUrl: 'https://api.example.com',
|
|
23
|
+
fetch: fetchMock,
|
|
24
|
+
onRequest: (request) => requests.push(request),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
await client.projects.getAppView('project/with/slash', 'app:content:../../environments');
|
|
28
|
+
|
|
29
|
+
expect(requests[0]?.url).toBe(
|
|
30
|
+
'https://api.example.com/api/v1/projects/project%2Fwith%2Fslash/app-views/app%3Acontent%3A..%2F..%2Fenvironments',
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
});
|
package/src/ProjectsApi.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
ICreateProjectPayload,
|
|
8
8
|
InCodeProcessDefinition,
|
|
9
9
|
InCodeTypeDefinition,
|
|
10
|
+
InCodeViewDefinition,
|
|
10
11
|
Project,
|
|
11
12
|
ProjectConfiguration,
|
|
12
13
|
ProjectIntegrationConfigRequest,
|
|
@@ -80,44 +81,54 @@ export default class ProjectsApi extends ApiTopic {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
listAppContentTypes(projectId: string, tag?: string): Promise<InCodeTypeDefinition[]> {
|
|
83
|
-
return this.get(`/${projectId}/app-types`, {
|
|
84
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-types`, {
|
|
84
85
|
query: { tag },
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
getAppContentType(projectId: string, typeId: string): Promise<InCodeTypeDefinition> {
|
|
89
|
-
return this.get(`/${projectId}/app-types/${typeId}`);
|
|
90
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-types/${encodeURIComponent(typeId)}`);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
listAppProcesses(projectId: string, tag?: string): Promise<InCodeProcessDefinition[]> {
|
|
93
|
-
return this.get(`/${projectId}/app-processes`, {
|
|
94
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-processes`, {
|
|
94
95
|
query: { tag },
|
|
95
96
|
});
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
getAppProcess(projectId: string, processId: string): Promise<InCodeProcessDefinition> {
|
|
99
|
-
return this.get(`/${projectId}/app-processes/${processId}`);
|
|
100
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-processes/${encodeURIComponent(processId)}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
listAppViews(projectId: string, tag?: string): Promise<InCodeViewDefinition[]> {
|
|
104
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-views`, {
|
|
105
|
+
query: { tag },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
getAppView(projectId: string, viewId: string): Promise<InCodeViewDefinition> {
|
|
110
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-views/${encodeURIComponent(viewId)}`);
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
listAppRenderingTemplates(projectId: string, tag?: string): Promise<RenderingTemplateDefinitionRef[]> {
|
|
103
|
-
return this.get(`/${projectId}/app-templates`, {
|
|
114
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-templates`, {
|
|
104
115
|
query: { tag },
|
|
105
116
|
});
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
getAppRenderingTemplate(projectId: string, templateUri: string): Promise<RenderingTemplateDefinition> {
|
|
109
|
-
return this.get(`/${projectId}/app-templates/${templateUri}`);
|
|
120
|
+
return this.get(`/${encodeURIComponent(projectId)}/app-templates/${encodeURIComponent(templateUri)}`);
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
getCompositeAppConfiguration(projectId: string): Promise<CompositeAppConfig> {
|
|
113
|
-
return this.get(`/${projectId}/composite-app`);
|
|
124
|
+
return this.get(`/${encodeURIComponent(projectId)}/composite-app`);
|
|
114
125
|
}
|
|
115
126
|
|
|
116
127
|
updateCompositeAppConfiguration(
|
|
117
128
|
projectId: string,
|
|
118
129
|
payload: CompositeAppConfigPayload,
|
|
119
130
|
): Promise<CompositeAppConfig> {
|
|
120
|
-
return this.put(`/${projectId}/composite-app`, {
|
|
131
|
+
return this.put(`/${encodeURIComponent(projectId)}/composite-app`, {
|
|
121
132
|
payload,
|
|
122
133
|
});
|
|
123
134
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { VertesiaClient } from './client.js';
|
|
3
|
+
|
|
4
|
+
describe('ViewsApi', () => {
|
|
5
|
+
it('keeps CRUD on Studio and proxies execution to Zeno', async () => {
|
|
6
|
+
const requests: Request[] = [];
|
|
7
|
+
const fetchMock = vi.fn(async () => {
|
|
8
|
+
return new Response(JSON.stringify({}), {
|
|
9
|
+
status: 200,
|
|
10
|
+
headers: { 'content-type': 'application/json' },
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
const client = new VertesiaClient({
|
|
14
|
+
serverUrl: 'https://studio.example.com',
|
|
15
|
+
storeUrl: 'https://zeno.example.com',
|
|
16
|
+
fetch: fetchMock,
|
|
17
|
+
onRequest: (request) => requests.push(request),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await client.views.retrieve('document-library');
|
|
21
|
+
await client.views.execute('document-library');
|
|
22
|
+
await client.views.preview({
|
|
23
|
+
configuration: {
|
|
24
|
+
name: 'Document library',
|
|
25
|
+
description: 'Browse documents.',
|
|
26
|
+
scope: {},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(requests.map((request) => request.url)).toEqual([
|
|
31
|
+
'https://studio.example.com/api/v1/views/document-library',
|
|
32
|
+
'https://zeno.example.com/api/v1/view-executions/document-library/execute',
|
|
33
|
+
'https://zeno.example.com/api/v1/view-executions/preview',
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
});
|
package/src/ViewsApi.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
|
+
import type {
|
|
3
|
+
CreateViewExperienceRequest,
|
|
4
|
+
DeleteByIdResult,
|
|
5
|
+
ExecuteViewRequest,
|
|
6
|
+
PreviewViewExperienceRequest,
|
|
7
|
+
UpdateViewExperienceRequest,
|
|
8
|
+
ViewExecutionResult,
|
|
9
|
+
ViewExperience,
|
|
10
|
+
ViewExperienceListQuery,
|
|
11
|
+
} from '@vertesia/common';
|
|
12
|
+
import type { StoreViewsApi } from './store/ViewsApi.js';
|
|
13
|
+
|
|
14
|
+
export default class ViewsApi extends ApiTopic {
|
|
15
|
+
constructor(
|
|
16
|
+
parent: ClientBase,
|
|
17
|
+
private readonly executionApi: StoreViewsApi,
|
|
18
|
+
) {
|
|
19
|
+
super(parent, '/api/v1/views');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
list(query: ViewExperienceListQuery = {}): Promise<ViewExperience[]> {
|
|
23
|
+
return this.get('/', {
|
|
24
|
+
query: {
|
|
25
|
+
limit: query.limit,
|
|
26
|
+
offset: query.offset,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
create(payload: CreateViewExperienceRequest): Promise<ViewExperience> {
|
|
32
|
+
return this.post('/', { payload });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
retrieve(id: string): Promise<ViewExperience> {
|
|
36
|
+
return this.get(`/${encodeURIComponent(id)}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
update(id: string, payload: UpdateViewExperienceRequest): Promise<ViewExperience> {
|
|
40
|
+
return this.put(`/${encodeURIComponent(id)}`, { payload });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
delete(id: string): Promise<DeleteByIdResult> {
|
|
44
|
+
return this.del(`/${encodeURIComponent(id)}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Execute a persisted or app-contributed View through the content service.
|
|
49
|
+
*/
|
|
50
|
+
execute(id: string, payload: ExecuteViewRequest = {}): Promise<ViewExecutionResult> {
|
|
51
|
+
return this.executionApi.execute(id, payload);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Validate and execute an unsaved View through the content service.
|
|
56
|
+
*/
|
|
57
|
+
preview(payload: PreviewViewExperienceRequest): Promise<ViewExecutionResult> {
|
|
58
|
+
return this.executionApi.preview(payload);
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -28,6 +28,7 @@ import { VERSION, VERSION_HEADER } from './store/version.js';
|
|
|
28
28
|
import ToolsApi from './ToolsApi.js';
|
|
29
29
|
import TrainingApi from './TrainingApi.js';
|
|
30
30
|
import UsersApi from './UsersApi.js';
|
|
31
|
+
import ViewsApi from './ViewsApi.js';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* 1 min threshold constant in ms
|
|
@@ -206,6 +207,7 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
206
207
|
timeout: opts.timeout,
|
|
207
208
|
fetch: opts.fetch,
|
|
208
209
|
});
|
|
210
|
+
this.views = new ViewsApi(this, this.store.views);
|
|
209
211
|
|
|
210
212
|
if (opts.retryPolicy) {
|
|
211
213
|
this.withRetryPolicy(opts.retryPolicy);
|
|
@@ -243,7 +245,7 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
243
245
|
/**
|
|
244
246
|
* Pin the app version this client's requests resolve against. A generated app's UI sets this from
|
|
245
247
|
* its build-time `VITE_APP_VERSION` so studio/zeno resolve its `app:<app>:…` refs against that
|
|
246
|
-
*
|
|
248
|
+
* exact built version instead of the promoted version. Pass null/empty to clear (→ promoted).
|
|
247
249
|
*/
|
|
248
250
|
withAppVersion(version: string | null | undefined) {
|
|
249
251
|
if (!version) {
|
|
@@ -425,6 +427,7 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
425
427
|
apps = new AppsApi(this);
|
|
426
428
|
tools = new ToolsApi(this);
|
|
427
429
|
quota = new QuotaApi(this);
|
|
430
|
+
views: ViewsApi;
|
|
428
431
|
}
|
|
429
432
|
|
|
430
433
|
function isApiKey(apiKey: string) {
|
package/src/index.ts
CHANGED
|
@@ -18,4 +18,5 @@ export type { ComputeRunFacetsResponse, FilterOption } from './RunsApi.js';
|
|
|
18
18
|
export { default as SecretsApi } from './SecretsApi.js';
|
|
19
19
|
export * from './StreamSource.js';
|
|
20
20
|
export * from './store/index.js';
|
|
21
|
+
export { default as ViewsApi } from './ViewsApi.js';
|
|
21
22
|
export type { AsyncExecutionResult };
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import { ApiTopic, type ClientBase
|
|
1
|
+
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
2
|
import type {
|
|
3
|
-
AdaptedTable,
|
|
4
|
-
AdaptTablesRequest,
|
|
5
3
|
DocAnalyzeRunStatusResponse,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
ExportTableFormats,
|
|
11
|
-
GetAdaptedTablesRequestQuery,
|
|
12
|
-
PdfToRichtextOptions,
|
|
13
|
-
WorkflowRunStatus,
|
|
4
|
+
DocumentPrepOptions,
|
|
5
|
+
GroundedAssistantResponse,
|
|
6
|
+
GroundedExtractionRequest,
|
|
7
|
+
GroundedExtractionResultResponse,
|
|
14
8
|
} from '@vertesia/common';
|
|
15
9
|
|
|
16
10
|
export class AnalyzeDocApi extends ApiTopic {
|
|
@@ -21,7 +15,7 @@ export class AnalyzeDocApi extends ApiTopic {
|
|
|
21
15
|
super(parent, `/${objectId}/analyze`);
|
|
22
16
|
}
|
|
23
17
|
|
|
24
|
-
async start(payload:
|
|
18
|
+
async start(payload: DocumentPrepOptions): Promise<DocAnalyzeRunStatusResponse> {
|
|
25
19
|
return this.post('/', { payload });
|
|
26
20
|
}
|
|
27
21
|
|
|
@@ -29,51 +23,19 @@ export class AnalyzeDocApi extends ApiTopic {
|
|
|
29
23
|
return this.get('/status');
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
async
|
|
33
|
-
return this.
|
|
26
|
+
async startGroundedExtraction(payload?: GroundedExtractionRequest): Promise<DocAnalyzeRunStatusResponse> {
|
|
27
|
+
return this.post('/grounded', { payload: payload ?? {} });
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
async
|
|
37
|
-
return this.
|
|
30
|
+
async getGroundedExtractionResult(): Promise<GroundedExtractionResultResponse> {
|
|
31
|
+
return this.get('/grounded/result');
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// Build query parameters
|
|
47
|
-
const queryParams: NonNullable<IRequestParams['query']> = {};
|
|
48
|
-
if (query?.format) queryParams.format = query.format;
|
|
49
|
-
if (query?.raw !== undefined) queryParams.raw = query.raw;
|
|
50
|
-
|
|
51
|
-
// If format is CSV, set response type to text to avoid automatic JSON parsing
|
|
52
|
-
const options: IRequestParams & { responseType?: 'text' } = { query: queryParams };
|
|
53
|
-
if (query?.format === 'csv') {
|
|
54
|
-
options.responseType = 'text';
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return this.get(path, options);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async getXml(): Promise<string> {
|
|
61
|
-
return this.get('/xml');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async getTables(format?: ExportTableFormats): Promise<DocTableCsv[] | DocTableJson[]> {
|
|
65
|
-
const options: IRequestParams = {};
|
|
66
|
-
if (format) {
|
|
67
|
-
options.query = { format: format };
|
|
68
|
-
}
|
|
69
|
-
return this.get('/tables', options);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async getImages(): Promise<DocImage[]> {
|
|
73
|
-
return this.get('/images');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async getAnnotated(): Promise<{ url: string }> {
|
|
77
|
-
return this.get('/annotated');
|
|
34
|
+
/**
|
|
35
|
+
* Launch the interactive grounded extraction assistant for this document.
|
|
36
|
+
* Returns the agent_run_id used to stream/render the conversation.
|
|
37
|
+
*/
|
|
38
|
+
async startGroundedAssistant(payload?: GroundedExtractionRequest): Promise<GroundedAssistantResponse> {
|
|
39
|
+
return this.post('/grounded/assistant', { payload: payload ?? {} });
|
|
78
40
|
}
|
|
79
41
|
}
|