rulesync 9.7.0 → 9.8.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 +2 -2
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-DC9T1JlQ.js → import-Dioh9ca8.js} +455 -109
- package/dist/import-Dioh9ca8.js.map +1 -0
- package/dist/{import-D5f_X4-A.cjs → import-l0o1jVdc.cjs} +464 -118
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-DC9T1JlQ.js.map +0 -1
|
@@ -114,22 +114,22 @@ function formatError(error) {
|
|
|
114
114
|
}
|
|
115
115
|
//#endregion
|
|
116
116
|
//#region src/constants/rulesync-paths.ts
|
|
117
|
-
const { join: join$
|
|
117
|
+
const { join: join$250 } = node_path.posix;
|
|
118
118
|
const RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
|
|
119
119
|
const RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH = "rulesync.local.jsonc";
|
|
120
120
|
const RULESYNC_RELATIVE_DIR_PATH = ".rulesync";
|
|
121
|
-
const RULESYNC_RULES_RELATIVE_DIR_PATH = join$
|
|
122
|
-
const RULESYNC_COMMANDS_RELATIVE_DIR_PATH = join$
|
|
123
|
-
const RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = join$
|
|
124
|
-
const RULESYNC_MCP_RELATIVE_FILE_PATH = join$
|
|
125
|
-
const RULESYNC_HOOKS_RELATIVE_FILE_PATH = join$
|
|
126
|
-
const RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH = join$
|
|
121
|
+
const RULESYNC_RULES_RELATIVE_DIR_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "rules");
|
|
122
|
+
const RULESYNC_COMMANDS_RELATIVE_DIR_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "commands");
|
|
123
|
+
const RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "subagents");
|
|
124
|
+
const RULESYNC_MCP_RELATIVE_FILE_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
|
|
125
|
+
const RULESYNC_HOOKS_RELATIVE_FILE_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "hooks.json");
|
|
126
|
+
const RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "permissions.json");
|
|
127
127
|
const RULESYNC_AIIGNORE_FILE_NAME = ".aiignore";
|
|
128
|
-
const RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = join$
|
|
128
|
+
const RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, ".aiignore");
|
|
129
129
|
const RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
|
|
130
130
|
const RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
|
|
131
|
-
const RULESYNC_SKILLS_RELATIVE_DIR_PATH = join$
|
|
132
|
-
const RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = join$
|
|
131
|
+
const RULESYNC_SKILLS_RELATIVE_DIR_PATH = join$250(RULESYNC_RELATIVE_DIR_PATH, "skills");
|
|
132
|
+
const RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = join$250(RULESYNC_SKILLS_RELATIVE_DIR_PATH, ".curated");
|
|
133
133
|
const RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH = "rulesync.lock";
|
|
134
134
|
const RULESYNC_MCP_FILE_NAME = "mcp.json";
|
|
135
135
|
const RULESYNC_HOOKS_FILE_NAME = "hooks.json";
|
|
@@ -347,7 +347,8 @@ const hooksProcessorToolTargetTuple = [
|
|
|
347
347
|
"junie",
|
|
348
348
|
"vibe",
|
|
349
349
|
"qwencode",
|
|
350
|
-
"reasonix"
|
|
350
|
+
"reasonix",
|
|
351
|
+
"grokcli"
|
|
351
352
|
];
|
|
352
353
|
const permissionsProcessorToolTargetTuple = [
|
|
353
354
|
"amp",
|
|
@@ -6295,10 +6296,13 @@ const CLAUDE_HOOK_EVENTS = [
|
|
|
6295
6296
|
* Hook events supported by Devin Local (native `.devin/` hooks).
|
|
6296
6297
|
*
|
|
6297
6298
|
* Devin Local adopts a Claude-Code-style lifecycle hooks surface. It documents
|
|
6298
|
-
*
|
|
6299
|
-
* `UserPromptSubmit`, `Stop`, `SessionStart`,
|
|
6299
|
+
* eight events: `PreToolUse`, `PostToolUse`, `PermissionRequest`,
|
|
6300
|
+
* `UserPromptSubmit`, `Stop`, `SessionStart`, `SessionEnd`, and
|
|
6301
|
+
* `PostCompaction` (fires after context compaction; added in the Devin CLI
|
|
6302
|
+
* stable changelog — https://docs.devin.ai/cli/changelog/stable). The
|
|
6300
6303
|
* tool/permission events (`PreToolUse`/`PostToolUse`/`PermissionRequest`) carry
|
|
6301
|
-
* a `matcher` (regex against `tool_name`); the session/turn events
|
|
6304
|
+
* a `matcher` (regex against `tool_name`); the session/turn/compaction events
|
|
6305
|
+
* do not.
|
|
6302
6306
|
*
|
|
6303
6307
|
* Hooks live in `.devin/hooks.v1.json` (project, standalone — the hooks object
|
|
6304
6308
|
* is the entire file) or under the `"hooks"` key of `.devin/config.json` /
|
|
@@ -6313,7 +6317,8 @@ const DEVIN_HOOK_EVENTS = [
|
|
|
6313
6317
|
"postToolUse",
|
|
6314
6318
|
"beforeSubmitPrompt",
|
|
6315
6319
|
"stop",
|
|
6316
|
-
"permissionRequest"
|
|
6320
|
+
"permissionRequest",
|
|
6321
|
+
"postCompact"
|
|
6317
6322
|
];
|
|
6318
6323
|
/** Hook events supported by OpenCode. */
|
|
6319
6324
|
const OPENCODE_HOOK_EVENTS = [
|
|
@@ -6507,7 +6512,7 @@ const ANTIGRAVITY_HOOK_EVENTS = [
|
|
|
6507
6512
|
* Hook events supported by AugmentCode (Auggie CLI).
|
|
6508
6513
|
* Auggie mirrors Claude Code's lifecycle hooks but exposes a smaller set:
|
|
6509
6514
|
* PreToolUse / PostToolUse (tool events, matcher-aware) plus the
|
|
6510
|
-
* SessionStart / SessionEnd / Stop session events (no matcher).
|
|
6515
|
+
* SessionStart / SessionEnd / Stop / Notification session events (no matcher).
|
|
6511
6516
|
* @see https://docs.augmentcode.com/cli/hooks
|
|
6512
6517
|
*/
|
|
6513
6518
|
const AUGMENTCODE_HOOK_EVENTS = [
|
|
@@ -6515,7 +6520,8 @@ const AUGMENTCODE_HOOK_EVENTS = [
|
|
|
6515
6520
|
"postToolUse",
|
|
6516
6521
|
"sessionStart",
|
|
6517
6522
|
"sessionEnd",
|
|
6518
|
-
"stop"
|
|
6523
|
+
"stop",
|
|
6524
|
+
"notification"
|
|
6519
6525
|
];
|
|
6520
6526
|
/**
|
|
6521
6527
|
* Hook events supported by Mistral Vibe (mistral-vibe).
|
|
@@ -6567,6 +6573,10 @@ const JUNIE_HOOK_EVENTS = [
|
|
|
6567
6573
|
* The Qwen-specific events
|
|
6568
6574
|
* `TodoCreated`, `TodoCompleted`, and `StopFailure` map to the canonical
|
|
6569
6575
|
* `todoCreated`, `todoCompleted`, and `stopFailure` events respectively.
|
|
6576
|
+
* Qwen's `HookEventName` enum (`packages/core/src/hooks/types.ts`) also documents
|
|
6577
|
+
* `PostToolBatch`, `UserPromptExpansion`, `PermissionDenied`, and
|
|
6578
|
+
* `InstructionsLoaded`, which map to the canonical `postToolBatch`,
|
|
6579
|
+
* `userPromptExpansion`, `permissionDenied`, and `instructionsLoaded` events.
|
|
6570
6580
|
* @see https://github.com/QwenLM/qwen-code/blob/main/docs/users/features/hooks.md
|
|
6571
6581
|
*/
|
|
6572
6582
|
const QWENCODE_HOOK_EVENTS = [
|
|
@@ -6575,7 +6585,9 @@ const QWENCODE_HOOK_EVENTS = [
|
|
|
6575
6585
|
"preToolUse",
|
|
6576
6586
|
"postToolUse",
|
|
6577
6587
|
"postToolUseFailure",
|
|
6588
|
+
"postToolBatch",
|
|
6578
6589
|
"beforeSubmitPrompt",
|
|
6590
|
+
"userPromptExpansion",
|
|
6579
6591
|
"stop",
|
|
6580
6592
|
"stopFailure",
|
|
6581
6593
|
"subagentStart",
|
|
@@ -6583,7 +6595,9 @@ const QWENCODE_HOOK_EVENTS = [
|
|
|
6583
6595
|
"preCompact",
|
|
6584
6596
|
"postCompact",
|
|
6585
6597
|
"permissionRequest",
|
|
6598
|
+
"permissionDenied",
|
|
6586
6599
|
"notification",
|
|
6600
|
+
"instructionsLoaded",
|
|
6587
6601
|
"todoCreated",
|
|
6588
6602
|
"todoCompleted"
|
|
6589
6603
|
];
|
|
@@ -6593,11 +6607,11 @@ const QWENCODE_HOOK_EVENTS = [
|
|
|
6593
6607
|
* Reasonix's `.reasonix/settings.json` (project) / `~/.reasonix/settings.json`
|
|
6594
6608
|
* (global) documents a ten-event surface (`PreToolUse`, `PostToolUse`,
|
|
6595
6609
|
* `UserPromptSubmit`, `Stop`, `PostLLMCall`, `SessionStart`, `SessionEnd`,
|
|
6596
|
-
* `SubagentStop`, `Notification`, `PreCompact`).
|
|
6597
|
-
*
|
|
6610
|
+
* `SubagentStop`, `Notification`, `PreCompact`). All ten have a clean canonical
|
|
6611
|
+
* equivalent and are mapped: `PreToolUse`, `PostToolUse`,
|
|
6598
6612
|
* `UserPromptSubmit` ← `beforeSubmitPrompt`, `Stop`, `SessionStart`,
|
|
6599
|
-
* `SessionEnd`, `SubagentStop`,
|
|
6600
|
-
*
|
|
6613
|
+
* `SessionEnd`, `SubagentStop`, `PostLLMCall` ← `postModelInvocation`,
|
|
6614
|
+
* `Notification` ← `notification`, and `PreCompact` ← `preCompact`.
|
|
6601
6615
|
* `match` (Reasonix's matcher field name) is honored only on
|
|
6602
6616
|
* `PreToolUse`/`PostToolUse`, matching the canonical `matcher` field's
|
|
6603
6617
|
* tool-event scoping used by other adapters.
|
|
@@ -6611,7 +6625,39 @@ const REASONIX_HOOK_EVENTS = [
|
|
|
6611
6625
|
"sessionStart",
|
|
6612
6626
|
"sessionEnd",
|
|
6613
6627
|
"subagentStop",
|
|
6614
|
-
"postModelInvocation"
|
|
6628
|
+
"postModelInvocation",
|
|
6629
|
+
"notification",
|
|
6630
|
+
"preCompact"
|
|
6631
|
+
];
|
|
6632
|
+
/**
|
|
6633
|
+
* Hook events supported by Grok CLI (xAI Grok Build).
|
|
6634
|
+
*
|
|
6635
|
+
* Grok Build documents a Claude-Code-compatible hooks surface with fourteen
|
|
6636
|
+
* PascalCase events, all of which map 1:1 onto an existing canonical arm:
|
|
6637
|
+
* `SessionStart`, `SessionEnd`, `UserPromptSubmit` ← `beforeSubmitPrompt`,
|
|
6638
|
+
* `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionDenied`,
|
|
6639
|
+
* `Stop`, `StopFailure`, `Notification`, `SubagentStart`, `SubagentStop`,
|
|
6640
|
+
* `PreCompact`, `PostCompact`. A `matcher` (a regex tested against the tool
|
|
6641
|
+
* name) is meaningful only on the tool-name events (`PreToolUse`, `PostToolUse`,
|
|
6642
|
+
* `PostToolUseFailure`, `PermissionDenied`), matching Claude Code's semantics;
|
|
6643
|
+
* the remaining lifecycle events are matcher-less.
|
|
6644
|
+
* @see https://docs.x.ai/build/features/hooks
|
|
6645
|
+
*/
|
|
6646
|
+
const GROKCLI_HOOK_EVENTS = [
|
|
6647
|
+
"sessionStart",
|
|
6648
|
+
"sessionEnd",
|
|
6649
|
+
"beforeSubmitPrompt",
|
|
6650
|
+
"preToolUse",
|
|
6651
|
+
"postToolUse",
|
|
6652
|
+
"postToolUseFailure",
|
|
6653
|
+
"permissionDenied",
|
|
6654
|
+
"stop",
|
|
6655
|
+
"stopFailure",
|
|
6656
|
+
"notification",
|
|
6657
|
+
"subagentStart",
|
|
6658
|
+
"subagentStop",
|
|
6659
|
+
"preCompact",
|
|
6660
|
+
"postCompact"
|
|
6615
6661
|
];
|
|
6616
6662
|
/**
|
|
6617
6663
|
* Hook events supported by Hermes Agent's native Shell Hooks system.
|
|
@@ -6685,6 +6731,7 @@ const HooksConfigSchema = zod_mini.z.looseObject({
|
|
|
6685
6731
|
junie: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
6686
6732
|
vibe: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
6687
6733
|
reasonix: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
6734
|
+
grokcli: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
6688
6735
|
qwencode: zod_mini.z.optional(zod_mini.z.looseObject({
|
|
6689
6736
|
hooks: zod_mini.z.optional(hooksRecordSchema),
|
|
6690
6737
|
disableAllHooks: zod_mini.z.optional(zod_mini.z.boolean())
|
|
@@ -6743,7 +6790,8 @@ const CANONICAL_TO_DEVIN_EVENT_NAMES = {
|
|
|
6743
6790
|
postToolUse: "PostToolUse",
|
|
6744
6791
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
6745
6792
|
stop: "Stop",
|
|
6746
|
-
permissionRequest: "PermissionRequest"
|
|
6793
|
+
permissionRequest: "PermissionRequest",
|
|
6794
|
+
postCompact: "PostCompaction"
|
|
6747
6795
|
};
|
|
6748
6796
|
/**
|
|
6749
6797
|
* Map Devin Local PascalCase event names to canonical camelCase.
|
|
@@ -6758,7 +6806,8 @@ const CANONICAL_TO_AUGMENTCODE_EVENT_NAMES = {
|
|
|
6758
6806
|
postToolUse: "PostToolUse",
|
|
6759
6807
|
sessionStart: "SessionStart",
|
|
6760
6808
|
sessionEnd: "SessionEnd",
|
|
6761
|
-
stop: "Stop"
|
|
6809
|
+
stop: "Stop",
|
|
6810
|
+
notification: "Notification"
|
|
6762
6811
|
};
|
|
6763
6812
|
/**
|
|
6764
6813
|
* Map AugmentCode PascalCase event names to canonical camelCase.
|
|
@@ -7028,7 +7077,9 @@ const CANONICAL_TO_QWENCODE_EVENT_NAMES = {
|
|
|
7028
7077
|
preToolUse: "PreToolUse",
|
|
7029
7078
|
postToolUse: "PostToolUse",
|
|
7030
7079
|
postToolUseFailure: "PostToolUseFailure",
|
|
7080
|
+
postToolBatch: "PostToolBatch",
|
|
7031
7081
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
7082
|
+
userPromptExpansion: "UserPromptExpansion",
|
|
7032
7083
|
stop: "Stop",
|
|
7033
7084
|
subagentStart: "SubagentStart",
|
|
7034
7085
|
subagentStop: "SubagentStop",
|
|
@@ -7036,7 +7087,9 @@ const CANONICAL_TO_QWENCODE_EVENT_NAMES = {
|
|
|
7036
7087
|
preCompact: "PreCompact",
|
|
7037
7088
|
postCompact: "PostCompact",
|
|
7038
7089
|
permissionRequest: "PermissionRequest",
|
|
7090
|
+
permissionDenied: "PermissionDenied",
|
|
7039
7091
|
notification: "Notification",
|
|
7092
|
+
instructionsLoaded: "InstructionsLoaded",
|
|
7040
7093
|
todoCreated: "TodoCreated",
|
|
7041
7094
|
todoCompleted: "TodoCompleted"
|
|
7042
7095
|
};
|
|
@@ -7058,12 +7111,40 @@ const CANONICAL_TO_REASONIX_EVENT_NAMES = {
|
|
|
7058
7111
|
sessionStart: "SessionStart",
|
|
7059
7112
|
sessionEnd: "SessionEnd",
|
|
7060
7113
|
subagentStop: "SubagentStop",
|
|
7061
|
-
postModelInvocation: "PostLLMCall"
|
|
7114
|
+
postModelInvocation: "PostLLMCall",
|
|
7115
|
+
notification: "Notification",
|
|
7116
|
+
preCompact: "PreCompact"
|
|
7062
7117
|
};
|
|
7063
7118
|
/**
|
|
7064
7119
|
* Map Reasonix PascalCase event names to canonical camelCase.
|
|
7065
7120
|
*/
|
|
7066
7121
|
const REASONIX_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_REASONIX_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
7122
|
+
/**
|
|
7123
|
+
* Map canonical camelCase event names to Grok CLI PascalCase.
|
|
7124
|
+
* Grok Build reuses the same Claude-style PascalCase event names, so each
|
|
7125
|
+
* canonical arm maps to its PascalCase equivalent.
|
|
7126
|
+
* @see https://docs.x.ai/build/features/hooks
|
|
7127
|
+
*/
|
|
7128
|
+
const CANONICAL_TO_GROKCLI_EVENT_NAMES = {
|
|
7129
|
+
sessionStart: "SessionStart",
|
|
7130
|
+
sessionEnd: "SessionEnd",
|
|
7131
|
+
beforeSubmitPrompt: "UserPromptSubmit",
|
|
7132
|
+
preToolUse: "PreToolUse",
|
|
7133
|
+
postToolUse: "PostToolUse",
|
|
7134
|
+
postToolUseFailure: "PostToolUseFailure",
|
|
7135
|
+
permissionDenied: "PermissionDenied",
|
|
7136
|
+
stop: "Stop",
|
|
7137
|
+
stopFailure: "StopFailure",
|
|
7138
|
+
notification: "Notification",
|
|
7139
|
+
subagentStart: "SubagentStart",
|
|
7140
|
+
subagentStop: "SubagentStop",
|
|
7141
|
+
preCompact: "PreCompact",
|
|
7142
|
+
postCompact: "PostCompact"
|
|
7143
|
+
};
|
|
7144
|
+
/**
|
|
7145
|
+
* Map Grok CLI PascalCase event names to canonical camelCase.
|
|
7146
|
+
*/
|
|
7147
|
+
const GROKCLI_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_GROKCLI_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
7067
7148
|
//#endregion
|
|
7068
7149
|
//#region src/features/hooks/tool-hooks-converter.ts
|
|
7069
7150
|
function isToolMatcherEntry(x) {
|
|
@@ -7588,7 +7669,8 @@ const AUGMENTCODE_CONVERTER_CONFIG = {
|
|
|
7588
7669
|
noMatcherEvents: /* @__PURE__ */ new Set([
|
|
7589
7670
|
"sessionStart",
|
|
7590
7671
|
"sessionEnd",
|
|
7591
|
-
"stop"
|
|
7672
|
+
"stop",
|
|
7673
|
+
"notification"
|
|
7592
7674
|
])
|
|
7593
7675
|
};
|
|
7594
7676
|
/**
|
|
@@ -8687,7 +8769,8 @@ const DEVIN_CONVERTER_CONFIG = {
|
|
|
8687
8769
|
"sessionStart",
|
|
8688
8770
|
"sessionEnd",
|
|
8689
8771
|
"stop",
|
|
8690
|
-
"beforeSubmitPrompt"
|
|
8772
|
+
"beforeSubmitPrompt",
|
|
8773
|
+
"postCompact"
|
|
8691
8774
|
])
|
|
8692
8775
|
};
|
|
8693
8776
|
/**
|
|
@@ -8996,6 +9079,167 @@ var GooseHooks = class GooseHooks extends ToolHooks {
|
|
|
8996
9079
|
}
|
|
8997
9080
|
};
|
|
8998
9081
|
//#endregion
|
|
9082
|
+
//#region src/constants/grokcli-paths.ts
|
|
9083
|
+
/**
|
|
9084
|
+
* Grok Build CLI (xAI) configuration-layout conventions.
|
|
9085
|
+
*
|
|
9086
|
+
* Single source of truth for where Grok Build expects its files. Grok Build
|
|
9087
|
+
* stores MCP servers (and other settings) in a `config.toml` under `.grok/`,
|
|
9088
|
+
* with project/global scopes resolved by the directory the CLI runs in
|
|
9089
|
+
* (`./.grok/config.toml` vs `~/.grok/config.toml`).
|
|
9090
|
+
*
|
|
9091
|
+
* Verified against `grok` 0.2.54 (`grok mcp add --help`, `grok mcp add`):
|
|
9092
|
+
* `-s project` writes `./.grok/config.toml`, `-s user` writes
|
|
9093
|
+
* `~/.grok/config.toml`, both as a TOML `[mcp_servers.<name>]` table.
|
|
9094
|
+
* @see https://docs.x.ai/build/overview
|
|
9095
|
+
*/
|
|
9096
|
+
/** Root directory for Grok Build configuration, relative to the scope root. */
|
|
9097
|
+
const GROKCLI_DIR = ".grok";
|
|
9098
|
+
/** MCP servers and other settings live in `config.toml` under `.grok/`. */
|
|
9099
|
+
const GROKCLI_MCP_FILE_NAME = "config.toml";
|
|
9100
|
+
/**
|
|
9101
|
+
* Shared Grok CLI config file (`config.toml`). MCP servers, the `[ui]`
|
|
9102
|
+
* permission mode, and other settings all live here; permissions reuse the same
|
|
9103
|
+
* file name as MCP since Grok consolidates everything into one config.
|
|
9104
|
+
*/
|
|
9105
|
+
const GROKCLI_CONFIG_FILE_NAME = "config.toml";
|
|
9106
|
+
/** Skills directory under `.grok/` (project: `./.grok/skills`, global: `~/.grok/skills`). */
|
|
9107
|
+
const GROKCLI_SKILLS_DIR_PATH = (0, node_path.join)(GROKCLI_DIR, "skills");
|
|
9108
|
+
/**
|
|
9109
|
+
* Hooks directory under `.grok/`. Grok Build discovers hook config files from
|
|
9110
|
+
* `.grok/hooks/*.json` (project) and `~/.grok/hooks/*.json` (global), each a
|
|
9111
|
+
* standalone JSON file using the Claude-Code-compatible nested `{ hooks: { … } }`
|
|
9112
|
+
* shape. rulesync writes all its hooks into a single `rulesync.json`.
|
|
9113
|
+
* @see https://docs.x.ai/build/features/hooks
|
|
9114
|
+
*/
|
|
9115
|
+
const GROKCLI_HOOKS_DIR_PATH = (0, node_path.join)(GROKCLI_DIR, "hooks");
|
|
9116
|
+
/** rulesync-managed Grok hooks file under `.grok/hooks/`. */
|
|
9117
|
+
const GROKCLI_HOOKS_FILE_NAME = "rulesync.json";
|
|
9118
|
+
/**
|
|
9119
|
+
* Subagents (agent profiles) directory under `.grok/`. Grok Build discovers
|
|
9120
|
+
* agent definitions from `.grok/agents/*.md` (project) and `~/.grok/agents/*.md`
|
|
9121
|
+
* (global), each a Markdown file with YAML frontmatter (verified via
|
|
9122
|
+
* `grok inspect`; format matches the bundled `~/.grok/bundled/agents/*.md`).
|
|
9123
|
+
*/
|
|
9124
|
+
const GROKCLI_AGENTS_DIR_PATH = (0, node_path.join)(GROKCLI_DIR, "agents");
|
|
9125
|
+
/**
|
|
9126
|
+
* Instruction file. Grok reads the AGENTS.md instruction-file family natively,
|
|
9127
|
+
* including the user-level `~/.grok/AGENTS.md` for global rules (verified via
|
|
9128
|
+
* `grok inspect`, consistent with the `.grok/` global discovery used by the
|
|
9129
|
+
* MCP/skills/subagents adapters).
|
|
9130
|
+
*/
|
|
9131
|
+
const GROKCLI_RULE_FILE_NAME = "AGENTS.md";
|
|
9132
|
+
//#endregion
|
|
9133
|
+
//#region src/features/hooks/grokcli-hooks.ts
|
|
9134
|
+
const GROKCLI_CONVERTER_CONFIG = {
|
|
9135
|
+
supportedEvents: GROKCLI_HOOK_EVENTS,
|
|
9136
|
+
canonicalToToolEventNames: CANONICAL_TO_GROKCLI_EVENT_NAMES,
|
|
9137
|
+
toolToCanonicalEventNames: GROKCLI_TO_CANONICAL_EVENT_NAMES,
|
|
9138
|
+
projectDirVar: "",
|
|
9139
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command"]),
|
|
9140
|
+
noMatcherEvents: /* @__PURE__ */ new Set([
|
|
9141
|
+
"sessionStart",
|
|
9142
|
+
"sessionEnd",
|
|
9143
|
+
"beforeSubmitPrompt",
|
|
9144
|
+
"stop",
|
|
9145
|
+
"stopFailure",
|
|
9146
|
+
"notification",
|
|
9147
|
+
"subagentStart",
|
|
9148
|
+
"subagentStop",
|
|
9149
|
+
"preCompact",
|
|
9150
|
+
"postCompact"
|
|
9151
|
+
])
|
|
9152
|
+
};
|
|
9153
|
+
/**
|
|
9154
|
+
* Hooks generator for Grok CLI (xAI Grok Build).
|
|
9155
|
+
*
|
|
9156
|
+
* Grok Build adopts a Claude-Code-compatible lifecycle hooks model: each event
|
|
9157
|
+
* maps to an array of `{ matcher?, hooks: [{ type, command, timeout? }] }`
|
|
9158
|
+
* matcher groups under a top-level `hooks` key. rulesync writes all its hooks
|
|
9159
|
+
* into a single standalone `rulesync.json` file discovered from
|
|
9160
|
+
* `.grok/hooks/*.json` (project) and `~/.grok/hooks/*.json` (global). The file
|
|
9161
|
+
* is dedicated to hooks and owned wholesale by rulesync, so it may be deleted
|
|
9162
|
+
* as an orphan.
|
|
9163
|
+
*
|
|
9164
|
+
* @see https://docs.x.ai/build/features/hooks
|
|
9165
|
+
*/
|
|
9166
|
+
var GrokcliHooks = class GrokcliHooks extends ToolHooks {
|
|
9167
|
+
constructor(params) {
|
|
9168
|
+
super({
|
|
9169
|
+
...params,
|
|
9170
|
+
fileContent: params.fileContent ?? "{}"
|
|
9171
|
+
});
|
|
9172
|
+
}
|
|
9173
|
+
static getSettablePaths(_options = {}) {
|
|
9174
|
+
return {
|
|
9175
|
+
relativeDirPath: GROKCLI_HOOKS_DIR_PATH,
|
|
9176
|
+
relativeFilePath: GROKCLI_HOOKS_FILE_NAME
|
|
9177
|
+
};
|
|
9178
|
+
}
|
|
9179
|
+
static async fromFile({ outputRoot = process.cwd(), validate = true, global = false }) {
|
|
9180
|
+
const paths = GrokcliHooks.getSettablePaths({ global });
|
|
9181
|
+
const fileContent = await readFileContentOrNull((0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath)) ?? "{\"hooks\":{}}";
|
|
9182
|
+
return new GrokcliHooks({
|
|
9183
|
+
outputRoot,
|
|
9184
|
+
relativeDirPath: paths.relativeDirPath,
|
|
9185
|
+
relativeFilePath: paths.relativeFilePath,
|
|
9186
|
+
fileContent,
|
|
9187
|
+
validate
|
|
9188
|
+
});
|
|
9189
|
+
}
|
|
9190
|
+
static async fromRulesyncHooks({ outputRoot = process.cwd(), rulesyncHooks, validate = true, global = false, logger }) {
|
|
9191
|
+
const paths = GrokcliHooks.getSettablePaths({ global });
|
|
9192
|
+
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
9193
|
+
const config = rulesyncHooks.getJson();
|
|
9194
|
+
const grokHooks = canonicalToToolHooks({
|
|
9195
|
+
config,
|
|
9196
|
+
toolOverrideHooks: config.grokcli?.hooks,
|
|
9197
|
+
converterConfig: GROKCLI_CONVERTER_CONFIG,
|
|
9198
|
+
logger
|
|
9199
|
+
});
|
|
9200
|
+
await readOrInitializeFileContent(filePath, JSON.stringify({ hooks: {} }, null, 2));
|
|
9201
|
+
const fileContent = JSON.stringify({ hooks: grokHooks }, null, 2);
|
|
9202
|
+
return new GrokcliHooks({
|
|
9203
|
+
outputRoot,
|
|
9204
|
+
relativeDirPath: paths.relativeDirPath,
|
|
9205
|
+
relativeFilePath: paths.relativeFilePath,
|
|
9206
|
+
fileContent,
|
|
9207
|
+
validate
|
|
9208
|
+
});
|
|
9209
|
+
}
|
|
9210
|
+
toRulesyncHooks() {
|
|
9211
|
+
let parsed;
|
|
9212
|
+
try {
|
|
9213
|
+
parsed = JSON.parse(this.getFileContent());
|
|
9214
|
+
} catch (error) {
|
|
9215
|
+
throw new Error(`Failed to parse Grok hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
9216
|
+
}
|
|
9217
|
+
const hooks = toolHooksToCanonical({
|
|
9218
|
+
hooks: isRecord(parsed) && isRecord(parsed.hooks) ? parsed.hooks : {},
|
|
9219
|
+
converterConfig: GROKCLI_CONVERTER_CONFIG
|
|
9220
|
+
});
|
|
9221
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9222
|
+
version: 1,
|
|
9223
|
+
hooks
|
|
9224
|
+
}, null, 2) });
|
|
9225
|
+
}
|
|
9226
|
+
validate() {
|
|
9227
|
+
return {
|
|
9228
|
+
success: true,
|
|
9229
|
+
error: null
|
|
9230
|
+
};
|
|
9231
|
+
}
|
|
9232
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
9233
|
+
return new GrokcliHooks({
|
|
9234
|
+
outputRoot,
|
|
9235
|
+
relativeDirPath,
|
|
9236
|
+
relativeFilePath,
|
|
9237
|
+
fileContent: JSON.stringify({ hooks: {} }, null, 2),
|
|
9238
|
+
validate: false
|
|
9239
|
+
});
|
|
9240
|
+
}
|
|
9241
|
+
};
|
|
9242
|
+
//#endregion
|
|
8999
9243
|
//#region src/features/hooks/hermesagent-hooks.ts
|
|
9000
9244
|
/**
|
|
9001
9245
|
* Canonical events that map to a Hermes tool-call event (`pre_tool_call` /
|
|
@@ -10202,9 +10446,9 @@ function reasonixHooksToCanonical(hooks) {
|
|
|
10202
10446
|
* Reasonix hooks live in a Claude-Code-style but standalone JSON file —
|
|
10203
10447
|
* `.reasonix/settings.json` (project) or `~/.reasonix/settings.json`
|
|
10204
10448
|
* (global) — separate from the `[permissions]`/`[[plugins]]` TOML config.
|
|
10205
|
-
*
|
|
10449
|
+
* All ten upstream events have a clean canonical equivalent and are mapped:
|
|
10206
10450
|
* PreToolUse/PostToolUse/UserPromptSubmit/Stop plus SessionStart/SessionEnd/
|
|
10207
|
-
* SubagentStop/PostLLMCall (see REASONIX_HOOK_EVENTS).
|
|
10451
|
+
* SubagentStop/PostLLMCall/Notification/PreCompact (see REASONIX_HOOK_EVENTS).
|
|
10208
10452
|
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
|
|
10209
10453
|
*/
|
|
10210
10454
|
var ReasonixHooks = class ReasonixHooks extends ToolHooks {
|
|
@@ -10792,6 +11036,17 @@ const toolHooksFactories = /* @__PURE__ */ new Map([
|
|
|
10792
11036
|
supportedEvents: REASONIX_HOOK_EVENTS,
|
|
10793
11037
|
supportedHookTypes: ["command"],
|
|
10794
11038
|
supportsMatcher: true
|
|
11039
|
+
}],
|
|
11040
|
+
["grokcli", {
|
|
11041
|
+
class: GrokcliHooks,
|
|
11042
|
+
meta: {
|
|
11043
|
+
supportsProject: true,
|
|
11044
|
+
supportsGlobal: true,
|
|
11045
|
+
supportsImport: true
|
|
11046
|
+
},
|
|
11047
|
+
supportedEvents: GROKCLI_HOOK_EVENTS,
|
|
11048
|
+
supportedHookTypes: ["command"],
|
|
11049
|
+
supportsMatcher: true
|
|
10795
11050
|
}]
|
|
10796
11051
|
]);
|
|
10797
11052
|
const hooksProcessorToolTargets = [...toolHooksFactories.entries()].filter(([, f]) => f.meta.supportsProject).map(([t]) => t);
|
|
@@ -13047,7 +13302,13 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
13047
13302
|
...rest,
|
|
13048
13303
|
validate: false
|
|
13049
13304
|
});
|
|
13050
|
-
|
|
13305
|
+
let toml;
|
|
13306
|
+
try {
|
|
13307
|
+
toml = smol_toml.parse(this.fileContent);
|
|
13308
|
+
} catch (error) {
|
|
13309
|
+
throw new Error(`Failed to parse Codex CLI config at ${this.getFilePath()}: ${formatError(error)}`, { cause: error });
|
|
13310
|
+
}
|
|
13311
|
+
this.toml = toml;
|
|
13051
13312
|
if (rest.validate) {
|
|
13052
13313
|
const result = this.validate();
|
|
13053
13314
|
if (!result.success) throw result.error;
|
|
@@ -13083,7 +13344,12 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
13083
13344
|
const paths = this.getSettablePaths({ global });
|
|
13084
13345
|
const configTomlFilePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
13085
13346
|
const configTomlFileContent = await readFileContentOrNull(configTomlFilePath) ?? "";
|
|
13086
|
-
|
|
13347
|
+
let configToml;
|
|
13348
|
+
try {
|
|
13349
|
+
configToml = smol_toml.parse(configTomlFileContent || smol_toml.stringify({}));
|
|
13350
|
+
} catch (error) {
|
|
13351
|
+
throw new Error(`Failed to parse existing Codex CLI config at ${configTomlFilePath}: ${formatError(error)}`, { cause: error });
|
|
13352
|
+
}
|
|
13087
13353
|
const strippedMcpServers = rulesyncMcp.getMcpServers();
|
|
13088
13354
|
const rawMcpServers = rulesyncMcp.getJson().mcpServers;
|
|
13089
13355
|
const converted = convertToCodexFormat(Object.fromEntries(Object.entries(strippedMcpServers).map(([serverName, serverConfig]) => {
|
|
@@ -14057,47 +14323,6 @@ var GooseMcp = class GooseMcp extends ToolMcp {
|
|
|
14057
14323
|
}
|
|
14058
14324
|
};
|
|
14059
14325
|
//#endregion
|
|
14060
|
-
//#region src/constants/grokcli-paths.ts
|
|
14061
|
-
/**
|
|
14062
|
-
* Grok Build CLI (xAI) configuration-layout conventions.
|
|
14063
|
-
*
|
|
14064
|
-
* Single source of truth for where Grok Build expects its files. Grok Build
|
|
14065
|
-
* stores MCP servers (and other settings) in a `config.toml` under `.grok/`,
|
|
14066
|
-
* with project/global scopes resolved by the directory the CLI runs in
|
|
14067
|
-
* (`./.grok/config.toml` vs `~/.grok/config.toml`).
|
|
14068
|
-
*
|
|
14069
|
-
* Verified against `grok` 0.2.54 (`grok mcp add --help`, `grok mcp add`):
|
|
14070
|
-
* `-s project` writes `./.grok/config.toml`, `-s user` writes
|
|
14071
|
-
* `~/.grok/config.toml`, both as a TOML `[mcp_servers.<name>]` table.
|
|
14072
|
-
* @see https://docs.x.ai/build/overview
|
|
14073
|
-
*/
|
|
14074
|
-
/** Root directory for Grok Build configuration, relative to the scope root. */
|
|
14075
|
-
const GROKCLI_DIR = ".grok";
|
|
14076
|
-
/** MCP servers and other settings live in `config.toml` under `.grok/`. */
|
|
14077
|
-
const GROKCLI_MCP_FILE_NAME = "config.toml";
|
|
14078
|
-
/**
|
|
14079
|
-
* Shared Grok CLI config file (`config.toml`). MCP servers, the `[ui]`
|
|
14080
|
-
* permission mode, and other settings all live here; permissions reuse the same
|
|
14081
|
-
* file name as MCP since Grok consolidates everything into one config.
|
|
14082
|
-
*/
|
|
14083
|
-
const GROKCLI_CONFIG_FILE_NAME = "config.toml";
|
|
14084
|
-
/** Skills directory under `.grok/` (project: `./.grok/skills`, global: `~/.grok/skills`). */
|
|
14085
|
-
const GROKCLI_SKILLS_DIR_PATH = (0, node_path.join)(GROKCLI_DIR, "skills");
|
|
14086
|
-
/**
|
|
14087
|
-
* Subagents (agent profiles) directory under `.grok/`. Grok Build discovers
|
|
14088
|
-
* agent definitions from `.grok/agents/*.md` (project) and `~/.grok/agents/*.md`
|
|
14089
|
-
* (global), each a Markdown file with YAML frontmatter (verified via
|
|
14090
|
-
* `grok inspect`; format matches the bundled `~/.grok/bundled/agents/*.md`).
|
|
14091
|
-
*/
|
|
14092
|
-
const GROKCLI_AGENTS_DIR_PATH = (0, node_path.join)(GROKCLI_DIR, "agents");
|
|
14093
|
-
/**
|
|
14094
|
-
* Instruction file. Grok reads the AGENTS.md instruction-file family natively,
|
|
14095
|
-
* including the user-level `~/.grok/AGENTS.md` for global rules (verified via
|
|
14096
|
-
* `grok inspect`, consistent with the `.grok/` global discovery used by the
|
|
14097
|
-
* MCP/skills/subagents adapters).
|
|
14098
|
-
*/
|
|
14099
|
-
const GROKCLI_RULE_FILE_NAME = "AGENTS.md";
|
|
14100
|
-
//#endregion
|
|
14101
14326
|
//#region src/features/mcp/grokcli-mcp.ts
|
|
14102
14327
|
const MAX_REMOVE_EMPTY_ENTRIES_DEPTH = 32;
|
|
14103
14328
|
/**
|
|
@@ -14257,6 +14482,54 @@ function resolveHermesTimeout(config) {
|
|
|
14257
14482
|
if (typeof config.networkTimeout === "number") return config.networkTimeout;
|
|
14258
14483
|
}
|
|
14259
14484
|
/**
|
|
14485
|
+
* Copies the advanced Hermes-recognized per-server fields that have no canonical
|
|
14486
|
+
* alias — `auth` (`oauth` for OAuth 2.1/PKCE), mTLS `client_cert` (string PEM
|
|
14487
|
+
* path, or `[cert, key]`/`[cert, key, password]` list) and `client_key`,
|
|
14488
|
+
* `connect_timeout` (seconds), and `supports_parallel_tool_calls` — verbatim
|
|
14489
|
+
* from `source` to `target`. Field names are identical on both sides (the
|
|
14490
|
+
* canonical `McpServerSchema` is a `looseObject`), so this serves export and
|
|
14491
|
+
* import alike. See the Hermes mcp-config-reference.
|
|
14492
|
+
*/
|
|
14493
|
+
function copyHermesAdvancedFields(source, target) {
|
|
14494
|
+
if (typeof source.auth === "string") target.auth = source.auth;
|
|
14495
|
+
if (typeof source.client_cert === "string" || isStringArray(source.client_cert)) target.client_cert = source.client_cert;
|
|
14496
|
+
if (typeof source.client_key === "string") target.client_key = source.client_key;
|
|
14497
|
+
if (typeof source.connect_timeout === "number") target.connect_timeout = source.connect_timeout;
|
|
14498
|
+
if (typeof source.supports_parallel_tool_calls === "boolean") target.supports_parallel_tool_calls = source.supports_parallel_tool_calls;
|
|
14499
|
+
}
|
|
14500
|
+
/**
|
|
14501
|
+
* Builds Hermes's per-server `tools` block from a canonical server config. The
|
|
14502
|
+
* canonical `enabledTools`/`disabledTools` arrays become `include`/`exclude`,
|
|
14503
|
+
* and the boolean `promptsEnabled`/`resourcesEnabled` toggles become Hermes's
|
|
14504
|
+
* `prompts`/`resources` capability flags. Returns an empty object when the
|
|
14505
|
+
* server has no tool scoping (the caller omits the block in that case).
|
|
14506
|
+
*
|
|
14507
|
+
* Note: `promptsEnabled`/`resourcesEnabled` are canonical top-level keys rather
|
|
14508
|
+
* than a nested canonical `tools` object, because canonical `McpServerSchema.tools`
|
|
14509
|
+
* is reserved as a `string[]` (used by other tools) — reusing it for an object
|
|
14510
|
+
* would fail validation on the next `generate`.
|
|
14511
|
+
*/
|
|
14512
|
+
function buildHermesToolsBlock(config) {
|
|
14513
|
+
const tools = {};
|
|
14514
|
+
if (isStringArray(config.enabledTools)) tools.include = config.enabledTools;
|
|
14515
|
+
if (isStringArray(config.disabledTools)) tools.exclude = config.disabledTools;
|
|
14516
|
+
if (typeof config.promptsEnabled === "boolean") tools.prompts = config.promptsEnabled;
|
|
14517
|
+
if (typeof config.resourcesEnabled === "boolean") tools.resources = config.resourcesEnabled;
|
|
14518
|
+
return tools;
|
|
14519
|
+
}
|
|
14520
|
+
/**
|
|
14521
|
+
* Applies a Hermes per-server `tools` block back onto a canonical server config
|
|
14522
|
+
* (inverse of {@link buildHermesToolsBlock}): `include`/`exclude` become
|
|
14523
|
+
* `enabledTools`/`disabledTools`, and `prompts`/`resources` become the boolean
|
|
14524
|
+
* `promptsEnabled`/`resourcesEnabled` top-level toggles.
|
|
14525
|
+
*/
|
|
14526
|
+
function applyHermesToolsBlock(hermesTools, server) {
|
|
14527
|
+
if (isStringArray(hermesTools.include)) server.enabledTools = hermesTools.include;
|
|
14528
|
+
if (isStringArray(hermesTools.exclude)) server.disabledTools = hermesTools.exclude;
|
|
14529
|
+
if (typeof hermesTools.prompts === "boolean") server.promptsEnabled = hermesTools.prompts;
|
|
14530
|
+
if (typeof hermesTools.resources === "boolean") server.resourcesEnabled = hermesTools.resources;
|
|
14531
|
+
}
|
|
14532
|
+
/**
|
|
14260
14533
|
* Converts a single rulesync canonical MCP server into a Hermes `mcp_servers:` entry.
|
|
14261
14534
|
*
|
|
14262
14535
|
* Hermes is close to the MCP spec but not identical: `command` must be a single
|
|
@@ -14290,9 +14563,8 @@ function convertServerToHermes(config) {
|
|
|
14290
14563
|
if (config.disabled === true) out.enabled = false;
|
|
14291
14564
|
const timeout = resolveHermesTimeout(config);
|
|
14292
14565
|
if (timeout !== void 0) out.timeout = timeout;
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
if (isStringArray(config.disabledTools)) tools.exclude = config.disabledTools;
|
|
14566
|
+
copyHermesAdvancedFields(config, out);
|
|
14567
|
+
const tools = buildHermesToolsBlock(config);
|
|
14296
14568
|
if (Object.keys(tools).length > 0) out.tools = tools;
|
|
14297
14569
|
return out;
|
|
14298
14570
|
}
|
|
@@ -14335,10 +14607,8 @@ function convertFromHermesFormat(mcpServers) {
|
|
|
14335
14607
|
if (isPlainObject$1(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
|
|
14336
14608
|
if (config.enabled === false) server.disabled = true;
|
|
14337
14609
|
if (typeof config.timeout === "number") server.networkTimeout = config.timeout;
|
|
14338
|
-
|
|
14339
|
-
|
|
14340
|
-
if (isStringArray(config.tools.exclude)) server.disabledTools = config.tools.exclude;
|
|
14341
|
-
}
|
|
14610
|
+
copyHermesAdvancedFields(config, server);
|
|
14611
|
+
if (isRecord(config.tools)) applyHermesToolsBlock(config.tools, server);
|
|
14342
14612
|
result[name] = server;
|
|
14343
14613
|
}
|
|
14344
14614
|
return result;
|
|
@@ -16633,18 +16903,27 @@ const CursorPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
16633
16903
|
* Tool-scoped override block for Qwen Code. Qwen's `settings.json` exposes
|
|
16634
16904
|
* autonomy/sandbox controls with no canonical permission category — under
|
|
16635
16905
|
* `tools` (`approvalMode` = plan/default/auto-edit/auto/yolo, `autoAccept`,
|
|
16636
|
-
* `sandbox`, `sandboxImage`, `disabled`) and `security` (`folderTrust`).
|
|
16637
|
-
*
|
|
16638
|
-
*
|
|
16639
|
-
*
|
|
16640
|
-
*
|
|
16906
|
+
* `sandbox`, `sandboxImage`, `disabled`) and `security` (`folderTrust`). It also
|
|
16907
|
+
* exposes `permissions.autoMode` (the Auto Mode classifier config:
|
|
16908
|
+
* `hints.{allow,softDeny,hardDeny}`, `environment`, `classifyAllShell` — see
|
|
16909
|
+
* https://qwenlm.github.io/qwen-code-docs/en/users/features/auto-mode/), which
|
|
16910
|
+
* likewise has no canonical category. Fields placed here are merged into the
|
|
16911
|
+
* matching `settings.json` group and emitted only for Qwen, while the shared
|
|
16912
|
+
* `permission` block continues to drive the `permissions.allow`/`ask`/`deny`
|
|
16913
|
+
* arrays. Kept `looseObject` (verbatim passthrough) so any current or future
|
|
16914
|
+
* `tools`/`security`/`autoMode` key can be authored.
|
|
16641
16915
|
*
|
|
16642
16916
|
* @example
|
|
16643
|
-
* {
|
|
16917
|
+
* {
|
|
16918
|
+
* "tools": { "approvalMode": "auto-edit" },
|
|
16919
|
+
* "security": { "folderTrust": { "enabled": true } },
|
|
16920
|
+
* "autoMode": { "hints": { "allow": ["Running tests"] }, "classifyAllShell": true }
|
|
16921
|
+
* }
|
|
16644
16922
|
*/
|
|
16645
16923
|
const QwencodePermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
16646
16924
|
tools: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
16647
|
-
security: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
16925
|
+
security: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
16926
|
+
autoMode: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
16648
16927
|
});
|
|
16649
16928
|
/**
|
|
16650
16929
|
* Tool-scoped override block for Reasonix. Reasonix has security axes orthogonal
|
|
@@ -16671,9 +16950,11 @@ const ReasonixPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
16671
16950
|
* exposes security controls with no canonical per-command allow/ask/deny slot —
|
|
16672
16951
|
* `commandBlocklist` (a hard-block tier that can never be approved, distinct from
|
|
16673
16952
|
* an approvable `deny`), `networkPolicy` (`allowedIps`), `sandbox`
|
|
16674
|
-
* (`enabled`/`mode`/`filesystem`/`network`), `mcpPolicy`,
|
|
16953
|
+
* (`enabled`/`mode`/`filesystem`/`network`), `mcpPolicy`,
|
|
16954
|
+
* `mcpAutonomyOverrides` (per-MCP-tool autonomy levels), `enableDroidShield`,
|
|
16675
16955
|
* and autonomy settings (`sessionDefaultSettings`, `maxAutonomyLevel`,
|
|
16676
|
-
* `interactionMode`). Fields placed here are merged
|
|
16956
|
+
* `subagentAutonomyLevel`, `interactionMode`). Fields placed here are merged
|
|
16957
|
+
* into `settings.json` and
|
|
16677
16958
|
* emitted only for Factory Droid, while the shared `permission` block continues
|
|
16678
16959
|
* to drive `commandAllowlist`/`commandDenylist`. Kept `looseObject` passthrough.
|
|
16679
16960
|
*
|
|
@@ -16866,6 +17147,41 @@ const KiroPermissionsOverrideSchema = zod_mini.z.looseObject({ toolsSettings: zo
|
|
|
16866
17147
|
}))
|
|
16867
17148
|
})) });
|
|
16868
17149
|
/**
|
|
17150
|
+
* Codex CLI's approval-workflow policy. Serialized as a kebab-case string in
|
|
17151
|
+
* `.codex/config.toml`. `on-failure` is a legacy alias for `on-request` that
|
|
17152
|
+
* Codex still accepts, so it is included so existing configs round-trip. The
|
|
17153
|
+
* granular table form (`{ granular = { … } }`) is modeled separately in the
|
|
17154
|
+
* override union.
|
|
17155
|
+
* @see https://learn.chatgpt.com/docs/config-file/config-reference
|
|
17156
|
+
*/
|
|
17157
|
+
const CodexApprovalPolicySchema = zod_mini.z.enum([
|
|
17158
|
+
"untrusted",
|
|
17159
|
+
"on-request",
|
|
17160
|
+
"on-failure",
|
|
17161
|
+
"never"
|
|
17162
|
+
]);
|
|
17163
|
+
/**
|
|
17164
|
+
* Codex CLI's classic sandbox mode. Serialized as a kebab-case string in
|
|
17165
|
+
* `.codex/config.toml`.
|
|
17166
|
+
* @see https://learn.chatgpt.com/docs/config-file/config-reference
|
|
17167
|
+
*/
|
|
17168
|
+
const CodexSandboxModeSchema = zod_mini.z.enum([
|
|
17169
|
+
"read-only",
|
|
17170
|
+
"workspace-write",
|
|
17171
|
+
"danger-full-access"
|
|
17172
|
+
]);
|
|
17173
|
+
/**
|
|
17174
|
+
* Codex CLI's reviewer for approval requests. `guardian_subagent` is a legacy
|
|
17175
|
+
* value Codex still accepts for backward compatibility, so it is included so
|
|
17176
|
+
* existing configs round-trip through the rulesync model.
|
|
17177
|
+
* @see https://learn.chatgpt.com/docs/config-file/config-reference
|
|
17178
|
+
*/
|
|
17179
|
+
const CodexApprovalsReviewerSchema = zod_mini.z.enum([
|
|
17180
|
+
"user",
|
|
17181
|
+
"auto_review",
|
|
17182
|
+
"guardian_subagent"
|
|
17183
|
+
]);
|
|
17184
|
+
/**
|
|
16869
17185
|
* Codex CLI-scoped permission override.
|
|
16870
17186
|
*
|
|
16871
17187
|
* Codex CLI's permission surface is richer than the canonical allow/ask/deny
|
|
@@ -16874,15 +17190,16 @@ const KiroPermissionsOverrideSchema = zod_mini.z.looseObject({ toolsSettings: zo
|
|
|
16874
17190
|
* override whose fields are written verbatim as top-level `.codex/config.toml`
|
|
16875
17191
|
* keys (the override wins per key; existing sibling keys the user set directly
|
|
16876
17192
|
* are preserved):
|
|
16877
|
-
* - `approval_policy` — `untrusted` | `on-request`
|
|
16878
|
-
* `{ granular = { … } }` table (kept verbatim; the granular
|
|
16879
|
-
* required fields that are brittle to model as typed keys).
|
|
17193
|
+
* - `approval_policy` — `untrusted` | `on-request` (legacy alias `on-failure`) |
|
|
17194
|
+
* `never`, or a `{ granular = { … } }` table (kept verbatim; the granular
|
|
17195
|
+
* schema has required fields that are brittle to model as typed keys).
|
|
16880
17196
|
* - `sandbox_mode` — `read-only` | `workspace-write` | `danger-full-access`,
|
|
16881
17197
|
* with the sibling `sandbox_workspace_write` table (`network_access`,
|
|
16882
17198
|
* `writable_roots`, …).
|
|
16883
17199
|
* - `apps` — per-app tool gating (`apps.<id>.tools.<tool>.approval_mode` /
|
|
16884
17200
|
* `.enabled`, `apps.<id>.default_tools_approval_mode`).
|
|
16885
|
-
* - `approvals_reviewer` — the reviewer-approval surface
|
|
17201
|
+
* - `approvals_reviewer` — the reviewer-approval surface (`user` | `auto_review`
|
|
17202
|
+
* | `guardian_subagent`), or a table for the richer reviewer config.
|
|
16886
17203
|
*
|
|
16887
17204
|
* Two surfaces are deliberately NOT authorable here so the override can never
|
|
16888
17205
|
* clobber a feature-owned key: `mcp_servers.*` per-MCP gating is owned by the
|
|
@@ -16900,11 +17217,11 @@ const KiroPermissionsOverrideSchema = zod_mini.z.looseObject({ toolsSettings: zo
|
|
|
16900
17217
|
* "sandbox_workspace_write": { "network_access": true } }
|
|
16901
17218
|
*/
|
|
16902
17219
|
const CodexcliPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
16903
|
-
approval_policy: zod_mini.z.optional(zod_mini.z.union([
|
|
16904
|
-
sandbox_mode: zod_mini.z.optional(
|
|
17220
|
+
approval_policy: zod_mini.z.optional(zod_mini.z.union([CodexApprovalPolicySchema, zod_mini.z.looseObject({})])),
|
|
17221
|
+
sandbox_mode: zod_mini.z.optional(CodexSandboxModeSchema),
|
|
16905
17222
|
sandbox_workspace_write: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
16906
17223
|
apps: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
16907
|
-
approvals_reviewer: zod_mini.z.optional(zod_mini.z.union([
|
|
17224
|
+
approvals_reviewer: zod_mini.z.optional(zod_mini.z.union([CodexApprovalsReviewerSchema, zod_mini.z.looseObject({})]))
|
|
16908
17225
|
});
|
|
16909
17226
|
/**
|
|
16910
17227
|
* Permissions configuration.
|
|
@@ -19765,9 +20082,11 @@ const FACTORYDROID_OVERRIDE_KEYS = [
|
|
|
19765
20082
|
"networkPolicy",
|
|
19766
20083
|
"sandbox",
|
|
19767
20084
|
"mcpPolicy",
|
|
20085
|
+
"mcpAutonomyOverrides",
|
|
19768
20086
|
"enableDroidShield",
|
|
19769
20087
|
"sessionDefaultSettings",
|
|
19770
20088
|
"maxAutonomyLevel",
|
|
20089
|
+
"subagentAutonomyLevel",
|
|
19771
20090
|
"interactionMode"
|
|
19772
20091
|
];
|
|
19773
20092
|
/**
|
|
@@ -20125,7 +20444,6 @@ function convertGoosePermissionConfigToRulesync(userPermission) {
|
|
|
20125
20444
|
}
|
|
20126
20445
|
//#endregion
|
|
20127
20446
|
//#region src/features/permissions/grokcli-permissions.ts
|
|
20128
|
-
const GROKCLI_GLOBAL_ONLY_MESSAGE = "Grok CLI permissions are global-only; use --global to sync ~/.grok/config.toml";
|
|
20129
20447
|
const GROKCLI_UI_KEY = "ui";
|
|
20130
20448
|
const GROKCLI_PERMISSION_MODE_KEY = "permission_mode";
|
|
20131
20449
|
const GROKCLI_PERMISSION_KEY = "permission";
|
|
@@ -20227,13 +20545,19 @@ function parseGrokEntry(entry) {
|
|
|
20227
20545
|
* compatibility with older Grok versions: `always-approve` when the config is
|
|
20228
20546
|
* pure-`allow`, otherwise `ask` (conservative — it is never `always-approve`
|
|
20229
20547
|
* while any `deny`/`ask` rule exists, so it never contradicts the fine-grained
|
|
20230
|
-
* arrays).
|
|
20231
|
-
*
|
|
20232
|
-
*
|
|
20233
|
-
*
|
|
20234
|
-
*
|
|
20548
|
+
* arrays). It is a user-level UI setting, so it is only written in global scope
|
|
20549
|
+
* (see below).
|
|
20550
|
+
*
|
|
20551
|
+
* Both scopes are supported: the adapter syncs the project-level
|
|
20552
|
+
* `./.grok/config.toml` (default) and the user-level `~/.grok/config.toml`
|
|
20553
|
+
* (with `--global`). Grok documents that "Project configs are limited to MCP
|
|
20554
|
+
* servers, plugins, and permission rules, not full user configs"
|
|
20555
|
+
* (https://docs.x.ai/build/settings), so the project config carries only the
|
|
20556
|
+
* fine-grained `[permission]` rules; the coarse `[ui] permission_mode` UI toggle
|
|
20557
|
+
* is written in global scope only. The shared config is merged in
|
|
20235
20558
|
* place: rulesync owns the `[permission]` `allow`/`deny`/`ask` entries for the
|
|
20236
|
-
* tools it models and the `[ui] permission_mode` value, while
|
|
20559
|
+
* tools it models and (in global scope) the `[ui] permission_mode` value, while
|
|
20560
|
+
* every other key
|
|
20237
20561
|
* (e.g. `[mcp_servers]`, `[permission] rules`, `[sandbox]`) and any user-authored
|
|
20238
20562
|
* entries for tools rulesync cannot model (e.g. `WebSearch`) are preserved. The
|
|
20239
20563
|
* file is never deleted.
|
|
@@ -20255,7 +20579,6 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
20255
20579
|
};
|
|
20256
20580
|
}
|
|
20257
20581
|
static async fromFile({ outputRoot = process.cwd(), validate = true, global = false }) {
|
|
20258
|
-
if (!global) throw new Error(GROKCLI_GLOBAL_ONLY_MESSAGE);
|
|
20259
20582
|
const paths = GrokcliPermissions.getSettablePaths({ global });
|
|
20260
20583
|
const fileContent = await readFileContentOrNull((0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath)) ?? "";
|
|
20261
20584
|
return new GrokcliPermissions({
|
|
@@ -20264,11 +20587,10 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
20264
20587
|
relativeFilePath: paths.relativeFilePath,
|
|
20265
20588
|
fileContent,
|
|
20266
20589
|
validate,
|
|
20267
|
-
global
|
|
20590
|
+
global
|
|
20268
20591
|
});
|
|
20269
20592
|
}
|
|
20270
20593
|
static async fromRulesyncPermissions({ outputRoot = process.cwd(), rulesyncPermissions, logger, global = false }) {
|
|
20271
|
-
if (!global) throw new Error(GROKCLI_GLOBAL_ONLY_MESSAGE);
|
|
20272
20594
|
const paths = GrokcliPermissions.getSettablePaths({ global });
|
|
20273
20595
|
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
20274
20596
|
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
@@ -20287,11 +20609,10 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
20287
20609
|
deny: buckets.deny,
|
|
20288
20610
|
ask: buckets.ask
|
|
20289
20611
|
};
|
|
20290
|
-
const
|
|
20291
|
-
const ui = {
|
|
20612
|
+
const uiPatch = global ? { [GROKCLI_UI_KEY]: {
|
|
20292
20613
|
...isRecord(parsed[GROKCLI_UI_KEY]) ? parsed[GROKCLI_UI_KEY] : {},
|
|
20293
|
-
[GROKCLI_PERMISSION_MODE_KEY]:
|
|
20294
|
-
};
|
|
20614
|
+
[GROKCLI_PERMISSION_MODE_KEY]: deriveGrokPermissionMode(config)
|
|
20615
|
+
} } : {};
|
|
20295
20616
|
return new GrokcliPermissions({
|
|
20296
20617
|
outputRoot,
|
|
20297
20618
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -20302,12 +20623,12 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
20302
20623
|
existingContent,
|
|
20303
20624
|
patch: {
|
|
20304
20625
|
[GROKCLI_PERMISSION_KEY]: permission,
|
|
20305
|
-
|
|
20626
|
+
...uiPatch
|
|
20306
20627
|
},
|
|
20307
20628
|
filePath
|
|
20308
20629
|
}),
|
|
20309
20630
|
validate: true,
|
|
20310
|
-
global
|
|
20631
|
+
global
|
|
20311
20632
|
});
|
|
20312
20633
|
}
|
|
20313
20634
|
toRulesyncPermissions() {
|
|
@@ -20328,14 +20649,14 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
20328
20649
|
error: null
|
|
20329
20650
|
};
|
|
20330
20651
|
}
|
|
20331
|
-
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
20652
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
|
|
20332
20653
|
return new GrokcliPermissions({
|
|
20333
20654
|
outputRoot,
|
|
20334
20655
|
relativeDirPath,
|
|
20335
20656
|
relativeFilePath,
|
|
20336
20657
|
fileContent: "",
|
|
20337
20658
|
validate: false,
|
|
20338
|
-
global
|
|
20659
|
+
global
|
|
20339
20660
|
});
|
|
20340
20661
|
}
|
|
20341
20662
|
};
|
|
@@ -21250,6 +21571,22 @@ const CANONICAL_PERMISSION_CATEGORIES = /* @__PURE__ */ new Set([
|
|
|
21250
21571
|
"notebookedit",
|
|
21251
21572
|
"agent"
|
|
21252
21573
|
]);
|
|
21574
|
+
/**
|
|
21575
|
+
* Translate between rulesync's canonical permission category names and
|
|
21576
|
+
* OpenCode's native permission keys. OpenCode has no `agent` key — subagent
|
|
21577
|
+
* launches are gated by the `task` key (see the documented key list at
|
|
21578
|
+
* https://opencode.ai/docs/permissions/). Without this translation a canonical
|
|
21579
|
+
* `agent: deny` would be written verbatim into `opencode.json` and silently
|
|
21580
|
+
* ignored by OpenCode. Unknown names pass through unchanged.
|
|
21581
|
+
*/
|
|
21582
|
+
const CANONICAL_TO_OPENCODE_PERMISSION_KEYS = { agent: "task" };
|
|
21583
|
+
const OPENCODE_TO_CANONICAL_PERMISSION_KEYS = Object.fromEntries(Object.entries(CANONICAL_TO_OPENCODE_PERMISSION_KEYS).map(([canonical, opencode]) => [opencode, canonical]));
|
|
21584
|
+
function toOpencodePermissionKey(canonical) {
|
|
21585
|
+
return CANONICAL_TO_OPENCODE_PERMISSION_KEYS[canonical] ?? canonical;
|
|
21586
|
+
}
|
|
21587
|
+
function toCanonicalPermissionKey(opencodeKey) {
|
|
21588
|
+
return OPENCODE_TO_CANONICAL_PERMISSION_KEYS[opencodeKey] ?? opencodeKey;
|
|
21589
|
+
}
|
|
21253
21590
|
function isSharedPermissionCategory(category) {
|
|
21254
21591
|
return category === "*" || CANONICAL_PERMISSION_CATEGORIES.has(category) || category.startsWith("mcp__");
|
|
21255
21592
|
}
|
|
@@ -21316,6 +21653,8 @@ var OpencodePermissions = class OpencodePermissions extends ToolPermissions {
|
|
|
21316
21653
|
}
|
|
21317
21654
|
const rulesyncJson = rulesyncPermissions.getJson();
|
|
21318
21655
|
const overridePermission = rulesyncJson.opencode?.permission ?? {};
|
|
21656
|
+
const sharedPermission = {};
|
|
21657
|
+
for (const [category, value] of Object.entries(rulesyncJson.permission ?? {})) sharedPermission[toOpencodePermissionKey(category)] = value;
|
|
21319
21658
|
return new OpencodePermissions({
|
|
21320
21659
|
outputRoot,
|
|
21321
21660
|
relativeDirPath: basePaths.relativeDirPath,
|
|
@@ -21325,7 +21664,7 @@ var OpencodePermissions = class OpencodePermissions extends ToolPermissions {
|
|
|
21325
21664
|
feature: "permissions",
|
|
21326
21665
|
existingContent: fileContent ?? "",
|
|
21327
21666
|
patch: { permission: {
|
|
21328
|
-
...
|
|
21667
|
+
...sharedPermission,
|
|
21329
21668
|
...overridePermission
|
|
21330
21669
|
} },
|
|
21331
21670
|
filePath: (0, node_path.join)(jsonDir, relativeFilePath)
|
|
@@ -21341,8 +21680,11 @@ var OpencodePermissions = class OpencodePermissions extends ToolPermissions {
|
|
|
21341
21680
|
}
|
|
21342
21681
|
const shared = {};
|
|
21343
21682
|
const overrideOnly = {};
|
|
21344
|
-
for (const [category, value] of Object.entries(rawPermission))
|
|
21345
|
-
|
|
21683
|
+
for (const [category, value] of Object.entries(rawPermission)) {
|
|
21684
|
+
const canonicalCategory = toCanonicalPermissionKey(category);
|
|
21685
|
+
if (isSharedPermissionCategory(canonicalCategory)) shared[canonicalCategory] = typeof value === "string" ? { "*": value } : value;
|
|
21686
|
+
else overrideOnly[category] = value;
|
|
21687
|
+
}
|
|
21346
21688
|
const json = Object.keys(overrideOnly).length > 0 ? {
|
|
21347
21689
|
permission: shared,
|
|
21348
21690
|
opencode: { permission: overrideOnly }
|
|
@@ -21467,6 +21809,7 @@ const QWEN_OVERRIDE_TOOLS_KEYS = [
|
|
|
21467
21809
|
"disabled"
|
|
21468
21810
|
];
|
|
21469
21811
|
const QWEN_OVERRIDE_SECURITY_KEYS = ["folderTrust"];
|
|
21812
|
+
const QWEN_OVERRIDE_PERMISSIONS_KEYS = ["autoMode"];
|
|
21470
21813
|
function asPlainRecord(value) {
|
|
21471
21814
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
21472
21815
|
}
|
|
@@ -21538,8 +21881,9 @@ var QwencodePermissions = class QwencodePermissions extends ToolPermissions {
|
|
|
21538
21881
|
else delete mergedPermissions.ask;
|
|
21539
21882
|
if (mergedDeny.length > 0) mergedPermissions.deny = mergedDeny;
|
|
21540
21883
|
else delete mergedPermissions.deny;
|
|
21541
|
-
const patch = { permissions: mergedPermissions };
|
|
21542
21884
|
const override = config.qwencode;
|
|
21885
|
+
if (override?.autoMode !== void 0) mergedPermissions.autoMode = override.autoMode;
|
|
21886
|
+
const patch = { permissions: mergedPermissions };
|
|
21543
21887
|
if (override?.tools !== void 0) patch.tools = {
|
|
21544
21888
|
...asPlainRecord(settings.tools),
|
|
21545
21889
|
...asPlainRecord(override.tools)
|
|
@@ -21581,9 +21925,11 @@ var QwencodePermissions = class QwencodePermissions extends ToolPermissions {
|
|
|
21581
21925
|
});
|
|
21582
21926
|
const overrideTools = pickQwenOverrideKeys(settings.tools, QWEN_OVERRIDE_TOOLS_KEYS);
|
|
21583
21927
|
const overrideSecurity = pickQwenOverrideKeys(settings.security, QWEN_OVERRIDE_SECURITY_KEYS);
|
|
21928
|
+
const overridePermissions = pickQwenOverrideKeys(settings.permissions, QWEN_OVERRIDE_PERMISSIONS_KEYS);
|
|
21584
21929
|
const qwencodeOverride = {};
|
|
21585
21930
|
if (Object.keys(overrideTools).length > 0) qwencodeOverride.tools = overrideTools;
|
|
21586
21931
|
if (Object.keys(overrideSecurity).length > 0) qwencodeOverride.security = overrideSecurity;
|
|
21932
|
+
if (overridePermissions.autoMode !== void 0) qwencodeOverride.autoMode = overridePermissions.autoMode;
|
|
21587
21933
|
const result = { ...config };
|
|
21588
21934
|
if (Object.keys(qwencodeOverride).length > 0) result.qwencode = qwencodeOverride;
|
|
21589
21935
|
return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
|
|
@@ -23092,7 +23438,7 @@ const toolPermissionsFactories = /* @__PURE__ */ new Map([
|
|
|
23092
23438
|
["grokcli", {
|
|
23093
23439
|
class: GrokcliPermissions,
|
|
23094
23440
|
meta: {
|
|
23095
|
-
supportsProject:
|
|
23441
|
+
supportsProject: true,
|
|
23096
23442
|
supportsGlobal: true,
|
|
23097
23443
|
supportsImport: true
|
|
23098
23444
|
}
|