@cdot65/prisma-airs-cli 6.0.0 → 6.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/dist/cli/index.js +151 -67
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -3713,6 +3713,7 @@ function registerAiGatewayInference(parent) {
|
|
|
3713
3713
|
}
|
|
3714
3714
|
|
|
3715
3715
|
// src/cli/commands/aigateway/inventory.ts
|
|
3716
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
3716
3717
|
import {
|
|
3717
3718
|
AI_GATEWAY_DEPLOYMENT_STATUSES,
|
|
3718
3719
|
AI_GATEWAY_DEPLOYMENT_TYPES,
|
|
@@ -3720,6 +3721,7 @@ import {
|
|
|
3720
3721
|
AI_GATEWAY_KNOWN_MCP_AUTH_TYPES,
|
|
3721
3722
|
AI_GATEWAY_KNOWN_MCP_TRANSPORTS,
|
|
3722
3723
|
AI_GATEWAY_MUTABLE_MCP_CAPABILITY_TYPES,
|
|
3724
|
+
customHostConfiguration,
|
|
3723
3725
|
GatewayApiKeyRotateRequestSchema,
|
|
3724
3726
|
GatewayApiKeyUpdateRequestSchema,
|
|
3725
3727
|
GatewayConfigCreateRequestSchema,
|
|
@@ -3915,6 +3917,38 @@ function installDebugLogger(logPath, options = {}) {
|
|
|
3915
3917
|
};
|
|
3916
3918
|
}
|
|
3917
3919
|
|
|
3920
|
+
// src/cli/tenant-input.ts
|
|
3921
|
+
import { input, password } from "@inquirer/prompts";
|
|
3922
|
+
async function promptTenantValue(message, secret = false) {
|
|
3923
|
+
if (!process.stdin.isTTY || !process.stderr.isTTY)
|
|
3924
|
+
throw new Error(
|
|
3925
|
+
"Interactive setup requires a terminal. Use --config, or --tsg-id and --client-id with --client-secret-stdin. For tenant set, pass a value or use --stdin."
|
|
3926
|
+
);
|
|
3927
|
+
const prompt = secret ? password : input;
|
|
3928
|
+
return prompt(
|
|
3929
|
+
{
|
|
3930
|
+
message,
|
|
3931
|
+
validate: (value) => Boolean(value.trim()) || "A nonempty value is required"
|
|
3932
|
+
},
|
|
3933
|
+
{ input: process.stdin, output: process.stderr }
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
async function readTenantStdin() {
|
|
3937
|
+
if (process.stdin.isTTY) throw new Error("--stdin requires piped input");
|
|
3938
|
+
const chunks = [];
|
|
3939
|
+
let size = 0;
|
|
3940
|
+
for await (const chunk of process.stdin) {
|
|
3941
|
+
const buffer = Buffer.from(chunk);
|
|
3942
|
+
size += buffer.length;
|
|
3943
|
+
if (size > 65536) throw new Error("Configuration input exceeds 64 KiB");
|
|
3944
|
+
chunks.push(buffer);
|
|
3945
|
+
}
|
|
3946
|
+
const value = Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
|
|
3947
|
+
if (!value.trim() || /[\r\n\0]/.test(value))
|
|
3948
|
+
throw new Error("Provide one nonempty configuration value on stdin");
|
|
3949
|
+
return value;
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3918
3952
|
// src/cli/commands/aigateway/shared.ts
|
|
3919
3953
|
import { open, readFile as readFile2, unlink } from "fs/promises";
|
|
3920
3954
|
import { AIGatewayClient as AIGatewayClient2 } from "@cdot65/prisma-airs-sdk";
|
|
@@ -4663,13 +4697,33 @@ function registerIntegrations(root) {
|
|
|
4663
4697
|
{ option: "name", path: "name" },
|
|
4664
4698
|
{ option: "organisationId", path: "organisation_id" },
|
|
4665
4699
|
{ option: "secretMappings", path: "secret_mappings", parse: parseJsonOption },
|
|
4666
|
-
{ option: "slug", path: "slug" }
|
|
4700
|
+
{ option: "slug", path: "slug" },
|
|
4701
|
+
// Derived by prepareIntegrationOptions() from --base-url / --header.
|
|
4702
|
+
{ option: "providerAuthType", path: "configurations.provider_auth_type" },
|
|
4703
|
+
{ option: "customHost", path: "configurations.custom_host" },
|
|
4704
|
+
{ option: "customHeaders", path: "configurations.custom_headers", parse: parseStringMapOption }
|
|
4667
4705
|
];
|
|
4668
|
-
const
|
|
4706
|
+
const addIntegrationSharedFields = (command) => command.option(
|
|
4707
|
+
"--base-url <url>",
|
|
4708
|
+
"Self-hosted or OpenAI-compatible endpoint (configurations.custom_host)"
|
|
4709
|
+
).option("--configurations <json>", "Provider configuration object").option("--description <text>", "Integration description").option(
|
|
4710
|
+
"--header <name=value>",
|
|
4711
|
+
"Extra header sent to the custom host (repeatable)",
|
|
4712
|
+
collectOption
|
|
4713
|
+
).option("--key <credential>", "Inline provider credential (visible in shell history)").option("--key-file <path>", "Read the provider credential from a file").option("--key-stdin", "Read the provider credential from piped stdin").option("--name <name>", "Integration name").option("--secret-mappings <json>", "Secret reference mapping array");
|
|
4714
|
+
const addIntegrationFields = (command) => addIntegrationSharedFields(command).option(
|
|
4715
|
+
"--ai-provider <slug-or-uuid>",
|
|
4716
|
+
"Provider catalog slug (see 'integrations providers') or UUID"
|
|
4717
|
+
).option("--ai-provider-id <uuid>", "Provider catalog UUID").option("--organisation-id <tsg>", "Numeric TSG id").option("--slug <slug>", "Stable integration slug");
|
|
4669
4718
|
const integrationUpdateFields = integrationFields.filter(
|
|
4670
|
-
(field) => ["
|
|
4719
|
+
(field) => !["aiProviderId", "organisationId", "slug"].includes(field.option)
|
|
4720
|
+
);
|
|
4721
|
+
const providers = addReadOutput(
|
|
4722
|
+
group.command("providers").description("List the provider catalog: the slug or UUID that --ai-provider accepts")
|
|
4723
|
+
);
|
|
4724
|
+
providers.action(
|
|
4725
|
+
(opts) => runList(providers, opts, "catalog providers", (client) => client.integrations.catalog())
|
|
4671
4726
|
);
|
|
4672
|
-
const addIntegrationUpdateFields = (command) => command.option("--configurations <json>", "Provider configuration object").option("--description <text>", "Integration description").option("--key <credential>", "Inline provider credential (prefer secret mappings)").option("--name <name>", "Integration name").option("--secret-mappings <json>", "Secret reference mapping array");
|
|
4673
4727
|
const create = addWriteOutput(
|
|
4674
4728
|
addStructuredInputOptions(
|
|
4675
4729
|
addIntegrationFields(
|
|
@@ -4678,31 +4732,38 @@ function registerIntegrations(root) {
|
|
|
4678
4732
|
)
|
|
4679
4733
|
);
|
|
4680
4734
|
create.action(
|
|
4681
|
-
(opts) => runWrite(
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4735
|
+
(opts) => runWrite(create, opts, async (client) => {
|
|
4736
|
+
const prepared = await prepareIntegrationOptions(opts, client);
|
|
4737
|
+
const body = await buildStructuredRequest(
|
|
4738
|
+
prepared,
|
|
4739
|
+
GatewayIntegrationCreateRequestSchema,
|
|
4740
|
+
integrationFields
|
|
4741
|
+
);
|
|
4742
|
+
if (!body.key && !(Array.isArray(body.secret_mappings) && body.secret_mappings.length)) {
|
|
4743
|
+
throw new CliUsageError(
|
|
4744
|
+
"A provider credential is required: pass --key-stdin, --key-file, --secret-mappings, or --key (the gateway rejects a credential-less integration with a generic AB01)"
|
|
4745
|
+
);
|
|
4746
|
+
}
|
|
4747
|
+
return client.integrations.create(body);
|
|
4748
|
+
})
|
|
4687
4749
|
);
|
|
4688
4750
|
const update = addWriteOutput(
|
|
4689
4751
|
addStructuredInputOptions(
|
|
4690
|
-
|
|
4752
|
+
addIntegrationSharedFields(
|
|
4691
4753
|
group.command("update <id>").description("Update an integration with structured flags")
|
|
4692
4754
|
)
|
|
4693
4755
|
)
|
|
4694
4756
|
);
|
|
4695
4757
|
update.action(
|
|
4696
|
-
(id, opts) => runWrite(
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
opts,
|
|
4758
|
+
(id, opts) => runWrite(update, opts, async (client) => {
|
|
4759
|
+
const prepared = await prepareIntegrationOptions(opts, client);
|
|
4760
|
+
const body = await buildStructuredRequest(
|
|
4761
|
+
prepared,
|
|
4701
4762
|
GatewayIntegrationUpdateRequestSchema,
|
|
4702
4763
|
integrationUpdateFields
|
|
4703
|
-
)
|
|
4704
|
-
|
|
4705
|
-
)
|
|
4764
|
+
);
|
|
4765
|
+
return client.integrations.update(id, body);
|
|
4766
|
+
})
|
|
4706
4767
|
);
|
|
4707
4768
|
const remove = addWriteOutput(
|
|
4708
4769
|
group.command("delete <id>").description("Permanently delete this integration").requiredOption("--organisation-id <tsg>", "Numeric TSG id").option("--force", "Skip confirmation prompt")
|
|
@@ -5032,6 +5093,61 @@ function registerPlugins(root) {
|
|
|
5032
5093
|
)
|
|
5033
5094
|
);
|
|
5034
5095
|
}
|
|
5096
|
+
async function prepareIntegrationOptions(opts, client) {
|
|
5097
|
+
const sources = [opts.key !== void 0, Boolean(opts.keyStdin), opts.keyFile !== void 0];
|
|
5098
|
+
if (sources.filter(Boolean).length > 1) {
|
|
5099
|
+
throw new CliUsageError("Use only one of --key, --key-stdin, or --key-file");
|
|
5100
|
+
}
|
|
5101
|
+
const prepared = { ...opts };
|
|
5102
|
+
delete prepared.keyStdin;
|
|
5103
|
+
delete prepared.keyFile;
|
|
5104
|
+
delete prepared.baseUrl;
|
|
5105
|
+
delete prepared.header;
|
|
5106
|
+
delete prepared.aiProvider;
|
|
5107
|
+
if (opts.keyStdin) {
|
|
5108
|
+
try {
|
|
5109
|
+
prepared.key = await readTenantStdin();
|
|
5110
|
+
} catch {
|
|
5111
|
+
throw new CliUsageError("--key-stdin requires one nonempty credential on piped stdin");
|
|
5112
|
+
}
|
|
5113
|
+
} else if (opts.keyFile !== void 0) {
|
|
5114
|
+
let raw;
|
|
5115
|
+
try {
|
|
5116
|
+
raw = await readFile3(opts.keyFile, "utf8");
|
|
5117
|
+
} catch {
|
|
5118
|
+
throw new CliUsageError(`Cannot read --key-file ${opts.keyFile}`);
|
|
5119
|
+
}
|
|
5120
|
+
const value = raw.replace(/\r?\n$/, "");
|
|
5121
|
+
if (!value.trim() || /[\r\n\0]/.test(value)) {
|
|
5122
|
+
throw new CliUsageError("--key-file must contain exactly one nonempty credential");
|
|
5123
|
+
}
|
|
5124
|
+
prepared.key = value;
|
|
5125
|
+
} else if (opts.key !== void 0) {
|
|
5126
|
+
ui.warning(
|
|
5127
|
+
"Inline --key is visible in shell history and process listings; prefer --key-stdin, --key-file, or --secret-mappings"
|
|
5128
|
+
);
|
|
5129
|
+
}
|
|
5130
|
+
if (opts.aiProvider !== void 0 && opts.aiProviderId !== void 0) {
|
|
5131
|
+
throw new CliUsageError("Use --ai-provider or --ai-provider-id, not both");
|
|
5132
|
+
}
|
|
5133
|
+
if (opts.aiProvider !== void 0) {
|
|
5134
|
+
prepared.aiProviderId = await client.integrations.resolveProviderId(opts.aiProvider);
|
|
5135
|
+
}
|
|
5136
|
+
if (opts.baseUrl !== void 0) {
|
|
5137
|
+
let configuration;
|
|
5138
|
+
try {
|
|
5139
|
+
configuration = customHostConfiguration({ host: opts.baseUrl });
|
|
5140
|
+
} catch (error) {
|
|
5141
|
+
throw new CliUsageError(
|
|
5142
|
+
`Invalid --base-url: ${error instanceof Error ? error.message : String(error)}`
|
|
5143
|
+
);
|
|
5144
|
+
}
|
|
5145
|
+
prepared.providerAuthType = configuration.provider_auth_type;
|
|
5146
|
+
prepared.customHost = configuration.custom_host;
|
|
5147
|
+
}
|
|
5148
|
+
if (opts.header?.length) prepared.customHeaders = opts.header;
|
|
5149
|
+
return prepared;
|
|
5150
|
+
}
|
|
5035
5151
|
function registerAiGatewayInventory(root) {
|
|
5036
5152
|
registerApiKeys(root);
|
|
5037
5153
|
registerAuditLogs(root);
|
|
@@ -5875,7 +5991,7 @@ function registerCompletionCommand(program) {
|
|
|
5875
5991
|
|
|
5876
5992
|
// src/cli/commands/doctor.ts
|
|
5877
5993
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5878
|
-
import { readFile as
|
|
5994
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
5879
5995
|
import { init, Scanner } from "@cdot65/prisma-airs-sdk";
|
|
5880
5996
|
|
|
5881
5997
|
// src/config/env.ts
|
|
@@ -5979,7 +6095,7 @@ async function checkConfigFile(context3) {
|
|
|
5979
6095
|
const { path: path3 } = context3;
|
|
5980
6096
|
let raw;
|
|
5981
6097
|
try {
|
|
5982
|
-
raw = await
|
|
6098
|
+
raw = await readFile4(path3, "utf-8");
|
|
5983
6099
|
} catch {
|
|
5984
6100
|
return {
|
|
5985
6101
|
name,
|
|
@@ -8316,7 +8432,7 @@ function registerRedteamCommand(program) {
|
|
|
8316
8432
|
// src/cli/commands/runtime.ts
|
|
8317
8433
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
8318
8434
|
import * as fs5 from "fs";
|
|
8319
|
-
import { readFile as
|
|
8435
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
8320
8436
|
import { basename as basename3, dirname as dirname2, join as join3, resolve as resolvePath } from "path";
|
|
8321
8437
|
import chalk11 from "chalk";
|
|
8322
8438
|
|
|
@@ -8995,7 +9111,7 @@ var topicsView = {
|
|
|
8995
9111
|
};
|
|
8996
9112
|
|
|
8997
9113
|
// src/cli/commands/dlp/dictionaries.ts
|
|
8998
|
-
import { readFile as
|
|
9114
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
8999
9115
|
import { basename as basename2 } from "path";
|
|
9000
9116
|
import { AISecSDKException as AISecSDKException2, ErrorType as ErrorType3 } from "@cdot65/prisma-airs-sdk";
|
|
9001
9117
|
|
|
@@ -9040,7 +9156,7 @@ async function loadDlpClientOptions() {
|
|
|
9040
9156
|
}
|
|
9041
9157
|
|
|
9042
9158
|
// src/cli/commands/dlp/patch.ts
|
|
9043
|
-
import { readFile as
|
|
9159
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
9044
9160
|
function buildMergePatch(opts) {
|
|
9045
9161
|
const out = {};
|
|
9046
9162
|
for (const entry of opts.set ?? []) {
|
|
@@ -9082,7 +9198,7 @@ function coerceValue(raw) {
|
|
|
9082
9198
|
async function parseBody(opts) {
|
|
9083
9199
|
let raw;
|
|
9084
9200
|
if (opts.bodyFile) {
|
|
9085
|
-
raw = await
|
|
9201
|
+
raw = await readFile7(opts.bodyFile, "utf-8");
|
|
9086
9202
|
} else if (opts.body === "-") {
|
|
9087
9203
|
const chunks = [];
|
|
9088
9204
|
for await (const chunk of opts.stdin ?? process.stdin) {
|
|
@@ -9113,7 +9229,7 @@ function visibleRecords(records, includePredefined) {
|
|
|
9113
9229
|
|
|
9114
9230
|
// src/cli/commands/dlp/dictionaries.ts
|
|
9115
9231
|
async function readMetadata(path3) {
|
|
9116
|
-
const raw = await
|
|
9232
|
+
const raw = await readFile8(path3, "utf-8");
|
|
9117
9233
|
let value;
|
|
9118
9234
|
try {
|
|
9119
9235
|
value = JSON.parse(raw);
|
|
@@ -9190,7 +9306,7 @@ function register(dlp) {
|
|
|
9190
9306
|
const format = await resolveOutput(command, opts);
|
|
9191
9307
|
const metadata = await buildMetadata(opts);
|
|
9192
9308
|
if (!opts.file) throw new CliUsageError("--file is required (multipart upload)");
|
|
9193
|
-
const file = await
|
|
9309
|
+
const file = await readFile8(opts.file);
|
|
9194
9310
|
const r = await new SdkDictionariesService(await loadDlpClientOptions()).create({
|
|
9195
9311
|
metadata,
|
|
9196
9312
|
file,
|
|
@@ -9221,7 +9337,7 @@ function register(dlp) {
|
|
|
9221
9337
|
const metadata = await buildMetadata(opts);
|
|
9222
9338
|
const format = await resolveOutput(command, opts);
|
|
9223
9339
|
if (!opts.file) throw new CliUsageError("--file is required (multipart upload)");
|
|
9224
|
-
const file = await
|
|
9340
|
+
const file = await readFile8(opts.file);
|
|
9225
9341
|
const r = await new SdkDictionariesService(await loadDlpClientOptions()).replace(id, {
|
|
9226
9342
|
metadata,
|
|
9227
9343
|
file,
|
|
@@ -9949,7 +10065,7 @@ function register5(dlp) {
|
|
|
9949
10065
|
|
|
9950
10066
|
// src/cli/commands/dlp/transfer.ts
|
|
9951
10067
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
9952
|
-
import { readFile as
|
|
10068
|
+
import { readFile as readFile9, stat } from "fs/promises";
|
|
9953
10069
|
import { extname, resolve as resolve5 } from "path";
|
|
9954
10070
|
import { AISecSDKException as AISecSDKException4, ManagementClient } from "@cdot65/prisma-airs-sdk";
|
|
9955
10071
|
import { dump as dump6, JSON_SCHEMA, load as load2 } from "js-yaml";
|
|
@@ -11256,7 +11372,7 @@ function register6(dlp) {
|
|
|
11256
11372
|
throw new CliUsageError("Backup must be a regular file no larger than 20 MiB");
|
|
11257
11373
|
let input2;
|
|
11258
11374
|
try {
|
|
11259
|
-
const text2 = await
|
|
11375
|
+
const text2 = await readFile9(path3, "utf8");
|
|
11260
11376
|
if (Buffer.byteLength(text2) > MAX_BACKUP_BYTES) throw new Error("Backup too large");
|
|
11261
11377
|
input2 = extension === ".json" ? JSON.parse(text2) : load2(text2, { schema: JSON_SCHEMA });
|
|
11262
11378
|
} catch {
|
|
@@ -11348,7 +11464,7 @@ function registerDlpCommands(runtime) {
|
|
|
11348
11464
|
|
|
11349
11465
|
// src/cli/commands/profile-transfer.ts
|
|
11350
11466
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
11351
|
-
import { readFile as
|
|
11467
|
+
import { readFile as readFile10, stat as stat2 } from "fs/promises";
|
|
11352
11468
|
import { extname as extname2, resolve as resolve6 } from "path";
|
|
11353
11469
|
import { AISecSDKException as AISecSDKException5, ManagementClient as ManagementClient2 } from "@cdot65/prisma-airs-sdk";
|
|
11354
11470
|
import { dump as dump7, JSON_SCHEMA as JSON_SCHEMA2, load as load3 } from "js-yaml";
|
|
@@ -12193,7 +12309,7 @@ function registerProfileTransferCommands(profiles2) {
|
|
|
12193
12309
|
throw new CliUsageError("Backup must be a regular file no larger than 20 MiB");
|
|
12194
12310
|
let input2;
|
|
12195
12311
|
try {
|
|
12196
|
-
const text2 = await
|
|
12312
|
+
const text2 = await readFile10(path3, "utf8");
|
|
12197
12313
|
if (Buffer.byteLength(text2) > MAX_BACKUP_BYTES2) throw new Error("Backup too large");
|
|
12198
12314
|
input2 = extension === ".json" ? JSON.parse(text2) : load3(text2, { schema: JSON_SCHEMA2 });
|
|
12199
12315
|
} catch {
|
|
@@ -12837,7 +12953,7 @@ function registerCreateCommand(parent) {
|
|
|
12837
12953
|
}
|
|
12838
12954
|
|
|
12839
12955
|
// src/cli/commands/topics-eval.ts
|
|
12840
|
-
import { readFile as
|
|
12956
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
12841
12957
|
|
|
12842
12958
|
// src/core/prompt-loader.ts
|
|
12843
12959
|
function parseCsvLine(line) {
|
|
@@ -12980,7 +13096,7 @@ function registerEvalCommand(parent) {
|
|
|
12980
13096
|
resolveDeprecatedAliases(cmd, opts);
|
|
12981
13097
|
try {
|
|
12982
13098
|
const config = await loadConfig();
|
|
12983
|
-
const csvContent = await
|
|
13099
|
+
const csvContent = await readFile11(opts.prompts, "utf-8");
|
|
12984
13100
|
const { cases, intent } = loadPrompts(csvContent, (msg) => ui.status(`Warning: ${msg}`));
|
|
12985
13101
|
assertScannerCredentials(config);
|
|
12986
13102
|
let scanner = new AirsScanService(runtimeInitOptions(config));
|
|
@@ -13275,7 +13391,7 @@ function registerRuntimeCommand(program) {
|
|
|
13275
13391
|
try {
|
|
13276
13392
|
const config = await loadConfig({});
|
|
13277
13393
|
assertScannerCredentials(config);
|
|
13278
|
-
const raw = await
|
|
13394
|
+
const raw = await readFile12(opts.file, "utf-8");
|
|
13279
13395
|
const prompts = parseInputFile(raw, opts.file);
|
|
13280
13396
|
if (prompts.length === 0) {
|
|
13281
13397
|
usageError("No prompts found in input file");
|
|
@@ -14045,38 +14161,6 @@ async function rewriteTenantConfig(entry, change) {
|
|
|
14045
14161
|
}
|
|
14046
14162
|
}
|
|
14047
14163
|
|
|
14048
|
-
// src/cli/tenant-input.ts
|
|
14049
|
-
import { input, password } from "@inquirer/prompts";
|
|
14050
|
-
async function promptTenantValue(message, secret = false) {
|
|
14051
|
-
if (!process.stdin.isTTY || !process.stderr.isTTY)
|
|
14052
|
-
throw new Error(
|
|
14053
|
-
"Interactive setup requires a terminal. Use --config, or --tsg-id and --client-id with --client-secret-stdin. For tenant set, pass a value or use --stdin."
|
|
14054
|
-
);
|
|
14055
|
-
const prompt = secret ? password : input;
|
|
14056
|
-
return prompt(
|
|
14057
|
-
{
|
|
14058
|
-
message,
|
|
14059
|
-
validate: (value) => Boolean(value.trim()) || "A nonempty value is required"
|
|
14060
|
-
},
|
|
14061
|
-
{ input: process.stdin, output: process.stderr }
|
|
14062
|
-
);
|
|
14063
|
-
}
|
|
14064
|
-
async function readTenantStdin() {
|
|
14065
|
-
if (process.stdin.isTTY) throw new Error("--stdin requires piped input");
|
|
14066
|
-
const chunks = [];
|
|
14067
|
-
let size = 0;
|
|
14068
|
-
for await (const chunk of process.stdin) {
|
|
14069
|
-
const buffer = Buffer.from(chunk);
|
|
14070
|
-
size += buffer.length;
|
|
14071
|
-
if (size > 65536) throw new Error("Configuration input exceeds 64 KiB");
|
|
14072
|
-
chunks.push(buffer);
|
|
14073
|
-
}
|
|
14074
|
-
const value = Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
|
|
14075
|
-
if (!value.trim() || /[\r\n\0]/.test(value))
|
|
14076
|
-
throw new Error("Provide one nonempty configuration value on stdin");
|
|
14077
|
-
return value;
|
|
14078
|
-
}
|
|
14079
|
-
|
|
14080
14164
|
// src/cli/commands/tenant.ts
|
|
14081
14165
|
function tenantInputFailure(error) {
|
|
14082
14166
|
if (error instanceof Error && error.name === "ExitPromptError") {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdot65/prisma-airs-cli",
|
|
3
3
|
"packageManager": "pnpm@10.6.5",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.1.0",
|
|
5
5
|
"description": "CLI and library for Palo Alto Prisma AIRS — guardrail refinement, AI red teaming, model security scanning, profile audits",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"license": "MIT",
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@cdot65/prisma-airs-sdk": "0.
|
|
62
|
+
"@cdot65/prisma-airs-sdk": "0.33.0",
|
|
63
63
|
"@inquirer/prompts": "^8.3.0",
|
|
64
64
|
"chalk": "^5.6.2",
|
|
65
65
|
"commander": "^14.0.3",
|