@seclai/cli 1.2.2 → 1.4.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 +26 -2
- package/dist/cli.js +67 -8
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ npx add-mcp https://api.seclai.com/mcp --header "X-API-Key: $SECLAI_API_KEY" --n
|
|
|
42
42
|
|
|
43
43
|
## Documentation
|
|
44
44
|
|
|
45
|
-
Command reference (latest): https://seclai.github.io/seclai-cli/1.
|
|
45
|
+
Command reference (latest): https://seclai.github.io/seclai-cli/1.4.0/
|
|
46
46
|
|
|
47
47
|
## Authentication
|
|
48
48
|
|
|
@@ -162,6 +162,9 @@ seclai agents runs delete <runId>
|
|
|
162
162
|
seclai agents runs cancel <runId>
|
|
163
163
|
seclai agents runs search [--page N] [--limit N] [--json '...']
|
|
164
164
|
seclai agents runs eval-results <agentId> <runId> [--page N] [--limit N]
|
|
165
|
+
# Download a file attachment emitted by a run step. attachmentId is the
|
|
166
|
+
# URL-safe-base64 storage_key from run output manifests / webhooks.
|
|
167
|
+
seclai agents runs download-attachment <runId> <attachmentId> [--download-name <name>] [--output <path>]
|
|
165
168
|
```
|
|
166
169
|
|
|
167
170
|
#### Agent Definition
|
|
@@ -171,16 +174,27 @@ seclai agents def get <agentId>
|
|
|
171
174
|
seclai agents def update <agentId> --json '{"steps":[...]}'
|
|
172
175
|
```
|
|
173
176
|
|
|
174
|
-
#### Agent Export
|
|
177
|
+
#### Agent Export / Import
|
|
175
178
|
|
|
176
179
|
```bash
|
|
177
180
|
seclai agents export <agentId>
|
|
178
181
|
seclai agents export <agentId> --no-download
|
|
182
|
+
|
|
183
|
+
# Validate an agent_definition payload without creating an agent.
|
|
184
|
+
# Reports counts and any unresolved_refs you'll need to map with entity_remap
|
|
185
|
+
# when calling `agents create` or `agents update`.
|
|
186
|
+
# The body shape is `{ "agent_definition": <export payload> }`.
|
|
187
|
+
seclai agents preview-import --json-file ./preview-body.json
|
|
188
|
+
seclai agents export <agentId> \
|
|
189
|
+
| jq '{agent_definition: .}' \
|
|
190
|
+
| seclai agents preview-import --json-file -
|
|
179
191
|
```
|
|
180
192
|
|
|
181
193
|
#### Agent Input Upload
|
|
182
194
|
|
|
183
195
|
```bash
|
|
196
|
+
# Discover which files (if any) the agent expects before staging uploads.
|
|
197
|
+
seclai agents attachment-references <agentId>
|
|
184
198
|
seclai agents upload-input <agentId> --file ./data.csv [--file-name data.csv] [--mime-type text/csv]
|
|
185
199
|
seclai agents input-status <agentId> <uploadId>
|
|
186
200
|
```
|
|
@@ -403,6 +417,16 @@ seclai models alerts unread-count
|
|
|
403
417
|
seclai models recommendations <modelId>
|
|
404
418
|
```
|
|
405
419
|
|
|
420
|
+
#### Model Playground Experiments
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
seclai models experiments list [--days N] [--start-date <date>] [--end-date <date>] [--limit N] [--offset N]
|
|
424
|
+
seclai models experiments create --json '{"model_ids":["gpt-4o"],"prompt":"Compare responses"}'
|
|
425
|
+
seclai models experiments get <experimentId>
|
|
426
|
+
seclai models experiments cancel <experimentId>
|
|
427
|
+
seclai models experiments delete <experimentId> # soft-delete, preserves audit history
|
|
428
|
+
```
|
|
429
|
+
|
|
406
430
|
### Search
|
|
407
431
|
|
|
408
432
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -21,6 +21,9 @@ function defaultRuntime() {
|
|
|
21
21
|
writeOut: (text) => {
|
|
22
22
|
process2.stdout.write(text);
|
|
23
23
|
},
|
|
24
|
+
writeOutBytes: (bytes) => {
|
|
25
|
+
process2.stdout.write(bytes);
|
|
26
|
+
},
|
|
24
27
|
writeErr: (text) => {
|
|
25
28
|
process2.stderr.write(text);
|
|
26
29
|
},
|
|
@@ -291,6 +294,37 @@ function register(program, rt) {
|
|
|
291
294
|
printJson(rt, await client.searchAgentRuns(body));
|
|
292
295
|
});
|
|
293
296
|
});
|
|
297
|
+
runs.command("download-attachment").description(
|
|
298
|
+
"Download a file attachment emitted by a step in an agent run. The attachmentId is the URL-safe-base64 storage_key from run output manifests / webhooks."
|
|
299
|
+
).argument("<runId>", "Run ID.").argument("<attachmentId>", "Attachment ID (storage_key).").option("--download-name <name>", "Filename hint for the download disposition.").option("--output <path>", "Write the attachment bytes to this file. If omitted, raw bytes are written to stdout.").action(async (runId, attachmentId, opts) => {
|
|
300
|
+
await run(rt, async () => {
|
|
301
|
+
const client = createClient(program.opts());
|
|
302
|
+
const res = await client.downloadAgentRunAttachment(
|
|
303
|
+
runId,
|
|
304
|
+
attachmentId,
|
|
305
|
+
opts.downloadName ? { downloadName: opts.downloadName } : {}
|
|
306
|
+
);
|
|
307
|
+
if (opts.output) {
|
|
308
|
+
const { createWriteStream } = await import("fs");
|
|
309
|
+
const { stat } = await import("fs/promises");
|
|
310
|
+
if (res.body) {
|
|
311
|
+
const { Readable } = await import("stream");
|
|
312
|
+
const { pipeline } = await import("stream/promises");
|
|
313
|
+
await pipeline(
|
|
314
|
+
Readable.fromWeb(res.body),
|
|
315
|
+
createWriteStream(opts.output)
|
|
316
|
+
);
|
|
317
|
+
} else {
|
|
318
|
+
const { writeFile: writeFile5 } = await import("fs/promises");
|
|
319
|
+
await writeFile5(opts.output, Buffer.from(await res.arrayBuffer()));
|
|
320
|
+
}
|
|
321
|
+
const { size } = await stat(opts.output);
|
|
322
|
+
printJson(rt, { saved: opts.output, bytes: size });
|
|
323
|
+
} else {
|
|
324
|
+
rt.writeOutBytes(new Uint8Array(await res.arrayBuffer()));
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
});
|
|
294
328
|
const def = agents.command("def").description("Agent definition (step workflow).");
|
|
295
329
|
def.command("get").description("Get agent definition.").argument("<agentId>", "Agent ID.").action(async (agentId) => {
|
|
296
330
|
await run(rt, async () => {
|
|
@@ -311,6 +345,15 @@ function register(program, rt) {
|
|
|
311
345
|
printJson(rt, await client.exportAgent(agentId, opts.download));
|
|
312
346
|
});
|
|
313
347
|
});
|
|
348
|
+
agents.command("preview-import").description(
|
|
349
|
+
"Validate an agent_definition payload without creating any agent. Reports step/schedule/alert/criteria/policy counts and any unresolved_refs (workflow refs to KBs, memory banks, source connections, or sub-agents that don't exist in this account)."
|
|
350
|
+
).option("--json <json>", "Inline JSON body ({ agent_definition: ... }). Use '-' for stdin.").option("--json-file <path>", "JSON file path. Use '-' for stdin.").action(async (opts) => {
|
|
351
|
+
await run(rt, async () => {
|
|
352
|
+
const client = createClient(program.opts());
|
|
353
|
+
const body = await readJsonInput(rt, { json: opts.json, jsonFile: opts.jsonFile });
|
|
354
|
+
printJson(rt, await client.previewImportAgent(body));
|
|
355
|
+
});
|
|
356
|
+
});
|
|
314
357
|
agents.command("upload-input").description("Upload a file as agent input.").argument("<agentId>", "Agent ID.").requiredOption("--file <path>", "File to upload.").option("--file-name <name>", "Override filename.").option("--mime-type <type>", "MIME type.").action(async (agentId, opts) => {
|
|
315
358
|
await run(rt, async () => {
|
|
316
359
|
const client = createClient(program.opts());
|
|
@@ -328,6 +371,14 @@ function register(program, rt) {
|
|
|
328
371
|
printJson(rt, await client.getAgentInputUploadStatus(agentId, uploadId));
|
|
329
372
|
});
|
|
330
373
|
});
|
|
374
|
+
agents.command("attachment-references").description(
|
|
375
|
+
"Show which files (if any) an agent's templates expect on a run. Call before staging uploads: requires_uploads reports whether the agent accepts files, and the agent block lists the exact names / indexes / patterns a run-time batch must satisfy."
|
|
376
|
+
).argument("<agentId>", "Agent ID.").action(async (agentId) => {
|
|
377
|
+
await run(rt, async () => {
|
|
378
|
+
const client = createClient(program.opts());
|
|
379
|
+
printJson(rt, await client.getAgentAttachmentReferences(agentId));
|
|
380
|
+
});
|
|
381
|
+
});
|
|
331
382
|
const ai = agents.command("ai").description("Agent AI assistant.");
|
|
332
383
|
withAiInputOptions(
|
|
333
384
|
ai.command("gen-steps").description("Generate agent steps via AI.").argument("<agentId>", "Agent ID.")
|
|
@@ -1126,6 +1177,13 @@ function register10(program, rt) {
|
|
|
1126
1177
|
printJson(rt, await client.cancelExperiment(experimentId));
|
|
1127
1178
|
});
|
|
1128
1179
|
});
|
|
1180
|
+
experiments.command("delete").description("Soft-delete a model playground experiment (preserves audit history).").argument("<experimentId>", "Experiment ID.").action(async (experimentId) => {
|
|
1181
|
+
await run(rt, async () => {
|
|
1182
|
+
const client = createClient(program.opts());
|
|
1183
|
+
await client.deleteExperiment(experimentId);
|
|
1184
|
+
printJson(rt, { ok: true });
|
|
1185
|
+
});
|
|
1186
|
+
});
|
|
1129
1187
|
}
|
|
1130
1188
|
|
|
1131
1189
|
// src/commands/search.ts
|
|
@@ -2002,10 +2060,10 @@ _seclai_completions() {
|
|
|
2002
2060
|
case "\${COMP_WORDS[1]}" in
|
|
2003
2061
|
agents)
|
|
2004
2062
|
case "\${COMP_WORDS[2]}" in
|
|
2005
|
-
runs) COMPREPLY=( $(compgen -W "list get delete cancel search eval-results" -- "$cur") ); return ;;
|
|
2063
|
+
runs) COMPREPLY=( $(compgen -W "list get delete cancel search eval-results download-attachment" -- "$cur") ); return ;;
|
|
2006
2064
|
def) COMPREPLY=( $(compgen -W "get update" -- "$cur") ); return ;;
|
|
2007
2065
|
ai) COMPREPLY=( $(compgen -W "gen-steps step-config history mark" -- "$cur") ); return ;;
|
|
2008
|
-
*) COMPREPLY=( $(compgen -W "list create get update delete run runs def export upload-input input-status ai" -- "$cur") ); return ;;
|
|
2066
|
+
*) COMPREPLY=( $(compgen -W "list create get update delete run runs def export preview-import upload-input input-status attachment-references ai" -- "$cur") ); return ;;
|
|
2009
2067
|
esac ;;
|
|
2010
2068
|
sources|source)
|
|
2011
2069
|
case "\${COMP_WORDS[2]}" in
|
|
@@ -2045,8 +2103,9 @@ _seclai_completions() {
|
|
|
2045
2103
|
esac ;;
|
|
2046
2104
|
models)
|
|
2047
2105
|
case "\${COMP_WORDS[2]}" in
|
|
2048
|
-
alerts)
|
|
2049
|
-
|
|
2106
|
+
alerts) COMPREPLY=( $(compgen -W "list mark-read mark-all-read unread-count" -- "$cur") ); return ;;
|
|
2107
|
+
experiments) COMPREPLY=( $(compgen -W "list create get cancel delete" -- "$cur") ); return ;;
|
|
2108
|
+
*) COMPREPLY=( $(compgen -W "alerts recommendations experiments" -- "$cur") ); return ;;
|
|
2050
2109
|
esac ;;
|
|
2051
2110
|
ai) COMPREPLY=( $(compgen -W "feedback kb source solution memory memory-history accept decline memory-accept" -- "$cur") ); return ;;
|
|
2052
2111
|
skills) COMPREPLY=( $(compgen -W "install" -- "$cur") ); return ;;
|
|
@@ -2097,7 +2156,7 @@ _seclai() {
|
|
|
2097
2156
|
args)
|
|
2098
2157
|
case \${words[1]} in
|
|
2099
2158
|
agents)
|
|
2100
|
-
local -a sub=(list create get update delete run runs def export upload-input input-status ai)
|
|
2159
|
+
local -a sub=(list create get update delete run runs def export preview-import upload-input input-status attachment-references ai)
|
|
2101
2160
|
_describe 'subcommand' sub ;;
|
|
2102
2161
|
sources|source)
|
|
2103
2162
|
local -a sub=(list create get update delete upload upload-text exports migration)
|
|
@@ -2124,7 +2183,7 @@ _seclai() {
|
|
|
2124
2183
|
local -a sub=(list get status comment subscribe unsubscribe configs prefs)
|
|
2125
2184
|
_describe 'subcommand' sub ;;
|
|
2126
2185
|
models)
|
|
2127
|
-
local -a sub=(alerts recommendations)
|
|
2186
|
+
local -a sub=(alerts recommendations experiments)
|
|
2128
2187
|
_describe 'subcommand' sub ;;
|
|
2129
2188
|
ai)
|
|
2130
2189
|
local -a sub=(feedback kb source solution memory memory-history accept decline memory-accept)
|
|
@@ -2167,7 +2226,7 @@ complete -c seclai -n "not __fish_seen_subcommand_from $top" -f -a "mcp" -d "MCP
|
|
|
2167
2226
|
complete -c seclai -n "not __fish_seen_subcommand_from $top" -f -a "completion" -d "Shell completions"
|
|
2168
2227
|
|
|
2169
2228
|
# agents
|
|
2170
|
-
complete -c seclai -n "__fish_seen_subcommand_from agents; and not __fish_seen_subcommand_from list create get update delete run runs def export upload-input input-status ai" -f -a "list create get update delete run runs def export upload-input input-status ai"
|
|
2229
|
+
complete -c seclai -n "__fish_seen_subcommand_from agents; and not __fish_seen_subcommand_from list create get update delete run runs def export preview-import upload-input input-status attachment-references ai" -f -a "list create get update delete run runs def export preview-import upload-input input-status attachment-references ai"
|
|
2171
2230
|
|
|
2172
2231
|
# sources
|
|
2173
2232
|
complete -c seclai -n "__fish_seen_subcommand_from sources; and not __fish_seen_subcommand_from list create get update delete upload upload-text exports migration" -f -a "list create get update delete upload upload-text exports migration"
|
|
@@ -2194,7 +2253,7 @@ complete -c seclai -n "__fish_seen_subcommand_from governance; and not __fish_se
|
|
|
2194
2253
|
complete -c seclai -n "__fish_seen_subcommand_from alerts; and not __fish_seen_subcommand_from list get status comment subscribe unsubscribe configs prefs" -f -a "list get status comment subscribe unsubscribe configs prefs"
|
|
2195
2254
|
|
|
2196
2255
|
# models
|
|
2197
|
-
complete -c seclai -n "__fish_seen_subcommand_from models; and not __fish_seen_subcommand_from alerts recommendations" -f -a "alerts recommendations"
|
|
2256
|
+
complete -c seclai -n "__fish_seen_subcommand_from models; and not __fish_seen_subcommand_from alerts recommendations experiments" -f -a "alerts recommendations experiments"
|
|
2198
2257
|
|
|
2199
2258
|
# ai
|
|
2200
2259
|
complete -c seclai -n "__fish_seen_subcommand_from ai; and not __fish_seen_subcommand_from feedback kb source solution memory memory-history accept decline memory-accept" -f -a "feedback kb source solution memory memory-history accept decline memory-accept"
|