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