@vertesia/client 1.5.0-dev.20260722.120446Z → 1.5.0-dev.20260725.083715Z
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 +7 -1
- package/lib/AppsApi.d.ts.map +1 -1
- package/lib/AppsApi.js +12 -0
- package/lib/AppsApi.js.map +1 -1
- package/lib/store/AgentsApi.d.ts +5 -1
- package/lib/store/AgentsApi.d.ts.map +1 -1
- package/lib/store/AgentsApi.js +8 -0
- package/lib/store/AgentsApi.js.map +1 -1
- package/lib/store/FilesApi.d.ts.map +1 -1
- package/lib/store/FilesApi.js +10 -4
- package/lib/store/FilesApi.js.map +1 -1
- package/lib/store/ObjectsApi.d.ts.map +1 -1
- package/lib/store/ObjectsApi.js +3 -2
- package/lib/store/ObjectsApi.js.map +1 -1
- package/lib/store/uploadMimeType.d.ts +3 -0
- package/lib/store/uploadMimeType.d.ts.map +1 -0
- package/lib/store/uploadMimeType.js +11 -0
- package/lib/store/uploadMimeType.js.map +1 -0
- package/lib/vertesia-client.js +3 -3
- package/lib/vertesia-client.js.map +1 -1
- package/package.json +6 -6
- package/src/AppsApi.test.ts +14 -6
- package/src/AppsApi.ts +19 -0
- package/src/store/AgentsApi.ts +17 -0
- package/src/store/FilesApi.ts +10 -4
- package/src/store/ObjectsApi.ts +3 -2
- package/src/store/uploadMimeType.test.ts +22 -0
- package/src/store/uploadMimeType.ts +16 -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.20260725.083715Z",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
"license": "Apache-2.0",
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@types/node": "^24.13.3",
|
|
15
|
-
"rolldown": "1.
|
|
15
|
+
"rolldown": "1.2.0",
|
|
16
16
|
"typescript": "^6.0.3",
|
|
17
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/
|
|
24
|
-
"@vertesia/
|
|
22
|
+
"@llumiverse/common": "1.5.0-dev.20260725.065646Z",
|
|
23
|
+
"@vertesia/api-fetch-client": "1.5.0-dev.20260725.083715Z",
|
|
24
|
+
"@vertesia/common": "1.5.0-dev.20260725.083715Z"
|
|
25
25
|
},
|
|
26
26
|
"exports": {
|
|
27
27
|
".": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"ai",
|
|
49
49
|
"typescript"
|
|
50
50
|
],
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "57bcc2f27dd17b3387f27c18e89329c4c37f98ac",
|
|
52
52
|
"scripts": {
|
|
53
53
|
"lint": "biome lint src",
|
|
54
54
|
"clean:lib": "rimraf ./lib ./tsconfig.tsbuildinfo",
|
package/src/AppsApi.test.ts
CHANGED
|
@@ -106,10 +106,13 @@ describe('AppsApi', () => {
|
|
|
106
106
|
|
|
107
107
|
expect(result.commit).toBe('2'.repeat(40));
|
|
108
108
|
const request = requests[0];
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
expect(
|
|
109
|
+
if (!request) {
|
|
110
|
+
throw new Error('Expected a multipart document request');
|
|
111
|
+
}
|
|
112
|
+
expect(request.url).toBe('https://studio.example.com/api/v1/apps/sample-app/repo/documents');
|
|
113
|
+
expect(request.headers.get('content-type')).toContain('multipart/form-data; boundary=');
|
|
114
|
+
const form = await request.formData();
|
|
115
|
+
expect(JSON.parse(String(form.get('metadata')))).toEqual({
|
|
113
116
|
ref: 'main',
|
|
114
117
|
expected_head: '1'.repeat(40),
|
|
115
118
|
message: 'Add docs',
|
|
@@ -118,7 +121,12 @@ describe('AppsApi', () => {
|
|
|
118
121
|
{ field: 'file_1', path: 'docs/diagram.png' },
|
|
119
122
|
],
|
|
120
123
|
});
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
const guideFile = form.get('file_0');
|
|
125
|
+
const diagramFile = form.get('file_1');
|
|
126
|
+
if (!(guideFile instanceof File) || !(diagramFile instanceof File)) {
|
|
127
|
+
throw new Error('Expected multipart file entries');
|
|
128
|
+
}
|
|
129
|
+
expect(guideFile.name).toBe('guide.md');
|
|
130
|
+
expect(diagramFile.size).toBe(3);
|
|
123
131
|
});
|
|
124
132
|
});
|
package/src/AppsApi.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { ApiTopic, type ClientBase, type ServerError } from '@vertesia/api-fetch
|
|
|
2
2
|
import type {
|
|
3
3
|
AppBuildProgress,
|
|
4
4
|
AppDeleteSummary,
|
|
5
|
+
AppDevelopmentTaskDetails,
|
|
6
|
+
AppDevelopmentTaskList,
|
|
5
7
|
AppInspectionResult,
|
|
6
8
|
AppInstallation,
|
|
7
9
|
AppInstallationKind,
|
|
@@ -12,6 +14,7 @@ import type {
|
|
|
12
14
|
AppManifestData,
|
|
13
15
|
AppPackage,
|
|
14
16
|
AppPackageScope,
|
|
17
|
+
AppRepoBranch,
|
|
15
18
|
AppRepoCommits,
|
|
16
19
|
AppRepoDocumentCommit,
|
|
17
20
|
AppRepoRefs,
|
|
@@ -21,6 +24,7 @@ import type {
|
|
|
21
24
|
AppVersionListQuery,
|
|
22
25
|
AppVersionRecord,
|
|
23
26
|
CountResult,
|
|
27
|
+
CreateAppRepoBranchRequest,
|
|
24
28
|
DeleteAppVersionResponse,
|
|
25
29
|
ProjectRef,
|
|
26
30
|
PromoteAppVersionResponse,
|
|
@@ -218,6 +222,21 @@ export default class AppsApi extends ApiTopic {
|
|
|
218
222
|
return this.get(`/${encodeURIComponent(appIdOrName)}/repo/refs`);
|
|
219
223
|
}
|
|
220
224
|
|
|
225
|
+
/** List mutable development tasks represented by `agent/*` repository branches. */
|
|
226
|
+
listDevelopmentTasks(appIdOrName: string): Promise<AppDevelopmentTaskList> {
|
|
227
|
+
return this.get(`/${encodeURIComponent(appIdOrName)}/development-tasks`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Get a development task and its latest parent Studio Assistant run, when started. */
|
|
231
|
+
getDevelopmentTask(appIdOrName: string, taskId: string): Promise<AppDevelopmentTaskDetails> {
|
|
232
|
+
return this.get(`/${encodeURIComponent(appIdOrName)}/development-tasks/${encodeURIComponent(taskId)}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Create a repository branch from an existing branch, tag, or commit. */
|
|
236
|
+
createRepoBranch(appIdOrName: string, payload: CreateAppRepoBranchRequest): Promise<AppRepoBranch> {
|
|
237
|
+
return this.post(`/${encodeURIComponent(appIdOrName)}/repo/branches`, { payload });
|
|
238
|
+
}
|
|
239
|
+
|
|
221
240
|
/**
|
|
222
241
|
* Get the promoted package an app exposes, filtered by scope. App-owned (in-code) artifacts are
|
|
223
242
|
* package-resolved (no per-id route), so this is how a client reads the full definition — type
|
package/src/store/AgentsApi.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
2
|
import {
|
|
3
3
|
type ActiveWorkstreamsQueryResult,
|
|
4
|
+
type AgentArtifactContentResponse,
|
|
4
5
|
type AgentArtifactUrlResponse,
|
|
5
6
|
type AgentEvent,
|
|
6
7
|
type AgentMessage,
|
|
@@ -41,6 +42,8 @@ import {
|
|
|
41
42
|
type ToolParameterAnalyticsResponse,
|
|
42
43
|
type TopPrincipalsAnalyticsResponse,
|
|
43
44
|
toAgentMessage,
|
|
45
|
+
type UpdateAgentArtifactContentPayload,
|
|
46
|
+
type UpdateAgentArtifactContentResponse,
|
|
44
47
|
type UpdateAgentRunStatusPayload,
|
|
45
48
|
type WorkflowAnalyticsFilterOptionsResponse,
|
|
46
49
|
type WorkflowAnalyticsSummaryQuery,
|
|
@@ -734,6 +737,20 @@ export class AgentsApi extends ApiTopic {
|
|
|
734
737
|
return this.get(`/${id}/artifacts`, { query });
|
|
735
738
|
}
|
|
736
739
|
|
|
740
|
+
/** Read a text artifact together with its conditional-write generation token. */
|
|
741
|
+
getArtifactContent(id: string, path: string): Promise<AgentArtifactContentResponse> {
|
|
742
|
+
return this.get(`/${id}/artifact-content/${path}`);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/** Conditionally replace the text content of an agent artifact. */
|
|
746
|
+
updateArtifactContent(
|
|
747
|
+
id: string,
|
|
748
|
+
path: string,
|
|
749
|
+
payload: UpdateAgentArtifactContentPayload,
|
|
750
|
+
): Promise<UpdateAgentArtifactContentResponse> {
|
|
751
|
+
return this.put(`/${id}/artifact-content/${path}`, { payload });
|
|
752
|
+
}
|
|
753
|
+
|
|
737
754
|
/**
|
|
738
755
|
* Get a signed download URL for an artifact.
|
|
739
756
|
*/
|
package/src/store/FilesApi.ts
CHANGED
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
} from '@vertesia/common';
|
|
18
18
|
import { StreamSource } from '../StreamSource.js';
|
|
19
19
|
import { fetchSignedUrl } from './signed-url.js';
|
|
20
|
+
import { getUploadMimeTypeHint, resolveUploadMimeType } from './uploadMimeType.js';
|
|
20
21
|
|
|
21
22
|
export const MEMORIES_PREFIX = 'memories';
|
|
22
23
|
export const ARTIFACTS_PREFIX = 'agents';
|
|
@@ -137,7 +138,7 @@ export class FilesApi extends ApiTopic {
|
|
|
137
138
|
): Promise<{ source: string; name: string; type?: string; etag?: string }[]> {
|
|
138
139
|
const fileDescriptors = sources.map((s) => ({
|
|
139
140
|
name: s.name,
|
|
140
|
-
mime_type: s.type,
|
|
141
|
+
mime_type: getUploadMimeTypeHint(s.type),
|
|
141
142
|
id: s instanceof StreamSource ? s.id : undefined,
|
|
142
143
|
}));
|
|
143
144
|
|
|
@@ -153,7 +154,7 @@ export class FilesApi extends ApiTopic {
|
|
|
153
154
|
const idx = i + j;
|
|
154
155
|
const { url, id, mime_type } = files[idx];
|
|
155
156
|
const isStream = source instanceof StreamSource;
|
|
156
|
-
const sourceMimeType = source.type
|
|
157
|
+
const sourceMimeType = resolveUploadMimeType(source.type, mime_type);
|
|
157
158
|
|
|
158
159
|
const res = await fetchSignedUrl(url, {
|
|
159
160
|
method: 'PUT',
|
|
@@ -193,13 +194,18 @@ export class FilesApi extends ApiTopic {
|
|
|
193
194
|
*/
|
|
194
195
|
async uploadFileWithPath(source: StreamSource | File): Promise<{ id: string; path: string }> {
|
|
195
196
|
const isStream = source instanceof StreamSource;
|
|
196
|
-
const { url, id, path } = await this.getUploadUrl(
|
|
197
|
+
const { url, id, path, mime_type } = await this.getUploadUrl({
|
|
198
|
+
id: isStream ? source.id : undefined,
|
|
199
|
+
name: source.name,
|
|
200
|
+
mime_type: getUploadMimeTypeHint(source.type),
|
|
201
|
+
});
|
|
202
|
+
const sourceMimeType = resolveUploadMimeType(source.type, mime_type) || 'application/gzip';
|
|
197
203
|
|
|
198
204
|
const res = await fetchSignedUrl(url, {
|
|
199
205
|
method: 'PUT',
|
|
200
206
|
body: isStream ? source.stream : source,
|
|
201
207
|
headers: {
|
|
202
|
-
'Content-Type':
|
|
208
|
+
'Content-Type': sourceMimeType,
|
|
203
209
|
},
|
|
204
210
|
}).catch((err) => {
|
|
205
211
|
console.error('Failed to upload file', { err, url, id, path });
|
package/src/store/ObjectsApi.ts
CHANGED
|
@@ -56,6 +56,7 @@ import { StreamSource } from '../StreamSource.js';
|
|
|
56
56
|
import { AnalyzeDocApi } from './AnalyzeDocApi.js';
|
|
57
57
|
import type { ZenoClient } from './client.js';
|
|
58
58
|
import { fetchSignedUrl } from './signed-url.js';
|
|
59
|
+
import { getUploadMimeTypeHint, resolveUploadMimeType } from './uploadMimeType.js';
|
|
59
60
|
|
|
60
61
|
type ContentObjectWritePayload = Omit<CreateContentObjectPayload, 'content'> & {
|
|
61
62
|
content?: ContentSource | File | StreamSource;
|
|
@@ -259,9 +260,9 @@ export class ObjectsApi extends ApiTopic {
|
|
|
259
260
|
const { url, id, mime_type } = await this.getUploadUrl({
|
|
260
261
|
id: isStream ? source.id : undefined,
|
|
261
262
|
name: source.name,
|
|
262
|
-
mime_type: source.type,
|
|
263
|
+
mime_type: getUploadMimeTypeHint(source.type),
|
|
263
264
|
});
|
|
264
|
-
const sourceMimeType = source.type
|
|
265
|
+
const sourceMimeType = resolveUploadMimeType(source.type, mime_type);
|
|
265
266
|
|
|
266
267
|
// upload the file content to the signed URL
|
|
267
268
|
const res = await fetchSignedUrl(url, {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getUploadMimeTypeHint, resolveUploadMimeType } from './uploadMimeType.js';
|
|
3
|
+
|
|
4
|
+
describe('upload MIME type resolution', () => {
|
|
5
|
+
it('keeps a specific browser-provided content type', () => {
|
|
6
|
+
expect(getUploadMimeTypeHint('text/plain')).toBe('text/plain');
|
|
7
|
+
expect(resolveUploadMimeType('text/plain', 'text/markdown')).toBe('text/plain');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('uses filename inference when the browser reports generic binary content', () => {
|
|
11
|
+
expect(getUploadMimeTypeHint('application/octet-stream')).toBeUndefined();
|
|
12
|
+
expect(resolveUploadMimeType('application/octet-stream', 'text/markdown')).toBe('text/markdown');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('uses filename inference when the browser omits the content type', () => {
|
|
16
|
+
expect(resolveUploadMimeType('', 'text/markdown')).toBe('text/markdown');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('retains octet-stream when no more specific type can be inferred', () => {
|
|
20
|
+
expect(resolveUploadMimeType('application/octet-stream', undefined)).toBe('application/octet-stream');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const GENERIC_BINARY_CONTENT_TYPE = 'application/octet-stream';
|
|
2
|
+
|
|
3
|
+
function normalizedContentType(contentType: string | undefined): string | undefined {
|
|
4
|
+
return contentType?.split(';', 1)[0]?.trim().toLowerCase() || undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getUploadMimeTypeHint(contentType: string | undefined): string | undefined {
|
|
8
|
+
return normalizedContentType(contentType) === GENERIC_BINARY_CONTENT_TYPE ? undefined : contentType || undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function resolveUploadMimeType(
|
|
12
|
+
sourceContentType: string | undefined,
|
|
13
|
+
inferredContentType: string | undefined,
|
|
14
|
+
): string | undefined {
|
|
15
|
+
return getUploadMimeTypeHint(sourceContentType) || inferredContentType || sourceContentType || undefined;
|
|
16
|
+
}
|