@seclai/sdk 0.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/index.cjs +369 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +708 -0
- package/dist/index.d.ts +708 -0
- package/dist/index.js +337 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var SeclaiError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "SeclaiError";
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var SeclaiConfigurationError = class extends SeclaiError {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "SeclaiConfigurationError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var SeclaiAPIStatusError = class extends SeclaiError {
|
|
15
|
+
/** HTTP status code returned by the API. */
|
|
16
|
+
statusCode;
|
|
17
|
+
/** HTTP method used for the request. */
|
|
18
|
+
method;
|
|
19
|
+
/** Full request URL. */
|
|
20
|
+
url;
|
|
21
|
+
/** Best-effort response body text (if available). */
|
|
22
|
+
responseText;
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
super(opts.message);
|
|
25
|
+
this.name = "SeclaiAPIStatusError";
|
|
26
|
+
this.statusCode = opts.statusCode;
|
|
27
|
+
this.method = opts.method;
|
|
28
|
+
this.url = opts.url;
|
|
29
|
+
this.responseText = opts.responseText;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var SeclaiAPIValidationError = class extends SeclaiAPIStatusError {
|
|
33
|
+
/** Parsed validation error payload (best-effort). */
|
|
34
|
+
validationError;
|
|
35
|
+
constructor(opts) {
|
|
36
|
+
super(opts);
|
|
37
|
+
this.name = "SeclaiAPIValidationError";
|
|
38
|
+
this.validationError = opts.validationError;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/client.ts
|
|
43
|
+
var SECLAI_API_URL = "https://seclai.com";
|
|
44
|
+
function getEnv(name) {
|
|
45
|
+
const p = globalThis?.process;
|
|
46
|
+
return p?.env?.[name];
|
|
47
|
+
}
|
|
48
|
+
function buildURL(baseUrl, path, query) {
|
|
49
|
+
const url = new URL(path, baseUrl);
|
|
50
|
+
if (query) {
|
|
51
|
+
for (const [key, value] of Object.entries(query)) {
|
|
52
|
+
if (value === void 0 || value === null) continue;
|
|
53
|
+
url.searchParams.set(key, String(value));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return url;
|
|
57
|
+
}
|
|
58
|
+
async function safeText(response) {
|
|
59
|
+
try {
|
|
60
|
+
return await response.clone().text();
|
|
61
|
+
} catch {
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function safeJson(response) {
|
|
66
|
+
try {
|
|
67
|
+
return await response.clone().json();
|
|
68
|
+
} catch {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
var Seclai = class {
|
|
73
|
+
apiKey;
|
|
74
|
+
baseUrl;
|
|
75
|
+
apiKeyHeader;
|
|
76
|
+
defaultHeaders;
|
|
77
|
+
fetcher;
|
|
78
|
+
/**
|
|
79
|
+
* Create a new Seclai client.
|
|
80
|
+
*
|
|
81
|
+
* @param opts - Client configuration.
|
|
82
|
+
* @throws {@link SeclaiConfigurationError} If no API key is provided (and `SECLAI_API_KEY` is not set).
|
|
83
|
+
* @throws {@link SeclaiConfigurationError} If no `fetch` implementation is available.
|
|
84
|
+
*/
|
|
85
|
+
constructor(opts = {}) {
|
|
86
|
+
const apiKey = opts.apiKey ?? getEnv("SECLAI_API_KEY");
|
|
87
|
+
if (!apiKey) {
|
|
88
|
+
throw new SeclaiConfigurationError(
|
|
89
|
+
"Missing API key. Provide apiKey or set SECLAI_API_KEY."
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const fetcher = opts.fetch ?? globalThis.fetch;
|
|
93
|
+
if (!fetcher) {
|
|
94
|
+
throw new SeclaiConfigurationError(
|
|
95
|
+
"No fetch implementation available. Provide opts.fetch or run in an environment with global fetch."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
this.apiKey = apiKey;
|
|
99
|
+
this.baseUrl = opts.baseUrl ?? getEnv("SECLAI_API_URL") ?? SECLAI_API_URL;
|
|
100
|
+
this.apiKeyHeader = opts.apiKeyHeader ?? "x-api-key";
|
|
101
|
+
this.defaultHeaders = { ...opts.defaultHeaders ?? {} };
|
|
102
|
+
this.fetcher = fetcher;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Make a raw HTTP request to the Seclai API.
|
|
106
|
+
*
|
|
107
|
+
* This is a low-level escape hatch. For most operations, prefer the typed convenience methods.
|
|
108
|
+
*
|
|
109
|
+
* @param method - HTTP method (e.g. `"GET"`, `"POST"`).
|
|
110
|
+
* @param path - Request path relative to `baseUrl` (e.g. `"/api/sources/"`).
|
|
111
|
+
* @param opts - Query params, JSON body, and per-request headers.
|
|
112
|
+
* @returns Parsed JSON for JSON responses, raw text for non-JSON responses, or `null` for empty bodies.
|
|
113
|
+
* @throws {@link SeclaiAPIValidationError} For validation errors (typically HTTP 422).
|
|
114
|
+
* @throws {@link SeclaiAPIStatusError} For other non-success HTTP status codes.
|
|
115
|
+
*/
|
|
116
|
+
async request(method, path, opts) {
|
|
117
|
+
const url = buildURL(this.baseUrl, path, opts?.query);
|
|
118
|
+
const headers = {
|
|
119
|
+
...this.defaultHeaders,
|
|
120
|
+
...opts?.headers ?? {},
|
|
121
|
+
[this.apiKeyHeader]: this.apiKey
|
|
122
|
+
};
|
|
123
|
+
let body;
|
|
124
|
+
if (opts?.json !== void 0) {
|
|
125
|
+
headers["content-type"] = headers["content-type"] ?? "application/json";
|
|
126
|
+
body = JSON.stringify(opts.json);
|
|
127
|
+
}
|
|
128
|
+
const init = { method, headers };
|
|
129
|
+
if (body !== void 0) {
|
|
130
|
+
init.body = body;
|
|
131
|
+
}
|
|
132
|
+
const response = await this.fetcher(url, init);
|
|
133
|
+
if (response.status === 204) return null;
|
|
134
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
135
|
+
const isJson = contentType.includes("application/json");
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
const responseText = await safeText(response);
|
|
138
|
+
if (response.status === 422) {
|
|
139
|
+
const validation = await safeJson(response);
|
|
140
|
+
throw new SeclaiAPIValidationError({
|
|
141
|
+
message: "Validation error",
|
|
142
|
+
statusCode: response.status,
|
|
143
|
+
method,
|
|
144
|
+
url: url.toString(),
|
|
145
|
+
responseText,
|
|
146
|
+
validationError: validation
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
throw new SeclaiAPIStatusError({
|
|
150
|
+
message: `Request failed with status ${response.status}`,
|
|
151
|
+
statusCode: response.status,
|
|
152
|
+
method,
|
|
153
|
+
url: url.toString(),
|
|
154
|
+
responseText
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (!response.body) return null;
|
|
158
|
+
if (isJson) {
|
|
159
|
+
return await response.json();
|
|
160
|
+
}
|
|
161
|
+
return await response.text();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Run an agent.
|
|
165
|
+
*
|
|
166
|
+
* @param agentId - Agent identifier.
|
|
167
|
+
* @param body - Agent run request payload.
|
|
168
|
+
* @returns The created agent run.
|
|
169
|
+
*/
|
|
170
|
+
async runAgent(agentId, body) {
|
|
171
|
+
const data = await this.request("POST", `/api/agents/${agentId}/runs`, { json: body });
|
|
172
|
+
return data;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* List agent runs for an agent.
|
|
176
|
+
*
|
|
177
|
+
* @param agentId - Agent identifier.
|
|
178
|
+
* @param opts - Pagination options.
|
|
179
|
+
* @returns A paginated list of runs.
|
|
180
|
+
*/
|
|
181
|
+
async listAgentRuns(agentId, opts = {}) {
|
|
182
|
+
const data = await this.request("GET", `/api/agents/${agentId}/runs`, {
|
|
183
|
+
query: { page: opts.page ?? 1, limit: opts.limit ?? 50 }
|
|
184
|
+
});
|
|
185
|
+
return data;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get details of a specific agent run.
|
|
189
|
+
*
|
|
190
|
+
* @param agentId - Agent identifier.
|
|
191
|
+
* @param runId - Run identifier.
|
|
192
|
+
* @returns Agent run details.
|
|
193
|
+
*/
|
|
194
|
+
async getAgentRun(agentId, runId) {
|
|
195
|
+
const data = await this.request("GET", `/api/agents/${agentId}/runs/${runId}`);
|
|
196
|
+
return data;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Cancel an agent run.
|
|
200
|
+
*
|
|
201
|
+
* @param agentId - Agent identifier.
|
|
202
|
+
* @param runId - Run identifier.
|
|
203
|
+
* @returns Updated agent run record.
|
|
204
|
+
*/
|
|
205
|
+
async deleteAgentRun(agentId, runId) {
|
|
206
|
+
const data = await this.request("DELETE", `/api/agents/${agentId}/runs/${runId}`);
|
|
207
|
+
return data;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get content detail.
|
|
211
|
+
*
|
|
212
|
+
* Fetches a slice of a content version (use `start`/`end` to page through large content).
|
|
213
|
+
*
|
|
214
|
+
* @param sourceConnectionContentVersion - Content version identifier.
|
|
215
|
+
* @param opts - Range options.
|
|
216
|
+
* @returns Content details for the requested range.
|
|
217
|
+
*/
|
|
218
|
+
async getContentDetail(sourceConnectionContentVersion, opts = {}) {
|
|
219
|
+
const data = await this.request(
|
|
220
|
+
"GET",
|
|
221
|
+
`/api/contents/${sourceConnectionContentVersion}`,
|
|
222
|
+
{ query: { start: opts.start ?? 0, end: opts.end ?? 5e3 } }
|
|
223
|
+
);
|
|
224
|
+
return data;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Delete a specific content version.
|
|
228
|
+
*
|
|
229
|
+
* @param sourceConnectionContentVersion - Content version identifier.
|
|
230
|
+
*/
|
|
231
|
+
async deleteContent(sourceConnectionContentVersion) {
|
|
232
|
+
await this.request("DELETE", `/api/contents/${sourceConnectionContentVersion}`);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* List embeddings for a content version.
|
|
236
|
+
*
|
|
237
|
+
* @param sourceConnectionContentVersion - Content version identifier.
|
|
238
|
+
* @param opts - Pagination options.
|
|
239
|
+
* @returns A paginated list of embeddings.
|
|
240
|
+
*/
|
|
241
|
+
async listContentEmbeddings(sourceConnectionContentVersion, opts = {}) {
|
|
242
|
+
const data = await this.request(
|
|
243
|
+
"GET",
|
|
244
|
+
`/api/contents/${sourceConnectionContentVersion}/embeddings`,
|
|
245
|
+
{ query: { page: opts.page ?? 1, limit: opts.limit ?? 20 } }
|
|
246
|
+
);
|
|
247
|
+
return data;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* List sources.
|
|
251
|
+
*
|
|
252
|
+
* @param opts - Pagination and filter options.
|
|
253
|
+
* @returns A paginated list of sources.
|
|
254
|
+
*/
|
|
255
|
+
async listSources(opts = {}) {
|
|
256
|
+
const data = await this.request("GET", "/api/sources/", {
|
|
257
|
+
query: {
|
|
258
|
+
page: opts.page ?? 1,
|
|
259
|
+
limit: opts.limit ?? 20,
|
|
260
|
+
sort: opts.sort ?? "created_at",
|
|
261
|
+
order: opts.order ?? "desc",
|
|
262
|
+
account_id: opts.accountId ?? void 0
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
return data;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Upload a file to a specific source connection.
|
|
269
|
+
*
|
|
270
|
+
* @param sourceConnectionId - Source connection identifier.
|
|
271
|
+
* @param opts - File payload and optional metadata.
|
|
272
|
+
* @param opts.file - File payload as a `Blob`, `Uint8Array`, or `ArrayBuffer`.
|
|
273
|
+
* @param opts.title - Optional title for the uploaded file.
|
|
274
|
+
* @param opts.fileName - Optional filename to send with the upload.
|
|
275
|
+
* @param opts.mimeType - Optional MIME type to attach to the upload.
|
|
276
|
+
* @returns Upload response details.
|
|
277
|
+
*/
|
|
278
|
+
async uploadFileToSource(sourceConnectionId, opts) {
|
|
279
|
+
const url = buildURL(this.baseUrl, `/api/sources/${sourceConnectionId}/upload`);
|
|
280
|
+
const headers = {
|
|
281
|
+
...this.defaultHeaders,
|
|
282
|
+
[this.apiKeyHeader]: this.apiKey
|
|
283
|
+
};
|
|
284
|
+
const form = new FormData();
|
|
285
|
+
let blob;
|
|
286
|
+
if (opts.file instanceof Blob) {
|
|
287
|
+
blob = opts.file;
|
|
288
|
+
} else if (opts.file instanceof ArrayBuffer) {
|
|
289
|
+
const blobOpts = opts.mimeType ? { type: opts.mimeType } : void 0;
|
|
290
|
+
blob = new Blob([new Uint8Array(opts.file)], blobOpts);
|
|
291
|
+
} else {
|
|
292
|
+
const blobOpts = opts.mimeType ? { type: opts.mimeType } : void 0;
|
|
293
|
+
blob = new Blob([opts.file], blobOpts);
|
|
294
|
+
}
|
|
295
|
+
const fileName = opts.fileName ?? "upload";
|
|
296
|
+
form.set("file", blob, fileName);
|
|
297
|
+
if (opts.title !== void 0) {
|
|
298
|
+
form.set("title", opts.title);
|
|
299
|
+
}
|
|
300
|
+
const response = await this.fetcher(url, {
|
|
301
|
+
method: "POST",
|
|
302
|
+
headers,
|
|
303
|
+
body: form
|
|
304
|
+
});
|
|
305
|
+
if (!response.ok) {
|
|
306
|
+
const responseText = await safeText(response);
|
|
307
|
+
if (response.status === 422) {
|
|
308
|
+
const validation = await safeJson(response);
|
|
309
|
+
throw new SeclaiAPIValidationError({
|
|
310
|
+
message: "Validation error",
|
|
311
|
+
statusCode: response.status,
|
|
312
|
+
method: "POST",
|
|
313
|
+
url: url.toString(),
|
|
314
|
+
responseText,
|
|
315
|
+
validationError: validation
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
throw new SeclaiAPIStatusError({
|
|
319
|
+
message: `Request failed with status ${response.status}`,
|
|
320
|
+
statusCode: response.status,
|
|
321
|
+
method: "POST",
|
|
322
|
+
url: url.toString(),
|
|
323
|
+
responseText
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
return await response.json();
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
export {
|
|
330
|
+
SECLAI_API_URL,
|
|
331
|
+
Seclai,
|
|
332
|
+
SeclaiAPIStatusError,
|
|
333
|
+
SeclaiAPIValidationError,
|
|
334
|
+
SeclaiConfigurationError,
|
|
335
|
+
SeclaiError
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["/** Base error class for the Seclai SDK. */\nexport class SeclaiError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SeclaiError\";\n }\n}\n\n/** Thrown when the SDK is misconfigured (for example, missing API key). */\nexport class SeclaiConfigurationError extends SeclaiError {\n constructor(message: string) {\n super(message);\n this.name = \"SeclaiConfigurationError\";\n }\n}\n\n/**\n * Thrown when the API returns a non-success status code.\n *\n * @remarks\n * Use {@link SeclaiAPIValidationError} for HTTP 422 validation errors.\n */\nexport class SeclaiAPIStatusError extends SeclaiError {\n /** HTTP status code returned by the API. */\n public readonly statusCode: number;\n /** HTTP method used for the request. */\n public readonly method: string;\n /** Full request URL. */\n public readonly url: string;\n /** Best-effort response body text (if available). */\n public readonly responseText: string | undefined;\n\n constructor(opts: {\n /** Human-readable error message. */\n message: string;\n statusCode: number;\n method: string;\n url: string;\n responseText: string | undefined;\n }) {\n super(opts.message);\n this.name = \"SeclaiAPIStatusError\";\n this.statusCode = opts.statusCode;\n this.method = opts.method;\n this.url = opts.url;\n this.responseText = opts.responseText;\n }\n}\n\n/**\n * Thrown when the API returns a validation error response (typically HTTP 422).\n *\n * The `validationError` field contains the decoded validation payload when available.\n */\nexport class SeclaiAPIValidationError extends SeclaiAPIStatusError {\n /** Parsed validation error payload (best-effort). */\n public readonly validationError: unknown;\n\n constructor(opts: {\n message: string;\n statusCode: number;\n method: string;\n url: string;\n responseText: string | undefined;\n validationError: unknown;\n }) {\n super(opts);\n this.name = \"SeclaiAPIValidationError\";\n this.validationError = opts.validationError;\n }\n}\n","import {\n SeclaiAPIStatusError,\n SeclaiAPIValidationError,\n SeclaiConfigurationError,\n} from \"./errors\";\nimport type {\n AgentRunListResponse,\n AgentRunRequest,\n AgentRunResponse,\n ContentDetailResponse,\n ContentEmbeddingsListResponse,\n FileUploadResponse,\n HTTPValidationError,\n SourceListResponse,\n} from \"./types\";\n\n/** Default API base URL (can be overridden with `baseUrl` or `SECLAI_API_URL`). */\nexport const SECLAI_API_URL = \"https://seclai.com\";\n\n/** A `fetch`-compatible function (e.g. `globalThis.fetch` or `undici.fetch`). */\nexport type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\n/** Configuration for the {@link Seclai} client. */\nexport interface SeclaiOptions {\n /** API key used for authentication. Defaults to `process.env.SECLAI_API_KEY` when available. */\n apiKey?: string;\n /** API base URL. Defaults to `process.env.SECLAI_API_URL` when available, else {@link SECLAI_API_URL}. */\n baseUrl?: string;\n /** Header name to use for the API key. Defaults to `x-api-key`. */\n apiKeyHeader?: string;\n /** Extra headers to include on every request. */\n defaultHeaders?: Record<string, string>;\n /** Optional `fetch` implementation for environments without a global `fetch`. */\n fetch?: FetchLike;\n}\n\nfunction getEnv(name: string): string | undefined {\n const p = (globalThis as any)?.process;\n return p?.env?.[name];\n}\n\nfunction buildURL(baseUrl: string, path: string, query?: Record<string, unknown>): URL {\n const url = new URL(path, baseUrl);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue;\n url.searchParams.set(key, String(value));\n }\n }\n return url;\n}\n\nasync function safeText(response: Response): Promise<string | undefined> {\n try {\n return await response.clone().text();\n } catch {\n return undefined;\n }\n}\n\nasync function safeJson(response: Response): Promise<unknown | undefined> {\n try {\n return await response.clone().json();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Seclai JavaScript/TypeScript client.\n *\n * @remarks\n * - Uses API key auth via `x-api-key` by default.\n * - Throws SDK exceptions for non-success responses.\n */\nexport class Seclai {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly apiKeyHeader: string;\n private readonly defaultHeaders: Record<string, string>;\n private readonly fetcher: FetchLike;\n\n /**\n * Create a new Seclai client.\n *\n * @param opts - Client configuration.\n * @throws {@link SeclaiConfigurationError} If no API key is provided (and `SECLAI_API_KEY` is not set).\n * @throws {@link SeclaiConfigurationError} If no `fetch` implementation is available.\n */\n constructor(opts: SeclaiOptions = {}) {\n const apiKey = opts.apiKey ?? getEnv(\"SECLAI_API_KEY\");\n if (!apiKey) {\n throw new SeclaiConfigurationError(\n \"Missing API key. Provide apiKey or set SECLAI_API_KEY.\"\n );\n }\n\n const fetcher = opts.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (!fetcher) {\n throw new SeclaiConfigurationError(\n \"No fetch implementation available. Provide opts.fetch or run in an environment with global fetch.\"\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = opts.baseUrl ?? getEnv(\"SECLAI_API_URL\") ?? SECLAI_API_URL;\n this.apiKeyHeader = opts.apiKeyHeader ?? \"x-api-key\";\n this.defaultHeaders = { ...(opts.defaultHeaders ?? {}) };\n this.fetcher = fetcher;\n }\n\n /**\n * Make a raw HTTP request to the Seclai API.\n *\n * This is a low-level escape hatch. For most operations, prefer the typed convenience methods.\n *\n * @param method - HTTP method (e.g. `\"GET\"`, `\"POST\"`).\n * @param path - Request path relative to `baseUrl` (e.g. `\"/api/sources/\"`).\n * @param opts - Query params, JSON body, and per-request headers.\n * @returns Parsed JSON for JSON responses, raw text for non-JSON responses, or `null` for empty bodies.\n * @throws {@link SeclaiAPIValidationError} For validation errors (typically HTTP 422).\n * @throws {@link SeclaiAPIStatusError} For other non-success HTTP status codes.\n */\n async request(\n method: string,\n path: string,\n opts?: {\n query?: Record<string, unknown>;\n json?: unknown;\n headers?: Record<string, string>;\n }\n ): Promise<unknown | string | null> {\n const url = buildURL(this.baseUrl, path, opts?.query);\n\n const headers: Record<string, string> = {\n ...this.defaultHeaders,\n ...(opts?.headers ?? {}),\n [this.apiKeyHeader]: this.apiKey,\n };\n\n let body: BodyInit | undefined;\n if (opts?.json !== undefined) {\n headers[\"content-type\"] = headers[\"content-type\"] ?? \"application/json\";\n body = JSON.stringify(opts.json);\n }\n\n const init: RequestInit = { method, headers };\n if (body !== undefined) {\n init.body = body;\n }\n const response = await this.fetcher(url, init);\n\n if (response.status === 204) return null;\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const isJson = contentType.includes(\"application/json\");\n\n if (!response.ok) {\n const responseText = await safeText(response);\n if (response.status === 422) {\n const validation = (await safeJson(response)) as HTTPValidationError | undefined;\n throw new SeclaiAPIValidationError({\n message: \"Validation error\",\n statusCode: response.status,\n method,\n url: url.toString(),\n responseText,\n validationError: validation,\n });\n }\n throw new SeclaiAPIStatusError({\n message: `Request failed with status ${response.status}`,\n statusCode: response.status,\n method,\n url: url.toString(),\n responseText,\n });\n }\n\n if (!response.body) return null;\n\n if (isJson) {\n return (await response.json()) as unknown;\n }\n return await response.text();\n }\n\n /**\n * Run an agent.\n *\n * @param agentId - Agent identifier.\n * @param body - Agent run request payload.\n * @returns The created agent run.\n */\n async runAgent(agentId: string, body: AgentRunRequest): Promise<AgentRunResponse> {\n const data = await this.request(\"POST\", `/api/agents/${agentId}/runs`, { json: body });\n return data as AgentRunResponse;\n }\n\n /**\n * List agent runs for an agent.\n *\n * @param agentId - Agent identifier.\n * @param opts - Pagination options.\n * @returns A paginated list of runs.\n */\n async listAgentRuns(\n agentId: string,\n opts: { page?: number; limit?: number } = {}\n ): Promise<AgentRunListResponse> {\n const data = await this.request(\"GET\", `/api/agents/${agentId}/runs`, {\n query: { page: opts.page ?? 1, limit: opts.limit ?? 50 },\n });\n return data as AgentRunListResponse;\n }\n\n /**\n * Get details of a specific agent run.\n *\n * @param agentId - Agent identifier.\n * @param runId - Run identifier.\n * @returns Agent run details.\n */\n async getAgentRun(agentId: string, runId: string): Promise<AgentRunResponse> {\n const data = await this.request(\"GET\", `/api/agents/${agentId}/runs/${runId}`);\n return data as AgentRunResponse;\n }\n\n /**\n * Cancel an agent run.\n *\n * @param agentId - Agent identifier.\n * @param runId - Run identifier.\n * @returns Updated agent run record.\n */\n async deleteAgentRun(agentId: string, runId: string): Promise<AgentRunResponse> {\n const data = await this.request(\"DELETE\", `/api/agents/${agentId}/runs/${runId}`);\n return data as AgentRunResponse;\n }\n\n /**\n * Get content detail.\n *\n * Fetches a slice of a content version (use `start`/`end` to page through large content).\n *\n * @param sourceConnectionContentVersion - Content version identifier.\n * @param opts - Range options.\n * @returns Content details for the requested range.\n */\n async getContentDetail(\n sourceConnectionContentVersion: string,\n opts: { start?: number; end?: number } = {}\n ): Promise<ContentDetailResponse> {\n const data = await this.request(\n \"GET\",\n `/api/contents/${sourceConnectionContentVersion}`,\n { query: { start: opts.start ?? 0, end: opts.end ?? 5000 } }\n );\n return data as ContentDetailResponse;\n }\n\n /**\n * Delete a specific content version.\n *\n * @param sourceConnectionContentVersion - Content version identifier.\n */\n async deleteContent(sourceConnectionContentVersion: string): Promise<void> {\n await this.request(\"DELETE\", `/api/contents/${sourceConnectionContentVersion}`);\n }\n\n /**\n * List embeddings for a content version.\n *\n * @param sourceConnectionContentVersion - Content version identifier.\n * @param opts - Pagination options.\n * @returns A paginated list of embeddings.\n */\n async listContentEmbeddings(\n sourceConnectionContentVersion: string,\n opts: { page?: number; limit?: number } = {}\n ): Promise<ContentEmbeddingsListResponse> {\n const data = await this.request(\n \"GET\",\n `/api/contents/${sourceConnectionContentVersion}/embeddings`,\n { query: { page: opts.page ?? 1, limit: opts.limit ?? 20 } }\n );\n return data as ContentEmbeddingsListResponse;\n }\n\n /**\n * List sources.\n *\n * @param opts - Pagination and filter options.\n * @returns A paginated list of sources.\n */\n async listSources(\n opts: {\n page?: number;\n limit?: number;\n sort?: string;\n order?: \"asc\" | \"desc\";\n accountId?: string | null;\n } = {}\n ): Promise<SourceListResponse> {\n const data = await this.request(\"GET\", \"/api/sources/\", {\n query: {\n page: opts.page ?? 1,\n limit: opts.limit ?? 20,\n sort: opts.sort ?? \"created_at\",\n order: opts.order ?? \"desc\",\n account_id: opts.accountId ?? undefined,\n },\n });\n return data as SourceListResponse;\n }\n\n /**\n * Upload a file to a specific source connection.\n *\n * @param sourceConnectionId - Source connection identifier.\n * @param opts - File payload and optional metadata.\n * @param opts.file - File payload as a `Blob`, `Uint8Array`, or `ArrayBuffer`.\n * @param opts.title - Optional title for the uploaded file.\n * @param opts.fileName - Optional filename to send with the upload.\n * @param opts.mimeType - Optional MIME type to attach to the upload.\n * @returns Upload response details.\n */\n async uploadFileToSource(\n sourceConnectionId: string,\n opts: {\n file: Blob | Uint8Array | ArrayBuffer;\n title?: string;\n fileName?: string;\n mimeType?: string;\n }\n ): Promise<FileUploadResponse> {\n const url = buildURL(this.baseUrl, `/api/sources/${sourceConnectionId}/upload`);\n\n const headers: Record<string, string> = {\n ...this.defaultHeaders,\n [this.apiKeyHeader]: this.apiKey,\n };\n\n const form = new FormData();\n\n let blob: Blob;\n if (opts.file instanceof Blob) {\n blob = opts.file;\n } else if (opts.file instanceof ArrayBuffer) {\n const blobOpts = opts.mimeType ? { type: opts.mimeType } : undefined;\n blob = new Blob([new Uint8Array(opts.file)], blobOpts);\n } else {\n const blobOpts = opts.mimeType ? { type: opts.mimeType } : undefined;\n blob = new Blob([opts.file as unknown as BlobPart], blobOpts);\n }\n\n const fileName = opts.fileName ?? \"upload\";\n form.set(\"file\", blob, fileName);\n\n if (opts.title !== undefined) {\n form.set(\"title\", opts.title);\n }\n\n const response = await this.fetcher(url, {\n method: \"POST\",\n headers,\n body: form,\n });\n\n if (!response.ok) {\n const responseText = await safeText(response);\n if (response.status === 422) {\n const validation = (await safeJson(response)) as HTTPValidationError | undefined;\n throw new SeclaiAPIValidationError({\n message: \"Validation error\",\n statusCode: response.status,\n method: \"POST\",\n url: url.toString(),\n responseText,\n validationError: validation,\n });\n }\n throw new SeclaiAPIStatusError({\n message: `Request failed with status ${response.status}`,\n statusCode: response.status,\n method: \"POST\",\n url: url.toString(),\n responseText,\n });\n }\n\n return (await response.json()) as FileUploadResponse;\n }\n}\n"],"mappings":";AACO,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,2BAAN,cAAuC,YAAY;AAAA,EACxD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAQO,IAAM,uBAAN,cAAmC,YAAY;AAAA;AAAA,EAEpC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAEhB,YAAY,MAOT;AACD,UAAM,KAAK,OAAO;AAClB,SAAK,OAAO;AACZ,SAAK,aAAa,KAAK;AACvB,SAAK,SAAS,KAAK;AACnB,SAAK,MAAM,KAAK;AAChB,SAAK,eAAe,KAAK;AAAA,EAC3B;AACF;AAOO,IAAM,2BAAN,cAAuC,qBAAqB;AAAA;AAAA,EAEjD;AAAA,EAEhB,YAAY,MAOT;AACD,UAAM,IAAI;AACV,SAAK,OAAO;AACZ,SAAK,kBAAkB,KAAK;AAAA,EAC9B;AACF;;;ACrDO,IAAM,iBAAiB;AAmB9B,SAAS,OAAO,MAAkC;AAChD,QAAM,IAAK,YAAoB;AAC/B,SAAO,GAAG,MAAM,IAAI;AACtB;AAEA,SAAS,SAAS,SAAiB,MAAc,OAAsC;AACrF,QAAM,MAAM,IAAI,IAAI,MAAM,OAAO;AACjC,MAAI,OAAO;AACT,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAI,UAAU,UAAa,UAAU,KAAM;AAC3C,UAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,SAAS,UAAiD;AACvE,MAAI;AACF,WAAO,MAAM,SAAS,MAAM,EAAE,KAAK;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,SAAS,UAAkD;AACxE,MAAI;AACF,WAAO,MAAM,SAAS,MAAM,EAAE,KAAK;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASO,IAAM,SAAN,MAAa;AAAA,EACD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjB,YAAY,OAAsB,CAAC,GAAG;AACpC,UAAM,SAAS,KAAK,UAAU,OAAO,gBAAgB;AACrD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,SAAU,WAAW;AAC1C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,SAAK,SAAS;AACd,SAAK,UAAU,KAAK,WAAW,OAAO,gBAAgB,KAAK;AAC3D,SAAK,eAAe,KAAK,gBAAgB;AACzC,SAAK,iBAAiB,EAAE,GAAI,KAAK,kBAAkB,CAAC,EAAG;AACvD,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QACJ,QACA,MACA,MAKkC;AAClC,UAAM,MAAM,SAAS,KAAK,SAAS,MAAM,MAAM,KAAK;AAEpD,UAAM,UAAkC;AAAA,MACtC,GAAG,KAAK;AAAA,MACR,GAAI,MAAM,WAAW,CAAC;AAAA,MACtB,CAAC,KAAK,YAAY,GAAG,KAAK;AAAA,IAC5B;AAEA,QAAI;AACJ,QAAI,MAAM,SAAS,QAAW;AAC5B,cAAQ,cAAc,IAAI,QAAQ,cAAc,KAAK;AACrD,aAAO,KAAK,UAAU,KAAK,IAAI;AAAA,IACjC;AAEA,UAAM,OAAoB,EAAE,QAAQ,QAAQ;AAC5C,QAAI,SAAS,QAAW;AACtB,WAAK,OAAO;AAAA,IACd;AACA,UAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAE7C,QAAI,SAAS,WAAW,IAAK,QAAO;AAEpC,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,UAAM,SAAS,YAAY,SAAS,kBAAkB;AAEtD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,eAAe,MAAM,SAAS,QAAQ;AAC5C,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,aAAc,MAAM,SAAS,QAAQ;AAC3C,cAAM,IAAI,yBAAyB;AAAA,UACjC,SAAS;AAAA,UACT,YAAY,SAAS;AAAA,UACrB;AAAA,UACA,KAAK,IAAI,SAAS;AAAA,UAClB;AAAA,UACA,iBAAiB;AAAA,QACnB,CAAC;AAAA,MACH;AACA,YAAM,IAAI,qBAAqB;AAAA,QAC7B,SAAS,8BAA8B,SAAS,MAAM;AAAA,QACtD,YAAY,SAAS;AAAA,QACrB;AAAA,QACA,KAAK,IAAI,SAAS;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,SAAS,KAAM,QAAO;AAE3B,QAAI,QAAQ;AACV,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AACA,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,SAAiB,MAAkD;AAChF,UAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,eAAe,OAAO,SAAS,EAAE,MAAM,KAAK,CAAC;AACrF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cACJ,SACA,OAA0C,CAAC,GACZ;AAC/B,UAAM,OAAO,MAAM,KAAK,QAAQ,OAAO,eAAe,OAAO,SAAS;AAAA,MACpE,OAAO,EAAE,MAAM,KAAK,QAAQ,GAAG,OAAO,KAAK,SAAS,GAAG;AAAA,IACzD,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YAAY,SAAiB,OAA0C;AAC3E,UAAM,OAAO,MAAM,KAAK,QAAQ,OAAO,eAAe,OAAO,SAAS,KAAK,EAAE;AAC7E,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,SAAiB,OAA0C;AAC9E,UAAM,OAAO,MAAM,KAAK,QAAQ,UAAU,eAAe,OAAO,SAAS,KAAK,EAAE;AAChF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,iBACJ,gCACA,OAAyC,CAAC,GACV;AAChC,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,iBAAiB,8BAA8B;AAAA,MAC/C,EAAE,OAAO,EAAE,OAAO,KAAK,SAAS,GAAG,KAAK,KAAK,OAAO,IAAK,EAAE;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,gCAAuD;AACzE,UAAM,KAAK,QAAQ,UAAU,iBAAiB,8BAA8B,EAAE;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,sBACJ,gCACA,OAA0C,CAAC,GACH;AACxC,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,iBAAiB,8BAA8B;AAAA,MAC/C,EAAE,OAAO,EAAE,MAAM,KAAK,QAAQ,GAAG,OAAO,KAAK,SAAS,GAAG,EAAE;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YACJ,OAMI,CAAC,GACwB;AAC7B,UAAM,OAAO,MAAM,KAAK,QAAQ,OAAO,iBAAiB;AAAA,MACtD,OAAO;AAAA,QACL,MAAM,KAAK,QAAQ;AAAA,QACnB,OAAO,KAAK,SAAS;AAAA,QACrB,MAAM,KAAK,QAAQ;AAAA,QACnB,OAAO,KAAK,SAAS;AAAA,QACrB,YAAY,KAAK,aAAa;AAAA,MAChC;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,mBACJ,oBACA,MAM6B;AAC7B,UAAM,MAAM,SAAS,KAAK,SAAS,gBAAgB,kBAAkB,SAAS;AAE9E,UAAM,UAAkC;AAAA,MACtC,GAAG,KAAK;AAAA,MACR,CAAC,KAAK,YAAY,GAAG,KAAK;AAAA,IAC5B;AAEA,UAAM,OAAO,IAAI,SAAS;AAE1B,QAAI;AACJ,QAAI,KAAK,gBAAgB,MAAM;AAC7B,aAAO,KAAK;AAAA,IACd,WAAW,KAAK,gBAAgB,aAAa;AAC3C,YAAM,WAAW,KAAK,WAAW,EAAE,MAAM,KAAK,SAAS,IAAI;AAC3D,aAAO,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,IAAI,CAAC,GAAG,QAAQ;AAAA,IACvD,OAAO;AACL,YAAM,WAAW,KAAK,WAAW,EAAE,MAAM,KAAK,SAAS,IAAI;AAC3D,aAAO,IAAI,KAAK,CAAC,KAAK,IAA2B,GAAG,QAAQ;AAAA,IAC9D;AAEA,UAAM,WAAW,KAAK,YAAY;AAClC,SAAK,IAAI,QAAQ,MAAM,QAAQ;AAE/B,QAAI,KAAK,UAAU,QAAW;AAC5B,WAAK,IAAI,SAAS,KAAK,KAAK;AAAA,IAC9B;AAEA,UAAM,WAAW,MAAM,KAAK,QAAQ,KAAK;AAAA,MACvC,QAAQ;AAAA,MACR;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,eAAe,MAAM,SAAS,QAAQ;AAC5C,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,aAAc,MAAM,SAAS,QAAQ;AAC3C,cAAM,IAAI,yBAAyB;AAAA,UACjC,SAAS;AAAA,UACT,YAAY,SAAS;AAAA,UACrB,QAAQ;AAAA,UACR,KAAK,IAAI,SAAS;AAAA,UAClB;AAAA,UACA,iBAAiB;AAAA,QACnB,CAAC;AAAA,MACH;AACA,YAAM,IAAI,qBAAqB;AAAA,QAC7B,SAAS,8BAA8B,SAAS,MAAM;AAAA,QACtD,YAAY,SAAS;AAAA,QACrB,QAAQ;AAAA,QACR,KAAK,IAAI,SAAS;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seclai/sdk",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Seclai JavaScript SDK",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"homepage": "https://github.com/seclai/seclai-javascript",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/seclai/seclai-javascript/issues",
|
|
25
|
+
"email": "support@seclai.com"
|
|
26
|
+
},
|
|
27
|
+
"repository": "github:seclai/seclai-javascript",
|
|
28
|
+
"scripts": {
|
|
29
|
+
"version:apply": "node scripts/set-version.mjs apply",
|
|
30
|
+
"version:restore": "node scripts/set-version.mjs restore",
|
|
31
|
+
"generate": "openapi-typescript ../seclai-python/openapi/seclai.openapi.json -o src/openapi.ts",
|
|
32
|
+
"build": "npm run generate && tsup src/index.ts --format esm,cjs --dts",
|
|
33
|
+
"build:versioned": "npm run version:apply && npm run build && npm run version:restore",
|
|
34
|
+
"publish:ci": "npm run version:apply && npm run build && npm publish --provenance --access public --ignore-scripts && npm run version:restore",
|
|
35
|
+
"docs": "npm run generate && typedoc",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"openapi-typescript": "^7.9.1",
|
|
40
|
+
"typedoc": "^0.27.6",
|
|
41
|
+
"tsup": "^8.5.0",
|
|
42
|
+
"typescript": "^5.7.3"
|
|
43
|
+
}
|
|
44
|
+
}
|