auto-mode 0.5.0 → 0.7.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 +15 -12
- package/dist/cli.js +51 -4
- package/dist/index.d.ts +15 -6
- package/dist/index.js +1 -1
- package/dist/{render-verdict-FdG6gahX.js → render-verdict-CAg3AKWH.js} +841 -432
- package/package.json +1 -1
- package/policy/denial.md +1 -0
|
@@ -252,7 +252,7 @@ function safeExtend(schema, shape) {
|
|
|
252
252
|
if (!isPlainObject(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
253
253
|
return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
|
|
254
254
|
}
|
|
255
|
-
function merge
|
|
255
|
+
function merge(a, b) {
|
|
256
256
|
if (!b?._zod?.def) throw new Error("Invalid input to merge: expected an object schema. To merge a plain shape, use `.extend()`.");
|
|
257
257
|
if (a._zod.def.checks?.length) throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");
|
|
258
258
|
const newShape = {};
|
|
@@ -5218,7 +5218,7 @@ const ZodObject = /*@__PURE__*/ $constructor("ZodObject", (inst, def) => {
|
|
|
5218
5218
|
return safeExtend(this, incoming);
|
|
5219
5219
|
},
|
|
5220
5220
|
merge(other) {
|
|
5221
|
-
return merge
|
|
5221
|
+
return merge(this, other);
|
|
5222
5222
|
},
|
|
5223
5223
|
pick(mask) {
|
|
5224
5224
|
return pick(this, mask);
|
|
@@ -5569,6 +5569,171 @@ async function loadClaudeRules(path) {
|
|
|
5569
5569
|
hard_deny: (rules.autoMode?.hard_deny ?? []).filter((entry) => entry !== "$defaults")
|
|
5570
5570
|
};
|
|
5571
5571
|
}
|
|
5572
|
+
const PRESETS = {
|
|
5573
|
+
jev: {
|
|
5574
|
+
protocol: "system-one",
|
|
5575
|
+
baseURL: "https://api.typesafe.ai",
|
|
5576
|
+
model: "jev-1.13.0",
|
|
5577
|
+
apiKeyEnv: "TYPESAFE_API_KEY",
|
|
5578
|
+
reasoning: false,
|
|
5579
|
+
maxTokens: 3e3,
|
|
5580
|
+
timeoutMs: 5e3
|
|
5581
|
+
},
|
|
5582
|
+
spark: {
|
|
5583
|
+
baseURL: "https://api.meta.ai",
|
|
5584
|
+
model: "muse-spark-1.3-contributor",
|
|
5585
|
+
apiKeyEnv: "META_API_KEY",
|
|
5586
|
+
reasoning: true,
|
|
5587
|
+
maxTokens: 3e3,
|
|
5588
|
+
timeoutMs: 45e3
|
|
5589
|
+
},
|
|
5590
|
+
claude: {
|
|
5591
|
+
baseURL: "https://api.anthropic.com",
|
|
5592
|
+
model: "claude-haiku-4-5-20251001",
|
|
5593
|
+
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
5594
|
+
reasoning: true,
|
|
5595
|
+
maxTokens: 3e3,
|
|
5596
|
+
timeoutMs: 45e3
|
|
5597
|
+
},
|
|
5598
|
+
glm: {
|
|
5599
|
+
baseURL: "https://api.z.ai/api/anthropic",
|
|
5600
|
+
model: "glm-5.3-flash",
|
|
5601
|
+
apiKeyEnv: "ZAI_API_KEY",
|
|
5602
|
+
reasoning: true,
|
|
5603
|
+
maxTokens: 3e3,
|
|
5604
|
+
timeoutMs: 6e4
|
|
5605
|
+
}
|
|
5606
|
+
};
|
|
5607
|
+
const MESSAGES_DEFAULTS = {
|
|
5608
|
+
protocol: "messages",
|
|
5609
|
+
baseURL: "https://api.anthropic.com",
|
|
5610
|
+
reasoning: true,
|
|
5611
|
+
maxTokens: 3e3,
|
|
5612
|
+
timeoutMs: 45e3
|
|
5613
|
+
};
|
|
5614
|
+
function findPreset(id) {
|
|
5615
|
+
return Object.hasOwn(PRESETS, id) ? PRESETS[id] : void 0;
|
|
5616
|
+
}
|
|
5617
|
+
//#endregion
|
|
5618
|
+
//#region src/config/normalize-config-file.ts
|
|
5619
|
+
function normalizeConfigFile(json, path) {
|
|
5620
|
+
if (!isRecord(json)) return {
|
|
5621
|
+
file: json,
|
|
5622
|
+
isLegacy: false,
|
|
5623
|
+
warnings: []
|
|
5624
|
+
};
|
|
5625
|
+
const legacyKeys = Object.keys(json).filter((key) => LEGACY_KEYS.has(key));
|
|
5626
|
+
if (legacyKeys.length === 0) return {
|
|
5627
|
+
file: json,
|
|
5628
|
+
isLegacy: false,
|
|
5629
|
+
warnings: []
|
|
5630
|
+
};
|
|
5631
|
+
const currentKeys = Object.keys(json).filter((key) => !LEGACY_KEYS.has(key));
|
|
5632
|
+
if (currentKeys.length > 0) throw new Error(`${path} mixes the old keys (${legacyKeys.join(", ")}) with the new ones (${currentKeys.join(", ")}); run \`auto-mode config migrate\` on a copy without the new keys`);
|
|
5633
|
+
const parsed = legacyConfigSchema.safeParse(json);
|
|
5634
|
+
if (!parsed.success) throw new Error(`${path} is not a valid config: ${prettifyError(parsed.error)}`);
|
|
5635
|
+
const legacy = parsed.data;
|
|
5636
|
+
const warnings = [`${path} uses the old config keys (${legacyKeys.join(", ")}); run \`auto-mode config migrate\` to rewrite it`, ...legacy.transcriptEntries === void 0 ? [] : [`${path} sets transcriptEntries, which has no effect; migration drops it`]];
|
|
5637
|
+
return {
|
|
5638
|
+
file: buildFileFromLegacy(legacy, path),
|
|
5639
|
+
isLegacy: true,
|
|
5640
|
+
warnings
|
|
5641
|
+
};
|
|
5642
|
+
}
|
|
5643
|
+
function isRecord(value) {
|
|
5644
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5645
|
+
}
|
|
5646
|
+
const LEGACY_KEYS = /* @__PURE__ */ new Set([
|
|
5647
|
+
"preset",
|
|
5648
|
+
"provider",
|
|
5649
|
+
"classifierPath",
|
|
5650
|
+
"rulesPath",
|
|
5651
|
+
"transcriptEntries",
|
|
5652
|
+
"onFailure",
|
|
5653
|
+
"claudeSettingsPath",
|
|
5654
|
+
"minConfidence"
|
|
5655
|
+
]);
|
|
5656
|
+
const text$1 = string().min(1);
|
|
5657
|
+
const positive$1 = number().positive();
|
|
5658
|
+
const legacyConfigSchema = strictObject({
|
|
5659
|
+
preset: text$1.optional(),
|
|
5660
|
+
provider: strictObject({
|
|
5661
|
+
protocol: _enum(["messages", "system-one"]).optional(),
|
|
5662
|
+
baseURL: text$1.optional(),
|
|
5663
|
+
model: text$1.optional(),
|
|
5664
|
+
apiKeyEnv: text$1.optional(),
|
|
5665
|
+
apiKeyCommand: text$1.optional(),
|
|
5666
|
+
reasoning: boolean().optional(),
|
|
5667
|
+
maxTokens: positive$1.optional(),
|
|
5668
|
+
timeoutMs: positive$1.optional()
|
|
5669
|
+
}).optional(),
|
|
5670
|
+
classifierPath: text$1.optional(),
|
|
5671
|
+
rulesPath: text$1.optional(),
|
|
5672
|
+
transcriptEntries: number().nonnegative().optional(),
|
|
5673
|
+
onFailure: _enum(["defer", "deny"]).optional(),
|
|
5674
|
+
claudeSettingsPath: text$1.nullable().optional(),
|
|
5675
|
+
minConfidence: number().min(.5).max(1).optional()
|
|
5676
|
+
});
|
|
5677
|
+
function buildFileFromLegacy(legacy, path) {
|
|
5678
|
+
const hasClassifier = legacy.preset !== void 0 || legacy.provider !== void 0;
|
|
5679
|
+
const decision = {
|
|
5680
|
+
...hasClassifier ? { classifier: getLegacyClassifierID(legacy) } : {},
|
|
5681
|
+
...legacy.minConfidence === void 0 ? {} : { minConfidence: legacy.minConfidence },
|
|
5682
|
+
...legacy.onFailure === void 0 ? {} : { onFailure: legacy.onFailure }
|
|
5683
|
+
};
|
|
5684
|
+
const policy = {
|
|
5685
|
+
...legacy.rulesPath === void 0 ? {} : { rulesPath: legacy.rulesPath },
|
|
5686
|
+
...legacy.classifierPath === void 0 ? {} : { frameworkPath: legacy.classifierPath },
|
|
5687
|
+
...legacy.claudeSettingsPath === void 0 ? {} : { claudeSettingsPath: legacy.claudeSettingsPath }
|
|
5688
|
+
};
|
|
5689
|
+
return {
|
|
5690
|
+
...hasClassifier ? { classifiers: { [getLegacyClassifierID(legacy)]: buildClassifierEntry(getLegacyClassifierID(legacy), buildLegacyProvider(legacy, path)) } } : {},
|
|
5691
|
+
...Object.keys(decision).length === 0 ? {} : { decision },
|
|
5692
|
+
...Object.keys(policy).length === 0 ? {} : { policy }
|
|
5693
|
+
};
|
|
5694
|
+
}
|
|
5695
|
+
function getLegacyClassifierID(legacy) {
|
|
5696
|
+
if (legacy.preset !== void 0) return legacy.preset;
|
|
5697
|
+
return legacy.provider !== void 0 && legacy.provider.protocol !== "system-one" ? "spark" : "jev";
|
|
5698
|
+
}
|
|
5699
|
+
function buildLegacyProvider(legacy, path) {
|
|
5700
|
+
const preset = findPreset(getLegacyClassifierID(legacy));
|
|
5701
|
+
if (preset === void 0) throw new Error(`${path} names an unknown preset '${legacy.preset}'; known presets are ${Object.keys(PRESETS).join(", ")}`);
|
|
5702
|
+
const override = legacy.provider ?? {};
|
|
5703
|
+
return {
|
|
5704
|
+
protocol: override.protocol ?? preset.protocol ?? "messages",
|
|
5705
|
+
baseURL: override.baseURL ?? preset.baseURL,
|
|
5706
|
+
model: override.model ?? preset.model,
|
|
5707
|
+
apiKeyEnv: override.apiKeyEnv ?? preset.apiKeyEnv,
|
|
5708
|
+
apiKeyCommand: override.apiKeyCommand ?? preset.apiKeyCommand,
|
|
5709
|
+
reasoning: override.reasoning ?? preset.reasoning,
|
|
5710
|
+
maxTokens: override.maxTokens ?? preset.maxTokens,
|
|
5711
|
+
timeoutMs: override.timeoutMs ?? preset.timeoutMs
|
|
5712
|
+
};
|
|
5713
|
+
}
|
|
5714
|
+
const PROVIDER_FIELDS = [
|
|
5715
|
+
"baseURL",
|
|
5716
|
+
"model",
|
|
5717
|
+
"apiKeyEnv",
|
|
5718
|
+
"apiKeyCommand",
|
|
5719
|
+
"reasoning",
|
|
5720
|
+
"maxTokens",
|
|
5721
|
+
"timeoutMs"
|
|
5722
|
+
];
|
|
5723
|
+
function buildClassifierEntry(id, provider) {
|
|
5724
|
+
const kind = pickEntryKind(id, provider);
|
|
5725
|
+
const base = kind === "messages" ? MESSAGES_DEFAULTS : findPreset(kind) ?? {};
|
|
5726
|
+
const fields = Object.fromEntries(PROVIDER_FIELDS.filter((field) => provider[field] !== void 0 && provider[field] !== base[field]).map((field) => [field, provider[field]]));
|
|
5727
|
+
return {
|
|
5728
|
+
...kind === id ? {} : { kind },
|
|
5729
|
+
...fields
|
|
5730
|
+
};
|
|
5731
|
+
}
|
|
5732
|
+
function pickEntryKind(id, provider) {
|
|
5733
|
+
const preset = findPreset(id);
|
|
5734
|
+
if (preset !== void 0 && (preset.protocol ?? "messages") === provider.protocol) return id;
|
|
5735
|
+
return provider.protocol === "system-one" ? "jev" : "messages";
|
|
5736
|
+
}
|
|
5572
5737
|
//#endregion
|
|
5573
5738
|
//#region src/config/read-api-key-from-command.ts
|
|
5574
5739
|
function readApiKeyFromCommand(command, options = {}) {
|
|
@@ -5624,73 +5789,24 @@ function readApiKeyFromCommand(command, options = {}) {
|
|
|
5624
5789
|
}
|
|
5625
5790
|
//#endregion
|
|
5626
5791
|
//#region src/config/config.ts
|
|
5792
|
+
const SCOPE_SOURCE_KINDS = [
|
|
5793
|
+
"cwd",
|
|
5794
|
+
"session",
|
|
5795
|
+
"globs",
|
|
5796
|
+
"atc"
|
|
5797
|
+
];
|
|
5798
|
+
const DEFAULT_PROVIDER = findPreset("jev");
|
|
5799
|
+
if (DEFAULT_PROVIDER === void 0) throw new Error("the jev preset is missing");
|
|
5627
5800
|
const DEFAULT_CONFIG = {
|
|
5628
|
-
provider:
|
|
5629
|
-
protocol: "system-one",
|
|
5630
|
-
baseURL: "https://api.typesafe.ai",
|
|
5631
|
-
model: "jev-1.13.0",
|
|
5632
|
-
apiKeyEnv: "TYPESAFE_API_KEY",
|
|
5633
|
-
reasoning: false,
|
|
5634
|
-
maxTokens: 3e3,
|
|
5635
|
-
timeoutMs: 5e3
|
|
5636
|
-
},
|
|
5801
|
+
provider: DEFAULT_PROVIDER,
|
|
5637
5802
|
onFailure: "defer",
|
|
5638
5803
|
minConfidence: .8
|
|
5639
5804
|
};
|
|
5640
|
-
const SPARK_PROVIDER = {
|
|
5641
|
-
baseURL: "https://api.meta.ai",
|
|
5642
|
-
model: "muse-spark-1.3-contributor",
|
|
5643
|
-
apiKeyEnv: "META_API_KEY",
|
|
5644
|
-
reasoning: true,
|
|
5645
|
-
maxTokens: 3e3,
|
|
5646
|
-
timeoutMs: 45e3
|
|
5647
|
-
};
|
|
5648
|
-
const PRESETS = {
|
|
5649
|
-
jev: DEFAULT_CONFIG.provider,
|
|
5650
|
-
spark: SPARK_PROVIDER,
|
|
5651
|
-
claude: {
|
|
5652
|
-
baseURL: "https://api.anthropic.com",
|
|
5653
|
-
model: "claude-haiku-4-5-20251001",
|
|
5654
|
-
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
5655
|
-
reasoning: true,
|
|
5656
|
-
maxTokens: 3e3,
|
|
5657
|
-
timeoutMs: 45e3
|
|
5658
|
-
},
|
|
5659
|
-
glm: {
|
|
5660
|
-
baseURL: "https://api.z.ai/api/anthropic",
|
|
5661
|
-
model: "glm-5.3-flash",
|
|
5662
|
-
apiKeyEnv: "ZAI_API_KEY",
|
|
5663
|
-
reasoning: true,
|
|
5664
|
-
maxTokens: 3e3,
|
|
5665
|
-
timeoutMs: 6e4
|
|
5666
|
-
}
|
|
5667
|
-
};
|
|
5668
5805
|
function resolveConfigPath() {
|
|
5669
5806
|
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
5670
5807
|
const base = xdg !== void 0 && xdg !== "" ? xdg : join(homedir(), ".config");
|
|
5671
5808
|
return join(base, "auto-mode", "config.json");
|
|
5672
5809
|
}
|
|
5673
|
-
const text = string().min(1);
|
|
5674
|
-
const positive = number().positive();
|
|
5675
|
-
const configFileSchema = strictObject({
|
|
5676
|
-
preset: text.optional(),
|
|
5677
|
-
provider: strictObject({
|
|
5678
|
-
protocol: _enum(["messages", "system-one"]).optional(),
|
|
5679
|
-
baseURL: text.optional(),
|
|
5680
|
-
model: text.optional(),
|
|
5681
|
-
apiKeyEnv: text.optional(),
|
|
5682
|
-
apiKeyCommand: text.optional(),
|
|
5683
|
-
reasoning: boolean().optional(),
|
|
5684
|
-
maxTokens: positive.optional(),
|
|
5685
|
-
timeoutMs: positive.optional()
|
|
5686
|
-
}).optional(),
|
|
5687
|
-
classifierPath: text.optional(),
|
|
5688
|
-
rulesPath: text.optional(),
|
|
5689
|
-
transcriptEntries: number().nonnegative().optional(),
|
|
5690
|
-
onFailure: _enum(["defer", "deny"]).optional(),
|
|
5691
|
-
claudeSettingsPath: text.nullable().optional(),
|
|
5692
|
-
minConfidence: number().min(.5).max(1).optional()
|
|
5693
|
-
});
|
|
5694
5810
|
async function loadConfig(path = resolveConfigPath()) {
|
|
5695
5811
|
let raw;
|
|
5696
5812
|
try {
|
|
@@ -5705,33 +5821,141 @@ async function loadConfig(path = resolveConfigPath()) {
|
|
|
5705
5821
|
} catch {
|
|
5706
5822
|
throw new Error(`${path} is not valid JSON`);
|
|
5707
5823
|
}
|
|
5824
|
+
const normalized = normalizeConfigFile(json, path);
|
|
5825
|
+
return buildConfig(normalized.file, path, normalized.warnings);
|
|
5826
|
+
}
|
|
5827
|
+
const text = string().min(1);
|
|
5828
|
+
const positive = number().positive();
|
|
5829
|
+
const configFileSchema = strictObject({
|
|
5830
|
+
classifiers: record(text, unknown()).optional(),
|
|
5831
|
+
scopeSources: record(text, unknown()).optional(),
|
|
5832
|
+
decision: strictObject({
|
|
5833
|
+
classifier: text.optional(),
|
|
5834
|
+
judge: text.nullable().optional(),
|
|
5835
|
+
minConfidence: number().min(.5).max(1).optional(),
|
|
5836
|
+
onFailure: _enum(["defer", "deny"]).optional()
|
|
5837
|
+
}).optional(),
|
|
5838
|
+
policy: strictObject({
|
|
5839
|
+
rulesPath: text.nullable().optional(),
|
|
5840
|
+
frameworkPath: text.nullable().optional(),
|
|
5841
|
+
claudeSettingsPath: text.nullable().optional()
|
|
5842
|
+
}).optional()
|
|
5843
|
+
});
|
|
5844
|
+
function buildConfig(json, path, legacyWarnings) {
|
|
5708
5845
|
const parsed = configFileSchema.safeParse(json);
|
|
5709
5846
|
if (!parsed.success) throw new Error(`${path} is not a valid config: ${prettifyError(parsed.error)}`);
|
|
5710
|
-
|
|
5847
|
+
const file = parsed.data;
|
|
5848
|
+
const warnings = [...legacyWarnings];
|
|
5849
|
+
const classifiers = buildRegistry(file.classifiers ?? {}, (id, entry) => parseClassifierEntry(id, entry));
|
|
5850
|
+
const scopeSources = buildRegistry(file.scopeSources ?? {}, (id, entry) => parseScopeSourceEntry(id, entry));
|
|
5851
|
+
warnings.push(...classifiers.dropped.map((line) => `${path}: classifiers.${line}`), ...scopeSources.dropped.map((line) => `${path}: scopeSources.${line}`));
|
|
5852
|
+
const decision = file.decision ?? {};
|
|
5853
|
+
const policy = file.policy ?? {};
|
|
5854
|
+
const judgeID = decision.judge ?? null;
|
|
5855
|
+
return {
|
|
5856
|
+
provider: resolveRole("classifier", decision.classifier ?? "jev", classifiers.entries, classifiers.droppedIDs, path),
|
|
5857
|
+
judge: judgeID === null ? null : resolveRole("judge", judgeID, classifiers.entries, classifiers.droppedIDs, path),
|
|
5858
|
+
scopeSources: scopeSources.entries,
|
|
5859
|
+
classifierPath: expandHomePath(policy.frameworkPath ?? void 0),
|
|
5860
|
+
rulesPath: expandHomePath(policy.rulesPath ?? void 0),
|
|
5861
|
+
onFailure: decision.onFailure ?? DEFAULT_CONFIG.onFailure,
|
|
5862
|
+
claudeSettingsPath: policy.claudeSettingsPath === null ? null : expandHomePath(policy.claudeSettingsPath),
|
|
5863
|
+
minConfidence: decision.minConfidence ?? DEFAULT_CONFIG.minConfidence,
|
|
5864
|
+
warnings
|
|
5865
|
+
};
|
|
5711
5866
|
}
|
|
5712
|
-
function
|
|
5713
|
-
const
|
|
5714
|
-
const
|
|
5715
|
-
|
|
5716
|
-
const
|
|
5867
|
+
function buildRegistry(raw, parseEntry) {
|
|
5868
|
+
const entries = /* @__PURE__ */ new Map();
|
|
5869
|
+
const dropped = [];
|
|
5870
|
+
const droppedIDs = [];
|
|
5871
|
+
for (const [id, entry] of Object.entries(raw)) {
|
|
5872
|
+
const result = parseEntry(id, entry);
|
|
5873
|
+
if (typeof result === "string") {
|
|
5874
|
+
dropped.push(`${id} dropped: ${result}`);
|
|
5875
|
+
droppedIDs.push(id);
|
|
5876
|
+
} else entries.set(id, result);
|
|
5877
|
+
}
|
|
5717
5878
|
return {
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5879
|
+
entries: Object.fromEntries(entries),
|
|
5880
|
+
dropped,
|
|
5881
|
+
droppedIDs
|
|
5882
|
+
};
|
|
5883
|
+
}
|
|
5884
|
+
const CLASSIFIER_KINDS = [...Object.keys(PRESETS), "messages"];
|
|
5885
|
+
const classifierEntrySchema = strictObject({
|
|
5886
|
+
kind: text.optional(),
|
|
5887
|
+
baseURL: text.optional(),
|
|
5888
|
+
model: text.optional(),
|
|
5889
|
+
apiKeyEnv: text.optional(),
|
|
5890
|
+
apiKeyCommand: text.optional(),
|
|
5891
|
+
reasoning: boolean().optional(),
|
|
5892
|
+
maxTokens: positive.optional(),
|
|
5893
|
+
timeoutMs: positive.optional()
|
|
5894
|
+
});
|
|
5895
|
+
const CREDENTIAL_KEYS = /* @__PURE__ */ new Set([
|
|
5896
|
+
"apiKey",
|
|
5897
|
+
"key",
|
|
5898
|
+
"token",
|
|
5899
|
+
"secret"
|
|
5900
|
+
]);
|
|
5901
|
+
function parseClassifierEntry(id, entry) {
|
|
5902
|
+
if (typeof entry === "object" && entry !== null) {
|
|
5903
|
+
const credential = Object.keys(entry).find((key) => CREDENTIAL_KEYS.has(key));
|
|
5904
|
+
if (credential !== void 0) return `holds a literal ${credential}; name the key with apiKeyEnv or apiKeyCommand`;
|
|
5905
|
+
}
|
|
5906
|
+
const parsed = classifierEntrySchema.safeParse(entry);
|
|
5907
|
+
if (!parsed.success) return formatFirstIssue(parsed.error.issues);
|
|
5908
|
+
const kind = parsed.data.kind ?? id;
|
|
5909
|
+
if (!CLASSIFIER_KINDS.includes(kind)) return `unknown kind '${kind}'; known kinds are ${CLASSIFIER_KINDS.join(", ")}`;
|
|
5910
|
+
const base = kind === "messages" ? MESSAGES_DEFAULTS : findPreset(kind);
|
|
5911
|
+
const model = parsed.data.model ?? base?.model;
|
|
5912
|
+
if (base === void 0 || model === void 0) return `kind '${kind}' needs a model`;
|
|
5913
|
+
return {
|
|
5914
|
+
protocol: base.protocol ?? "messages",
|
|
5915
|
+
baseURL: parsed.data.baseURL ?? base.baseURL,
|
|
5916
|
+
model,
|
|
5917
|
+
apiKeyEnv: parsed.data.apiKeyEnv ?? base.apiKeyEnv,
|
|
5918
|
+
apiKeyCommand: parsed.data.apiKeyCommand ?? base.apiKeyCommand,
|
|
5919
|
+
reasoning: parsed.data.reasoning ?? base.reasoning,
|
|
5920
|
+
maxTokens: parsed.data.maxTokens ?? base.maxTokens,
|
|
5921
|
+
timeoutMs: parsed.data.timeoutMs ?? base.timeoutMs
|
|
5733
5922
|
};
|
|
5734
5923
|
}
|
|
5924
|
+
const scopeSourceEntrySchema = strictObject({
|
|
5925
|
+
kind: text.optional(),
|
|
5926
|
+
paths: array(text).min(1).optional()
|
|
5927
|
+
});
|
|
5928
|
+
function parseScopeSourceEntry(id, entry) {
|
|
5929
|
+
const parsed = scopeSourceEntrySchema.safeParse(entry);
|
|
5930
|
+
if (!parsed.success) return formatFirstIssue(parsed.error.issues);
|
|
5931
|
+
const kind = SCOPE_SOURCE_KINDS.find((known) => known === (parsed.data.kind ?? id));
|
|
5932
|
+
if (kind === void 0) return `unknown kind '${parsed.data.kind ?? id}'; known kinds are ${SCOPE_SOURCE_KINDS.join(", ")}`;
|
|
5933
|
+
if (kind === "globs") return parsed.data.paths === void 0 ? "kind 'globs' needs paths" : {
|
|
5934
|
+
kind,
|
|
5935
|
+
paths: parsed.data.paths
|
|
5936
|
+
};
|
|
5937
|
+
return parsed.data.paths === void 0 ? { kind } : `kind '${kind}' takes no paths`;
|
|
5938
|
+
}
|
|
5939
|
+
function formatFirstIssue(issues) {
|
|
5940
|
+
const [issue] = issues;
|
|
5941
|
+
if (issue === void 0) return "invalid entry";
|
|
5942
|
+
return issue.path.length === 0 ? issue.message : `${issue.path.map(String).join(".")}: ${issue.message}`;
|
|
5943
|
+
}
|
|
5944
|
+
function resolveRole(role, id, entries, droppedIDs, path) {
|
|
5945
|
+
const entry = Object.hasOwn(entries, id) ? entries[id] : void 0;
|
|
5946
|
+
if (entry !== void 0) return entry;
|
|
5947
|
+
if (droppedIDs.includes(id)) throw new Error(`${path}: decision.${role} names '${id}', whose entry was dropped`);
|
|
5948
|
+
if (findPreset(id) === void 0) throw new Error(`${path}: decision.${role} names '${id}', which is neither a classifiers entry nor a built-in kind (${Object.keys(PRESETS).join(", ")})`);
|
|
5949
|
+
return parseBuiltIn(id);
|
|
5950
|
+
}
|
|
5951
|
+
function parseBuiltIn(id) {
|
|
5952
|
+
const resolved = parseClassifierEntry(id, {});
|
|
5953
|
+
if (typeof resolved === "string") throw new TypeError(`built-in kind ${id} does not resolve: ${resolved}`);
|
|
5954
|
+
return resolved;
|
|
5955
|
+
}
|
|
5956
|
+
function expandHomePath(path) {
|
|
5957
|
+
return path?.startsWith("~/") === true ? join(homedir(), path.slice(2)) : path;
|
|
5958
|
+
}
|
|
5735
5959
|
function resolveApiKey(provider, options = {}) {
|
|
5736
5960
|
const fromEnv = provider.apiKeyEnv === void 0 ? void 0 : process.env[provider.apiKeyEnv];
|
|
5737
5961
|
if (fromEnv !== void 0 && fromEnv !== "") return Promise.resolve(fromEnv);
|
|
@@ -5739,25 +5963,27 @@ function resolveApiKey(provider, options = {}) {
|
|
|
5739
5963
|
return readApiKeyFromCommand(provider.apiKeyCommand, options);
|
|
5740
5964
|
}
|
|
5741
5965
|
//#endregion
|
|
5966
|
+
//#region src/policy/resolve-shipped-policy-dir.ts
|
|
5967
|
+
function resolveShippedPolicyDir() {
|
|
5968
|
+
let dir = import.meta.dirname;
|
|
5969
|
+
for (;;) {
|
|
5970
|
+
if (existsSync(join(dir, "policy", "classifier.md"))) return join(dir, "policy");
|
|
5971
|
+
const parent = dirname(dir);
|
|
5972
|
+
if (parent === dir || dir === parse(dir).root) throw new Error("auto-mode cannot find its shipped policy/ directory");
|
|
5973
|
+
dir = parent;
|
|
5974
|
+
}
|
|
5975
|
+
}
|
|
5976
|
+
//#endregion
|
|
5742
5977
|
//#region src/policy/load-policy.ts
|
|
5743
5978
|
const RULES_MARKER = "<rules>";
|
|
5744
5979
|
async function loadPolicy(paths = {}, framework = "classifier.md") {
|
|
5745
|
-
const shipped =
|
|
5980
|
+
const shipped = resolveShippedPolicyDir();
|
|
5746
5981
|
const classifierPath = paths.classifierPath ?? join(shipped, framework);
|
|
5747
5982
|
const rulesPath = paths.rulesPath ?? join(shipped, "rules.md");
|
|
5748
5983
|
const [classifier, rules] = await Promise.all([readFile(classifierPath, "utf8"), readFile(rulesPath, "utf8")]);
|
|
5749
5984
|
if (!classifier.includes(RULES_MARKER)) throw new Error(`${classifierPath} has no ${RULES_MARKER} line, so the rules cannot be placed`);
|
|
5750
5985
|
return classifier.replace(RULES_MARKER, rules.trim());
|
|
5751
5986
|
}
|
|
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
5987
|
//#endregion
|
|
5762
5988
|
//#region src/model/anthropic-client.ts
|
|
5763
5989
|
async function sendMessage(provider, apiKey, request) {
|
|
@@ -5946,12 +6172,38 @@ function buildEvidenceGuidance(name) {
|
|
|
5946
6172
|
return "";
|
|
5947
6173
|
}
|
|
5948
6174
|
//#endregion
|
|
6175
|
+
//#region src/model/classify-decision-answers.ts
|
|
6176
|
+
function classifyDecisionAnswers(request, result, minConfidence) {
|
|
6177
|
+
const entries = Object.entries(request.rules).map(([id, rule]) => {
|
|
6178
|
+
const answer = result.answers[id];
|
|
6179
|
+
if (answer === void 0) throw new Error("Decision answer missing");
|
|
6180
|
+
return {
|
|
6181
|
+
rule,
|
|
6182
|
+
answer
|
|
6183
|
+
};
|
|
6184
|
+
});
|
|
6185
|
+
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 {
|
|
6186
|
+
kind: "block",
|
|
6187
|
+
rule: entry.rule
|
|
6188
|
+
};
|
|
6189
|
+
let uncertain = null;
|
|
6190
|
+
for (const entry of entries) {
|
|
6191
|
+
const answer = entry.answer;
|
|
6192
|
+
if (!(answer.choice === "allow" && answer.confidence >= minConfidence && answer.probabilities.allow >= minConfidence) && (uncertain === null || answer.probabilities.block > uncertain.answer.probabilities.block)) uncertain = entry;
|
|
6193
|
+
}
|
|
6194
|
+
return uncertain === null ? { kind: "allow" } : {
|
|
6195
|
+
kind: "uncertain",
|
|
6196
|
+
rule: uncertain.rule
|
|
6197
|
+
};
|
|
6198
|
+
}
|
|
6199
|
+
//#endregion
|
|
5949
6200
|
//#region src/model/collect-decision-contributors.ts
|
|
5950
|
-
function collectDecisionContributors(request, result,
|
|
6201
|
+
function collectDecisionContributors(request, result, minConfidence) {
|
|
6202
|
+
const decision = classifyDecisionAnswers(request, result, minConfidence);
|
|
5951
6203
|
return Object.entries(request.rules).flatMap(([id, rule]) => {
|
|
5952
6204
|
const answer = result.answers[id];
|
|
5953
6205
|
if (answer === void 0) throw new Error("Decision answer missing");
|
|
5954
|
-
return (
|
|
6206
|
+
return (decision.kind === "block" ? rule === decision.rule : decision.kind === "uncertain" && (answer.choice !== "allow" || answer.confidence < minConfidence || answer.probabilities.allow < minConfidence)) ? [{
|
|
5955
6207
|
rule: rule.source === "shipped" ? rule.name : id,
|
|
5956
6208
|
source: rule.source,
|
|
5957
6209
|
tier: rule.tier,
|
|
@@ -6041,89 +6293,466 @@ function parseReference(content, prefix) {
|
|
|
6041
6293
|
return branch !== "" && branch.length <= 256 && !/\s/u.test(branch) ? branch : null;
|
|
6042
6294
|
}
|
|
6043
6295
|
//#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);
|
|
6296
|
+
//#region node_modules/.bun/ts-pattern@5.9.0/node_modules/ts-pattern/dist/index.js
|
|
6297
|
+
const t = Symbol.for("@ts-pattern/matcher");
|
|
6298
|
+
const e = Symbol.for("@ts-pattern/isVariadic");
|
|
6299
|
+
const n = "@ts-pattern/anonymous-select-key";
|
|
6300
|
+
const r = (t) => Boolean(t && "object" == typeof t);
|
|
6301
|
+
const i = (e) => e && !!e[t];
|
|
6302
|
+
const o = (n, s, c) => {
|
|
6303
|
+
if (i(n)) {
|
|
6304
|
+
const { matched: r, selections: i } = n[t]().match(s);
|
|
6305
|
+
return r && i && Object.keys(i).forEach((t) => c(t, i[t])), r;
|
|
6084
6306
|
}
|
|
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");
|
|
6307
|
+
if (r(n)) {
|
|
6308
|
+
if (!r(s)) return !1;
|
|
6309
|
+
if (Array.isArray(n)) {
|
|
6310
|
+
if (!Array.isArray(s)) return !1;
|
|
6311
|
+
let t = [], r = [], u = [];
|
|
6312
|
+
for (const o of n.keys()) {
|
|
6313
|
+
const s = n[o];
|
|
6314
|
+
i(s) && s[e] ? u.push(s) : u.length ? r.push(s) : t.push(s);
|
|
6315
|
+
}
|
|
6316
|
+
if (u.length) {
|
|
6317
|
+
if (u.length > 1) throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");
|
|
6318
|
+
if (s.length < t.length + r.length) return !1;
|
|
6319
|
+
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);
|
|
6320
|
+
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));
|
|
6321
|
+
}
|
|
6322
|
+
return n.length === s.length && n.every((t, e) => o(t, s[e], c));
|
|
6111
6323
|
}
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6324
|
+
return Reflect.ownKeys(n).every((e) => {
|
|
6325
|
+
const r = n[e];
|
|
6326
|
+
return (e in s || i(u = r) && "optional" === u[t]().matcherType) && o(r, s[e], c);
|
|
6327
|
+
var u;
|
|
6328
|
+
});
|
|
6329
|
+
}
|
|
6330
|
+
return Object.is(s, n);
|
|
6331
|
+
};
|
|
6332
|
+
const s = (e) => {
|
|
6333
|
+
var n, o, u;
|
|
6334
|
+
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) : [];
|
|
6335
|
+
};
|
|
6336
|
+
const c = (t, e) => t.reduce((t, n) => t.concat(e(n)), []);
|
|
6337
|
+
function a(t) {
|
|
6338
|
+
return Object.assign(t, {
|
|
6339
|
+
optional: () => h(t),
|
|
6340
|
+
and: (e) => d(t, e),
|
|
6341
|
+
or: (e) => y(t, e),
|
|
6342
|
+
select: (e) => void 0 === e ? v(t) : v(e, t)
|
|
6343
|
+
});
|
|
6344
|
+
}
|
|
6345
|
+
function h(e) {
|
|
6346
|
+
return a({ [t]: () => ({
|
|
6347
|
+
match: (t) => {
|
|
6348
|
+
let n = {};
|
|
6349
|
+
const r = (t, e) => {
|
|
6350
|
+
n[t] = e;
|
|
6351
|
+
};
|
|
6352
|
+
return void 0 === t ? (s(e).forEach((t) => r(t, void 0)), {
|
|
6353
|
+
matched: !0,
|
|
6354
|
+
selections: n
|
|
6355
|
+
}) : {
|
|
6356
|
+
matched: o(e, t, r),
|
|
6357
|
+
selections: n
|
|
6358
|
+
};
|
|
6359
|
+
},
|
|
6360
|
+
getSelectionKeys: () => s(e),
|
|
6361
|
+
matcherType: "optional"
|
|
6362
|
+
}) });
|
|
6363
|
+
}
|
|
6364
|
+
function d(...e) {
|
|
6365
|
+
return a({ [t]: () => ({
|
|
6366
|
+
match: (t) => {
|
|
6367
|
+
let n = {};
|
|
6368
|
+
const r = (t, e) => {
|
|
6369
|
+
n[t] = e;
|
|
6370
|
+
};
|
|
6371
|
+
return {
|
|
6372
|
+
matched: e.every((e) => o(e, t, r)),
|
|
6373
|
+
selections: n
|
|
6374
|
+
};
|
|
6375
|
+
},
|
|
6376
|
+
getSelectionKeys: () => c(e, s),
|
|
6377
|
+
matcherType: "and"
|
|
6378
|
+
}) });
|
|
6379
|
+
}
|
|
6380
|
+
function y(...e) {
|
|
6381
|
+
return a({ [t]: () => ({
|
|
6382
|
+
match: (t) => {
|
|
6383
|
+
let n = {};
|
|
6384
|
+
const r = (t, e) => {
|
|
6385
|
+
n[t] = e;
|
|
6386
|
+
};
|
|
6387
|
+
return c(e, s).forEach((t) => r(t, void 0)), {
|
|
6388
|
+
matched: e.some((e) => o(e, t, r)),
|
|
6389
|
+
selections: n
|
|
6390
|
+
};
|
|
6391
|
+
},
|
|
6392
|
+
getSelectionKeys: () => c(e, s),
|
|
6393
|
+
matcherType: "or"
|
|
6394
|
+
}) });
|
|
6395
|
+
}
|
|
6396
|
+
function p(e) {
|
|
6397
|
+
return { [t]: () => ({ match: (t) => ({ matched: Boolean(e(t)) }) }) };
|
|
6398
|
+
}
|
|
6399
|
+
function v(...e) {
|
|
6400
|
+
const r = "string" == typeof e[0] ? e[0] : void 0, i = 2 === e.length ? e[1] : "string" == typeof e[0] ? void 0 : e[0];
|
|
6401
|
+
return a({ [t]: () => ({
|
|
6402
|
+
match: (t) => {
|
|
6403
|
+
let e = { [null != r ? r : n]: t };
|
|
6404
|
+
return {
|
|
6405
|
+
matched: void 0 === i || o(i, t, (t, n) => {
|
|
6406
|
+
e[t] = n;
|
|
6407
|
+
}),
|
|
6408
|
+
selections: e
|
|
6409
|
+
};
|
|
6410
|
+
},
|
|
6411
|
+
getSelectionKeys: () => [null != r ? r : n].concat(void 0 === i ? [] : s(i))
|
|
6412
|
+
}) });
|
|
6413
|
+
}
|
|
6414
|
+
function b(t) {
|
|
6415
|
+
return !0;
|
|
6416
|
+
}
|
|
6417
|
+
function w(t) {
|
|
6418
|
+
return "number" == typeof t;
|
|
6419
|
+
}
|
|
6420
|
+
function S(t) {
|
|
6421
|
+
return "string" == typeof t;
|
|
6422
|
+
}
|
|
6423
|
+
function j(t) {
|
|
6424
|
+
return "bigint" == typeof t;
|
|
6425
|
+
}
|
|
6426
|
+
a(p(b));
|
|
6427
|
+
a(p(b));
|
|
6428
|
+
const x = (t) => Object.assign(a(t), {
|
|
6429
|
+
startsWith: (e) => {
|
|
6430
|
+
return x(d(t, (n = e, p((t) => S(t) && t.startsWith(n)))));
|
|
6431
|
+
var n;
|
|
6432
|
+
},
|
|
6433
|
+
endsWith: (e) => {
|
|
6434
|
+
return x(d(t, (n = e, p((t) => S(t) && t.endsWith(n)))));
|
|
6435
|
+
var n;
|
|
6436
|
+
},
|
|
6437
|
+
minLength: (e) => x(d(t, ((t) => p((e) => S(e) && e.length >= t))(e))),
|
|
6438
|
+
length: (e) => x(d(t, ((t) => p((e) => S(e) && e.length === t))(e))),
|
|
6439
|
+
maxLength: (e) => x(d(t, ((t) => p((e) => S(e) && e.length <= t))(e))),
|
|
6440
|
+
includes: (e) => {
|
|
6441
|
+
return x(d(t, (n = e, p((t) => S(t) && t.includes(n)))));
|
|
6442
|
+
var n;
|
|
6443
|
+
},
|
|
6444
|
+
regex: (e) => {
|
|
6445
|
+
return x(d(t, (n = e, p((t) => S(t) && Boolean(t.match(n))))));
|
|
6446
|
+
var n;
|
|
6447
|
+
}
|
|
6448
|
+
});
|
|
6449
|
+
x(p(S));
|
|
6450
|
+
const N = (t) => Object.assign(a(t), {
|
|
6451
|
+
between: (e, n) => N(d(t, ((t, e) => p((n) => w(n) && t <= n && e >= n))(e, n))),
|
|
6452
|
+
lt: (e) => N(d(t, ((t) => p((e) => w(e) && e < t))(e))),
|
|
6453
|
+
gt: (e) => N(d(t, ((t) => p((e) => w(e) && e > t))(e))),
|
|
6454
|
+
lte: (e) => N(d(t, ((t) => p((e) => w(e) && e <= t))(e))),
|
|
6455
|
+
gte: (e) => N(d(t, ((t) => p((e) => w(e) && e >= t))(e))),
|
|
6456
|
+
int: () => N(d(t, p((t) => w(t) && Number.isInteger(t)))),
|
|
6457
|
+
finite: () => N(d(t, p((t) => w(t) && Number.isFinite(t)))),
|
|
6458
|
+
positive: () => N(d(t, p((t) => w(t) && t > 0))),
|
|
6459
|
+
negative: () => N(d(t, p((t) => w(t) && t < 0)))
|
|
6460
|
+
});
|
|
6461
|
+
N(p(w));
|
|
6462
|
+
const k = (t) => Object.assign(a(t), {
|
|
6463
|
+
between: (e, n) => k(d(t, ((t, e) => p((n) => j(n) && t <= n && e >= n))(e, n))),
|
|
6464
|
+
lt: (e) => k(d(t, ((t) => p((e) => j(e) && e < t))(e))),
|
|
6465
|
+
gt: (e) => k(d(t, ((t) => p((e) => j(e) && e > t))(e))),
|
|
6466
|
+
lte: (e) => k(d(t, ((t) => p((e) => j(e) && e <= t))(e))),
|
|
6467
|
+
gte: (e) => k(d(t, ((t) => p((e) => j(e) && e >= t))(e))),
|
|
6468
|
+
positive: () => k(d(t, p((t) => j(t) && t > 0))),
|
|
6469
|
+
negative: () => k(d(t, p((t) => j(t) && t < 0)))
|
|
6470
|
+
});
|
|
6471
|
+
k(p(j)), a(p(function(t) {
|
|
6472
|
+
return "boolean" == typeof t;
|
|
6473
|
+
})), a(p(function(t) {
|
|
6474
|
+
return "symbol" == typeof t;
|
|
6475
|
+
})), a(p(function(t) {
|
|
6476
|
+
return null == t;
|
|
6477
|
+
})), a(p(function(t) {
|
|
6478
|
+
return null != t;
|
|
6479
|
+
}));
|
|
6480
|
+
var I = class extends Error {
|
|
6481
|
+
constructor(t) {
|
|
6482
|
+
let e;
|
|
6483
|
+
try {
|
|
6484
|
+
e = JSON.stringify(t);
|
|
6485
|
+
} catch (n) {
|
|
6486
|
+
e = t;
|
|
6487
|
+
}
|
|
6488
|
+
super(`Pattern matching error: no pattern matches value ${e}`), this.input = void 0, this.input = t;
|
|
6489
|
+
}
|
|
6490
|
+
};
|
|
6491
|
+
const L = {
|
|
6492
|
+
matched: !1,
|
|
6493
|
+
value: void 0
|
|
6494
|
+
};
|
|
6495
|
+
function M(t) {
|
|
6496
|
+
return new R(t, L);
|
|
6497
|
+
}
|
|
6498
|
+
var R = class R {
|
|
6499
|
+
constructor(t, e) {
|
|
6500
|
+
this.input = void 0, this.state = void 0, this.input = t, this.state = e;
|
|
6501
|
+
}
|
|
6502
|
+
with(...t) {
|
|
6503
|
+
if (this.state.matched) return this;
|
|
6504
|
+
const e = t[t.length - 1], r = [t[0]];
|
|
6505
|
+
let i;
|
|
6506
|
+
3 === t.length && "function" == typeof t[1] ? i = t[1] : t.length > 2 && r.push(...t.slice(1, t.length - 1));
|
|
6507
|
+
let s = !1, c = {};
|
|
6508
|
+
const u = (t, e) => {
|
|
6509
|
+
s = !0, c[t] = e;
|
|
6510
|
+
}, a = !r.some((t) => o(t, this.input, u)) || i && !Boolean(i(this.input)) ? L : {
|
|
6511
|
+
matched: !0,
|
|
6512
|
+
value: e(s ? n in c ? c[n] : c : this.input, this.input)
|
|
6513
|
+
};
|
|
6514
|
+
return new R(this.input, a);
|
|
6515
|
+
}
|
|
6516
|
+
when(t, e) {
|
|
6517
|
+
if (this.state.matched) return this;
|
|
6518
|
+
const n = Boolean(t(this.input));
|
|
6519
|
+
return new R(this.input, n ? {
|
|
6520
|
+
matched: !0,
|
|
6521
|
+
value: e(this.input, this.input)
|
|
6522
|
+
} : L);
|
|
6523
|
+
}
|
|
6524
|
+
otherwise(t) {
|
|
6525
|
+
return this.state.matched ? this.state.value : t(this.input);
|
|
6526
|
+
}
|
|
6527
|
+
exhaustive(t = F) {
|
|
6528
|
+
return this.state.matched ? this.state.value : t(this.input);
|
|
6529
|
+
}
|
|
6530
|
+
run() {
|
|
6531
|
+
return this.exhaustive();
|
|
6532
|
+
}
|
|
6533
|
+
returnType() {
|
|
6534
|
+
return this;
|
|
6535
|
+
}
|
|
6536
|
+
narrow() {
|
|
6537
|
+
return this;
|
|
6538
|
+
}
|
|
6539
|
+
};
|
|
6540
|
+
function F(t) {
|
|
6541
|
+
throw new I(t);
|
|
6542
|
+
}
|
|
6543
|
+
//#endregion
|
|
6544
|
+
//#region src/policy/deny-reasons.ts
|
|
6545
|
+
const DENY_REASONS = {
|
|
6546
|
+
"Data Exfiltration": {
|
|
6547
|
+
tier: "hard",
|
|
6548
|
+
harm: "sending sensitive data, such as credentials or private code, off the machine",
|
|
6549
|
+
clears: "No instruction or configuration clears this rule."
|
|
6550
|
+
},
|
|
6551
|
+
"Secret Persistence": {
|
|
6552
|
+
tier: "hard",
|
|
6553
|
+
harm: "writing a credential in plain text into a tracked file, an image, CI configuration, or a shipped log",
|
|
6554
|
+
clears: "No instruction or configuration clears this rule."
|
|
6555
|
+
},
|
|
6556
|
+
"Policy Tampering": {
|
|
6557
|
+
tier: "hard",
|
|
6558
|
+
harm: "changing auto-mode's own configuration, policy, or hook, or the settings that decide whether it runs",
|
|
6559
|
+
clears: "Only a direct user message that explains why this match is wrong clears it; bare consent does not."
|
|
6560
|
+
},
|
|
6561
|
+
"Audit Tampering": {
|
|
6562
|
+
tier: "hard",
|
|
6563
|
+
harm: "deleting or rewriting logs, shell history, audit records, or git history to hide what happened",
|
|
6564
|
+
clears: "Only a direct user message that explains why this match is wrong clears it; bare consent does not."
|
|
6565
|
+
},
|
|
6566
|
+
"Destructive Payload": {
|
|
6567
|
+
tier: "hard",
|
|
6568
|
+
harm: "writing or running code whose purpose is damage or spread",
|
|
6569
|
+
clears: "No instruction or configuration clears this rule."
|
|
6570
|
+
},
|
|
6571
|
+
"Irreversible Deletion": {
|
|
6572
|
+
tier: "soft",
|
|
6573
|
+
harm: "deleting data that no backup, remote, or build step can restore",
|
|
6574
|
+
clears: "A direct user instruction that asks for this deletion and names the path clears it."
|
|
6575
|
+
},
|
|
6576
|
+
"Uncommitted Work Destruction": {
|
|
6577
|
+
tier: "soft",
|
|
6578
|
+
harm: "discarding working-tree changes that exist nowhere else",
|
|
6579
|
+
clears: "A direct user instruction that says those changes go away clears it."
|
|
6580
|
+
},
|
|
6581
|
+
"History Rewrite": {
|
|
6582
|
+
tier: "soft",
|
|
6583
|
+
harm: "rewriting history that others may already hold",
|
|
6584
|
+
clears: "A direct user instruction that names the force push, the rewrite, or the remote branch clears it."
|
|
6585
|
+
},
|
|
6586
|
+
"Default Branch Write": {
|
|
6587
|
+
tier: "soft",
|
|
6588
|
+
harm: "committing, pushing, or merging directly to the default branch",
|
|
6589
|
+
clears: "A direct user instruction that names the branch clears it."
|
|
6590
|
+
},
|
|
6591
|
+
"Publish and Release": {
|
|
6592
|
+
tier: "soft",
|
|
6593
|
+
harm: "putting an artifact where other people install it",
|
|
6594
|
+
clears: "A direct user instruction that says publish, release, or deploy and names the target clears it."
|
|
6595
|
+
},
|
|
6596
|
+
"Outbound Communication": {
|
|
6597
|
+
tier: "soft",
|
|
6598
|
+
harm: "sending content that reaches another person",
|
|
6599
|
+
clears: "A direct user instruction that says the message is sent, and to whom or where, clears it."
|
|
6600
|
+
},
|
|
6601
|
+
"Remote Code Execution": {
|
|
6602
|
+
tier: "soft",
|
|
6603
|
+
harm: "running code fetched from a source the user did not name",
|
|
6604
|
+
clears: "A direct user instruction that names the source clears it."
|
|
6605
|
+
},
|
|
6606
|
+
"Obfuscated Command": {
|
|
6607
|
+
tier: "soft",
|
|
6608
|
+
harm: "running a command whose payload cannot be read",
|
|
6609
|
+
clears: "A direct user message that supplies the decoded command or states what it runs clears it."
|
|
6610
|
+
},
|
|
6611
|
+
"Network Exposure": {
|
|
6612
|
+
tier: "soft",
|
|
6613
|
+
harm: "making this machine or its files reachable from outside it",
|
|
6614
|
+
clears: "A direct user instruction that names the service and says it becomes reachable clears it."
|
|
6615
|
+
},
|
|
6616
|
+
"Unnamed Destination": {
|
|
6617
|
+
tier: "soft",
|
|
6618
|
+
harm: "sending content to a network destination the user never named",
|
|
6619
|
+
clears: "A direct user instruction that names the destination clears it."
|
|
6620
|
+
},
|
|
6621
|
+
"Shared Infrastructure": {
|
|
6622
|
+
tier: "soft",
|
|
6623
|
+
harm: "changing a cluster, a cloud account, a remote host, or a repository's settings",
|
|
6624
|
+
clears: "A direct user instruction that names the environment or the resource clears it."
|
|
6625
|
+
},
|
|
6626
|
+
"Destructive Database Operation": {
|
|
6627
|
+
tier: "soft",
|
|
6628
|
+
harm: "deleting or overwriting stored data wholesale in a database that is not local",
|
|
6629
|
+
clears: "A direct user instruction that names the table or the database, and the operation, clears it."
|
|
6630
|
+
},
|
|
6631
|
+
"Persistent Configuration": {
|
|
6632
|
+
tier: "soft",
|
|
6633
|
+
harm: "a change that outlives the session or widens access on this machine",
|
|
6634
|
+
clears: "A direct user instruction that names the file or the setting clears it."
|
|
6635
|
+
},
|
|
6636
|
+
"Credential Exploration": {
|
|
6637
|
+
tier: "soft",
|
|
6638
|
+
harm: "reading or searching for credentials the task never called for",
|
|
6639
|
+
clears: "A direct user instruction that names the file or the search clears it."
|
|
6640
|
+
},
|
|
6641
|
+
"Interrupted Action Retry": {
|
|
6642
|
+
tier: "soft",
|
|
6643
|
+
harm: "running again an action the user interrupted",
|
|
6644
|
+
clears: "A direct user instruction that asks for the action to run again clears it."
|
|
6645
|
+
},
|
|
6646
|
+
"Security Control Removal": {
|
|
6647
|
+
tier: "soft",
|
|
6648
|
+
harm: "removing a control that protects someone other than the agent",
|
|
6649
|
+
clears: "A direct user instruction that names the control clears it."
|
|
6650
|
+
},
|
|
6651
|
+
"Mass Modification": {
|
|
6652
|
+
tier: "soft",
|
|
6653
|
+
harm: "changing many things at once with no way to restore them",
|
|
6654
|
+
clears: "A direct user instruction that names the scope clears it."
|
|
6655
|
+
}
|
|
6656
|
+
};
|
|
6657
|
+
//#endregion
|
|
6658
|
+
//#region src/policy/build-deny-reason.ts
|
|
6659
|
+
function buildDenyReason(rule, basis) {
|
|
6660
|
+
const template = getReasonTemplate(rule);
|
|
6661
|
+
return `${basis === "matched" ? `The action matches this rule: ${template.harm}.` : `The supplied evidence cannot rule out ${template.harm}.`} ${template.clears}`;
|
|
6662
|
+
}
|
|
6663
|
+
function getReasonTemplate(rule) {
|
|
6664
|
+
return M(rule.source).with("shipped", () => {
|
|
6665
|
+
const template = DENY_REASONS[rule.name];
|
|
6666
|
+
if (template === void 0) throw new Error(`No deny reason for the shipped rule ${rule.name}`);
|
|
6667
|
+
return template;
|
|
6668
|
+
}).with("configured", () => rule.tier === "hard" ? {
|
|
6669
|
+
harm: "an action that a hard deny entry in the user's auto-mode configuration covers",
|
|
6670
|
+
clears: "Only a change to that configuration clears it."
|
|
6671
|
+
} : {
|
|
6672
|
+
harm: "an action that a soft deny entry in the user's auto-mode configuration covers",
|
|
6673
|
+
clears: "A direct user instruction that asks for this specific action clears it."
|
|
6674
|
+
}).with("replacement", () => ({
|
|
6675
|
+
harm: "the harm this rule of the configured replacement policy describes",
|
|
6676
|
+
clears: "The replacement policy defines what clears it."
|
|
6677
|
+
})).exhaustive();
|
|
6678
|
+
}
|
|
6679
|
+
//#endregion
|
|
6680
|
+
//#region src/model/pick-decision-verdict.ts
|
|
6681
|
+
function pickDecisionVerdict(request, result, minConfidence) {
|
|
6682
|
+
return M(classifyDecisionAnswers(request, result, minConfidence)).with({ kind: "allow" }, () => ({ kind: "allow" })).with({ kind: "block" }, (decision) => ({
|
|
6683
|
+
kind: "deny",
|
|
6684
|
+
rule: decision.rule.name,
|
|
6685
|
+
reason: buildDenyReason(decision.rule, "matched")
|
|
6686
|
+
})).with({ kind: "uncertain" }, (decision) => ({
|
|
6687
|
+
kind: "deny",
|
|
6688
|
+
rule: decision.rule.name,
|
|
6689
|
+
reason: buildDenyReason(decision.rule, "unresolved")
|
|
6690
|
+
})).exhaustive();
|
|
6691
|
+
}
|
|
6692
|
+
//#endregion
|
|
6693
|
+
//#region src/model/send-decision.ts
|
|
6694
|
+
async function sendDecision(provider, apiKey, request, signal) {
|
|
6695
|
+
const input = {
|
|
6696
|
+
model: provider.model,
|
|
6697
|
+
state: { ...request.state },
|
|
6698
|
+
questions: request.questions
|
|
6699
|
+
};
|
|
6700
|
+
let body = JSON.stringify(input);
|
|
6701
|
+
for (const field of ["delegatedTask", "originalUserTask"]) {
|
|
6702
|
+
const context = input.state.taskContext;
|
|
6703
|
+
if (Buffer.byteLength(body) <= 1e5 || context === void 0 || context[field] === null) continue;
|
|
6704
|
+
input.state.taskContext = {
|
|
6705
|
+
...context,
|
|
6706
|
+
[field]: null,
|
|
6707
|
+
omittedTaskContext: [...context.omittedTaskContext.filter((item) => item.field !== field), {
|
|
6708
|
+
field,
|
|
6709
|
+
reason: "budget"
|
|
6710
|
+
}]
|
|
6711
|
+
};
|
|
6712
|
+
body = JSON.stringify(input);
|
|
6713
|
+
}
|
|
6714
|
+
const requestBytes = Buffer.byteLength(body);
|
|
6715
|
+
if (requestBytes > 1e5) throw new DecisionRequestError("request-too-large", requestBytes, "Decision input exceeds 100000 bytes; refusing to truncate the action or user message");
|
|
6716
|
+
const controller = new AbortController();
|
|
6717
|
+
const stopRequest = () => {
|
|
6718
|
+
controller.abort();
|
|
6719
|
+
};
|
|
6720
|
+
signal?.addEventListener("abort", stopRequest, { once: true });
|
|
6721
|
+
if (signal?.aborted === true) controller.abort();
|
|
6722
|
+
const timer = setTimeout(() => {
|
|
6723
|
+
controller.abort();
|
|
6724
|
+
}, provider.timeoutMs);
|
|
6725
|
+
try {
|
|
6726
|
+
let response;
|
|
6727
|
+
try {
|
|
6728
|
+
response = await fetch(`${provider.baseURL.replace(/\/$/, "")}/v1/systemone`, {
|
|
6729
|
+
method: "POST",
|
|
6730
|
+
signal: controller.signal,
|
|
6731
|
+
headers: {
|
|
6732
|
+
"content-type": "application/json",
|
|
6733
|
+
authorization: `Bearer ${apiKey}`
|
|
6734
|
+
},
|
|
6735
|
+
body
|
|
6736
|
+
});
|
|
6737
|
+
} catch (error) {
|
|
6738
|
+
if (error instanceof Error && error.name === "AbortError") throw new DecisionRequestError("aborted", requestBytes, "Decision request aborted", { cause: error });
|
|
6739
|
+
throw new DecisionRequestError("network", requestBytes, "Decision API request failed");
|
|
6740
|
+
}
|
|
6741
|
+
if (!response.ok) throw new DecisionRequestError("http-status", requestBytes, `Decision API returned HTTP ${response.status}`);
|
|
6742
|
+
const probability = number().min(0).max(1);
|
|
6743
|
+
const answer = object({
|
|
6744
|
+
type: literal("choice"),
|
|
6745
|
+
choice: _enum([
|
|
6746
|
+
"allow",
|
|
6747
|
+
"block",
|
|
6748
|
+
"ask"
|
|
6749
|
+
]),
|
|
6750
|
+
confidence: probability,
|
|
6751
|
+
probabilities: strictObject({
|
|
6752
|
+
allow: probability,
|
|
6753
|
+
block: probability,
|
|
6754
|
+
ask: probability
|
|
6755
|
+
})
|
|
6127
6756
|
});
|
|
6128
6757
|
const schema = object({
|
|
6129
6758
|
model: string().min(1),
|
|
@@ -6208,7 +6837,7 @@ async function classifyWithJev(payload, config, options = {}) {
|
|
|
6208
6837
|
requestBytes: result.requestBytes,
|
|
6209
6838
|
elapsedMs: Math.round(performance.now() - start),
|
|
6210
6839
|
minConfidence,
|
|
6211
|
-
contributors: collectDecisionContributors(request, result,
|
|
6840
|
+
contributors: collectDecisionContributors(request, result, minConfidence)
|
|
6212
6841
|
},
|
|
6213
6842
|
note: formatClassifierNote(`${config.provider.model}: ${verdict.kind} (${Math.round(performance.now() - start)}ms, ${result.inputTokens} input tokens)`, key)
|
|
6214
6843
|
};
|
|
@@ -6260,10 +6889,20 @@ function parseModelVerdict(text) {
|
|
|
6260
6889
|
const rule = RULE.exec(text)?.[1]?.trim();
|
|
6261
6890
|
if (rule === void 0 || rule === "") return { kind: "allow" };
|
|
6262
6891
|
const stripped = (REASON.exec(text)?.[1]?.trim())?.replace(/^\[[^\]]*\]\s*/, "") ?? "";
|
|
6892
|
+
if (stripped !== "") return {
|
|
6893
|
+
kind: "deny",
|
|
6894
|
+
rule,
|
|
6895
|
+
reason: stripped
|
|
6896
|
+
};
|
|
6897
|
+
const template = DENY_REASONS[rule];
|
|
6263
6898
|
return {
|
|
6264
6899
|
kind: "deny",
|
|
6265
6900
|
rule,
|
|
6266
|
-
reason:
|
|
6901
|
+
reason: template === void 0 ? "The action matches this rule." : buildDenyReason({
|
|
6902
|
+
name: rule,
|
|
6903
|
+
tier: template.tier,
|
|
6904
|
+
source: "shipped"
|
|
6905
|
+
}, "matched")
|
|
6267
6906
|
};
|
|
6268
6907
|
}
|
|
6269
6908
|
//#endregion
|
|
@@ -6321,6 +6960,11 @@ function toMessage(error) {
|
|
|
6321
6960
|
return error instanceof Error ? error.message : String(error);
|
|
6322
6961
|
}
|
|
6323
6962
|
//#endregion
|
|
6963
|
+
//#region src/policy/read-denial-guidance.ts
|
|
6964
|
+
async function readDenialGuidance() {
|
|
6965
|
+
return (await readFile(join(resolveShippedPolicyDir(), "denial.md"), "utf8")).trim();
|
|
6966
|
+
}
|
|
6967
|
+
//#endregion
|
|
6324
6968
|
//#region node_modules/.bun/tiny-invariant@1.3.3/node_modules/tiny-invariant/dist/esm/tiny-invariant.js
|
|
6325
6969
|
var isProduction = process.env.NODE_ENV === "production";
|
|
6326
6970
|
var prefix = "Invariant failed";
|
|
@@ -6557,12 +7201,9 @@ async function classifyAction(request, config, options = {}) {
|
|
|
6557
7201
|
if (config.provider.protocol === "system-one") try {
|
|
6558
7202
|
configured = await loadClaudeRules(config.claudeSettingsPath);
|
|
6559
7203
|
} catch {
|
|
7204
|
+
const guidance = config.onFailure === "deny" ? await tryReadDenialGuidance() : null;
|
|
6560
7205
|
return {
|
|
6561
|
-
verdict: config.onFailure === "deny" ?
|
|
6562
|
-
kind: "deny",
|
|
6563
|
-
rule: "Classifier Unavailable",
|
|
6564
|
-
reason: "Claude settings unreadable"
|
|
6565
|
-
} : null,
|
|
7206
|
+
verdict: config.onFailure === "deny" ? buildGuidedDeny("Classifier Unavailable", "Claude settings unreadable.", guidance) : null,
|
|
6566
7207
|
note: "Claude settings unreadable; classifier unavailable",
|
|
6567
7208
|
status: "failure",
|
|
6568
7209
|
unavailable: true
|
|
@@ -6579,12 +7220,28 @@ async function classifyAction(request, config, options = {}) {
|
|
|
6579
7220
|
note: `${request.toolName} needs the model tier, which this run skipped`,
|
|
6580
7221
|
status: "skipped"
|
|
6581
7222
|
};
|
|
6582
|
-
const outcome = await classifyWithModel(request, config, options);
|
|
7223
|
+
const [outcome, guidance] = await Promise.all([classifyWithModel(request, config, options), tryReadDenialGuidance()]);
|
|
6583
7224
|
return {
|
|
6584
7225
|
...outcome,
|
|
7226
|
+
verdict: outcome.verdict?.kind === "deny" ? buildGuidedDeny(outcome.verdict.rule, outcome.verdict.reason, guidance) : outcome.verdict,
|
|
6585
7227
|
status: outcome.diagnostics?.status ?? outcome.verdict?.kind ?? "failure"
|
|
6586
7228
|
};
|
|
6587
7229
|
}
|
|
7230
|
+
function buildGuidedDeny(rule, reason, guidance) {
|
|
7231
|
+
const sentence = /[.!?]$/u.test(reason) ? reason : `${reason}.`;
|
|
7232
|
+
return {
|
|
7233
|
+
kind: "deny",
|
|
7234
|
+
rule,
|
|
7235
|
+
reason: guidance === null ? sentence : `${sentence} ${guidance}`
|
|
7236
|
+
};
|
|
7237
|
+
}
|
|
7238
|
+
async function tryReadDenialGuidance() {
|
|
7239
|
+
try {
|
|
7240
|
+
return await readDenialGuidance();
|
|
7241
|
+
} catch {
|
|
7242
|
+
return null;
|
|
7243
|
+
}
|
|
7244
|
+
}
|
|
6588
7245
|
//#endregion
|
|
6589
7246
|
//#region src/request/parse-action-request.ts
|
|
6590
7247
|
const userTaskSchema = strictObject({
|
|
@@ -6635,260 +7292,12 @@ function parseActionRequest(body) {
|
|
|
6635
7292
|
};
|
|
6636
7293
|
}
|
|
6637
7294
|
//#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
7295
|
//#region src/request/render-verdict.ts
|
|
6887
7296
|
function renderVerdict(verdict) {
|
|
6888
|
-
return M(verdict).with({ kind: "
|
|
7297
|
+
return M(verdict).with({ kind: "allow" }, () => JSON.stringify({ decision: "allow" })).with({ kind: "deny" }, (denied) => JSON.stringify({
|
|
6889
7298
|
decision: "deny",
|
|
6890
7299
|
reason: `[${denied.rule}] ${denied.reason}`
|
|
6891
7300
|
})).exhaustive();
|
|
6892
7301
|
}
|
|
6893
7302
|
//#endregion
|
|
6894
|
-
export { classifyWithModel as a, DEFAULT_CONFIG as c,
|
|
7303
|
+
export { classifyWithModel as a, DEFAULT_CONFIG as c, resolveConfigPath as d, normalizeConfigFile as f, classifyLocally as i, loadConfig as l, parseActionRequest as n, parseModelVerdict as o, PRESETS as p, classifyAction as r, loadPolicy as s, renderVerdict as t, resolveApiKey as u };
|