@vertesia/client 1.6.0-dev.20260923.085325Z → 1.6.0-dev.20261008.064737Z
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/AuditTrailApi.d.ts +3 -1
- package/lib/AuditTrailApi.d.ts.map +1 -1
- package/lib/AuditTrailApi.js +6 -0
- package/lib/AuditTrailApi.js.map +1 -1
- package/lib/EnvironmentsApi.d.ts +2 -1
- package/lib/EnvironmentsApi.d.ts.map +1 -1
- package/lib/EnvironmentsApi.js +3 -0
- package/lib/EnvironmentsApi.js.map +1 -1
- package/lib/InferenceProfilesApi.d.ts +14 -0
- package/lib/InferenceProfilesApi.d.ts.map +1 -0
- package/lib/InferenceProfilesApi.js +33 -0
- package/lib/InferenceProfilesApi.js.map +1 -0
- package/lib/InteractionBase.d.ts +2 -954
- package/lib/InteractionBase.d.ts.map +1 -1
- package/lib/InteractionConfigurationsApi.d.ts +9 -0
- package/lib/InteractionConfigurationsApi.d.ts.map +1 -0
- package/lib/InteractionConfigurationsApi.js +16 -0
- package/lib/InteractionConfigurationsApi.js.map +1 -0
- package/lib/InteractionsApi.d.ts +2 -7
- package/lib/InteractionsApi.d.ts.map +1 -1
- package/lib/InteractionsApi.js.map +1 -1
- package/lib/client.d.ts +6 -12
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +4 -3
- package/lib/client.js.map +1 -1
- package/lib/execute.d.ts.map +1 -1
- package/lib/execute.js +9 -2
- package/lib/execute.js.map +1 -1
- package/lib/index.d.ts +0 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -2
- package/lib/index.js.map +1 -1
- package/lib/managed-sse.d.ts.map +1 -1
- package/lib/managed-sse.js +2 -3
- package/lib/managed-sse.js.map +1 -1
- package/lib/store/AgentsApi.d.ts +6 -1
- package/lib/store/AgentsApi.d.ts.map +1 -1
- package/lib/store/AgentsApi.js +12 -4
- package/lib/store/AgentsApi.js.map +1 -1
- package/lib/store/ContentApi.d.ts +111 -0
- package/lib/store/ContentApi.d.ts.map +1 -0
- package/lib/store/ContentApi.js +83 -0
- package/lib/store/ContentApi.js.map +1 -0
- package/lib/store/DataApi.d.ts +1 -1
- package/lib/store/DataApi.js +1 -1
- package/lib/store/IndexingApi.d.ts +1 -1
- package/lib/store/IndexingApi.d.ts.map +1 -1
- package/lib/store/IndexingApi.js +2 -1
- package/lib/store/IndexingApi.js.map +1 -1
- package/lib/store/WorkflowsApi.d.ts.map +1 -1
- package/lib/store/WorkflowsApi.js +6 -1
- package/lib/store/WorkflowsApi.js.map +1 -1
- 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/store/signed-url.d.ts +13 -0
- package/lib/store/signed-url.d.ts.map +1 -1
- package/lib/store/signed-url.js +29 -1
- package/lib/store/signed-url.js.map +1 -1
- package/lib/vertesia-client.js +4 -4
- package/lib/vertesia-client.js.map +1 -1
- package/package.json +12 -11
- package/src/AuditTrailApi.ts +12 -0
- package/src/EnvironmentsApi.ts +6 -0
- package/src/InferenceProfilesApi.ts +47 -0
- package/src/InteractionConfigurationsApi.ts +20 -0
- package/src/InteractionsApi.ts +2 -9
- package/src/client.ts +4 -3
- package/src/execute.ts +15 -4
- package/src/index.ts +0 -2
- package/src/managed-sse.ts +2 -5
- package/src/store/AgentsApi.ts +14 -4
- package/src/store/ContentApi.ts +158 -0
- package/src/store/DataApi.ts +1 -1
- package/src/store/IndexingApi.ts +2 -0
- package/src/store/WorkflowsApi.ts +5 -1
- package/src/store/client.ts +2 -0
- package/src/store/index.ts +1 -0
- package/src/store/signed-url.ts +32 -1
- package/lib/InternalAccountsApi.d.ts +0 -7
- package/lib/InternalAccountsApi.d.ts.map +0 -1
- package/lib/InternalAccountsApi.js +0 -10
- package/lib/InternalAccountsApi.js.map +0 -1
- package/lib/InternalSecretsApi.d.ts +0 -18
- package/lib/InternalSecretsApi.d.ts.map +0 -1
- package/lib/InternalSecretsApi.js +0 -29
- package/lib/InternalSecretsApi.js.map +0 -1
- package/src/AccountApi.test.ts +0 -30
- package/src/AppsApi.test.ts +0 -132
- package/src/EnvironmentsApi.test.ts +0 -39
- package/src/InteractionOutput.test.ts +0 -338
- package/src/InternalAccountsApi.ts +0 -12
- package/src/InternalSecretsApi.ts +0 -63
- package/src/OAuthServerApi.test.ts +0 -56
- package/src/ProjectsApi.test.ts +0 -33
- package/src/RunsApi.test.ts +0 -24
- package/src/ViewsApi.test.ts +0 -38
- package/src/app-session.test.ts +0 -23
- package/src/bundle-isolation.test.ts +0 -37
- package/src/client.test.ts +0 -332
- package/src/execute.test.ts +0 -22
- package/src/store/AgentsApi.artifacts.test.ts +0 -119
- package/src/store/AgentsApi.history.test.ts +0 -29
- package/src/store/AgentsApi.stream.test.ts +0 -386
- package/src/store/DataApi.test.ts +0 -42
- package/src/store/EmbeddingsApi.test.ts +0 -31
- package/src/store/EventsApi.test.ts +0 -131
- package/src/store/FilesApi.test.ts +0 -118
- package/src/store/ObjectsApi.test.ts +0 -50
- package/src/store/ProcessApi.test.ts +0 -24
- package/src/store/ViewsApi.test.ts +0 -33
- package/src/store/signed-url.test.ts +0 -204
- package/src/store/stream-gap.test.ts +0 -230
- package/src/store/stream-termination.test.ts +0 -82
- package/src/store/uploadMimeType.test.ts +0 -22
package/package.json
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/client",
|
|
3
|
-
"version": "1.6.0-dev.
|
|
3
|
+
"version": "1.6.0-dev.20261008.064737Z",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"lib",
|
|
9
9
|
"src",
|
|
10
|
+
"!src/**/*.test.*",
|
|
10
11
|
"tsconfig.dist.json"
|
|
11
12
|
],
|
|
12
13
|
"license": "Apache-2.0",
|
|
13
14
|
"devDependencies": {
|
|
14
|
-
"@types/node": "^24.
|
|
15
|
+
"@types/node": "^24.19.0",
|
|
15
16
|
"@vertesia/tsconfig": "0.1.0",
|
|
16
|
-
"rolldown": "1.2.
|
|
17
|
+
"rolldown": "1.2.11",
|
|
17
18
|
"typescript": "7.0.2",
|
|
18
|
-
"vitest": "5.0.
|
|
19
|
+
"vitest": "5.0.2"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@llumiverse/common": "1.6.0-dev.
|
|
22
|
-
"@vertesia/api-fetch-client": "1.6.0-dev.
|
|
23
|
-
"@vertesia/common": "1.6.0-dev.
|
|
24
|
-
"eventsource": "^5.1.
|
|
22
|
+
"@llumiverse/common": "1.6.0-dev.20261008.064411Z",
|
|
23
|
+
"@vertesia/api-fetch-client": "1.6.0-dev.20261008.064737Z",
|
|
24
|
+
"@vertesia/common": "1.6.0-dev.20261008.064737Z",
|
|
25
|
+
"eventsource": "^5.1.2"
|
|
25
26
|
},
|
|
26
27
|
"exports": {
|
|
27
28
|
".": {
|
|
@@ -48,13 +49,13 @@
|
|
|
48
49
|
"ai",
|
|
49
50
|
"typescript"
|
|
50
51
|
],
|
|
51
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "8ee3a33e9a7c3dbcd13937e971cbdcc5fad56717",
|
|
52
53
|
"scripts": {
|
|
53
54
|
"lint": "biome lint src",
|
|
54
55
|
"clean:lib": "rimraf ./lib ./tsconfig.tsbuildinfo",
|
|
55
|
-
"build": "pnpm run clean:lib && tsc -p tsconfig.json && pnpm exec rolldown -c rolldown.config.js",
|
|
56
|
+
"build": "pnpm run clean:lib && tsc --checkers 1 -p tsconfig.json && pnpm exec rolldown -c rolldown.config.js",
|
|
56
57
|
"clean": "rimraf ./node_modules ./lib ./tsconfig.tsbuildinfo",
|
|
57
58
|
"test": "vitest run",
|
|
58
|
-
"typecheck:test": "tsc -p tsconfig.test.json --noEmit"
|
|
59
|
+
"typecheck:test": "tsc --checkers 1 -p tsconfig.test.json --noEmit"
|
|
59
60
|
}
|
|
60
61
|
}
|
package/src/AuditTrailApi.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
2
|
import type {
|
|
3
|
+
AuditAdoptionQuery,
|
|
4
|
+
AuditAdoptionResponse,
|
|
3
5
|
AuditAggregationQuery,
|
|
4
6
|
AuditAggregationResponse,
|
|
5
7
|
AuditTrailQuery,
|
|
6
8
|
AuditTrailResponse,
|
|
9
|
+
AuditUsageQuery,
|
|
10
|
+
AuditUsageResponse,
|
|
7
11
|
} from '@vertesia/common';
|
|
8
12
|
|
|
9
13
|
export default class AuditTrailApi extends ApiTopic {
|
|
@@ -33,4 +37,12 @@ export default class AuditTrailApi extends ApiTopic {
|
|
|
33
37
|
aggregate(query: AuditAggregationQuery): Promise<AuditAggregationResponse> {
|
|
34
38
|
return this.post('/aggregate', { payload: query });
|
|
35
39
|
}
|
|
40
|
+
|
|
41
|
+
adoption(query: AuditAdoptionQuery = {}): Promise<AuditAdoptionResponse> {
|
|
42
|
+
return this.post('/adoption', { payload: query });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
usage(query: AuditUsageQuery = {}): Promise<AuditUsageResponse> {
|
|
46
|
+
return this.post('/usage', { payload: query });
|
|
47
|
+
}
|
|
36
48
|
}
|
package/src/EnvironmentsApi.ts
CHANGED
|
@@ -15,6 +15,8 @@ import type {
|
|
|
15
15
|
ExecutionEnvironmentUpdatePayload,
|
|
16
16
|
MigrateInteractionsPayload,
|
|
17
17
|
MigrateInteractionsResult,
|
|
18
|
+
RunBudgetCapability,
|
|
19
|
+
RunBudgetCapabilityQuery,
|
|
18
20
|
} from '@vertesia/common';
|
|
19
21
|
|
|
20
22
|
export default class EnvironmentsApi extends ApiTopic {
|
|
@@ -38,6 +40,10 @@ export default class EnvironmentsApi extends ApiTopic {
|
|
|
38
40
|
});
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
runBudgetCapability(id: string, query: RunBudgetCapabilityQuery): Promise<RunBudgetCapability> {
|
|
44
|
+
return this.get(`/${id}/run-budget-capability`, { query });
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
retrieve(id: string): Promise<ExecutionEnvironment> {
|
|
42
48
|
return this.get(`/${id}`);
|
|
43
49
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
|
+
import type {
|
|
3
|
+
CreateInferenceProfilePayload,
|
|
4
|
+
DeleteByIdResult,
|
|
5
|
+
InferenceProfile,
|
|
6
|
+
InferenceProfileRecord,
|
|
7
|
+
InferenceProfileUsage,
|
|
8
|
+
InferenceProfileUsageQuery,
|
|
9
|
+
ProjectConfiguration,
|
|
10
|
+
ProjectInferenceProfiles,
|
|
11
|
+
UpdateInferenceProfilePayload,
|
|
12
|
+
} from '@vertesia/common';
|
|
13
|
+
|
|
14
|
+
export default class InferenceProfilesApi extends ApiTopic {
|
|
15
|
+
constructor(parent: ClientBase) {
|
|
16
|
+
super(parent, '/api/v1/inference-profiles');
|
|
17
|
+
}
|
|
18
|
+
/** Read a category or base default, including projects awaiting the defaults migration. */
|
|
19
|
+
async getDefault(
|
|
20
|
+
configuration: Pick<ProjectConfiguration, 'inference' | 'defaults'>,
|
|
21
|
+
category?: keyof NonNullable<ProjectInferenceProfiles['system']>,
|
|
22
|
+
): Promise<InferenceProfileRecord | InferenceProfile | undefined> {
|
|
23
|
+
const settings = configuration.inference;
|
|
24
|
+
const id = (category ? settings?.system?.[category] : undefined) ?? settings?.default_profile;
|
|
25
|
+
if (id) return this.retrieve(id);
|
|
26
|
+
return (category ? configuration.defaults?.system?.[category] : undefined) ?? configuration.defaults?.base;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
list(): Promise<InferenceProfileRecord[]> {
|
|
30
|
+
return this.get('/');
|
|
31
|
+
}
|
|
32
|
+
retrieve(id: string): Promise<InferenceProfileRecord> {
|
|
33
|
+
return this.get(`/${encodeURIComponent(id)}`);
|
|
34
|
+
}
|
|
35
|
+
usage(id: string, query: InferenceProfileUsageQuery = {}): Promise<InferenceProfileUsage> {
|
|
36
|
+
return this.get(`/${encodeURIComponent(id)}/usage`, { query });
|
|
37
|
+
}
|
|
38
|
+
create(payload: CreateInferenceProfilePayload): Promise<InferenceProfileRecord> {
|
|
39
|
+
return this.post('/', { payload });
|
|
40
|
+
}
|
|
41
|
+
update(id: string, payload: UpdateInferenceProfilePayload): Promise<InferenceProfileRecord> {
|
|
42
|
+
return this.put(`/${encodeURIComponent(id)}`, { payload });
|
|
43
|
+
}
|
|
44
|
+
delete(id: string): Promise<DeleteByIdResult> {
|
|
45
|
+
return this.del(`/${encodeURIComponent(id)}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
|
+
import type { InteractionConfigurationResult, UpdateInteractionConfigurationPayload } from '@vertesia/common';
|
|
3
|
+
|
|
4
|
+
export default class InteractionConfigurationsApi extends ApiTopic {
|
|
5
|
+
constructor(parent: ClientBase) {
|
|
6
|
+
super(parent, '/api/v1/interaction-configurations');
|
|
7
|
+
}
|
|
8
|
+
retrieve(interactionId: string): Promise<InteractionConfigurationResult> {
|
|
9
|
+
return this.get(`/${encodeURIComponent(interactionId)}`);
|
|
10
|
+
}
|
|
11
|
+
update(
|
|
12
|
+
interactionId: string,
|
|
13
|
+
payload: UpdateInteractionConfigurationPayload,
|
|
14
|
+
): Promise<InteractionConfigurationResult> {
|
|
15
|
+
return this.put(`/${encodeURIComponent(interactionId)}`, { payload });
|
|
16
|
+
}
|
|
17
|
+
delete(interactionId: string): Promise<InteractionConfigurationResult> {
|
|
18
|
+
return this.del(`/${encodeURIComponent(interactionId)}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/InteractionsApi.ts
CHANGED
|
@@ -30,6 +30,7 @@ import type {
|
|
|
30
30
|
RateLimitRequestPayload,
|
|
31
31
|
RateLimitRequestResponse,
|
|
32
32
|
ResolvedInteractionExecutionInfo,
|
|
33
|
+
ResolveInteractionQuery,
|
|
33
34
|
} from '@vertesia/common';
|
|
34
35
|
import type { VertesiaClient } from './client.js';
|
|
35
36
|
import { checkRateLimit, executeInteraction, executeInteractionAsync, executeInteractionByName } from './execute.js';
|
|
@@ -341,15 +342,7 @@ export default class InteractionsApi extends ApiTopic {
|
|
|
341
342
|
* @param options Optional environment and/or model to resolve with
|
|
342
343
|
* @returns ResolvedInteractionExecutionInfo with the resolved environment and model
|
|
343
344
|
*/
|
|
344
|
-
resolve(
|
|
345
|
-
nameOrId: string,
|
|
346
|
-
options?: {
|
|
347
|
-
environment?: string;
|
|
348
|
-
model?: string;
|
|
349
|
-
hasImage?: boolean;
|
|
350
|
-
hasVideo?: boolean;
|
|
351
|
-
},
|
|
352
|
-
): Promise<ResolvedInteractionExecutionInfo> {
|
|
345
|
+
resolve(nameOrId: string, options?: ResolveInteractionQuery): Promise<ResolvedInteractionExecutionInfo> {
|
|
353
346
|
return this.get(`/resolve/${encodeURIComponent(nameOrId)}`, {
|
|
354
347
|
query: options,
|
|
355
348
|
});
|
package/src/client.ts
CHANGED
|
@@ -11,8 +11,9 @@ import CommandsApi from './CommandsApi.js';
|
|
|
11
11
|
import DelegationGrantsApi from './DelegationGrantsApi.js';
|
|
12
12
|
import EnvironmentsApi from './EnvironmentsApi.js';
|
|
13
13
|
import { IamApi } from './IamApi.js';
|
|
14
|
+
import InferenceProfilesApi from './InferenceProfilesApi.js';
|
|
15
|
+
import InteractionConfigurationsApi from './InteractionConfigurationsApi.js';
|
|
14
16
|
import InteractionsApi from './InteractionsApi.js';
|
|
15
|
-
import InternalSecretsApi from './InternalSecretsApi.js';
|
|
16
17
|
import OAuthClientsApi from './OAuthClientsApi.js';
|
|
17
18
|
import OAuthGrantsApi from './OAuthGrantsApi.js';
|
|
18
19
|
import OAuthProvidersApi from './OAuthProvidersApi.js';
|
|
@@ -125,7 +126,6 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
125
126
|
oauthProviders: OAuthProvidersApi;
|
|
126
127
|
remoteMcpConnections: RemoteMcpConnectionsApi;
|
|
127
128
|
secrets: SecretsApi;
|
|
128
|
-
internalSecrets: InternalSecretsApi;
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
131
|
* Create a client from the given token.
|
|
@@ -257,7 +257,6 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
257
257
|
this.oauthProviders = new OAuthProvidersApi(this);
|
|
258
258
|
this.remoteMcpConnections = new RemoteMcpConnectionsApi(this);
|
|
259
259
|
this.secrets = new SecretsApi(this);
|
|
260
|
-
this.internalSecrets = new InternalSecretsApi(this);
|
|
261
260
|
}
|
|
262
261
|
|
|
263
262
|
withApiVersion(version: string | number | null) {
|
|
@@ -445,6 +444,8 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
|
|
|
445
444
|
}
|
|
446
445
|
|
|
447
446
|
projects = new ProjectsApi(this);
|
|
447
|
+
interactionConfigurations = new InteractionConfigurationsApi(this);
|
|
448
|
+
inferenceProfiles = new InferenceProfilesApi(this);
|
|
448
449
|
environments = new EnvironmentsApi(this);
|
|
449
450
|
interactions = new InteractionsApi(this);
|
|
450
451
|
skills = new SkillsApi(this);
|
package/src/execute.ts
CHANGED
|
@@ -62,7 +62,7 @@ export async function executeInteraction<P = unknown>(
|
|
|
62
62
|
if (response.status === ExecutionRunStatus.failed) {
|
|
63
63
|
return response;
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
return handleStreaming<P>(client, response.id, onChunk);
|
|
66
66
|
}
|
|
67
67
|
return response;
|
|
68
68
|
}
|
|
@@ -105,13 +105,17 @@ export async function executeInteractionByName<P = unknown>(
|
|
|
105
105
|
if (response.status === ExecutionRunStatus.failed) {
|
|
106
106
|
return response;
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
return handleStreaming<P>(client, response.id, onChunk);
|
|
109
109
|
}
|
|
110
110
|
return response;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
function handleStreaming(
|
|
114
|
-
|
|
113
|
+
function handleStreaming<P>(
|
|
114
|
+
client: VertesiaClient,
|
|
115
|
+
runId: string,
|
|
116
|
+
onChunk: (chunk: string) => void,
|
|
117
|
+
): Promise<InteractionExecutionResult<P>> {
|
|
118
|
+
return new Promise<InteractionExecutionResult<P>>((resolve, reject) => {
|
|
115
119
|
void (async () => {
|
|
116
120
|
try {
|
|
117
121
|
const EventSourceImpl = await EventSourceProvider();
|
|
@@ -133,6 +137,7 @@ function handleStreaming(client: VertesiaClient, runId: string, onChunk: (chunk:
|
|
|
133
137
|
onChunk?.(data);
|
|
134
138
|
}
|
|
135
139
|
} catch (err) {
|
|
140
|
+
sse.close();
|
|
136
141
|
reject(err);
|
|
137
142
|
}
|
|
138
143
|
});
|
|
@@ -145,6 +150,12 @@ function handleStreaming(client: VertesiaClient, runId: string, onChunk: (chunk:
|
|
|
145
150
|
reject(err);
|
|
146
151
|
}
|
|
147
152
|
});
|
|
153
|
+
sse.addEventListener('error', () => {
|
|
154
|
+
if (sse.readyState === EventSourceImpl.CLOSED) {
|
|
155
|
+
sse.close();
|
|
156
|
+
reject(new Error('Interaction result stream closed before completion'));
|
|
157
|
+
}
|
|
158
|
+
});
|
|
148
159
|
} catch (err) {
|
|
149
160
|
reject(err);
|
|
150
161
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,8 +7,6 @@ export { default as DelegationGrantsApi } from './DelegationGrantsApi.js';
|
|
|
7
7
|
export type { GroupsQueryOptions } from './GroupsApi.js';
|
|
8
8
|
export * from './InteractionBase.js';
|
|
9
9
|
export * from './InteractionOutput.js';
|
|
10
|
-
export { default as InternalAccountsApi } from './InternalAccountsApi.js';
|
|
11
|
-
export { default as InternalSecretsApi } from './InternalSecretsApi.js';
|
|
12
10
|
export * from './managed-sse.js';
|
|
13
11
|
export { default as OAuthClientsApi } from './OAuthClientsApi.js';
|
|
14
12
|
export { default as OAuthGrantsApi } from './OAuthGrantsApi.js';
|
package/src/managed-sse.ts
CHANGED
|
@@ -101,6 +101,7 @@ export function openManagedEventSource<T>(options: ManagedEventSourceOptions<T>)
|
|
|
101
101
|
}
|
|
102
102
|
cleanupCurrentSource();
|
|
103
103
|
const connectionDuration = connectionOpenedAt ? Date.now() - connectionOpenedAt : 0;
|
|
104
|
+
connectionOpenedAt = 0;
|
|
104
105
|
if (connectionDuration > 5000) {
|
|
105
106
|
reconnectAttempts = 0;
|
|
106
107
|
}
|
|
@@ -147,11 +148,7 @@ export function openManagedEventSource<T>(options: ManagedEventSourceOptions<T>)
|
|
|
147
148
|
return;
|
|
148
149
|
}
|
|
149
150
|
const url = await resolveUrl(options.url);
|
|
150
|
-
if (
|
|
151
|
-
lastEventId &&
|
|
152
|
-
options.last_event_id_query_param &&
|
|
153
|
-
!url.searchParams.has(options.last_event_id_query_param)
|
|
154
|
-
) {
|
|
151
|
+
if (lastEventId && options.last_event_id_query_param) {
|
|
155
152
|
url.searchParams.set(options.last_event_id_query_param, lastEventId);
|
|
156
153
|
}
|
|
157
154
|
withAccessToken(url, await options.get_access_token?.());
|
package/src/store/AgentsApi.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type AgentRunInternals,
|
|
13
13
|
type AgentRunResponse,
|
|
14
14
|
type AgentRunUpdatesResponse,
|
|
15
|
+
type AllocateAgentRunBudgetPayload,
|
|
15
16
|
type BindRunWorkflowPayload,
|
|
16
17
|
type CreateAgentRunPayload,
|
|
17
18
|
type CreateProcessRunPayload,
|
|
@@ -226,6 +227,14 @@ export class AgentsApi extends ApiTopic {
|
|
|
226
227
|
return this.post(`/${id}/restart`, {});
|
|
227
228
|
}
|
|
228
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Add token budget to a run paused because its budget ran out; the run resumes from where it
|
|
232
|
+
* stopped. The amount is added to the limit the run was granted, so usage past it is paid first.
|
|
233
|
+
*/
|
|
234
|
+
allocateBudget(id: string, payload: AllocateAgentRunBudgetPayload): Promise<SignalAgentResponse> {
|
|
235
|
+
return this.post(`/${id}/budget`, { payload });
|
|
236
|
+
}
|
|
237
|
+
|
|
229
238
|
/**
|
|
230
239
|
* Fork a conversation into a new agent run.
|
|
231
240
|
*/
|
|
@@ -397,7 +406,7 @@ export class AgentsApi extends ApiTopic {
|
|
|
397
406
|
currentSse.close();
|
|
398
407
|
currentSse = null;
|
|
399
408
|
}
|
|
400
|
-
if (signal && abortHandler) {
|
|
409
|
+
if (isClosed && signal && abortHandler) {
|
|
401
410
|
signal.removeEventListener('abort', abortHandler);
|
|
402
411
|
abortHandler = null;
|
|
403
412
|
}
|
|
@@ -450,13 +459,14 @@ export class AgentsApi extends ApiTopic {
|
|
|
450
459
|
try {
|
|
451
460
|
// Resume from the last message we handed to the caller, whether it came from
|
|
452
461
|
// history, SSE, or an earlier poll. The server returns messages with ts > since.
|
|
453
|
-
const
|
|
462
|
+
const previousMessageTimestamp = lastMessageTimestamp;
|
|
463
|
+
const recent = await this.retrieveMessages(id, previousMessageTimestamp || undefined);
|
|
454
464
|
polledMessages = true;
|
|
455
465
|
for (const msg of recent) {
|
|
456
466
|
if (isClosed) return;
|
|
457
467
|
const timestamp = msg.timestamp || 0;
|
|
458
|
-
if (timestamp <=
|
|
459
|
-
lastMessageTimestamp = timestamp;
|
|
468
|
+
if (timestamp <= previousMessageTimestamp) continue;
|
|
469
|
+
lastMessageTimestamp = Math.max(lastMessageTimestamp, timestamp);
|
|
460
470
|
if (onMessage) onMessage(msg, exit);
|
|
461
471
|
if (isClosed) return;
|
|
462
472
|
if (shouldCloseAgentRunStream(msg, id, options?.closeOnIdle)) {
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
|
+
import type {
|
|
3
|
+
Collection,
|
|
4
|
+
ComplexSearchPayload,
|
|
5
|
+
ComputedFacetResponse,
|
|
6
|
+
ContentObject,
|
|
7
|
+
ContentObjectItem,
|
|
8
|
+
GetFileUrlResponse,
|
|
9
|
+
GetRenditionResponse,
|
|
10
|
+
} from '@vertesia/common';
|
|
11
|
+
|
|
12
|
+
/** A project sharing content with the caller. */
|
|
13
|
+
export interface SharedProjectRef {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A lightweight entry in a shared browse listing (root list or collection members). */
|
|
19
|
+
export interface SharedContentEntry {
|
|
20
|
+
type: 'object' | 'collection';
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
modified_at: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Result of resolving a bare content id: the entity, its type, and the project it lives in. */
|
|
27
|
+
export type ResolvedContent =
|
|
28
|
+
| { type: 'object'; projectId: string; entity: ContentObject }
|
|
29
|
+
| { type: 'collection'; projectId: string; entity: Collection };
|
|
30
|
+
|
|
31
|
+
/** A cross-project search hit, stamped with its owner project and relevance score. */
|
|
32
|
+
export type ContentSearchHit = ContentObjectItem & { projectId: string; score: number };
|
|
33
|
+
|
|
34
|
+
/** Which projects a cross-project content search covered. */
|
|
35
|
+
export interface SharedSearchCoverage {
|
|
36
|
+
/** 'hybrid' when vector search ran on at least one field, otherwise 'text'. */
|
|
37
|
+
mode: 'text' | 'hybrid';
|
|
38
|
+
/** Project ids actually searched — full-text spans every reachable project. */
|
|
39
|
+
searched: string[];
|
|
40
|
+
/** Reachable project ids excluded from the vector pass as embedding-incompatible (hybrid only). */
|
|
41
|
+
vectorIncompatible: string[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Response of the cross-project content search: the hits plus `coverage`. This is an object envelope —
|
|
46
|
+
* distinct from the plain array returned by the single-project object search — so callers can tell the
|
|
47
|
+
* two apart (array = project search, `{ results, coverage }` = cross-project search).
|
|
48
|
+
*/
|
|
49
|
+
export interface ContentSearchResponse {
|
|
50
|
+
results: ContentSearchHit[];
|
|
51
|
+
/** Facets computed across every reachable project. */
|
|
52
|
+
facets: ComputedFacetResponse;
|
|
53
|
+
coverage: SharedSearchCoverage;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Read-only client for the `/api/content` namespace: browse and read content shared by other
|
|
58
|
+
* projects in the account, resolve a bare content id, and search across the caller's reachable
|
|
59
|
+
* content (current project + shared projects). There are no write operations.
|
|
60
|
+
*/
|
|
61
|
+
export class ContentApi extends ApiTopic {
|
|
62
|
+
constructor(parent: ClientBase) {
|
|
63
|
+
super(parent, '/api/v1/content');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The projects sharing content with the caller (`{ id, name }`). */
|
|
67
|
+
listSharedProjects(): Promise<SharedProjectRef[]> {
|
|
68
|
+
return this.get('/shared');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Shared COLLECTIONS at a browse level — the root collections of a shared project (no `parentId`),
|
|
73
|
+
* or the sub-collections of `parentId` within it. Bounded set, returned in full, newest first.
|
|
74
|
+
*/
|
|
75
|
+
sharedCollections(projectId: string, parentId?: string): Promise<SharedContentEntry[]> {
|
|
76
|
+
const path = parentId ? `/shared/${projectId}/${parentId}` : `/shared/${projectId}`;
|
|
77
|
+
return this.get(path, { query: { list: 'collections' } });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A page of shared OBJECTS at a browse level — the root objects of a shared project (no `parentId`),
|
|
82
|
+
* or the member objects of `parentId` within it. Paginated via `from`/`limit`, newest first.
|
|
83
|
+
*/
|
|
84
|
+
sharedObjects(
|
|
85
|
+
projectId: string,
|
|
86
|
+
parentId?: string,
|
|
87
|
+
options?: { from?: number; limit?: number },
|
|
88
|
+
): Promise<SharedContentEntry[]> {
|
|
89
|
+
const path = parentId ? `/shared/${projectId}/${parentId}` : `/shared/${projectId}`;
|
|
90
|
+
return this.get(path, { query: { list: 'objects', from: options?.from, limit: options?.limit } });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Read a shared entity's detail: an object id → the full object; a collection id → its meta. */
|
|
94
|
+
getShared(projectId: string, id: string): Promise<ContentObject | Collection> {
|
|
95
|
+
return this.get(`/shared/${projectId}/${id}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A rendition (visual content) of a shared object — the rendered file (image / PDF) from the owner
|
|
100
|
+
* project's storage. `format`: 'jpeg' | 'png' | 'webp' | 'pdf' | 'docx'. Returns `{ status, renditions:
|
|
101
|
+
* url[] }`; rejects with 404 if no rendition of that format has been generated yet by the owner project.
|
|
102
|
+
*/
|
|
103
|
+
getSharedRendition(
|
|
104
|
+
projectId: string,
|
|
105
|
+
id: string,
|
|
106
|
+
format: string,
|
|
107
|
+
options?: { max_hw?: number },
|
|
108
|
+
): Promise<GetRenditionResponse> {
|
|
109
|
+
return this.get(`/shared/${projectId}/${id}/renditions/${format}`, {
|
|
110
|
+
query: { max_hw: options?.max_hw },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Signed download URL for a shared object's OWN file (its content source) from the owner project's
|
|
116
|
+
* storage — used to preview a native PDF/image or download the existing file cross-project.
|
|
117
|
+
* `disposition` 'attachment' forces a download (default 'inline'). Rejects with 404 if the object
|
|
118
|
+
* isn't shared/authorized or has no content source. Read-only: never generates anything.
|
|
119
|
+
*/
|
|
120
|
+
getSharedFileUrl(
|
|
121
|
+
projectId: string,
|
|
122
|
+
id: string,
|
|
123
|
+
disposition?: 'inline' | 'attachment',
|
|
124
|
+
): Promise<GetFileUrlResponse> {
|
|
125
|
+
return this.get(`/shared/${projectId}/${id}/file`, { query: { disposition } });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Resolve a bare content id when the project is unknown — the current project is checked first,
|
|
130
|
+
* then the shared projects. Returns the entity, its type, and the resolved projectId.
|
|
131
|
+
*/
|
|
132
|
+
resolve(objectId: string): Promise<ResolvedContent> {
|
|
133
|
+
return this.get(`/resolve/${objectId}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Search content reachable by the caller (current project + shared projects). Takes the same
|
|
138
|
+
* `ComplexSearchPayload` as `objects.search` — full-text, vector/hybrid, filters and facets — applied
|
|
139
|
+
* across every reachable project (vector runs only over embedding-compatible ones). `onlyShared` drops
|
|
140
|
+
* the current project. Pagination (`payload.limit`/`offset`) is text-only; a vector/hybrid run returns
|
|
141
|
+
* a top-N window. Returns `{ results, facets, coverage }` — each hit stamped with its owner projectId,
|
|
142
|
+
* plus which projects were searched vs. excluded from the vector pass.
|
|
143
|
+
*/
|
|
144
|
+
search(payload: ComplexSearchPayload, options?: { onlyShared?: boolean }): Promise<ContentSearchResponse> {
|
|
145
|
+
return this.post('/search', {
|
|
146
|
+
payload,
|
|
147
|
+
query: { onlyShared: options?.onlyShared ? 'true' : undefined },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The CURRENT project's shared roots (collections + documents) — the Manage view. Requires
|
|
153
|
+
* content-admin. Unshare an entry via the regular collection/object update with `shared_root: false`.
|
|
154
|
+
*/
|
|
155
|
+
managed(): Promise<SharedContentEntry[]> {
|
|
156
|
+
return this.get('/managed');
|
|
157
|
+
}
|
|
158
|
+
}
|
package/src/store/DataApi.ts
CHANGED
|
@@ -463,7 +463,7 @@ export class DataApi extends ApiTopic {
|
|
|
463
463
|
* const info = await client.data.getDownloadInfo(storeId);
|
|
464
464
|
* // Download if gcs_generation changed
|
|
465
465
|
* if (info.gcs_generation !== localGeneration) {
|
|
466
|
-
* await downloadFile(info.url, '
|
|
466
|
+
* await downloadFile(info.url, 'databases/store.duckdb');
|
|
467
467
|
* }
|
|
468
468
|
* ```
|
|
469
469
|
*/
|
package/src/store/IndexingApi.ts
CHANGED
|
@@ -335,12 +335,14 @@ export class IndexingApi extends ApiTopic {
|
|
|
335
335
|
targetIndex: string,
|
|
336
336
|
alias?: string,
|
|
337
337
|
backend?: ElasticsearchBackend,
|
|
338
|
+
cleanup?: boolean,
|
|
338
339
|
): Promise<SwapAliasResult> {
|
|
339
340
|
return this.zenoBulkPost('/reindex/swap-alias', {
|
|
340
341
|
tenant_id: tenantId,
|
|
341
342
|
target_index: targetIndex,
|
|
342
343
|
alias,
|
|
343
344
|
backend,
|
|
345
|
+
cleanup,
|
|
344
346
|
} satisfies SwapAliasRequest);
|
|
345
347
|
}
|
|
346
348
|
}
|
|
@@ -212,7 +212,7 @@ export class WorkflowsApi extends ApiTopic {
|
|
|
212
212
|
currentSse.close();
|
|
213
213
|
currentSse = null;
|
|
214
214
|
}
|
|
215
|
-
if (signal && abortHandler) {
|
|
215
|
+
if (isClosed && signal && abortHandler) {
|
|
216
216
|
signal.removeEventListener('abort', abortHandler);
|
|
217
217
|
abortHandler = null;
|
|
218
218
|
}
|
|
@@ -349,12 +349,14 @@ export class WorkflowsApi extends ApiTopic {
|
|
|
349
349
|
`Failed to reconnect to SSE stream for run ${runId} after ${maxReconnectAttempts} attempts`,
|
|
350
350
|
);
|
|
351
351
|
isClosed = true;
|
|
352
|
+
cleanup();
|
|
352
353
|
reject(
|
|
353
354
|
new Error(`SSE connection failed after ${maxReconnectAttempts} reconnection attempts`),
|
|
354
355
|
);
|
|
355
356
|
}
|
|
356
357
|
};
|
|
357
358
|
} catch (err) {
|
|
359
|
+
if (isClosed) return;
|
|
358
360
|
console.error('Error setting up SSE stream:', err);
|
|
359
361
|
if (reconnectAttempts < maxReconnectAttempts) {
|
|
360
362
|
const delay = calculateBackoffDelay(reconnectAttempts);
|
|
@@ -366,6 +368,8 @@ export class WorkflowsApi extends ApiTopic {
|
|
|
366
368
|
}
|
|
367
369
|
}, delay);
|
|
368
370
|
} else {
|
|
371
|
+
isClosed = true;
|
|
372
|
+
cleanup();
|
|
369
373
|
reject(err);
|
|
370
374
|
}
|
|
371
375
|
}
|
package/src/store/client.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { APP_VERSION_HEADER, type BulkOperationPayload, type BulkOperationRespon
|
|
|
8
8
|
import { warnUnknownOptions } from '../unknown-options.js';
|
|
9
9
|
import { AgentsApi } from './AgentsApi.js';
|
|
10
10
|
import { CollectionsApi } from './CollectionsApi.js';
|
|
11
|
+
import { ContentApi } from './ContentApi.js';
|
|
11
12
|
import { CostApi } from './CostApi.js';
|
|
12
13
|
import { DataApi } from './DataApi.js';
|
|
13
14
|
import { EmailApi } from './EmailApi.js';
|
|
@@ -122,6 +123,7 @@ export class ZenoClient extends AbstractFetchClient<ZenoClient> {
|
|
|
122
123
|
agents = new AgentsApi(this);
|
|
123
124
|
cost = new CostApi(this);
|
|
124
125
|
objects = new ObjectsApi(this);
|
|
126
|
+
content = new ContentApi(this);
|
|
125
127
|
types = new TypesApi(this);
|
|
126
128
|
workflows = new WorkflowsApi(this);
|
|
127
129
|
schedules = new SchedulesApi(this);
|
package/src/store/index.ts
CHANGED
package/src/store/signed-url.ts
CHANGED
|
@@ -36,6 +36,33 @@ export interface SignedUrlFetchOptions {
|
|
|
36
36
|
retryableStatuses?: ReadonlySet<number>;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
const AZURE_BLOB_HOST_SUFFIX = '.blob.core.windows.net';
|
|
40
|
+
|
|
41
|
+
/** Whether a signed URL points at Azure Blob Storage (a SAS URL on `<account>.blob.core.windows.net`). */
|
|
42
|
+
export function isAzureBlobUrl(url: string): boolean {
|
|
43
|
+
try {
|
|
44
|
+
return new URL(url).hostname.toLowerCase().endsWith(AZURE_BLOB_HOST_SUFFIX);
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The headers for a `PUT` of file content to a signed upload URL.
|
|
52
|
+
*
|
|
53
|
+
* Azure's Put Blob rejects a request without `x-ms-blob-type`, so it is added for Azure Blob URLs
|
|
54
|
+
* only. GCS and S3 requests are left untouched: from a browser every extra header must be allowed
|
|
55
|
+
* by the bucket's CORS policy, and a header those backends do not expect would fail the preflight.
|
|
56
|
+
*/
|
|
57
|
+
export function signedUrlUploadHeaders(
|
|
58
|
+
url: string,
|
|
59
|
+
headers?: Record<string, string>,
|
|
60
|
+
): Record<string, string> | undefined {
|
|
61
|
+
if (!isAzureBlobUrl(url)) return headers;
|
|
62
|
+
if (headers && Object.keys(headers).some((name) => name.toLowerCase() === 'x-ms-blob-type')) return headers;
|
|
63
|
+
return { ...headers, 'x-ms-blob-type': 'BlockBlob' };
|
|
64
|
+
}
|
|
65
|
+
|
|
39
66
|
function sleep(ms: number): Promise<void> {
|
|
40
67
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
68
|
}
|
|
@@ -145,6 +172,9 @@ async function toReplayableBody(body: BodyInit | null | undefined): Promise<Body
|
|
|
145
172
|
* `Retry-After` response header up to 60 seconds. Longer delays return the response
|
|
146
173
|
* without retrying so the caller can schedule recovery outside this request.
|
|
147
174
|
*
|
|
175
|
+
* A `PUT` to an Azure Blob SAS URL gets the `x-ms-blob-type` header it requires (see
|
|
176
|
+
* {@link signedUrlUploadHeaders}).
|
|
177
|
+
*
|
|
148
178
|
* The returned `Response` is only guaranteed to be retried while it carries a
|
|
149
179
|
* retryable status; a non-retryable error response (e.g. 403, 404) is returned
|
|
150
180
|
* as-is for the caller to handle.
|
|
@@ -160,12 +190,13 @@ export async function fetchSignedUrl(url: string, options: SignedUrlFetchOptions
|
|
|
160
190
|
} = options;
|
|
161
191
|
|
|
162
192
|
const body = await toReplayableBody(options.body);
|
|
193
|
+
const requestHeaders = method.toUpperCase() === 'PUT' ? signedUrlUploadHeaders(url, headers) : headers;
|
|
163
194
|
|
|
164
195
|
let lastError: unknown;
|
|
165
196
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
166
197
|
const isLastAttempt = attempt === attempts - 1;
|
|
167
198
|
try {
|
|
168
|
-
const res = await fetch(url, { method, headers, body });
|
|
199
|
+
const res = await fetch(url, { method, headers: requestHeaders, body });
|
|
169
200
|
if (res.ok || !retryableStatuses.has(res.status) || isLastAttempt) {
|
|
170
201
|
return res;
|
|
171
202
|
}
|