rulesync 43.6.2 → 43.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/dist/cli/index.cjs +3 -3
- package/dist/cli/index.js +3 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-8kSEsosv.cjs → import-CfxyzbvB.cjs} +144 -48
- package/dist/{import-iLVVcze8.js → import-tr3jHcG2.js} +145 -49
- package/dist/{import-iLVVcze8.js.map → import-tr3jHcG2.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +12 -12
|
@@ -9745,11 +9745,9 @@ var RulesyncPermissions = class RulesyncPermissions extends RulesyncFile {
|
|
|
9745
9745
|
* `PERMISSION_OVERRIDE_KEY_ALIASES`) is replaced wholesale, and removed when
|
|
9746
9746
|
* the import does not produce one: only that tool's import ever writes it, so
|
|
9747
9747
|
* a setting removed from the tool's own config has to disappear here too.
|
|
9748
|
-
*
|
|
9749
|
-
*
|
|
9750
|
-
*
|
|
9751
|
-
* `permission` record inside the block merges per category. Every other
|
|
9752
|
-
* top-level key — `$schema` included — is kept unless the import names it.
|
|
9748
|
+
* Every other top-level key — `$schema` included — is kept unless the import
|
|
9749
|
+
* names it, in which case the imported value replaces it. No importer emits
|
|
9750
|
+
* another tool's override block, so those blocks are never touched here.
|
|
9753
9751
|
*/
|
|
9754
9752
|
static mergeImportedJson({ existing, imported, toolTarget }) {
|
|
9755
9753
|
const ownOverrideKey = PERMISSION_OVERRIDE_KEY_ALIASES[toolTarget] ?? toolTarget;
|
|
@@ -9761,14 +9759,7 @@ var RulesyncPermissions = class RulesyncPermissions extends RulesyncFile {
|
|
|
9761
9759
|
existing: current,
|
|
9762
9760
|
imported: value
|
|
9763
9761
|
});
|
|
9764
|
-
else
|
|
9765
|
-
const block = { ...current };
|
|
9766
|
-
for (const [field, fieldValue] of Object.entries(value)) block[field] = field === "permission" ? mergePermissionCategories({
|
|
9767
|
-
existing: block[field],
|
|
9768
|
-
imported: fieldValue
|
|
9769
|
-
}) : fieldValue;
|
|
9770
|
-
merged[key] = block;
|
|
9771
|
-
} else merged[key] = value;
|
|
9762
|
+
else merged[key] = value;
|
|
9772
9763
|
}
|
|
9773
9764
|
return merged;
|
|
9774
9765
|
}
|
|
@@ -29131,11 +29122,7 @@ var ZoocodeSkill = class extends RooSkill {
|
|
|
29131
29122
|
static toolTarget = "zoocode";
|
|
29132
29123
|
};
|
|
29133
29124
|
// src/features/skills/skills-processor.ts
|
|
29134
|
-
var skills_processor_exports = /* @__PURE__ */ __exportAll({
|
|
29135
|
-
SkillsProcessor: () => SkillsProcessor,
|
|
29136
|
-
SkillsProcessorToolTargetSchema: () => SkillsProcessorToolTargetSchema,
|
|
29137
|
-
toolSkillFactories: () => toolSkillFactories
|
|
29138
|
-
});
|
|
29125
|
+
var skills_processor_exports = /* @__PURE__ */ __exportAll({ toolSkillFactories: () => toolSkillFactories });
|
|
29139
29126
|
const SkillsProcessorToolTargetSchema = zod_mini.z.enum(skillsProcessorToolTargetTuple);
|
|
29140
29127
|
/**
|
|
29141
29128
|
* Factory Map mapping tool targets to their skill factories.
|
|
@@ -52429,6 +52416,29 @@ var AmpHooks = class AmpHooks extends ToolHooks {
|
|
|
52429
52416
|
});
|
|
52430
52417
|
}
|
|
52431
52418
|
};
|
|
52419
|
+
// src/features/hooks/hook-matcher-tool-names.ts
|
|
52420
|
+
const MATCHER_TOKEN_PATTERN = /\\.|\[(?:\\.|[^\]\\])*\]|(?<=^|[^\w\\]|\\\w)[A-Za-z_]\w*(?!\w)/gs;
|
|
52421
|
+
function isMatcherName(token) {
|
|
52422
|
+
return !token.startsWith("\\") && !token.startsWith("[");
|
|
52423
|
+
}
|
|
52424
|
+
/**
|
|
52425
|
+
* The distinct whole names in a matcher that start with a capital letter, for
|
|
52426
|
+
* adapters whose runtime tool names are all lowercase: after translation, such
|
|
52427
|
+
* a name has no runtime equivalent and can never match.
|
|
52428
|
+
*/
|
|
52429
|
+
function capitalizedMatcherNames(matcher) {
|
|
52430
|
+
const names = [...matcher.matchAll(MATCHER_TOKEN_PATTERN)].map(([token]) => token).filter((token) => isMatcherName(token) && /^[A-Z]/.test(token));
|
|
52431
|
+
return [...new Set(names)];
|
|
52432
|
+
}
|
|
52433
|
+
/**
|
|
52434
|
+
* Rewrites the whole tool names inside a hook `matcher` regex through `names`,
|
|
52435
|
+
* leaving escapes, character classes and unknown names as written. Used by
|
|
52436
|
+
* adapters whose runtime tool names differ from the canonical (Claude Code)
|
|
52437
|
+
* spelling.
|
|
52438
|
+
*/
|
|
52439
|
+
function replaceMatcherNames(matcher, names) {
|
|
52440
|
+
return matcher.replace(MATCHER_TOKEN_PATTERN, (token) => isMatcherName(token) && Object.hasOwn(names, token) ? names[token] ?? token : token);
|
|
52441
|
+
}
|
|
52432
52442
|
// src/utils/object.ts
|
|
52433
52443
|
/**
|
|
52434
52444
|
* Return a shallow copy of `obj` keeping only the entries whose value is
|
|
@@ -54349,6 +54359,48 @@ const ANTIGRAVITY_FLAT_HANDLER_EVENTS = new Set([...ANTIGRAVITY_NO_MATCHER_EVENT
|
|
|
54349
54359
|
record: CANONICAL_TO_ANTIGRAVITY_EVENT_NAMES,
|
|
54350
54360
|
key: event
|
|
54351
54361
|
}) ?? event));
|
|
54362
|
+
const CANONICAL_TO_ANTIGRAVITY_TOOL_NAMES = {
|
|
54363
|
+
Bash: "run_command",
|
|
54364
|
+
Read: "(?:read_file|view_file)",
|
|
54365
|
+
Write: "(?:write_file|write_to_file)",
|
|
54366
|
+
Edit: "(?:edit_file|replace_file_content)",
|
|
54367
|
+
WebSearch: "search_web"
|
|
54368
|
+
};
|
|
54369
|
+
const ANTIGRAVITY_TO_CANONICAL_TOOL_NAMES = {
|
|
54370
|
+
run_command: "Bash",
|
|
54371
|
+
read_file: "Read",
|
|
54372
|
+
view_file: "Read",
|
|
54373
|
+
write_file: "Write",
|
|
54374
|
+
write_to_file: "Write",
|
|
54375
|
+
edit_file: "Edit",
|
|
54376
|
+
replace_file_content: "Edit",
|
|
54377
|
+
search_web: "WebSearch"
|
|
54378
|
+
};
|
|
54379
|
+
const ANTIGRAVITY_GROUP_TO_CANONICAL_TOOL_NAMES = Object.entries(CANONICAL_TO_ANTIGRAVITY_TOOL_NAMES).filter(([, name]) => name.startsWith("(?:")).map(([canonical, group]) => [group, canonical]);
|
|
54380
|
+
const ANTIGRAVITY_DOCUMENTED_TOOL_CANDIDATES = {
|
|
54381
|
+
Grep: "grep_search",
|
|
54382
|
+
Glob: "find_by_name",
|
|
54383
|
+
WebFetch: "read_url_content",
|
|
54384
|
+
MultiEdit: "multi_replace_file_content"
|
|
54385
|
+
};
|
|
54386
|
+
function canonicalToAntigravityMatcher({ matcher, eventName, warn }) {
|
|
54387
|
+
const translated = replaceMatcherNames(matcher, CANONICAL_TO_ANTIGRAVITY_TOOL_NAMES);
|
|
54388
|
+
const unmatched = capitalizedMatcherNames(translated);
|
|
54389
|
+
if (unmatched.length > 0) {
|
|
54390
|
+
const candidates = unmatched.flatMap((name) => {
|
|
54391
|
+
const candidate = lookupOwn({
|
|
54392
|
+
record: ANTIGRAVITY_DOCUMENTED_TOOL_CANDIDATES,
|
|
54393
|
+
key: name
|
|
54394
|
+
});
|
|
54395
|
+
return candidate ? [`\`${candidate}\` for ${quoteValueForWarning(name)}`] : [];
|
|
54396
|
+
});
|
|
54397
|
+
warn(`Antigravity reports lowercase tool names in the hook payload (\`toolCall.name\`), and ${unmatched.map((name) => quoteValueForWarning(name)).join(", ")} in the "${eventName}" matcher ${quoteValueForWarning(matcher)} has no verified Antigravity equivalent, so it is written as-is and will likely never match. Use the tool name Antigravity reports instead` + (candidates.length > 0 ? ` (the Antigravity hooks docs list ${candidates.join(", ")}, unverified).` : "."));
|
|
54398
|
+
}
|
|
54399
|
+
return translated;
|
|
54400
|
+
}
|
|
54401
|
+
function antigravityToCanonicalMatcher(matcher) {
|
|
54402
|
+
return replaceMatcherNames(ANTIGRAVITY_GROUP_TO_CANONICAL_TOOL_NAMES.reduce((current, [group, canonical]) => current.split(group).join(canonical), matcher), ANTIGRAVITY_TO_CANONICAL_TOOL_NAMES);
|
|
54403
|
+
}
|
|
54352
54404
|
/**
|
|
54353
54405
|
* Antigravity uses a Claude-Code-like `hooks.json`. The `PreToolUse` /
|
|
54354
54406
|
* `PostToolUse` events use the matcher-based group shape, while `SessionStart`,
|
|
@@ -54362,7 +54414,11 @@ const ANTIGRAVITY_CONVERTER_CONFIG = {
|
|
|
54362
54414
|
toolToCanonicalEventNames: ANTIGRAVITY_TO_CANONICAL_EVENT_NAMES,
|
|
54363
54415
|
projectDirVar: "",
|
|
54364
54416
|
noMatcherEvents: ANTIGRAVITY_NO_MATCHER_EVENTS,
|
|
54365
|
-
supportedHookTypes: /* @__PURE__ */ new Set(["command"])
|
|
54417
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command"]),
|
|
54418
|
+
matcherTranslation: {
|
|
54419
|
+
toTool: canonicalToAntigravityMatcher,
|
|
54420
|
+
toCanonical: antigravityToCanonicalMatcher
|
|
54421
|
+
}
|
|
54366
54422
|
};
|
|
54367
54423
|
/**
|
|
54368
54424
|
* Turn the shared converter's matcher-group output into Antigravity's shape:
|
|
@@ -57395,20 +57451,6 @@ var CopilotcliHooks = class CopilotcliHooks extends ToolHooks {
|
|
|
57395
57451
|
}), null, 2) });
|
|
57396
57452
|
}
|
|
57397
57453
|
};
|
|
57398
|
-
// src/features/hooks/hook-matcher-tool-names.ts
|
|
57399
|
-
const MATCHER_TOKEN_PATTERN = /\\.|\[(?:\\.|[^\]\\])*\]|(?<=^|[^\w\\]|\\\w)[A-Za-z_]\w*(?!\w)/gs;
|
|
57400
|
-
function isMatcherName(token) {
|
|
57401
|
-
return !token.startsWith("\\") && !token.startsWith("[");
|
|
57402
|
-
}
|
|
57403
|
-
/**
|
|
57404
|
-
* Rewrites the whole tool names inside a hook `matcher` regex through `names`,
|
|
57405
|
-
* leaving escapes, character classes and unknown names as written. Used by
|
|
57406
|
-
* adapters whose runtime tool names differ from the canonical (Claude Code)
|
|
57407
|
-
* spelling.
|
|
57408
|
-
*/
|
|
57409
|
-
function replaceMatcherNames(matcher, names) {
|
|
57410
|
-
return matcher.replace(MATCHER_TOKEN_PATTERN, (token) => isMatcherName(token) && Object.hasOwn(names, token) ? names[token] ?? token : token);
|
|
57411
|
-
}
|
|
57412
57454
|
// src/features/hooks/cortexcode-hooks.ts
|
|
57413
57455
|
const CORTEXCODE_NO_MATCHER_EVENTS = /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"]);
|
|
57414
57456
|
const CANONICAL_TO_CORTEXCODE_TOOL_NAMES = {
|
|
@@ -57422,8 +57464,8 @@ const CANONICAL_TO_CORTEXCODE_TOOL_NAMES = {
|
|
|
57422
57464
|
const CORTEXCODE_TO_CANONICAL_TOOL_NAMES = invertRecord(CANONICAL_TO_CORTEXCODE_TOOL_NAMES);
|
|
57423
57465
|
function canonicalToCortexcodeMatcher({ matcher, eventName, warn }) {
|
|
57424
57466
|
const translated = replaceMatcherNames(matcher, CANONICAL_TO_CORTEXCODE_TOOL_NAMES);
|
|
57425
|
-
const unmatched =
|
|
57426
|
-
if (unmatched.length > 0) warn(`Cortex Code matches hook matchers case-sensitively against lowercase runtime tool names, and ${
|
|
57467
|
+
const unmatched = capitalizedMatcherNames(translated);
|
|
57468
|
+
if (unmatched.length > 0) warn(`Cortex Code matches hook matchers case-sensitively against lowercase runtime tool names, and ${unmatched.map((name) => quoteValueForWarning(name)).join(", ")} in the "${eventName}" matcher ${quoteValueForWarning(matcher)} is not a tool Cortex Code documents a runtime ID for, so it is written as-is and will likely never match. Replace it with the lowercase name Cortex Code uses for that tool, if it has one.`);
|
|
57427
57469
|
return translated;
|
|
57428
57470
|
}
|
|
57429
57471
|
function cortexcodeToCanonicalMatcher(matcher) {
|
|
@@ -79859,6 +79901,39 @@ const MATCH_ALL_PATH_GLOBS = /* @__PURE__ */ new Set([
|
|
|
79859
79901
|
]);
|
|
79860
79902
|
const DIRECTORY_CONTENTS_SUFFIX = /\/\*\*(?:\/\*)?$/;
|
|
79861
79903
|
const HOME_OR_VARIABLE_PATH = /^~(?:\/|$)|^\$[A-Za-z_]|\$\{[A-Za-z_]/;
|
|
79904
|
+
const LEADING_HOME = /^~(?:\/|$)/;
|
|
79905
|
+
/**
|
|
79906
|
+
* The home directory as an Antigravity path: forward slashes, no trailing
|
|
79907
|
+
* slash. agy accepts `C:/Users/...` on Windows, so one spelling serves both.
|
|
79908
|
+
*/
|
|
79909
|
+
function toAntigravityHomePath(homeDirectory) {
|
|
79910
|
+
return homeDirectory.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
79911
|
+
}
|
|
79912
|
+
/**
|
|
79913
|
+
* Rewrite a leading `~` or `~/` of a path target to the absolute home
|
|
79914
|
+
* directory. agy 1.5.1 matches `~` literally, so a `~/...` rule would never
|
|
79915
|
+
* apply (rulesync#3324). Only a file the user's own home holds, such as the
|
|
79916
|
+
* global Antigravity CLI settings, may carry a machine-specific path, so the
|
|
79917
|
+
* caller passes `homeDirectory` only then. `$HOME`, `${HOME}`, `%VAR%` and
|
|
79918
|
+
* `~user/` are left as written (the variable forms are still warned about).
|
|
79919
|
+
*/
|
|
79920
|
+
function expandLeadingHome(target, homeDirectory) {
|
|
79921
|
+
if (homeDirectory === void 0 || !LEADING_HOME.test(target)) return target;
|
|
79922
|
+
const home = toAntigravityHomePath(homeDirectory);
|
|
79923
|
+
return target === "~" ? home || "/" : `${home}${target.slice(1)}`;
|
|
79924
|
+
}
|
|
79925
|
+
/**
|
|
79926
|
+
* The reverse of {@link expandLeadingHome} on import: an absolute path in the
|
|
79927
|
+
* home directory goes back to `~/...`, so `.rulesync/permissions.jsonc` stays
|
|
79928
|
+
* the same on every machine.
|
|
79929
|
+
*/
|
|
79930
|
+
function collapseLeadingHome(target, homeDirectory) {
|
|
79931
|
+
if (homeDirectory === void 0) return target;
|
|
79932
|
+
const home = toAntigravityHomePath(homeDirectory);
|
|
79933
|
+
if (home.length === 0) return target;
|
|
79934
|
+
if (target === home) return "~";
|
|
79935
|
+
return target.startsWith(`${home}/`) ? `~${target.slice(home.length)}` : target;
|
|
79936
|
+
}
|
|
79862
79937
|
const HOSTNAME = /^[a-z0-9-]+(?:\.[a-z0-9-]+)*$/;
|
|
79863
79938
|
const DENY_HINTS = {
|
|
79864
79939
|
read_file: "deny a directory or file path instead",
|
|
@@ -80011,13 +80086,14 @@ function warnHomeOrVariablePath({ action, target, rule, decision, logger, toolLa
|
|
|
80011
80086
|
* nothing enforces it, and a widened one is warned about too, because it
|
|
80012
80087
|
* blocks more than it says.
|
|
80013
80088
|
*/
|
|
80014
|
-
function buildAntigravityPermissionEntry({ action: toolAction, category, pattern, decision, logger, toolLabel }) {
|
|
80089
|
+
function buildAntigravityPermissionEntry({ action: toolAction, category, pattern, decision, logger, toolLabel, homeDirectory }) {
|
|
80015
80090
|
const isMcp = category.startsWith(MCP_CATEGORY_PREFIX);
|
|
80016
80091
|
const action = isMcp ? "mcp" : toolAction;
|
|
80017
80092
|
const result = isMcp ? toMcpRuleTarget(category, pattern) : pattern === "*" ? { target: "*" } : toTarget(action, pattern);
|
|
80018
80093
|
const rule = `${category}: { "${pattern}": "${decision}" }`;
|
|
80019
80094
|
if ("skipReason" in result) {
|
|
80020
|
-
const
|
|
80095
|
+
const lead = decision !== "deny" ? void 0 : isMcp ? result.lead : toWidenedDenyTarget(action, pattern);
|
|
80096
|
+
const prefix = lead !== void 0 && PATH_ACTIONS.has(action) ? expandLeadingHome(lead, homeDirectory) : lead;
|
|
80021
80097
|
if (prefix !== void 0) {
|
|
80022
80098
|
const { entry, scope } = describeWidenedDeny({
|
|
80023
80099
|
action,
|
|
@@ -80043,22 +80119,23 @@ function buildAntigravityPermissionEntry({ action: toolAction, category, pattern
|
|
|
80043
80119
|
const consequence = decision === "deny" ? ", so the deny also overrides any allow or ask there" : "";
|
|
80044
80120
|
logger.warn(`${toolLabel} permissions: ${rule}: ${result.note}${consequence}.`);
|
|
80045
80121
|
}
|
|
80122
|
+
const target = PATH_ACTIONS.has(action) ? expandLeadingHome(result.target, homeDirectory) : result.target;
|
|
80046
80123
|
warnHomeOrVariablePath({
|
|
80047
80124
|
action,
|
|
80048
|
-
target
|
|
80125
|
+
target,
|
|
80049
80126
|
rule,
|
|
80050
80127
|
decision,
|
|
80051
80128
|
logger,
|
|
80052
80129
|
toolLabel
|
|
80053
80130
|
});
|
|
80054
|
-
return
|
|
80131
|
+
return target === "*" ? action : `${action}(${target})`;
|
|
80055
80132
|
}
|
|
80056
80133
|
/**
|
|
80057
80134
|
* Convert rulesync permissions config to Antigravity allow/ask/deny arrays,
|
|
80058
80135
|
* shared by the CLI and IDE generators; `toAction` maps a canonical category to
|
|
80059
80136
|
* the target's tool or action name.
|
|
80060
80137
|
*/
|
|
80061
|
-
function convertRulesyncToAntigravityPermissions({ config, toAction, toolLabel, logger }) {
|
|
80138
|
+
function convertRulesyncToAntigravityPermissions({ config, toAction, toolLabel, logger, homeDirectory }) {
|
|
80062
80139
|
const allow = [];
|
|
80063
80140
|
const ask = [];
|
|
80064
80141
|
const deny = [];
|
|
@@ -80071,7 +80148,8 @@ function convertRulesyncToAntigravityPermissions({ config, toAction, toolLabel,
|
|
|
80071
80148
|
pattern,
|
|
80072
80149
|
decision: permissionAction,
|
|
80073
80150
|
logger,
|
|
80074
|
-
toolLabel
|
|
80151
|
+
toolLabel,
|
|
80152
|
+
homeDirectory
|
|
80075
80153
|
});
|
|
80076
80154
|
if (entry === void 0) continue;
|
|
80077
80155
|
switch (permissionAction) {
|
|
@@ -80096,7 +80174,7 @@ function convertRulesyncToAntigravityPermissions({ config, toAction, toolLabel,
|
|
|
80096
80174
|
* shared by the CLI and IDE adapters; `toCategory` maps the target's tool or
|
|
80097
80175
|
* action name back to a canonical category.
|
|
80098
80176
|
*/
|
|
80099
|
-
function convertAntigravityToRulesyncPermissions({ allow, ask, deny, toCategory, toolLabel, logger }) {
|
|
80177
|
+
function convertAntigravityToRulesyncPermissions({ allow, ask, deny, toCategory, toolLabel, logger, homeDirectory }) {
|
|
80100
80178
|
const permission = {};
|
|
80101
80179
|
const processEntries = (entries, action) => {
|
|
80102
80180
|
for (const entry of entries) {
|
|
@@ -80108,7 +80186,7 @@ function convertAntigravityToRulesyncPermissions({ allow, ask, deny, toCategory,
|
|
|
80108
80186
|
decision: action,
|
|
80109
80187
|
logger,
|
|
80110
80188
|
toolLabel
|
|
80111
|
-
}) : target;
|
|
80189
|
+
}) : PATH_ACTIONS.has(toolName) ? collapseLeadingHome(target, homeDirectory) : target;
|
|
80112
80190
|
if (isPrototypePollutionKey(canonical) || isPrototypePollutionKey(pattern)) continue;
|
|
80113
80191
|
getOrCreateOwn({
|
|
80114
80192
|
record: permission,
|
|
@@ -80247,7 +80325,8 @@ var AntigravityCliPermissions = class AntigravityCliPermissions extends ToolPerm
|
|
|
80247
80325
|
config,
|
|
80248
80326
|
toAction: toAntigravityCliToolName,
|
|
80249
80327
|
toolLabel: "Antigravity CLI",
|
|
80250
|
-
logger
|
|
80328
|
+
logger,
|
|
80329
|
+
homeDirectory: outputRoot
|
|
80251
80330
|
});
|
|
80252
80331
|
const managedToolNames = new Set(Object.keys(config.permission).map((category) => toAntigravityCliToolName(category)));
|
|
80253
80332
|
const isManagedToolName = (toolName) => managedToolNames.has(toolName) || managedToolNames.has("mcp") && toolName.startsWith("mcp__");
|
|
@@ -80298,7 +80377,8 @@ var AntigravityCliPermissions = class AntigravityCliPermissions extends ToolPerm
|
|
|
80298
80377
|
deny: permissions.deny ?? [],
|
|
80299
80378
|
toCategory: toCanonicalToolName$9,
|
|
80300
80379
|
toolLabel: "Antigravity CLI",
|
|
80301
|
-
logger: moduleLogger$4
|
|
80380
|
+
logger: moduleLogger$4,
|
|
80381
|
+
homeDirectory: this.getOutputRoot()
|
|
80302
80382
|
});
|
|
80303
80383
|
const override = {};
|
|
80304
80384
|
const toolPermission = pickDocumentedValue({
|
|
@@ -90261,6 +90341,22 @@ function unmanagedMcpAllowlistEntries({ existing, previousPermission, nextPermis
|
|
|
90261
90341
|
return category === null || !Object.hasOwn(previousPermission, category) && !Object.hasOwn(nextPermission, category);
|
|
90262
90342
|
});
|
|
90263
90343
|
}
|
|
90344
|
+
/** Hermes's override key in the canonical document (`hermes`). */
|
|
90345
|
+
const HERMES_OVERRIDE_KEY = PERMISSION_OVERRIDE_KEY_ALIASES.hermesagent ?? "hermesagent";
|
|
90346
|
+
/**
|
|
90347
|
+
* The part of a canonical permissions document Hermes keeps as provenance: the
|
|
90348
|
+
* `$schema`, the canonical `permission` block, and Hermes's own override.
|
|
90349
|
+
*/
|
|
90350
|
+
function hermesProvenanceOf(permissions) {
|
|
90351
|
+
const source = permissions;
|
|
90352
|
+
const provenance = {};
|
|
90353
|
+
for (const key of [
|
|
90354
|
+
"$schema",
|
|
90355
|
+
"permission",
|
|
90356
|
+
HERMES_OVERRIDE_KEY
|
|
90357
|
+
]) if (source[key] !== void 0) provenance[key] = source[key];
|
|
90358
|
+
return provenance;
|
|
90359
|
+
}
|
|
90264
90360
|
/** The validated canonical `permission` block of a config's `permissions.rulesync` blob. */
|
|
90265
90361
|
function canonicalPermissionOf(config) {
|
|
90266
90362
|
const parsed = RulesyncPermissionsFileSchema.safeParse({ permission: provenancePermissionOf(config) });
|
|
@@ -90428,10 +90524,10 @@ var HermesagentPermissions = class HermesagentPermissions extends ToolPermission
|
|
|
90428
90524
|
patterns: websiteBlocklist.enabled === true && isStringArray(websiteBlocklist.domains) ? websiteBlocklist.domains : []
|
|
90429
90525
|
});
|
|
90430
90526
|
removeEmptyCategories(permission);
|
|
90431
|
-
const { permission: _permission, hermes: _hermes, ...otherProvenance } = provenance;
|
|
90432
90527
|
const hermes = buildHermesOverride(config, provenance);
|
|
90528
|
+
const { $schema } = provenance;
|
|
90433
90529
|
const imported = {
|
|
90434
|
-
|
|
90530
|
+
...$schema !== void 0 && { $schema },
|
|
90435
90531
|
permission,
|
|
90436
90532
|
...Object.keys(hermes).length > 0 && { hermes }
|
|
90437
90533
|
};
|
|
@@ -90489,7 +90585,7 @@ var HermesagentPermissions = class HermesagentPermissions extends ToolPermission
|
|
|
90489
90585
|
base: config,
|
|
90490
90586
|
patch: permissions.hermes
|
|
90491
90587
|
});
|
|
90492
|
-
config.permissions = { rulesync: permissions };
|
|
90588
|
+
config.permissions = { rulesync: hermesProvenanceOf(permissions) };
|
|
90493
90589
|
return new HermesagentPermissions({
|
|
90494
90590
|
outputRoot,
|
|
90495
90591
|
fileContent: stringifySharedConfig({
|