roe-typescript 0.1.2 → 1.0.0
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/README.md +48 -7
- package/dist/api/agents.d.ts +40 -27
- package/dist/api/agents.js +222 -112
- package/dist/api/policies.d.ts +15 -9
- package/dist/api/policies.js +75 -31
- package/dist/api/users.d.ts +18 -0
- package/dist/api/users.js +17 -0
- package/dist/client.d.ts +6 -2
- package/dist/client.js +17 -5
- package/dist/exceptions.js +8 -0
- package/dist/generated/client.d.ts +12 -0
- package/dist/generated/client.js +55 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +9 -5
- package/dist/models/file.d.ts +17 -0
- package/dist/models/file.js +36 -0
- package/dist/models/job.d.ts +30 -6
- package/dist/models/job.js +130 -37
- package/dist/utils/dynamicInputs.d.ts +30 -0
- package/dist/utils/dynamicInputs.js +114 -0
- package/dist/utils/middleware.d.ts +6 -0
- package/dist/utils/middleware.js +80 -0
- package/package.json +6 -6
- package/dist/models/agent.d.ts +0 -78
- package/dist/models/agent.js +0 -40
- package/dist/models/policy.d.ts +0 -19
- package/dist/models/policy.js +0 -1
- package/dist/models/responses.d.ts +0 -71
- package/dist/models/responses.js +0 -36
- package/dist/models/user.d.ts +0 -6
- package/dist/models/user.js +0 -1
- package/dist/utils/httpClient.d.ts +0 -30
- package/dist/utils/httpClient.js +0 -229
package/dist/api/policies.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { PaginationHelper } from "../utils/pagination.js";
|
|
2
1
|
import { isUuidString } from "../utils/fileDetection.js";
|
|
3
2
|
import { BadRequestError, RoeAPIException } from "../exceptions.js";
|
|
4
3
|
/**
|
|
@@ -14,77 +13,122 @@ export class PolicyVersionsAPI {
|
|
|
14
13
|
constructor(policiesApi) {
|
|
15
14
|
this.policiesApi = policiesApi;
|
|
16
15
|
}
|
|
17
|
-
get
|
|
18
|
-
return this.policiesApi.
|
|
16
|
+
get raw() {
|
|
17
|
+
return this.policiesApi.raw;
|
|
18
|
+
}
|
|
19
|
+
get organizationId() {
|
|
20
|
+
return this.policiesApi.config.organizationId;
|
|
19
21
|
}
|
|
20
22
|
async list(policyId) {
|
|
21
23
|
validateUuid(policyId, "policyId");
|
|
22
|
-
const data = await this.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const { data } = await this.raw.GET("/v1/policies/{policy_id}/versions/", {
|
|
25
|
+
params: {
|
|
26
|
+
path: { policy_id: policyId },
|
|
27
|
+
query: { organization_id: this.organizationId },
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
return data?.results ?? [];
|
|
26
31
|
}
|
|
27
32
|
async retrieve(policyId, versionId) {
|
|
28
33
|
validateUuid(policyId, "policyId");
|
|
29
34
|
validateUuid(versionId, "versionId");
|
|
30
|
-
|
|
35
|
+
const { data } = await this.raw.GET("/v1/policies/{policy_id}/versions/{version_id}/", {
|
|
36
|
+
params: {
|
|
37
|
+
path: { policy_id: policyId, version_id: versionId },
|
|
38
|
+
query: { organization_id: this.organizationId },
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
return data;
|
|
31
42
|
}
|
|
32
43
|
async create(params) {
|
|
33
44
|
validateUuid(params.policyId, "policyId");
|
|
34
45
|
if (params.baseVersionId !== undefined)
|
|
35
46
|
validateUuid(params.baseVersionId, "baseVersionId");
|
|
36
|
-
const
|
|
47
|
+
const body = {
|
|
48
|
+
content: params.content,
|
|
49
|
+
};
|
|
37
50
|
if (params.versionName !== undefined)
|
|
38
|
-
|
|
51
|
+
body.version_name = params.versionName;
|
|
39
52
|
if (params.baseVersionId !== undefined)
|
|
40
|
-
|
|
41
|
-
const data = await this.
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
body.base_version_id = params.baseVersionId;
|
|
54
|
+
const { data } = await this.raw.POST("/v1/policies/{policy_id}/versions/", {
|
|
55
|
+
params: {
|
|
56
|
+
path: { policy_id: params.policyId },
|
|
57
|
+
query: { organization_id: this.organizationId },
|
|
58
|
+
},
|
|
59
|
+
body,
|
|
44
60
|
});
|
|
45
|
-
if (!data
|
|
61
|
+
if (!data?.id) {
|
|
46
62
|
throw new RoeAPIException(`Unexpected response from server: ${JSON.stringify(data)}`);
|
|
47
63
|
}
|
|
48
|
-
// POST returns partial
|
|
64
|
+
// POST returns a partial CreatePolicyVersion; re-fetch to get the full version.
|
|
49
65
|
return this.retrieve(params.policyId, data.id);
|
|
50
66
|
}
|
|
51
67
|
}
|
|
52
68
|
export class PoliciesAPI {
|
|
53
|
-
constructor(config,
|
|
69
|
+
constructor(config, raw) {
|
|
54
70
|
this.config = config;
|
|
55
|
-
this.
|
|
71
|
+
this.raw = raw;
|
|
56
72
|
this.versions = new PolicyVersionsAPI(this);
|
|
57
73
|
}
|
|
58
74
|
async list(params) {
|
|
59
|
-
const
|
|
60
|
-
|
|
75
|
+
const { data } = await this.raw.GET("/v1/policies/", {
|
|
76
|
+
params: {
|
|
77
|
+
query: {
|
|
78
|
+
organization_id: this.config.organizationId,
|
|
79
|
+
page: params?.page,
|
|
80
|
+
page_size: params?.pageSize,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
return data;
|
|
61
85
|
}
|
|
62
86
|
async retrieve(policyId) {
|
|
63
87
|
validateUuid(policyId, "policyId");
|
|
64
|
-
|
|
88
|
+
const { data } = await this.raw.GET("/v1/policies/{id}/", {
|
|
89
|
+
params: {
|
|
90
|
+
path: { id: policyId },
|
|
91
|
+
query: { organization_id: this.config.organizationId },
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
return data;
|
|
65
95
|
}
|
|
66
96
|
async create(params) {
|
|
67
|
-
const
|
|
97
|
+
const body = {
|
|
68
98
|
name: params.name,
|
|
69
99
|
content: params.content,
|
|
70
100
|
description: params.description ?? "",
|
|
71
|
-
|
|
101
|
+
version_name: params.versionName ?? "version 1",
|
|
72
102
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
103
|
+
const { data } = await this.raw.POST("/v1/policies/", {
|
|
104
|
+
params: { query: { organization_id: this.config.organizationId } },
|
|
105
|
+
body,
|
|
106
|
+
});
|
|
107
|
+
return data;
|
|
76
108
|
}
|
|
77
109
|
async update(policyId, updates) {
|
|
78
110
|
validateUuid(policyId, "policyId");
|
|
79
|
-
const
|
|
111
|
+
const body = {};
|
|
80
112
|
if (updates.name !== undefined)
|
|
81
|
-
|
|
113
|
+
body.name = updates.name;
|
|
82
114
|
if (updates.description !== undefined)
|
|
83
|
-
|
|
84
|
-
|
|
115
|
+
body.description = updates.description;
|
|
116
|
+
const { data } = await this.raw.PATCH("/v1/policies/{id}/", {
|
|
117
|
+
params: {
|
|
118
|
+
path: { id: policyId },
|
|
119
|
+
query: { organization_id: this.config.organizationId },
|
|
120
|
+
},
|
|
121
|
+
body,
|
|
122
|
+
});
|
|
123
|
+
return data;
|
|
85
124
|
}
|
|
86
125
|
async delete(policyId) {
|
|
87
126
|
validateUuid(policyId, "policyId");
|
|
88
|
-
await this.
|
|
127
|
+
await this.raw.DELETE("/v1/policies/{id}/", {
|
|
128
|
+
params: {
|
|
129
|
+
path: { id: policyId },
|
|
130
|
+
query: { organization_id: this.config.organizationId },
|
|
131
|
+
},
|
|
132
|
+
});
|
|
89
133
|
}
|
|
90
134
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RoeConfig } from "../config.js";
|
|
2
|
+
import type { RoeRawClient } from "../generated/client.js";
|
|
3
|
+
import type { components } from "../generated/schema.js";
|
|
4
|
+
type User = components["schemas"]["UserInfo"];
|
|
5
|
+
export declare class UsersAPI {
|
|
6
|
+
readonly config: RoeConfig;
|
|
7
|
+
readonly raw: RoeRawClient;
|
|
8
|
+
constructor(config: RoeConfig, raw: RoeRawClient);
|
|
9
|
+
/**
|
|
10
|
+
* Retrieve the currently authenticated user.
|
|
11
|
+
*
|
|
12
|
+
* Wraps `GET /v1/users/current_user/`. The OpenAPI spec marks the response
|
|
13
|
+
* body as undocumented, so we read JSON via openapi-fetch's `parseAs` escape
|
|
14
|
+
* hatch and cast the result to `UserInfo` (the schema the backend returns).
|
|
15
|
+
*/
|
|
16
|
+
me(): Promise<User>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class UsersAPI {
|
|
2
|
+
constructor(config, raw) {
|
|
3
|
+
this.config = config;
|
|
4
|
+
this.raw = raw;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Retrieve the currently authenticated user.
|
|
8
|
+
*
|
|
9
|
+
* Wraps `GET /v1/users/current_user/`. The OpenAPI spec marks the response
|
|
10
|
+
* body as undocumented, so we read JSON via openapi-fetch's `parseAs` escape
|
|
11
|
+
* hatch and cast the result to `UserInfo` (the schema the backend returns).
|
|
12
|
+
*/
|
|
13
|
+
async me() {
|
|
14
|
+
const result = await this.raw.GET("/v1/users/current_user/", { parseAs: "json" });
|
|
15
|
+
return result.data;
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { AgentsAPI } from "./api/agents.js";
|
|
2
2
|
import { PoliciesAPI } from "./api/policies.js";
|
|
3
|
+
import { UsersAPI } from "./api/users.js";
|
|
3
4
|
import { RoeAuth } from "./auth.js";
|
|
4
5
|
import { RoeConfig, RoeConfigInput } from "./config.js";
|
|
5
|
-
import {
|
|
6
|
+
import { type RoeRawClient } from "./generated/client.js";
|
|
6
7
|
export declare class RoeClient {
|
|
7
8
|
readonly config: RoeConfig;
|
|
8
9
|
readonly auth: RoeAuth;
|
|
9
|
-
readonly
|
|
10
|
+
readonly raw: RoeRawClient;
|
|
10
11
|
private readonly _agents;
|
|
11
12
|
private readonly _policies;
|
|
13
|
+
private readonly _users;
|
|
12
14
|
constructor(input?: RoeConfigInput);
|
|
13
15
|
get agents(): AgentsAPI;
|
|
14
16
|
get policies(): PoliciesAPI;
|
|
17
|
+
get users(): UsersAPI;
|
|
18
|
+
/** No-op kept for source compatibility; the raw client manages its own connections. */
|
|
15
19
|
close(): void;
|
|
16
20
|
}
|
package/dist/client.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { AgentsAPI } from "./api/agents.js";
|
|
2
2
|
import { PoliciesAPI } from "./api/policies.js";
|
|
3
|
+
import { UsersAPI } from "./api/users.js";
|
|
3
4
|
import { RoeAuth } from "./auth.js";
|
|
4
5
|
import { RoeConfig } from "./config.js";
|
|
5
|
-
import {
|
|
6
|
+
import { createRoeRawClient } from "./generated/client.js";
|
|
6
7
|
export class RoeClient {
|
|
7
8
|
constructor(input = {}) {
|
|
8
9
|
this.config = RoeConfig.fromEnv(input);
|
|
9
10
|
this.auth = new RoeAuth(this.config);
|
|
10
|
-
this.
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
this.raw = createRoeRawClient({
|
|
12
|
+
baseUrl: this.config.baseUrl,
|
|
13
|
+
// Auth headers are injected per-request by authMiddleware; no static
|
|
14
|
+
// headers option here so a stale snapshot can't shadow the live token.
|
|
15
|
+
auth: this.auth,
|
|
16
|
+
maxRetries: this.config.maxRetries,
|
|
17
|
+
});
|
|
18
|
+
this._agents = new AgentsAPI(this.config, this.raw);
|
|
19
|
+
this._policies = new PoliciesAPI(this.config, this.raw);
|
|
20
|
+
this._users = new UsersAPI(this.config, this.raw);
|
|
13
21
|
}
|
|
14
22
|
get agents() {
|
|
15
23
|
return this._agents;
|
|
@@ -17,7 +25,11 @@ export class RoeClient {
|
|
|
17
25
|
get policies() {
|
|
18
26
|
return this._policies;
|
|
19
27
|
}
|
|
28
|
+
get users() {
|
|
29
|
+
return this._users;
|
|
30
|
+
}
|
|
31
|
+
/** No-op kept for source compatibility; the raw client manages its own connections. */
|
|
20
32
|
close() {
|
|
21
|
-
|
|
33
|
+
/* no-op */
|
|
22
34
|
}
|
|
23
35
|
}
|
package/dist/exceptions.js
CHANGED
|
@@ -74,6 +74,14 @@ export function extractErrorMessage(data, statusCode) {
|
|
|
74
74
|
return firstError.message;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
+
for (const value of Object.values(obj)) {
|
|
78
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
79
|
+
return value.map(String).join("; ");
|
|
80
|
+
}
|
|
81
|
+
if (typeof value === "string" && value.length > 0) {
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
77
85
|
}
|
|
78
86
|
// Fallback to generic message
|
|
79
87
|
return `HTTP ${statusCode} error`;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { components, paths } from "./schema.js";
|
|
2
|
+
import type { RoeAuth } from "../auth.js";
|
|
3
|
+
export type RoeApiComponents = components;
|
|
4
|
+
export type RoeApiPaths = paths;
|
|
5
|
+
export type RoeRawClient = ReturnType<typeof createRoeRawClient>;
|
|
6
|
+
export declare function createRoeRawClient(options: {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
headers?: HeadersInit;
|
|
9
|
+
fetch?: typeof fetch;
|
|
10
|
+
auth?: RoeAuth;
|
|
11
|
+
maxRetries?: number;
|
|
12
|
+
}): import("openapi-fetch").Client<paths, `${string}/${string}`>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Hand-maintained boilerplate. Lives under src/generated/ alongside schema.d.ts
|
|
2
|
+
// because it imports from it. Drift CI regenerates schema.d.ts and verifies
|
|
3
|
+
// this file is unchanged.
|
|
4
|
+
import createClient from "openapi-fetch";
|
|
5
|
+
import { authMiddleware, errorMiddleware, retryMiddleware, } from "../utils/middleware.js";
|
|
6
|
+
// Default fetch: resolves globalThis.fetch at call time so vitest's
|
|
7
|
+
// vi.stubGlobal('fetch', ...) is honored. In Node 18+ globalThis.fetch is
|
|
8
|
+
// undici-backed, so streaming bodies work end-to-end. For the multipart-with-
|
|
9
|
+
// Node-stream case in AgentsAPI we'll import undici.fetch directly.
|
|
10
|
+
const defaultFetch = (...args) => globalThis.fetch(...args);
|
|
11
|
+
function isNetworkFetchError(error) {
|
|
12
|
+
return error instanceof TypeError && /fetch failed/i.test(error.message);
|
|
13
|
+
}
|
|
14
|
+
function networkRetryFetch(fetchImpl, maxRetries) {
|
|
15
|
+
return async (input, init) => {
|
|
16
|
+
let attempt = 0;
|
|
17
|
+
while (true) {
|
|
18
|
+
try {
|
|
19
|
+
// `Request` bodies are single-use. Clone before each attempt so a
|
|
20
|
+
// transient socket failure can be retried without disturbing the
|
|
21
|
+
// original request object openapi-fetch handed us.
|
|
22
|
+
const retryableInput = maxRetries > 0 && input instanceof Request ? input.clone() : input;
|
|
23
|
+
return await fetchImpl(retryableInput, init);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (attempt >= maxRetries || !isNetworkFetchError(error)) {
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
const backoffMs = Math.min(1000 * 2 ** attempt, 10000);
|
|
30
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
31
|
+
attempt += 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function createRoeRawClient(options) {
|
|
37
|
+
const maxRetries = options.maxRetries ?? 0;
|
|
38
|
+
const client = createClient({
|
|
39
|
+
baseUrl: options.baseUrl,
|
|
40
|
+
headers: options.headers,
|
|
41
|
+
fetch: networkRetryFetch(options.fetch ?? defaultFetch, maxRetries),
|
|
42
|
+
});
|
|
43
|
+
// openapi-fetch runs onRequest in registration order and onResponse in
|
|
44
|
+
// REVERSE registration order. We want responses to flow auth -> retry ->
|
|
45
|
+
// error so the error middleware sees the final post-retry response.
|
|
46
|
+
// Registration order is therefore the inverse: error -> retry -> auth.
|
|
47
|
+
client.use(errorMiddleware);
|
|
48
|
+
if (maxRetries > 0) {
|
|
49
|
+
client.use(retryMiddleware(maxRetries));
|
|
50
|
+
}
|
|
51
|
+
if (options.auth) {
|
|
52
|
+
client.use(authMiddleware(options.auth));
|
|
53
|
+
}
|
|
54
|
+
return client;
|
|
55
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,13 @@ export { RoeClient } from "./client.js";
|
|
|
2
2
|
export { RoeConfig } from "./config.js";
|
|
3
3
|
export type { RoeConfigInput } from "./config.js";
|
|
4
4
|
export { RoeAuth } from "./auth.js";
|
|
5
|
+
export { createRoeRawClient } from "./generated/client.js";
|
|
6
|
+
export type { RoeApiComponents, RoeApiPaths, RoeRawClient } from "./generated/client.js";
|
|
7
|
+
export type { components, paths } from "./generated/schema.js";
|
|
5
8
|
export * from "./exceptions.js";
|
|
6
9
|
export * from "./api/agents.js";
|
|
7
10
|
export * from "./api/policies.js";
|
|
8
|
-
export * from "./
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
export
|
|
12
|
-
export * from "./models/file.js";
|
|
11
|
+
export * from "./api/users.js";
|
|
12
|
+
export { Job, JobBatch, JobStatus } from "./models/job.js";
|
|
13
|
+
export type { JobResult, JobBatchItem } from "./models/job.js";
|
|
14
|
+
export { FileUpload } from "./models/file.js";
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
export { RoeClient } from "./client.js";
|
|
2
2
|
export { RoeConfig } from "./config.js";
|
|
3
3
|
export { RoeAuth } from "./auth.js";
|
|
4
|
+
export { createRoeRawClient } from "./generated/client.js";
|
|
4
5
|
export * from "./exceptions.js";
|
|
5
6
|
export * from "./api/agents.js";
|
|
6
7
|
export * from "./api/policies.js";
|
|
7
|
-
export * from "./
|
|
8
|
-
export
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export * from "./api/users.js";
|
|
9
|
+
export { Job, JobBatch, JobStatus } from "./models/job.js";
|
|
10
|
+
export { FileUpload } from "./models/file.js";
|
|
11
|
+
// Hand-written response models removed in v1.0 (Agent, BaseAgent, Policy, PolicyVersion,
|
|
12
|
+
// AgentVersion, AgentDatum, AgentJobResult, AgentJobStatus, Reference, JobDataDeleteResponse,
|
|
13
|
+
// PaginatedResponse, UserInfo). Import the generated equivalents instead, e.g.:
|
|
14
|
+
// import type { components } from "@roe-ai/typescript";
|
|
15
|
+
// type Policy = components["schemas"]["Policy"];
|
package/dist/models/file.d.ts
CHANGED
|
@@ -10,6 +10,13 @@ export declare class FileUpload {
|
|
|
10
10
|
readonly filename?: string;
|
|
11
11
|
readonly mimeType?: string;
|
|
12
12
|
private _openedStream;
|
|
13
|
+
/**
|
|
14
|
+
* Cached Blob built from the stream-backed source. Streams can only be read
|
|
15
|
+
* once, so we buffer their bytes on the first `toBlob()` call and reuse the
|
|
16
|
+
* result on retries — otherwise repeated calls would silently upload an
|
|
17
|
+
* empty file.
|
|
18
|
+
*/
|
|
19
|
+
private _streamBlob;
|
|
13
20
|
constructor(init: FileUploadInit);
|
|
14
21
|
get effectiveFilename(): string;
|
|
15
22
|
get effectiveMimeType(): string;
|
|
@@ -18,6 +25,16 @@ export declare class FileUpload {
|
|
|
18
25
|
* Track opened streams so they can be closed later.
|
|
19
26
|
*/
|
|
20
27
|
open(): NodeJS.ReadableStream;
|
|
28
|
+
/**
|
|
29
|
+
* Loads the file contents as a Blob with the resolved MIME type.
|
|
30
|
+
*
|
|
31
|
+
* Path-backed uploads are read fully into memory before the Blob is built.
|
|
32
|
+
* That keeps the wrapper cross-runtime (browser + Node) at the cost of
|
|
33
|
+
* peak RAM = file size. Real-world files are well under MAX_FILE_SIZE,
|
|
34
|
+
* but if you hit memory pressure switch to a streaming `Readable` and
|
|
35
|
+
* use `undici`-flavored FormData.
|
|
36
|
+
*/
|
|
37
|
+
toBlob(): Promise<Blob>;
|
|
21
38
|
/**
|
|
22
39
|
* Closes any opened file stream to prevent resource leaks.
|
|
23
40
|
* Should be called after the file upload is complete.
|
package/dist/models/file.js
CHANGED
|
@@ -7,6 +7,13 @@ const MAX_FILE_SIZE = 2 * 1024 * 1024 * 1024;
|
|
|
7
7
|
export class FileUpload {
|
|
8
8
|
constructor(init) {
|
|
9
9
|
this._openedStream = null;
|
|
10
|
+
/**
|
|
11
|
+
* Cached Blob built from the stream-backed source. Streams can only be read
|
|
12
|
+
* once, so we buffer their bytes on the first `toBlob()` call and reuse the
|
|
13
|
+
* result on retries — otherwise repeated calls would silently upload an
|
|
14
|
+
* empty file.
|
|
15
|
+
*/
|
|
16
|
+
this._streamBlob = null;
|
|
10
17
|
this.path = init.path;
|
|
11
18
|
this.file = init.file;
|
|
12
19
|
this.filename = init.filename;
|
|
@@ -58,6 +65,35 @@ export class FileUpload {
|
|
|
58
65
|
}
|
|
59
66
|
throw new Error("No file source available");
|
|
60
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Loads the file contents as a Blob with the resolved MIME type.
|
|
70
|
+
*
|
|
71
|
+
* Path-backed uploads are read fully into memory before the Blob is built.
|
|
72
|
+
* That keeps the wrapper cross-runtime (browser + Node) at the cost of
|
|
73
|
+
* peak RAM = file size. Real-world files are well under MAX_FILE_SIZE,
|
|
74
|
+
* but if you hit memory pressure switch to a streaming `Readable` and
|
|
75
|
+
* use `undici`-flavored FormData.
|
|
76
|
+
*/
|
|
77
|
+
async toBlob() {
|
|
78
|
+
if (this.path) {
|
|
79
|
+
const buf = await fs.promises.readFile(this.path);
|
|
80
|
+
return new Blob([buf], { type: this.effectiveMimeType });
|
|
81
|
+
}
|
|
82
|
+
if (this.file) {
|
|
83
|
+
// Streams are single-shot. Buffer the bytes once and cache the resulting
|
|
84
|
+
// Blob so retry attempts (which call `toBlob()` again) don't end up
|
|
85
|
+
// uploading a zero-byte body.
|
|
86
|
+
if (this._streamBlob)
|
|
87
|
+
return this._streamBlob;
|
|
88
|
+
const chunks = [];
|
|
89
|
+
for await (const chunk of this.file) {
|
|
90
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
91
|
+
}
|
|
92
|
+
this._streamBlob = new Blob([Buffer.concat(chunks)], { type: this.effectiveMimeType });
|
|
93
|
+
return this._streamBlob;
|
|
94
|
+
}
|
|
95
|
+
throw new Error("No file source available");
|
|
96
|
+
}
|
|
61
97
|
/**
|
|
62
98
|
* Closes any opened file stream to prevent resource leaks.
|
|
63
99
|
* Should be called after the file upload is complete.
|
package/dist/models/job.d.ts
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
import { AgentsAPI } from "../api/agents.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { components } from "../generated/schema.js";
|
|
3
|
+
export declare enum JobStatus {
|
|
4
|
+
PENDING = 0,
|
|
5
|
+
STARTED = 1,
|
|
6
|
+
RETRY = 2,
|
|
7
|
+
SUCCESS = 3,
|
|
8
|
+
FAILURE = 4,
|
|
9
|
+
CANCELLED = 5,
|
|
10
|
+
CACHED = 6
|
|
11
|
+
}
|
|
12
|
+
type AgentJobStatus = components["schemas"]["AgentJobStatus"];
|
|
13
|
+
type AgentJobResultResponse = components["schemas"]["AgentJobResultResponse"];
|
|
14
|
+
type AgentJobResultItem = components["schemas"]["AgentJobResultItem"];
|
|
15
|
+
type AgentDatum = components["schemas"]["AgentDatum"];
|
|
16
|
+
/** Result returned by `Job.wait()` — generated body merged with terminal status + error. */
|
|
17
|
+
export type JobResult = AgentJobResultResponse & {
|
|
18
|
+
status: number | null;
|
|
19
|
+
error_message: string | null;
|
|
20
|
+
};
|
|
21
|
+
/** Result returned by `JobBatch.wait()` — per-job item merged with normalized error message. */
|
|
22
|
+
export type JobBatchItem = AgentJobResultItem & {
|
|
23
|
+
outputs: AgentDatum[];
|
|
24
|
+
error_message: string | null;
|
|
25
|
+
};
|
|
3
26
|
export declare class Job {
|
|
4
27
|
private readonly agentsApi;
|
|
5
28
|
private readonly jobId;
|
|
@@ -13,16 +36,16 @@ export declare class Job {
|
|
|
13
36
|
wait(params?: {
|
|
14
37
|
intervalSeconds?: number;
|
|
15
38
|
timeoutSeconds?: number;
|
|
16
|
-
}): Promise<
|
|
39
|
+
}): Promise<JobResult>;
|
|
17
40
|
retrieveStatus(): Promise<AgentJobStatus>;
|
|
18
|
-
retrieveResult(): Promise<
|
|
41
|
+
retrieveResult(): Promise<AgentJobResultResponse>;
|
|
19
42
|
}
|
|
20
43
|
export declare class JobBatch {
|
|
21
44
|
private readonly agentsApi;
|
|
22
45
|
private readonly jobIds;
|
|
23
46
|
private readonly timeoutSeconds;
|
|
24
47
|
private completed;
|
|
25
|
-
private
|
|
48
|
+
private statuses;
|
|
26
49
|
constructor(opts: {
|
|
27
50
|
agentsApi: AgentsAPI;
|
|
28
51
|
jobIds: string[];
|
|
@@ -32,6 +55,7 @@ export declare class JobBatch {
|
|
|
32
55
|
wait(params?: {
|
|
33
56
|
intervalSeconds?: number;
|
|
34
57
|
timeoutSeconds?: number;
|
|
35
|
-
}): Promise<
|
|
36
|
-
retrieveStatus(): Promise<Record<string,
|
|
58
|
+
}): Promise<JobBatchItem[]>;
|
|
59
|
+
retrieveStatus(): Promise<Record<string, AgentJobStatus>>;
|
|
37
60
|
}
|
|
61
|
+
export {};
|