@runtypelabs/cli 2.59.0 → 2.59.2
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/chunk-0-T9NWjH.js +3899 -0
- package/dist/chunk-0x7UKC1U.js +17 -0
- package/dist/chunk-2ySxXtcg.js +418 -0
- package/dist/chunk-3An_BRHv.js +501 -0
- package/dist/chunk-6uTxgdiY.js +16218 -0
- package/dist/chunk-87nRnNRG.js +1363 -0
- package/dist/chunk-B3wo8uRx.js +322 -0
- package/dist/chunk-BGp3ZdBy.js +560 -0
- package/dist/chunk-BJQv9Elp.js +107 -0
- package/dist/chunk-BOpO6xE-.js +6053 -0
- package/dist/chunk-BQXXCL8B.js +102 -0
- package/dist/chunk-BV-8isOd.js +34 -0
- package/dist/chunk-BVMhjGVe.js +826 -0
- package/dist/chunk-BW2fg46T.js +141 -0
- package/dist/chunk-BWJdY5Ag.js +36 -0
- package/dist/chunk-BYJOrLhh.js +302 -0
- package/dist/chunk-BYab8EVL.js +127 -0
- package/dist/chunk-BfEKvp7h.js +82 -0
- package/dist/chunk-BhgLSfH6.js +1123 -0
- package/dist/chunk-BirUxTtH.js +296 -0
- package/dist/chunk-BmB6UVZ9.js +1559 -0
- package/dist/chunk-BnWhIqW1.js +109 -0
- package/dist/chunk-Bpfnfk0t.js +123 -0
- package/dist/chunk-BrhgdnM3.js +108 -0
- package/dist/chunk-Bt0XAgX5.js +327 -0
- package/dist/chunk-Bu0FJr6S.js +84 -0
- package/dist/chunk-BvEoKpN3.js +255 -0
- package/dist/chunk-BxNJgYbE.js +28 -0
- package/dist/chunk-C1OFhd7F.js +6131 -0
- package/dist/chunk-C7e7WwbU.js +331 -0
- package/dist/chunk-CDTYP6bN.js +558 -0
- package/dist/chunk-CGDQoqDC.js +24 -0
- package/dist/chunk-CJraEBVd.js +127 -0
- package/dist/chunk-CQrNhOtv.js +40 -0
- package/dist/chunk-CW6AzBH6.js +128 -0
- package/dist/chunk-CXgL4w-9.js +317 -0
- package/dist/chunk-CZrqoPyf.js +233 -0
- package/dist/chunk-CcFCyqbB.js +83 -0
- package/dist/chunk-CdaIvO-y.js +485 -0
- package/dist/chunk-CehSXtgK.js +624 -0
- package/dist/chunk-Ciqkop65.js +218 -0
- package/dist/chunk-CoAWdSiE.js +43 -0
- package/dist/chunk-Crb4y7t4.js +830 -0
- package/dist/chunk-CrlqIfmb.js +337 -0
- package/dist/chunk-Cs4pwCQ-.js +324 -0
- package/dist/chunk-CwM_9y01.js +519 -0
- package/dist/chunk-CyRbIJg8.js +440 -0
- package/dist/chunk-D0OHsyMy.js +212 -0
- package/dist/chunk-D3y2bURs.js +1347 -0
- package/dist/chunk-D4_mJk03.js +2338 -0
- package/dist/chunk-D6C8rned.js +578 -0
- package/dist/chunk-D9ZbUnks.js +11 -0
- package/dist/chunk-DEPmLshX.js +834 -0
- package/dist/chunk-DFj1UPB2.js +330 -0
- package/dist/chunk-DGdFdZVf.js +197 -0
- package/dist/chunk-DGv7X9S_.js +63 -0
- package/dist/chunk-DJQ47WYZ.js +664 -0
- package/dist/chunk-DJw3O61j.js +1974 -0
- package/dist/chunk-DK4FbWVK.js +100 -0
- package/dist/chunk-DSRYhUus.js +993 -0
- package/dist/chunk-DajZ9Eg4.js +299 -0
- package/dist/chunk-Df4dunvU.js +195 -0
- package/dist/chunk-DjNTPhfO.js +481 -0
- package/dist/chunk-Dn8eaJuu.js +1042 -0
- package/dist/chunk-DwDWqSxM.js +637 -0
- package/dist/chunk-Dz7cEtxl.js +84 -0
- package/dist/chunk-E_0bgjrS.js +359 -0
- package/dist/chunk-KPYN2vUp.js +776 -0
- package/dist/chunk-KcqPQJBi.js +86 -0
- package/dist/chunk-N9H0JnoG.js +349 -0
- package/dist/chunk-NONFcXkn.js +728 -0
- package/dist/chunk-PrFjcpmH.js +256 -0
- package/dist/chunk-QSfNYiw9.js +11 -0
- package/dist/chunk-R265bzj9.js +226 -0
- package/dist/chunk-X9V_r6jM.js +166 -0
- package/dist/chunk-ZBtPUtyA.js +55 -0
- package/dist/chunk-ZCTfmOs7.js +4939 -0
- package/dist/chunk-h6oavj0t.js +97 -0
- package/dist/chunk-i7DwkvvD.js +42 -0
- package/dist/chunk-mG-4eZ6S.js +203 -0
- package/dist/chunk-o0ygUbCf.js +313 -0
- package/dist/chunk-ucu5lrDZ.js +5715 -0
- package/dist/index.js +11367 -73764
- package/package.json +6 -6
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { a as getCliConfig, c as loadEffectiveContext, l as normalizeApiUrl, u as redactEffectiveContext } from "./index.js";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
// src/commands/config.ts
|
|
6
|
+
const CLI_CONFIG_KEYS = [
|
|
7
|
+
"apiUrl",
|
|
8
|
+
"defaultModel",
|
|
9
|
+
"defaultTemperature",
|
|
10
|
+
"outputFormat",
|
|
11
|
+
"streamResponses"
|
|
12
|
+
];
|
|
13
|
+
const isCliConfigKey = (value) => {
|
|
14
|
+
return CLI_CONFIG_KEYS.includes(value);
|
|
15
|
+
};
|
|
16
|
+
const configCommand = new Command("config").description("Manage CLI configuration");
|
|
17
|
+
configCommand.command("context").description("Show the effective API target and credential source without exposing keys (offline)").option("--json", "Output as JSON").action(async (options) => {
|
|
18
|
+
const context = redactEffectiveContext(await loadEffectiveContext());
|
|
19
|
+
if (options.json) {
|
|
20
|
+
console.log(JSON.stringify(context, null, 2));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
console.log(`API URL: ${context.apiUrl} (${context.apiUrlSource})`);
|
|
24
|
+
console.log(`Credential source: ${context.credentialSource}`);
|
|
25
|
+
console.log(`Organization: ${context.orgId ?? "unknown"} (not verified; use auth whoami)`);
|
|
26
|
+
console.log(`Login selected by: ${context.accountSource}${context.requestedOrgId ? ` (${context.requestedOrgId})` : ""}`);
|
|
27
|
+
if (context.projectLink) console.log(`Project link: ${context.projectLink}`);
|
|
28
|
+
if (context.credentialStore) console.log(`Credential stored in: ${context.credentialStore}`);
|
|
29
|
+
});
|
|
30
|
+
configCommand.command("get [key]").description("Get configuration value").action((key) => {
|
|
31
|
+
const config = getCliConfig();
|
|
32
|
+
if (key) {
|
|
33
|
+
if (!isCliConfigKey(key)) {
|
|
34
|
+
console.log(chalk.yellow(`Configuration key '${key}' not found`));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const value = config.get(key);
|
|
38
|
+
if (value !== void 0) console.log(value);
|
|
39
|
+
else console.log(chalk.yellow(`Configuration key '${key}' not found`));
|
|
40
|
+
} else {
|
|
41
|
+
const allConfig = config.store;
|
|
42
|
+
if (Object.keys(allConfig).length > 0) {
|
|
43
|
+
console.log(chalk.cyan("Current Configuration:"));
|
|
44
|
+
for (const [k, v] of Object.entries(allConfig)) console.log(` ${chalk.green(k)}: ${v}`);
|
|
45
|
+
} else console.log(chalk.gray("No configuration set"));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
configCommand.command("set <key> <value>").description("Set configuration value").action((key, value) => {
|
|
49
|
+
const config = getCliConfig();
|
|
50
|
+
if (!isCliConfigKey(key)) {
|
|
51
|
+
console.log(chalk.red(`Invalid configuration key: ${key}`));
|
|
52
|
+
console.log(chalk.gray(`Valid keys: ${CLI_CONFIG_KEYS.join(", ")}`));
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
let parsedValue;
|
|
56
|
+
switch (key) {
|
|
57
|
+
case "apiUrl":
|
|
58
|
+
parsedValue = normalizeApiUrl(value);
|
|
59
|
+
break;
|
|
60
|
+
case "defaultTemperature":
|
|
61
|
+
{
|
|
62
|
+
const temperature = parseFloat(value);
|
|
63
|
+
if (isNaN(temperature) || temperature < 0 || temperature > 1) {
|
|
64
|
+
console.log(chalk.red("Temperature must be a number between 0 and 1"));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
parsedValue = temperature;
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
case "streamResponses":
|
|
71
|
+
parsedValue = value === "true";
|
|
72
|
+
break;
|
|
73
|
+
case "outputFormat":
|
|
74
|
+
if (![
|
|
75
|
+
"table",
|
|
76
|
+
"json",
|
|
77
|
+
"plain"
|
|
78
|
+
].includes(value)) {
|
|
79
|
+
console.log(chalk.red("Output format must be: table, json, or plain"));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
parsedValue = value;
|
|
83
|
+
break;
|
|
84
|
+
default: parsedValue = value;
|
|
85
|
+
}
|
|
86
|
+
config.set(key, parsedValue);
|
|
87
|
+
console.log(chalk.green(`Configuration updated: ${key} = ${parsedValue}`));
|
|
88
|
+
});
|
|
89
|
+
configCommand.command("reset").description("Reset all configuration to defaults").action(() => {
|
|
90
|
+
getCliConfig().clear();
|
|
91
|
+
console.log(chalk.green("Configuration reset to defaults"));
|
|
92
|
+
});
|
|
93
|
+
configCommand.command("path").description("Show configuration file path").action(() => {
|
|
94
|
+
console.log(getCliConfig().path);
|
|
95
|
+
});
|
|
96
|
+
export { configCommand };
|
|
97
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { r as createCliClient } from "./chunk-BW2fg46T.js";
|
|
3
|
+
import { RuntypeApiError } from "@runtypelabs/sdk";
|
|
4
|
+
// src/lib/quick-start-api.ts
|
|
5
|
+
function isObjectRecord(value) {
|
|
6
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function isQuickStartValidationResponse(value) {
|
|
9
|
+
if (!isObjectRecord(value) || typeof value.valid !== "boolean") return false;
|
|
10
|
+
if (value.valid === false) return typeof value.error === "string" && typeof value.code === "string";
|
|
11
|
+
return typeof value.templateId === "string" && isObjectRecord(value.agentCard);
|
|
12
|
+
}
|
|
13
|
+
function isQuickStartCreateResponse(value) {
|
|
14
|
+
if (!isObjectRecord(value) || typeof value.success !== "boolean") return false;
|
|
15
|
+
if (value.success === false) return typeof value.error === "string" && typeof value.code === "string";
|
|
16
|
+
return isObjectRecord(value.product) && Array.isArray(value.capabilities) && typeof value.redirectUrl === "string";
|
|
17
|
+
}
|
|
18
|
+
function getApiErrorData(error) {
|
|
19
|
+
return error instanceof RuntypeApiError ? error.data : void 0;
|
|
20
|
+
}
|
|
21
|
+
async function validateQuickStartUrl(url, apiUrl) {
|
|
22
|
+
const client = createCliClient(void 0, apiUrl);
|
|
23
|
+
try {
|
|
24
|
+
return await client.post("/quick-start/validate", { url });
|
|
25
|
+
} catch (error) {
|
|
26
|
+
const data = getApiErrorData(error);
|
|
27
|
+
if (isQuickStartValidationResponse(data)) return data;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function createQuickStartProduct(apiKey, input, apiUrl) {
|
|
32
|
+
const client = createCliClient(apiKey, apiUrl);
|
|
33
|
+
try {
|
|
34
|
+
return await client.post("/quick-start/create", input);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
const data = getApiErrorData(error);
|
|
37
|
+
if (isQuickStartCreateResponse(data)) return data;
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export { validateQuickStartUrl as n, createQuickStartProduct as t };
|
|
42
|
+
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ../shared/dist/chunk-DqvHhX2A.mjs
|
|
3
|
+
/**
|
|
4
|
+
* Default entity set for redaction.
|
|
5
|
+
*
|
|
6
|
+
* IP_ADDRESS is intentionally EXCLUDED: infrastructure logs legitimately contain
|
|
7
|
+
* server IPs, so the false-positive cost of redacting every dotted-quad by
|
|
8
|
+
* default is too high. Callers that want it opt in via `policy.entities`.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_PII_ENTITIES = [
|
|
11
|
+
"EMAIL_ADDRESS",
|
|
12
|
+
"PHONE_NUMBER",
|
|
13
|
+
"CREDIT_CARD",
|
|
14
|
+
"US_SSN",
|
|
15
|
+
"CA_SIN",
|
|
16
|
+
"IBAN"
|
|
17
|
+
];
|
|
18
|
+
/** Luhn (mod-10) check over a run of ASCII digits. */
|
|
19
|
+
function passesLuhn(digits) {
|
|
20
|
+
let sum = 0;
|
|
21
|
+
let double = false;
|
|
22
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
23
|
+
let d = digits.charCodeAt(i) - 48;
|
|
24
|
+
if (d < 0 || d > 9) return false;
|
|
25
|
+
if (double) {
|
|
26
|
+
d *= 2;
|
|
27
|
+
if (d > 9) d -= 9;
|
|
28
|
+
}
|
|
29
|
+
sum += d;
|
|
30
|
+
double = !double;
|
|
31
|
+
}
|
|
32
|
+
return sum % 10 === 0;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* ISO 7064 mod-97-10 check for IBANs. Rearranges (first four chars to the end),
|
|
36
|
+
* expands letters to two-digit numbers (A=10 .. Z=35), then computes the value
|
|
37
|
+
* mod 97 in bounded chunks so we never need BigInt or overflow a 53-bit float.
|
|
38
|
+
*/
|
|
39
|
+
function passesIbanMod97(iban) {
|
|
40
|
+
const rearranged = iban.slice(4) + iban.slice(0, 4);
|
|
41
|
+
let remainder = 0;
|
|
42
|
+
for (let i = 0; i < rearranged.length; i++) {
|
|
43
|
+
const code = rearranged.charCodeAt(i);
|
|
44
|
+
let piece;
|
|
45
|
+
if (code >= 48 && code <= 57) piece = String(code - 48);
|
|
46
|
+
else if (code >= 65 && code <= 90) piece = String(code - 55);
|
|
47
|
+
else if (code >= 97 && code <= 122) piece = String(code - 87);
|
|
48
|
+
else return false;
|
|
49
|
+
for (let j = 0; j < piece.length; j++) remainder = (remainder * 10 + (piece.charCodeAt(j) - 48)) % 97;
|
|
50
|
+
}
|
|
51
|
+
return remainder === 1;
|
|
52
|
+
}
|
|
53
|
+
/** Strip ASCII spaces and hyphens/dots used as visual separators. */
|
|
54
|
+
function digitsOnly(value) {
|
|
55
|
+
let out = "";
|
|
56
|
+
for (let i = 0; i < value.length; i++) {
|
|
57
|
+
const c = value.charCodeAt(i);
|
|
58
|
+
if (c >= 48 && c <= 57) out += value[i];
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
const DETECTORS = [
|
|
63
|
+
{
|
|
64
|
+
entityType: "EMAIL_ADDRESS",
|
|
65
|
+
pattern: () => /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,24}/g,
|
|
66
|
+
validate: () => .95
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
entityType: "CREDIT_CARD",
|
|
70
|
+
pattern: () => /(?<![A-Za-z0-9])\d(?:[ -]?\d){12,18}(?![A-Za-z0-9])/g,
|
|
71
|
+
validate: (m) => {
|
|
72
|
+
const digits = digitsOnly(m[0]);
|
|
73
|
+
if (digits.length < 13 || digits.length > 19) return null;
|
|
74
|
+
return passesLuhn(digits) ? .97 : null;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
entityType: "US_SSN",
|
|
79
|
+
pattern: () => /(?<![A-Za-z0-9-])(\d{3})-(\d{2})-(\d{4})(?![A-Za-z0-9-])/g,
|
|
80
|
+
validate: (m) => {
|
|
81
|
+
const area = m[1];
|
|
82
|
+
const group = m[2];
|
|
83
|
+
const serial = m[3];
|
|
84
|
+
if (area === "000" || area === "666" || area >= "900") return null;
|
|
85
|
+
if (group === "00") return null;
|
|
86
|
+
if (serial === "0000") return null;
|
|
87
|
+
return .9;
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
entityType: "CA_SIN",
|
|
92
|
+
pattern: () => /(?<![A-Za-z0-9-])(\d{3})([ -])(\d{3})\2(\d{3})(?![A-Za-z0-9-])/g,
|
|
93
|
+
validate: (m) => {
|
|
94
|
+
const digits = m[1] + m[3] + m[4];
|
|
95
|
+
const first = digits.charCodeAt(0) - 48;
|
|
96
|
+
if (first === 0 || first === 8) return null;
|
|
97
|
+
return passesLuhn(digits) ? .9 : null;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
entityType: "PHONE_NUMBER",
|
|
102
|
+
pattern: () => /(?<![A-Za-z0-9])\+\d(?:[ .-]?\d){7,14}(?![A-Za-z0-9])/g,
|
|
103
|
+
validate: (m) => {
|
|
104
|
+
const digits = digitsOnly(m[0]);
|
|
105
|
+
return digits.length >= 8 && digits.length <= 15 ? .85 : null;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
entityType: "PHONE_NUMBER",
|
|
110
|
+
pattern: () => /(?<![A-Za-z0-9])(?:\+?1[ .-]?)?(?:\(\d{3}\)[ .-]?|\d{3}[ .-])\d{3}[ .-]?\d{4}(?![A-Za-z0-9])/g,
|
|
111
|
+
validate: () => .85
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
entityType: "IBAN",
|
|
115
|
+
pattern: () => /(?<![A-Za-z0-9])[A-Za-z]{2}\d{2}[A-Za-z0-9]{11,30}(?![A-Za-z0-9])/g,
|
|
116
|
+
validate: (m) => passesIbanMod97(m[0]) ? .97 : null
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
entityType: "IP_ADDRESS",
|
|
120
|
+
pattern: () => /(?<![A-Za-z0-9.])(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?![A-Za-z0-9.])/g,
|
|
121
|
+
validate: (m) => {
|
|
122
|
+
for (let i = 1; i <= 4; i++) {
|
|
123
|
+
if (Number(m[i]) > 255) return null;
|
|
124
|
+
if (m[i].length > 1 && m[i].charCodeAt(0) === 48) return null;
|
|
125
|
+
}
|
|
126
|
+
return .8;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
];
|
|
130
|
+
function analyzeWithDetectors(text, entities) {
|
|
131
|
+
const raw = [];
|
|
132
|
+
for (const detector of DETECTORS) {
|
|
133
|
+
if (!entities.has(detector.entityType)) continue;
|
|
134
|
+
const pattern = detector.pattern();
|
|
135
|
+
let match;
|
|
136
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
137
|
+
if (match[0].length === 0) {
|
|
138
|
+
pattern.lastIndex++;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const confidence = detector.validate(match);
|
|
142
|
+
if (confidence === null) continue;
|
|
143
|
+
raw.push({
|
|
144
|
+
entityType: detector.entityType,
|
|
145
|
+
start: match.index,
|
|
146
|
+
end: match.index + match[0].length,
|
|
147
|
+
confidence
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return resolveOverlaps(raw);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Drop overlapping findings, preferring higher confidence then the longer span.
|
|
155
|
+
* Sorts and dedupes by priority. Returns findings
|
|
156
|
+
* sorted by `start` ascending.
|
|
157
|
+
*/
|
|
158
|
+
function resolveOverlaps(findings) {
|
|
159
|
+
if (findings.length <= 1) return findings;
|
|
160
|
+
const byPriority = [...findings].sort((a, b) => b.confidence - a.confidence || b.end - b.start - (a.end - a.start) || a.start - b.start);
|
|
161
|
+
const accepted = [];
|
|
162
|
+
for (const candidate of byPriority) if (!accepted.some((kept) => candidate.start < kept.end && kept.start < candidate.end)) accepted.push(candidate);
|
|
163
|
+
return accepted.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
164
|
+
}
|
|
165
|
+
/** The built-in regex-tier analyzer. Stateless and safe to share. */
|
|
166
|
+
const defaultRegexPiiAnalyzer = { analyze(text, entities) {
|
|
167
|
+
if (typeof text !== "string" || text.length === 0) return [];
|
|
168
|
+
return analyzeWithDetectors(text, entities);
|
|
169
|
+
} };
|
|
170
|
+
function resolvePolicyEntities(policy) {
|
|
171
|
+
const list = policy.entities && policy.entities.length > 0 ? policy.entities : DEFAULT_PII_ENTITIES;
|
|
172
|
+
return new Set(list);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Detect and mask PII in a single string.
|
|
176
|
+
*
|
|
177
|
+
* `mode: 'off'` is a pass-through (returns the input verbatim with no findings).
|
|
178
|
+
* Replacement is applied end-to-start so finding offsets stay valid, and the
|
|
179
|
+
* mask token (`<ENTITY_TYPE>`) matches no detector, keeping redaction idempotent.
|
|
180
|
+
*/
|
|
181
|
+
function redactPiiText(text, policy, analyzer = defaultRegexPiiAnalyzer) {
|
|
182
|
+
if (policy.mode === "off" || typeof text !== "string" || text.length === 0) return {
|
|
183
|
+
text,
|
|
184
|
+
findings: []
|
|
185
|
+
};
|
|
186
|
+
const entities = resolvePolicyEntities(policy);
|
|
187
|
+
const findings = analyzer.analyze(text, entities);
|
|
188
|
+
if (findings.length === 0) return {
|
|
189
|
+
text,
|
|
190
|
+
findings
|
|
191
|
+
};
|
|
192
|
+
let out = text;
|
|
193
|
+
for (let i = findings.length - 1; i >= 0; i--) {
|
|
194
|
+
const finding = findings[i];
|
|
195
|
+
out = out.slice(0, finding.start) + `<${finding.entityType}>` + out.slice(finding.end);
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
text: out,
|
|
199
|
+
findings
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
export { redactPiiText as t };
|
|
203
|
+
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as isTTY } from "./index.js";
|
|
3
|
+
import { DataList, EntityCard, MutationResult, React, Text, render, useEffect, useState } from "./chunk-CoAWdSiE.js";
|
|
4
|
+
import { r as createCliClient } from "./chunk-BW2fg46T.js";
|
|
5
|
+
import { n as ensureAuth } from "./chunk-CJraEBVd.js";
|
|
6
|
+
import { a as printJson, i as printDetail } from "./chunk-CcFCyqbB.js";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
// src/commands/flow-versions.ts
|
|
10
|
+
const flowVersionsCommand = new Command("flow-versions").description("Manage flow versions");
|
|
11
|
+
flowVersionsCommand.command("list <flowId>").description("List all versions for a flow").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (flowId, options) => {
|
|
12
|
+
const apiKey = await ensureAuth();
|
|
13
|
+
if (!apiKey) return;
|
|
14
|
+
const client = createCliClient(apiKey);
|
|
15
|
+
if (!isTTY(options) || options.json) {
|
|
16
|
+
try {
|
|
17
|
+
const data = await client.get(`/flow-versions/${flowId}`);
|
|
18
|
+
if (options.json) printJson(data);
|
|
19
|
+
else {
|
|
20
|
+
const versions = data.data ?? [];
|
|
21
|
+
if (versions.length === 0) {
|
|
22
|
+
console.log(chalk.gray("No versions found"));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk.cyan(`Versions for flow ${flowId}:`));
|
|
26
|
+
for (const v of versions) {
|
|
27
|
+
const publishedTag = v.published ? chalk.green(" [published]") : "";
|
|
28
|
+
const versionNum = v.version !== void 0 ? `v${v.version}` : v.id;
|
|
29
|
+
const date = v.createdAt ? chalk.gray(` ${v.createdAt}`) : "";
|
|
30
|
+
console.log(` ${chalk.green(v.id)} ${versionNum}${publishedTag}${date}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
35
|
+
console.error(chalk.red("Failed to fetch versions"));
|
|
36
|
+
console.error(chalk.red(message));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const App = () => {
|
|
42
|
+
const [loading, setLoading] = useState(true);
|
|
43
|
+
const [items, setItems] = useState(null);
|
|
44
|
+
const [error, setError] = useState(null);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const run = async () => {
|
|
47
|
+
try {
|
|
48
|
+
const data = await client.get(`/flow-versions/${flowId}`);
|
|
49
|
+
setItems(data.data ?? []);
|
|
50
|
+
setLoading(false);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
53
|
+
setLoading(false);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
run();
|
|
57
|
+
}, []);
|
|
58
|
+
return React.createElement(DataList, {
|
|
59
|
+
title: `Versions for flow ${flowId}`,
|
|
60
|
+
items,
|
|
61
|
+
error,
|
|
62
|
+
loading,
|
|
63
|
+
emptyMessage: "No versions found",
|
|
64
|
+
renderCard: (item) => {
|
|
65
|
+
const v = item;
|
|
66
|
+
const publishedTag = v.published ? " [published]" : "";
|
|
67
|
+
const versionNum = v.version !== void 0 ? `v${v.version}` : v.id;
|
|
68
|
+
return React.createElement(Text, null, ` ${v.id} ${versionNum}${publishedTag}${v.createdAt ? ` ${v.createdAt}` : ""}`);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
73
|
+
await waitUntilExit();
|
|
74
|
+
});
|
|
75
|
+
flowVersionsCommand.command("get <flowId> <versionId>").description("Get a specific version").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (flowId, versionId, options) => {
|
|
76
|
+
const apiKey = await ensureAuth();
|
|
77
|
+
if (!apiKey) return;
|
|
78
|
+
const client = createCliClient(apiKey);
|
|
79
|
+
if (!isTTY(options) || options.json) {
|
|
80
|
+
try {
|
|
81
|
+
const data = await client.get(`/flow-versions/${flowId}/${versionId}`);
|
|
82
|
+
if (options.json) printJson(data);
|
|
83
|
+
else printDetail("Flow Version", [
|
|
84
|
+
{
|
|
85
|
+
label: "ID",
|
|
86
|
+
value: data.id
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
label: "Flow ID",
|
|
90
|
+
value: data.flowId
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
label: "Version",
|
|
94
|
+
value: data.version
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
label: "Published",
|
|
98
|
+
value: data.published
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
label: "Created",
|
|
102
|
+
value: data.createdAt
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: "Steps",
|
|
106
|
+
value: data.steps?.length
|
|
107
|
+
}
|
|
108
|
+
]);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
111
|
+
console.error(chalk.red("Failed to fetch version"));
|
|
112
|
+
console.error(chalk.red(message));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const App = () => {
|
|
118
|
+
const [loading, setLoading] = useState(true);
|
|
119
|
+
const [success, setSuccess] = useState(null);
|
|
120
|
+
const [error, setError] = useState(null);
|
|
121
|
+
const [resultNode, setResultNode] = useState(void 0);
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
const run = async () => {
|
|
124
|
+
try {
|
|
125
|
+
const data = await client.get(`/flow-versions/${flowId}/${versionId}`);
|
|
126
|
+
setResultNode(React.createElement(EntityCard, { fields: [
|
|
127
|
+
{
|
|
128
|
+
label: "ID",
|
|
129
|
+
value: data.id
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
label: "Flow ID",
|
|
133
|
+
value: data.flowId
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
label: "Version",
|
|
137
|
+
value: data.version
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
label: "Published",
|
|
141
|
+
value: data.published ? "Yes" : "No",
|
|
142
|
+
color: data.published ? "green" : void 0
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: "Created",
|
|
146
|
+
value: data.createdAt
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: "Steps",
|
|
150
|
+
value: data.steps?.length
|
|
151
|
+
}
|
|
152
|
+
] }));
|
|
153
|
+
setSuccess(true);
|
|
154
|
+
setLoading(false);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
157
|
+
setSuccess(false);
|
|
158
|
+
setLoading(false);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
run();
|
|
162
|
+
}, []);
|
|
163
|
+
return React.createElement(MutationResult, {
|
|
164
|
+
loading,
|
|
165
|
+
loadingLabel: "Fetching version...",
|
|
166
|
+
success,
|
|
167
|
+
successMessage: "Flow Version",
|
|
168
|
+
error,
|
|
169
|
+
result: resultNode
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
173
|
+
await waitUntilExit();
|
|
174
|
+
});
|
|
175
|
+
flowVersionsCommand.command("published <flowId>").description("Get the published version for a flow").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (flowId, options) => {
|
|
176
|
+
const apiKey = await ensureAuth();
|
|
177
|
+
if (!apiKey) return;
|
|
178
|
+
const client = createCliClient(apiKey);
|
|
179
|
+
if (!isTTY(options) || options.json) {
|
|
180
|
+
try {
|
|
181
|
+
const data = await client.get(`/flow-versions/${flowId}/published`);
|
|
182
|
+
if (options.json) printJson(data);
|
|
183
|
+
else printDetail("Published Version", [
|
|
184
|
+
{
|
|
185
|
+
label: "ID",
|
|
186
|
+
value: data.id
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
label: "Version",
|
|
190
|
+
value: data.version
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
label: "Created",
|
|
194
|
+
value: data.createdAt
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
label: "Steps",
|
|
198
|
+
value: data.steps?.length
|
|
199
|
+
}
|
|
200
|
+
]);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
203
|
+
console.error(chalk.red("Failed to fetch published version"));
|
|
204
|
+
console.error(chalk.red(message));
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const App = () => {
|
|
210
|
+
const [loading, setLoading] = useState(true);
|
|
211
|
+
const [success, setSuccess] = useState(null);
|
|
212
|
+
const [error, setError] = useState(null);
|
|
213
|
+
const [resultNode, setResultNode] = useState(void 0);
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
const run = async () => {
|
|
216
|
+
try {
|
|
217
|
+
const data = await client.get(`/flow-versions/${flowId}/published`);
|
|
218
|
+
setResultNode(React.createElement(EntityCard, { fields: [
|
|
219
|
+
{
|
|
220
|
+
label: "ID",
|
|
221
|
+
value: data.id
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
label: "Version",
|
|
225
|
+
value: data.version
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
label: "Created",
|
|
229
|
+
value: data.createdAt
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
label: "Steps",
|
|
233
|
+
value: data.steps?.length
|
|
234
|
+
}
|
|
235
|
+
] }));
|
|
236
|
+
setSuccess(true);
|
|
237
|
+
setLoading(false);
|
|
238
|
+
} catch (err) {
|
|
239
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
240
|
+
setSuccess(false);
|
|
241
|
+
setLoading(false);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
run();
|
|
245
|
+
}, []);
|
|
246
|
+
return React.createElement(MutationResult, {
|
|
247
|
+
loading,
|
|
248
|
+
loadingLabel: "Fetching published version...",
|
|
249
|
+
success,
|
|
250
|
+
successMessage: "Published Version",
|
|
251
|
+
error,
|
|
252
|
+
result: resultNode
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
256
|
+
await waitUntilExit();
|
|
257
|
+
});
|
|
258
|
+
flowVersionsCommand.command("publish <flowId>").description("Publish a version").requiredOption("-v, --version <versionId>", "Version ID to publish").option("--overwrite-managed", "Confirm replacing a definition managed by code").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (flowId, options) => {
|
|
259
|
+
const apiKey = await ensureAuth();
|
|
260
|
+
if (!apiKey) return;
|
|
261
|
+
const client = createCliClient(apiKey);
|
|
262
|
+
if (!isTTY(options)) {
|
|
263
|
+
try {
|
|
264
|
+
const result = await client.post(`/flow-versions/${flowId}/publish`, {
|
|
265
|
+
versionId: options.version,
|
|
266
|
+
...options.overwriteManaged ? { onConflict: "overwrite" } : {}
|
|
267
|
+
});
|
|
268
|
+
console.log(chalk.green("Version published"));
|
|
269
|
+
for (const warning of result.warnings ?? []) console.warn(chalk.yellow(`Warning: ${warning}`));
|
|
270
|
+
} catch (error) {
|
|
271
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
272
|
+
console.error(chalk.red("Failed to publish version"));
|
|
273
|
+
console.error(chalk.red(message));
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const App = () => {
|
|
279
|
+
const [loading, setLoading] = useState(true);
|
|
280
|
+
const [success, setSuccess] = useState(null);
|
|
281
|
+
const [error, setError] = useState(null);
|
|
282
|
+
const [successMessage, setSuccessMessage] = useState("Version published");
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
const run = async () => {
|
|
285
|
+
try {
|
|
286
|
+
const result = await client.post(`/flow-versions/${flowId}/publish`, {
|
|
287
|
+
versionId: options.version,
|
|
288
|
+
...options.overwriteManaged ? { onConflict: "overwrite" } : {}
|
|
289
|
+
});
|
|
290
|
+
if (result.warnings?.length) setSuccessMessage(`Version published. ${result.warnings.join(" ")}`);
|
|
291
|
+
setSuccess(true);
|
|
292
|
+
setLoading(false);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
295
|
+
setSuccess(false);
|
|
296
|
+
setLoading(false);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
run();
|
|
300
|
+
}, []);
|
|
301
|
+
return React.createElement(MutationResult, {
|
|
302
|
+
loading,
|
|
303
|
+
loadingLabel: "Publishing version...",
|
|
304
|
+
success,
|
|
305
|
+
successMessage,
|
|
306
|
+
error
|
|
307
|
+
});
|
|
308
|
+
};
|
|
309
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
310
|
+
await waitUntilExit();
|
|
311
|
+
});
|
|
312
|
+
export { flowVersionsCommand };
|
|
313
|
+
|