@cdot65/prisma-airs-cli 6.0.0 → 6.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/dist/cli/index.js +160 -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, { promptWhenMissing: true });
|
|
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: run in a terminal to be prompted, or pass --key-file, --key-stdin (piped), --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,70 @@ function registerPlugins(root) {
|
|
|
5032
5093
|
)
|
|
5033
5094
|
);
|
|
5034
5095
|
}
|
|
5096
|
+
async function prepareIntegrationOptions(opts, client, settings = {}) {
|
|
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
|
+
const interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
5108
|
+
if (opts.keyStdin) {
|
|
5109
|
+
if (interactive) {
|
|
5110
|
+
prepared.key = await promptTenantValue("Provider API key:", true);
|
|
5111
|
+
} else {
|
|
5112
|
+
try {
|
|
5113
|
+
prepared.key = await readTenantStdin();
|
|
5114
|
+
} catch {
|
|
5115
|
+
throw new CliUsageError(
|
|
5116
|
+
"--key-stdin reads one credential from piped stdin, e.g. `airs aigateway integrations create ... --key-stdin < provider.key`; in a terminal, omit every key flag to be prompted"
|
|
5117
|
+
);
|
|
5118
|
+
}
|
|
5119
|
+
}
|
|
5120
|
+
} else if (opts.keyFile !== void 0) {
|
|
5121
|
+
let raw;
|
|
5122
|
+
try {
|
|
5123
|
+
raw = await readFile3(opts.keyFile, "utf8");
|
|
5124
|
+
} catch {
|
|
5125
|
+
throw new CliUsageError(`Cannot read --key-file ${opts.keyFile}`);
|
|
5126
|
+
}
|
|
5127
|
+
const value = raw.replace(/\r?\n$/, "");
|
|
5128
|
+
if (!value.trim() || /[\r\n\0]/.test(value)) {
|
|
5129
|
+
throw new CliUsageError("--key-file must contain exactly one nonempty credential");
|
|
5130
|
+
}
|
|
5131
|
+
prepared.key = value;
|
|
5132
|
+
} else if (opts.key !== void 0) {
|
|
5133
|
+
ui.warning(
|
|
5134
|
+
"Inline --key is visible in shell history and process listings; prefer --key-stdin, --key-file, or --secret-mappings"
|
|
5135
|
+
);
|
|
5136
|
+
} else if (settings.promptWhenMissing && interactive && opts.secretMappings === void 0 && opts.file === void 0) {
|
|
5137
|
+
prepared.key = await promptTenantValue("Provider API key:", true);
|
|
5138
|
+
}
|
|
5139
|
+
if (opts.aiProvider !== void 0 && opts.aiProviderId !== void 0) {
|
|
5140
|
+
throw new CliUsageError("Use --ai-provider or --ai-provider-id, not both");
|
|
5141
|
+
}
|
|
5142
|
+
if (opts.aiProvider !== void 0) {
|
|
5143
|
+
prepared.aiProviderId = await client.integrations.resolveProviderId(opts.aiProvider);
|
|
5144
|
+
}
|
|
5145
|
+
if (opts.baseUrl !== void 0) {
|
|
5146
|
+
let configuration;
|
|
5147
|
+
try {
|
|
5148
|
+
configuration = customHostConfiguration({ host: opts.baseUrl });
|
|
5149
|
+
} catch (error) {
|
|
5150
|
+
throw new CliUsageError(
|
|
5151
|
+
`Invalid --base-url: ${error instanceof Error ? error.message : String(error)}`
|
|
5152
|
+
);
|
|
5153
|
+
}
|
|
5154
|
+
prepared.providerAuthType = configuration.provider_auth_type;
|
|
5155
|
+
prepared.customHost = configuration.custom_host;
|
|
5156
|
+
}
|
|
5157
|
+
if (opts.header?.length) prepared.customHeaders = opts.header;
|
|
5158
|
+
return prepared;
|
|
5159
|
+
}
|
|
5035
5160
|
function registerAiGatewayInventory(root) {
|
|
5036
5161
|
registerApiKeys(root);
|
|
5037
5162
|
registerAuditLogs(root);
|
|
@@ -5875,7 +6000,7 @@ function registerCompletionCommand(program) {
|
|
|
5875
6000
|
|
|
5876
6001
|
// src/cli/commands/doctor.ts
|
|
5877
6002
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5878
|
-
import { readFile as
|
|
6003
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
5879
6004
|
import { init, Scanner } from "@cdot65/prisma-airs-sdk";
|
|
5880
6005
|
|
|
5881
6006
|
// src/config/env.ts
|
|
@@ -5979,7 +6104,7 @@ async function checkConfigFile(context3) {
|
|
|
5979
6104
|
const { path: path3 } = context3;
|
|
5980
6105
|
let raw;
|
|
5981
6106
|
try {
|
|
5982
|
-
raw = await
|
|
6107
|
+
raw = await readFile4(path3, "utf-8");
|
|
5983
6108
|
} catch {
|
|
5984
6109
|
return {
|
|
5985
6110
|
name,
|
|
@@ -8316,7 +8441,7 @@ function registerRedteamCommand(program) {
|
|
|
8316
8441
|
// src/cli/commands/runtime.ts
|
|
8317
8442
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
8318
8443
|
import * as fs5 from "fs";
|
|
8319
|
-
import { readFile as
|
|
8444
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
8320
8445
|
import { basename as basename3, dirname as dirname2, join as join3, resolve as resolvePath } from "path";
|
|
8321
8446
|
import chalk11 from "chalk";
|
|
8322
8447
|
|
|
@@ -8995,7 +9120,7 @@ var topicsView = {
|
|
|
8995
9120
|
};
|
|
8996
9121
|
|
|
8997
9122
|
// src/cli/commands/dlp/dictionaries.ts
|
|
8998
|
-
import { readFile as
|
|
9123
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
8999
9124
|
import { basename as basename2 } from "path";
|
|
9000
9125
|
import { AISecSDKException as AISecSDKException2, ErrorType as ErrorType3 } from "@cdot65/prisma-airs-sdk";
|
|
9001
9126
|
|
|
@@ -9040,7 +9165,7 @@ async function loadDlpClientOptions() {
|
|
|
9040
9165
|
}
|
|
9041
9166
|
|
|
9042
9167
|
// src/cli/commands/dlp/patch.ts
|
|
9043
|
-
import { readFile as
|
|
9168
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
9044
9169
|
function buildMergePatch(opts) {
|
|
9045
9170
|
const out = {};
|
|
9046
9171
|
for (const entry of opts.set ?? []) {
|
|
@@ -9082,7 +9207,7 @@ function coerceValue(raw) {
|
|
|
9082
9207
|
async function parseBody(opts) {
|
|
9083
9208
|
let raw;
|
|
9084
9209
|
if (opts.bodyFile) {
|
|
9085
|
-
raw = await
|
|
9210
|
+
raw = await readFile7(opts.bodyFile, "utf-8");
|
|
9086
9211
|
} else if (opts.body === "-") {
|
|
9087
9212
|
const chunks = [];
|
|
9088
9213
|
for await (const chunk of opts.stdin ?? process.stdin) {
|
|
@@ -9113,7 +9238,7 @@ function visibleRecords(records, includePredefined) {
|
|
|
9113
9238
|
|
|
9114
9239
|
// src/cli/commands/dlp/dictionaries.ts
|
|
9115
9240
|
async function readMetadata(path3) {
|
|
9116
|
-
const raw = await
|
|
9241
|
+
const raw = await readFile8(path3, "utf-8");
|
|
9117
9242
|
let value;
|
|
9118
9243
|
try {
|
|
9119
9244
|
value = JSON.parse(raw);
|
|
@@ -9190,7 +9315,7 @@ function register(dlp) {
|
|
|
9190
9315
|
const format = await resolveOutput(command, opts);
|
|
9191
9316
|
const metadata = await buildMetadata(opts);
|
|
9192
9317
|
if (!opts.file) throw new CliUsageError("--file is required (multipart upload)");
|
|
9193
|
-
const file = await
|
|
9318
|
+
const file = await readFile8(opts.file);
|
|
9194
9319
|
const r = await new SdkDictionariesService(await loadDlpClientOptions()).create({
|
|
9195
9320
|
metadata,
|
|
9196
9321
|
file,
|
|
@@ -9221,7 +9346,7 @@ function register(dlp) {
|
|
|
9221
9346
|
const metadata = await buildMetadata(opts);
|
|
9222
9347
|
const format = await resolveOutput(command, opts);
|
|
9223
9348
|
if (!opts.file) throw new CliUsageError("--file is required (multipart upload)");
|
|
9224
|
-
const file = await
|
|
9349
|
+
const file = await readFile8(opts.file);
|
|
9225
9350
|
const r = await new SdkDictionariesService(await loadDlpClientOptions()).replace(id, {
|
|
9226
9351
|
metadata,
|
|
9227
9352
|
file,
|
|
@@ -9949,7 +10074,7 @@ function register5(dlp) {
|
|
|
9949
10074
|
|
|
9950
10075
|
// src/cli/commands/dlp/transfer.ts
|
|
9951
10076
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
9952
|
-
import { readFile as
|
|
10077
|
+
import { readFile as readFile9, stat } from "fs/promises";
|
|
9953
10078
|
import { extname, resolve as resolve5 } from "path";
|
|
9954
10079
|
import { AISecSDKException as AISecSDKException4, ManagementClient } from "@cdot65/prisma-airs-sdk";
|
|
9955
10080
|
import { dump as dump6, JSON_SCHEMA, load as load2 } from "js-yaml";
|
|
@@ -11256,7 +11381,7 @@ function register6(dlp) {
|
|
|
11256
11381
|
throw new CliUsageError("Backup must be a regular file no larger than 20 MiB");
|
|
11257
11382
|
let input2;
|
|
11258
11383
|
try {
|
|
11259
|
-
const text2 = await
|
|
11384
|
+
const text2 = await readFile9(path3, "utf8");
|
|
11260
11385
|
if (Buffer.byteLength(text2) > MAX_BACKUP_BYTES) throw new Error("Backup too large");
|
|
11261
11386
|
input2 = extension === ".json" ? JSON.parse(text2) : load2(text2, { schema: JSON_SCHEMA });
|
|
11262
11387
|
} catch {
|
|
@@ -11348,7 +11473,7 @@ function registerDlpCommands(runtime) {
|
|
|
11348
11473
|
|
|
11349
11474
|
// src/cli/commands/profile-transfer.ts
|
|
11350
11475
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
11351
|
-
import { readFile as
|
|
11476
|
+
import { readFile as readFile10, stat as stat2 } from "fs/promises";
|
|
11352
11477
|
import { extname as extname2, resolve as resolve6 } from "path";
|
|
11353
11478
|
import { AISecSDKException as AISecSDKException5, ManagementClient as ManagementClient2 } from "@cdot65/prisma-airs-sdk";
|
|
11354
11479
|
import { dump as dump7, JSON_SCHEMA as JSON_SCHEMA2, load as load3 } from "js-yaml";
|
|
@@ -12193,7 +12318,7 @@ function registerProfileTransferCommands(profiles2) {
|
|
|
12193
12318
|
throw new CliUsageError("Backup must be a regular file no larger than 20 MiB");
|
|
12194
12319
|
let input2;
|
|
12195
12320
|
try {
|
|
12196
|
-
const text2 = await
|
|
12321
|
+
const text2 = await readFile10(path3, "utf8");
|
|
12197
12322
|
if (Buffer.byteLength(text2) > MAX_BACKUP_BYTES2) throw new Error("Backup too large");
|
|
12198
12323
|
input2 = extension === ".json" ? JSON.parse(text2) : load3(text2, { schema: JSON_SCHEMA2 });
|
|
12199
12324
|
} catch {
|
|
@@ -12837,7 +12962,7 @@ function registerCreateCommand(parent) {
|
|
|
12837
12962
|
}
|
|
12838
12963
|
|
|
12839
12964
|
// src/cli/commands/topics-eval.ts
|
|
12840
|
-
import { readFile as
|
|
12965
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
12841
12966
|
|
|
12842
12967
|
// src/core/prompt-loader.ts
|
|
12843
12968
|
function parseCsvLine(line) {
|
|
@@ -12980,7 +13105,7 @@ function registerEvalCommand(parent) {
|
|
|
12980
13105
|
resolveDeprecatedAliases(cmd, opts);
|
|
12981
13106
|
try {
|
|
12982
13107
|
const config = await loadConfig();
|
|
12983
|
-
const csvContent = await
|
|
13108
|
+
const csvContent = await readFile11(opts.prompts, "utf-8");
|
|
12984
13109
|
const { cases, intent } = loadPrompts(csvContent, (msg) => ui.status(`Warning: ${msg}`));
|
|
12985
13110
|
assertScannerCredentials(config);
|
|
12986
13111
|
let scanner = new AirsScanService(runtimeInitOptions(config));
|
|
@@ -13275,7 +13400,7 @@ function registerRuntimeCommand(program) {
|
|
|
13275
13400
|
try {
|
|
13276
13401
|
const config = await loadConfig({});
|
|
13277
13402
|
assertScannerCredentials(config);
|
|
13278
|
-
const raw = await
|
|
13403
|
+
const raw = await readFile12(opts.file, "utf-8");
|
|
13279
13404
|
const prompts = parseInputFile(raw, opts.file);
|
|
13280
13405
|
if (prompts.length === 0) {
|
|
13281
13406
|
usageError("No prompts found in input file");
|
|
@@ -14045,38 +14170,6 @@ async function rewriteTenantConfig(entry, change) {
|
|
|
14045
14170
|
}
|
|
14046
14171
|
}
|
|
14047
14172
|
|
|
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
14173
|
// src/cli/commands/tenant.ts
|
|
14081
14174
|
function tenantInputFailure(error) {
|
|
14082
14175
|
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.1",
|
|
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",
|