auto-mode 0.5.0 → 0.6.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 +3 -2
- package/dist/cli.js +2 -3
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -1
- package/dist/{render-verdict-FdG6gahX.js → render-verdict-9pnm4JBS.js} +648 -463
- package/package.json +1 -1
- package/policy/denial.md +1 -0
package/README.md
CHANGED
|
@@ -59,8 +59,9 @@ assessment.
|
|
|
59
59
|
## Decisions and failures
|
|
60
60
|
|
|
61
61
|
Jev evaluates each named rule with a typed choice. auto-mode returns a denial for a confident block,
|
|
62
|
-
approval when every rule confidently allows the action, and
|
|
63
|
-
|
|
62
|
+
approval when every rule confidently allows the action, and a denial for uncertain decisions. Every
|
|
63
|
+
denial names its rule, the harm, and what clears it, and the agent continues on another path. The
|
|
64
|
+
confidence threshold is configurable and needs evaluation against your actions.
|
|
64
65
|
|
|
65
66
|
A missing key, failed API call, malformed response, or oversized request follows `onFailure`. The
|
|
66
67
|
default `defer` writes no verdict and keeps the prompt; `deny` fails closed. Failures write a
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as parseActionRequest, r as classifyAction, s as loadPolicy, t as renderVerdict, u as loadConfig } from "./render-verdict-
|
|
2
|
+
import { n as parseActionRequest, r as classifyAction, s as loadPolicy, t as renderVerdict, u as loadConfig } from "./render-verdict-9pnm4JBS.js";
|
|
3
3
|
import { appendFile, mkdir } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
@@ -138,8 +138,7 @@ async function run(explain, localOnly, jevOnly, deadline) {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
function writeVerdict(verdict) {
|
|
141
|
-
|
|
142
|
-
if (rendered !== null) process.stdout.write(rendered);
|
|
141
|
+
process.stdout.write(renderVerdict(verdict));
|
|
143
142
|
}
|
|
144
143
|
function printNote(explain, message) {
|
|
145
144
|
if (explain) process.stderr.write(`auto-mode: ${message}\n`);
|
package/dist/index.d.ts
CHANGED
|
@@ -57,8 +57,6 @@ interface ActionRequest {
|
|
|
57
57
|
}
|
|
58
58
|
type Verdict = {
|
|
59
59
|
readonly kind: 'allow';
|
|
60
|
-
} | {
|
|
61
|
-
readonly kind: 'ask';
|
|
62
60
|
} | {
|
|
63
61
|
readonly kind: 'deny';
|
|
64
62
|
readonly rule: string;
|
|
@@ -80,7 +78,7 @@ interface DecisionAnswer {
|
|
|
80
78
|
}
|
|
81
79
|
type DecisionFailureReason = 'request-too-large' | 'aborted' | 'network' | 'http-status' | 'invalid-response';
|
|
82
80
|
interface DecisionDiagnostics {
|
|
83
|
-
readonly status: 'allow' | 'deny' | '
|
|
81
|
+
readonly status: 'allow' | 'deny' | 'failure' | 'timeout' | 'cancelled';
|
|
84
82
|
readonly stage: 'credential' | 'evidence' | 'request' | 'response';
|
|
85
83
|
readonly keyResolved: boolean;
|
|
86
84
|
readonly keySource: 'environment' | 'command' | 'none';
|
|
@@ -134,7 +132,7 @@ export declare function loadPolicy(paths?: PolicyPaths, framework?: 'classifier.
|
|
|
134
132
|
export declare function parseActionRequest(body: unknown): ActionRequest | null;
|
|
135
133
|
//#endregion
|
|
136
134
|
//#region src/request/render-verdict.d.ts
|
|
137
|
-
export declare function renderVerdict(verdict: Verdict): string
|
|
135
|
+
export declare function renderVerdict(verdict: Verdict): string;
|
|
138
136
|
//#endregion
|
|
139
137
|
//#region src/rules/classify-locally.d.ts
|
|
140
138
|
type LocalVerdict = {
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as classifyWithModel, c as DEFAULT_CONFIG, d as resolveApiKey, f as resolveConfigPath, i as classifyLocally, l as PRESETS, n as parseActionRequest, o as parseModelVerdict, r as classifyAction, s as loadPolicy, t as renderVerdict, u as loadConfig } from "./render-verdict-
|
|
1
|
+
import { a as classifyWithModel, c as DEFAULT_CONFIG, d as resolveApiKey, f as resolveConfigPath, i as classifyLocally, l as PRESETS, n as parseActionRequest, o as parseModelVerdict, r as classifyAction, s as loadPolicy, t as renderVerdict, u as loadConfig } from "./render-verdict-9pnm4JBS.js";
|
|
2
2
|
export { DEFAULT_CONFIG, PRESETS, classifyAction, classifyLocally, classifyWithModel, loadConfig, loadPolicy, parseActionRequest, parseModelVerdict, renderVerdict, resolveApiKey, resolveConfigPath };
|
|
@@ -5739,25 +5739,27 @@ function resolveApiKey(provider, options = {}) {
|
|
|
5739
5739
|
return readApiKeyFromCommand(provider.apiKeyCommand, options);
|
|
5740
5740
|
}
|
|
5741
5741
|
//#endregion
|
|
5742
|
+
//#region src/policy/resolve-shipped-policy-dir.ts
|
|
5743
|
+
function resolveShippedPolicyDir() {
|
|
5744
|
+
let dir = import.meta.dirname;
|
|
5745
|
+
for (;;) {
|
|
5746
|
+
if (existsSync(join(dir, "policy", "classifier.md"))) return join(dir, "policy");
|
|
5747
|
+
const parent = dirname(dir);
|
|
5748
|
+
if (parent === dir || dir === parse(dir).root) throw new Error("auto-mode cannot find its shipped policy/ directory");
|
|
5749
|
+
dir = parent;
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5752
|
+
//#endregion
|
|
5742
5753
|
//#region src/policy/load-policy.ts
|
|
5743
5754
|
const RULES_MARKER = "<rules>";
|
|
5744
5755
|
async function loadPolicy(paths = {}, framework = "classifier.md") {
|
|
5745
|
-
const shipped =
|
|
5756
|
+
const shipped = resolveShippedPolicyDir();
|
|
5746
5757
|
const classifierPath = paths.classifierPath ?? join(shipped, framework);
|
|
5747
5758
|
const rulesPath = paths.rulesPath ?? join(shipped, "rules.md");
|
|
5748
5759
|
const [classifier, rules] = await Promise.all([readFile(classifierPath, "utf8"), readFile(rulesPath, "utf8")]);
|
|
5749
5760
|
if (!classifier.includes(RULES_MARKER)) throw new Error(`${classifierPath} has no ${RULES_MARKER} line, so the rules cannot be placed`);
|
|
5750
5761
|
return classifier.replace(RULES_MARKER, rules.trim());
|
|
5751
5762
|
}
|
|
5752
|
-
function findShippedPolicyDir() {
|
|
5753
|
-
let dir = import.meta.dirname;
|
|
5754
|
-
for (;;) {
|
|
5755
|
-
if (existsSync(join(dir, "policy", "classifier.md"))) return join(dir, "policy");
|
|
5756
|
-
const parent = dirname(dir);
|
|
5757
|
-
if (parent === dir || dir === parse(dir).root) throw new Error("auto-mode cannot find its shipped policy/ directory");
|
|
5758
|
-
dir = parent;
|
|
5759
|
-
}
|
|
5760
|
-
}
|
|
5761
5763
|
//#endregion
|
|
5762
5764
|
//#region src/model/anthropic-client.ts
|
|
5763
5765
|
async function sendMessage(provider, apiKey, request) {
|
|
@@ -5946,12 +5948,38 @@ function buildEvidenceGuidance(name) {
|
|
|
5946
5948
|
return "";
|
|
5947
5949
|
}
|
|
5948
5950
|
//#endregion
|
|
5951
|
+
//#region src/model/classify-decision-answers.ts
|
|
5952
|
+
function classifyDecisionAnswers(request, result, minConfidence) {
|
|
5953
|
+
const entries = Object.entries(request.rules).map(([id, rule]) => {
|
|
5954
|
+
const answer = result.answers[id];
|
|
5955
|
+
if (answer === void 0) throw new Error("Decision answer missing");
|
|
5956
|
+
return {
|
|
5957
|
+
rule,
|
|
5958
|
+
answer
|
|
5959
|
+
};
|
|
5960
|
+
});
|
|
5961
|
+
for (const tier of ["hard", "soft"]) for (const entry of entries) if (entry.rule.tier === tier && entry.answer.choice === "block" && entry.answer.confidence >= minConfidence && entry.answer.probabilities.block >= minConfidence) return {
|
|
5962
|
+
kind: "block",
|
|
5963
|
+
rule: entry.rule
|
|
5964
|
+
};
|
|
5965
|
+
let uncertain = null;
|
|
5966
|
+
for (const entry of entries) {
|
|
5967
|
+
const answer = entry.answer;
|
|
5968
|
+
if (!(answer.choice === "allow" && answer.confidence >= minConfidence && answer.probabilities.allow >= minConfidence) && (uncertain === null || answer.probabilities.block > uncertain.answer.probabilities.block)) uncertain = entry;
|
|
5969
|
+
}
|
|
5970
|
+
return uncertain === null ? { kind: "allow" } : {
|
|
5971
|
+
kind: "uncertain",
|
|
5972
|
+
rule: uncertain.rule
|
|
5973
|
+
};
|
|
5974
|
+
}
|
|
5975
|
+
//#endregion
|
|
5949
5976
|
//#region src/model/collect-decision-contributors.ts
|
|
5950
|
-
function collectDecisionContributors(request, result,
|
|
5977
|
+
function collectDecisionContributors(request, result, minConfidence) {
|
|
5978
|
+
const decision = classifyDecisionAnswers(request, result, minConfidence);
|
|
5951
5979
|
return Object.entries(request.rules).flatMap(([id, rule]) => {
|
|
5952
5980
|
const answer = result.answers[id];
|
|
5953
5981
|
if (answer === void 0) throw new Error("Decision answer missing");
|
|
5954
|
-
return (
|
|
5982
|
+
return (decision.kind === "block" ? rule === decision.rule : decision.kind === "uncertain" && (answer.choice !== "allow" || answer.confidence < minConfidence || answer.probabilities.allow < minConfidence)) ? [{
|
|
5955
5983
|
rule: rule.source === "shipped" ? rule.name : id,
|
|
5956
5984
|
source: rule.source,
|
|
5957
5985
|
tier: rule.tier,
|
|
@@ -6041,206 +6069,583 @@ function parseReference(content, prefix) {
|
|
|
6041
6069
|
return branch !== "" && branch.length <= 256 && !/\s/u.test(branch) ? branch : null;
|
|
6042
6070
|
}
|
|
6043
6071
|
//#endregion
|
|
6044
|
-
//#region
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
};
|
|
6055
|
-
}
|
|
6056
|
-
for (const [id] of entries) {
|
|
6057
|
-
const answer = result.answers[id];
|
|
6058
|
-
if (answer === void 0) throw new Error("Decision answer missing");
|
|
6059
|
-
if (answer.choice !== "allow" || answer.confidence < minConfidence || answer.probabilities.allow < minConfidence) return { kind: "ask" };
|
|
6060
|
-
}
|
|
6061
|
-
return { kind: "allow" };
|
|
6062
|
-
}
|
|
6063
|
-
//#endregion
|
|
6064
|
-
//#region src/model/send-decision.ts
|
|
6065
|
-
async function sendDecision(provider, apiKey, request, signal) {
|
|
6066
|
-
const input = {
|
|
6067
|
-
model: provider.model,
|
|
6068
|
-
state: { ...request.state },
|
|
6069
|
-
questions: request.questions
|
|
6070
|
-
};
|
|
6071
|
-
let body = JSON.stringify(input);
|
|
6072
|
-
for (const field of ["delegatedTask", "originalUserTask"]) {
|
|
6073
|
-
const context = input.state.taskContext;
|
|
6074
|
-
if (Buffer.byteLength(body) <= 1e5 || context === void 0 || context[field] === null) continue;
|
|
6075
|
-
input.state.taskContext = {
|
|
6076
|
-
...context,
|
|
6077
|
-
[field]: null,
|
|
6078
|
-
omittedTaskContext: [...context.omittedTaskContext.filter((item) => item.field !== field), {
|
|
6079
|
-
field,
|
|
6080
|
-
reason: "budget"
|
|
6081
|
-
}]
|
|
6082
|
-
};
|
|
6083
|
-
body = JSON.stringify(input);
|
|
6072
|
+
//#region node_modules/.bun/ts-pattern@5.9.0/node_modules/ts-pattern/dist/index.js
|
|
6073
|
+
const t = Symbol.for("@ts-pattern/matcher");
|
|
6074
|
+
const e = Symbol.for("@ts-pattern/isVariadic");
|
|
6075
|
+
const n = "@ts-pattern/anonymous-select-key";
|
|
6076
|
+
const r = (t) => Boolean(t && "object" == typeof t);
|
|
6077
|
+
const i = (e) => e && !!e[t];
|
|
6078
|
+
const o = (n, s, c) => {
|
|
6079
|
+
if (i(n)) {
|
|
6080
|
+
const { matched: r, selections: i } = n[t]().match(s);
|
|
6081
|
+
return r && i && Object.keys(i).forEach((t) => c(t, i[t])), r;
|
|
6084
6082
|
}
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
signal: controller.signal,
|
|
6102
|
-
headers: {
|
|
6103
|
-
"content-type": "application/json",
|
|
6104
|
-
authorization: `Bearer ${apiKey}`
|
|
6105
|
-
},
|
|
6106
|
-
body
|
|
6107
|
-
});
|
|
6108
|
-
} catch (error) {
|
|
6109
|
-
if (error instanceof Error && error.name === "AbortError") throw new DecisionRequestError("aborted", requestBytes, "Decision request aborted", { cause: error });
|
|
6110
|
-
throw new DecisionRequestError("network", requestBytes, "Decision API request failed");
|
|
6083
|
+
if (r(n)) {
|
|
6084
|
+
if (!r(s)) return !1;
|
|
6085
|
+
if (Array.isArray(n)) {
|
|
6086
|
+
if (!Array.isArray(s)) return !1;
|
|
6087
|
+
let t = [], r = [], u = [];
|
|
6088
|
+
for (const o of n.keys()) {
|
|
6089
|
+
const s = n[o];
|
|
6090
|
+
i(s) && s[e] ? u.push(s) : u.length ? r.push(s) : t.push(s);
|
|
6091
|
+
}
|
|
6092
|
+
if (u.length) {
|
|
6093
|
+
if (u.length > 1) throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");
|
|
6094
|
+
if (s.length < t.length + r.length) return !1;
|
|
6095
|
+
const e = s.slice(0, t.length), n = 0 === r.length ? [] : s.slice(-r.length), i = s.slice(t.length, 0 === r.length ? Infinity : -r.length);
|
|
6096
|
+
return t.every((t, n) => o(t, e[n], c)) && r.every((t, e) => o(t, n[e], c)) && (0 === u.length || o(u[0], i, c));
|
|
6097
|
+
}
|
|
6098
|
+
return n.length === s.length && n.every((t, e) => o(t, s[e], c));
|
|
6111
6099
|
}
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
choice: _enum([
|
|
6117
|
-
"allow",
|
|
6118
|
-
"block",
|
|
6119
|
-
"ask"
|
|
6120
|
-
]),
|
|
6121
|
-
confidence: probability,
|
|
6122
|
-
probabilities: strictObject({
|
|
6123
|
-
allow: probability,
|
|
6124
|
-
block: probability,
|
|
6125
|
-
ask: probability
|
|
6126
|
-
})
|
|
6127
|
-
});
|
|
6128
|
-
const schema = object({
|
|
6129
|
-
model: string().min(1),
|
|
6130
|
-
answers: record(string(), answer),
|
|
6131
|
-
usage: object({ input_tokens: number().int().nonnegative() })
|
|
6100
|
+
return Reflect.ownKeys(n).every((e) => {
|
|
6101
|
+
const r = n[e];
|
|
6102
|
+
return (e in s || i(u = r) && "optional" === u[t]().matcherType) && o(r, s[e], c);
|
|
6103
|
+
var u;
|
|
6132
6104
|
});
|
|
6133
|
-
let responseBody;
|
|
6134
|
-
try {
|
|
6135
|
-
responseBody = await response.json();
|
|
6136
|
-
} catch (error) {
|
|
6137
|
-
if (error instanceof Error && error.name === "AbortError") throw new DecisionRequestError("aborted", requestBytes, "Decision request aborted", { cause: error });
|
|
6138
|
-
throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned invalid JSON");
|
|
6139
|
-
}
|
|
6140
|
-
const parsedResponse = schema.safeParse(responseBody);
|
|
6141
|
-
if (!parsedResponse.success) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned a malformed response");
|
|
6142
|
-
const parsed = parsedResponse.data;
|
|
6143
|
-
if (Object.keys(parsed.answers).length !== Object.keys(request.questions).length) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned an incomplete answer set");
|
|
6144
|
-
for (const id of Object.keys(request.questions)) {
|
|
6145
|
-
const value = parsed.answers[id];
|
|
6146
|
-
if (value === void 0) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API omitted a requested answer");
|
|
6147
|
-
const distribution = Object.values(value.probabilities);
|
|
6148
|
-
if (Math.abs(distribution.reduce((sum, p) => sum + p, 0) - 1) > .010000001 || value.probabilities[value.choice] < Math.max(...distribution)) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned invalid probabilities");
|
|
6149
|
-
}
|
|
6150
|
-
return {
|
|
6151
|
-
model: parsed.model,
|
|
6152
|
-
answers: parsed.answers,
|
|
6153
|
-
inputTokens: parsed.usage.input_tokens,
|
|
6154
|
-
requestBytes
|
|
6155
|
-
};
|
|
6156
|
-
} finally {
|
|
6157
|
-
clearTimeout(timer);
|
|
6158
|
-
signal?.removeEventListener("abort", stopRequest);
|
|
6159
6105
|
}
|
|
6106
|
+
return Object.is(s, n);
|
|
6107
|
+
};
|
|
6108
|
+
const s = (e) => {
|
|
6109
|
+
var n, o, u;
|
|
6110
|
+
return r(e) ? i(e) ? null != (n = null == (o = (u = e[t]()).getSelectionKeys) ? void 0 : o.call(u)) ? n : [] : Array.isArray(e) ? c(e, s) : c(Object.values(e), s) : [];
|
|
6111
|
+
};
|
|
6112
|
+
const c = (t, e) => t.reduce((t, n) => t.concat(e(n)), []);
|
|
6113
|
+
function a(t) {
|
|
6114
|
+
return Object.assign(t, {
|
|
6115
|
+
optional: () => h(t),
|
|
6116
|
+
and: (e) => d(t, e),
|
|
6117
|
+
or: (e) => y(t, e),
|
|
6118
|
+
select: (e) => void 0 === e ? v(t) : v(e, t)
|
|
6119
|
+
});
|
|
6160
6120
|
}
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6121
|
+
function h(e) {
|
|
6122
|
+
return a({ [t]: () => ({
|
|
6123
|
+
match: (t) => {
|
|
6124
|
+
let n = {};
|
|
6125
|
+
const r = (t, e) => {
|
|
6126
|
+
n[t] = e;
|
|
6127
|
+
};
|
|
6128
|
+
return void 0 === t ? (s(e).forEach((t) => r(t, void 0)), {
|
|
6129
|
+
matched: !0,
|
|
6130
|
+
selections: n
|
|
6131
|
+
}) : {
|
|
6132
|
+
matched: o(e, t, r),
|
|
6133
|
+
selections: n
|
|
6134
|
+
};
|
|
6135
|
+
},
|
|
6136
|
+
getSelectionKeys: () => s(e),
|
|
6137
|
+
matcherType: "optional"
|
|
6138
|
+
}) });
|
|
6139
|
+
}
|
|
6140
|
+
function d(...e) {
|
|
6141
|
+
return a({ [t]: () => ({
|
|
6142
|
+
match: (t) => {
|
|
6143
|
+
let n = {};
|
|
6144
|
+
const r = (t, e) => {
|
|
6145
|
+
n[t] = e;
|
|
6146
|
+
};
|
|
6147
|
+
return {
|
|
6148
|
+
matched: e.every((e) => o(e, t, r)),
|
|
6149
|
+
selections: n
|
|
6150
|
+
};
|
|
6151
|
+
},
|
|
6152
|
+
getSelectionKeys: () => c(e, s),
|
|
6153
|
+
matcherType: "and"
|
|
6154
|
+
}) });
|
|
6155
|
+
}
|
|
6156
|
+
function y(...e) {
|
|
6157
|
+
return a({ [t]: () => ({
|
|
6158
|
+
match: (t) => {
|
|
6159
|
+
let n = {};
|
|
6160
|
+
const r = (t, e) => {
|
|
6161
|
+
n[t] = e;
|
|
6162
|
+
};
|
|
6163
|
+
return c(e, s).forEach((t) => r(t, void 0)), {
|
|
6164
|
+
matched: e.some((e) => o(e, t, r)),
|
|
6165
|
+
selections: n
|
|
6166
|
+
};
|
|
6167
|
+
},
|
|
6168
|
+
getSelectionKeys: () => c(e, s),
|
|
6169
|
+
matcherType: "or"
|
|
6170
|
+
}) });
|
|
6171
|
+
}
|
|
6172
|
+
function p(e) {
|
|
6173
|
+
return { [t]: () => ({ match: (t) => ({ matched: Boolean(e(t)) }) }) };
|
|
6174
|
+
}
|
|
6175
|
+
function v(...e) {
|
|
6176
|
+
const r = "string" == typeof e[0] ? e[0] : void 0, i = 2 === e.length ? e[1] : "string" == typeof e[0] ? void 0 : e[0];
|
|
6177
|
+
return a({ [t]: () => ({
|
|
6178
|
+
match: (t) => {
|
|
6179
|
+
let e = { [null != r ? r : n]: t };
|
|
6180
|
+
return {
|
|
6181
|
+
matched: void 0 === i || o(i, t, (t, n) => {
|
|
6182
|
+
e[t] = n;
|
|
6183
|
+
}),
|
|
6184
|
+
selections: e
|
|
6185
|
+
};
|
|
6186
|
+
},
|
|
6187
|
+
getSelectionKeys: () => [null != r ? r : n].concat(void 0 === i ? [] : s(i))
|
|
6188
|
+
}) });
|
|
6189
|
+
}
|
|
6190
|
+
function b(t) {
|
|
6191
|
+
return !0;
|
|
6192
|
+
}
|
|
6193
|
+
function w(t) {
|
|
6194
|
+
return "number" == typeof t;
|
|
6195
|
+
}
|
|
6196
|
+
function S(t) {
|
|
6197
|
+
return "string" == typeof t;
|
|
6198
|
+
}
|
|
6199
|
+
function j(t) {
|
|
6200
|
+
return "bigint" == typeof t;
|
|
6201
|
+
}
|
|
6202
|
+
a(p(b));
|
|
6203
|
+
a(p(b));
|
|
6204
|
+
const x = (t) => Object.assign(a(t), {
|
|
6205
|
+
startsWith: (e) => {
|
|
6206
|
+
return x(d(t, (n = e, p((t) => S(t) && t.startsWith(n)))));
|
|
6207
|
+
var n;
|
|
6208
|
+
},
|
|
6209
|
+
endsWith: (e) => {
|
|
6210
|
+
return x(d(t, (n = e, p((t) => S(t) && t.endsWith(n)))));
|
|
6211
|
+
var n;
|
|
6212
|
+
},
|
|
6213
|
+
minLength: (e) => x(d(t, ((t) => p((e) => S(e) && e.length >= t))(e))),
|
|
6214
|
+
length: (e) => x(d(t, ((t) => p((e) => S(e) && e.length === t))(e))),
|
|
6215
|
+
maxLength: (e) => x(d(t, ((t) => p((e) => S(e) && e.length <= t))(e))),
|
|
6216
|
+
includes: (e) => {
|
|
6217
|
+
return x(d(t, (n = e, p((t) => S(t) && t.includes(n)))));
|
|
6218
|
+
var n;
|
|
6219
|
+
},
|
|
6220
|
+
regex: (e) => {
|
|
6221
|
+
return x(d(t, (n = e, p((t) => S(t) && Boolean(t.match(n))))));
|
|
6222
|
+
var n;
|
|
6223
|
+
}
|
|
6224
|
+
});
|
|
6225
|
+
x(p(S));
|
|
6226
|
+
const N = (t) => Object.assign(a(t), {
|
|
6227
|
+
between: (e, n) => N(d(t, ((t, e) => p((n) => w(n) && t <= n && e >= n))(e, n))),
|
|
6228
|
+
lt: (e) => N(d(t, ((t) => p((e) => w(e) && e < t))(e))),
|
|
6229
|
+
gt: (e) => N(d(t, ((t) => p((e) => w(e) && e > t))(e))),
|
|
6230
|
+
lte: (e) => N(d(t, ((t) => p((e) => w(e) && e <= t))(e))),
|
|
6231
|
+
gte: (e) => N(d(t, ((t) => p((e) => w(e) && e >= t))(e))),
|
|
6232
|
+
int: () => N(d(t, p((t) => w(t) && Number.isInteger(t)))),
|
|
6233
|
+
finite: () => N(d(t, p((t) => w(t) && Number.isFinite(t)))),
|
|
6234
|
+
positive: () => N(d(t, p((t) => w(t) && t > 0))),
|
|
6235
|
+
negative: () => N(d(t, p((t) => w(t) && t < 0)))
|
|
6236
|
+
});
|
|
6237
|
+
N(p(w));
|
|
6238
|
+
const k = (t) => Object.assign(a(t), {
|
|
6239
|
+
between: (e, n) => k(d(t, ((t, e) => p((n) => j(n) && t <= n && e >= n))(e, n))),
|
|
6240
|
+
lt: (e) => k(d(t, ((t) => p((e) => j(e) && e < t))(e))),
|
|
6241
|
+
gt: (e) => k(d(t, ((t) => p((e) => j(e) && e > t))(e))),
|
|
6242
|
+
lte: (e) => k(d(t, ((t) => p((e) => j(e) && e <= t))(e))),
|
|
6243
|
+
gte: (e) => k(d(t, ((t) => p((e) => j(e) && e >= t))(e))),
|
|
6244
|
+
positive: () => k(d(t, p((t) => j(t) && t > 0))),
|
|
6245
|
+
negative: () => k(d(t, p((t) => j(t) && t < 0)))
|
|
6246
|
+
});
|
|
6247
|
+
k(p(j)), a(p(function(t) {
|
|
6248
|
+
return "boolean" == typeof t;
|
|
6249
|
+
})), a(p(function(t) {
|
|
6250
|
+
return "symbol" == typeof t;
|
|
6251
|
+
})), a(p(function(t) {
|
|
6252
|
+
return null == t;
|
|
6253
|
+
})), a(p(function(t) {
|
|
6254
|
+
return null != t;
|
|
6255
|
+
}));
|
|
6256
|
+
var I = class extends Error {
|
|
6257
|
+
constructor(t) {
|
|
6258
|
+
let e;
|
|
6259
|
+
try {
|
|
6260
|
+
e = JSON.stringify(t);
|
|
6261
|
+
} catch (n) {
|
|
6262
|
+
e = t;
|
|
6263
|
+
}
|
|
6264
|
+
super(`Pattern matching error: no pattern matches value ${e}`), this.input = void 0, this.input = t;
|
|
6265
|
+
}
|
|
6266
|
+
};
|
|
6267
|
+
const L = {
|
|
6268
|
+
matched: !1,
|
|
6269
|
+
value: void 0
|
|
6270
|
+
};
|
|
6271
|
+
function M(t) {
|
|
6272
|
+
return new R(t, L);
|
|
6273
|
+
}
|
|
6274
|
+
var R = class R {
|
|
6275
|
+
constructor(t, e) {
|
|
6276
|
+
this.input = void 0, this.state = void 0, this.input = t, this.state = e;
|
|
6277
|
+
}
|
|
6278
|
+
with(...t) {
|
|
6279
|
+
if (this.state.matched) return this;
|
|
6280
|
+
const e = t[t.length - 1], r = [t[0]];
|
|
6281
|
+
let i;
|
|
6282
|
+
3 === t.length && "function" == typeof t[1] ? i = t[1] : t.length > 2 && r.push(...t.slice(1, t.length - 1));
|
|
6283
|
+
let s = !1, c = {};
|
|
6284
|
+
const u = (t, e) => {
|
|
6285
|
+
s = !0, c[t] = e;
|
|
6286
|
+
}, a = !r.some((t) => o(t, this.input, u)) || i && !Boolean(i(this.input)) ? L : {
|
|
6287
|
+
matched: !0,
|
|
6288
|
+
value: e(s ? n in c ? c[n] : c : this.input, this.input)
|
|
6289
|
+
};
|
|
6290
|
+
return new R(this.input, a);
|
|
6291
|
+
}
|
|
6292
|
+
when(t, e) {
|
|
6293
|
+
if (this.state.matched) return this;
|
|
6294
|
+
const n = Boolean(t(this.input));
|
|
6295
|
+
return new R(this.input, n ? {
|
|
6296
|
+
matched: !0,
|
|
6297
|
+
value: e(this.input, this.input)
|
|
6298
|
+
} : L);
|
|
6299
|
+
}
|
|
6300
|
+
otherwise(t) {
|
|
6301
|
+
return this.state.matched ? this.state.value : t(this.input);
|
|
6302
|
+
}
|
|
6303
|
+
exhaustive(t = F) {
|
|
6304
|
+
return this.state.matched ? this.state.value : t(this.input);
|
|
6305
|
+
}
|
|
6306
|
+
run() {
|
|
6307
|
+
return this.exhaustive();
|
|
6308
|
+
}
|
|
6309
|
+
returnType() {
|
|
6310
|
+
return this;
|
|
6311
|
+
}
|
|
6312
|
+
narrow() {
|
|
6313
|
+
return this;
|
|
6314
|
+
}
|
|
6315
|
+
};
|
|
6316
|
+
function F(t) {
|
|
6317
|
+
throw new I(t);
|
|
6318
|
+
}
|
|
6319
|
+
//#endregion
|
|
6320
|
+
//#region src/policy/deny-reasons.ts
|
|
6321
|
+
const DENY_REASONS = {
|
|
6322
|
+
"Data Exfiltration": {
|
|
6323
|
+
tier: "hard",
|
|
6324
|
+
harm: "sending sensitive data, such as credentials or private code, off the machine",
|
|
6325
|
+
clears: "No instruction or configuration clears this rule."
|
|
6326
|
+
},
|
|
6327
|
+
"Secret Persistence": {
|
|
6328
|
+
tier: "hard",
|
|
6329
|
+
harm: "writing a credential in plain text into a tracked file, an image, CI configuration, or a shipped log",
|
|
6330
|
+
clears: "No instruction or configuration clears this rule."
|
|
6331
|
+
},
|
|
6332
|
+
"Policy Tampering": {
|
|
6333
|
+
tier: "hard",
|
|
6334
|
+
harm: "changing auto-mode's own configuration, policy, or hook, or the settings that decide whether it runs",
|
|
6335
|
+
clears: "Only a direct user message that explains why this match is wrong clears it; bare consent does not."
|
|
6336
|
+
},
|
|
6337
|
+
"Audit Tampering": {
|
|
6338
|
+
tier: "hard",
|
|
6339
|
+
harm: "deleting or rewriting logs, shell history, audit records, or git history to hide what happened",
|
|
6340
|
+
clears: "Only a direct user message that explains why this match is wrong clears it; bare consent does not."
|
|
6341
|
+
},
|
|
6342
|
+
"Destructive Payload": {
|
|
6343
|
+
tier: "hard",
|
|
6344
|
+
harm: "writing or running code whose purpose is damage or spread",
|
|
6345
|
+
clears: "No instruction or configuration clears this rule."
|
|
6346
|
+
},
|
|
6347
|
+
"Irreversible Deletion": {
|
|
6348
|
+
tier: "soft",
|
|
6349
|
+
harm: "deleting data that no backup, remote, or build step can restore",
|
|
6350
|
+
clears: "A direct user instruction that asks for this deletion and names the path clears it."
|
|
6351
|
+
},
|
|
6352
|
+
"Uncommitted Work Destruction": {
|
|
6353
|
+
tier: "soft",
|
|
6354
|
+
harm: "discarding working-tree changes that exist nowhere else",
|
|
6355
|
+
clears: "A direct user instruction that says those changes go away clears it."
|
|
6356
|
+
},
|
|
6357
|
+
"History Rewrite": {
|
|
6358
|
+
tier: "soft",
|
|
6359
|
+
harm: "rewriting history that others may already hold",
|
|
6360
|
+
clears: "A direct user instruction that names the force push, the rewrite, or the remote branch clears it."
|
|
6361
|
+
},
|
|
6362
|
+
"Default Branch Write": {
|
|
6363
|
+
tier: "soft",
|
|
6364
|
+
harm: "committing, pushing, or merging directly to the default branch",
|
|
6365
|
+
clears: "A direct user instruction that names the branch clears it."
|
|
6366
|
+
},
|
|
6367
|
+
"Publish and Release": {
|
|
6368
|
+
tier: "soft",
|
|
6369
|
+
harm: "putting an artifact where other people install it",
|
|
6370
|
+
clears: "A direct user instruction that says publish, release, or deploy and names the target clears it."
|
|
6371
|
+
},
|
|
6372
|
+
"Outbound Communication": {
|
|
6373
|
+
tier: "soft",
|
|
6374
|
+
harm: "sending content that reaches another person",
|
|
6375
|
+
clears: "A direct user instruction that says the message is sent, and to whom or where, clears it."
|
|
6376
|
+
},
|
|
6377
|
+
"Remote Code Execution": {
|
|
6378
|
+
tier: "soft",
|
|
6379
|
+
harm: "running code fetched from a source the user did not name",
|
|
6380
|
+
clears: "A direct user instruction that names the source clears it."
|
|
6381
|
+
},
|
|
6382
|
+
"Obfuscated Command": {
|
|
6383
|
+
tier: "soft",
|
|
6384
|
+
harm: "running a command whose payload cannot be read",
|
|
6385
|
+
clears: "A direct user message that supplies the decoded command or states what it runs clears it."
|
|
6386
|
+
},
|
|
6387
|
+
"Network Exposure": {
|
|
6388
|
+
tier: "soft",
|
|
6389
|
+
harm: "making this machine or its files reachable from outside it",
|
|
6390
|
+
clears: "A direct user instruction that names the service and says it becomes reachable clears it."
|
|
6391
|
+
},
|
|
6392
|
+
"Unnamed Destination": {
|
|
6393
|
+
tier: "soft",
|
|
6394
|
+
harm: "sending content to a network destination the user never named",
|
|
6395
|
+
clears: "A direct user instruction that names the destination clears it."
|
|
6396
|
+
},
|
|
6397
|
+
"Shared Infrastructure": {
|
|
6398
|
+
tier: "soft",
|
|
6399
|
+
harm: "changing a cluster, a cloud account, a remote host, or a repository's settings",
|
|
6400
|
+
clears: "A direct user instruction that names the environment or the resource clears it."
|
|
6401
|
+
},
|
|
6402
|
+
"Destructive Database Operation": {
|
|
6403
|
+
tier: "soft",
|
|
6404
|
+
harm: "deleting or overwriting stored data wholesale in a database that is not local",
|
|
6405
|
+
clears: "A direct user instruction that names the table or the database, and the operation, clears it."
|
|
6406
|
+
},
|
|
6407
|
+
"Persistent Configuration": {
|
|
6408
|
+
tier: "soft",
|
|
6409
|
+
harm: "a change that outlives the session or widens access on this machine",
|
|
6410
|
+
clears: "A direct user instruction that names the file or the setting clears it."
|
|
6411
|
+
},
|
|
6412
|
+
"Credential Exploration": {
|
|
6413
|
+
tier: "soft",
|
|
6414
|
+
harm: "reading or searching for credentials the task never called for",
|
|
6415
|
+
clears: "A direct user instruction that names the file or the search clears it."
|
|
6416
|
+
},
|
|
6417
|
+
"Interrupted Action Retry": {
|
|
6418
|
+
tier: "soft",
|
|
6419
|
+
harm: "running again an action the user interrupted",
|
|
6420
|
+
clears: "A direct user instruction that asks for the action to run again clears it."
|
|
6421
|
+
},
|
|
6422
|
+
"Security Control Removal": {
|
|
6423
|
+
tier: "soft",
|
|
6424
|
+
harm: "removing a control that protects someone other than the agent",
|
|
6425
|
+
clears: "A direct user instruction that names the control clears it."
|
|
6426
|
+
},
|
|
6427
|
+
"Mass Modification": {
|
|
6428
|
+
tier: "soft",
|
|
6429
|
+
harm: "changing many things at once with no way to restore them",
|
|
6430
|
+
clears: "A direct user instruction that names the scope clears it."
|
|
6431
|
+
}
|
|
6432
|
+
};
|
|
6433
|
+
//#endregion
|
|
6434
|
+
//#region src/policy/build-deny-reason.ts
|
|
6435
|
+
function buildDenyReason(rule, basis) {
|
|
6436
|
+
const template = getReasonTemplate(rule);
|
|
6437
|
+
return `${basis === "matched" ? `The action matches this rule: ${template.harm}.` : `The supplied evidence cannot rule out ${template.harm}.`} ${template.clears}`;
|
|
6438
|
+
}
|
|
6439
|
+
function getReasonTemplate(rule) {
|
|
6440
|
+
return M(rule.source).with("shipped", () => {
|
|
6441
|
+
const template = DENY_REASONS[rule.name];
|
|
6442
|
+
if (template === void 0) throw new Error(`No deny reason for the shipped rule ${rule.name}`);
|
|
6443
|
+
return template;
|
|
6444
|
+
}).with("configured", () => rule.tier === "hard" ? {
|
|
6445
|
+
harm: "an action that a hard deny entry in the user's auto-mode configuration covers",
|
|
6446
|
+
clears: "Only a change to that configuration clears it."
|
|
6447
|
+
} : {
|
|
6448
|
+
harm: "an action that a soft deny entry in the user's auto-mode configuration covers",
|
|
6449
|
+
clears: "A direct user instruction that asks for this specific action clears it."
|
|
6450
|
+
}).with("replacement", () => ({
|
|
6451
|
+
harm: "the harm this rule of the configured replacement policy describes",
|
|
6452
|
+
clears: "The replacement policy defines what clears it."
|
|
6453
|
+
})).exhaustive();
|
|
6454
|
+
}
|
|
6455
|
+
//#endregion
|
|
6456
|
+
//#region src/model/pick-decision-verdict.ts
|
|
6457
|
+
function pickDecisionVerdict(request, result, minConfidence) {
|
|
6458
|
+
return M(classifyDecisionAnswers(request, result, minConfidence)).with({ kind: "allow" }, () => ({ kind: "allow" })).with({ kind: "block" }, (decision) => ({
|
|
6459
|
+
kind: "deny",
|
|
6460
|
+
rule: decision.rule.name,
|
|
6461
|
+
reason: buildDenyReason(decision.rule, "matched")
|
|
6462
|
+
})).with({ kind: "uncertain" }, (decision) => ({
|
|
6463
|
+
kind: "deny",
|
|
6464
|
+
rule: decision.rule.name,
|
|
6465
|
+
reason: buildDenyReason(decision.rule, "unresolved")
|
|
6466
|
+
})).exhaustive();
|
|
6467
|
+
}
|
|
6468
|
+
//#endregion
|
|
6469
|
+
//#region src/model/send-decision.ts
|
|
6470
|
+
async function sendDecision(provider, apiKey, request, signal) {
|
|
6471
|
+
const input = {
|
|
6472
|
+
model: provider.model,
|
|
6473
|
+
state: { ...request.state },
|
|
6474
|
+
questions: request.questions
|
|
6475
|
+
};
|
|
6476
|
+
let body = JSON.stringify(input);
|
|
6477
|
+
for (const field of ["delegatedTask", "originalUserTask"]) {
|
|
6478
|
+
const context = input.state.taskContext;
|
|
6479
|
+
if (Buffer.byteLength(body) <= 1e5 || context === void 0 || context[field] === null) continue;
|
|
6480
|
+
input.state.taskContext = {
|
|
6481
|
+
...context,
|
|
6482
|
+
[field]: null,
|
|
6483
|
+
omittedTaskContext: [...context.omittedTaskContext.filter((item) => item.field !== field), {
|
|
6484
|
+
field,
|
|
6485
|
+
reason: "budget"
|
|
6486
|
+
}]
|
|
6487
|
+
};
|
|
6488
|
+
body = JSON.stringify(input);
|
|
6489
|
+
}
|
|
6490
|
+
const requestBytes = Buffer.byteLength(body);
|
|
6491
|
+
if (requestBytes > 1e5) throw new DecisionRequestError("request-too-large", requestBytes, "Decision input exceeds 100000 bytes; refusing to truncate the action or user message");
|
|
6492
|
+
const controller = new AbortController();
|
|
6493
|
+
const stopRequest = () => {
|
|
6494
|
+
controller.abort();
|
|
6495
|
+
};
|
|
6496
|
+
signal?.addEventListener("abort", stopRequest, { once: true });
|
|
6497
|
+
if (signal?.aborted === true) controller.abort();
|
|
6498
|
+
const timer = setTimeout(() => {
|
|
6499
|
+
controller.abort();
|
|
6500
|
+
}, provider.timeoutMs);
|
|
6501
|
+
try {
|
|
6502
|
+
let response;
|
|
6503
|
+
try {
|
|
6504
|
+
response = await fetch(`${provider.baseURL.replace(/\/$/, "")}/v1/systemone`, {
|
|
6505
|
+
method: "POST",
|
|
6506
|
+
signal: controller.signal,
|
|
6507
|
+
headers: {
|
|
6508
|
+
"content-type": "application/json",
|
|
6509
|
+
authorization: `Bearer ${apiKey}`
|
|
6510
|
+
},
|
|
6511
|
+
body
|
|
6512
|
+
});
|
|
6513
|
+
} catch (error) {
|
|
6514
|
+
if (error instanceof Error && error.name === "AbortError") throw new DecisionRequestError("aborted", requestBytes, "Decision request aborted", { cause: error });
|
|
6515
|
+
throw new DecisionRequestError("network", requestBytes, "Decision API request failed");
|
|
6516
|
+
}
|
|
6517
|
+
if (!response.ok) throw new DecisionRequestError("http-status", requestBytes, `Decision API returned HTTP ${response.status}`);
|
|
6518
|
+
const probability = number().min(0).max(1);
|
|
6519
|
+
const answer = object({
|
|
6520
|
+
type: literal("choice"),
|
|
6521
|
+
choice: _enum([
|
|
6522
|
+
"allow",
|
|
6523
|
+
"block",
|
|
6524
|
+
"ask"
|
|
6525
|
+
]),
|
|
6526
|
+
confidence: probability,
|
|
6527
|
+
probabilities: strictObject({
|
|
6528
|
+
allow: probability,
|
|
6529
|
+
block: probability,
|
|
6530
|
+
ask: probability
|
|
6531
|
+
})
|
|
6532
|
+
});
|
|
6533
|
+
const schema = object({
|
|
6534
|
+
model: string().min(1),
|
|
6535
|
+
answers: record(string(), answer),
|
|
6536
|
+
usage: object({ input_tokens: number().int().nonnegative() })
|
|
6537
|
+
});
|
|
6538
|
+
let responseBody;
|
|
6539
|
+
try {
|
|
6540
|
+
responseBody = await response.json();
|
|
6541
|
+
} catch (error) {
|
|
6542
|
+
if (error instanceof Error && error.name === "AbortError") throw new DecisionRequestError("aborted", requestBytes, "Decision request aborted", { cause: error });
|
|
6543
|
+
throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned invalid JSON");
|
|
6544
|
+
}
|
|
6545
|
+
const parsedResponse = schema.safeParse(responseBody);
|
|
6546
|
+
if (!parsedResponse.success) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned a malformed response");
|
|
6547
|
+
const parsed = parsedResponse.data;
|
|
6548
|
+
if (Object.keys(parsed.answers).length !== Object.keys(request.questions).length) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned an incomplete answer set");
|
|
6549
|
+
for (const id of Object.keys(request.questions)) {
|
|
6550
|
+
const value = parsed.answers[id];
|
|
6551
|
+
if (value === void 0) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API omitted a requested answer");
|
|
6552
|
+
const distribution = Object.values(value.probabilities);
|
|
6553
|
+
if (Math.abs(distribution.reduce((sum, p) => sum + p, 0) - 1) > .010000001 || value.probabilities[value.choice] < Math.max(...distribution)) throw new DecisionRequestError("invalid-response", requestBytes, "Decision API returned invalid probabilities");
|
|
6554
|
+
}
|
|
6555
|
+
return {
|
|
6556
|
+
model: parsed.model,
|
|
6557
|
+
answers: parsed.answers,
|
|
6558
|
+
inputTokens: parsed.usage.input_tokens,
|
|
6559
|
+
requestBytes
|
|
6560
|
+
};
|
|
6561
|
+
} finally {
|
|
6562
|
+
clearTimeout(timer);
|
|
6563
|
+
signal?.removeEventListener("abort", stopRequest);
|
|
6564
|
+
}
|
|
6565
|
+
}
|
|
6566
|
+
//#endregion
|
|
6567
|
+
//#region src/model/classify-with-jev.ts
|
|
6568
|
+
async function classifyWithJev(payload, config, options = {}) {
|
|
6569
|
+
const start = performance.now();
|
|
6570
|
+
let key = null;
|
|
6571
|
+
let stage = "credential";
|
|
6572
|
+
const minConfidence = config.minConfidence ?? .8;
|
|
6573
|
+
let keySource = "none";
|
|
6574
|
+
const envKey = config.provider.apiKeyEnv === void 0 ? void 0 : process.env[config.provider.apiKeyEnv];
|
|
6575
|
+
if (envKey !== void 0 && envKey !== "") keySource = "environment";
|
|
6576
|
+
else if (config.provider.apiKeyCommand !== void 0 && config.provider.apiKeyCommand !== "") keySource = "command";
|
|
6577
|
+
try {
|
|
6578
|
+
key = await resolveApiKey(config.provider, options);
|
|
6579
|
+
if (key === null) throw new Error("no API key: set the configured environment variable or key command");
|
|
6580
|
+
stage = "evidence";
|
|
6581
|
+
const directUserText = payload.decisionContext?.agentID === null ? payload.decisionContext.lastDirectUserMessage?.text ?? null : null;
|
|
6582
|
+
const command = payload.toolInput["command"] ?? payload.toolInput["cmd"];
|
|
6583
|
+
const hasGitCommand = typeof command === "string" && /\bgit\s/u.test(command);
|
|
6584
|
+
const isFileEdit = payload.toolName === "Write" || payload.toolName === "Edit";
|
|
6585
|
+
const needsRepositoryContext = hasGitCommand || isFileEdit;
|
|
6586
|
+
const [policy, rules, repositoryContext] = await Promise.all([
|
|
6587
|
+
loadPolicy({
|
|
6588
|
+
classifierPath: config.classifierPath,
|
|
6589
|
+
rulesPath: config.rulesPath
|
|
6590
|
+
}, "decision.md"),
|
|
6591
|
+
loadClaudeRules(config.claudeSettingsPath),
|
|
6592
|
+
needsRepositoryContext ? loadRepositoryContext(payload.cwd) : Promise.resolve(null)
|
|
6593
|
+
]);
|
|
6594
|
+
const request = buildDecisionRequest(payload, policy, rules, directUserText, config.rulesPath === void 0 ? "shipped" : "replacement", repositoryContext);
|
|
6595
|
+
const remainingMs = options.deadlineAt === void 0 ? config.provider.timeoutMs : options.deadlineAt - Date.now();
|
|
6596
|
+
if (remainingMs <= 0 || options.signal?.aborted === true) throw new DOMException("Evaluation deadline expired", "AbortError");
|
|
6597
|
+
const provider = {
|
|
6598
|
+
...config.provider,
|
|
6599
|
+
timeoutMs: Math.min(config.provider.timeoutMs, remainingMs)
|
|
6600
|
+
};
|
|
6601
|
+
stage = "request";
|
|
6602
|
+
const result = await sendDecision(provider, key, request, options.signal);
|
|
6603
|
+
stage = "response";
|
|
6604
|
+
const verdict = pickDecisionVerdict(request, result, minConfidence);
|
|
6605
|
+
return {
|
|
6606
|
+
verdict,
|
|
6607
|
+
diagnostics: {
|
|
6608
|
+
status: verdict.kind,
|
|
6609
|
+
stage,
|
|
6610
|
+
keyResolved: true,
|
|
6611
|
+
keySource,
|
|
6612
|
+
failureReason: null,
|
|
6613
|
+
requestBytes: result.requestBytes,
|
|
6614
|
+
elapsedMs: Math.round(performance.now() - start),
|
|
6615
|
+
minConfidence,
|
|
6616
|
+
contributors: collectDecisionContributors(request, result, minConfidence)
|
|
6617
|
+
},
|
|
6618
|
+
note: formatClassifierNote(`${config.provider.model}: ${verdict.kind} (${Math.round(performance.now() - start)}ms, ${result.inputTokens} input tokens)`, key)
|
|
6619
|
+
};
|
|
6620
|
+
} catch (error) {
|
|
6621
|
+
let reason = "classifier failed";
|
|
6622
|
+
let status = "failure";
|
|
6623
|
+
if (options.signal?.aborted === true) {
|
|
6624
|
+
reason = "evaluation cancelled";
|
|
6625
|
+
status = "cancelled";
|
|
6626
|
+
} else if (options.deadlineAt !== void 0 && Date.now() >= options.deadlineAt) {
|
|
6627
|
+
reason = "evaluation deadline expired";
|
|
6628
|
+
status = "timeout";
|
|
6629
|
+
} else if (error instanceof Error) {
|
|
6630
|
+
const isTimeout = error.name === "AbortError" || error instanceof DecisionRequestError && error.reason === "aborted";
|
|
6631
|
+
if (isTimeout) status = "timeout";
|
|
6632
|
+
reason = isTimeout ? `timed out after ${config.provider.timeoutMs}ms` : error.message;
|
|
6633
|
+
}
|
|
6634
|
+
const note = formatClassifierNote(`${config.provider.model} unavailable: ${reason}`, key);
|
|
6635
|
+
return {
|
|
6636
|
+
verdict: config.onFailure === "deny" ? {
|
|
6637
|
+
kind: "deny",
|
|
6638
|
+
rule: "Classifier Unavailable",
|
|
6639
|
+
reason: note
|
|
6640
|
+
} : null,
|
|
6641
|
+
note,
|
|
6642
|
+
unavailable: true,
|
|
6643
|
+
diagnostics: {
|
|
6644
|
+
status,
|
|
6645
|
+
stage,
|
|
6646
|
+
keyResolved: key !== null,
|
|
6647
|
+
keySource,
|
|
6648
|
+
failureReason: error instanceof DecisionRequestError ? error.reason : null,
|
|
6244
6649
|
requestBytes: error instanceof DecisionRequestError ? error.requestBytes : null,
|
|
6245
6650
|
elapsedMs: Math.round(performance.now() - start),
|
|
6246
6651
|
minConfidence,
|
|
@@ -6260,10 +6665,20 @@ function parseModelVerdict(text) {
|
|
|
6260
6665
|
const rule = RULE.exec(text)?.[1]?.trim();
|
|
6261
6666
|
if (rule === void 0 || rule === "") return { kind: "allow" };
|
|
6262
6667
|
const stripped = (REASON.exec(text)?.[1]?.trim())?.replace(/^\[[^\]]*\]\s*/, "") ?? "";
|
|
6668
|
+
if (stripped !== "") return {
|
|
6669
|
+
kind: "deny",
|
|
6670
|
+
rule,
|
|
6671
|
+
reason: stripped
|
|
6672
|
+
};
|
|
6673
|
+
const template = DENY_REASONS[rule];
|
|
6263
6674
|
return {
|
|
6264
6675
|
kind: "deny",
|
|
6265
6676
|
rule,
|
|
6266
|
-
reason:
|
|
6677
|
+
reason: template === void 0 ? "The action matches this rule." : buildDenyReason({
|
|
6678
|
+
name: rule,
|
|
6679
|
+
tier: template.tier,
|
|
6680
|
+
source: "shipped"
|
|
6681
|
+
}, "matched")
|
|
6267
6682
|
};
|
|
6268
6683
|
}
|
|
6269
6684
|
//#endregion
|
|
@@ -6321,6 +6736,11 @@ function toMessage(error) {
|
|
|
6321
6736
|
return error instanceof Error ? error.message : String(error);
|
|
6322
6737
|
}
|
|
6323
6738
|
//#endregion
|
|
6739
|
+
//#region src/policy/read-denial-guidance.ts
|
|
6740
|
+
async function readDenialGuidance() {
|
|
6741
|
+
return (await readFile(join(resolveShippedPolicyDir(), "denial.md"), "utf8")).trim();
|
|
6742
|
+
}
|
|
6743
|
+
//#endregion
|
|
6324
6744
|
//#region node_modules/.bun/tiny-invariant@1.3.3/node_modules/tiny-invariant/dist/esm/tiny-invariant.js
|
|
6325
6745
|
var isProduction = process.env.NODE_ENV === "production";
|
|
6326
6746
|
var prefix = "Invariant failed";
|
|
@@ -6557,12 +6977,9 @@ async function classifyAction(request, config, options = {}) {
|
|
|
6557
6977
|
if (config.provider.protocol === "system-one") try {
|
|
6558
6978
|
configured = await loadClaudeRules(config.claudeSettingsPath);
|
|
6559
6979
|
} catch {
|
|
6980
|
+
const guidance = config.onFailure === "deny" ? await tryReadDenialGuidance() : null;
|
|
6560
6981
|
return {
|
|
6561
|
-
verdict: config.onFailure === "deny" ?
|
|
6562
|
-
kind: "deny",
|
|
6563
|
-
rule: "Classifier Unavailable",
|
|
6564
|
-
reason: "Claude settings unreadable"
|
|
6565
|
-
} : null,
|
|
6982
|
+
verdict: config.onFailure === "deny" ? buildGuidedDeny("Classifier Unavailable", "Claude settings unreadable.", guidance) : null,
|
|
6566
6983
|
note: "Claude settings unreadable; classifier unavailable",
|
|
6567
6984
|
status: "failure",
|
|
6568
6985
|
unavailable: true
|
|
@@ -6579,12 +6996,28 @@ async function classifyAction(request, config, options = {}) {
|
|
|
6579
6996
|
note: `${request.toolName} needs the model tier, which this run skipped`,
|
|
6580
6997
|
status: "skipped"
|
|
6581
6998
|
};
|
|
6582
|
-
const outcome = await classifyWithModel(request, config, options);
|
|
6999
|
+
const [outcome, guidance] = await Promise.all([classifyWithModel(request, config, options), tryReadDenialGuidance()]);
|
|
6583
7000
|
return {
|
|
6584
7001
|
...outcome,
|
|
7002
|
+
verdict: outcome.verdict?.kind === "deny" ? buildGuidedDeny(outcome.verdict.rule, outcome.verdict.reason, guidance) : outcome.verdict,
|
|
6585
7003
|
status: outcome.diagnostics?.status ?? outcome.verdict?.kind ?? "failure"
|
|
6586
7004
|
};
|
|
6587
7005
|
}
|
|
7006
|
+
function buildGuidedDeny(rule, reason, guidance) {
|
|
7007
|
+
const sentence = /[.!?]$/u.test(reason) ? reason : `${reason}.`;
|
|
7008
|
+
return {
|
|
7009
|
+
kind: "deny",
|
|
7010
|
+
rule,
|
|
7011
|
+
reason: guidance === null ? sentence : `${sentence} ${guidance}`
|
|
7012
|
+
};
|
|
7013
|
+
}
|
|
7014
|
+
async function tryReadDenialGuidance() {
|
|
7015
|
+
try {
|
|
7016
|
+
return await readDenialGuidance();
|
|
7017
|
+
} catch {
|
|
7018
|
+
return null;
|
|
7019
|
+
}
|
|
7020
|
+
}
|
|
6588
7021
|
//#endregion
|
|
6589
7022
|
//#region src/request/parse-action-request.ts
|
|
6590
7023
|
const userTaskSchema = strictObject({
|
|
@@ -6635,257 +7068,9 @@ function parseActionRequest(body) {
|
|
|
6635
7068
|
};
|
|
6636
7069
|
}
|
|
6637
7070
|
//#endregion
|
|
6638
|
-
//#region node_modules/.bun/ts-pattern@5.9.0/node_modules/ts-pattern/dist/index.js
|
|
6639
|
-
const t = Symbol.for("@ts-pattern/matcher");
|
|
6640
|
-
const e = Symbol.for("@ts-pattern/isVariadic");
|
|
6641
|
-
const n = "@ts-pattern/anonymous-select-key";
|
|
6642
|
-
const r = (t) => Boolean(t && "object" == typeof t);
|
|
6643
|
-
const i = (e) => e && !!e[t];
|
|
6644
|
-
const o = (n, s, c) => {
|
|
6645
|
-
if (i(n)) {
|
|
6646
|
-
const { matched: r, selections: i } = n[t]().match(s);
|
|
6647
|
-
return r && i && Object.keys(i).forEach((t) => c(t, i[t])), r;
|
|
6648
|
-
}
|
|
6649
|
-
if (r(n)) {
|
|
6650
|
-
if (!r(s)) return !1;
|
|
6651
|
-
if (Array.isArray(n)) {
|
|
6652
|
-
if (!Array.isArray(s)) return !1;
|
|
6653
|
-
let t = [], r = [], u = [];
|
|
6654
|
-
for (const o of n.keys()) {
|
|
6655
|
-
const s = n[o];
|
|
6656
|
-
i(s) && s[e] ? u.push(s) : u.length ? r.push(s) : t.push(s);
|
|
6657
|
-
}
|
|
6658
|
-
if (u.length) {
|
|
6659
|
-
if (u.length > 1) throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");
|
|
6660
|
-
if (s.length < t.length + r.length) return !1;
|
|
6661
|
-
const e = s.slice(0, t.length), n = 0 === r.length ? [] : s.slice(-r.length), i = s.slice(t.length, 0 === r.length ? Infinity : -r.length);
|
|
6662
|
-
return t.every((t, n) => o(t, e[n], c)) && r.every((t, e) => o(t, n[e], c)) && (0 === u.length || o(u[0], i, c));
|
|
6663
|
-
}
|
|
6664
|
-
return n.length === s.length && n.every((t, e) => o(t, s[e], c));
|
|
6665
|
-
}
|
|
6666
|
-
return Reflect.ownKeys(n).every((e) => {
|
|
6667
|
-
const r = n[e];
|
|
6668
|
-
return (e in s || i(u = r) && "optional" === u[t]().matcherType) && o(r, s[e], c);
|
|
6669
|
-
var u;
|
|
6670
|
-
});
|
|
6671
|
-
}
|
|
6672
|
-
return Object.is(s, n);
|
|
6673
|
-
};
|
|
6674
|
-
const s = (e) => {
|
|
6675
|
-
var n, o, u;
|
|
6676
|
-
return r(e) ? i(e) ? null != (n = null == (o = (u = e[t]()).getSelectionKeys) ? void 0 : o.call(u)) ? n : [] : Array.isArray(e) ? c(e, s) : c(Object.values(e), s) : [];
|
|
6677
|
-
};
|
|
6678
|
-
const c = (t, e) => t.reduce((t, n) => t.concat(e(n)), []);
|
|
6679
|
-
function a(t) {
|
|
6680
|
-
return Object.assign(t, {
|
|
6681
|
-
optional: () => h(t),
|
|
6682
|
-
and: (e) => d(t, e),
|
|
6683
|
-
or: (e) => y(t, e),
|
|
6684
|
-
select: (e) => void 0 === e ? v(t) : v(e, t)
|
|
6685
|
-
});
|
|
6686
|
-
}
|
|
6687
|
-
function h(e) {
|
|
6688
|
-
return a({ [t]: () => ({
|
|
6689
|
-
match: (t) => {
|
|
6690
|
-
let n = {};
|
|
6691
|
-
const r = (t, e) => {
|
|
6692
|
-
n[t] = e;
|
|
6693
|
-
};
|
|
6694
|
-
return void 0 === t ? (s(e).forEach((t) => r(t, void 0)), {
|
|
6695
|
-
matched: !0,
|
|
6696
|
-
selections: n
|
|
6697
|
-
}) : {
|
|
6698
|
-
matched: o(e, t, r),
|
|
6699
|
-
selections: n
|
|
6700
|
-
};
|
|
6701
|
-
},
|
|
6702
|
-
getSelectionKeys: () => s(e),
|
|
6703
|
-
matcherType: "optional"
|
|
6704
|
-
}) });
|
|
6705
|
-
}
|
|
6706
|
-
function d(...e) {
|
|
6707
|
-
return a({ [t]: () => ({
|
|
6708
|
-
match: (t) => {
|
|
6709
|
-
let n = {};
|
|
6710
|
-
const r = (t, e) => {
|
|
6711
|
-
n[t] = e;
|
|
6712
|
-
};
|
|
6713
|
-
return {
|
|
6714
|
-
matched: e.every((e) => o(e, t, r)),
|
|
6715
|
-
selections: n
|
|
6716
|
-
};
|
|
6717
|
-
},
|
|
6718
|
-
getSelectionKeys: () => c(e, s),
|
|
6719
|
-
matcherType: "and"
|
|
6720
|
-
}) });
|
|
6721
|
-
}
|
|
6722
|
-
function y(...e) {
|
|
6723
|
-
return a({ [t]: () => ({
|
|
6724
|
-
match: (t) => {
|
|
6725
|
-
let n = {};
|
|
6726
|
-
const r = (t, e) => {
|
|
6727
|
-
n[t] = e;
|
|
6728
|
-
};
|
|
6729
|
-
return c(e, s).forEach((t) => r(t, void 0)), {
|
|
6730
|
-
matched: e.some((e) => o(e, t, r)),
|
|
6731
|
-
selections: n
|
|
6732
|
-
};
|
|
6733
|
-
},
|
|
6734
|
-
getSelectionKeys: () => c(e, s),
|
|
6735
|
-
matcherType: "or"
|
|
6736
|
-
}) });
|
|
6737
|
-
}
|
|
6738
|
-
function p(e) {
|
|
6739
|
-
return { [t]: () => ({ match: (t) => ({ matched: Boolean(e(t)) }) }) };
|
|
6740
|
-
}
|
|
6741
|
-
function v(...e) {
|
|
6742
|
-
const r = "string" == typeof e[0] ? e[0] : void 0, i = 2 === e.length ? e[1] : "string" == typeof e[0] ? void 0 : e[0];
|
|
6743
|
-
return a({ [t]: () => ({
|
|
6744
|
-
match: (t) => {
|
|
6745
|
-
let e = { [null != r ? r : n]: t };
|
|
6746
|
-
return {
|
|
6747
|
-
matched: void 0 === i || o(i, t, (t, n) => {
|
|
6748
|
-
e[t] = n;
|
|
6749
|
-
}),
|
|
6750
|
-
selections: e
|
|
6751
|
-
};
|
|
6752
|
-
},
|
|
6753
|
-
getSelectionKeys: () => [null != r ? r : n].concat(void 0 === i ? [] : s(i))
|
|
6754
|
-
}) });
|
|
6755
|
-
}
|
|
6756
|
-
function b(t) {
|
|
6757
|
-
return !0;
|
|
6758
|
-
}
|
|
6759
|
-
function w(t) {
|
|
6760
|
-
return "number" == typeof t;
|
|
6761
|
-
}
|
|
6762
|
-
function S(t) {
|
|
6763
|
-
return "string" == typeof t;
|
|
6764
|
-
}
|
|
6765
|
-
function j(t) {
|
|
6766
|
-
return "bigint" == typeof t;
|
|
6767
|
-
}
|
|
6768
|
-
a(p(b));
|
|
6769
|
-
a(p(b));
|
|
6770
|
-
const x = (t) => Object.assign(a(t), {
|
|
6771
|
-
startsWith: (e) => {
|
|
6772
|
-
return x(d(t, (n = e, p((t) => S(t) && t.startsWith(n)))));
|
|
6773
|
-
var n;
|
|
6774
|
-
},
|
|
6775
|
-
endsWith: (e) => {
|
|
6776
|
-
return x(d(t, (n = e, p((t) => S(t) && t.endsWith(n)))));
|
|
6777
|
-
var n;
|
|
6778
|
-
},
|
|
6779
|
-
minLength: (e) => x(d(t, ((t) => p((e) => S(e) && e.length >= t))(e))),
|
|
6780
|
-
length: (e) => x(d(t, ((t) => p((e) => S(e) && e.length === t))(e))),
|
|
6781
|
-
maxLength: (e) => x(d(t, ((t) => p((e) => S(e) && e.length <= t))(e))),
|
|
6782
|
-
includes: (e) => {
|
|
6783
|
-
return x(d(t, (n = e, p((t) => S(t) && t.includes(n)))));
|
|
6784
|
-
var n;
|
|
6785
|
-
},
|
|
6786
|
-
regex: (e) => {
|
|
6787
|
-
return x(d(t, (n = e, p((t) => S(t) && Boolean(t.match(n))))));
|
|
6788
|
-
var n;
|
|
6789
|
-
}
|
|
6790
|
-
});
|
|
6791
|
-
x(p(S));
|
|
6792
|
-
const N = (t) => Object.assign(a(t), {
|
|
6793
|
-
between: (e, n) => N(d(t, ((t, e) => p((n) => w(n) && t <= n && e >= n))(e, n))),
|
|
6794
|
-
lt: (e) => N(d(t, ((t) => p((e) => w(e) && e < t))(e))),
|
|
6795
|
-
gt: (e) => N(d(t, ((t) => p((e) => w(e) && e > t))(e))),
|
|
6796
|
-
lte: (e) => N(d(t, ((t) => p((e) => w(e) && e <= t))(e))),
|
|
6797
|
-
gte: (e) => N(d(t, ((t) => p((e) => w(e) && e >= t))(e))),
|
|
6798
|
-
int: () => N(d(t, p((t) => w(t) && Number.isInteger(t)))),
|
|
6799
|
-
finite: () => N(d(t, p((t) => w(t) && Number.isFinite(t)))),
|
|
6800
|
-
positive: () => N(d(t, p((t) => w(t) && t > 0))),
|
|
6801
|
-
negative: () => N(d(t, p((t) => w(t) && t < 0)))
|
|
6802
|
-
});
|
|
6803
|
-
N(p(w));
|
|
6804
|
-
const k = (t) => Object.assign(a(t), {
|
|
6805
|
-
between: (e, n) => k(d(t, ((t, e) => p((n) => j(n) && t <= n && e >= n))(e, n))),
|
|
6806
|
-
lt: (e) => k(d(t, ((t) => p((e) => j(e) && e < t))(e))),
|
|
6807
|
-
gt: (e) => k(d(t, ((t) => p((e) => j(e) && e > t))(e))),
|
|
6808
|
-
lte: (e) => k(d(t, ((t) => p((e) => j(e) && e <= t))(e))),
|
|
6809
|
-
gte: (e) => k(d(t, ((t) => p((e) => j(e) && e >= t))(e))),
|
|
6810
|
-
positive: () => k(d(t, p((t) => j(t) && t > 0))),
|
|
6811
|
-
negative: () => k(d(t, p((t) => j(t) && t < 0)))
|
|
6812
|
-
});
|
|
6813
|
-
k(p(j)), a(p(function(t) {
|
|
6814
|
-
return "boolean" == typeof t;
|
|
6815
|
-
})), a(p(function(t) {
|
|
6816
|
-
return "symbol" == typeof t;
|
|
6817
|
-
})), a(p(function(t) {
|
|
6818
|
-
return null == t;
|
|
6819
|
-
})), a(p(function(t) {
|
|
6820
|
-
return null != t;
|
|
6821
|
-
}));
|
|
6822
|
-
var I = class extends Error {
|
|
6823
|
-
constructor(t) {
|
|
6824
|
-
let e;
|
|
6825
|
-
try {
|
|
6826
|
-
e = JSON.stringify(t);
|
|
6827
|
-
} catch (n) {
|
|
6828
|
-
e = t;
|
|
6829
|
-
}
|
|
6830
|
-
super(`Pattern matching error: no pattern matches value ${e}`), this.input = void 0, this.input = t;
|
|
6831
|
-
}
|
|
6832
|
-
};
|
|
6833
|
-
const L = {
|
|
6834
|
-
matched: !1,
|
|
6835
|
-
value: void 0
|
|
6836
|
-
};
|
|
6837
|
-
function M(t) {
|
|
6838
|
-
return new R(t, L);
|
|
6839
|
-
}
|
|
6840
|
-
var R = class R {
|
|
6841
|
-
constructor(t, e) {
|
|
6842
|
-
this.input = void 0, this.state = void 0, this.input = t, this.state = e;
|
|
6843
|
-
}
|
|
6844
|
-
with(...t) {
|
|
6845
|
-
if (this.state.matched) return this;
|
|
6846
|
-
const e = t[t.length - 1], r = [t[0]];
|
|
6847
|
-
let i;
|
|
6848
|
-
3 === t.length && "function" == typeof t[1] ? i = t[1] : t.length > 2 && r.push(...t.slice(1, t.length - 1));
|
|
6849
|
-
let s = !1, c = {};
|
|
6850
|
-
const u = (t, e) => {
|
|
6851
|
-
s = !0, c[t] = e;
|
|
6852
|
-
}, a = !r.some((t) => o(t, this.input, u)) || i && !Boolean(i(this.input)) ? L : {
|
|
6853
|
-
matched: !0,
|
|
6854
|
-
value: e(s ? n in c ? c[n] : c : this.input, this.input)
|
|
6855
|
-
};
|
|
6856
|
-
return new R(this.input, a);
|
|
6857
|
-
}
|
|
6858
|
-
when(t, e) {
|
|
6859
|
-
if (this.state.matched) return this;
|
|
6860
|
-
const n = Boolean(t(this.input));
|
|
6861
|
-
return new R(this.input, n ? {
|
|
6862
|
-
matched: !0,
|
|
6863
|
-
value: e(this.input, this.input)
|
|
6864
|
-
} : L);
|
|
6865
|
-
}
|
|
6866
|
-
otherwise(t) {
|
|
6867
|
-
return this.state.matched ? this.state.value : t(this.input);
|
|
6868
|
-
}
|
|
6869
|
-
exhaustive(t = F) {
|
|
6870
|
-
return this.state.matched ? this.state.value : t(this.input);
|
|
6871
|
-
}
|
|
6872
|
-
run() {
|
|
6873
|
-
return this.exhaustive();
|
|
6874
|
-
}
|
|
6875
|
-
returnType() {
|
|
6876
|
-
return this;
|
|
6877
|
-
}
|
|
6878
|
-
narrow() {
|
|
6879
|
-
return this;
|
|
6880
|
-
}
|
|
6881
|
-
};
|
|
6882
|
-
function F(t) {
|
|
6883
|
-
throw new I(t);
|
|
6884
|
-
}
|
|
6885
|
-
//#endregion
|
|
6886
7071
|
//#region src/request/render-verdict.ts
|
|
6887
7072
|
function renderVerdict(verdict) {
|
|
6888
|
-
return M(verdict).with({ kind: "
|
|
7073
|
+
return M(verdict).with({ kind: "allow" }, () => JSON.stringify({ decision: "allow" })).with({ kind: "deny" }, (denied) => JSON.stringify({
|
|
6889
7074
|
decision: "deny",
|
|
6890
7075
|
reason: `[${denied.rule}] ${denied.reason}`
|
|
6891
7076
|
})).exhaustive();
|
package/package.json
CHANGED
package/policy/denial.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Do not retry this action, and do not reach the same result another way: not with a different command, tool, script, file, or agent. Continue the task on a safer path that does not need this action. If no safer path exists for this step, finish the rest of the task first, then tell the user what you need from them for this step.
|