@vertesia/client 1.6.0-dev.20261019.172735Z → 1.6.0-dev.20261022.120426Z
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/ApiKeysApi.d.ts +4 -7
- package/lib/ApiKeysApi.d.ts.map +1 -1
- package/lib/ApiKeysApi.js +5 -4
- package/lib/ApiKeysApi.js.map +1 -1
- package/lib/InteractionsApi.d.ts +3 -1
- package/lib/InteractionsApi.d.ts.map +1 -1
- package/lib/InteractionsApi.js +2 -1
- package/lib/InteractionsApi.js.map +1 -1
- package/lib/RunsApi.d.ts +3 -2
- package/lib/RunsApi.d.ts.map +1 -1
- package/lib/RunsApi.js +3 -2
- package/lib/RunsApi.js.map +1 -1
- package/lib/execute.d.ts +16 -2
- package/lib/execute.d.ts.map +1 -1
- package/lib/execute.js +13 -2
- package/lib/execute.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/nodejs/NodeStreamSource.d.ts +1 -0
- package/lib/nodejs/NodeStreamSource.d.ts.map +1 -1
- package/lib/nodejs/NodeStreamSource.js +17 -15
- package/lib/nodejs/NodeStreamSource.js.map +1 -1
- package/lib/store/AgentsApi.d.ts +3 -0
- package/lib/store/AgentsApi.d.ts.map +1 -1
- package/lib/store/AgentsApi.js +7 -1
- package/lib/store/AgentsApi.js.map +1 -1
- package/lib/store/FilesApi.d.ts.map +1 -1
- package/lib/store/FilesApi.js +8 -2
- package/lib/store/FilesApi.js.map +1 -1
- package/lib/store/IndexingApi.d.ts +0 -6
- package/lib/store/IndexingApi.d.ts.map +1 -1
- package/lib/store/IndexingApi.js +3 -17
- package/lib/store/IndexingApi.js.map +1 -1
- package/lib/store/ObjectsApi.d.ts +0 -6
- package/lib/store/ObjectsApi.d.ts.map +1 -1
- package/lib/store/ObjectsApi.js +2 -16
- package/lib/store/ObjectsApi.js.map +1 -1
- package/lib/store/zeno-bulk.d.ts +9 -0
- package/lib/store/zeno-bulk.d.ts.map +1 -0
- package/lib/store/zeno-bulk.js +26 -0
- package/lib/store/zeno-bulk.js.map +1 -0
- package/lib/vertesia-client.js +4 -4
- package/lib/vertesia-client.js.map +1 -1
- package/package.json +13 -8
- package/src/ApiKeysApi.ts +4 -12
- package/src/InteractionsApi.ts +9 -2
- package/src/RunsApi.ts +7 -2
- package/src/execute.ts +30 -3
- package/src/index.ts +1 -0
- package/src/nodejs/NodeStreamSource.ts +28 -24
- package/src/store/AgentsApi.ts +10 -1
- package/src/store/FilesApi.ts +8 -2
- package/src/store/IndexingApi.ts +3 -18
- package/src/store/ObjectsApi.ts +2 -17
- package/src/store/zeno-bulk.ts +30 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/client",
|
|
3
|
-
"version": "1.6.0-dev.
|
|
3
|
+
"version": "1.6.0-dev.20261022.120426Z",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
],
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/node": "^24.19.
|
|
15
|
+
"@types/node": "^24.19.2",
|
|
16
16
|
"@vertesia/tsconfig": "0.1.0",
|
|
17
|
-
"rolldown": "1.2.
|
|
17
|
+
"rolldown": "1.2.14",
|
|
18
18
|
"typescript": "7.0.2",
|
|
19
|
-
"vitest": "5.0.
|
|
19
|
+
"vitest": "5.0.4"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@llumiverse/common": "1.6.0-dev.
|
|
23
|
-
"@vertesia/api-fetch-client": "1.6.0-dev.
|
|
24
|
-
"@vertesia/common": "1.6.0-dev.
|
|
22
|
+
"@llumiverse/common": "1.6.0-dev.20261022.120426Z",
|
|
23
|
+
"@vertesia/api-fetch-client": "1.6.0-dev.20261022.120426Z",
|
|
24
|
+
"@vertesia/common": "1.6.0-dev.20261022.120426Z",
|
|
25
25
|
"eventsource": "^5.1.2"
|
|
26
26
|
},
|
|
27
27
|
"exports": {
|
|
@@ -49,7 +49,12 @@
|
|
|
49
49
|
"ai",
|
|
50
50
|
"typescript"
|
|
51
51
|
],
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "bcaa7879b601ce9ccc394bcd3257822da13869cd",
|
|
53
|
+
"releaseIdentity": {
|
|
54
|
+
"source_sha": "bcaa7879b601ce9ccc394bcd3257822da13869cd",
|
|
55
|
+
"dependency_sha": "93466e47b06db23ac3c800e248d170afe65e5006",
|
|
56
|
+
"lock_sha256": "117e1c8068aa07d59117323a51ceccfc96cab543e50c03eb7efc19709d6f5e6b"
|
|
57
|
+
},
|
|
53
58
|
"scripts": {
|
|
54
59
|
"lint": "biome lint src",
|
|
55
60
|
"clean:lib": "rimraf ./lib ./tsconfig.tsbuildinfo",
|
package/src/ApiKeysApi.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ApiTopic, type ClientBase } from '@vertesia/api-fetch-client';
|
|
2
2
|
import type {
|
|
3
3
|
ApiKey,
|
|
4
|
-
ApiKeyReadResponse,
|
|
5
4
|
ApiKeyWithValue,
|
|
6
5
|
AuthTokenResponse,
|
|
7
6
|
CreateApiKeyPayload,
|
|
@@ -42,17 +41,10 @@ export class ApiKeysApi extends ApiTopic {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
/**
|
|
45
|
-
* Retrieve an ApiKey
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* */
|
|
50
|
-
retrieve(id: string, withValue: true): Promise<ApiKeyWithValue>;
|
|
51
|
-
retrieve(id: string, withValue?: false): Promise<ApiKey>;
|
|
52
|
-
retrieve(id: string, withValue: boolean = false): Promise<ApiKeyReadResponse> {
|
|
53
|
-
if (withValue) {
|
|
54
|
-
return this.get(`/${id}`, { query: { withValue: true } });
|
|
55
|
-
}
|
|
44
|
+
* Retrieve an ApiKey without its value. The raw value is returned only once, by `create`.
|
|
45
|
+
* @returns ApiKey
|
|
46
|
+
*/
|
|
47
|
+
retrieve(id: string): Promise<ApiKey> {
|
|
56
48
|
return this.get(`/${id}`);
|
|
57
49
|
}
|
|
58
50
|
|
package/src/InteractionsApi.ts
CHANGED
|
@@ -33,7 +33,13 @@ import type {
|
|
|
33
33
|
ResolveInteractionQuery,
|
|
34
34
|
} from '@vertesia/common';
|
|
35
35
|
import type { VertesiaClient } from './client.js';
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
checkRateLimit,
|
|
38
|
+
type ExecuteInteractionRequestOptions,
|
|
39
|
+
executeInteraction,
|
|
40
|
+
executeInteractionAsync,
|
|
41
|
+
executeInteractionByName,
|
|
42
|
+
} from './execute.js';
|
|
37
43
|
import { InteractionCatalogApi } from './InteractionCatalogApi.js';
|
|
38
44
|
import { type EnhancedInteractionExecutionResult, enhanceInteractionExecutionResult } from './InteractionOutput.js';
|
|
39
45
|
|
|
@@ -222,13 +228,14 @@ export default class InteractionsApi extends ApiTopic {
|
|
|
222
228
|
* @param nameWithTag
|
|
223
229
|
* @param payload
|
|
224
230
|
* @param onChunk
|
|
231
|
+
* @param requestOptions request options, e.g. `{ query: { include_prompt: false } }` to omit the rendered prompt
|
|
225
232
|
* @returns
|
|
226
233
|
*/
|
|
227
234
|
async executeByName<ResultT = unknown, ParamsT = unknown>(
|
|
228
235
|
nameWithTag: string,
|
|
229
236
|
payload: InteractionExecutionPayload = {},
|
|
230
237
|
onChunk?: (chunk: string) => void,
|
|
231
|
-
requestOptions?:
|
|
238
|
+
requestOptions?: ExecuteInteractionRequestOptions,
|
|
232
239
|
): Promise<EnhancedInteractionExecutionResult<ResultT, ParamsT>> {
|
|
233
240
|
const r = await executeInteractionByName<ParamsT>(
|
|
234
241
|
this.client as VertesiaClient,
|
package/src/RunsApi.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ExecutionRunRef,
|
|
9
9
|
FindPayload,
|
|
10
10
|
FindRunResult,
|
|
11
|
+
GetRunQuery,
|
|
11
12
|
InteractionExecutionResult,
|
|
12
13
|
PopulatedExecutionRun,
|
|
13
14
|
RunClonePayload,
|
|
@@ -67,10 +68,14 @@ export class RunsApi extends ApiTopic {
|
|
|
67
68
|
* Get a run by id
|
|
68
69
|
*
|
|
69
70
|
* @param id
|
|
71
|
+
* @param query response options, e.g. `{ include_prompt: false }` to omit the rendered prompt
|
|
70
72
|
* @returns InteractionResult
|
|
71
73
|
**/
|
|
72
|
-
async retrieve<ResultT = unknown, ParamsT = unknown>(
|
|
73
|
-
|
|
74
|
+
async retrieve<ResultT = unknown, ParamsT = unknown>(
|
|
75
|
+
id: string,
|
|
76
|
+
query?: GetRunQuery,
|
|
77
|
+
): Promise<EnhancedExecutionRun<ResultT, ParamsT>> {
|
|
78
|
+
const r = await this.get<ExecutionRun<ParamsT>>(`/${id}`, { query });
|
|
74
79
|
return enhanceExecutionRun<ResultT, ParamsT>(r);
|
|
75
80
|
}
|
|
76
81
|
|
package/src/execute.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { IRequestParams } from '@vertesia/api-fetch-client';
|
|
|
2
2
|
import {
|
|
3
3
|
type AsyncExecutionPayload,
|
|
4
4
|
type AsyncExecutionResult,
|
|
5
|
+
type ExecuteNamedInteractionQuery,
|
|
5
6
|
ExecutionRunStatus,
|
|
6
7
|
type InteractionExecutionPayload,
|
|
7
8
|
type InteractionExecutionResult,
|
|
@@ -23,6 +24,20 @@ const INTERACTION_EXECUTION_TIMEOUT_MS = (() => {
|
|
|
23
24
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 30 * 60 * 1000; // 30 minutes
|
|
24
25
|
})();
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Per-request options for a synchronous named-interaction execution: the request options this method
|
|
29
|
+
* can honour, plus the published execute query.
|
|
30
|
+
*
|
|
31
|
+
* `reader` and `jsonPayload` are left out: the method parses the JSON execution result and serializes
|
|
32
|
+
* the payload it builds, so either would break the call. `query` is the typed execute query instead of
|
|
33
|
+
* a free-form record, so a misspelt parameter fails to compile rather than being ignored by the server.
|
|
34
|
+
* With `onChunk`, the options apply to the initial request only; the stream that follows is a separate
|
|
35
|
+
* connection.
|
|
36
|
+
*/
|
|
37
|
+
export type ExecuteInteractionRequestOptions = Omit<IRequestParams, 'reader' | 'jsonPayload' | 'query'> & {
|
|
38
|
+
query?: ExecuteNamedInteractionQuery;
|
|
39
|
+
};
|
|
40
|
+
|
|
26
41
|
export async function EventSourceProvider(): Promise<typeof EventSource> {
|
|
27
42
|
if (typeof globalThis.EventSource === 'function') {
|
|
28
43
|
return globalThis.EventSource;
|
|
@@ -81,6 +96,7 @@ export async function executeInteraction<P = unknown>(
|
|
|
81
96
|
* @param interaction
|
|
82
97
|
* @param payload
|
|
83
98
|
* @param onChunk
|
|
99
|
+
* @param requestOptions request options, e.g. `{ query: { include_prompt: false } }` to omit the rendered prompt
|
|
84
100
|
* @returns
|
|
85
101
|
*/
|
|
86
102
|
export async function executeInteractionByName<P = unknown>(
|
|
@@ -88,7 +104,7 @@ export async function executeInteractionByName<P = unknown>(
|
|
|
88
104
|
interaction: string,
|
|
89
105
|
payload: InteractionExecutionPayload = {},
|
|
90
106
|
onChunk?: (chunk: string) => void,
|
|
91
|
-
requestOptions?:
|
|
107
|
+
requestOptions?: ExecuteInteractionRequestOptions,
|
|
92
108
|
): Promise<InteractionExecutionResult<P>> {
|
|
93
109
|
const stream = !!onChunk;
|
|
94
110
|
const response = await client.post<InteractionExecutionResult<P>>('/api/v1/execute', {
|
|
@@ -98,8 +114,14 @@ export async function executeInteractionByName<P = unknown>(
|
|
|
98
114
|
interaction,
|
|
99
115
|
stream,
|
|
100
116
|
} as NamedInteractionExecutionPayload,
|
|
101
|
-
// Synchronous interaction execution blocks on the model; keep a long client timeout.
|
|
102
|
-
|
|
117
|
+
// Synchronous interaction execution blocks on the model; keep a long client timeout. An explicit
|
|
118
|
+
// timeout wins, including `null`, `false` or `0`, which disable it.
|
|
119
|
+
timeoutMs:
|
|
120
|
+
requestOptions?.timeoutMs !== undefined
|
|
121
|
+
? requestOptions.timeoutMs
|
|
122
|
+
: stream
|
|
123
|
+
? undefined
|
|
124
|
+
: INTERACTION_EXECUTION_TIMEOUT_MS,
|
|
103
125
|
});
|
|
104
126
|
if (stream) {
|
|
105
127
|
if (response.status === ExecutionRunStatus.failed) {
|
|
@@ -167,8 +189,13 @@ export async function executeInteractionAsync(
|
|
|
167
189
|
client: VertesiaClient,
|
|
168
190
|
payload: AsyncExecutionPayload,
|
|
169
191
|
): Promise<AsyncExecutionResult> {
|
|
192
|
+
// A conversation starts an agent run: without `idempotency_key` a replay could start a second one,
|
|
193
|
+
// so opt out of any client-level retry policy (see `AgentsApi.start`). With a key, a replay
|
|
194
|
+
// returns the run the first request started.
|
|
195
|
+
const unkeyedConversation = payload.type === 'conversation' && !payload.idempotency_key;
|
|
170
196
|
return await client.post('/api/v1/execute/async', {
|
|
171
197
|
payload,
|
|
198
|
+
retryPolicy: unkeyedConversation ? false : undefined,
|
|
172
199
|
});
|
|
173
200
|
}
|
|
174
201
|
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type { EnableEnvironmentModelPayload, OrphanedAppInstallation } from '@ve
|
|
|
4
4
|
export { getOAuthPermissionScopes, Permission } from '@vertesia/common';
|
|
5
5
|
export * from './client.js';
|
|
6
6
|
export { default as DelegationGrantsApi } from './DelegationGrantsApi.js';
|
|
7
|
+
export type { ExecuteInteractionRequestOptions } from './execute.js';
|
|
7
8
|
export type { GroupsQueryOptions } from './GroupsApi.js';
|
|
8
9
|
export * from './InteractionBase.js';
|
|
9
10
|
export * from './InteractionOutput.js';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Readable } from 'node:stream';
|
|
2
|
-
import {
|
|
2
|
+
import { finished } from 'node:stream/promises';
|
|
3
3
|
import { StreamSource } from '../StreamSource.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A stream source that wraps a Node.js Readable stream.
|
|
7
7
|
* This class is only works in Node.js environments.
|
|
8
|
+
* Cancelling the web stream destroys the Node.js stream, releasing its underlying resource (e.g. a file descriptor).
|
|
8
9
|
*/
|
|
9
10
|
export class NodeStreamSource extends StreamSource {
|
|
10
11
|
constructor(stream: Readable, name: string, type?: string, id?: string) {
|
|
@@ -12,31 +13,34 @@ export class NodeStreamSource extends StreamSource {
|
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
function readableToWebStream<T = string | Buffer>(stream: Readable): ReadableStream<T> {
|
|
16
|
-
if (NodeReadableStream.from) {
|
|
17
|
-
return NodeReadableStream.from(stream) as ReadableStream<T>;
|
|
18
|
-
} else {
|
|
19
|
-
return readableToWebStream_BUN(stream);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
16
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
17
|
+
* Not ReadableStream.from: it cancels by calling return() on the Node.js async iterator, which is a no-op
|
|
18
|
+
* when nothing was read yet, so the Node.js stream would stay open. Also covers Bun, which lacks ReadableStream.from.
|
|
26
19
|
*/
|
|
27
|
-
function
|
|
20
|
+
function readableToWebStream<T = string | Buffer>(stream: Readable): ReadableStream<T> {
|
|
21
|
+
// Nothing listens until the first read, so an error before it (e.g. a failed lazy file open) would otherwise
|
|
22
|
+
// crash the process. The iterator still reports the error on the next read.
|
|
23
|
+
stream.on('error', () => undefined);
|
|
28
24
|
const it = stream[Symbol.asyncIterator]();
|
|
29
|
-
return new ReadableStream<T>(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
return new ReadableStream<T>(
|
|
26
|
+
{
|
|
27
|
+
async pull(controller) {
|
|
28
|
+
const { value, done } = await it.next();
|
|
29
|
+
if (done) {
|
|
30
|
+
controller.close();
|
|
31
|
+
} else {
|
|
32
|
+
controller.enqueue(value);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
async cancel() {
|
|
36
|
+
// no error argument: it would emit 'error', which the caller may not listen for
|
|
37
|
+
stream.destroy();
|
|
38
|
+
// resolve once the underlying resource is released, so callers can remove the file afterwards;
|
|
39
|
+
// bounded because some streams never report their close
|
|
40
|
+
await finished(stream, { signal: AbortSignal.timeout(5_000) }).catch(() => undefined);
|
|
41
|
+
},
|
|
40
42
|
},
|
|
41
|
-
|
|
43
|
+
// read on demand, like ReadableStream.from
|
|
44
|
+
{ highWaterMark: 0 },
|
|
45
|
+
);
|
|
42
46
|
}
|
package/src/store/AgentsApi.ts
CHANGED
|
@@ -87,13 +87,22 @@ export class AgentsApi extends ApiTopic {
|
|
|
87
87
|
/**
|
|
88
88
|
* Create and start a new agent run.
|
|
89
89
|
* Returns the created AgentRun with its stable id.
|
|
90
|
+
*
|
|
91
|
+
* Set `idempotency_key` on an agent run to make the call safe to retry: the client's retry policy
|
|
92
|
+
* then applies, and a replayed request returns the run the first one started.
|
|
90
93
|
*/
|
|
91
94
|
start<TData = Record<string, unknown>>(payload: CreateAgentRunPayload<TData>): Promise<AgentRun<TData>>;
|
|
92
95
|
start<TData = Record<string, unknown>>(payload: CreateProcessRunPayload<TData>): Promise<ProcessRun>;
|
|
93
96
|
start<TData = Record<string, unknown>>(
|
|
94
97
|
payload: CreateAgentRunPayload<TData> | CreateProcessRunPayload<TData>,
|
|
95
98
|
): Promise<AgentRun<TData> | ProcessRun> {
|
|
96
|
-
|
|
99
|
+
// Without a key, starting an agent run is not idempotent: a request abandoned client-side can
|
|
100
|
+
// still complete server-side, so a replay would start a second run. Opt out of any client-level
|
|
101
|
+
// retry policy explicitly rather than relying on POST being absent from its method list.
|
|
102
|
+
// Rate-limiter pacing retries are unaffected: those happen before the request reaches the
|
|
103
|
+
// handler. Process starts take no key and keep the client's policy.
|
|
104
|
+
const unkeyedAgentStart = 'interaction' in payload && !payload.idempotency_key;
|
|
105
|
+
return this.post('/', { payload, retryPolicy: unkeyedAgentStart ? false : undefined });
|
|
97
106
|
}
|
|
98
107
|
|
|
99
108
|
/**
|
package/src/store/FilesApi.ts
CHANGED
|
@@ -258,11 +258,17 @@ export class FilesApi extends ApiTopic {
|
|
|
258
258
|
'Content-Type': sourceMimeType,
|
|
259
259
|
},
|
|
260
260
|
}).catch((err) => {
|
|
261
|
-
console.error('Failed to upload file', { err, url, id, path });
|
|
261
|
+
console.error('Failed to upload file', { err, location: fileLocationForError(url), id, path });
|
|
262
262
|
throw err;
|
|
263
263
|
});
|
|
264
264
|
if (!res.ok) {
|
|
265
|
-
console.
|
|
265
|
+
console.error('Failed to upload file', {
|
|
266
|
+
status: res.status,
|
|
267
|
+
statusText: res.statusText,
|
|
268
|
+
location: fileLocationForError(url),
|
|
269
|
+
id,
|
|
270
|
+
path,
|
|
271
|
+
});
|
|
266
272
|
throw new Error(`Failed to upload file: ${res.statusText}`);
|
|
267
273
|
}
|
|
268
274
|
|
package/src/store/IndexingApi.ts
CHANGED
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
SwapAliasResult,
|
|
28
28
|
TriggerReindexResult,
|
|
29
29
|
} from '@vertesia/common';
|
|
30
|
+
import { zenoBulkBaseUrl } from './zeno-bulk.js';
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* API for indexing operations on content objects.
|
|
@@ -274,30 +275,14 @@ export class IndexingApi extends ApiTopic {
|
|
|
274
275
|
|
|
275
276
|
// ========================================================================
|
|
276
277
|
// Zeno Bulk endpoints (Go migration service)
|
|
277
|
-
// Routes via LB path rules in prod, or derived URL in dev.
|
|
278
|
+
// Routes via LB path rules in prod, or derived URL in dev (see zenoBulkBaseUrl).
|
|
278
279
|
// ========================================================================
|
|
279
280
|
|
|
280
|
-
/**
|
|
281
|
-
* Get the zeno-bulk base URL.
|
|
282
|
-
* Dev branches: store URL contains "zeno-server" -> replace with "zeno-bulk".
|
|
283
|
-
* Production/preview: same domain, LB routes /reindex/* to zeno-bulk.
|
|
284
|
-
*/
|
|
285
|
-
private get zenoBulkBaseUrl(): string {
|
|
286
|
-
const storeBaseUrl = this.client.baseUrl;
|
|
287
|
-
if (storeBaseUrl.includes('localhost:') || storeBaseUrl.includes('127.0.0.1:')) {
|
|
288
|
-
return 'https://zeno-bulk-dev-main.api.dev1.vertesia.io';
|
|
289
|
-
}
|
|
290
|
-
if (storeBaseUrl.includes('zeno-server')) {
|
|
291
|
-
return storeBaseUrl.replace(/zeno-server/, 'zeno-bulk');
|
|
292
|
-
}
|
|
293
|
-
return storeBaseUrl;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
281
|
/**
|
|
297
282
|
* POST to a zeno-bulk endpoint. Resolves the path against the zeno-bulk base URL.
|
|
298
283
|
*/
|
|
299
284
|
private zenoBulkPost<T>(path: string, body: object): Promise<T> {
|
|
300
|
-
return this.client.post(this.
|
|
285
|
+
return this.client.post(zenoBulkBaseUrl(this.client.baseUrl) + path, { payload: body });
|
|
301
286
|
}
|
|
302
287
|
|
|
303
288
|
/**
|
package/src/store/ObjectsApi.ts
CHANGED
|
@@ -63,6 +63,7 @@ import { AnalyzeDocApi } from './AnalyzeDocApi.js';
|
|
|
63
63
|
import type { ZenoClient } from './client.js';
|
|
64
64
|
import { fetchSignedUrl } from './signed-url.js';
|
|
65
65
|
import { getUploadMimeTypeHint, resolveUploadMimeType } from './uploadMimeType.js';
|
|
66
|
+
import { zenoBulkBaseUrl } from './zeno-bulk.js';
|
|
66
67
|
|
|
67
68
|
/**
|
|
68
69
|
* The two write payloads, each widened at `content` so callers can hand us a browser `File` or a
|
|
@@ -215,24 +216,8 @@ export class ObjectsApi extends ApiTopic {
|
|
|
215
216
|
return this.zenoBulkPost('/export/compose', payload, timeoutMs);
|
|
216
217
|
}
|
|
217
218
|
|
|
218
|
-
/**
|
|
219
|
-
* Get the zeno-bulk base URL.
|
|
220
|
-
* Dev branches: store URL contains "zeno-server" -> replace with "zeno-bulk".
|
|
221
|
-
* Production/preview: same domain, LB routes /export to zeno-bulk.
|
|
222
|
-
*/
|
|
223
|
-
private get zenoBulkBaseUrl(): string {
|
|
224
|
-
const storeBaseUrl = this.client.baseUrl;
|
|
225
|
-
if (storeBaseUrl.includes('localhost:') || storeBaseUrl.includes('127.0.0.1:')) {
|
|
226
|
-
return 'https://zeno-bulk-dev-main.api.dev1.vertesia.io';
|
|
227
|
-
}
|
|
228
|
-
if (storeBaseUrl.includes('zeno-server')) {
|
|
229
|
-
return storeBaseUrl.replace(/zeno-server/, 'zeno-bulk');
|
|
230
|
-
}
|
|
231
|
-
return storeBaseUrl;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
219
|
private zenoBulkPost<T>(path: string, body: object, timeoutMs?: number | false | null): Promise<T> {
|
|
235
|
-
return this.client.post(this.
|
|
220
|
+
return this.client.post(zenoBulkBaseUrl(this.client.baseUrl) + path, { payload: body, timeoutMs });
|
|
236
221
|
}
|
|
237
222
|
|
|
238
223
|
listFolders(_path: string = '/') {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type RuntimeProcess = {
|
|
2
|
+
env?: Record<string, string | undefined>;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
/** The ZENO_BULK_URL environment variable, in a runtime that has one. */
|
|
6
|
+
function getRuntimeZenoBulkUrl() {
|
|
7
|
+
const runtimeProcess = (globalThis as typeof globalThis & { process?: RuntimeProcess }).process;
|
|
8
|
+
return runtimeProcess?.env?.ZENO_BULK_URL || undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The base URL of zeno-bulk, the service behind the bulk export and reindex endpoints, for a store base URL.
|
|
13
|
+
* - ZENO_BULK_URL, when the runtime sets it: a local stack that runs its own zeno-bulk, or none, points it there.
|
|
14
|
+
* - A store on localhost: the dev1 zeno-bulk, which serves the database a default local stack uses.
|
|
15
|
+
* - A dev-branch store, whose host names zeno-server: the matching zeno-bulk host.
|
|
16
|
+
* - Any other store: its own domain, whose load balancer routes the bulk paths to zeno-bulk.
|
|
17
|
+
*/
|
|
18
|
+
export function zenoBulkBaseUrl(storeBaseUrl: string): string {
|
|
19
|
+
const override = getRuntimeZenoBulkUrl();
|
|
20
|
+
if (override) {
|
|
21
|
+
return override.replace(/\/+$/, '');
|
|
22
|
+
}
|
|
23
|
+
if (storeBaseUrl.includes('localhost:') || storeBaseUrl.includes('127.0.0.1:')) {
|
|
24
|
+
return 'https://zeno-bulk-dev-main.api.dev1.vertesia.io';
|
|
25
|
+
}
|
|
26
|
+
if (storeBaseUrl.includes('zeno-server')) {
|
|
27
|
+
return storeBaseUrl.replace(/zeno-server/, 'zeno-bulk');
|
|
28
|
+
}
|
|
29
|
+
return storeBaseUrl;
|
|
30
|
+
}
|