@seclai/sdk 1.0.7 → 1.1.1
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 +456 -78
- package/dist/index.cjs +1927 -252
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4782 -475
- package/dist/index.d.ts +4782 -475
- package/dist/index.js +1915 -251
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Seclai JavaScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The official JavaScript/TypeScript SDK for the [Seclai](https://seclai.com) API. Provides full typed coverage of all API endpoints, file uploads, SSE streaming, polling helpers, and automatic pagination.
|
|
4
|
+
|
|
5
|
+
Works in Node.js 18+, Deno, Bun, Cloudflare Workers, and any runtime with a `fetch` implementation.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
@@ -8,138 +10,508 @@ This is the official Seclai JavaScript SDK with TypeScript typings.
|
|
|
8
10
|
npm install @seclai/sdk
|
|
9
11
|
```
|
|
10
12
|
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { Seclai } from "@seclai/sdk";
|
|
17
|
+
|
|
18
|
+
const client = new Seclai({ apiKey: process.env.SECLAI_API_KEY });
|
|
19
|
+
|
|
20
|
+
// List all sources
|
|
21
|
+
const sources = await client.listSources();
|
|
22
|
+
|
|
23
|
+
// Run an agent and stream the result
|
|
24
|
+
const result = await client.runStreamingAgentAndWait(
|
|
25
|
+
"agent_id",
|
|
26
|
+
{ input: "Summarize the latest uploads", metadata: {} },
|
|
27
|
+
{ timeoutMs: 120_000 },
|
|
28
|
+
);
|
|
29
|
+
console.log(result);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
| Option | Environment variable | Default |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `apiKey` | `SECLAI_API_KEY` | — |
|
|
37
|
+
| `accessToken` | — | — |
|
|
38
|
+
| `profile` | `SECLAI_PROFILE` | `"default"` |
|
|
39
|
+
| `configDir` | `SECLAI_CONFIG_DIR` | `~/.seclai` |
|
|
40
|
+
| `autoRefresh` | — | `true` |
|
|
41
|
+
| `accountId` | — | — |
|
|
42
|
+
| `baseUrl` | `SECLAI_API_URL` | `https://api.seclai.com` |
|
|
43
|
+
| `apiKeyHeader` | — | `x-api-key` |
|
|
44
|
+
| `defaultHeaders` | — | `{}` |
|
|
45
|
+
| `fetch` | — | `globalThis.fetch` |
|
|
46
|
+
|
|
47
|
+
### Authentication
|
|
48
|
+
|
|
49
|
+
Credentials are resolved via a chain (first match wins):
|
|
50
|
+
|
|
51
|
+
1. Explicit `apiKey` option
|
|
52
|
+
2. Explicit `accessToken` option (string or `() => string | Promise<string>`)
|
|
53
|
+
3. `SECLAI_API_KEY` environment variable
|
|
54
|
+
4. SSO profile from `~/.seclai/config` with cached tokens in `~/.seclai/sso/cache/`
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// API key
|
|
58
|
+
const client = new Seclai({ apiKey: "sk-..." });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// Static bearer token
|
|
63
|
+
const client = new Seclai({ accessToken: "eyJhbGciOi..." });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
// Dynamic bearer token provider (called per request)
|
|
68
|
+
const client = new Seclai({
|
|
69
|
+
accessToken: async () => fetchTokenFromVault(),
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// SSO profile (uses cached tokens, auto-refreshes)
|
|
75
|
+
const client = new Seclai({ profile: "my-profile" });
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// Environment variable (no options needed)
|
|
80
|
+
// export SECLAI_API_KEY="sk-..."
|
|
81
|
+
const client = new Seclai();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To set up SSO authentication, install the [Seclai CLI](https://www.npmjs.com/package/seclai) and run:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
seclai configure sso # set up an SSO profile
|
|
88
|
+
seclai auth login # authenticate via browser
|
|
89
|
+
```
|
|
90
|
+
|
|
11
91
|
## API documentation
|
|
12
92
|
|
|
13
93
|
Online API documentation (latest):
|
|
14
94
|
|
|
15
|
-
https://seclai.github.io/seclai-javascript/1.
|
|
95
|
+
https://seclai.github.io/seclai-javascript/1.1.1/
|
|
96
|
+
|
|
97
|
+
## Resources
|
|
16
98
|
|
|
17
|
-
|
|
99
|
+
### Agents
|
|
18
100
|
|
|
19
101
|
```ts
|
|
20
|
-
|
|
102
|
+
// CRUD
|
|
103
|
+
const agents = await client.listAgents({ page: 1, limit: 20 });
|
|
104
|
+
const agent = await client.createAgent({ name: "My Agent", description: "..." });
|
|
105
|
+
const fetched = await client.getAgent("agent_id");
|
|
106
|
+
const updated = await client.updateAgent("agent_id", { name: "Renamed" });
|
|
107
|
+
await client.deleteAgent("agent_id");
|
|
108
|
+
|
|
109
|
+
// Definition (step workflow)
|
|
110
|
+
const def = await client.getAgentDefinition("agent_id");
|
|
111
|
+
await client.updateAgentDefinition("agent_id", { steps: [...], change_id: def.change_id });
|
|
112
|
+
```
|
|
21
113
|
|
|
22
|
-
|
|
114
|
+
### Agent runs
|
|
23
115
|
|
|
24
|
-
|
|
25
|
-
|
|
116
|
+
```ts
|
|
117
|
+
// Start a run
|
|
118
|
+
const run = await client.runAgent("agent_id", { input: "Hello" });
|
|
119
|
+
|
|
120
|
+
// List & search runs
|
|
121
|
+
const runs = await client.listAgentRuns("agent_id", { status: "completed" });
|
|
122
|
+
const search = await client.searchAgentRuns({ agent_id: "...", status: ["completed"] });
|
|
123
|
+
|
|
124
|
+
// Fetch run details (optionally with step outputs)
|
|
125
|
+
const detail = await client.getAgentRun("run_id", { includeStepOutputs: true });
|
|
126
|
+
|
|
127
|
+
// Cancel or delete
|
|
128
|
+
await client.cancelAgentRun("run_id");
|
|
129
|
+
await client.deleteAgentRun("run_id");
|
|
26
130
|
```
|
|
27
131
|
|
|
28
|
-
###
|
|
132
|
+
### Streaming
|
|
29
133
|
|
|
30
|
-
|
|
134
|
+
The SDK provides two streaming patterns over the SSE `/runs/stream` endpoint:
|
|
31
135
|
|
|
32
|
-
|
|
136
|
+
**Block until done** — returns the final `done` payload or throws on timeout:
|
|
33
137
|
|
|
34
138
|
```ts
|
|
35
|
-
|
|
139
|
+
const result = await client.runStreamingAgentAndWait(
|
|
140
|
+
"agent_id",
|
|
141
|
+
{ input: "Hello", metadata: {} },
|
|
142
|
+
{ timeoutMs: 60_000 },
|
|
143
|
+
);
|
|
144
|
+
```
|
|
36
145
|
|
|
37
|
-
|
|
146
|
+
**Async iterator** — yields every SSE event as `{ event, data }`:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
for await (const event of client.runStreamingAgent(
|
|
150
|
+
"agent_id",
|
|
151
|
+
{ input: "Hello" },
|
|
152
|
+
{ timeoutMs: 120_000 },
|
|
153
|
+
)) {
|
|
154
|
+
console.log(event.event, event.data);
|
|
155
|
+
if (event.event === "done") break;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Polling
|
|
38
160
|
|
|
39
|
-
|
|
161
|
+
For environments where SSE is not practical, poll for a completed run:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
const result = await client.runAgentAndPoll(
|
|
40
165
|
"agent_id",
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
metadata: { app: "My App" },
|
|
44
|
-
},
|
|
45
|
-
{ timeoutMs: 60_000 }
|
|
166
|
+
{ input: "Hello" },
|
|
167
|
+
{ pollIntervalMs: 2_000, timeoutMs: 120_000 },
|
|
46
168
|
);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Agent input uploads
|
|
47
172
|
|
|
48
|
-
|
|
173
|
+
```ts
|
|
174
|
+
const upload = await client.uploadAgentInput("agent_id", {
|
|
175
|
+
file: new Uint8Array([...]),
|
|
176
|
+
fileName: "input.pdf",
|
|
177
|
+
});
|
|
178
|
+
const status = await client.getAgentInputUploadStatus("agent_id", upload.upload_id);
|
|
49
179
|
```
|
|
50
180
|
|
|
51
|
-
###
|
|
181
|
+
### Agent AI assistant
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const steps = await client.generateAgentSteps("agent_id", { user_input: "Build a RAG pipeline" });
|
|
185
|
+
const config = await client.generateStepConfig("agent_id", { step_type: "llm", user_input: "..." });
|
|
186
|
+
|
|
187
|
+
// Conversation history
|
|
188
|
+
const history = await client.getAgentAiConversationHistory("agent_id");
|
|
189
|
+
await client.markAgentAiSuggestion("agent_id", "conversation_id", { accepted: true });
|
|
190
|
+
```
|
|
52
191
|
|
|
53
|
-
|
|
192
|
+
### Agent evaluations
|
|
54
193
|
|
|
55
194
|
```ts
|
|
56
|
-
|
|
195
|
+
const criteria = await client.listEvaluationCriteria("agent_id");
|
|
196
|
+
const created = await client.createEvaluationCriteria("agent_id", { name: "Accuracy", ... });
|
|
197
|
+
const detail = await client.getEvaluationCriteria("criteria_id");
|
|
198
|
+
await client.updateEvaluationCriteria("criteria_id", { ... });
|
|
199
|
+
await client.deleteEvaluationCriteria("criteria_id");
|
|
57
200
|
|
|
58
|
-
|
|
201
|
+
// Test a draft
|
|
202
|
+
await client.testDraftEvaluation("agent_id", { criteria: { ... }, run_id: "..." });
|
|
59
203
|
|
|
60
|
-
//
|
|
61
|
-
const
|
|
62
|
-
|
|
204
|
+
// Results by criteria
|
|
205
|
+
const results = await client.listEvaluationResults("criteria_id");
|
|
206
|
+
const summary = await client.getEvaluationCriteriaSummary("criteria_id");
|
|
207
|
+
await client.createEvaluationResult("criteria_id", { ... });
|
|
63
208
|
|
|
64
|
-
//
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
209
|
+
// Results by run
|
|
210
|
+
const runResults = await client.listRunEvaluationResults("agent_id", "run_id");
|
|
211
|
+
|
|
212
|
+
// Non-manual evaluation summary
|
|
213
|
+
const nonManual = await client.getNonManualEvaluationSummary("agent_id");
|
|
214
|
+
|
|
215
|
+
// Compatible runs for a criteria
|
|
216
|
+
const compatible = await client.listCompatibleRuns("criteria_id");
|
|
69
217
|
```
|
|
70
218
|
|
|
71
|
-
###
|
|
219
|
+
### Knowledge bases
|
|
72
220
|
|
|
73
|
-
|
|
221
|
+
```ts
|
|
222
|
+
const kbs = await client.listKnowledgeBases();
|
|
223
|
+
const kb = await client.createKnowledgeBase({ name: "Docs KB" });
|
|
224
|
+
const fetched = await client.getKnowledgeBase("kb_id");
|
|
225
|
+
await client.updateKnowledgeBase("kb_id", { name: "Renamed KB" });
|
|
226
|
+
await client.deleteKnowledgeBase("kb_id");
|
|
227
|
+
```
|
|
74
228
|
|
|
75
|
-
|
|
76
|
-
- `application/epub+zip`
|
|
77
|
-
- `application/json`
|
|
78
|
-
- `application/msword`
|
|
79
|
-
- `application/pdf`
|
|
80
|
-
- `application/vnd.ms-excel`
|
|
81
|
-
- `application/vnd.ms-outlook`
|
|
82
|
-
- `application/vnd.ms-powerpoint`
|
|
83
|
-
- `application/vnd.openxmlformats-officedocument.presentationml.presentation`
|
|
84
|
-
- `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
|
|
85
|
-
- `application/vnd.openxmlformats-officedocument.wordprocessingml.document`
|
|
86
|
-
- `application/xml`
|
|
87
|
-
- `application/zip`
|
|
88
|
-
- `audio/flac`, `audio/mp4`, `audio/mpeg`, `audio/ogg`, `audio/wav`
|
|
89
|
-
- `image/bmp`, `image/gif`, `image/jpeg`, `image/png`, `image/tiff`, `image/webp`
|
|
90
|
-
- `text/csv`, `text/html`, `text/markdown`, `text/x-markdown`, `text/plain`, `text/xml`
|
|
91
|
-
- `video/mp4`, `video/quicktime`, `video/x-msvideo`
|
|
229
|
+
### Memory banks
|
|
92
230
|
|
|
93
|
-
|
|
231
|
+
```ts
|
|
232
|
+
const banks = await client.listMemoryBanks();
|
|
233
|
+
const bank = await client.createMemoryBank({ name: "Chat Memory", type: "conversation" });
|
|
234
|
+
const fetched = await client.getMemoryBank("mb_id");
|
|
235
|
+
await client.updateMemoryBank("mb_id", { name: "Renamed" });
|
|
236
|
+
await client.deleteMemoryBank("mb_id");
|
|
237
|
+
|
|
238
|
+
// Stats & compaction
|
|
239
|
+
const stats = await client.getMemoryBankStats("mb_id");
|
|
240
|
+
await client.compactMemoryBank("mb_id");
|
|
241
|
+
|
|
242
|
+
// Test compaction
|
|
243
|
+
const test = await client.testMemoryBankCompaction("mb_id", { ... });
|
|
244
|
+
const standalone = await client.testCompactionPromptStandalone({ ... });
|
|
245
|
+
|
|
246
|
+
// Templates & agents
|
|
247
|
+
const templates = await client.listMemoryBankTemplates();
|
|
248
|
+
const agents = await client.getAgentsUsingMemoryBank("mb_id");
|
|
249
|
+
|
|
250
|
+
// AI assistant
|
|
251
|
+
const suggestion = await client.generateMemoryBankConfig({ user_input: "..." });
|
|
252
|
+
const history = await client.getMemoryBankAiLastConversation();
|
|
253
|
+
await client.acceptMemoryBankAiSuggestion("conv_id", { ... });
|
|
254
|
+
|
|
255
|
+
// Source management
|
|
256
|
+
await client.deleteMemoryBankSource("mb_id");
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Sources
|
|
94
260
|
|
|
95
261
|
```ts
|
|
96
|
-
|
|
262
|
+
const sources = await client.listSources({ page: 1, limit: 20, order: "asc" });
|
|
263
|
+
const source = await client.createSource({ name: "My Source", ... });
|
|
264
|
+
const fetched = await client.getSource("source_id");
|
|
265
|
+
await client.updateSource("source_id", { name: "Renamed" });
|
|
266
|
+
await client.deleteSource("source_id");
|
|
267
|
+
```
|
|
97
268
|
|
|
98
|
-
|
|
269
|
+
### File uploads
|
|
270
|
+
|
|
271
|
+
Upload a file to a source (max 200 MiB). The SDK infers MIME type from the file extension when `mimeType` is not provided.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import { readFile } from "node:fs/promises";
|
|
99
275
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
title: "Hello",
|
|
106
|
-
metadata: { category: "docs", author: "Ada" },
|
|
276
|
+
await client.uploadFileToSource("source_id", {
|
|
277
|
+
file: await readFile("document.pdf"),
|
|
278
|
+
fileName: "document.pdf",
|
|
279
|
+
title: "Q4 Report",
|
|
280
|
+
metadata: { department: "finance" },
|
|
107
281
|
});
|
|
108
|
-
console.log(upload);
|
|
109
282
|
```
|
|
110
283
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
If you need to correct or update an uploaded document while keeping references stable,
|
|
114
|
-
use `uploadFileToContent` to upload a new file and replace the content behind an existing
|
|
115
|
-
`source_connection_content_version`.
|
|
284
|
+
Upload inline text:
|
|
116
285
|
|
|
117
286
|
```ts
|
|
118
|
-
|
|
287
|
+
await client.uploadInlineTextToSource("source_id", {
|
|
288
|
+
text: "Hello, world!",
|
|
289
|
+
title: "Greeting",
|
|
290
|
+
});
|
|
291
|
+
```
|
|
119
292
|
|
|
120
|
-
|
|
293
|
+
Replace a content version with a new file:
|
|
121
294
|
|
|
122
|
-
|
|
123
|
-
|
|
295
|
+
```ts
|
|
296
|
+
await client.uploadFileToContent("content_version_id", {
|
|
297
|
+
file: await readFile("updated.pdf"),
|
|
124
298
|
fileName: "updated.pdf",
|
|
125
299
|
mimeType: "application/pdf",
|
|
126
|
-
title: "Updated document",
|
|
127
|
-
metadata: { revision: 2 },
|
|
128
300
|
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Source exports
|
|
129
304
|
|
|
130
|
-
|
|
305
|
+
```ts
|
|
306
|
+
const exports = await client.listSourceExports("source_id");
|
|
307
|
+
const exp = await client.createSourceExport("source_id", { format: "json" });
|
|
308
|
+
const status = await client.getSourceExport("source_id", exp.id);
|
|
309
|
+
const estimate = await client.estimateSourceExport("source_id", {});
|
|
310
|
+
const response = await client.downloadSourceExport("source_id", exp.id);
|
|
311
|
+
await client.deleteSourceExport("source_id", exp.id);
|
|
312
|
+
await client.cancelSourceExport("source_id", exp.id);
|
|
131
313
|
```
|
|
132
314
|
|
|
133
|
-
|
|
315
|
+
### Source embedding migrations
|
|
134
316
|
|
|
135
|
-
|
|
317
|
+
```ts
|
|
318
|
+
const migration = await client.getSourceEmbeddingMigration("source_id");
|
|
319
|
+
await client.startSourceEmbeddingMigration("source_id", { target_model: "..." });
|
|
320
|
+
await client.cancelSourceEmbeddingMigration("source_id");
|
|
321
|
+
```
|
|
136
322
|
|
|
137
|
-
|
|
323
|
+
### Content
|
|
138
324
|
|
|
139
|
-
```
|
|
140
|
-
|
|
325
|
+
```ts
|
|
326
|
+
const detail = await client.getContentDetail("content_id", { start: 0, end: 1000 });
|
|
327
|
+
const embeddings = await client.listContentEmbeddings("content_id");
|
|
328
|
+
await client.deleteContent("content_id");
|
|
329
|
+
|
|
330
|
+
// Replace content with inline text
|
|
331
|
+
await client.replaceContentWithInlineText("content_id", { text: "Updated text", title: "Updated" });
|
|
332
|
+
|
|
333
|
+
// Upload a replacement file
|
|
334
|
+
await client.uploadFileToContent("content_id", {
|
|
335
|
+
file: await readFile("updated.pdf"),
|
|
336
|
+
fileName: "updated.pdf",
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Solutions
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
const solutions = await client.listSolutions();
|
|
344
|
+
const sol = await client.createSolution({ name: "My Solution" });
|
|
345
|
+
const fetched = await client.getSolution("solution_id");
|
|
346
|
+
await client.updateSolution("solution_id", { name: "Renamed" });
|
|
347
|
+
await client.deleteSolution("solution_id");
|
|
348
|
+
|
|
349
|
+
// Link / unlink resources
|
|
350
|
+
await client.linkAgentsToSolution("solution_id", { ids: ["agent_id"] });
|
|
351
|
+
await client.unlinkAgentsFromSolution("solution_id", { ids: ["agent_id"] });
|
|
352
|
+
await client.linkKnowledgeBasesToSolution("solution_id", { ids: ["kb_id"] });
|
|
353
|
+
await client.unlinkKnowledgeBasesFromSolution("solution_id", { ids: ["kb_id"] });
|
|
354
|
+
await client.linkSourceConnectionsToSolution("solution_id", { ids: ["source_id"] });
|
|
355
|
+
await client.unlinkSourceConnectionsFromSolution("solution_id", { ids: ["source_id"] });
|
|
356
|
+
|
|
357
|
+
// AI assistant
|
|
358
|
+
const plan = await client.generateSolutionAiPlan("solution_id", { user_input: "Set up a RAG pipeline" });
|
|
359
|
+
await client.acceptSolutionAiPlan("solution_id", "conversation_id", {});
|
|
360
|
+
await client.declineSolutionAiPlan("solution_id", "conversation_id");
|
|
361
|
+
|
|
362
|
+
// AI-generated knowledge base / source within the solution
|
|
363
|
+
await client.generateSolutionAiKnowledgeBase("solution_id", { user_input: "..." });
|
|
364
|
+
await client.generateSolutionAiSource("solution_id", { user_input: "..." });
|
|
365
|
+
|
|
366
|
+
// Conversations
|
|
367
|
+
const convs = await client.listSolutionConversations("solution_id");
|
|
368
|
+
await client.addSolutionConversationTurn("solution_id", { user_input: "..." });
|
|
369
|
+
await client.markSolutionConversationTurn("solution_id", "conversation_id", { ... });
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Governance AI
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
const plan = await client.generateGovernanceAiPlan({ user_input: "Add a toxicity policy" });
|
|
376
|
+
const convs = await client.listGovernanceAiConversations();
|
|
377
|
+
await client.acceptGovernanceAiPlan("conversation_id");
|
|
378
|
+
await client.declineGovernanceAiPlan("conversation_id");
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Alerts
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
const alerts = await client.listAlerts({ status: "active" });
|
|
385
|
+
const alert = await client.getAlert("alert_id");
|
|
386
|
+
await client.changeAlertStatus("alert_id", { status: "resolved" });
|
|
387
|
+
await client.addAlertComment("alert_id", { text: "Investigating" });
|
|
388
|
+
|
|
389
|
+
// Subscriptions
|
|
390
|
+
await client.subscribeToAlert("alert_id");
|
|
391
|
+
await client.unsubscribeFromAlert("alert_id");
|
|
392
|
+
|
|
393
|
+
// Alert configs
|
|
394
|
+
const configs = await client.listAlertConfigs();
|
|
395
|
+
await client.createAlertConfig({ ... });
|
|
396
|
+
await client.getAlertConfig("config_id");
|
|
397
|
+
await client.updateAlertConfig("config_id", { ... });
|
|
398
|
+
await client.deleteAlertConfig("config_id");
|
|
399
|
+
|
|
400
|
+
// Organization preferences
|
|
401
|
+
const prefs = await client.listOrganizationAlertPreferences();
|
|
402
|
+
await client.updateOrganizationAlertPreference("org_id", "alert_type", { ... });
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Models
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
const alerts = await client.listModelAlerts();
|
|
409
|
+
await client.markModelAlertRead("alert_id");
|
|
410
|
+
await client.markAllModelAlertsRead();
|
|
411
|
+
const unread = await client.getUnreadModelAlertCount();
|
|
412
|
+
const recs = await client.getModelRecommendations("model_id");
|
|
141
413
|
```
|
|
142
414
|
|
|
415
|
+
### Search
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
const results = await client.search({ query: "quarterly report" });
|
|
419
|
+
const filtered = await client.search({ query: "my agent", entityType: "agent", limit: 5 });
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Top-level AI assistant
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
// Generate plans for different resource types
|
|
426
|
+
const kb = await client.aiAssistantKnowledgeBase({ user_input: "Create a docs KB" });
|
|
427
|
+
const src = await client.aiAssistantSource({ user_input: "Add a web source" });
|
|
428
|
+
const sol = await client.aiAssistantSolution({ user_input: "Set up monitoring" });
|
|
429
|
+
const mb = await client.aiAssistantMemoryBank({ user_input: "Create a chat memory" });
|
|
430
|
+
|
|
431
|
+
// Accept or decline the generated plan
|
|
432
|
+
await client.acceptAiAssistantPlan("conversation_id", { confirm_deletions: true });
|
|
433
|
+
await client.declineAiAssistantPlan("conversation_id");
|
|
434
|
+
|
|
435
|
+
// Memory bank conversation history
|
|
436
|
+
const history = await client.getAiAssistantMemoryBankHistory();
|
|
437
|
+
await client.acceptAiMemoryBankSuggestion("conversation_id", { ... });
|
|
438
|
+
|
|
439
|
+
// Feedback
|
|
440
|
+
await client.submitAiFeedback({ ... });
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Pagination helper
|
|
444
|
+
|
|
445
|
+
Automatically iterate through all pages:
|
|
446
|
+
|
|
447
|
+
```ts
|
|
448
|
+
for await (const source of client.paginate(
|
|
449
|
+
(opts) => client.listSources(opts),
|
|
450
|
+
{ limit: 50 },
|
|
451
|
+
)) {
|
|
452
|
+
console.log(source.name);
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Error handling
|
|
457
|
+
|
|
458
|
+
All errors extend `SeclaiError`:
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
import {
|
|
462
|
+
SeclaiError,
|
|
463
|
+
SeclaiConfigurationError,
|
|
464
|
+
SeclaiAPIStatusError,
|
|
465
|
+
SeclaiAPIValidationError,
|
|
466
|
+
SeclaiStreamingError,
|
|
467
|
+
} from "@seclai/sdk";
|
|
468
|
+
|
|
469
|
+
try {
|
|
470
|
+
await client.getAgent("bad_id");
|
|
471
|
+
} catch (err) {
|
|
472
|
+
if (err instanceof SeclaiAPIValidationError) {
|
|
473
|
+
console.error("Validation:", err.validationError);
|
|
474
|
+
} else if (err instanceof SeclaiAPIStatusError) {
|
|
475
|
+
console.error(`HTTP ${err.statusCode}:`, err.responseText);
|
|
476
|
+
} else if (err instanceof SeclaiStreamingError) {
|
|
477
|
+
console.error("Stream failed for run:", err.runId);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Cancellation (AbortSignal)
|
|
483
|
+
|
|
484
|
+
All low-level methods support an `AbortSignal` for request cancellation:
|
|
485
|
+
|
|
486
|
+
```ts
|
|
487
|
+
const controller = new AbortController();
|
|
488
|
+
|
|
489
|
+
// Cancel after 5 seconds
|
|
490
|
+
setTimeout(() => controller.abort(), 5_000);
|
|
491
|
+
|
|
492
|
+
const data = await client.request("GET", "/agents", {
|
|
493
|
+
signal: controller.signal,
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Low-level access
|
|
498
|
+
|
|
499
|
+
For endpoints not yet covered by a convenience method, use `request` or `requestRaw`:
|
|
500
|
+
|
|
501
|
+
```ts
|
|
502
|
+
// JSON request/response
|
|
503
|
+
const data = await client.request("POST", "/custom/endpoint", {
|
|
504
|
+
json: { key: "value" },
|
|
505
|
+
query: { filter: "active" },
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// Raw Response (e.g. binary downloads)
|
|
509
|
+
const response = await client.requestRaw("GET", "/files/download/123");
|
|
510
|
+
const blob = await response.blob();
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## Development
|
|
514
|
+
|
|
143
515
|
### Install dependencies
|
|
144
516
|
|
|
145
517
|
```bash
|
|
@@ -160,6 +532,12 @@ npm run build
|
|
|
160
532
|
|
|
161
533
|
This also regenerates `src/openapi.ts` from `openapi/seclai.openapi.json`.
|
|
162
534
|
|
|
535
|
+
### Run tests
|
|
536
|
+
|
|
537
|
+
```bash
|
|
538
|
+
npm test
|
|
539
|
+
```
|
|
540
|
+
|
|
163
541
|
### Generate docs
|
|
164
542
|
|
|
165
543
|
Generate HTML docs into `build/docs/`:
|