@pretense/cli 0.6.2 → 0.6.4
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/index.js +94 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15862,6 +15862,30 @@ function extractDeltas(line, provider) {
|
|
|
15862
15862
|
delta[prop] = v;
|
|
15863
15863
|
}
|
|
15864
15864
|
});
|
|
15865
|
+
} else if (provider === "google") {
|
|
15866
|
+
const candidates = json["candidates"];
|
|
15867
|
+
if (!Array.isArray(candidates)) return null;
|
|
15868
|
+
for (let ci = 0; ci < candidates.length; ci++) {
|
|
15869
|
+
const cand = candidates[ci];
|
|
15870
|
+
const candIndex = typeof cand["index"] === "number" ? cand["index"] : ci;
|
|
15871
|
+
const content = cand["content"];
|
|
15872
|
+
if (!content) continue;
|
|
15873
|
+
const parts = content["parts"];
|
|
15874
|
+
if (!Array.isArray(parts)) continue;
|
|
15875
|
+
for (const part of parts) {
|
|
15876
|
+
if (typeof part["text"] !== "string") continue;
|
|
15877
|
+
const isThought = part["thought"] === true;
|
|
15878
|
+
refs.push({
|
|
15879
|
+
key: `g:${candIndex}:${isThought ? "thought" : "text"}`,
|
|
15880
|
+
index: candIndex,
|
|
15881
|
+
kind: isThought ? "google_thought" : "google_text",
|
|
15882
|
+
text: part["text"],
|
|
15883
|
+
set: (v) => {
|
|
15884
|
+
part["text"] = v;
|
|
15885
|
+
}
|
|
15886
|
+
});
|
|
15887
|
+
}
|
|
15888
|
+
}
|
|
15865
15889
|
} else {
|
|
15866
15890
|
const choices = json["choices"];
|
|
15867
15891
|
if (!Array.isArray(choices) || choices.length === 0) return null;
|
|
@@ -15907,6 +15931,14 @@ function toJsonStringContextMap(map) {
|
|
|
15907
15931
|
}
|
|
15908
15932
|
return out;
|
|
15909
15933
|
}
|
|
15934
|
+
function classifyStreamProvider(upstream) {
|
|
15935
|
+
const u = upstream.toLowerCase();
|
|
15936
|
+
if (u.includes("anthropic")) return "anthropic";
|
|
15937
|
+
if (u.includes("generativelanguage") || u.includes("googleapis") || u.includes("gemini")) {
|
|
15938
|
+
return "google";
|
|
15939
|
+
}
|
|
15940
|
+
return "openai";
|
|
15941
|
+
}
|
|
15910
15942
|
async function streamWithRollingBuffer(upstreamResp, map, provider, requestId) {
|
|
15911
15943
|
const buffers = /* @__PURE__ */ new Map();
|
|
15912
15944
|
const bufferMeta = /* @__PURE__ */ new Map();
|
|
@@ -16021,6 +16053,12 @@ function buildFlushEvent(text, provider, kind, index) {
|
|
|
16021
16053
|
const delta2 = kind === "input_json" ? { type: "input_json_delta", partial_json: text } : kind === "thinking" ? { type: "thinking_delta", thinking: text } : { type: "text_delta", text };
|
|
16022
16054
|
return "data: " + JSON.stringify({ type: "content_block_delta", index, delta: delta2 });
|
|
16023
16055
|
}
|
|
16056
|
+
if (provider === "google") {
|
|
16057
|
+
const part = kind === "google_thought" ? { text, thought: true } : { text };
|
|
16058
|
+
return "data: " + JSON.stringify({
|
|
16059
|
+
candidates: [{ content: { parts: [part], role: "model" }, index }]
|
|
16060
|
+
});
|
|
16061
|
+
}
|
|
16024
16062
|
const delta = kind === "openai_tool_args" ? { tool_calls: [{ index, function: { arguments: text } }] } : { content: text };
|
|
16025
16063
|
return "data: " + JSON.stringify({
|
|
16026
16064
|
id: "pretense-flush",
|
|
@@ -16276,7 +16314,7 @@ function tokenizeBodyDeep(body, scanText) {
|
|
|
16276
16314
|
};
|
|
16277
16315
|
}
|
|
16278
16316
|
async function handleStreaming(upstreamResp, map, requestId, upstream) {
|
|
16279
|
-
const provider = upstream
|
|
16317
|
+
const provider = classifyStreamProvider(upstream);
|
|
16280
16318
|
return streamWithRollingBuffer(upstreamResp, map, provider, requestId);
|
|
16281
16319
|
}
|
|
16282
16320
|
function createProxy(opts = {}) {
|
|
@@ -16750,7 +16788,10 @@ Upgrade to ${_upgradeTier === "enterprise" ? "Enterprise" : "Pro"} for ${_upgrad
|
|
|
16750
16788
|
for (const [orig, syn] of globalMap.entries()) {
|
|
16751
16789
|
if (!secretMap.has(syn)) reverseMap.set(orig, syn);
|
|
16752
16790
|
}
|
|
16753
|
-
|
|
16791
|
+
const upstreamIsSse = (upstreamResp.headers.get("content-type") ?? "").includes(
|
|
16792
|
+
"text/event-stream"
|
|
16793
|
+
);
|
|
16794
|
+
if (body["stream"] === true || upstreamIsSse) {
|
|
16754
16795
|
return handleStreaming(upstreamResp, reverseMap, requestId, upstream);
|
|
16755
16796
|
}
|
|
16756
16797
|
let respBody;
|
|
@@ -17567,8 +17608,12 @@ function logsCommand() {
|
|
|
17567
17608
|
entries = store.getRecentEntries(limit);
|
|
17568
17609
|
store.close();
|
|
17569
17610
|
} catch {
|
|
17570
|
-
|
|
17571
|
-
|
|
17611
|
+
if (opts.json) {
|
|
17612
|
+
console.log("[]");
|
|
17613
|
+
return;
|
|
17614
|
+
}
|
|
17615
|
+
console.error(chalk6.dim("\n No audit data available. The audit database has not been initialized yet."));
|
|
17616
|
+
console.error(chalk6.dim(" Run " + chalk6.cyan("pretense start") + " and make some requests first.\n"));
|
|
17572
17617
|
return;
|
|
17573
17618
|
}
|
|
17574
17619
|
if (opts.json) {
|
|
@@ -18962,15 +19007,26 @@ async function collectMutationFindings(content, file, level) {
|
|
|
18962
19007
|
}
|
|
18963
19008
|
async function runMutate(file, opts = {}) {
|
|
18964
19009
|
const level = resolveMutateLevel(opts);
|
|
18965
|
-
let
|
|
19010
|
+
let raw2;
|
|
18966
19011
|
try {
|
|
18967
|
-
|
|
19012
|
+
raw2 = readFileSync14(file);
|
|
18968
19013
|
} catch {
|
|
18969
19014
|
console.error(chalk13.red(`
|
|
18970
19015
|
x Cannot read file: ${file}
|
|
18971
19016
|
`));
|
|
18972
19017
|
return 1;
|
|
18973
19018
|
}
|
|
19019
|
+
const content = raw2.toString("utf-8");
|
|
19020
|
+
if (!Buffer.from(content, "utf-8").equals(raw2)) {
|
|
19021
|
+
console.error(
|
|
19022
|
+
chalk13.red(`
|
|
19023
|
+
x Not valid UTF-8: ${file}`) + chalk13.dim(`
|
|
19024
|
+
Mutating would replace the undecodable bytes with U+FFFD and the`) + chalk13.dim(`
|
|
19025
|
+
original content could not be restored. File left untouched.
|
|
19026
|
+
`)
|
|
19027
|
+
);
|
|
19028
|
+
return 1;
|
|
19029
|
+
}
|
|
18974
19030
|
const findings = await collectMutationFindings(content, file, level);
|
|
18975
19031
|
if (findings.length === 0) {
|
|
18976
19032
|
console.error(chalk13.dim(` No secrets found in ${file} \u2014 nothing to mutate.`));
|
|
@@ -18978,15 +19034,6 @@ async function runMutate(file, opts = {}) {
|
|
|
18978
19034
|
return 0;
|
|
18979
19035
|
}
|
|
18980
19036
|
const result = mutateSecrets(content, findings);
|
|
18981
|
-
if (opts.inPlace) {
|
|
18982
|
-
writeFileSync9(file, result.content);
|
|
18983
|
-
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets in ${file} (in-place)`));
|
|
18984
|
-
} else if (opts.output) {
|
|
18985
|
-
writeFileSync9(opts.output, result.content);
|
|
18986
|
-
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets \u2192 ${opts.output}`));
|
|
18987
|
-
} else {
|
|
18988
|
-
process.stdout.write(result.content);
|
|
18989
|
-
}
|
|
18990
19037
|
if (opts.map) {
|
|
18991
19038
|
const absFile = resolve4(file);
|
|
18992
19039
|
const projectKey = getOrCreateProjectKey(findProjectRoot(absFile), opts.keysDir);
|
|
@@ -19001,7 +19048,18 @@ async function runMutate(file, opts = {}) {
|
|
|
19001
19048
|
type: m.type
|
|
19002
19049
|
}))
|
|
19003
19050
|
};
|
|
19004
|
-
|
|
19051
|
+
try {
|
|
19052
|
+
writeFileSync9(opts.map, JSON.stringify(mapFile, null, 2), { mode: 384 });
|
|
19053
|
+
} catch (e) {
|
|
19054
|
+
console.error(
|
|
19055
|
+
chalk13.red(`
|
|
19056
|
+
x Cannot write reversal map: ${opts.map}`) + chalk13.dim(`
|
|
19057
|
+
${e.message}`) + chalk13.dim(`
|
|
19058
|
+
Nothing was mutated \u2014 without a map the original could not be restored.
|
|
19059
|
+
`)
|
|
19060
|
+
);
|
|
19061
|
+
return 1;
|
|
19062
|
+
}
|
|
19005
19063
|
try {
|
|
19006
19064
|
chmodSync6(opts.map, 384);
|
|
19007
19065
|
} catch {
|
|
@@ -19010,6 +19068,25 @@ async function runMutate(file, opts = {}) {
|
|
|
19010
19068
|
chalk13.green(` \u2713 Wrote encrypted reversal map \u2192 ${opts.map}`) + chalk13.dim(" (AES-256-GCM, mode 0600)")
|
|
19011
19069
|
);
|
|
19012
19070
|
}
|
|
19071
|
+
try {
|
|
19072
|
+
if (opts.inPlace) {
|
|
19073
|
+
writeFileSync9(file, result.content);
|
|
19074
|
+
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets in ${file} (in-place)`));
|
|
19075
|
+
} else if (opts.output) {
|
|
19076
|
+
writeFileSync9(opts.output, result.content);
|
|
19077
|
+
console.error(chalk13.green(` \u2713 Mutated ${result.mutations.length} secrets \u2192 ${opts.output}`));
|
|
19078
|
+
} else {
|
|
19079
|
+
process.stdout.write(result.content);
|
|
19080
|
+
}
|
|
19081
|
+
} catch (e) {
|
|
19082
|
+
console.error(
|
|
19083
|
+
chalk13.red(`
|
|
19084
|
+
x Cannot write mutated content: ${opts.output ?? file}`) + chalk13.dim(`
|
|
19085
|
+
${e.message}
|
|
19086
|
+
`)
|
|
19087
|
+
);
|
|
19088
|
+
return 1;
|
|
19089
|
+
}
|
|
19013
19090
|
if (opts.showMap) {
|
|
19014
19091
|
console.error(JSON.stringify(result.mutations, null, 2));
|
|
19015
19092
|
}
|
|
@@ -19527,7 +19604,7 @@ function findClosestCommand(input, knownCommands) {
|
|
|
19527
19604
|
return bestDist <= 3 ? best : null;
|
|
19528
19605
|
}
|
|
19529
19606
|
var program = new Command20();
|
|
19530
|
-
program.name("pretense").description(chalk19.bold("AI firewall") + " \u2014 mutates proprietary code before LLM API calls").version("0.6.
|
|
19607
|
+
program.name("pretense").description(chalk19.bold("AI firewall") + " \u2014 mutates proprietary code before LLM API calls").version("0.6.4", "-v, --version").addHelpText("after", `
|
|
19531
19608
|
${chalk19.bold("Quick start:")}
|
|
19532
19609
|
${chalk19.cyan("pretense scan")} ${chalk19.dim("<file|dir>")} Scan for secrets and PII
|
|
19533
19610
|
${chalk19.cyan("pretense mutate")} ${chalk19.dim("<file>")} Preview code mutations
|