rulesync 9.5.0 → 9.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 +1 -1
- package/dist/cli/index.cjs +33 -8
- package/dist/cli/index.js +34 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-BdJG1fyb.js → import-B6nwZmGl.js} +686 -88
- package/dist/import-B6nwZmGl.js.map +1 -0
- package/dist/{import-DngV1i49.cjs → import-CiS5ckUo.cjs} +700 -96
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -3
- package/dist/import-BdJG1fyb.js.map +0 -1
|
@@ -7,9 +7,9 @@ import os from "node:os";
|
|
|
7
7
|
import { intersection, kebabCase, uniq } from "es-toolkit";
|
|
8
8
|
import { globbySync } from "globby";
|
|
9
9
|
import { isDeepStrictEqual } from "node:util";
|
|
10
|
-
import { dump, load } from "js-yaml";
|
|
11
10
|
import * as smolToml from "smol-toml";
|
|
12
11
|
import matter from "gray-matter";
|
|
12
|
+
import { YAMLException, dump, load } from "js-yaml";
|
|
13
13
|
import { omit } from "es-toolkit/object";
|
|
14
14
|
import { encode } from "@toon-format/toon";
|
|
15
15
|
//#region src/types/features.ts
|
|
@@ -141,6 +141,7 @@ const rulesProcessorToolTargetTuple = [
|
|
|
141
141
|
"opencode",
|
|
142
142
|
"pi",
|
|
143
143
|
"qwencode",
|
|
144
|
+
"reasonix",
|
|
144
145
|
"replit",
|
|
145
146
|
"roo",
|
|
146
147
|
"rovodev",
|
|
@@ -288,6 +289,7 @@ const skillsProcessorToolTargetTuple = [
|
|
|
288
289
|
"opencode",
|
|
289
290
|
"pi",
|
|
290
291
|
"qwencode",
|
|
292
|
+
"reasonix",
|
|
291
293
|
"replit",
|
|
292
294
|
"roo",
|
|
293
295
|
"rovodev",
|
|
@@ -1424,7 +1426,7 @@ function isRecord(value) {
|
|
|
1424
1426
|
* conversion, etc.) should reject inputs whose prototype could carry
|
|
1425
1427
|
* malicious accessor descriptors.
|
|
1426
1428
|
*/
|
|
1427
|
-
function isPlainObject(value) {
|
|
1429
|
+
function isPlainObject$1(value) {
|
|
1428
1430
|
if (!isRecord(value)) return false;
|
|
1429
1431
|
const proto = Object.getPrototypeOf(value);
|
|
1430
1432
|
return proto === null || proto === Object.prototype;
|
|
@@ -1436,11 +1438,43 @@ function isStringArray(value) {
|
|
|
1436
1438
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
1437
1439
|
}
|
|
1438
1440
|
//#endregion
|
|
1441
|
+
//#region src/utils/yaml.ts
|
|
1442
|
+
/**
|
|
1443
|
+
* js-yaml v5's `reason` for an empty document. `load("")` — and any
|
|
1444
|
+
* whitespace/comment-only input — throws a `YAMLException` with this reason
|
|
1445
|
+
* instead of returning `undefined` the way v4 did.
|
|
1446
|
+
*/
|
|
1447
|
+
const EMPTY_INPUT_REASON = "expected a document, but the input is empty";
|
|
1448
|
+
/**
|
|
1449
|
+
* Load YAML content while preserving js-yaml v4's behavior of returning
|
|
1450
|
+
* `undefined` for empty documents (empty, whitespace-only, or comment-only
|
|
1451
|
+
* input).
|
|
1452
|
+
*
|
|
1453
|
+
* js-yaml v5 changed `load("")` to **throw** ("expected a document, but the
|
|
1454
|
+
* input is empty") instead of returning `undefined`. Many call sites here parse
|
|
1455
|
+
* config/lock/frontmatter files that can legitimately be empty and rely on the
|
|
1456
|
+
* old `undefined` sentinel (`load(input) ?? {}`, `if (loaded === undefined)`,
|
|
1457
|
+
* "an empty file parses to undefined/null"). Routing every load through this
|
|
1458
|
+
* wrapper keeps that contract in one place so a future js-yaml bump cannot
|
|
1459
|
+
* reintroduce the empty-input regression. Genuine parse errors still propagate.
|
|
1460
|
+
*
|
|
1461
|
+
* @see https://github.com/nodeca/js-yaml/blob/master/docs/migrate_v4_to_v5.md#empty-input-throws
|
|
1462
|
+
*/
|
|
1463
|
+
function loadYaml(content) {
|
|
1464
|
+
if (content.trim() === "") return;
|
|
1465
|
+
try {
|
|
1466
|
+
return load(content);
|
|
1467
|
+
} catch (error) {
|
|
1468
|
+
if (error instanceof YAMLException && error.reason === EMPTY_INPUT_REASON) return;
|
|
1469
|
+
throw error;
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
//#endregion
|
|
1439
1473
|
//#region src/utils/frontmatter.ts
|
|
1440
1474
|
function deepRemoveNullishValue(value) {
|
|
1441
1475
|
if (value === null || value === void 0) return;
|
|
1442
1476
|
if (Array.isArray(value)) return value.map((item) => deepRemoveNullishValue(item)).filter((item) => item !== void 0);
|
|
1443
|
-
if (isPlainObject(value)) {
|
|
1477
|
+
if (isPlainObject$1(value)) {
|
|
1444
1478
|
const result = {};
|
|
1445
1479
|
for (const [key, val] of Object.entries(value)) {
|
|
1446
1480
|
const cleaned = deepRemoveNullishValue(val);
|
|
@@ -1463,7 +1497,7 @@ function deepFlattenStringsValue(value) {
|
|
|
1463
1497
|
if (value === null || value === void 0) return;
|
|
1464
1498
|
if (typeof value === "string") return value.replace(/\n+/g, " ").trim();
|
|
1465
1499
|
if (Array.isArray(value)) return value.map((item) => deepFlattenStringsValue(item)).filter((item) => item !== void 0);
|
|
1466
|
-
if (isPlainObject(value)) {
|
|
1500
|
+
if (isPlainObject$1(value)) {
|
|
1467
1501
|
const result = {};
|
|
1468
1502
|
for (const [key, val] of Object.entries(value)) {
|
|
1469
1503
|
const cleaned = deepFlattenStringsValue(val);
|
|
@@ -1486,7 +1520,7 @@ function stringifyFrontmatter(body, frontmatter, options) {
|
|
|
1486
1520
|
const { avoidBlockScalars = false } = options ?? {};
|
|
1487
1521
|
const cleanFrontmatter = avoidBlockScalars ? deepFlattenStringsObject(frontmatter) : deepRemoveNullishObject(frontmatter);
|
|
1488
1522
|
if (avoidBlockScalars) return matter.stringify(body, cleanFrontmatter, { engines: { yaml: {
|
|
1489
|
-
parse: (input) =>
|
|
1523
|
+
parse: (input) => loadYaml(input) ?? {},
|
|
1490
1524
|
stringify: (data) => dump(data, { lineWidth: -1 })
|
|
1491
1525
|
} } });
|
|
1492
1526
|
return matter.stringify(body, cleanFrontmatter);
|
|
@@ -1525,7 +1559,7 @@ function tryJsonEquivalent(a, b) {
|
|
|
1525
1559
|
}
|
|
1526
1560
|
function tryYamlEquivalent(a, b) {
|
|
1527
1561
|
try {
|
|
1528
|
-
return isDeepStrictEqual(
|
|
1562
|
+
return isDeepStrictEqual(loadYaml(a), loadYaml(b));
|
|
1529
1563
|
} catch {
|
|
1530
1564
|
return;
|
|
1531
1565
|
}
|
|
@@ -3332,7 +3366,7 @@ var GooseCommand = class GooseCommand extends ToolCommand {
|
|
|
3332
3366
|
const where = join(this.relativeDirPath, this.relativeFilePath);
|
|
3333
3367
|
let parsed;
|
|
3334
3368
|
try {
|
|
3335
|
-
parsed =
|
|
3369
|
+
parsed = loadYaml(content);
|
|
3336
3370
|
} catch (error) {
|
|
3337
3371
|
throw new Error(`Failed to parse Goose recipe (${where}): ${formatError(error)}`, { cause: error });
|
|
3338
3372
|
}
|
|
@@ -3985,7 +4019,7 @@ function omitPrototypePollutionKeys(record) {
|
|
|
3985
4019
|
//#region src/features/shared/shared-config-gateway.ts
|
|
3986
4020
|
function sanitizeSharedConfigValue(value) {
|
|
3987
4021
|
if (Array.isArray(value)) return value.map(sanitizeSharedConfigValue);
|
|
3988
|
-
if (!isPlainObject(value)) return value;
|
|
4022
|
+
if (!isPlainObject$1(value)) return value;
|
|
3989
4023
|
const result = {};
|
|
3990
4024
|
for (const [key, nested] of Object.entries(omitPrototypePollutionKeys(value))) result[key] = sanitizeSharedConfigValue(nested);
|
|
3991
4025
|
return result;
|
|
@@ -4001,14 +4035,14 @@ function parseSharedConfig({ format, fileContent, filePath, invalidRootPolicy =
|
|
|
4001
4035
|
const at = filePath === void 0 ? "" : ` at ${filePath}`;
|
|
4002
4036
|
let parsed;
|
|
4003
4037
|
try {
|
|
4004
|
-
if (format === "yaml") parsed =
|
|
4038
|
+
if (format === "yaml") parsed = loadYaml(fileContent);
|
|
4005
4039
|
else if (format === "json") parsed = JSON.parse(fileContent);
|
|
4006
4040
|
else parsed = parse(fileContent);
|
|
4007
4041
|
} catch (error) {
|
|
4008
4042
|
throw new Error(`Failed to parse shared config${at}: ${formatError(error)}`, { cause: error });
|
|
4009
4043
|
}
|
|
4010
4044
|
if (parsed === void 0 || parsed === null) return {};
|
|
4011
|
-
if (!isPlainObject(parsed)) {
|
|
4045
|
+
if (!isPlainObject$1(parsed)) {
|
|
4012
4046
|
if (invalidRootPolicy === "error") throw new Error(`Failed to parse shared config${at}: expected a mapping at the root`);
|
|
4013
4047
|
return {};
|
|
4014
4048
|
}
|
|
@@ -4051,7 +4085,7 @@ function mergeSharedConfigDeep({ base, patch }) {
|
|
|
4051
4085
|
for (const [key, patchValue] of Object.entries(patch)) {
|
|
4052
4086
|
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
4053
4087
|
const baseValue = result[key];
|
|
4054
|
-
if (isPlainObject(baseValue) && isPlainObject(patchValue)) result[key] = mergeSharedConfigDeep({
|
|
4088
|
+
if (isPlainObject$1(baseValue) && isPlainObject$1(patchValue)) result[key] = mergeSharedConfigDeep({
|
|
4055
4089
|
base: baseValue,
|
|
4056
4090
|
patch: patchValue
|
|
4057
4091
|
});
|
|
@@ -4685,6 +4719,8 @@ const REASONIX_GLOBAL_PERMISSIONS_FILE_NAME = REASONIX_GLOBAL_MCP_FILE_NAME;
|
|
|
4685
4719
|
const REASONIX_DIR = REASONIX_GLOBAL_DIR;
|
|
4686
4720
|
const REASONIX_SETTINGS_FILE_NAME = "settings.json";
|
|
4687
4721
|
const REASONIX_COMMANDS_DIR_PATH = join(REASONIX_DIR, "commands");
|
|
4722
|
+
const REASONIX_RULE_FILE_NAME = "REASONIX.md";
|
|
4723
|
+
const REASONIX_SKILLS_DIR_PATH = join(REASONIX_DIR, "skills");
|
|
4688
4724
|
//#endregion
|
|
4689
4725
|
//#region src/features/commands/reasonix-command.ts
|
|
4690
4726
|
/**
|
|
@@ -5090,8 +5126,8 @@ var RovodevCommand = class RovodevCommand extends ToolCommand {
|
|
|
5090
5126
|
const existingContent = await readFileContentOrNull(join(outputRoot, ROVODEV_DIR, ROVODEV_PROMPTS_FILE_NAME));
|
|
5091
5127
|
let existing = {};
|
|
5092
5128
|
if (existingContent) try {
|
|
5093
|
-
const parsed =
|
|
5094
|
-
if (isPlainObject(parsed)) existing = parsed;
|
|
5129
|
+
const parsed = loadYaml(existingContent);
|
|
5130
|
+
if (isPlainObject$1(parsed)) existing = parsed;
|
|
5095
5131
|
} catch {}
|
|
5096
5132
|
const prompts = rovodevCommands.map((command) => ({
|
|
5097
5133
|
name: command.getName(),
|
|
@@ -5121,11 +5157,11 @@ async function lookupPromptDescription({ outputRoot, relativeFilePath, name }) {
|
|
|
5121
5157
|
if (!manifestContent) return "";
|
|
5122
5158
|
let parsed;
|
|
5123
5159
|
try {
|
|
5124
|
-
parsed =
|
|
5160
|
+
parsed = loadYaml(manifestContent);
|
|
5125
5161
|
} catch {
|
|
5126
5162
|
return "";
|
|
5127
5163
|
}
|
|
5128
|
-
if (!isPlainObject(parsed) || !Array.isArray(parsed.prompts)) return "";
|
|
5164
|
+
if (!isPlainObject$1(parsed) || !Array.isArray(parsed.prompts)) return "";
|
|
5129
5165
|
const expectedContentFile = toPosixPath(join("prompts", relativeFilePath));
|
|
5130
5166
|
const entry = parsed.prompts.find((candidate) => isRecord(candidate) && (candidate.content_file === expectedContentFile || candidate.name === name));
|
|
5131
5167
|
return isRecord(entry) && typeof entry.description === "string" ? entry.description : "";
|
|
@@ -6163,18 +6199,25 @@ const QWENCODE_HOOK_EVENTS = [
|
|
|
6163
6199
|
* Reasonix's `.reasonix/settings.json` (project) / `~/.reasonix/settings.json`
|
|
6164
6200
|
* (global) documents a ten-event surface (`PreToolUse`, `PostToolUse`,
|
|
6165
6201
|
* `UserPromptSubmit`, `Stop`, `PostLLMCall`, `SessionStart`, `SessionEnd`,
|
|
6166
|
-
* `SubagentStop`, `Notification`, `PreCompact`)
|
|
6167
|
-
*
|
|
6168
|
-
* `UserPromptSubmit` ← `beforeSubmitPrompt`,
|
|
6169
|
-
*
|
|
6170
|
-
*
|
|
6202
|
+
* `SubagentStop`, `Notification`, `PreCompact`). The eight events with a clean
|
|
6203
|
+
* canonical equivalent are mapped: `PreToolUse`, `PostToolUse`,
|
|
6204
|
+
* `UserPromptSubmit` ← `beforeSubmitPrompt`, `Stop`, `SessionStart`,
|
|
6205
|
+
* `SessionEnd`, `SubagentStop`, and `PostLLMCall` ← `postModelInvocation`.
|
|
6206
|
+
* (`Notification` and `PreCompact` have no canonical event and are left out.)
|
|
6207
|
+
* `match` (Reasonix's matcher field name) is honored only on
|
|
6208
|
+
* `PreToolUse`/`PostToolUse`, matching the canonical `matcher` field's
|
|
6209
|
+
* tool-event scoping used by other adapters.
|
|
6171
6210
|
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
|
|
6172
6211
|
*/
|
|
6173
6212
|
const REASONIX_HOOK_EVENTS = [
|
|
6174
6213
|
"preToolUse",
|
|
6175
6214
|
"postToolUse",
|
|
6176
6215
|
"beforeSubmitPrompt",
|
|
6177
|
-
"stop"
|
|
6216
|
+
"stop",
|
|
6217
|
+
"sessionStart",
|
|
6218
|
+
"sessionEnd",
|
|
6219
|
+
"subagentStop",
|
|
6220
|
+
"postModelInvocation"
|
|
6178
6221
|
];
|
|
6179
6222
|
/**
|
|
6180
6223
|
* Hook events supported by Hermes Agent's native Shell Hooks system.
|
|
@@ -6610,14 +6653,18 @@ const QWENCODE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANO
|
|
|
6610
6653
|
/**
|
|
6611
6654
|
* Map canonical camelCase event names to Reasonix PascalCase.
|
|
6612
6655
|
* Reasonix explicitly mirrors Claude Code's hooks model, so it reuses the same
|
|
6613
|
-
* PascalCase names for the
|
|
6656
|
+
* PascalCase names for the events rulesync maps.
|
|
6614
6657
|
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
|
|
6615
6658
|
*/
|
|
6616
6659
|
const CANONICAL_TO_REASONIX_EVENT_NAMES = {
|
|
6617
6660
|
preToolUse: "PreToolUse",
|
|
6618
6661
|
postToolUse: "PostToolUse",
|
|
6619
6662
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
6620
|
-
stop: "Stop"
|
|
6663
|
+
stop: "Stop",
|
|
6664
|
+
sessionStart: "SessionStart",
|
|
6665
|
+
sessionEnd: "SessionEnd",
|
|
6666
|
+
subagentStop: "SubagentStop",
|
|
6667
|
+
postModelInvocation: "PostLLMCall"
|
|
6621
6668
|
};
|
|
6622
6669
|
/**
|
|
6623
6670
|
* Map Reasonix PascalCase event names to canonical camelCase.
|
|
@@ -6666,6 +6713,21 @@ function applyCommandPrefix({ def, converterConfig }) {
|
|
|
6666
6713
|
return converterConfig.projectDirVar !== "" && typeof trimmedCommand === "string" && !trimmedCommand.startsWith("$") && (!converterConfig.prefixDotRelativeCommandsOnly || trimmedCommand.startsWith(".")) && typeof trimmedCommand === "string" ? `"${converterConfig.projectDirVar}"/${trimmedCommand.replace(/^\.\//, "")}` : def.command;
|
|
6667
6714
|
}
|
|
6668
6715
|
/**
|
|
6716
|
+
* Emit the configured boolean passthrough fields on the tool side, mapping each
|
|
6717
|
+
* canonical field name to its (possibly renamed) tool field name. Only boolean
|
|
6718
|
+
* values are carried through.
|
|
6719
|
+
*/
|
|
6720
|
+
function emitBooleanPassthroughFields({ def, converterConfig }) {
|
|
6721
|
+
return Object.fromEntries((converterConfig.booleanPassthroughFields ?? []).filter(({ canonical }) => typeof def[canonical] === "boolean").map(({ canonical, tool }) => [tool, def[canonical]]));
|
|
6722
|
+
}
|
|
6723
|
+
/**
|
|
6724
|
+
* Import the configured boolean passthrough fields back into canonical fields,
|
|
6725
|
+
* reversing {@link emitBooleanPassthroughFields}. Only boolean values are read.
|
|
6726
|
+
*/
|
|
6727
|
+
function importBooleanPassthroughFields({ h, converterConfig }) {
|
|
6728
|
+
return Object.fromEntries((converterConfig.booleanPassthroughFields ?? []).filter(({ tool }) => typeof h[tool] === "boolean").map(({ canonical, tool }) => [canonical, h[tool]]));
|
|
6729
|
+
}
|
|
6730
|
+
/**
|
|
6669
6731
|
* Convert the definitions of a single matcher group into tool hook entries,
|
|
6670
6732
|
* honoring supported hook types and passthrough fields.
|
|
6671
6733
|
*/
|
|
@@ -6679,6 +6741,10 @@ function buildToolHooks({ defs, converterConfig }) {
|
|
|
6679
6741
|
converterConfig
|
|
6680
6742
|
});
|
|
6681
6743
|
hooks.push({
|
|
6744
|
+
...emitBooleanPassthroughFields({
|
|
6745
|
+
def,
|
|
6746
|
+
converterConfig
|
|
6747
|
+
}),
|
|
6682
6748
|
type: hookType,
|
|
6683
6749
|
...command !== void 0 && command !== null && { command },
|
|
6684
6750
|
...def.timeout !== void 0 && def.timeout !== null && { timeout: def.timeout },
|
|
@@ -6766,6 +6832,10 @@ function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
|
6766
6832
|
...prompt !== void 0 && prompt !== null && { prompt },
|
|
6767
6833
|
...converterConfig.passthroughFields?.includes("name") && typeof h.name === "string" && { name: h.name },
|
|
6768
6834
|
...converterConfig.passthroughFields?.includes("description") && typeof h.description === "string" && { description: h.description },
|
|
6835
|
+
...importBooleanPassthroughFields({
|
|
6836
|
+
h,
|
|
6837
|
+
converterConfig
|
|
6838
|
+
}),
|
|
6769
6839
|
...rawEntry.matcher !== void 0 && rawEntry.matcher !== null && rawEntry.matcher !== "" && { matcher: rawEntry.matcher }
|
|
6770
6840
|
};
|
|
6771
6841
|
}
|
|
@@ -7060,7 +7130,7 @@ function combineAugmentSettings(base, local) {
|
|
|
7060
7130
|
const baseValue = result[key];
|
|
7061
7131
|
if (AUGMENTCODE_REPLACE_KEYS.has(key)) result[key] = localValue;
|
|
7062
7132
|
else if (Array.isArray(localValue) && Array.isArray(baseValue)) result[key] = [...localValue, ...baseValue];
|
|
7063
|
-
else if (isPlainObject(localValue) && isPlainObject(baseValue)) result[key] = combineAugmentSettings(baseValue, localValue);
|
|
7133
|
+
else if (isPlainObject$1(localValue) && isPlainObject$1(baseValue)) result[key] = combineAugmentSettings(baseValue, localValue);
|
|
7064
7134
|
else result[key] = localValue;
|
|
7065
7135
|
}
|
|
7066
7136
|
return result;
|
|
@@ -7104,14 +7174,14 @@ async function readAugmentcodeSettingsWithLocalOverlay({ outputRoot, relativeDir
|
|
|
7104
7174
|
} catch (error) {
|
|
7105
7175
|
throw new Error(`Failed to parse AugmentCode settings at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
7106
7176
|
}
|
|
7107
|
-
if (!isPlainObject(localParsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
|
|
7177
|
+
if (!isPlainObject$1(localParsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
|
|
7108
7178
|
let baseParsed;
|
|
7109
7179
|
try {
|
|
7110
7180
|
baseParsed = JSON.parse(baseContent);
|
|
7111
7181
|
} catch {
|
|
7112
7182
|
return baseContent;
|
|
7113
7183
|
}
|
|
7114
|
-
const merged = combineAugmentSettings(isPlainObject(baseParsed) ? baseParsed : {}, localParsed);
|
|
7184
|
+
const merged = combineAugmentSettings(isPlainObject$1(baseParsed) ? baseParsed : {}, localParsed);
|
|
7115
7185
|
return JSON.stringify(merged, null, 2);
|
|
7116
7186
|
}
|
|
7117
7187
|
//#endregion
|
|
@@ -8696,7 +8766,14 @@ const JUNIE_CONVERTER_CONFIG = {
|
|
|
8696
8766
|
toolToCanonicalEventNames: JUNIE_TO_CANONICAL_EVENT_NAMES,
|
|
8697
8767
|
projectDirVar: "",
|
|
8698
8768
|
supportedHookTypes: /* @__PURE__ */ new Set(["command"]),
|
|
8699
|
-
noMatcherEvents: /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"])
|
|
8769
|
+
noMatcherEvents: /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"]),
|
|
8770
|
+
booleanPassthroughFields: [{
|
|
8771
|
+
canonical: "failClosed",
|
|
8772
|
+
tool: "blockOnError"
|
|
8773
|
+
}, {
|
|
8774
|
+
canonical: "async",
|
|
8775
|
+
tool: "async"
|
|
8776
|
+
}]
|
|
8700
8777
|
};
|
|
8701
8778
|
var JunieHooks = class JunieHooks extends ToolHooks {
|
|
8702
8779
|
constructor(params) {
|
|
@@ -9732,8 +9809,9 @@ function reasonixHooksToCanonical(hooks) {
|
|
|
9732
9809
|
* Reasonix hooks live in a Claude-Code-style but standalone JSON file —
|
|
9733
9810
|
* `.reasonix/settings.json` (project) or `~/.reasonix/settings.json`
|
|
9734
9811
|
* (global) — separate from the `[permissions]`/`[[plugins]]` TOML config.
|
|
9735
|
-
*
|
|
9736
|
-
* PreToolUse/PostToolUse/UserPromptSubmit/Stop
|
|
9812
|
+
* The eight upstream events with a clean canonical equivalent are mapped:
|
|
9813
|
+
* PreToolUse/PostToolUse/UserPromptSubmit/Stop plus SessionStart/SessionEnd/
|
|
9814
|
+
* SubagentStop/PostLLMCall (see REASONIX_HOOK_EVENTS).
|
|
9737
9815
|
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
|
|
9738
9816
|
*/
|
|
9739
9817
|
var ReasonixHooks = class ReasonixHooks extends ToolHooks {
|
|
@@ -11812,7 +11890,7 @@ function parseAmpSettingsJsonc(fileContent) {
|
|
|
11812
11890
|
const details = errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ");
|
|
11813
11891
|
throw new Error(`Failed to parse Amp settings: ${details}`);
|
|
11814
11892
|
}
|
|
11815
|
-
if (!isPlainObject(parsed)) throw new Error("Amp settings must be a JSON object");
|
|
11893
|
+
if (!isPlainObject$1(parsed)) throw new Error("Amp settings must be a JSON object");
|
|
11816
11894
|
return parsed;
|
|
11817
11895
|
}
|
|
11818
11896
|
function filterMcpServers(mcpServers) {
|
|
@@ -12134,7 +12212,7 @@ function parseAugmentcodeSettings(fileContent, relativeDirPath, relativeFilePath
|
|
|
12134
12212
|
} catch (error) {
|
|
12135
12213
|
throw new Error(`Failed to parse AugmentCode settings at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
12136
12214
|
}
|
|
12137
|
-
if (!isPlainObject(parsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
|
|
12215
|
+
if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
|
|
12138
12216
|
return parsed;
|
|
12139
12217
|
}
|
|
12140
12218
|
/**
|
|
@@ -12360,7 +12438,7 @@ function parseClineSettings(fileContent, relativeDirPath, relativeFilePath) {
|
|
|
12360
12438
|
} catch (error) {
|
|
12361
12439
|
throw new Error(`Failed to parse Cline MCP settings at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
12362
12440
|
}
|
|
12363
|
-
if (!isPlainObject(parsed)) throw new Error(`Failed to parse Cline MCP settings at ${configPath}: expected a JSON object`);
|
|
12441
|
+
if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse Cline MCP settings at ${configPath}: expected a JSON object`);
|
|
12364
12442
|
return parsed;
|
|
12365
12443
|
}
|
|
12366
12444
|
/**
|
|
@@ -12631,7 +12709,7 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
12631
12709
|
for (const [key, value] of Object.entries(obj)) {
|
|
12632
12710
|
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
12633
12711
|
if (value === null) continue;
|
|
12634
|
-
if (isPlainObject(value)) {
|
|
12712
|
+
if (isPlainObject$1(value)) {
|
|
12635
12713
|
const cleaned = this.removeEmptyEntries(value, depth + 1);
|
|
12636
12714
|
if (Object.keys(cleaned).length === 0) continue;
|
|
12637
12715
|
filtered[key] = cleaned;
|
|
@@ -13272,12 +13350,12 @@ function parseGooseConfig(fileContent, relativeDirPath, relativeFilePath) {
|
|
|
13272
13350
|
const configPath = join(relativeDirPath, relativeFilePath);
|
|
13273
13351
|
let parsed;
|
|
13274
13352
|
try {
|
|
13275
|
-
parsed =
|
|
13353
|
+
parsed = loadYaml(fileContent);
|
|
13276
13354
|
} catch (error) {
|
|
13277
13355
|
throw new Error(`Failed to parse Goose config at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
13278
13356
|
}
|
|
13279
13357
|
if (parsed === void 0 || parsed === null) return {};
|
|
13280
|
-
if (!isPlainObject(parsed)) throw new Error(`Failed to parse Goose config at ${configPath}: expected a YAML mapping`);
|
|
13358
|
+
if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse Goose config at ${configPath}: expected a YAML mapping`);
|
|
13281
13359
|
return parsed;
|
|
13282
13360
|
}
|
|
13283
13361
|
/**
|
|
@@ -13322,7 +13400,7 @@ function applyGooseStdioFields(ext, config) {
|
|
|
13322
13400
|
ext.cmd = command;
|
|
13323
13401
|
if (isStringArray(config.args)) ext.args = config.args;
|
|
13324
13402
|
}
|
|
13325
|
-
if (isPlainObject(config.env)) ext.envs = omitPrototypePollutionKeys(config.env);
|
|
13403
|
+
if (isPlainObject$1(config.env)) ext.envs = omitPrototypePollutionKeys(config.env);
|
|
13326
13404
|
}
|
|
13327
13405
|
/**
|
|
13328
13406
|
* Converts a single rulesync canonical MCP server into a Goose `extensions:` entry.
|
|
@@ -13337,7 +13415,7 @@ function convertServerToGooseExtension(name, config) {
|
|
|
13337
13415
|
if (gooseType === "stdio") applyGooseStdioFields(ext, config);
|
|
13338
13416
|
else if (gooseType === "sse" || gooseType === "streamable_http") {
|
|
13339
13417
|
if (url !== void 0) ext.uri = url;
|
|
13340
|
-
if (isPlainObject(config.headers)) ext.headers = omitPrototypePollutionKeys(config.headers);
|
|
13418
|
+
if (isPlainObject$1(config.headers)) ext.headers = omitPrototypePollutionKeys(config.headers);
|
|
13341
13419
|
}
|
|
13342
13420
|
ext.enabled = config.disabled !== true;
|
|
13343
13421
|
const timeout = resolveGooseTimeout(config);
|
|
@@ -13379,9 +13457,9 @@ function convertFromGooseFormat(extensions) {
|
|
|
13379
13457
|
else if (type === "stdio") server.type = "stdio";
|
|
13380
13458
|
if (typeof ext.cmd === "string") server.command = ext.cmd;
|
|
13381
13459
|
if (isStringArray(ext.args)) server.args = ext.args;
|
|
13382
|
-
if (isPlainObject(ext.envs)) server.env = omitPrototypePollutionKeys(ext.envs);
|
|
13460
|
+
if (isPlainObject$1(ext.envs)) server.env = omitPrototypePollutionKeys(ext.envs);
|
|
13383
13461
|
if (typeof ext.uri === "string") server.url = ext.uri;
|
|
13384
|
-
if (isPlainObject(ext.headers)) server.headers = omitPrototypePollutionKeys(ext.headers);
|
|
13462
|
+
if (isPlainObject$1(ext.headers)) server.headers = omitPrototypePollutionKeys(ext.headers);
|
|
13385
13463
|
if (ext.enabled === false) server.disabled = true;
|
|
13386
13464
|
if (typeof ext.timeout === "number") server.timeout = ext.timeout;
|
|
13387
13465
|
result[name] = server;
|
|
@@ -13404,7 +13482,7 @@ function buildGoosePluginStdioServer(config) {
|
|
|
13404
13482
|
server.command = command;
|
|
13405
13483
|
if (isStringArray(config.args)) server.args = config.args;
|
|
13406
13484
|
}
|
|
13407
|
-
if (isPlainObject(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
13485
|
+
if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
13408
13486
|
if (typeof config.cwd === "string") server.cwd = config.cwd;
|
|
13409
13487
|
return server;
|
|
13410
13488
|
}
|
|
@@ -13704,7 +13782,7 @@ var GrokcliMcp = class GrokcliMcp extends ToolMcp {
|
|
|
13704
13782
|
for (const [key, value] of Object.entries(obj)) {
|
|
13705
13783
|
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
13706
13784
|
if (value === null) continue;
|
|
13707
|
-
if (isPlainObject(value)) {
|
|
13785
|
+
if (isPlainObject$1(value)) {
|
|
13708
13786
|
const cleaned = this.removeEmptyEntries(value, depth + 1);
|
|
13709
13787
|
if (Object.keys(cleaned).length === 0) continue;
|
|
13710
13788
|
filtered[key] = cleaned;
|
|
@@ -13766,10 +13844,10 @@ function convertServerToHermes(config) {
|
|
|
13766
13844
|
out.command = command;
|
|
13767
13845
|
if (isStringArray(config.args)) out.args = config.args;
|
|
13768
13846
|
}
|
|
13769
|
-
if (isPlainObject(config.env)) out.env = omitPrototypePollutionKeys(config.env);
|
|
13847
|
+
if (isPlainObject$1(config.env)) out.env = omitPrototypePollutionKeys(config.env);
|
|
13770
13848
|
} else if (url !== void 0) {
|
|
13771
13849
|
out.url = url;
|
|
13772
|
-
if (isPlainObject(config.headers)) out.headers = omitPrototypePollutionKeys(config.headers);
|
|
13850
|
+
if (isPlainObject$1(config.headers)) out.headers = omitPrototypePollutionKeys(config.headers);
|
|
13773
13851
|
}
|
|
13774
13852
|
if (config.disabled === true) out.enabled = false;
|
|
13775
13853
|
const timeout = resolveHermesTimeout(config);
|
|
@@ -13814,9 +13892,9 @@ function convertFromHermesFormat(mcpServers) {
|
|
|
13814
13892
|
const server = {};
|
|
13815
13893
|
if (typeof config.command === "string") server.command = config.command;
|
|
13816
13894
|
if (isStringArray(config.args)) server.args = config.args;
|
|
13817
|
-
if (isPlainObject(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
13895
|
+
if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
13818
13896
|
if (typeof config.url === "string") server.url = config.url;
|
|
13819
|
-
if (isPlainObject(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
|
|
13897
|
+
if (isPlainObject$1(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
|
|
13820
13898
|
if (config.enabled === false) server.disabled = true;
|
|
13821
13899
|
if (typeof config.timeout === "number") server.networkTimeout = config.timeout;
|
|
13822
13900
|
if (isRecord(config.tools)) {
|
|
@@ -14753,7 +14831,9 @@ const REASONIX_PLUGIN_FIELDS = [
|
|
|
14753
14831
|
"env",
|
|
14754
14832
|
"url",
|
|
14755
14833
|
"headers",
|
|
14756
|
-
"trusted_read_only_tools"
|
|
14834
|
+
"trusted_read_only_tools",
|
|
14835
|
+
"call_timeout_seconds",
|
|
14836
|
+
"tool_timeout_seconds"
|
|
14757
14837
|
];
|
|
14758
14838
|
var ReasonixMcp = class ReasonixMcp extends ToolMcp {
|
|
14759
14839
|
toml;
|
|
@@ -14985,7 +15065,7 @@ function parseRovodevMcpJson(fileContent, relativeDirPath, relativeFilePath) {
|
|
|
14985
15065
|
} catch (error) {
|
|
14986
15066
|
throw new Error(`Failed to parse Rovodev MCP config at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
14987
15067
|
}
|
|
14988
|
-
if (!isPlainObject(parsed)) throw new Error(`Failed to parse Rovodev MCP config at ${configPath}: expected a JSON object`);
|
|
15068
|
+
if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse Rovodev MCP config at ${configPath}: expected a JSON object`);
|
|
14989
15069
|
return parsed;
|
|
14990
15070
|
}
|
|
14991
15071
|
/**
|
|
@@ -16256,15 +16336,123 @@ const AntigravityCliPermissionsOverrideSchema = z.looseObject({
|
|
|
16256
16336
|
enableTerminalSandbox: z.optional(z.boolean())
|
|
16257
16337
|
});
|
|
16258
16338
|
/**
|
|
16339
|
+
* Tool-scoped override block for AugmentCode. AugmentCode's `toolPermissions[]`
|
|
16340
|
+
* array supports "custom policy" entries the canonical allow/ask/deny model
|
|
16341
|
+
* cannot express: `permission.type` of `webhook-policy` / `script-policy`
|
|
16342
|
+
* (delegating the decision to a `webhookUrl` / `script`) and an `eventType` of
|
|
16343
|
+
* `tool-response` (a post-execution check rather than the default pre-execution
|
|
16344
|
+
* `tool-call`). These are authored here as verbatim `toolPermissions` entries
|
|
16345
|
+
* and prepended — ahead of the canonical-generated basic rules — into the shared
|
|
16346
|
+
* `.augment/settings.json`, so a webhook/script gate or tool-response check is
|
|
16347
|
+
* never shadowed by a regenerated allow/deny/ask entry under AugmentCode's
|
|
16348
|
+
* first-match-wins evaluation. The shared `permission` block continues to drive
|
|
16349
|
+
* the basic `allow` / `deny` / `ask-user` entries. Kept `looseObject` (verbatim
|
|
16350
|
+
* passthrough) so `shellInputRegex`, `eventType`, `webhookUrl`, `script`, and
|
|
16351
|
+
* any future policy field survive untouched. Both project and global scope are
|
|
16352
|
+
* supported.
|
|
16353
|
+
*
|
|
16354
|
+
* @example
|
|
16355
|
+
* { "toolPermissions": [
|
|
16356
|
+
* { "toolName": "github-api",
|
|
16357
|
+
* "permission": { "type": "webhook-policy", "webhookUrl": "https://api.example.com/validate" } },
|
|
16358
|
+
* { "toolName": "view", "eventType": "tool-response", "permission": { "type": "allow" } } ] }
|
|
16359
|
+
*/
|
|
16360
|
+
const AugmentcodePermissionsOverrideSchema = z.looseObject({ toolPermissions: z.optional(z.array(z.looseObject({
|
|
16361
|
+
toolName: z.string(),
|
|
16362
|
+
permission: z.looseObject({ type: z.string() })
|
|
16363
|
+
}))) });
|
|
16364
|
+
/**
|
|
16365
|
+
* Tool-scoped override block for Kiro. Kiro's agent config (`.kiro/agents/<name>.json`)
|
|
16366
|
+
* exposes per-tool `toolsSettings` knobs with no canonical allow/ask/deny
|
|
16367
|
+
* category: the shell auto-trust flags `shell.autoAllowReadonly` /
|
|
16368
|
+
* `shell.denyByDefault`, the `aws` built-in tool's `allowedServices` /
|
|
16369
|
+
* `deniedServices` (+ `autoAllowReadonly`), and the `web_fetch` domain trust
|
|
16370
|
+
* arrays `trusted` / `blocked` (regex host patterns; documented for `web_fetch`
|
|
16371
|
+
* only — `web_search` has no such surface). Fields placed here are deep-merged
|
|
16372
|
+
* (per `toolsSettings` key, override wins at the leaf) into the shared agent
|
|
16373
|
+
* config, while the canonical `permission` block continues to drive
|
|
16374
|
+
* `shell.{allowed,denied}Commands`, `read`/`write`/`grep`/`glob` paths, and the
|
|
16375
|
+
* `web_fetch`/`web_search` `allowedTools` toggles. Kept `looseObject` at every
|
|
16376
|
+
* level (verbatim passthrough) so future Kiro `toolsSettings` fields survive.
|
|
16377
|
+
*
|
|
16378
|
+
* Kiro's MCP `autoApprove` / `disabledTools` lists are intentionally NOT modeled
|
|
16379
|
+
* here: they live in a SEPARATE file (`.kiro/settings/mcp.json`, under
|
|
16380
|
+
* `mcpServers.<name>`), not the agent config this permissions translator writes,
|
|
16381
|
+
* and reconciling them with the canonical `mcp__*` model is a distinct design
|
|
16382
|
+
* question left out of scope.
|
|
16383
|
+
*
|
|
16384
|
+
* @example
|
|
16385
|
+
* { "toolsSettings": { "shell": { "autoAllowReadonly": true },
|
|
16386
|
+
* "aws": { "allowedServices": ["s3"], "deniedServices": ["eks"] },
|
|
16387
|
+
* "web_fetch": { "trusted": [".*github\\.com.*"] } } }
|
|
16388
|
+
*/
|
|
16389
|
+
const KiroPermissionsOverrideSchema = z.looseObject({ toolsSettings: z.optional(z.looseObject({
|
|
16390
|
+
shell: z.optional(z.looseObject({
|
|
16391
|
+
autoAllowReadonly: z.optional(z.boolean()),
|
|
16392
|
+
denyByDefault: z.optional(z.boolean())
|
|
16393
|
+
})),
|
|
16394
|
+
aws: z.optional(z.looseObject({
|
|
16395
|
+
allowedServices: z.optional(z.array(z.string())),
|
|
16396
|
+
deniedServices: z.optional(z.array(z.string())),
|
|
16397
|
+
autoAllowReadonly: z.optional(z.boolean())
|
|
16398
|
+
})),
|
|
16399
|
+
web_fetch: z.optional(z.looseObject({
|
|
16400
|
+
trusted: z.optional(z.array(z.string())),
|
|
16401
|
+
blocked: z.optional(z.array(z.string()))
|
|
16402
|
+
}))
|
|
16403
|
+
})) });
|
|
16404
|
+
/**
|
|
16405
|
+
* Codex CLI-scoped permission override.
|
|
16406
|
+
*
|
|
16407
|
+
* Codex CLI's permission surface is richer than the canonical allow/ask/deny
|
|
16408
|
+
* model: its approval workflow, classic sandbox system, and per-app tool gating
|
|
16409
|
+
* have no canonical category. Author them through a tool-scoped `codexcli`
|
|
16410
|
+
* override whose fields are written verbatim as top-level `.codex/config.toml`
|
|
16411
|
+
* keys (the override wins per key; existing sibling keys the user set directly
|
|
16412
|
+
* are preserved):
|
|
16413
|
+
* - `approval_policy` — `untrusted` | `on-request` | `never`, or a
|
|
16414
|
+
* `{ granular = { … } }` table (kept verbatim; the granular schema has
|
|
16415
|
+
* required fields that are brittle to model as typed keys).
|
|
16416
|
+
* - `sandbox_mode` — `read-only` | `workspace-write` | `danger-full-access`,
|
|
16417
|
+
* with the sibling `sandbox_workspace_write` table (`network_access`,
|
|
16418
|
+
* `writable_roots`, …).
|
|
16419
|
+
* - `apps` — per-app tool gating (`apps.<id>.tools.<tool>.approval_mode` /
|
|
16420
|
+
* `.enabled`, `apps.<id>.default_tools_approval_mode`).
|
|
16421
|
+
* - `approvals_reviewer` — the reviewer-approval surface.
|
|
16422
|
+
*
|
|
16423
|
+
* Two surfaces are deliberately NOT authorable here so the override can never
|
|
16424
|
+
* clobber a feature-owned key: `mcp_servers.*` per-MCP gating is owned by the
|
|
16425
|
+
* MCP feature (`codexcli-mcp.ts` already writes the `mcp_servers` tables in the
|
|
16426
|
+
* same `config.toml`), and `permissions` / `default_permissions` are owned by
|
|
16427
|
+
* the canonical model. Any such key placed in the override is skipped with a
|
|
16428
|
+
* warning. Kept `looseObject` (verbatim passthrough) so future top-level Codex
|
|
16429
|
+
* config keys can be authored without Rulesync modeling each one.
|
|
16430
|
+
*
|
|
16431
|
+
* @see https://developers.openai.com/codex/config-reference
|
|
16432
|
+
* @see https://developers.openai.com/codex/permissions
|
|
16433
|
+
*
|
|
16434
|
+
* @example
|
|
16435
|
+
* { "approval_policy": "on-request", "sandbox_mode": "workspace-write",
|
|
16436
|
+
* "sandbox_workspace_write": { "network_access": true } }
|
|
16437
|
+
*/
|
|
16438
|
+
const CodexcliPermissionsOverrideSchema = z.looseObject({
|
|
16439
|
+
approval_policy: z.optional(z.union([z.string(), z.looseObject({})])),
|
|
16440
|
+
sandbox_mode: z.optional(z.string()),
|
|
16441
|
+
sandbox_workspace_write: z.optional(z.looseObject({})),
|
|
16442
|
+
apps: z.optional(z.looseObject({})),
|
|
16443
|
+
approvals_reviewer: z.optional(z.union([z.string(), z.looseObject({})]))
|
|
16444
|
+
});
|
|
16445
|
+
/**
|
|
16259
16446
|
* Permissions configuration.
|
|
16260
16447
|
* Keys are tool category names (e.g., "bash", "edit", "read", "webfetch").
|
|
16261
16448
|
* Values are pattern-to-action mappings for that tool category.
|
|
16262
16449
|
*
|
|
16263
16450
|
* The optional `opencode`/`hermes`/`cline`/`kilo`/`claudecode`/`vibe`/`cursor`/
|
|
16264
16451
|
* `qwencode`/`reasonix`/`factorydroid`/`warp`/`junie`/`takt`/`amp`/
|
|
16265
|
-
* `antigravity-cli` keys are tool-scoped
|
|
16266
|
-
* respective translator (see the matching
|
|
16267
|
-
* other tool reads the shared `permission`
|
|
16452
|
+
* `antigravity-cli`/`augmentcode`/`kiro`/`codexcli` keys are tool-scoped
|
|
16453
|
+
* overrides consumed only by their respective translator (see the matching
|
|
16454
|
+
* `*PermissionsOverrideSchema`); every other tool reads the shared `permission`
|
|
16455
|
+
* block and ignores them.
|
|
16268
16456
|
*
|
|
16269
16457
|
* @example
|
|
16270
16458
|
* {
|
|
@@ -16288,7 +16476,10 @@ const PermissionsConfigSchema = z.looseObject({
|
|
|
16288
16476
|
junie: z.optional(JuniePermissionsOverrideSchema),
|
|
16289
16477
|
takt: z.optional(TaktPermissionsOverrideSchema),
|
|
16290
16478
|
amp: z.optional(AmpPermissionsOverrideSchema),
|
|
16291
|
-
"antigravity-cli": z.optional(AntigravityCliPermissionsOverrideSchema)
|
|
16479
|
+
"antigravity-cli": z.optional(AntigravityCliPermissionsOverrideSchema),
|
|
16480
|
+
augmentcode: z.optional(AugmentcodePermissionsOverrideSchema),
|
|
16481
|
+
kiro: z.optional(KiroPermissionsOverrideSchema),
|
|
16482
|
+
codexcli: z.optional(CodexcliPermissionsOverrideSchema)
|
|
16292
16483
|
});
|
|
16293
16484
|
/**
|
|
16294
16485
|
* Full permissions file schema including optional $schema field.
|
|
@@ -16440,7 +16631,7 @@ function parseAmpSettings(fileContent) {
|
|
|
16440
16631
|
const details = errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ");
|
|
16441
16632
|
throw new Error(`Failed to parse Amp settings: ${details}`);
|
|
16442
16633
|
}
|
|
16443
|
-
if (!isPlainObject(parsed)) throw new Error("Amp settings must be a JSON object");
|
|
16634
|
+
if (!isPlainObject$1(parsed)) throw new Error("Amp settings must be a JSON object");
|
|
16444
16635
|
return parsed;
|
|
16445
16636
|
}
|
|
16446
16637
|
function toDisableList(value) {
|
|
@@ -16467,7 +16658,7 @@ function toPermissionsList(value) {
|
|
|
16467
16658
|
if (!Array.isArray(value)) return [];
|
|
16468
16659
|
const entries = [];
|
|
16469
16660
|
for (const raw of value) {
|
|
16470
|
-
if (!isPlainObject(raw)) continue;
|
|
16661
|
+
if (!isPlainObject$1(raw)) continue;
|
|
16471
16662
|
const { tool, action } = raw;
|
|
16472
16663
|
if (typeof tool !== "string" || typeof action !== "string") continue;
|
|
16473
16664
|
if (action !== "allow" && action !== "reject" && action !== "ask" && action !== "delegate") continue;
|
|
@@ -16475,7 +16666,7 @@ function toPermissionsList(value) {
|
|
|
16475
16666
|
...raw,
|
|
16476
16667
|
tool,
|
|
16477
16668
|
action,
|
|
16478
|
-
...isPlainObject(raw.matches) ? { matches: raw.matches } : {}
|
|
16669
|
+
...isPlainObject$1(raw.matches) ? { matches: raw.matches } : {}
|
|
16479
16670
|
});
|
|
16480
16671
|
}
|
|
16481
16672
|
return entries;
|
|
@@ -17335,6 +17526,55 @@ function isSpecialEntry(entry) {
|
|
|
17335
17526
|
return false;
|
|
17336
17527
|
}
|
|
17337
17528
|
/**
|
|
17529
|
+
* A composite identity for a special entry, used to de-duplicate authored
|
|
17530
|
+
* (`augmentcode` override) and preserved (existing-file) special entries so the
|
|
17531
|
+
* same policy is not emitted twice into `toolPermissions`. Every field that can
|
|
17532
|
+
* distinguish two special entries is included.
|
|
17533
|
+
*/
|
|
17534
|
+
function specialEntryKey(entry) {
|
|
17535
|
+
return JSON.stringify([
|
|
17536
|
+
entry.toolName,
|
|
17537
|
+
entry.shellInputRegex ?? "",
|
|
17538
|
+
entry.eventType ?? "",
|
|
17539
|
+
entry.permission.type,
|
|
17540
|
+
entry.permission.webhookUrl ?? "",
|
|
17541
|
+
entry.permission.script ?? ""
|
|
17542
|
+
]);
|
|
17543
|
+
}
|
|
17544
|
+
/**
|
|
17545
|
+
* Stable de-duplication of special entries by {@link specialEntryKey}, keeping
|
|
17546
|
+
* the first occurrence (authored entries lead, so an authored policy wins over
|
|
17547
|
+
* an identical preserved one).
|
|
17548
|
+
*/
|
|
17549
|
+
function dedupeSpecialEntries(entries) {
|
|
17550
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17551
|
+
const out = [];
|
|
17552
|
+
for (const entry of entries) {
|
|
17553
|
+
const key = specialEntryKey(entry);
|
|
17554
|
+
if (seen.has(key)) continue;
|
|
17555
|
+
seen.add(key);
|
|
17556
|
+
out.push(entry);
|
|
17557
|
+
}
|
|
17558
|
+
return out;
|
|
17559
|
+
}
|
|
17560
|
+
/**
|
|
17561
|
+
* Validate/normalize the `augmentcode` override's `toolPermissions` array into
|
|
17562
|
+
* typed `AugmentToolPermission` entries, dropping any malformed item (with a
|
|
17563
|
+
* warning so a typo is not lost silently). The override schema is intentionally
|
|
17564
|
+
* loose (verbatim passthrough), so entries are re-parsed through the full entry
|
|
17565
|
+
* schema here to guarantee shape before they are written into the shared
|
|
17566
|
+
* settings file.
|
|
17567
|
+
*/
|
|
17568
|
+
function coerceAuthoredEntries(entries, logger) {
|
|
17569
|
+
const out = [];
|
|
17570
|
+
for (const item of entries) {
|
|
17571
|
+
const parsed = AugmentToolPermissionSchema.safeParse(item);
|
|
17572
|
+
if (parsed.success) out.push(parsed.data);
|
|
17573
|
+
else logger?.warn(`AugmentCode permissions: dropping malformed 'augmentcode.toolPermissions' override entry: ${formatError(parsed.error)}.`);
|
|
17574
|
+
}
|
|
17575
|
+
return out;
|
|
17576
|
+
}
|
|
17577
|
+
/**
|
|
17338
17578
|
* Convert a glob-like pattern into a regex string for AugmentCode's `shellInputRegex`.
|
|
17339
17579
|
* Maps glob `*` to `.*`, `?` to `.`, escapes other regex metacharacters, and anchors at both ends.
|
|
17340
17580
|
*/
|
|
@@ -17465,12 +17705,18 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
17465
17705
|
} catch (error) {
|
|
17466
17706
|
throw new Error(`Failed to parse existing AugmentCode settings at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
17467
17707
|
}
|
|
17708
|
+
const config = rulesyncPermissions.getJson();
|
|
17468
17709
|
const generated = convertRulesyncToAugmentEntries({
|
|
17469
|
-
config
|
|
17710
|
+
config,
|
|
17470
17711
|
logger
|
|
17471
17712
|
});
|
|
17472
17713
|
const existingEntries = settings.toolPermissions ?? [];
|
|
17473
|
-
const
|
|
17714
|
+
const override = config.augmentcode;
|
|
17715
|
+
const authoredEntries = override?.toolPermissions ? coerceAuthoredEntries(override.toolPermissions, logger) : [];
|
|
17716
|
+
const authoredSpecials = authoredEntries.filter((entry) => isSpecialEntry(entry));
|
|
17717
|
+
const authoredBasics = authoredEntries.filter((entry) => !isSpecialEntry(entry));
|
|
17718
|
+
const preservedSpecials = override?.toolPermissions ? [] : existingEntries.filter((entry) => isSpecialEntry(entry));
|
|
17719
|
+
const specialEntries = dedupeSpecialEntries([...authoredSpecials, ...preservedSpecials]);
|
|
17474
17720
|
const basicExistingEntries = existingEntries.filter((entry) => !isSpecialEntry(entry));
|
|
17475
17721
|
const generatedKeys = new Set(generated.map((e) => `${e.toolName}|${e.shellInputRegex ?? ""}|${e.permission.type}`));
|
|
17476
17722
|
const preservedBasicEntries = basicExistingEntries.filter((entry) => {
|
|
@@ -17481,7 +17727,11 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
17481
17727
|
}
|
|
17482
17728
|
return false;
|
|
17483
17729
|
});
|
|
17484
|
-
const sortedBasic = sortAugmentEntries([
|
|
17730
|
+
const sortedBasic = sortAugmentEntries([
|
|
17731
|
+
...generated,
|
|
17732
|
+
...preservedBasicEntries,
|
|
17733
|
+
...authoredBasics
|
|
17734
|
+
]);
|
|
17485
17735
|
const merged = {
|
|
17486
17736
|
...settings,
|
|
17487
17737
|
toolPermissions: [...specialEntries, ...sortedBasic]
|
|
@@ -17505,11 +17755,14 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
17505
17755
|
} catch (error) {
|
|
17506
17756
|
throw new Error(`Failed to parse AugmentCode permissions content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
17507
17757
|
}
|
|
17508
|
-
const
|
|
17509
|
-
|
|
17758
|
+
const allEntries = settings.toolPermissions ?? [];
|
|
17759
|
+
const specialEntries = allEntries.filter((entry) => isSpecialEntry(entry));
|
|
17760
|
+
const result = { ...convertAugmentToRulesyncPermissions({
|
|
17761
|
+
entries: allEntries.filter((entry) => !isSpecialEntry(entry)),
|
|
17510
17762
|
logger: moduleLogger$1
|
|
17511
|
-
});
|
|
17512
|
-
|
|
17763
|
+
}) };
|
|
17764
|
+
if (specialEntries.length > 0) result.augmentcode = { toolPermissions: specialEntries };
|
|
17765
|
+
return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
|
|
17513
17766
|
}
|
|
17514
17767
|
validate() {
|
|
17515
17768
|
try {
|
|
@@ -17643,10 +17896,7 @@ function convertAugmentToRulesyncPermissions({ entries, logger }) {
|
|
|
17643
17896
|
]);
|
|
17644
17897
|
const permission = {};
|
|
17645
17898
|
for (const entry of entries) {
|
|
17646
|
-
if (isSpecialEntry(entry))
|
|
17647
|
-
logger?.warn(`AugmentCode permissions: skipping advanced entry for tool '${entry.toolName}' (type '${entry.permission.type}'${entry.eventType !== void 0 ? `, eventType '${entry.eventType}'` : ""}) on import; rulesync's permission model cannot represent custom policies, eventType, webhookUrl, or script. Such entries are preserved on generate but not imported.`);
|
|
17648
|
-
continue;
|
|
17649
|
-
}
|
|
17899
|
+
if (isSpecialEntry(entry)) continue;
|
|
17650
17900
|
const type = entry.permission.type;
|
|
17651
17901
|
if (!isBasicAugmentType(type)) continue;
|
|
17652
17902
|
const canonical = toCanonicalToolName$5(entry.toolName);
|
|
@@ -18078,6 +18328,13 @@ const WORKSPACE_WIDE_WRITE_PATTERNS = /* @__PURE__ */ new Set([
|
|
|
18078
18328
|
]);
|
|
18079
18329
|
const CODEX_MINIMAL_KEY = ":minimal";
|
|
18080
18330
|
const GLOBAL_WILDCARD_DOMAIN = "*";
|
|
18331
|
+
const CODEXCLI_OVERRIDE_KEYS = [
|
|
18332
|
+
"approval_policy",
|
|
18333
|
+
"sandbox_mode",
|
|
18334
|
+
"sandbox_workspace_write",
|
|
18335
|
+
"apps",
|
|
18336
|
+
"approvals_reviewer"
|
|
18337
|
+
];
|
|
18081
18338
|
var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
18082
18339
|
static getSettablePaths(_options = {}) {
|
|
18083
18340
|
return {
|
|
@@ -18119,6 +18376,11 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
18119
18376
|
});
|
|
18120
18377
|
parsed.permissions = permissionsTable;
|
|
18121
18378
|
parsed.default_permissions = RULESYNC_PROFILE_NAME;
|
|
18379
|
+
applyCodexcliOverride({
|
|
18380
|
+
parsed,
|
|
18381
|
+
override: rulesyncPermissions.getJson().codexcli,
|
|
18382
|
+
logger
|
|
18383
|
+
});
|
|
18122
18384
|
return new CodexcliPermissions({
|
|
18123
18385
|
outputRoot,
|
|
18124
18386
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -18143,7 +18405,12 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
18143
18405
|
profile,
|
|
18144
18406
|
domainsHadUnknown
|
|
18145
18407
|
});
|
|
18146
|
-
|
|
18408
|
+
const override = extractCodexcliOverride(table);
|
|
18409
|
+
const result = Object.keys(override).length > 0 ? {
|
|
18410
|
+
...config,
|
|
18411
|
+
codexcli: override
|
|
18412
|
+
} : config;
|
|
18413
|
+
return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
|
|
18147
18414
|
}
|
|
18148
18415
|
validate() {
|
|
18149
18416
|
return {
|
|
@@ -18335,6 +18602,30 @@ function toMutableTable(value) {
|
|
|
18335
18602
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
18336
18603
|
return { ...value };
|
|
18337
18604
|
}
|
|
18605
|
+
function isPlainObject(value) {
|
|
18606
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
18607
|
+
}
|
|
18608
|
+
function applyCodexcliOverride({ parsed, override, logger }) {
|
|
18609
|
+
if (!override) return;
|
|
18610
|
+
const allowed = new Set(CODEXCLI_OVERRIDE_KEYS);
|
|
18611
|
+
for (const [key, value] of Object.entries(override)) {
|
|
18612
|
+
if (!allowed.has(key)) {
|
|
18613
|
+
logger?.warn(`Codex CLI permission override key "${key}" is not managed and was skipped. "permissions"/"default_permissions" are owned by the canonical permission model and "mcp_servers" gating by the MCP feature.`);
|
|
18614
|
+
continue;
|
|
18615
|
+
}
|
|
18616
|
+
if (value === void 0) continue;
|
|
18617
|
+
const existing = parsed[key];
|
|
18618
|
+
parsed[key] = isPlainObject(existing) && isPlainObject(value) ? {
|
|
18619
|
+
...existing,
|
|
18620
|
+
...value
|
|
18621
|
+
} : value;
|
|
18622
|
+
}
|
|
18623
|
+
}
|
|
18624
|
+
function extractCodexcliOverride(table) {
|
|
18625
|
+
const override = {};
|
|
18626
|
+
for (const key of CODEXCLI_OVERRIDE_KEYS) if (table[key] !== void 0) override[key] = table[key];
|
|
18627
|
+
return override;
|
|
18628
|
+
}
|
|
18338
18629
|
function toFilesystemRecord(value) {
|
|
18339
18630
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
18340
18631
|
const result = {};
|
|
@@ -19249,7 +19540,7 @@ var GoosePermissions = class GoosePermissions extends ToolPermissions {
|
|
|
19249
19540
|
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
19250
19541
|
let parsed;
|
|
19251
19542
|
try {
|
|
19252
|
-
parsed = existingContent.trim() === "" ? {} :
|
|
19543
|
+
parsed = existingContent.trim() === "" ? {} : loadYaml(existingContent);
|
|
19253
19544
|
} catch (error) {
|
|
19254
19545
|
throw new Error(`Failed to parse existing Goose permission.yaml at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
19255
19546
|
}
|
|
@@ -19271,7 +19562,7 @@ var GoosePermissions = class GoosePermissions extends ToolPermissions {
|
|
|
19271
19562
|
let parsed;
|
|
19272
19563
|
try {
|
|
19273
19564
|
const content = this.getFileContent();
|
|
19274
|
-
parsed = content.trim() === "" ? {} :
|
|
19565
|
+
parsed = content.trim() === "" ? {} : loadYaml(content);
|
|
19275
19566
|
} catch (error) {
|
|
19276
19567
|
throw new Error(`Failed to parse Goose permissions content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
19277
19568
|
}
|
|
@@ -20178,6 +20469,13 @@ const KiroAgentSchema = z.looseObject({
|
|
|
20178
20469
|
toolsSettings: z.optional(z.record(z.string(), z.unknown()))
|
|
20179
20470
|
});
|
|
20180
20471
|
const UnknownRecordSchema = z.record(z.string(), z.unknown());
|
|
20472
|
+
const CANONICAL_SHELL_KEYS = /* @__PURE__ */ new Set(["allowedCommands", "deniedCommands"]);
|
|
20473
|
+
const CANONICAL_TOOL_SETTINGS_KEYS = /* @__PURE__ */ new Set([
|
|
20474
|
+
"read",
|
|
20475
|
+
"write",
|
|
20476
|
+
"grep",
|
|
20477
|
+
"glob"
|
|
20478
|
+
]);
|
|
20181
20479
|
var KiroPermissions = class KiroPermissions extends ToolPermissions {
|
|
20182
20480
|
static getSettablePaths(_options = {}) {
|
|
20183
20481
|
return {
|
|
@@ -20241,7 +20539,10 @@ var KiroPermissions = class KiroPermissions extends ToolPermissions {
|
|
|
20241
20539
|
const allowedTools = new Set(parsed.allowedTools ?? []);
|
|
20242
20540
|
if (allowedTools.has("web_fetch")) permission.webfetch = { "*": "allow" };
|
|
20243
20541
|
if (allowedTools.has("web_search")) permission.websearch = { "*": "allow" };
|
|
20244
|
-
|
|
20542
|
+
const kiroOverride = extractKiroOverride(toolsSettings);
|
|
20543
|
+
const result = { permission };
|
|
20544
|
+
if (kiroOverride !== void 0) result.kiro = kiroOverride;
|
|
20545
|
+
return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
|
|
20245
20546
|
}
|
|
20246
20547
|
validate() {
|
|
20247
20548
|
return {
|
|
@@ -20291,19 +20592,71 @@ function buildKiroPermissionsFromRulesync({ config, logger, existing }) {
|
|
|
20291
20592
|
});
|
|
20292
20593
|
else logger?.warn(`Kiro permissions do not support category: ${category}. Skipping.`);
|
|
20293
20594
|
}
|
|
20294
|
-
nextToolsSettings.shell =
|
|
20595
|
+
nextToolsSettings.shell = {
|
|
20596
|
+
...preservedShellFlags(existing),
|
|
20597
|
+
...shell
|
|
20598
|
+
};
|
|
20295
20599
|
nextToolsSettings.read = pathTable(pathBuckets.read);
|
|
20296
20600
|
nextToolsSettings.write = pathTable(pathBuckets.write);
|
|
20297
20601
|
for (const key of ["grep", "glob"]) {
|
|
20298
20602
|
const bucket = pathBuckets[key];
|
|
20299
20603
|
if (bucket && (bucket.allow.length > 0 || bucket.deny.length > 0)) nextToolsSettings[key] = pathTable(bucket);
|
|
20300
20604
|
}
|
|
20605
|
+
applyKiroOverride({
|
|
20606
|
+
override: config.kiro,
|
|
20607
|
+
nextToolsSettings,
|
|
20608
|
+
logger
|
|
20609
|
+
});
|
|
20301
20610
|
return {
|
|
20302
20611
|
...existing,
|
|
20303
20612
|
allowedTools: [...nextAllowedTools].toSorted(),
|
|
20304
20613
|
toolsSettings: nextToolsSettings
|
|
20305
20614
|
};
|
|
20306
20615
|
}
|
|
20616
|
+
/**
|
|
20617
|
+
* Non-canonical `toolsSettings.shell` keys already present in the existing agent
|
|
20618
|
+
* config (everything except the canonical `allowed`/`deniedCommands`), so a
|
|
20619
|
+
* regenerate does not silently drop a hand-set `autoAllowReadonly` /
|
|
20620
|
+
* `denyByDefault` when no `kiro` override re-authors it.
|
|
20621
|
+
*/
|
|
20622
|
+
function preservedShellFlags(existing) {
|
|
20623
|
+
const existingShell = asRecord$1(asRecord$1(existing.toolsSettings).shell);
|
|
20624
|
+
const flags = {};
|
|
20625
|
+
for (const [key, value] of Object.entries(existingShell)) if (!CANONICAL_SHELL_KEYS.has(key)) flags[key] = value;
|
|
20626
|
+
return flags;
|
|
20627
|
+
}
|
|
20628
|
+
/**
|
|
20629
|
+
* Deep-merge the `kiro` override's `toolsSettings` block into the generated
|
|
20630
|
+
* settings, one `toolsSettings` key at a time so the override's leaf fields win
|
|
20631
|
+
* without clobbering canonical-generated siblings.
|
|
20632
|
+
*
|
|
20633
|
+
* Guards, so the override can only author the non-canonical surfaces it is meant
|
|
20634
|
+
* for and can never weaken a canonical-generated deny:
|
|
20635
|
+
* - prototype-pollution keys are skipped before being used as object keys;
|
|
20636
|
+
* - fully-canonical `toolsSettings` keys (`read`/`write`/`grep`/`glob`) are
|
|
20637
|
+
* rejected outright with a warning (their paths are owned by the canonical
|
|
20638
|
+
* `permission` block);
|
|
20639
|
+
* - for `shell` (partly canonical), the canonical command-list leaves
|
|
20640
|
+
* (`allowed`/`deniedCommands`) are stripped from the override value so only the
|
|
20641
|
+
* auto-trust flags merge.
|
|
20642
|
+
*/
|
|
20643
|
+
function applyKiroOverride({ override, nextToolsSettings, logger }) {
|
|
20644
|
+
const overrideToolsSettings = override?.toolsSettings;
|
|
20645
|
+
if (!isPlainObject$1(overrideToolsSettings)) return;
|
|
20646
|
+
for (const [key, value] of Object.entries(overrideToolsSettings)) {
|
|
20647
|
+
if (isPrototypePollutionKey(key)) continue;
|
|
20648
|
+
if (!isPlainObject$1(value)) continue;
|
|
20649
|
+
if (CANONICAL_TOOL_SETTINGS_KEYS.has(key)) {
|
|
20650
|
+
logger?.warn(`Kiro permissions: ignoring 'kiro.toolsSettings.${key}' override; '${key}' paths are driven by the canonical permission block.`);
|
|
20651
|
+
continue;
|
|
20652
|
+
}
|
|
20653
|
+
const mergeValue = key === "shell" ? Object.fromEntries(Object.entries(value).filter(([leaf]) => !CANONICAL_SHELL_KEYS.has(leaf))) : value;
|
|
20654
|
+
nextToolsSettings[key] = {
|
|
20655
|
+
...asRecord$1(nextToolsSettings[key]),
|
|
20656
|
+
...mergeValue
|
|
20657
|
+
};
|
|
20658
|
+
}
|
|
20659
|
+
}
|
|
20307
20660
|
function pathTable(bucket) {
|
|
20308
20661
|
return {
|
|
20309
20662
|
allowedPaths: bucket?.allow ?? [],
|
|
@@ -20323,6 +20676,31 @@ function asRecord$1(value) {
|
|
|
20323
20676
|
const result = UnknownRecordSchema.safeParse(value);
|
|
20324
20677
|
return result.success ? result.data : {};
|
|
20325
20678
|
}
|
|
20679
|
+
/**
|
|
20680
|
+
* Build the `kiro` permissions override from a parsed agent config's
|
|
20681
|
+
* `toolsSettings`, lifting the Kiro-specific knobs with no canonical category:
|
|
20682
|
+
* - `shell.*` flags other than the canonical `allowed`/`deniedCommands`
|
|
20683
|
+
* (e.g. `autoAllowReadonly`, `denyByDefault`), verbatim.
|
|
20684
|
+
* - the whole `aws` object (`allowedServices` / `deniedServices` / …), verbatim.
|
|
20685
|
+
* - the whole `web_fetch` object (`trusted` / `blocked`), verbatim.
|
|
20686
|
+
*
|
|
20687
|
+
* Returns `undefined` when none are present so the override key is omitted.
|
|
20688
|
+
*/
|
|
20689
|
+
function extractKiroOverride(toolsSettings) {
|
|
20690
|
+
const overrideToolsSettings = {};
|
|
20691
|
+
const shellFlags = {};
|
|
20692
|
+
for (const [key, value] of Object.entries(asRecord$1(toolsSettings.shell))) {
|
|
20693
|
+
if (isPrototypePollutionKey(key)) continue;
|
|
20694
|
+
if (!CANONICAL_SHELL_KEYS.has(key)) shellFlags[key] = value;
|
|
20695
|
+
}
|
|
20696
|
+
if (Object.keys(shellFlags).length > 0) overrideToolsSettings.shell = shellFlags;
|
|
20697
|
+
const aws = asRecord$1(toolsSettings.aws);
|
|
20698
|
+
if (Object.keys(aws).length > 0) overrideToolsSettings.aws = aws;
|
|
20699
|
+
const webFetch = asRecord$1(toolsSettings.web_fetch);
|
|
20700
|
+
if (Object.keys(webFetch).length > 0) overrideToolsSettings.web_fetch = webFetch;
|
|
20701
|
+
if (Object.keys(overrideToolsSettings).length === 0) return void 0;
|
|
20702
|
+
return { toolsSettings: overrideToolsSettings };
|
|
20703
|
+
}
|
|
20326
20704
|
function asStringArray(value) {
|
|
20327
20705
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
20328
20706
|
}
|
|
@@ -21135,7 +21513,7 @@ var RovodevPermissions = class RovodevPermissions extends ToolPermissions {
|
|
|
21135
21513
|
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
21136
21514
|
let parsed;
|
|
21137
21515
|
try {
|
|
21138
|
-
parsed = existingContent.trim() === "" ? {} :
|
|
21516
|
+
parsed = existingContent.trim() === "" ? {} : loadYaml(existingContent);
|
|
21139
21517
|
} catch (error) {
|
|
21140
21518
|
throw new Error(`Failed to parse existing Rovodev config at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
21141
21519
|
}
|
|
@@ -21161,7 +21539,7 @@ var RovodevPermissions = class RovodevPermissions extends ToolPermissions {
|
|
|
21161
21539
|
let parsed;
|
|
21162
21540
|
try {
|
|
21163
21541
|
const content = this.getFileContent();
|
|
21164
|
-
parsed = content.trim() === "" ? {} :
|
|
21542
|
+
parsed = content.trim() === "" ? {} : loadYaml(content);
|
|
21165
21543
|
} catch (error) {
|
|
21166
21544
|
throw new Error(`Failed to parse Rovodev permissions content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
21167
21545
|
}
|
|
@@ -21356,9 +21734,9 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
|
|
|
21356
21734
|
const rulesyncJson = rulesyncPermissions.getJson();
|
|
21357
21735
|
const provider = resolveActiveProvider(config);
|
|
21358
21736
|
const mode = deriveTaktPermissionMode(rulesyncJson);
|
|
21359
|
-
const override = isPlainObject(rulesyncJson.takt) ? rulesyncJson.takt : void 0;
|
|
21360
|
-
const stepOverrides = isPlainObject(override?.[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? override[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
|
|
21361
|
-
const overrideProviderOptions = isPlainObject(override?.[TAKT_PROVIDER_OPTIONS_KEY]) ? override[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
|
|
21737
|
+
const override = isPlainObject$1(rulesyncJson.takt) ? rulesyncJson.takt : void 0;
|
|
21738
|
+
const stepOverrides = isPlainObject$1(override?.[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? override[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
|
|
21739
|
+
const overrideProviderOptions = isPlainObject$1(override?.[TAKT_PROVIDER_OPTIONS_KEY]) ? override[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
|
|
21362
21740
|
const patch = {
|
|
21363
21741
|
[TAKT_PROVIDER_PROFILES_KEY]: { [provider]: {
|
|
21364
21742
|
[TAKT_DEFAULT_PERMISSION_MODE_KEY]: mode,
|
|
@@ -21389,12 +21767,12 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
|
|
|
21389
21767
|
invalidRootPolicy: "error"
|
|
21390
21768
|
});
|
|
21391
21769
|
const provider = resolveActiveProvider(config);
|
|
21392
|
-
const profiles = isPlainObject(config[TAKT_PROVIDER_PROFILES_KEY]) ? config[TAKT_PROVIDER_PROFILES_KEY] : {};
|
|
21393
|
-
const profile = isPlainObject(profiles[provider]) ? profiles[provider] : {};
|
|
21770
|
+
const profiles = isPlainObject$1(config[TAKT_PROVIDER_PROFILES_KEY]) ? config[TAKT_PROVIDER_PROFILES_KEY] : {};
|
|
21771
|
+
const profile = isPlainObject$1(profiles[provider]) ? profiles[provider] : {};
|
|
21394
21772
|
const mode = profile[TAKT_DEFAULT_PERMISSION_MODE_KEY];
|
|
21395
21773
|
const rulesyncConfig = taktModeToRulesyncConfig(mode);
|
|
21396
|
-
const stepOverrides = isPlainObject(profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
|
|
21397
|
-
const providerOptions = isPlainObject(config[TAKT_PROVIDER_OPTIONS_KEY]) ? config[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
|
|
21774
|
+
const stepOverrides = isPlainObject$1(profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
|
|
21775
|
+
const providerOptions = isPlainObject$1(config[TAKT_PROVIDER_OPTIONS_KEY]) ? config[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
|
|
21398
21776
|
const taktOverride = {};
|
|
21399
21777
|
if (stepOverrides && Object.keys(stepOverrides).length > 0) taktOverride[TAKT_STEP_PERMISSION_OVERRIDES_KEY] = stepOverrides;
|
|
21400
21778
|
if (providerOptions && Object.keys(providerOptions).length > 0) taktOverride[TAKT_PROVIDER_OPTIONS_KEY] = providerOptions;
|
|
@@ -21426,7 +21804,7 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
|
|
|
21426
21804
|
function resolveActiveProvider(config) {
|
|
21427
21805
|
if (typeof config[TAKT_PROVIDER_KEY] === "string" && config[TAKT_PROVIDER_KEY].trim() !== "") return config[TAKT_PROVIDER_KEY];
|
|
21428
21806
|
const profiles = config[TAKT_PROVIDER_PROFILES_KEY];
|
|
21429
|
-
if (isPlainObject(profiles)) {
|
|
21807
|
+
if (isPlainObject$1(profiles)) {
|
|
21430
21808
|
const keys = Object.keys(profiles);
|
|
21431
21809
|
if (keys.length === 1) return keys[0];
|
|
21432
21810
|
}
|
|
@@ -24415,7 +24793,7 @@ function extractOpenaiYamlFile(otherFiles) {
|
|
|
24415
24793
|
const rest = [];
|
|
24416
24794
|
for (const file of otherFiles) {
|
|
24417
24795
|
if (toPosixPath(file.relativeFilePathToDirPath) === target) try {
|
|
24418
|
-
const loaded =
|
|
24796
|
+
const loaded = loadYaml(file.fileBuffer.toString("utf-8"));
|
|
24419
24797
|
if (loaded !== null && typeof loaded === "object" && !Array.isArray(loaded)) {
|
|
24420
24798
|
parsed = loaded;
|
|
24421
24799
|
continue;
|
|
@@ -26666,6 +27044,139 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
26666
27044
|
}
|
|
26667
27045
|
};
|
|
26668
27046
|
//#endregion
|
|
27047
|
+
//#region src/features/skills/reasonix-skill.ts
|
|
27048
|
+
const ReasonixSkillFrontmatterSchema = z.looseObject({
|
|
27049
|
+
name: z.string(),
|
|
27050
|
+
description: z.string()
|
|
27051
|
+
});
|
|
27052
|
+
/**
|
|
27053
|
+
* Represents a DeepSeek-Reasonix skill directory.
|
|
27054
|
+
*
|
|
27055
|
+
* Reasonix discovers directory-layout skills (`<name>/SKILL.md`) under
|
|
27056
|
+
* `.reasonix/skills/` (project) and `~/.reasonix/skills/` (global); the global
|
|
27057
|
+
* scope is served by the processor supplying the home directory as outputRoot.
|
|
27058
|
+
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/GUIDE.md
|
|
27059
|
+
*/
|
|
27060
|
+
var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
27061
|
+
constructor({ outputRoot = process.cwd(), relativeDirPath = REASONIX_SKILLS_DIR_PATH, dirName, frontmatter, body, otherFiles = [], validate = true, global = false }) {
|
|
27062
|
+
super({
|
|
27063
|
+
outputRoot,
|
|
27064
|
+
relativeDirPath,
|
|
27065
|
+
dirName,
|
|
27066
|
+
mainFile: {
|
|
27067
|
+
name: SKILL_FILE_NAME,
|
|
27068
|
+
body,
|
|
27069
|
+
frontmatter: { ...frontmatter }
|
|
27070
|
+
},
|
|
27071
|
+
otherFiles,
|
|
27072
|
+
global
|
|
27073
|
+
});
|
|
27074
|
+
if (validate) {
|
|
27075
|
+
const result = this.validate();
|
|
27076
|
+
if (!result.success) throw result.error;
|
|
27077
|
+
}
|
|
27078
|
+
}
|
|
27079
|
+
static getSettablePaths({ global: _global = false } = {}) {
|
|
27080
|
+
return { relativeDirPath: REASONIX_SKILLS_DIR_PATH };
|
|
27081
|
+
}
|
|
27082
|
+
getFrontmatter() {
|
|
27083
|
+
return ReasonixSkillFrontmatterSchema.parse(this.requireMainFileFrontmatter());
|
|
27084
|
+
}
|
|
27085
|
+
getBody() {
|
|
27086
|
+
return this.mainFile?.body ?? "";
|
|
27087
|
+
}
|
|
27088
|
+
validate() {
|
|
27089
|
+
if (this.mainFile === void 0) return {
|
|
27090
|
+
success: false,
|
|
27091
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27092
|
+
};
|
|
27093
|
+
const result = ReasonixSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27094
|
+
if (!result.success) return {
|
|
27095
|
+
success: false,
|
|
27096
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`)
|
|
27097
|
+
};
|
|
27098
|
+
return {
|
|
27099
|
+
success: true,
|
|
27100
|
+
error: null
|
|
27101
|
+
};
|
|
27102
|
+
}
|
|
27103
|
+
toRulesyncSkill() {
|
|
27104
|
+
const frontmatter = this.getFrontmatter();
|
|
27105
|
+
const rulesyncFrontmatter = {
|
|
27106
|
+
name: frontmatter.name,
|
|
27107
|
+
description: frontmatter.description,
|
|
27108
|
+
targets: ["*"]
|
|
27109
|
+
};
|
|
27110
|
+
return new RulesyncSkill({
|
|
27111
|
+
outputRoot: this.outputRoot,
|
|
27112
|
+
relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH,
|
|
27113
|
+
dirName: this.getDirName(),
|
|
27114
|
+
frontmatter: rulesyncFrontmatter,
|
|
27115
|
+
body: this.getBody(),
|
|
27116
|
+
otherFiles: this.getOtherFiles(),
|
|
27117
|
+
validate: true,
|
|
27118
|
+
global: this.global
|
|
27119
|
+
});
|
|
27120
|
+
}
|
|
27121
|
+
static fromRulesyncSkill({ outputRoot = process.cwd(), rulesyncSkill, validate = true, global = false }) {
|
|
27122
|
+
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
|
|
27123
|
+
const reasonixFrontmatter = {
|
|
27124
|
+
name: rulesyncFrontmatter.name,
|
|
27125
|
+
description: rulesyncFrontmatter.description
|
|
27126
|
+
};
|
|
27127
|
+
return new ReasonixSkill({
|
|
27128
|
+
outputRoot,
|
|
27129
|
+
relativeDirPath: ReasonixSkill.getSettablePaths({ global }).relativeDirPath,
|
|
27130
|
+
dirName: rulesyncSkill.getDirName(),
|
|
27131
|
+
frontmatter: reasonixFrontmatter,
|
|
27132
|
+
body: rulesyncSkill.getBody(),
|
|
27133
|
+
otherFiles: rulesyncSkill.getOtherFiles(),
|
|
27134
|
+
validate,
|
|
27135
|
+
global
|
|
27136
|
+
});
|
|
27137
|
+
}
|
|
27138
|
+
static isTargetedByRulesyncSkill(rulesyncSkill) {
|
|
27139
|
+
const targets = rulesyncSkill.getFrontmatter().targets;
|
|
27140
|
+
return targets.includes("*") || targets.includes("reasonix");
|
|
27141
|
+
}
|
|
27142
|
+
static async fromDir(params) {
|
|
27143
|
+
const loaded = await this.loadSkillDirContent({
|
|
27144
|
+
...params,
|
|
27145
|
+
getSettablePaths: ReasonixSkill.getSettablePaths
|
|
27146
|
+
});
|
|
27147
|
+
const result = ReasonixSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27148
|
+
if (!result.success) {
|
|
27149
|
+
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27150
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27151
|
+
}
|
|
27152
|
+
return new ReasonixSkill({
|
|
27153
|
+
outputRoot: loaded.outputRoot,
|
|
27154
|
+
relativeDirPath: loaded.relativeDirPath,
|
|
27155
|
+
dirName: loaded.dirName,
|
|
27156
|
+
frontmatter: result.data,
|
|
27157
|
+
body: loaded.body,
|
|
27158
|
+
otherFiles: loaded.otherFiles,
|
|
27159
|
+
validate: true,
|
|
27160
|
+
global: loaded.global
|
|
27161
|
+
});
|
|
27162
|
+
}
|
|
27163
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, dirName, global = false }) {
|
|
27164
|
+
return new ReasonixSkill({
|
|
27165
|
+
outputRoot,
|
|
27166
|
+
relativeDirPath,
|
|
27167
|
+
dirName,
|
|
27168
|
+
frontmatter: {
|
|
27169
|
+
name: "",
|
|
27170
|
+
description: ""
|
|
27171
|
+
},
|
|
27172
|
+
body: "",
|
|
27173
|
+
otherFiles: [],
|
|
27174
|
+
validate: false,
|
|
27175
|
+
global
|
|
27176
|
+
});
|
|
27177
|
+
}
|
|
27178
|
+
};
|
|
27179
|
+
//#endregion
|
|
26669
27180
|
//#region src/constants/replit-paths.ts
|
|
26670
27181
|
const REPLIT_RULE_FILE_NAME = "replit.md";
|
|
26671
27182
|
const REPLIT_SKILLS_DIR_PATH = join(".agents", "skills");
|
|
@@ -27760,6 +28271,14 @@ const toolSkillFactories = /* @__PURE__ */ new Map([
|
|
|
27760
28271
|
supportsGlobal: true
|
|
27761
28272
|
}
|
|
27762
28273
|
}],
|
|
28274
|
+
["reasonix", {
|
|
28275
|
+
class: ReasonixSkill,
|
|
28276
|
+
meta: {
|
|
28277
|
+
supportsProject: true,
|
|
28278
|
+
supportsSimulated: false,
|
|
28279
|
+
supportsGlobal: true
|
|
28280
|
+
}
|
|
28281
|
+
}],
|
|
27763
28282
|
["replit", {
|
|
27764
28283
|
class: ReplitSkill,
|
|
27765
28284
|
meta: {
|
|
@@ -30043,7 +30562,7 @@ var GooseSubagent = class GooseSubagent extends ToolSubagent {
|
|
|
30043
30562
|
const fileContent = await readFileContent(filePath);
|
|
30044
30563
|
let parsed;
|
|
30045
30564
|
try {
|
|
30046
|
-
parsed =
|
|
30565
|
+
parsed = loadYaml(fileContent);
|
|
30047
30566
|
} catch (error) {
|
|
30048
30567
|
throw new Error(`Failed to parse Goose recipe (${filePath}): ${formatError(error)}`, { cause: error });
|
|
30049
30568
|
}
|
|
@@ -31431,7 +31950,7 @@ var RooSubagent = class RooSubagent extends ToolSubagent {
|
|
|
31431
31950
|
const fileContent = await readFileContent(filePath);
|
|
31432
31951
|
let parsed;
|
|
31433
31952
|
try {
|
|
31434
|
-
parsed =
|
|
31953
|
+
parsed = loadYaml(fileContent);
|
|
31435
31954
|
} catch (error) {
|
|
31436
31955
|
throw new Error(`Failed to parse .roomodes (${filePath}): ${formatError(error)}`, { cause: error });
|
|
31437
31956
|
}
|
|
@@ -35624,6 +36143,72 @@ var QwencodeRule = class QwencodeRule extends ToolRule {
|
|
|
35624
36143
|
}
|
|
35625
36144
|
};
|
|
35626
36145
|
//#endregion
|
|
36146
|
+
//#region src/features/rules/reasonix-rule.ts
|
|
36147
|
+
var ReasonixRule = class ReasonixRule extends ToolRule {
|
|
36148
|
+
constructor({ fileContent, root, ...rest }) {
|
|
36149
|
+
super({
|
|
36150
|
+
...rest,
|
|
36151
|
+
fileContent,
|
|
36152
|
+
root: root ?? false
|
|
36153
|
+
});
|
|
36154
|
+
}
|
|
36155
|
+
static getSettablePaths({ global = false } = {}) {
|
|
36156
|
+
return { root: {
|
|
36157
|
+
relativeDirPath: global ? REASONIX_GLOBAL_DIR : ".",
|
|
36158
|
+
relativeFilePath: REASONIX_RULE_FILE_NAME
|
|
36159
|
+
} };
|
|
36160
|
+
}
|
|
36161
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath: _relativeFilePath, validate = true, global = false }) {
|
|
36162
|
+
const { root } = this.getSettablePaths({ global });
|
|
36163
|
+
const fileContent = await readFileContent(join(outputRoot, join(root.relativeDirPath, root.relativeFilePath)));
|
|
36164
|
+
return new ReasonixRule({
|
|
36165
|
+
outputRoot,
|
|
36166
|
+
relativeDirPath: root.relativeDirPath,
|
|
36167
|
+
relativeFilePath: root.relativeFilePath,
|
|
36168
|
+
fileContent,
|
|
36169
|
+
validate,
|
|
36170
|
+
root: true
|
|
36171
|
+
});
|
|
36172
|
+
}
|
|
36173
|
+
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
36174
|
+
const { root } = this.getSettablePaths({ global });
|
|
36175
|
+
const isRoot = rulesyncRule.getFrontmatter().root ?? false;
|
|
36176
|
+
return new ReasonixRule({
|
|
36177
|
+
outputRoot,
|
|
36178
|
+
relativeDirPath: root.relativeDirPath,
|
|
36179
|
+
relativeFilePath: root.relativeFilePath,
|
|
36180
|
+
fileContent: rulesyncRule.getBody(),
|
|
36181
|
+
validate,
|
|
36182
|
+
root: isRoot
|
|
36183
|
+
});
|
|
36184
|
+
}
|
|
36185
|
+
toRulesyncRule() {
|
|
36186
|
+
return this.toRulesyncRuleDefault();
|
|
36187
|
+
}
|
|
36188
|
+
validate() {
|
|
36189
|
+
return {
|
|
36190
|
+
success: true,
|
|
36191
|
+
error: null
|
|
36192
|
+
};
|
|
36193
|
+
}
|
|
36194
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
36195
|
+
return new ReasonixRule({
|
|
36196
|
+
outputRoot,
|
|
36197
|
+
relativeDirPath,
|
|
36198
|
+
relativeFilePath,
|
|
36199
|
+
fileContent: "",
|
|
36200
|
+
validate: false,
|
|
36201
|
+
root: relativeFilePath === "REASONIX.md" && (relativeDirPath === "." || relativeDirPath === ".reasonix")
|
|
36202
|
+
});
|
|
36203
|
+
}
|
|
36204
|
+
static isTargetedByRulesyncRule(rulesyncRule) {
|
|
36205
|
+
return this.isTargetedByRulesyncRuleDefault({
|
|
36206
|
+
rulesyncRule,
|
|
36207
|
+
toolTarget: "reasonix"
|
|
36208
|
+
});
|
|
36209
|
+
}
|
|
36210
|
+
};
|
|
36211
|
+
//#endregion
|
|
35627
36212
|
//#region src/features/rules/replit-rule.ts
|
|
35628
36213
|
/**
|
|
35629
36214
|
* Rule generator for Replit Agent
|
|
@@ -36536,6 +37121,15 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
36536
37121
|
additionalConventions: { subagents: { subagentClass: QwencodeSubagent } }
|
|
36537
37122
|
}
|
|
36538
37123
|
}],
|
|
37124
|
+
["reasonix", {
|
|
37125
|
+
class: ReasonixRule,
|
|
37126
|
+
meta: {
|
|
37127
|
+
extension: "md",
|
|
37128
|
+
supportsGlobal: true,
|
|
37129
|
+
ruleDiscoveryMode: "auto",
|
|
37130
|
+
foldsNonRootIntoRoot: true
|
|
37131
|
+
}
|
|
37132
|
+
}],
|
|
36539
37133
|
["replit", {
|
|
36540
37134
|
class: ReplitRule,
|
|
36541
37135
|
meta: {
|
|
@@ -37421,7 +38015,6 @@ const SHARED_WRITE_FEATURE_ORDER = [
|
|
|
37421
38015
|
"permissions",
|
|
37422
38016
|
"rules"
|
|
37423
38017
|
];
|
|
37424
|
-
const SHARED_WRITE_FEATURES = new Set(SHARED_WRITE_FEATURE_ORDER);
|
|
37425
38018
|
const TARGETS_NOT_DERIVED = /* @__PURE__ */ new Set(["augmentcode-legacy", "claudecode-legacy"]);
|
|
37426
38019
|
const sharedFileKey = (path) => {
|
|
37427
38020
|
const dir = path.relativeDirPath.replace(/\\/g, "/").replace(/\/$/, "");
|
|
@@ -37444,7 +38037,13 @@ const settablePathsForScope = (cls, global) => {
|
|
|
37444
38037
|
paths.push(settable.root);
|
|
37445
38038
|
for (const alt of settable.alternativeRoots ?? []) paths.push(alt);
|
|
37446
38039
|
}
|
|
37447
|
-
|
|
38040
|
+
let extra;
|
|
38041
|
+
try {
|
|
38042
|
+
extra = cls.getExtraSharedWritePaths?.({ global }) ?? [];
|
|
38043
|
+
} catch {
|
|
38044
|
+
return paths;
|
|
38045
|
+
}
|
|
38046
|
+
for (const path of extra) if (path.relativeFilePath) paths.push(path);
|
|
37448
38047
|
return paths;
|
|
37449
38048
|
};
|
|
37450
38049
|
const collectFactoryPaths = (factory) => [...settablePathsForScope(factory.class, false), ...settablePathsForScope(factory.class, true)];
|
|
@@ -37457,7 +38056,6 @@ const deriveSharedFileWriters = () => {
|
|
|
37457
38056
|
const byKey = /* @__PURE__ */ new Map();
|
|
37458
38057
|
const pathByKey = /* @__PURE__ */ new Map();
|
|
37459
38058
|
for (const entry of PROCESSOR_REGISTRY) {
|
|
37460
|
-
if (!SHARED_WRITE_FEATURES.has(entry.feature)) continue;
|
|
37461
38059
|
const factories = entry.factory;
|
|
37462
38060
|
for (const [tool, factory] of factories) {
|
|
37463
38061
|
if (TARGETS_NOT_DERIVED.has(tool)) continue;
|
|
@@ -38423,6 +39021,6 @@ async function importPermissionsCore(params) {
|
|
|
38423
39021
|
return writtenCount;
|
|
38424
39022
|
}
|
|
38425
39023
|
//#endregion
|
|
38426
|
-
export {
|
|
39024
|
+
export { removeTempDirectory as $, RulesyncCommand as A, checkPathTraversal as B, RulesyncHooks as C, RULESYNC_RULES_RELATIVE_DIR_PATH as Ct, CLAUDECODE_MEMORIES_DIR_NAME as D, formatError as Dt, CLAUDECODE_LOCAL_RULE_FILE_NAME as E, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as Et, findControlCharacter as F, findFilesByGlobs as G, directoryExists as H, ConsoleLogger as I, isSymlink as J, getFileSize as K, JsonLogger as L, stringifyFrontmatter as M, loadYaml as N, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as O, ALL_FEATURES as Ot, ConfigResolver as P, removeFile as Q, CLIError as R, HooksProcessor as S, RULESYNC_RELATIVE_DIR_PATH as St, CLAUDECODE_DIR as T, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as Tt, ensureDir as U, createTempDirectory as V, fileExists as W, readFileContent as X, listDirectoryFiles as Y, removeDirectory as Z, RulesyncPermissions as _, RULESYNC_MCP_RELATIVE_FILE_PATH as _t, convertFromTool as a, MAX_FILE_SIZE as at, IgnoreProcessor as b, RULESYNC_PERMISSIONS_FILE_NAME as bt, RulesyncRuleFrontmatterSchema as c, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as ct, RulesyncSubagentFrontmatterSchema as d, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as dt, toPosixPath as et, SkillsProcessor as f, RULESYNC_HOOKS_FILE_NAME as ft, SKILL_FILE_NAME as g, RULESYNC_MCP_FILE_NAME as gt, RulesyncSkillFrontmatterSchema as h, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as ht, getProcessorRegistryEntry as i, ToolTargetSchema as it, RulesyncCommandFrontmatterSchema as j, CLAUDECODE_SKILLS_DIR_PATH as k, ALL_FEATURES_WITH_WILDCARD as kt, SubagentsProcessor as l, RULESYNC_CONFIG_RELATIVE_FILE_PATH as lt, RulesyncSkill as m, RULESYNC_IGNORE_RELATIVE_FILE_PATH as mt, checkRulesyncDirExists as n, ALL_TOOL_TARGETS as nt, RulesProcessor as o, RULESYNC_AIIGNORE_FILE_NAME as ot, getLocalSkillDirNames as p, RULESYNC_HOOKS_RELATIVE_FILE_PATH as pt, getHomeDirectory as q, generate as r, ALL_TOOL_TARGETS_WITH_WILDCARD as rt, RulesyncRule as s, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as st, importFromTool as t, writeFileContent as tt, RulesyncSubagent as u, RULESYNC_CONFIG_SCHEMA_URL as ut, McpProcessor as v, RULESYNC_MCP_SCHEMA_URL as vt, CommandsProcessor as w, RULESYNC_SKILLS_RELATIVE_DIR_PATH as wt, RulesyncIgnore as x, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as xt, RulesyncMcp as y, RULESYNC_OVERVIEW_FILE_NAME as yt, ErrorCodes as z };
|
|
38427
39025
|
|
|
38428
|
-
//# sourceMappingURL=import-
|
|
39026
|
+
//# sourceMappingURL=import-B6nwZmGl.js.map
|