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.
@@ -1,4 +1,13 @@
1
- import { JobStatus } from "./responses.js";
1
+ export var JobStatus;
2
+ (function (JobStatus) {
3
+ JobStatus[JobStatus["PENDING"] = 0] = "PENDING";
4
+ JobStatus[JobStatus["STARTED"] = 1] = "STARTED";
5
+ JobStatus[JobStatus["RETRY"] = 2] = "RETRY";
6
+ JobStatus[JobStatus["SUCCESS"] = 3] = "SUCCESS";
7
+ JobStatus[JobStatus["FAILURE"] = 4] = "FAILURE";
8
+ JobStatus[JobStatus["CANCELLED"] = 5] = "CANCELLED";
9
+ JobStatus[JobStatus["CACHED"] = 6] = "CACHED";
10
+ })(JobStatus || (JobStatus = {}));
2
11
  export class Job {
3
12
  constructor(opts) {
4
13
  this.agentsApi = opts.agentsApi;
@@ -20,11 +29,32 @@ export class Job {
20
29
  while (true) {
21
30
  const status = await this.retrieveStatus();
22
31
  const code = status.status;
23
- if (code === JobStatus.SUCCESS || code === JobStatus.CACHED) {
24
- return this.retrieveResult();
25
- }
26
- if (code === JobStatus.FAILURE || code === JobStatus.CANCELLED) {
27
- throw new Error(`Job ${this.jobId} failed with status ${code}${status.error_message ? `: ${status.error_message}` : ""}`);
32
+ if (code === JobStatus.SUCCESS ||
33
+ code === JobStatus.CACHED ||
34
+ code === JobStatus.FAILURE ||
35
+ code === JobStatus.CANCELLED) {
36
+ const isFailed = code === JobStatus.FAILURE || code === JobStatus.CANCELLED;
37
+ let result;
38
+ try {
39
+ result = await this.retrieveResult();
40
+ }
41
+ catch (err) {
42
+ if (!isFailed)
43
+ throw err;
44
+ result = {
45
+ agent_id: "",
46
+ agent_version_id: "",
47
+ inputs: [],
48
+ outputs: [],
49
+ input_tokens: null,
50
+ output_tokens: null,
51
+ };
52
+ }
53
+ return {
54
+ ...result,
55
+ status: code,
56
+ error_message: status.error_message ?? null,
57
+ };
28
58
  }
29
59
  if (Date.now() - start > timeoutSeconds * 1000) {
30
60
  throw new Error(`Job ${this.jobId} did not complete within ${timeoutSeconds} seconds`);
@@ -42,7 +72,7 @@ export class Job {
42
72
  export class JobBatch {
43
73
  constructor(opts) {
44
74
  this.completed = {};
45
- this.statusCache = {};
75
+ this.statuses = {};
46
76
  this.agentsApi = opts.agentsApi;
47
77
  this.jobIds = opts.jobIds;
48
78
  this.timeoutSeconds = opts.timeoutSeconds ?? 7200;
@@ -64,45 +94,88 @@ export class JobBatch {
64
94
  if (!pending.length)
65
95
  break;
66
96
  const statusBatch = await this.agentsApi.jobs.retrieveStatusMany(pending);
67
- const failures = statusBatch.filter((s) => s.status === JobStatus.FAILURE || s.status === JobStatus.CANCELLED);
68
- if (failures.length) {
69
- const detail = failures.map((f) => `${f.id}:${f.status ?? "unknown"}`).join(', ');
70
- throw new Error(`Jobs failed or cancelled: ${detail}`);
71
- }
72
97
  const completedIds = [];
73
98
  for (const status of statusBatch) {
99
+ // The bulk status endpoint returns AgentJobStatus[]; the schema lacks an `id`
100
+ // field on each, but the backend includes it in practice — extract via cast.
101
+ const id = status.id;
102
+ if (!id) {
103
+ throw new Error("AgentJobStatus response is missing an `id` field; backend schema may have changed");
104
+ }
74
105
  const code = status.status;
75
- if (code === JobStatus.SUCCESS || code === JobStatus.CACHED) {
76
- completedIds.push(status.id);
106
+ if (code === JobStatus.SUCCESS ||
107
+ code === JobStatus.CACHED ||
108
+ code === JobStatus.FAILURE ||
109
+ code === JobStatus.CANCELLED) {
110
+ completedIds.push(id);
77
111
  }
78
112
  if (code !== undefined && code !== null) {
79
- this.statusCache[status.id] = code;
113
+ this.statuses[id] = {
114
+ id,
115
+ status: code,
116
+ timestamp: status.timestamp,
117
+ error_message: status.error_message,
118
+ };
80
119
  }
81
120
  }
82
121
  if (completedIds.length) {
83
- const resultBatch = await this.agentsApi.jobs.retrieveResultMany(completedIds);
122
+ let resultBatch;
123
+ try {
124
+ resultBatch = await this.agentsApi.jobs.retrieveResultMany(completedIds);
125
+ }
126
+ catch (err) {
127
+ // Only synthesize for failed/cancelled — can't fake results for success/cached
128
+ const failedIds = completedIds.filter((id) => {
129
+ const s = this.statuses[id]?.status;
130
+ return s === JobStatus.FAILURE || s === JobStatus.CANCELLED;
131
+ });
132
+ if (failedIds.length < completedIds.length) {
133
+ throw err;
134
+ }
135
+ resultBatch = failedIds.map((id) => ({
136
+ id,
137
+ status: this.statuses[id]?.status ?? null,
138
+ agent_id: null,
139
+ agent_version_id: null,
140
+ cost: null,
141
+ inputs: null,
142
+ result: null,
143
+ corrected_outputs: null,
144
+ input_tokens: null,
145
+ output_tokens: null,
146
+ }));
147
+ }
84
148
  for (const res of resultBatch) {
149
+ const jobStatus = res.status ?? this.statuses[res.id]?.status ?? null;
150
+ const isFailed = jobStatus === JobStatus.FAILURE || jobStatus === JobStatus.CANCELLED;
85
151
  if (!res.agent_id || !res.agent_version_id) {
86
- const id = res.id ?? 'unknown';
87
- throw new Error(`Job ${id} missing agent identifiers`);
152
+ if (!isFailed) {
153
+ const id = res.id ?? "unknown";
154
+ throw new Error(`Job ${id} missing agent identifiers`);
155
+ }
88
156
  }
89
- // Use corrected_outputs as fallback if result is null/undefined
90
- const outputs = res.result ?? res.corrected_outputs;
91
- if (outputs == null) {
92
- // Both result and corrected_outputs are null - this may indicate an error or incomplete job
93
- throw new Error(`Job ${res.id} returned null or undefined result`);
157
+ const rawOutputs = res.result ?? res.corrected_outputs;
158
+ let outputs;
159
+ if (rawOutputs == null) {
160
+ if (!isFailed) {
161
+ throw new Error(`Job ${res.id} returned null or undefined result`);
162
+ }
163
+ outputs = [];
94
164
  }
95
- if (!Array.isArray(outputs)) {
96
- // Result exists but is not an array - unexpected format
97
- throw new Error(`Job ${res.id} returned unexpected result format: ${typeof outputs}`);
165
+ else if (!Array.isArray(rawOutputs)) {
166
+ if (!isFailed) {
167
+ throw new Error(`Job ${res.id} returned unexpected result format: ${typeof rawOutputs}`);
168
+ }
169
+ outputs = [];
170
+ }
171
+ else {
172
+ outputs = rawOutputs;
98
173
  }
99
174
  this.completed[res.id] = {
100
- agent_id: res.agent_id,
101
- agent_version_id: res.agent_version_id,
102
- inputs: res.inputs ?? [],
103
- input_tokens: res.input_tokens,
104
- output_tokens: res.output_tokens,
175
+ ...res,
176
+ status: jobStatus,
105
177
  outputs,
178
+ error_message: this.statuses[res.id]?.error_message ?? null,
106
179
  };
107
180
  }
108
181
  }
@@ -117,14 +190,34 @@ export class JobBatch {
117
190
  return this.jobIds.map((id) => this.completed[id]);
118
191
  }
119
192
  async retrieveStatus() {
120
- const statusMap = { ...this.statusCache };
121
- const toQuery = this.jobIds.filter((id) => statusMap[id] === undefined);
193
+ const statusMap = {};
194
+ const toQuery = [];
195
+ const TERMINAL = new Set([JobStatus.SUCCESS, JobStatus.CACHED, JobStatus.FAILURE, JobStatus.CANCELLED]);
196
+ for (const id of this.jobIds) {
197
+ const cached = this.statuses[id];
198
+ if (cached !== undefined && TERMINAL.has(cached.status)) {
199
+ statusMap[id] = cached;
200
+ }
201
+ else {
202
+ toQuery.push(id);
203
+ }
204
+ }
122
205
  if (toQuery.length) {
123
- const statuses = await this.agentsApi.jobs.retrieveStatusMany(toQuery);
124
- for (const s of statuses) {
206
+ const batchStatuses = await this.agentsApi.jobs.retrieveStatusMany(toQuery);
207
+ for (const s of batchStatuses) {
208
+ const id = s.id;
209
+ if (!id) {
210
+ throw new Error("AgentJobStatus response is missing an `id` field; backend schema may have changed");
211
+ }
125
212
  if (s.status !== undefined && s.status !== null) {
126
- statusMap[s.id] = s.status;
127
- this.statusCache[s.id] = s.status;
213
+ const js = {
214
+ id,
215
+ status: s.status,
216
+ timestamp: s.timestamp,
217
+ error_message: s.error_message,
218
+ };
219
+ this.statuses[id] = js;
220
+ statusMap[id] = js;
128
221
  }
129
222
  }
130
223
  }
@@ -0,0 +1,30 @@
1
+ import type { RoeRawClient } from "../generated/client.js";
2
+ import { FileUpload } from "../models/file.js";
3
+ export type ClassifiedInputs = {
4
+ formData: Record<string, string>;
5
+ files: Record<string, FileUpload>;
6
+ };
7
+ /**
8
+ * Splits a free-form `inputs` dict into form fields + file uploads, mirroring
9
+ * the detection rules from the legacy `RoeHTTPClient.postWithDynamicInputs`:
10
+ *
11
+ * - `FileUpload` instance -> file part
12
+ * - object with a `pipe` function (Node Readable) -> wrapped in FileUpload
13
+ * - string that's a valid UUID -> form field (treated as a Roe file ref)
14
+ * - string that resolves to a real file path -> opened as a FileUpload
15
+ * - other strings / numbers / booleans -> form field (stringified)
16
+ */
17
+ export declare function classifyInputs(inputs: Record<string, unknown>): Promise<ClassifiedInputs>;
18
+ /**
19
+ * Posts a multipart body built from a free-form `inputs` dict (with optional
20
+ * sibling `metadata`) to a generated raw-client path. Bypasses openapi-fetch's
21
+ * default JSON serialization via the `bodySerializer` escape hatch and runs
22
+ * its own retry loop because Node `Readable` bodies cannot be re-read.
23
+ *
24
+ * The path / pathParams are intentionally typed loosely (`string` /
25
+ * `Record<string, string>`) — multipart agent-run endpoints have dynamic
26
+ * input keys that aren't statically modeled in the OpenAPI spec, so the
27
+ * generated typed-body variant is unusable here. Callers pass the path
28
+ * literal that matches `paths` in schema.d.ts.
29
+ */
30
+ export declare function postDynamicInputs<T = unknown>(raw: RoeRawClient, path: string, pathParams: Record<string, string>, queryParams: Record<string, string | undefined>, inputs: Record<string, unknown>, metadata: Record<string, unknown> | undefined, maxRetries: number): Promise<T>;
@@ -0,0 +1,114 @@
1
+ import { FileUpload } from "../models/file.js";
2
+ import { isFilePath, isUuidString } from "./fileDetection.js";
3
+ /**
4
+ * Sentinel header read by `retryMiddleware`. Multipart bodies aren't safely
5
+ * cloneable for retry by the middleware — the wrapper-side loop in
6
+ * `postDynamicInputs` rebuilds FormData per attempt instead.
7
+ */
8
+ const RETRY_BYPASS_HEADER = "x-roe-retry-bypass";
9
+ const isRetriable = (status) => status >= 500 || status === 429 || status === 408;
10
+ /**
11
+ * Splits a free-form `inputs` dict into form fields + file uploads, mirroring
12
+ * the detection rules from the legacy `RoeHTTPClient.postWithDynamicInputs`:
13
+ *
14
+ * - `FileUpload` instance -> file part
15
+ * - object with a `pipe` function (Node Readable) -> wrapped in FileUpload
16
+ * - string that's a valid UUID -> form field (treated as a Roe file ref)
17
+ * - string that resolves to a real file path -> opened as a FileUpload
18
+ * - other strings / numbers / booleans -> form field (stringified)
19
+ */
20
+ export async function classifyInputs(inputs) {
21
+ const formData = {};
22
+ const files = {};
23
+ for (const [key, value] of Object.entries(inputs)) {
24
+ if (value === undefined || value === null)
25
+ continue;
26
+ if (value instanceof FileUpload) {
27
+ files[key] = value;
28
+ continue;
29
+ }
30
+ if (typeof value === "object" && typeof value.pipe === "function") {
31
+ files[key] = new FileUpload({ file: value });
32
+ continue;
33
+ }
34
+ if (typeof value === "string") {
35
+ if (isUuidString(value)) {
36
+ formData[key] = value;
37
+ }
38
+ else if (await isFilePath(value)) {
39
+ files[key] = new FileUpload({ path: value });
40
+ }
41
+ else {
42
+ formData[key] = value;
43
+ }
44
+ continue;
45
+ }
46
+ if (typeof value === "boolean" || typeof value === "number") {
47
+ formData[key] = String(value);
48
+ continue;
49
+ }
50
+ // Unknown shape — JSON-encode so e.g. nested objects survive the round-trip.
51
+ formData[key] = JSON.stringify(value);
52
+ }
53
+ return { formData, files };
54
+ }
55
+ async function buildFormData(formData, files, metadata) {
56
+ const fd = new FormData();
57
+ for (const [k, v] of Object.entries(formData))
58
+ fd.append(k, v);
59
+ if (metadata !== undefined)
60
+ fd.append("metadata", JSON.stringify(metadata));
61
+ for (const [k, fu] of Object.entries(files)) {
62
+ fd.append(k, await fu.toBlob(), fu.effectiveFilename);
63
+ }
64
+ return fd;
65
+ }
66
+ /**
67
+ * Posts a multipart body built from a free-form `inputs` dict (with optional
68
+ * sibling `metadata`) to a generated raw-client path. Bypasses openapi-fetch's
69
+ * default JSON serialization via the `bodySerializer` escape hatch and runs
70
+ * its own retry loop because Node `Readable` bodies cannot be re-read.
71
+ *
72
+ * The path / pathParams are intentionally typed loosely (`string` /
73
+ * `Record<string, string>`) — multipart agent-run endpoints have dynamic
74
+ * input keys that aren't statically modeled in the OpenAPI spec, so the
75
+ * generated typed-body variant is unusable here. Callers pass the path
76
+ * literal that matches `paths` in schema.d.ts.
77
+ */
78
+ export async function postDynamicInputs(raw, path, pathParams, queryParams, inputs, metadata, maxRetries) {
79
+ const { formData, files } = await classifyInputs(inputs);
80
+ let attempt = 0;
81
+ let lastErr;
82
+ while (attempt <= maxRetries) {
83
+ const fd = await buildFormData(formData, files, metadata);
84
+ try {
85
+ // openapi-fetch's typed POST is keyed on `paths`; we deliberately escape
86
+ // the type system here for multipart agent-run endpoints.
87
+ // NOTE: openapi-fetch skips `bodySerializer` entirely when `body` is
88
+ // `undefined`, so we pass the FormData as the body itself and use
89
+ // bodySerializer as an identity to preserve the FormData type signal
90
+ // (openapi-fetch then refrains from forcing Content-Type: application/json).
91
+ const result = await raw.POST(path, {
92
+ params: { path: pathParams, query: queryParams },
93
+ body: fd,
94
+ bodySerializer: (b) => b,
95
+ headers: { [RETRY_BYPASS_HEADER]: "1" },
96
+ });
97
+ // errorMiddleware throws on non-2xx, so reaching here means success.
98
+ // `error` is therefore always undefined; surface `data` directly.
99
+ return result.data;
100
+ }
101
+ catch (err) {
102
+ lastErr = err;
103
+ const status = err?.statusCode;
104
+ if (status !== undefined && isRetriable(status) && attempt < maxRetries) {
105
+ const backoff = Math.min(1000 * 2 ** attempt, 10000);
106
+ await new Promise((r) => setTimeout(r, backoff));
107
+ attempt += 1;
108
+ continue;
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+ throw lastErr ?? new Error("postDynamicInputs exhausted retries without producing an error");
114
+ }
@@ -0,0 +1,6 @@
1
+ import type { Middleware } from "openapi-fetch";
2
+ import { RoeAuth } from "../auth.js";
3
+ export declare function shouldBypassRetry(request: Request): boolean;
4
+ export declare function authMiddleware(auth: RoeAuth): Middleware;
5
+ export declare function retryMiddleware(maxRetries: number): Middleware;
6
+ export declare const errorMiddleware: Middleware;
@@ -0,0 +1,80 @@
1
+ import { extractErrorMessage, getExceptionForStatusCode } from "../exceptions.js";
2
+ const RETRY_BYPASS_HEADER = "x-roe-retry-bypass";
3
+ export function shouldBypassRetry(request) {
4
+ if (request.headers.get(RETRY_BYPASS_HEADER))
5
+ return true;
6
+ const ct = request.headers.get("content-type");
7
+ return !!ct && ct.toLowerCase().startsWith("multipart/");
8
+ }
9
+ export function authMiddleware(auth) {
10
+ return {
11
+ onRequest({ request }) {
12
+ for (const [k, v] of Object.entries(auth.getHeaders())) {
13
+ request.headers.set(k, v);
14
+ }
15
+ return request;
16
+ },
17
+ };
18
+ }
19
+ // Per-request body cache populated in onRequest (where the body is still
20
+ // fresh) and consumed in onResponse to rebuild Requests on retry. Cloning
21
+ // the original request post-fetch fails in Node 18+ undici with
22
+ // `TypeError: Cannot perform 'clone' on a Request with a disturbed body`,
23
+ // because the body stream has already been consumed by the initial fetch.
24
+ const bodyCache = new WeakMap();
25
+ export function retryMiddleware(maxRetries) {
26
+ return {
27
+ async onRequest({ request }) {
28
+ if (!shouldBypassRetry(request) && request.body) {
29
+ // Clone-then-buffer here is safe — the original `request` is still
30
+ // un-disturbed and goes on to fetch unchanged. Only the clone is
31
+ // consumed.
32
+ bodyCache.set(request, await request.clone().arrayBuffer());
33
+ }
34
+ return request;
35
+ },
36
+ async onResponse({ request, response, options }) {
37
+ if (shouldBypassRetry(request))
38
+ return response;
39
+ const retriable = (status) => status >= 500 || status === 429 || status === 408;
40
+ let attempt = 0;
41
+ let res = response;
42
+ const doFetch = options.fetch;
43
+ const cachedBody = bodyCache.get(request);
44
+ while (attempt < maxRetries && retriable(res.status)) {
45
+ const backoffMs = Math.min(1000 * 2 ** attempt, 10000);
46
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
47
+ // Build a fresh Request per attempt — the original's body stream
48
+ // was disturbed by the previous fetch.
49
+ const retryReq = new Request(request.url, {
50
+ method: request.method,
51
+ headers: request.headers,
52
+ body: cachedBody ?? null,
53
+ });
54
+ res = await doFetch(retryReq);
55
+ attempt += 1;
56
+ }
57
+ bodyCache.delete(request);
58
+ return res;
59
+ },
60
+ };
61
+ }
62
+ export const errorMiddleware = {
63
+ async onResponse({ response }) {
64
+ if (response.ok)
65
+ return response;
66
+ let data = null;
67
+ try {
68
+ data = await response.clone().json();
69
+ }
70
+ catch {
71
+ data = null;
72
+ }
73
+ const ExceptionClass = getExceptionForStatusCode(response.status);
74
+ const message = extractErrorMessage(data, response.status);
75
+ const responseObj = data && typeof data === "object" && !Array.isArray(data)
76
+ ? data
77
+ : null;
78
+ throw new ExceptionClass(message, response.status, responseObj);
79
+ },
80
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roe-typescript",
3
- "version": "0.1.2",
3
+ "version": "1.0.0",
4
4
  "description": "TypeScript SDK for the Roe AI API (feature parity with roe-python).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,24 +13,24 @@
13
13
  },
14
14
  "scripts": {
15
15
  "build": "tsc -p tsconfig.json",
16
+ "generate-sdk": "bash scripts/generate-sdk",
16
17
  "lint": "tsc --noEmit",
17
18
  "test": "vitest run tests/unit --passWithNoTests",
18
19
  "test:watch": "vitest",
19
20
  "prepublishOnly": "npm run lint && npm run test && npm run build"
20
21
  },
21
22
  "dependencies": {
22
- "axios": "^1.7.7",
23
- "form-data": "^4.0.0",
24
23
  "mime-types": "^2.1.35",
24
+ "openapi-fetch": "^0.13.8",
25
+ "undici": "^6.25.0",
25
26
  "uuid": "^11.0.3"
26
27
  },
27
28
  "devDependencies": {
28
- "@types/form-data": "^2.5.0",
29
29
  "@types/mime-types": "^2.1.4",
30
- "@types/uuid": "^10.0.0",
31
30
  "@types/node": "^22.9.0",
31
+ "@types/uuid": "^10.0.0",
32
+ "openapi-typescript": "^7.6.1",
32
33
  "typescript": "^5.6.3",
33
34
  "vitest": "^1.6.0"
34
35
  }
35
36
  }
36
-
@@ -1,78 +0,0 @@
1
- import { UserInfo } from "./user.js";
2
- import { AgentsAPI } from "../api/agents.js";
3
- import { Job } from "./job.js";
4
- export type AgentInputDefinition = {
5
- key: string;
6
- data_type: string;
7
- description: string;
8
- example?: string;
9
- accepts_multiple_files?: boolean | null;
10
- };
11
- export type BaseAgent = {
12
- id: string;
13
- name: string;
14
- creator?: UserInfo | null;
15
- created_at: string;
16
- disable_cache: boolean;
17
- cache_failed_jobs: boolean;
18
- organization_id: string;
19
- engine_class_id: string;
20
- current_version_id?: string | null;
21
- job_count?: number;
22
- most_recent_job?: string | null;
23
- engine_name?: string;
24
- };
25
- export declare class BaseAgentWithApi implements BaseAgent {
26
- id: string;
27
- name: string;
28
- creator?: UserInfo | null;
29
- created_at: string;
30
- disable_cache: boolean;
31
- cache_failed_jobs: boolean;
32
- organization_id: string;
33
- engine_class_id: string;
34
- current_version_id?: string | null;
35
- job_count?: number;
36
- most_recent_job?: string | null;
37
- engine_name?: string;
38
- private _agentsApi?;
39
- constructor(data: BaseAgent);
40
- setAgentsApi(api: AgentsAPI): void;
41
- run(inputs: Record<string, unknown>): Promise<Job>;
42
- listVersions(): Promise<AgentVersionWithApi[]>;
43
- getCurrentVersion(): Promise<AgentVersionWithApi> | null;
44
- }
45
- export type AgentVersion = {
46
- id: string;
47
- name: string;
48
- version_name: string;
49
- creator?: UserInfo | null;
50
- created_at: string;
51
- description?: string | null;
52
- engine_class_id: string;
53
- engine_name: string;
54
- input_definitions: AgentInputDefinition[];
55
- engine_config: Record<string, unknown>;
56
- organization_id: string;
57
- readonly: boolean;
58
- base_agent: BaseAgent;
59
- };
60
- export declare class AgentVersionWithApi implements AgentVersion {
61
- id: string;
62
- name: string;
63
- version_name: string;
64
- creator?: UserInfo | null;
65
- created_at: string;
66
- description?: string | null;
67
- engine_class_id: string;
68
- engine_name: string;
69
- input_definitions: AgentInputDefinition[];
70
- engine_config: Record<string, unknown>;
71
- organization_id: string;
72
- readonly: boolean;
73
- base_agent: BaseAgent;
74
- private _agentsApi?;
75
- constructor(data: AgentVersion);
76
- setAgentsApi(api: AgentsAPI): void;
77
- run(inputs: Record<string, unknown>): Promise<Job>;
78
- }
@@ -1,40 +0,0 @@
1
- export class BaseAgentWithApi {
2
- constructor(data) {
3
- Object.assign(this, data);
4
- }
5
- setAgentsApi(api) {
6
- this._agentsApi = api;
7
- }
8
- run(inputs) {
9
- if (!this._agentsApi)
10
- throw new Error("Agents API not set");
11
- return this._agentsApi.run({ agentId: this.id, inputs });
12
- }
13
- listVersions() {
14
- if (!this._agentsApi)
15
- throw new Error("Agents API not set");
16
- return this._agentsApi.versions.list(this.id);
17
- }
18
- getCurrentVersion() {
19
- if (!this._agentsApi)
20
- throw new Error("Agents API not set");
21
- if (!this.current_version_id)
22
- return null;
23
- return this._agentsApi.versions.retrieve(this.id, this.current_version_id);
24
- }
25
- }
26
- export class AgentVersionWithApi {
27
- constructor(data) {
28
- Object.assign(this, data);
29
- }
30
- setAgentsApi(api) {
31
- this._agentsApi = api;
32
- }
33
- run(inputs) {
34
- if (!this._agentsApi)
35
- throw new Error("Agents API not set");
36
- if (!this.base_agent?.id)
37
- throw new Error("AgentVersion missing base_agent id");
38
- return this._agentsApi.runVersion({ agentId: this.base_agent.id, versionId: this.id, inputs });
39
- }
40
- }
@@ -1,19 +0,0 @@
1
- export type Policy = {
2
- id: string;
3
- name: string;
4
- description: string;
5
- organization_id: string;
6
- current_version_id: string | null;
7
- created_at: string;
8
- updated_at: string;
9
- };
10
- export type PolicyVersion = {
11
- id: string;
12
- version_name: string;
13
- content: Record<string, unknown>;
14
- created_at: string;
15
- updated_at: string;
16
- policy: Policy | null;
17
- created_by: Record<string, unknown> | null;
18
- base_version_id: string | null;
19
- };
@@ -1 +0,0 @@
1
- export {};