rulesync 16.25.0 → 16.26.1
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 +9 -9
- package/dist/cli/index.cjs +60 -19
- package/dist/cli/index.js +60 -19
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-B6p6c3L0.js → import-BNh_gCUr.js} +460 -106
- package/dist/import-BNh_gCUr.js.map +1 -0
- package/dist/{import-DwtzMiDG.cjs → import-LjMdFijG.cjs} +464 -104
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/import-B6p6c3L0.js.map +0 -1
|
@@ -4730,9 +4730,14 @@ const KIMI_CODE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CAN
|
|
|
4730
4730
|
* ZCode's configuration-file hooks expose exactly seven PascalCase events, all
|
|
4731
4731
|
* of which have a clean canonical equivalent: `SessionStart`, `PreToolUse`,
|
|
4732
4732
|
* `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `Stop`, and
|
|
4733
|
-
* `UserPromptSubmit` ← `beforeSubmitPrompt`. An optional matcher
|
|
4734
|
-
*
|
|
4735
|
-
*
|
|
4733
|
+
* `UserPromptSubmit` ← `beforeSubmitPrompt`. An optional matcher is honored on
|
|
4734
|
+
* all of them except `UserPromptSubmit` and `Stop`, which expose no value to
|
|
4735
|
+
* match against. ZCode reads the matcher in one of two ways: a value made up
|
|
4736
|
+
* solely of letters, digits, underscores and `|` is an exact name list
|
|
4737
|
+
* (`Write|Edit` matches those two tool names, not the regex alternation), and
|
|
4738
|
+
* any other character makes the whole value a case-sensitive JavaScript regex.
|
|
4739
|
+
* Rulesync passes matchers through verbatim, so an authored value keeps
|
|
4740
|
+
* whichever reading ZCode gives it — worth knowing before escaping one.
|
|
4736
4741
|
* Configuration hooks are read only from the user config
|
|
4737
4742
|
* `~/.zcode/cli/config.json` (workspace config hooks are never executed) and
|
|
4738
4743
|
* additionally require `hooks.enabled: true` to run.
|
|
@@ -6710,7 +6715,7 @@ const CursorPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
6710
6715
|
* Tool-scoped override block for Qwen Code. Qwen's `settings.json` exposes
|
|
6711
6716
|
* autonomy/sandbox controls with no canonical permission category — under
|
|
6712
6717
|
* `tools` (`approvalMode` = plan/default/auto-edit/auto/yolo, `autoAccept`,
|
|
6713
|
-
* `sandbox`, `sandboxImage`, `disabled`, `visible`, `listDirectory`,
|
|
6718
|
+
* `sandbox`, `sandboxImage`, `disabled`, `visible`, `eager`, `listDirectory`,
|
|
6714
6719
|
* `workflowsEnabled`) and `security` (`folderTrust`, `allowedHttpHookUrls`,
|
|
6715
6720
|
* `allowPrivateNetworkHooks`, `allowedInsecureVoiceBaseUrls`). Qwen Code strips
|
|
6716
6721
|
* `tools.workflowsEnabled`, `security.allowPrivateNetworkHooks` and
|
|
@@ -6724,7 +6729,9 @@ const CursorPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
6724
6729
|
* changes what the file said is reported in either scope, naming what that key
|
|
6725
6730
|
* decides there — the autonomy and containment
|
|
6726
6731
|
* controls (`approvalMode`, `autoAccept`, `sandbox`, `sandboxImage`), the
|
|
6727
|
-
* registry controls (`disabled`, `visible`, `listDirectory
|
|
6732
|
+
* registry controls (`disabled`, `visible`, `listDirectory`, and `eager`, which
|
|
6733
|
+
* demotes an omitted tool to deferred rather than removing it, replacing rather
|
|
6734
|
+
* than merging with the list a higher scope set), the Auto Mode
|
|
6728
6735
|
* classifier config, and, because these groups are loose objects, any key
|
|
6729
6736
|
* rulesync does not model. Import flags a scope-dependent key only when it read
|
|
6730
6737
|
* the project file, since that is the value a `--global` regenerate would
|
|
@@ -6904,12 +6911,37 @@ const DeepagentsStartupOverrideSchema = zod_mini.z.looseObject({
|
|
|
6904
6911
|
read_project_dotenv: zod_mini.z.optional(zod_mini.z.boolean())
|
|
6905
6912
|
});
|
|
6906
6913
|
/**
|
|
6914
|
+
* deepagents-cli's Python extension gate under `[extensions]` in
|
|
6915
|
+
* `~/.deepagents/config.toml`. `discover_extensions` auto-loads `*.py` from the
|
|
6916
|
+
* user's `~/.deepagents/extensions/` and from the checked-out project's
|
|
6917
|
+
* `<root>/.deepagents/extensions/`, so these two keys decide whether
|
|
6918
|
+
* repository-authored Python is imported into the agent process at all —
|
|
6919
|
+
* the same class of knob as `[startup].mode`, and one that ships defaulting to
|
|
6920
|
+
* a prompt a user can accept. Loose so a key added upstream passes through
|
|
6921
|
+
* verbatim.
|
|
6922
|
+
*
|
|
6923
|
+
* `extensions.extra_paths` is deliberately absent: it names machine-local files
|
|
6924
|
+
* and directories, which do not belong in a committed
|
|
6925
|
+
* `.rulesync/permissions.jsonc`, and it only ever widens what loads.
|
|
6926
|
+
*
|
|
6927
|
+
* @see https://docs.langchain.com/oss/deepagents/code/configuration
|
|
6928
|
+
*/
|
|
6929
|
+
const DeepagentsExtensionsOverrideSchema = zod_mini.z.looseObject({
|
|
6930
|
+
enabled: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
6931
|
+
trust: zod_mini.z.optional(zod_mini.z.enum([
|
|
6932
|
+
"ask",
|
|
6933
|
+
"always",
|
|
6934
|
+
"never"
|
|
6935
|
+
]))
|
|
6936
|
+
});
|
|
6937
|
+
/**
|
|
6907
6938
|
* The `[shell].allow_list` array itself is rulesync-owned, driven by the
|
|
6908
6939
|
* shared `permission.bash` block, so it has no key here.
|
|
6909
6940
|
*/
|
|
6910
6941
|
const DeepagentsPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
6911
6942
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
6912
|
-
startup: zod_mini.z.optional(DeepagentsStartupOverrideSchema)
|
|
6943
|
+
startup: zod_mini.z.optional(DeepagentsStartupOverrideSchema),
|
|
6944
|
+
extensions: zod_mini.z.optional(DeepagentsExtensionsOverrideSchema)
|
|
6913
6945
|
});
|
|
6914
6946
|
/**
|
|
6915
6947
|
* The actions Junie's allowlist accepts. Verified against the shipped Junie
|
|
@@ -7920,8 +7952,9 @@ const RulesyncRuleFrontmatterSchema = zod_mini.z.object({
|
|
|
7920
7952
|
agentsmd: zod_mini.z.optional(zod_mini.z.looseObject({ subprojectPath: zod_mini.z.optional(zod_mini.z.string()) })),
|
|
7921
7953
|
claudecode: zod_mini.z.optional(zod_mini.z.looseObject({ paths: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())) })),
|
|
7922
7954
|
codebuddy: zod_mini.z.optional(zod_mini.z.looseObject({
|
|
7923
|
-
paths: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())),
|
|
7955
|
+
paths: zod_mini.z.optional(zod_mini.z.union([zod_mini.z.string(), zod_mini.z.array(zod_mini.z.string())])),
|
|
7924
7956
|
alwaysApply: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
7957
|
+
enabled: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
7925
7958
|
description: zod_mini.z.optional(zod_mini.z.string())
|
|
7926
7959
|
})),
|
|
7927
7960
|
cursor: zod_mini.z.optional(zod_mini.z.looseObject({
|
|
@@ -9214,6 +9247,11 @@ const RulesyncSkillFrontmatterSchema = zod_mini.z.looseObject({
|
|
|
9214
9247
|
license: zod_mini.z.optional(zod_mini.z.string()),
|
|
9215
9248
|
compatibility: zod_mini.z.optional(zod_mini.z.union([zod_mini.z.string(), zod_mini.z.looseObject({})])),
|
|
9216
9249
|
metadata: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
9250
|
+
})),
|
|
9251
|
+
zcode: zod_mini.z.optional(zod_mini.z.looseObject({
|
|
9252
|
+
when_to_use: zod_mini.z.optional(zod_mini.z.string()),
|
|
9253
|
+
license: zod_mini.z.optional(zod_mini.z.string()),
|
|
9254
|
+
metadata: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
9217
9255
|
}))
|
|
9218
9256
|
});
|
|
9219
9257
|
/**
|
|
@@ -17796,6 +17834,20 @@ const ROO_MCP_FILE_NAME = "mcp.json";
|
|
|
17796
17834
|
*/
|
|
17797
17835
|
const ROO_MODE_SLUG_PATTERN = /^[a-zA-Z0-9-]+$/;
|
|
17798
17836
|
/**
|
|
17837
|
+
* `~/.roo/rules/AGENTS.md` — where the root rule goes in global scope.
|
|
17838
|
+
*
|
|
17839
|
+
* Roo/Zoo Code discover the agent-rules files (`AGENTS.md`, `AGENT.md`,
|
|
17840
|
+
* `AGENTS.local.md`) in the **workspace only**: `loadAllAgentRulesFiles` reads
|
|
17841
|
+
* `cwd`, plus subdirectories holding a `.roo` folder when `enableSubfolderRules`
|
|
17842
|
+
* is on. There is no home-directory branch, so a `~/AGENTS.md` is never read.
|
|
17843
|
+
* The global rules directory `~/.roo/rules/` *is* loaded, so the root rule is
|
|
17844
|
+
* written there alongside the non-root files rather than to an unread path.
|
|
17845
|
+
* The basename is kept so the file still reads as the root overview.
|
|
17846
|
+
* @see https://github.com/Zoo-Code-Org/Zoo-Code/blob/main/src/core/prompts/sections/custom-instructions.ts
|
|
17847
|
+
* @see https://github.com/Zoo-Code-Org/Zoo-Code/blob/main/src/services/roo-config/index.ts
|
|
17848
|
+
*/
|
|
17849
|
+
const ROO_GLOBAL_ROOT_RULE_FILE_NAME = "AGENTS.md";
|
|
17850
|
+
/**
|
|
17799
17851
|
* `.roo/rules-{mode}/` — the mode-specific rule directory Roo/Zoo Code load
|
|
17800
17852
|
* INSTEAD of `.roo/rules/` while that mode is active. The relative path is the
|
|
17801
17853
|
* same in global scope, where it resolves under `~/.roo/`.
|
|
@@ -22855,7 +22907,7 @@ var DevinHooks = class DevinHooks extends ToolHooks {
|
|
|
22855
22907
|
* adapter so the settings reader in `src/utils/` can name the same list without
|
|
22856
22908
|
* importing a feature.
|
|
22857
22909
|
*
|
|
22858
|
-
* @see https://docs.factory.ai/cli/
|
|
22910
|
+
* @see https://docs.factory.ai/droid-cli/settings
|
|
22859
22911
|
*/
|
|
22860
22912
|
const FACTORYDROID_OVERRIDE_KEYS = [
|
|
22861
22913
|
"commandBlocklist",
|
|
@@ -22863,6 +22915,8 @@ const FACTORYDROID_OVERRIDE_KEYS = [
|
|
|
22863
22915
|
"sandbox",
|
|
22864
22916
|
"mcpPolicy",
|
|
22865
22917
|
"mcpAutonomyOverrides",
|
|
22918
|
+
"mcpAutonomyUrlOverrides",
|
|
22919
|
+
"builtInToolAutonomyOverrides",
|
|
22866
22920
|
"enableDroidShield",
|
|
22867
22921
|
"sessionDefaultSettings",
|
|
22868
22922
|
"maxAutonomyLevel",
|
|
@@ -22870,7 +22924,10 @@ const FACTORYDROID_OVERRIDE_KEYS = [
|
|
|
22870
22924
|
"interactionMode",
|
|
22871
22925
|
"extraKnownMarketplaces",
|
|
22872
22926
|
"enabledPlugins",
|
|
22927
|
+
"strictEnabledPlugins",
|
|
22928
|
+
"strictKnownMarketplaces",
|
|
22873
22929
|
"hooksDisabled",
|
|
22930
|
+
"allowManagedHooksOnly",
|
|
22874
22931
|
"disabledSkills",
|
|
22875
22932
|
"modelPolicy",
|
|
22876
22933
|
"missionPolicy"
|
|
@@ -26911,6 +26968,7 @@ var ClineIgnore = class ClineIgnore extends ToolIgnore {
|
|
|
26911
26968
|
//#region src/constants/crush-paths.ts
|
|
26912
26969
|
const CRUSH_RULE_FILE_NAME = "CRUSH.md";
|
|
26913
26970
|
const CRUSH_GLOBAL_DIR = (0, node_path.join)(".config", "crush");
|
|
26971
|
+
const CRUSH_LOCAL_RULE_FILE_NAME = "CRUSH.local.md";
|
|
26914
26972
|
const CRUSH_IGNORE_FILE_NAME = ".crushignore";
|
|
26915
26973
|
const CRUSH_SKILLS_PROJECT_DIR = (0, node_path.join)(".crush", "skills");
|
|
26916
26974
|
const CRUSH_SKILLS_GLOBAL_DIR = (0, node_path.join)(CRUSH_GLOBAL_DIR, "skills");
|
|
@@ -32824,7 +32882,9 @@ const REASONIX_PLUGIN_FIELDS = [
|
|
|
32824
32882
|
"headers",
|
|
32825
32883
|
"startup_timeout_seconds",
|
|
32826
32884
|
"call_timeout_seconds",
|
|
32827
|
-
"tool_timeout_seconds"
|
|
32885
|
+
"tool_timeout_seconds",
|
|
32886
|
+
"concurrency",
|
|
32887
|
+
"auto_start"
|
|
32828
32888
|
];
|
|
32829
32889
|
var ReasonixMcp = class ReasonixMcp extends ToolMcp {
|
|
32830
32890
|
toml;
|
|
@@ -33131,9 +33191,16 @@ function lookupTransport(map, key) {
|
|
|
33131
33191
|
}
|
|
33132
33192
|
/**
|
|
33133
33193
|
* Read the "put this server's own instructions into the agent's prompt" flag
|
|
33134
|
-
* off an unfiltered canonical entry, under either spelling.
|
|
33135
|
-
*
|
|
33136
|
-
*
|
|
33194
|
+
* off an unfiltered canonical entry, under either spelling. `undefined` means
|
|
33195
|
+
* the entry says nothing, which is Rovo Dev's own default.
|
|
33196
|
+
*
|
|
33197
|
+
* The flag is a **tri-state**, not a switch that only exists when on. Atlassian
|
|
33198
|
+
* inverted the default on 2026-09-02: a server's instructions are now surfaced
|
|
33199
|
+
* when the key is absent or `true`, and `false` is what suppresses them — the
|
|
33200
|
+
* opposite of the opt-in wording this adapter was first written against, where
|
|
33201
|
+
* absent and `false` meant the same thing. So `false` has to travel end to end;
|
|
33202
|
+
* collapsing it away is what makes a suppression impossible to author, and
|
|
33203
|
+
* erases one on import.
|
|
33137
33204
|
*
|
|
33138
33205
|
* The canonical key decides whenever it is present, the way codex resolves the
|
|
33139
33206
|
* same two-spelling conflict for `experimental_environment`. OR-ing the two
|
|
@@ -33141,28 +33208,25 @@ function lookupTransport(map, key) {
|
|
|
33141
33208
|
* `enable_instructions: true` copied out of Atlassian's docs — fail-open, on
|
|
33142
33209
|
* the one key whose whole purpose is a trust decision.
|
|
33143
33210
|
*
|
|
33211
|
+
* A non-boolean under either spelling reads as `undefined` rather than as a
|
|
33212
|
+
* suppression: Rovo Dev surfaces the instructions for anything that is not
|
|
33213
|
+
* `false`, so writing `false` there would invent a restriction the tool is not
|
|
33214
|
+
* applying. (The canonical key is a strict boolean in the schema, so only the
|
|
33215
|
+
* raw spelling can carry one.)
|
|
33216
|
+
*
|
|
33144
33217
|
* `isPlainObject` rather than `isRecord`: this walks a user-supplied key set,
|
|
33145
33218
|
* so a `constructor` entry must not resolve up the prototype chain.
|
|
33146
33219
|
*/
|
|
33147
33220
|
function readEnableInstructions(rawServer) {
|
|
33148
|
-
if (!isPlainObject$1(rawServer)) return
|
|
33149
|
-
|
|
33150
|
-
return
|
|
33151
|
-
|
|
33152
|
-
|
|
33153
|
-
* Names that were emitted with `enable_instructions: true` during one
|
|
33154
|
-
* `fromRulesyncMcp` call, so the run can say so once rather than per server.
|
|
33155
|
-
* Atlassian gates this key on trust, and it is the only thing generate writes
|
|
33156
|
-
* that widens what steers the model — the quietest possible write is the wrong
|
|
33157
|
-
* one for it.
|
|
33158
|
-
*/
|
|
33159
|
-
function warnEnabledInstructions(names, logger) {
|
|
33160
|
-
if (names.length === 0) return;
|
|
33161
|
-
logger?.warn(`Rovo Dev MCP: writing enable_instructions: true for ${names.join(", ")}. Rovo Dev pastes ${names.length === 1 ? "that server's" : "those servers'"} own instructions into the agent's system prompt, so enable it only for servers you trust.`);
|
|
33221
|
+
if (!isPlainObject$1(rawServer)) return;
|
|
33222
|
+
const canonical = rawServer.rovodevEnableInstructions;
|
|
33223
|
+
if (canonical !== void 0) return typeof canonical === "boolean" ? canonical : void 0;
|
|
33224
|
+
const raw = rawServer.enable_instructions;
|
|
33225
|
+
return typeof raw === "boolean" ? raw : void 0;
|
|
33162
33226
|
}
|
|
33163
33227
|
function toRovodevServer(name, server, logger) {
|
|
33164
33228
|
const { type, transport, disabled: _disabled, rovodevEnableInstructions, ...rest } = server;
|
|
33165
|
-
if (rovodevEnableInstructions ===
|
|
33229
|
+
if (typeof rovodevEnableInstructions === "boolean") rest.enable_instructions = rovodevEnableInstructions;
|
|
33166
33230
|
const declared = typeof transport === "string" ? transport : typeof type === "string" ? type : void 0;
|
|
33167
33231
|
if (declared === void 0) return rest;
|
|
33168
33232
|
const mapped = lookupTransport(CANONICAL_TO_ROVODEV_TRANSPORT, declared);
|
|
@@ -33177,7 +33241,7 @@ function toRovodevServer(name, server, logger) {
|
|
|
33177
33241
|
}
|
|
33178
33242
|
function fromRovodevServer(server) {
|
|
33179
33243
|
const { transport, enable_instructions: enableInstructions, ...rest } = server;
|
|
33180
|
-
if (enableInstructions ===
|
|
33244
|
+
if (typeof enableInstructions === "boolean") rest.rovodevEnableInstructions = enableInstructions;
|
|
33181
33245
|
if (typeof transport !== "string") return rest;
|
|
33182
33246
|
const mapped = lookupTransport(ROVODEV_TO_CANONICAL_TRANSPORT, transport);
|
|
33183
33247
|
return mapped === void 0 ? rest : {
|
|
@@ -33618,10 +33682,10 @@ var RovodevMcp = class RovodevMcp extends ToolMcp {
|
|
|
33618
33682
|
canWriteDisableToggle = false;
|
|
33619
33683
|
}
|
|
33620
33684
|
const mcpServers = Object.fromEntries(Object.entries(rulesyncMcp.getMcpServers()).map(([name, server]) => {
|
|
33621
|
-
const
|
|
33685
|
+
const enableInstructions = readEnableInstructions(rulesyncMcp.getRawMcpServer(name));
|
|
33622
33686
|
const record = {
|
|
33623
33687
|
...server,
|
|
33624
|
-
...
|
|
33688
|
+
...enableInstructions !== void 0 && { rovodevEnableInstructions: enableInstructions }
|
|
33625
33689
|
};
|
|
33626
33690
|
if (record.disabled === true && !canWriteDisableToggle) {
|
|
33627
33691
|
logger?.warn(`Rovo Dev MCP: skipping disabled server "${name}" because config.yml cannot be parsed, so mcp.disabledMcpServers cannot be written to switch it off.`);
|
|
@@ -33630,7 +33694,6 @@ var RovodevMcp = class RovodevMcp extends ToolMcp {
|
|
|
33630
33694
|
const converted = toRovodevServer(name, record, logger);
|
|
33631
33695
|
return converted === null ? null : [name, converted];
|
|
33632
33696
|
}).filter((entry) => entry !== null));
|
|
33633
|
-
warnEnabledInstructions(Object.entries(mcpServers).filter(([, server]) => server.enable_instructions === true).map(([name]) => name), logger);
|
|
33634
33697
|
const rovodevConfig = {
|
|
33635
33698
|
...json,
|
|
33636
33699
|
mcpServers
|
|
@@ -39774,6 +39837,34 @@ const DEEPAGENTS_STARTUP_BOOLEAN_DEFAULTS = {
|
|
|
39774
39837
|
yolo_switcher: true,
|
|
39775
39838
|
read_project_dotenv: true
|
|
39776
39839
|
};
|
|
39840
|
+
/**
|
|
39841
|
+
* `[extensions]` gates dcode's Python extension system. `discover_extensions`
|
|
39842
|
+
* auto-loads `*.py` from the user's `~/.deepagents/extensions/` and from the
|
|
39843
|
+
* checked-out project's `<root>/.deepagents/extensions/`, so this table decides
|
|
39844
|
+
* whether a cloned repository's Python is imported into the agent process.
|
|
39845
|
+
*/
|
|
39846
|
+
const EXTENSIONS_TABLE_KEY = "extensions";
|
|
39847
|
+
/**
|
|
39848
|
+
* Keys lifted back into the override on import. `extensions.extra_paths` is
|
|
39849
|
+
* deliberately absent: it names machine-local files and directories, which do
|
|
39850
|
+
* not belong in a committed `.rulesync/permissions.jsonc`, and it only ever
|
|
39851
|
+
* widens what loads.
|
|
39852
|
+
*/
|
|
39853
|
+
const DEEPAGENTS_EXTENSIONS_KEYS = ["enabled", "trust"];
|
|
39854
|
+
/** `TrustPolicy` in `extensions/settings.py`; dcode reads nothing else. */
|
|
39855
|
+
const DEEPAGENTS_EXTENSION_TRUST_POLICIES = [
|
|
39856
|
+
"ask",
|
|
39857
|
+
"always",
|
|
39858
|
+
"never"
|
|
39859
|
+
];
|
|
39860
|
+
/**
|
|
39861
|
+
* `[extensions].enabled` defaults to `true` upstream, so writing `true` on a
|
|
39862
|
+
* machine that has not set it changes nothing — the same reasoning as
|
|
39863
|
+
* `DEEPAGENTS_STARTUP_BOOLEAN_DEFAULTS`.
|
|
39864
|
+
*
|
|
39865
|
+
* @see https://github.com/langchain-ai/deepagents `config_manifest.py`
|
|
39866
|
+
*/
|
|
39867
|
+
const DEEPAGENTS_EXTENSIONS_ENABLED_DEFAULT = true;
|
|
39777
39868
|
const ALLOW_ALL_SENTINEL = "all";
|
|
39778
39869
|
const RECOMMENDED_SENTINEL = "recommended";
|
|
39779
39870
|
const GLOB_CHARACTERS_PATTERN = /[*?[\]]/;
|
|
@@ -39843,7 +39934,10 @@ const TRAILING_ARGUMENT_WILDCARD_PATTERN = /:\*$/;
|
|
|
39843
39934
|
* `DeepagentsPermissionsOverrideSchema`): `[startup].mode`
|
|
39844
39935
|
* (`manual` / `auto` / `yolo`), `[startup].yolo_switcher` and
|
|
39845
39936
|
* `[startup].read_project_dotenv` are merged into the file on generate and
|
|
39846
|
-
* lifted back into the override on import.
|
|
39937
|
+
* lifted back into the override on import. The same override carries
|
|
39938
|
+
* `[extensions].enabled` and `[extensions].trust` (`ask` / `always` / `never`),
|
|
39939
|
+
* which decide whether the Python in a checked-out project's
|
|
39940
|
+
* `.deepagents/extensions/` is imported into the agent process.
|
|
39847
39941
|
*
|
|
39848
39942
|
* On **import** the allowlist comes back as `bash` `allow` rules named by the
|
|
39849
39943
|
* executable — skipping any entry dcode could not match in the first place, so
|
|
@@ -39945,6 +40039,13 @@ var DeepagentsPermissions = class DeepagentsPermissions extends ToolPermissions
|
|
|
39945
40039
|
filePath,
|
|
39946
40040
|
logger
|
|
39947
40041
|
});
|
|
40042
|
+
const extensionsOverride = config.deepagents?.extensions;
|
|
40043
|
+
if (isPlainObject$1(extensionsOverride) && Object.keys(extensionsOverride).length > 0) mergeExtensionsOverride({
|
|
40044
|
+
settings,
|
|
40045
|
+
extensionsOverride,
|
|
40046
|
+
filePath,
|
|
40047
|
+
logger
|
|
40048
|
+
});
|
|
39948
40049
|
return new DeepagentsPermissions({
|
|
39949
40050
|
outputRoot,
|
|
39950
40051
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -39969,8 +40070,15 @@ var DeepagentsPermissions = class DeepagentsPermissions extends ToolPermissions
|
|
|
39969
40070
|
startup: isPlainObject$1(settings[STARTUP_TABLE_KEY]) ? settings[STARTUP_TABLE_KEY] : {},
|
|
39970
40071
|
selfPath
|
|
39971
40072
|
});
|
|
40073
|
+
const extensionsOverride = liftExtensionsOverride({
|
|
40074
|
+
extensions: isPlainObject$1(settings[EXTENSIONS_TABLE_KEY]) ? settings[EXTENSIONS_TABLE_KEY] : {},
|
|
40075
|
+
selfPath
|
|
40076
|
+
});
|
|
39972
40077
|
const result = { ...config };
|
|
39973
|
-
|
|
40078
|
+
const deepagents = {};
|
|
40079
|
+
if (Object.keys(startupOverride).length > 0) deepagents.startup = startupOverride;
|
|
40080
|
+
if (Object.keys(extensionsOverride).length > 0) deepagents.extensions = extensionsOverride;
|
|
40081
|
+
if (Object.keys(deepagents).length > 0) result.deepagents = deepagents;
|
|
39974
40082
|
return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
|
|
39975
40083
|
}
|
|
39976
40084
|
validate() {
|
|
@@ -40057,57 +40165,192 @@ function warnAboutUnwrittenBashRules({ allowAll, requestedAllowAll, askPatterns,
|
|
|
40057
40165
|
if (willWrite && allowAll) warnWithFallback(logger, "The bash '*' allow rule became allow_list = [\"all\"] for deepagents-cli, which auto-approves every command and skips its dangerous-pattern check (command substitution, redirects, process substitution). List the executables you want instead if that is more than you meant.");
|
|
40058
40166
|
}
|
|
40059
40167
|
/**
|
|
40060
|
-
* Lift the
|
|
40061
|
-
* override, keeping only values dcode itself accepts.
|
|
40168
|
+
* Lift the keys rulesync models from one `config.toml` table back into the
|
|
40169
|
+
* `deepagents` override, keeping only values dcode itself accepts.
|
|
40170
|
+
*
|
|
40171
|
+
* A value outside what the option's own parser reads is `Invalid` upstream —
|
|
40172
|
+
* dcode ignores it and falls back to its default. Importing it anyway would
|
|
40173
|
+
* record a setting the tool is not applying and, because the canonical schema
|
|
40174
|
+
* is stricter than TOML, would write a `.rulesync/permissions.jsonc` the next
|
|
40175
|
+
* `rulesync generate` cannot even read.
|
|
40062
40176
|
*
|
|
40063
|
-
*
|
|
40064
|
-
*
|
|
40065
|
-
*
|
|
40066
|
-
* and, because the canonical schema is stricter than TOML, would write a
|
|
40067
|
-
* `.rulesync/permissions.jsonc` the next `rulesync generate` cannot even read.
|
|
40177
|
+
* `normalize` returns the value to keep, or `null` for one dcode would not
|
|
40178
|
+
* read — a wrapper rather than the bare value, so a legitimately falsy setting
|
|
40179
|
+
* is not mistaken for a rejection.
|
|
40068
40180
|
*/
|
|
40069
|
-
function
|
|
40070
|
-
const
|
|
40181
|
+
function liftOverrideTable({ table, tableKey, keys, normalize, selfPath }) {
|
|
40182
|
+
const override = {};
|
|
40071
40183
|
const rejected = [];
|
|
40072
|
-
for (const key of
|
|
40073
|
-
const value =
|
|
40184
|
+
for (const key of keys) {
|
|
40185
|
+
const value = table[key];
|
|
40074
40186
|
if (value === void 0) continue;
|
|
40075
|
-
|
|
40187
|
+
const normalized = normalize({
|
|
40188
|
+
key,
|
|
40189
|
+
value
|
|
40190
|
+
});
|
|
40191
|
+
if (normalized) override[key] = normalized.value;
|
|
40076
40192
|
else rejected.push(`${key} = ${JSON.stringify(value)}`);
|
|
40077
40193
|
}
|
|
40078
|
-
if (rejected.length > 0) warnWithFallback(void 0, `deepagents-cli falls back to its own default for a '[${
|
|
40079
|
-
return
|
|
40194
|
+
if (rejected.length > 0) warnWithFallback(void 0, `deepagents-cli falls back to its own default for a '[${tableKey}]' value it cannot read, so ${rejected.join(", ")} in ${selfPath} ${rejected.length === 1 ? "was" : "were"} not imported.`);
|
|
40195
|
+
return override;
|
|
40080
40196
|
}
|
|
40081
40197
|
/**
|
|
40082
|
-
*
|
|
40083
|
-
*
|
|
40084
|
-
*
|
|
40085
|
-
* user has it rather than replaced.
|
|
40198
|
+
* Lift the `[startup]` keys rulesync models back into the `deepagents`
|
|
40199
|
+
* override. A `mode` outside the three approval modes, or a non-boolean where
|
|
40200
|
+
* a switch belongs, is one dcode ignores.
|
|
40086
40201
|
*/
|
|
40087
|
-
function
|
|
40088
|
-
|
|
40089
|
-
|
|
40090
|
-
|
|
40202
|
+
function liftStartupOverride({ startup, selfPath }) {
|
|
40203
|
+
return liftOverrideTable({
|
|
40204
|
+
table: startup,
|
|
40205
|
+
tableKey: STARTUP_TABLE_KEY,
|
|
40206
|
+
keys: DEEPAGENTS_STARTUP_KEYS,
|
|
40207
|
+
normalize: ({ key, value }) => {
|
|
40208
|
+
if (key === "mode") return DEEPAGENTS_STARTUP_MODES.includes(value) ? { value } : null;
|
|
40209
|
+
return typeof value === "boolean" ? { value } : null;
|
|
40210
|
+
},
|
|
40211
|
+
selfPath
|
|
40212
|
+
});
|
|
40213
|
+
}
|
|
40214
|
+
/**
|
|
40215
|
+
* Lift the `[extensions]` keys rulesync models back into the `deepagents`
|
|
40216
|
+
* override.
|
|
40217
|
+
*
|
|
40218
|
+
* `trust` is read the way `parse_trust_policy` reads it — trimmed and
|
|
40219
|
+
* lowercased — so `"Always"` comes back as the policy dcode is actually
|
|
40220
|
+
* applying rather than being dropped, the same courtesy the allowlist
|
|
40221
|
+
* sentinels already get. The canonical enum holds only the lowercase
|
|
40222
|
+
* spellings, so keeping the value verbatim would write a permissions file the
|
|
40223
|
+
* next generate could not parse.
|
|
40224
|
+
*/
|
|
40225
|
+
function liftExtensionsOverride({ extensions, selfPath }) {
|
|
40226
|
+
return liftOverrideTable({
|
|
40227
|
+
table: extensions,
|
|
40228
|
+
tableKey: EXTENSIONS_TABLE_KEY,
|
|
40229
|
+
keys: DEEPAGENTS_EXTENSIONS_KEYS,
|
|
40230
|
+
normalize: ({ key, value }) => {
|
|
40231
|
+
if (key === "trust") {
|
|
40232
|
+
if (typeof value !== "string") return null;
|
|
40233
|
+
const policy = value.trim().toLowerCase();
|
|
40234
|
+
return DEEPAGENTS_EXTENSION_TRUST_POLICIES.includes(policy) ? { value: policy } : null;
|
|
40235
|
+
}
|
|
40236
|
+
return typeof value === "boolean" ? { value } : null;
|
|
40237
|
+
},
|
|
40238
|
+
selfPath
|
|
40239
|
+
});
|
|
40240
|
+
}
|
|
40241
|
+
/**
|
|
40242
|
+
* Merge one block of the `deepagents` override into its `config.toml` table,
|
|
40243
|
+
* preserving every other key of that table. A table that is not a table at all
|
|
40244
|
+
* is something rulesync did not write and cannot merge into, so it is left
|
|
40245
|
+
* exactly as the user has it rather than replaced.
|
|
40246
|
+
*/
|
|
40247
|
+
function mergeOverrideTable({ settings, tableKey, override, knownKeys, isDroppedKey, warnAboutRelaxations, filePath, logger }) {
|
|
40248
|
+
const existing = settings[tableKey];
|
|
40249
|
+
if (existing !== void 0 && !isPlainObject$1(existing)) {
|
|
40250
|
+
warnWithFallback(logger, `deepagents-cli: '${tableKey}' in ${filePath} is not a table, so the deepagents ${tableKey} override was skipped rather than overwriting it.`);
|
|
40091
40251
|
return;
|
|
40092
40252
|
}
|
|
40093
|
-
const
|
|
40094
|
-
const
|
|
40253
|
+
const table = isPlainObject$1(existing) ? { ...existing } : {};
|
|
40254
|
+
const previous = { ...table };
|
|
40095
40255
|
const writtenKeys = [];
|
|
40096
|
-
for (const [key, value] of Object.entries(
|
|
40256
|
+
for (const [key, value] of Object.entries(override)) {
|
|
40097
40257
|
if (isPrototypePollutionKey(key)) continue;
|
|
40098
|
-
if (key
|
|
40258
|
+
if (isDroppedKey?.(key)) continue;
|
|
40099
40259
|
if (value === null || value === void 0) continue;
|
|
40100
|
-
|
|
40260
|
+
table[key] = value;
|
|
40101
40261
|
writtenKeys.push(key);
|
|
40102
40262
|
}
|
|
40103
|
-
|
|
40104
|
-
|
|
40105
|
-
|
|
40263
|
+
warnAboutRelaxations({
|
|
40264
|
+
override,
|
|
40265
|
+
previous,
|
|
40266
|
+
filePath,
|
|
40267
|
+
logger
|
|
40268
|
+
});
|
|
40269
|
+
warnAboutUncheckedKeys({
|
|
40270
|
+
tableKey,
|
|
40271
|
+
knownKeys,
|
|
40106
40272
|
writtenKeys,
|
|
40107
40273
|
filePath,
|
|
40108
40274
|
logger
|
|
40109
40275
|
});
|
|
40110
|
-
if (Object.keys(
|
|
40276
|
+
if (Object.keys(table).length > 0) settings[tableKey] = table;
|
|
40277
|
+
}
|
|
40278
|
+
/**
|
|
40279
|
+
* Name the keys the merge wrote that rulesync does not model. The override is a
|
|
40280
|
+
* loose object so a key added upstream still reaches the config, but this one
|
|
40281
|
+
* writes into the machine's global file: what rulesync cannot judge, it at
|
|
40282
|
+
* least names.
|
|
40283
|
+
*/
|
|
40284
|
+
function warnAboutUncheckedKeys({ tableKey, knownKeys, writtenKeys, filePath, logger }) {
|
|
40285
|
+
const known = new Set(knownKeys);
|
|
40286
|
+
const unknownKeys = writtenKeys.filter((key) => !known.has(key));
|
|
40287
|
+
if (unknownKeys.length === 0) return;
|
|
40288
|
+
warnWithFallback(logger, `The deepagents ${tableKey} override wrote ${unknownKeys.join(", ")} into ${filePath} unchecked — rulesync does not know what those keys grant, and that file is your global deepagents-cli config.`);
|
|
40289
|
+
}
|
|
40290
|
+
/**
|
|
40291
|
+
* Merge the `deepagents.startup` override into `[startup]`.
|
|
40292
|
+
*/
|
|
40293
|
+
function mergeStartupOverride({ settings, startupOverride, filePath, logger }) {
|
|
40294
|
+
mergeOverrideTable({
|
|
40295
|
+
settings,
|
|
40296
|
+
tableKey: STARTUP_TABLE_KEY,
|
|
40297
|
+
override: startupOverride,
|
|
40298
|
+
knownKeys: DEEPAGENTS_STARTUP_KEYS,
|
|
40299
|
+
isDroppedKey: (key) => key === STARTUP_RECENT_KEY,
|
|
40300
|
+
warnAboutRelaxations: warnAboutStartupRelaxations,
|
|
40301
|
+
filePath,
|
|
40302
|
+
logger
|
|
40303
|
+
});
|
|
40304
|
+
}
|
|
40305
|
+
/**
|
|
40306
|
+
* Merge the `deepagents.extensions` override into `[extensions]`. Nothing is
|
|
40307
|
+
* dropped here — `extra_paths` is not modeled, but it is a key the user may
|
|
40308
|
+
* legitimately want carried, so it passes through as any other unknown key
|
|
40309
|
+
* does, named by the unchecked-key warning.
|
|
40310
|
+
*/
|
|
40311
|
+
function mergeExtensionsOverride({ settings, extensionsOverride, filePath, logger }) {
|
|
40312
|
+
mergeOverrideTable({
|
|
40313
|
+
settings,
|
|
40314
|
+
tableKey: EXTENSIONS_TABLE_KEY,
|
|
40315
|
+
override: extensionsOverride,
|
|
40316
|
+
knownKeys: DEEPAGENTS_EXTENSIONS_KEYS,
|
|
40317
|
+
warnAboutRelaxations: warnAboutExtensionsRelaxations,
|
|
40318
|
+
filePath,
|
|
40319
|
+
logger
|
|
40320
|
+
});
|
|
40321
|
+
}
|
|
40322
|
+
/**
|
|
40323
|
+
* Name the value an override key replaces, so a setting the user had turned
|
|
40324
|
+
* down is visible as such rather than reported as a bare new value.
|
|
40325
|
+
*/
|
|
40326
|
+
function describeOverriddenValue({ key, value, previous }) {
|
|
40327
|
+
const previousValue = previous[key];
|
|
40328
|
+
return previousValue === void 0 || previousValue === value ? `${key} = ${JSON.stringify(value)}` : `${key} = ${JSON.stringify(value)} (was ${JSON.stringify(previousValue)})`;
|
|
40329
|
+
}
|
|
40330
|
+
/**
|
|
40331
|
+
* Warn when the `deepagents` extensions override widens what dcode loads on its
|
|
40332
|
+
* own, for the same reason the startup one does: this block is written into the
|
|
40333
|
+
* user's **global** config from a `.rulesync/permissions.jsonc` a repository
|
|
40334
|
+
* can carry.
|
|
40335
|
+
*
|
|
40336
|
+
* `trust` decides what happens to the Python in a checked-out project's
|
|
40337
|
+
* `.deepagents/extensions/` — `always` imports it into the agent process with
|
|
40338
|
+
* no prompt at all — and `enabled` is the switch above it. `never` and `false`
|
|
40339
|
+
* restrict, so neither is reported.
|
|
40340
|
+
*/
|
|
40341
|
+
function warnAboutExtensionsRelaxations({ override, previous, filePath, logger }) {
|
|
40342
|
+
const relaxations = [];
|
|
40343
|
+
if (override.trust === "always") relaxations.push(describeOverriddenValue({
|
|
40344
|
+
key: "trust",
|
|
40345
|
+
value: "always",
|
|
40346
|
+
previous
|
|
40347
|
+
}));
|
|
40348
|
+
if (override.enabled === true && (previous.enabled ?? DEEPAGENTS_EXTENSIONS_ENABLED_DEFAULT) !== true) relaxations.push(describeOverriddenValue({
|
|
40349
|
+
key: "enabled",
|
|
40350
|
+
value: true,
|
|
40351
|
+
previous
|
|
40352
|
+
}));
|
|
40353
|
+
if (relaxations.length > 0) warnWithFallback(logger, `The deepagents extensions override wrote ${relaxations.join(", ")} into ${filePath}, which is your global deepagents-cli config: it decides whether the Python in a checked-out project's .deepagents/extensions/ is imported into dcode, for every project on this machine, not just this one.`);
|
|
40111
40354
|
}
|
|
40112
40355
|
/**
|
|
40113
40356
|
* Warn when the `deepagents` startup override relaxes what dcode may do on its
|
|
@@ -40122,12 +40365,13 @@ function mergeStartupOverride({ settings, startupOverride, filePath, logger }) {
|
|
|
40122
40365
|
* process environment. The value being replaced is named alongside, so a
|
|
40123
40366
|
* setting the user had turned down is visible as such.
|
|
40124
40367
|
*/
|
|
40125
|
-
function warnAboutStartupRelaxations({ startupOverride, previousStartup,
|
|
40368
|
+
function warnAboutStartupRelaxations({ override: startupOverride, previous: previousStartup, filePath, logger }) {
|
|
40126
40369
|
const relaxations = [];
|
|
40127
|
-
const describe = (key, value) => {
|
|
40128
|
-
|
|
40129
|
-
|
|
40130
|
-
|
|
40370
|
+
const describe = (key, value) => describeOverriddenValue({
|
|
40371
|
+
key,
|
|
40372
|
+
value,
|
|
40373
|
+
previous: previousStartup
|
|
40374
|
+
});
|
|
40131
40375
|
const mode = startupOverride.mode;
|
|
40132
40376
|
if (mode === "auto" || mode === "yolo") relaxations.push(describe("mode", mode));
|
|
40133
40377
|
for (const [key, upstreamDefault] of Object.entries(DEEPAGENTS_STARTUP_BOOLEAN_DEFAULTS)) {
|
|
@@ -40137,9 +40381,6 @@ function warnAboutStartupRelaxations({ startupOverride, previousStartup, written
|
|
|
40137
40381
|
}
|
|
40138
40382
|
if (relaxations.length > 0) warnWithFallback(logger, `The deepagents startup override wrote ${relaxations.join(", ")} into ${filePath}, which is your global deepagents-cli config: it relaxes how much dcode does without asking, for every project on this machine, not just this one.`);
|
|
40139
40383
|
if (startupOverride[STARTUP_RECENT_KEY] !== void 0) warnWithFallback(logger, `The deepagents startup override's '${STARTUP_RECENT_KEY}' was not written to ${filePath}: dcode manages that key itself, and with no explicit 'mode' beside it, it is what restores auto-approval at launch. Set 'mode' if switching approval modes is the intent.`);
|
|
40140
|
-
const known = new Set(DEEPAGENTS_STARTUP_KEYS);
|
|
40141
|
-
const unknownKeys = writtenKeys.filter((key) => !known.has(key));
|
|
40142
|
-
if (unknownKeys.length > 0) warnWithFallback(logger, `The deepagents startup override wrote ${unknownKeys.join(", ")} into ${filePath} unchecked — rulesync does not know what those keys grant, and that file is your global deepagents-cli config.`);
|
|
40143
40384
|
}
|
|
40144
40385
|
/**
|
|
40145
40386
|
* Read `[shell].allow_list` the way dcode does: a TOML array is taken element
|
|
@@ -43249,6 +43490,7 @@ const QWEN_OVERRIDE_TOOLS_KEYS = [
|
|
|
43249
43490
|
"sandboxImage",
|
|
43250
43491
|
"disabled",
|
|
43251
43492
|
"visible",
|
|
43493
|
+
"eager",
|
|
43252
43494
|
"listDirectory",
|
|
43253
43495
|
"workflowsEnabled"
|
|
43254
43496
|
];
|
|
@@ -43346,6 +43588,11 @@ const QWEN_OVERRIDE_GROUPS = [{
|
|
|
43346
43588
|
projectNote: ({ qualifiedKey, quotedValue, filePath }) => `${qualifiedKey} = ${quotedValue} was written to the project-scoped ${filePath}, so it decides which deferred tools are visible at startup in this repository.`,
|
|
43347
43589
|
globalNote: "Qwen Code honors this key wherever it is written, so in the global scope this decides which deferred tools are visible at startup for every project on this machine."
|
|
43348
43590
|
},
|
|
43591
|
+
eager: {
|
|
43592
|
+
rule: "global-machine-wide",
|
|
43593
|
+
projectNote: ({ qualifiedKey, quotedValue, filePath }) => `${qualifiedKey} = ${quotedValue} was written to the project-scoped ${filePath}, replacing the list in that file rather than adding to it, so in this repository every non-exempt eager-by-default tool it does not name is demoted to deferred — still callable, but only after \`tool_search\` loads it, and out of reach for the session if \`tool_search\` is not registered. A name added back is a tool whose schema is in the initial request again.`,
|
|
43594
|
+
globalNote: "Qwen Code honors this key wherever it is written, and the override replaces the list in this file rather than adding to it, so in the global scope it decides which eager-by-default tools keep their schemas in the initial request for every project on this machine — the ones it does not name are demoted to deferred, reachable only through `tool_search`, and out of reach entirely for a session where `tool_search` is not registered, while a name it adds back is a tool declared up front again."
|
|
43595
|
+
},
|
|
43349
43596
|
listDirectory: {
|
|
43350
43597
|
rule: "global-machine-wide",
|
|
43351
43598
|
projectNote: ({ qualifiedKey, quotedValue, filePath }) => `${qualifiedKey} = ${quotedValue} was written to the project-scoped ${filePath}, so it decides whether the built-in \`list_directory\` tool is registered in this repository.`,
|
|
@@ -54760,7 +55007,10 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
54760
55007
|
//#region src/features/skills/zcode-skill.ts
|
|
54761
55008
|
const ZcodeSkillFrontmatterSchema = zod_mini.z.looseObject({
|
|
54762
55009
|
name: zod_mini.z.string(),
|
|
54763
|
-
description: zod_mini.z.string()
|
|
55010
|
+
description: zod_mini.z.string(),
|
|
55011
|
+
when_to_use: zod_mini.z.optional(zod_mini.z.string()),
|
|
55012
|
+
license: zod_mini.z.optional(zod_mini.z.string()),
|
|
55013
|
+
metadata: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
54764
55014
|
});
|
|
54765
55015
|
/**
|
|
54766
55016
|
* Represents a ZCode skill directory.
|
|
@@ -54823,10 +55073,16 @@ var ZcodeSkill = class ZcodeSkill extends ToolSkill {
|
|
|
54823
55073
|
}
|
|
54824
55074
|
toRulesyncSkill() {
|
|
54825
55075
|
const frontmatter = this.getFrontmatter();
|
|
55076
|
+
const zcodeSection = {
|
|
55077
|
+
...frontmatter.when_to_use !== void 0 && { when_to_use: frontmatter.when_to_use },
|
|
55078
|
+
...frontmatter.license !== void 0 && { license: frontmatter.license },
|
|
55079
|
+
...frontmatter.metadata !== void 0 && { metadata: frontmatter.metadata }
|
|
55080
|
+
};
|
|
54826
55081
|
const rulesyncFrontmatter = {
|
|
54827
55082
|
name: frontmatter.name,
|
|
54828
55083
|
description: frontmatter.description,
|
|
54829
|
-
targets: ["*"]
|
|
55084
|
+
targets: ["*"],
|
|
55085
|
+
...Object.keys(zcodeSection).length > 0 && { zcode: zcodeSection }
|
|
54830
55086
|
};
|
|
54831
55087
|
return new RulesyncSkill({
|
|
54832
55088
|
outputRoot: this.outputRoot,
|
|
@@ -54841,9 +55097,21 @@ var ZcodeSkill = class ZcodeSkill extends ToolSkill {
|
|
|
54841
55097
|
}
|
|
54842
55098
|
static fromRulesyncSkill({ outputRoot = process.cwd(), rulesyncSkill, validate = true, global = false }) {
|
|
54843
55099
|
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
|
|
55100
|
+
const zcodeSection = rulesyncFrontmatter.zcode;
|
|
55101
|
+
const license = resolveLicense({
|
|
55102
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
55103
|
+
section: zcodeSection
|
|
55104
|
+
});
|
|
55105
|
+
const metadata = resolveMetadata({
|
|
55106
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
55107
|
+
section: zcodeSection
|
|
55108
|
+
});
|
|
54844
55109
|
const zcodeFrontmatter = {
|
|
54845
55110
|
name: rulesyncFrontmatter.name,
|
|
54846
|
-
description: rulesyncFrontmatter.description
|
|
55111
|
+
description: rulesyncFrontmatter.description,
|
|
55112
|
+
...zcodeSection?.when_to_use !== void 0 && { when_to_use: zcodeSection.when_to_use },
|
|
55113
|
+
...license !== void 0 && { license },
|
|
55114
|
+
...metadata !== void 0 && { metadata }
|
|
54847
55115
|
};
|
|
54848
55116
|
const settablePaths = ZcodeSkill.getSettablePaths({ global });
|
|
54849
55117
|
return new ZcodeSkill({
|
|
@@ -62944,10 +63212,21 @@ var ClineRule = class ClineRule extends ToolRule {
|
|
|
62944
63212
|
*/
|
|
62945
63213
|
const CodebuddyRuleFrontmatterSchema = zod_mini.z.object({
|
|
62946
63214
|
description: zod_mini.z.optional(zod_mini.z.string()),
|
|
62947
|
-
paths: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())),
|
|
62948
|
-
alwaysApply: zod_mini.z.optional(zod_mini.z.boolean())
|
|
63215
|
+
paths: zod_mini.z.optional(zod_mini.z.union([zod_mini.z.string(), zod_mini.z.array(zod_mini.z.string())])),
|
|
63216
|
+
alwaysApply: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
63217
|
+
enabled: zod_mini.z.optional(zod_mini.z.boolean())
|
|
62949
63218
|
});
|
|
62950
63219
|
/**
|
|
63220
|
+
* Normalizes the documented `string` / `string[]` shapes of `paths` to the
|
|
63221
|
+
* list form the rest of the adapter works with. An empty list and an empty
|
|
63222
|
+
* string both mean "no paths".
|
|
63223
|
+
*/
|
|
63224
|
+
function normalizeCodebuddyPaths(paths) {
|
|
63225
|
+
if (paths === void 0) return;
|
|
63226
|
+
const list = (typeof paths === "string" ? [paths] : paths).filter((path) => path.trim() !== "");
|
|
63227
|
+
return list.length > 0 ? list : void 0;
|
|
63228
|
+
}
|
|
63229
|
+
/**
|
|
62951
63230
|
* A universal glob (matching everything) is redundant on an Always Apply
|
|
62952
63231
|
* rule and, paired with `alwaysApply: true`, is the same semantic conflict
|
|
62953
63232
|
* `CursorRule.resolveCursorGlobs` avoids for Cursor: `alwaysApply` already
|
|
@@ -62965,7 +63244,7 @@ const UNIVERSAL_PATHS = /* @__PURE__ */ new Set(["**/*", "*"]);
|
|
|
62965
63244
|
* Rules format:
|
|
62966
63245
|
* - {project}/CODEBUDDY.md (root: true), also read from {project}/.codebuddy/CODEBUDDY.md
|
|
62967
63246
|
* - {project}/.codebuddy/rules/*.md (root: false, with optional
|
|
62968
|
-
* `description` / `paths` / `alwaysApply` frontmatter)
|
|
63247
|
+
* `description` / `paths` / `alwaysApply` / `enabled` frontmatter)
|
|
62969
63248
|
* - Global: ~/.codebuddy/CODEBUDDY.md and ~/.codebuddy/rules/*.md
|
|
62970
63249
|
*
|
|
62971
63250
|
* @see https://www.codebuddy.ai/docs/cli/memory
|
|
@@ -63007,9 +63286,10 @@ var CodebuddyRule = class CodebuddyRule extends ToolRule {
|
|
|
63007
63286
|
this.body = body;
|
|
63008
63287
|
}
|
|
63009
63288
|
static generateFileContent(body, frontmatter) {
|
|
63010
|
-
if (frontmatter.description === void 0 && frontmatter.paths === void 0 && frontmatter.alwaysApply === void 0) return body;
|
|
63289
|
+
if (frontmatter.description === void 0 && frontmatter.paths === void 0 && frontmatter.alwaysApply === void 0 && frontmatter.enabled === void 0) return body;
|
|
63011
63290
|
return stringifyFrontmatter(body, {
|
|
63012
63291
|
description: frontmatter.description,
|
|
63292
|
+
enabled: frontmatter.enabled,
|
|
63013
63293
|
alwaysApply: frontmatter.alwaysApply,
|
|
63014
63294
|
paths: frontmatter.paths
|
|
63015
63295
|
});
|
|
@@ -63057,10 +63337,36 @@ var CodebuddyRule = class CodebuddyRule extends ToolRule {
|
|
|
63057
63337
|
root: isRoot
|
|
63058
63338
|
});
|
|
63059
63339
|
}
|
|
63060
|
-
|
|
63061
|
-
|
|
63062
|
-
|
|
63063
|
-
|
|
63340
|
+
/**
|
|
63341
|
+
* Resolves the `paths` / `alwaysApply` pair against CodeBuddy's Rule Type
|
|
63342
|
+
* Determination table, which reads:
|
|
63343
|
+
*
|
|
63344
|
+
* | `alwaysApply` | `paths` | Rule type |
|
|
63345
|
+
* | ---------------- | --------- | ---------------------------------- |
|
|
63346
|
+
* | `true` (default) | any | ALWAYS — always injected |
|
|
63347
|
+
* | `false` | has value | MANUAL — triggered on matching file |
|
|
63348
|
+
* | `false` | none | not supported; the rule is dropped |
|
|
63349
|
+
*
|
|
63350
|
+
* The default being `true` is the opposite of Cursor, which the adapter was
|
|
63351
|
+
* modeled on: `paths` alone scopes nothing, so a rule meant to be path
|
|
63352
|
+
* triggered has to carry an explicit `alwaysApply: false` alongside it.
|
|
63353
|
+
*
|
|
63354
|
+
* @see https://www.codebuddy.ai/docs/cli/memory
|
|
63355
|
+
*/
|
|
63356
|
+
static resolveCodebuddyRuleType({ paths, alwaysApply }) {
|
|
63357
|
+
const scopedPaths = paths && paths.length > 0 && !paths.every((path) => UNIVERSAL_PATHS.has(path.trim())) ? paths : void 0;
|
|
63358
|
+
if (alwaysApply === true) return {
|
|
63359
|
+
paths: scopedPaths,
|
|
63360
|
+
alwaysApply: true
|
|
63361
|
+
};
|
|
63362
|
+
if (scopedPaths === void 0) return {
|
|
63363
|
+
paths: void 0,
|
|
63364
|
+
alwaysApply: void 0
|
|
63365
|
+
};
|
|
63366
|
+
return {
|
|
63367
|
+
paths: scopedPaths,
|
|
63368
|
+
alwaysApply: false
|
|
63369
|
+
};
|
|
63064
63370
|
}
|
|
63065
63371
|
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
63066
63372
|
const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
|
|
@@ -63077,17 +63383,17 @@ var CodebuddyRule = class CodebuddyRule extends ToolRule {
|
|
|
63077
63383
|
root
|
|
63078
63384
|
});
|
|
63079
63385
|
if (!paths.nonRoot) throw new Error(`nonRoot path is not set for ${rulesyncRule.getRelativeFilePath()}`);
|
|
63080
|
-
const codebuddyPaths = rulesyncFrontmatter.codebuddy?.paths;
|
|
63386
|
+
const codebuddyPaths = normalizeCodebuddyPaths(rulesyncFrontmatter.codebuddy?.paths);
|
|
63081
63387
|
const globs = rulesyncFrontmatter.globs;
|
|
63082
|
-
const
|
|
63083
|
-
const pathsValue = CodebuddyRule.resolveCodebuddyPaths({
|
|
63388
|
+
const ruleType = CodebuddyRule.resolveCodebuddyRuleType({
|
|
63084
63389
|
paths: codebuddyPaths ?? (globs?.length ? globs : void 0),
|
|
63085
|
-
alwaysApply: alwaysApply
|
|
63390
|
+
alwaysApply: rulesyncFrontmatter.codebuddy?.alwaysApply
|
|
63086
63391
|
});
|
|
63087
63392
|
const codebuddyFrontmatter = {
|
|
63088
63393
|
description: rulesyncFrontmatter.codebuddy?.description ?? rulesyncFrontmatter.description,
|
|
63089
|
-
paths:
|
|
63090
|
-
alwaysApply
|
|
63394
|
+
paths: ruleType.paths,
|
|
63395
|
+
alwaysApply: ruleType.alwaysApply,
|
|
63396
|
+
enabled: rulesyncFrontmatter.codebuddy?.enabled
|
|
63091
63397
|
};
|
|
63092
63398
|
return new CodebuddyRule({
|
|
63093
63399
|
outputRoot,
|
|
@@ -63117,17 +63423,19 @@ var CodebuddyRule = class CodebuddyRule extends ToolRule {
|
|
|
63117
63423
|
validate: true
|
|
63118
63424
|
});
|
|
63119
63425
|
}
|
|
63120
|
-
const
|
|
63121
|
-
const
|
|
63426
|
+
const sourcePaths = normalizeCodebuddyPaths(this.frontmatter.paths) ?? [];
|
|
63427
|
+
const isAlways = this.frontmatter.alwaysApply !== false;
|
|
63122
63428
|
const globs = sourcePaths.length === 0 && isAlways ? ["**/*"] : sourcePaths;
|
|
63429
|
+
const alwaysApply = this.frontmatter.alwaysApply ?? (sourcePaths.length > 0 ? true : void 0);
|
|
63123
63430
|
const rulesyncFrontmatter = {
|
|
63124
63431
|
targets,
|
|
63125
63432
|
root: false,
|
|
63126
63433
|
description: this.frontmatter.description,
|
|
63127
63434
|
globs,
|
|
63128
|
-
...(this.frontmatter.paths !== void 0 || this.frontmatter.alwaysApply !== void 0 || this.frontmatter.description !== void 0) && { codebuddy: {
|
|
63129
|
-
paths:
|
|
63130
|
-
alwaysApply
|
|
63435
|
+
...(this.frontmatter.paths !== void 0 || this.frontmatter.alwaysApply !== void 0 || this.frontmatter.enabled !== void 0 || this.frontmatter.description !== void 0) && { codebuddy: {
|
|
63436
|
+
paths: sourcePaths.length > 0 ? sourcePaths : void 0,
|
|
63437
|
+
alwaysApply,
|
|
63438
|
+
enabled: this.frontmatter.enabled,
|
|
63131
63439
|
description: this.frontmatter.description
|
|
63132
63440
|
} }
|
|
63133
63441
|
};
|
|
@@ -65910,33 +66218,49 @@ var ReplitRule = class ReplitRule extends ToolRule {
|
|
|
65910
66218
|
* Supports plain Markdown without frontmatter, mode-specific rules,
|
|
65911
66219
|
* and both directory-based and single-file configurations.
|
|
65912
66220
|
*
|
|
65913
|
-
* - Project scope writes the non-root directory `.roo/rules
|
|
66221
|
+
* - Project scope writes the non-root directory `.roo/rules/`, and the root
|
|
66222
|
+
* rule to the workspace-root `AGENTS.md` the extension reads from `cwd`.
|
|
65914
66223
|
* - Global scope writes the same non-root directory resolved under the home
|
|
65915
|
-
* directory (`~/.roo/rules/`), which Roo loads before workspace rules.
|
|
66224
|
+
* directory (`~/.roo/rules/`), which Roo loads before workspace rules. The
|
|
66225
|
+
* root rule joins it as `~/.roo/rules/AGENTS.md`: agent-rules discovery is
|
|
66226
|
+
* workspace-only, so the default project-scope root would resolve to a
|
|
66227
|
+
* `~/AGENTS.md` nothing ever reads.
|
|
65916
66228
|
* @see https://roocodeinc.github.io/Roo-Code/features/custom-instructions
|
|
65917
66229
|
*/
|
|
65918
66230
|
var RooRule = class RooRule extends ToolRule {
|
|
65919
|
-
static getSettablePaths(
|
|
65920
|
-
|
|
66231
|
+
static getSettablePaths({ global, excludeToolDir } = {}) {
|
|
66232
|
+
const rulesDirPath = buildToolPath(ROO_DIR, "rules", excludeToolDir);
|
|
66233
|
+
if (global) return {
|
|
66234
|
+
root: {
|
|
66235
|
+
relativeDirPath: rulesDirPath,
|
|
66236
|
+
relativeFilePath: ROO_GLOBAL_ROOT_RULE_FILE_NAME
|
|
66237
|
+
},
|
|
66238
|
+
nonRoot: { relativeDirPath: rulesDirPath }
|
|
66239
|
+
};
|
|
66240
|
+
return { nonRoot: { relativeDirPath: rulesDirPath } };
|
|
65921
66241
|
}
|
|
65922
|
-
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, relativeDirPath: overrideDirPath, validate = true }) {
|
|
65923
|
-
const
|
|
66242
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, relativeDirPath: overrideDirPath, validate = true, global = false }) {
|
|
66243
|
+
const paths = this.getSettablePaths({ global });
|
|
66244
|
+
const relativeDirPath = overrideDirPath !== void 0 && RooRule.extractModeFromDirPath(overrideDirPath) !== void 0 ? overrideDirPath : paths.nonRoot?.relativeDirPath ?? buildToolPath(".roo", "rules");
|
|
65924
66245
|
const fileContent = await readFileContent((0, node_path.join)(outputRoot, relativeDirPath, relativeFilePath));
|
|
66246
|
+
const isRoot = "root" in paths && relativeDirPath === paths.root.relativeDirPath && relativeFilePath === paths.root.relativeFilePath;
|
|
65925
66247
|
return new RooRule({
|
|
65926
66248
|
outputRoot,
|
|
65927
66249
|
relativeDirPath,
|
|
65928
66250
|
relativeFilePath,
|
|
65929
66251
|
fileContent,
|
|
65930
66252
|
validate,
|
|
65931
|
-
root:
|
|
66253
|
+
root: isRoot
|
|
65932
66254
|
});
|
|
65933
66255
|
}
|
|
65934
|
-
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true }) {
|
|
66256
|
+
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
66257
|
+
const paths = this.getSettablePaths({ global });
|
|
65935
66258
|
const params = this.buildToolRuleParamsDefault({
|
|
65936
66259
|
outputRoot,
|
|
65937
66260
|
rulesyncRule,
|
|
65938
66261
|
validate,
|
|
65939
|
-
|
|
66262
|
+
..."root" in paths && { rootPath: paths.root },
|
|
66263
|
+
nonRootPath: paths.nonRoot
|
|
65940
66264
|
});
|
|
65941
66265
|
const mode = rulesyncRule.getFrontmatter().roo?.mode;
|
|
65942
66266
|
if (!params.root && mode !== void 0 && mode !== "") {
|
|
@@ -66859,7 +67183,9 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
66859
67183
|
extension: "md",
|
|
66860
67184
|
supportsGlobal: true,
|
|
66861
67185
|
ruleDiscoveryMode: "auto",
|
|
66862
|
-
collisionPolicy: "fold"
|
|
67186
|
+
collisionPolicy: "fold",
|
|
67187
|
+
localRootMode: "separate-local-file",
|
|
67188
|
+
localRootFileName: CRUSH_LOCAL_RULE_FILE_NAME
|
|
66863
67189
|
}
|
|
66864
67190
|
}],
|
|
66865
67191
|
["cursor", {
|
|
@@ -67579,6 +67905,34 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
67579
67905
|
root: true,
|
|
67580
67906
|
localRoot
|
|
67581
67907
|
});
|
|
67908
|
+
if (isClassOrSubclassOf({
|
|
67909
|
+
candidate: factory.class,
|
|
67910
|
+
base: CodebuddyRule
|
|
67911
|
+
})) {
|
|
67912
|
+
const paths = CodebuddyRule.getSettablePaths({ global: this.global });
|
|
67913
|
+
return new CodebuddyRule({
|
|
67914
|
+
outputRoot: this.outputRoot,
|
|
67915
|
+
relativeDirPath: relativeDirPath ?? paths.root.relativeDirPath,
|
|
67916
|
+
relativeFilePath: fileName,
|
|
67917
|
+
frontmatter: {},
|
|
67918
|
+
body,
|
|
67919
|
+
validate: true,
|
|
67920
|
+
root: true,
|
|
67921
|
+
localRoot
|
|
67922
|
+
});
|
|
67923
|
+
}
|
|
67924
|
+
if (isClassOrSubclassOf({
|
|
67925
|
+
candidate: factory.class,
|
|
67926
|
+
base: CrushRule
|
|
67927
|
+
})) return new CrushRule({
|
|
67928
|
+
outputRoot: this.outputRoot,
|
|
67929
|
+
relativeDirPath: relativeDirPath ?? ".",
|
|
67930
|
+
relativeFilePath: fileName,
|
|
67931
|
+
fileContent: body,
|
|
67932
|
+
validate: true,
|
|
67933
|
+
root: true,
|
|
67934
|
+
localRoot
|
|
67935
|
+
});
|
|
67582
67936
|
if (isClassOrSubclassOf({
|
|
67583
67937
|
candidate: factory.class,
|
|
67584
67938
|
base: QwencodeRule
|
|
@@ -70279,6 +70633,12 @@ Object.defineProperty(exports, "CONFLICTING_TARGET_PAIRS", {
|
|
|
70279
70633
|
return CONFLICTING_TARGET_PAIRS;
|
|
70280
70634
|
}
|
|
70281
70635
|
});
|
|
70636
|
+
Object.defineProperty(exports, "CRUSH_LOCAL_RULE_FILE_NAME", {
|
|
70637
|
+
enumerable: true,
|
|
70638
|
+
get: function() {
|
|
70639
|
+
return CRUSH_LOCAL_RULE_FILE_NAME;
|
|
70640
|
+
}
|
|
70641
|
+
});
|
|
70282
70642
|
Object.defineProperty(exports, "CURATED_RULES_FEATURE_SUBDIR", {
|
|
70283
70643
|
enumerable: true,
|
|
70284
70644
|
get: function() {
|