rulesync 16.34.2 → 16.35.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 +4 -2
- package/dist/cli/index.cjs +9 -4
- package/dist/cli/index.js +9 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-DoCUTXaU.js → import-DxRza3o_.js} +441 -59
- package/dist/import-DxRza3o_.js.map +1 -0
- package/dist/{import-D50FT0lm.cjs → import-j_cW_K5C.cjs} +451 -57
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-DoCUTXaU.js.map +0 -1
|
@@ -515,6 +515,7 @@ const rulesProcessorToolTargetTuple = [
|
|
|
515
515
|
"musecode",
|
|
516
516
|
"opencode",
|
|
517
517
|
"pi",
|
|
518
|
+
"pool",
|
|
518
519
|
"qwencode",
|
|
519
520
|
"reasonix",
|
|
520
521
|
"replit",
|
|
@@ -528,7 +529,6 @@ const rulesProcessorToolTargetTuple = [
|
|
|
528
529
|
"zcode",
|
|
529
530
|
"zed",
|
|
530
531
|
"zoocode",
|
|
531
|
-
"pool",
|
|
532
532
|
"dsh"
|
|
533
533
|
];
|
|
534
534
|
const ignoreProcessorToolTargetTuple = [
|
|
@@ -4091,6 +4091,10 @@ const HookDefinitionSchema = z.looseObject({
|
|
|
4091
4091
|
model: z.optional(safeString),
|
|
4092
4092
|
args: z.optional(z.array(safeString)),
|
|
4093
4093
|
metadata: z.optional(z.looseObject({})),
|
|
4094
|
+
source: z.optional(z.looseObject({
|
|
4095
|
+
source: safeString,
|
|
4096
|
+
ref: z.optional(safeString)
|
|
4097
|
+
})),
|
|
4094
4098
|
if: z.optional(safeString),
|
|
4095
4099
|
commandWindows: z.optional(safeString),
|
|
4096
4100
|
additionalContextLimit: z.optional(z.int().check(nonnegative())),
|
|
@@ -4851,10 +4855,12 @@ const ZCODE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONIC
|
|
|
4851
4855
|
*
|
|
4852
4856
|
* Bob reads `hooks` from `.bob/settings.json` (project) and
|
|
4853
4857
|
* `~/.bob/settings/settings.json` (user) in the Claude-Code shape and fires
|
|
4854
|
-
*
|
|
4855
|
-
*
|
|
4856
|
-
*
|
|
4858
|
+
* seven events: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse,
|
|
4859
|
+
* PreCompact, PostCompact (both added by Bob Shell 2.0.3) and Stop. Handlers
|
|
4860
|
+
* are `command` or `https` hooks, and `matcher` (a regex over the tool name)
|
|
4861
|
+
* applies to the two tool events.
|
|
4857
4862
|
*
|
|
4863
|
+
* @see https://bob.ibm.com/docs/shell/configuration/lifecycle-hooks
|
|
4858
4864
|
* @see https://bob.ibm.com/docs/ide/configuration/lifecycle-hooks
|
|
4859
4865
|
*/
|
|
4860
4866
|
const BOB_HOOK_EVENTS = [
|
|
@@ -4862,6 +4868,8 @@ const BOB_HOOK_EVENTS = [
|
|
|
4862
4868
|
"beforeSubmitPrompt",
|
|
4863
4869
|
"preToolUse",
|
|
4864
4870
|
"postToolUse",
|
|
4871
|
+
"preCompact",
|
|
4872
|
+
"postCompact",
|
|
4865
4873
|
"stop"
|
|
4866
4874
|
];
|
|
4867
4875
|
const CANONICAL_TO_BOB_EVENT_NAMES = {
|
|
@@ -4869,6 +4877,8 @@ const CANONICAL_TO_BOB_EVENT_NAMES = {
|
|
|
4869
4877
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
4870
4878
|
preToolUse: "PreToolUse",
|
|
4871
4879
|
postToolUse: "PostToolUse",
|
|
4880
|
+
preCompact: "PreCompact",
|
|
4881
|
+
postCompact: "PostCompact",
|
|
4872
4882
|
stop: "Stop"
|
|
4873
4883
|
};
|
|
4874
4884
|
const BOB_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_BOB_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
@@ -7280,13 +7290,30 @@ const DeepagentsExtensionsOverrideSchema = z.looseObject({
|
|
|
7280
7290
|
]))
|
|
7281
7291
|
});
|
|
7282
7292
|
/**
|
|
7293
|
+
* The `[mcp]` table of `~/.deepagents/config.toml`, where dcode keeps its
|
|
7294
|
+
* per-server trust for the MCP servers a project's `.mcp.json` /
|
|
7295
|
+
* `.deepagents/.mcp.json` declares. dcode reads these lists from the user-level
|
|
7296
|
+
* file only — never from a project file — which is exactly why the global
|
|
7297
|
+
* permissions adapter is the place to author them.
|
|
7298
|
+
*
|
|
7299
|
+
* `disabled_project_servers` names project MCP servers dcode always rejects;
|
|
7300
|
+
* a rejection wins over any approval or trust. The sibling
|
|
7301
|
+
* `enabled_project_server_approvals` is the fingerprint-bound approval store
|
|
7302
|
+
* the interactive prompt fills in, and `enabled_project_servers` is a
|
|
7303
|
+
* deprecated flat allowlist dcode ignores, so neither has a key here.
|
|
7304
|
+
*
|
|
7305
|
+
* @see https://docs.langchain.com/oss/deepagents/code/configuration
|
|
7306
|
+
*/
|
|
7307
|
+
const DeepagentsMcpOverrideSchema = z.looseObject({ disabled_project_servers: z.optional(z.array(z.string())) });
|
|
7308
|
+
/**
|
|
7283
7309
|
* The `[shell].allow_list` array itself is rulesync-owned, driven by the
|
|
7284
7310
|
* shared `permission.bash` block, so it has no key here.
|
|
7285
7311
|
*/
|
|
7286
7312
|
const DeepagentsPermissionsOverrideSchema = z.looseObject({
|
|
7287
7313
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
7288
7314
|
startup: z.optional(DeepagentsStartupOverrideSchema),
|
|
7289
|
-
extensions: z.optional(DeepagentsExtensionsOverrideSchema)
|
|
7315
|
+
extensions: z.optional(DeepagentsExtensionsOverrideSchema),
|
|
7316
|
+
mcp: z.optional(DeepagentsMcpOverrideSchema)
|
|
7290
7317
|
});
|
|
7291
7318
|
/**
|
|
7292
7319
|
* The actions Junie's allowlist accepts. Verified against the shipped Junie
|
|
@@ -9600,7 +9627,13 @@ const RulesyncSkillFrontmatterSchema = z.looseObject({
|
|
|
9600
9627
|
"user-invocable": z.optional(z.boolean()),
|
|
9601
9628
|
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())]))
|
|
9602
9629
|
})),
|
|
9603
|
-
commandcode: z.optional(z.looseObject({
|
|
9630
|
+
commandcode: z.optional(z.looseObject({
|
|
9631
|
+
license: z.optional(z.string()),
|
|
9632
|
+
compatibility: z.optional(z.union([z.string(), z.looseObject({})])),
|
|
9633
|
+
metadata: z.optional(z.looseObject({})),
|
|
9634
|
+
"disable-model-invocation": z.optional(z.boolean()),
|
|
9635
|
+
"user-invocable": z.optional(z.boolean())
|
|
9636
|
+
})),
|
|
9604
9637
|
cortexcode: z.optional(z.looseObject({})),
|
|
9605
9638
|
continue: z.optional(z.looseObject({})),
|
|
9606
9639
|
tabnine: z.optional(z.looseObject({})),
|
|
@@ -9844,7 +9877,7 @@ async function getLocalSkillDirNames(sourceTree) {
|
|
|
9844
9877
|
*
|
|
9845
9878
|
* The rulesync skill frontmatter exposes a root-level `disable-model-invocation`
|
|
9846
9879
|
* default that applies to every tool supporting the flag (claudecode, copilot,
|
|
9847
|
-
* copilotcli, crush, cursor, zed, pi, qwencode, grokcli, factorydroid, dsh). Each tool's own section may override that
|
|
9880
|
+
* copilotcli, crush, cursor, zed, pi, qwencode, grokcli, factorydroid, dsh, commandcode). Each tool's own section may override that
|
|
9848
9881
|
* default with a per-target value. A defined section value (including `false`)
|
|
9849
9882
|
* always wins over the root default.
|
|
9850
9883
|
*
|
|
@@ -9863,7 +9896,7 @@ function resolveDisableModelInvocation({ rootFrontmatter, section }) {
|
|
|
9863
9896
|
*
|
|
9864
9897
|
* The rulesync skill frontmatter exposes a root-level `user-invocable` default
|
|
9865
9898
|
* that applies to every tool supporting the flag (claudecode, copilot,
|
|
9866
|
-
* copilotcli, crush, cursor, qwencode, vibe, grokcli, factorydroid, dsh). Each tool's own section may override that default with a
|
|
9899
|
+
* copilotcli, crush, cursor, qwencode, vibe, grokcli, factorydroid, dsh, commandcode). Each tool's own section may override that default with a
|
|
9867
9900
|
* per-target value. A defined section value (including `false`) always wins
|
|
9868
9901
|
* over the root default.
|
|
9869
9902
|
*
|
|
@@ -15431,6 +15464,7 @@ var CodexcliCommand = class CodexcliCommand extends ToolCommand {
|
|
|
15431
15464
|
const COMMANDCODE_DIR = ".commandcode";
|
|
15432
15465
|
const COMMANDCODE_RULE_FILE_NAME = "AGENTS.md";
|
|
15433
15466
|
const COMMANDCODE_SETTINGS_FILE_NAME = "settings.json";
|
|
15467
|
+
const COMMANDCODE_SETTINGS_LOCAL_FILE_NAME = "settings.local.json";
|
|
15434
15468
|
const COMMANDCODE_PROJECT_MCP_FILE_NAME = ".mcp.json";
|
|
15435
15469
|
const COMMANDCODE_GLOBAL_MCP_FILE_NAME = "mcp.json";
|
|
15436
15470
|
const COMMANDCODE_COMMANDS_DIR_PATH = join(COMMANDCODE_DIR, "commands");
|
|
@@ -20645,6 +20679,18 @@ function isToolMatcherEntry(x) {
|
|
|
20645
20679
|
return true;
|
|
20646
20680
|
}
|
|
20647
20681
|
/**
|
|
20682
|
+
* Convert a canonical `timeout` (seconds) into the tool's unit.
|
|
20683
|
+
*/
|
|
20684
|
+
function emitTimeout({ timeout, converterConfig }) {
|
|
20685
|
+
return converterConfig.timeoutUnit === "milliseconds" && Number.isFinite(timeout) ? Math.round(timeout * 1e3) : timeout;
|
|
20686
|
+
}
|
|
20687
|
+
/**
|
|
20688
|
+
* Convert a tool `timeout` back into the canonical unit (seconds).
|
|
20689
|
+
*/
|
|
20690
|
+
function importTimeout({ timeout, converterConfig }) {
|
|
20691
|
+
return converterConfig.timeoutUnit === "milliseconds" && Number.isFinite(timeout) ? timeout / 1e3 : timeout;
|
|
20692
|
+
}
|
|
20693
|
+
/**
|
|
20648
20694
|
* Filter the shared canonical hooks to the supported events and merge tool overrides on top.
|
|
20649
20695
|
*/
|
|
20650
20696
|
function buildEffectiveHooks$1({ config, toolOverrideHooks, supportedEvents }) {
|
|
@@ -20785,6 +20831,7 @@ const isEmittableString = ({ value }) => isNonEmptyString(value);
|
|
|
20785
20831
|
const isEmittableArray = ({ value }) => isStringArray$1(value);
|
|
20786
20832
|
const isEmittableRecord = ({ value }) => isSafeStringRecord(value);
|
|
20787
20833
|
const isImportableArray = ({ value }) => isSafeStringArray(value);
|
|
20834
|
+
const isEmittableObject = ({ value }) => isPlainObject$1(value);
|
|
20788
20835
|
/**
|
|
20789
20836
|
* The canonical schema of one hook field, looked up by name. Read off the
|
|
20790
20837
|
* schema's own shape rather than by parsing a one-field object, so a `canonical`
|
|
@@ -20819,11 +20866,17 @@ const isImportableNumber = ({ value, canonical }) => Number.isFinite(value) && s
|
|
|
20819
20866
|
value,
|
|
20820
20867
|
canonical
|
|
20821
20868
|
});
|
|
20869
|
+
const isImportableObject = ({ value, canonical }) => isPlainObject$1(value) && satisfiesCanonicalField({
|
|
20870
|
+
value,
|
|
20871
|
+
canonical
|
|
20872
|
+
});
|
|
20822
20873
|
/**
|
|
20823
20874
|
* Say which rule the value broke, so the warning names the actual constraint
|
|
20824
20875
|
* rather than asserting a canonical rejection that may not be the reason. A
|
|
20825
20876
|
* closed enum lists its members; a rule carrying its own message (the
|
|
20826
|
-
* control-character check behind `safeString`) reuses it.
|
|
20877
|
+
* control-character check behind `safeString`) reuses it. An object field
|
|
20878
|
+
* names the offending key, since zod's generic "Invalid input" would not tell
|
|
20879
|
+
* the reader which key is missing or malformed.
|
|
20827
20880
|
*/
|
|
20828
20881
|
function describeScalarConstraint({ canonical, value }) {
|
|
20829
20882
|
const schema = canonicalFieldSchema(canonical);
|
|
@@ -20831,13 +20884,22 @@ function describeScalarConstraint({ canonical, value }) {
|
|
|
20831
20884
|
if (result === void 0 || result.success) return `it is not a value this field carries through.`;
|
|
20832
20885
|
const issue = result.error.issues[0];
|
|
20833
20886
|
if (issue === void 0) return `it is not a value the canonical "${canonical}" field accepts.`;
|
|
20834
|
-
return `it does not satisfy the canonical "${canonical}" field: ${issue.message}.`;
|
|
20887
|
+
return `it does not satisfy the canonical "${canonical}" field${issue.path.length > 0 ? ` at ${quoteValueForWarning(issue.path.map(String).join("."))}` : ""}: ${issue.message}.`;
|
|
20835
20888
|
}
|
|
20836
20889
|
const describeInvalidScalar = ({ tool, canonical, value }) => `Dropping "${tool}" (${quoteValueForWarning(value)}) while importing a hook: ${describeScalarConstraint({
|
|
20837
20890
|
canonical,
|
|
20838
20891
|
value
|
|
20839
20892
|
})} Importing it would fail validation on the next run.`;
|
|
20840
20893
|
const describeInvalidArray = ({ tool }) => `Dropping "${tool}" while importing a hook: it must be a list of strings without newline, carriage return or NUL characters.`;
|
|
20894
|
+
/**
|
|
20895
|
+
* An object is quoted by its offending key rather than its value: the payload
|
|
20896
|
+
* can be arbitrarily large, and the missing or malformed key is what the
|
|
20897
|
+
* reader needs to fix.
|
|
20898
|
+
*/
|
|
20899
|
+
const describeInvalidObject = ({ tool, canonical, value }) => isPlainObject$1(value) ? `Dropping "${tool}" while importing a hook: ${describeScalarConstraint({
|
|
20900
|
+
canonical,
|
|
20901
|
+
value
|
|
20902
|
+
})} Importing it would fail validation on the next run.` : `Dropping "${tool}" while importing a hook: it must be an object.`;
|
|
20841
20903
|
const describeInvalidRecord = ({ tool }) => `Dropping "${tool}" while importing a hook: it must be a map of strings whose keys are non-empty and free of "=", and whose keys and values carry no newline, carriage return or NUL characters.`;
|
|
20842
20904
|
/**
|
|
20843
20905
|
* Check a value against the shape its field documents. A string field also
|
|
@@ -20943,6 +21005,14 @@ function emitAllPassthroughFields({ def, hookType, eventName, converterConfig, w
|
|
|
20943
21005
|
fields: converterConfig.recordPassthroughFields ?? [],
|
|
20944
21006
|
isValid: isEmittableRecord,
|
|
20945
21007
|
warn
|
|
21008
|
+
}),
|
|
21009
|
+
...emitPassthroughFields({
|
|
21010
|
+
def,
|
|
21011
|
+
hookType,
|
|
21012
|
+
eventName,
|
|
21013
|
+
fields: converterConfig.objectPassthroughFields ?? [],
|
|
21014
|
+
isValid: isEmittableObject,
|
|
21015
|
+
warn
|
|
20946
21016
|
})
|
|
20947
21017
|
};
|
|
20948
21018
|
}
|
|
@@ -20966,9 +21036,12 @@ function buildToolHooks({ defs, eventName, converterConfig, warn }) {
|
|
|
20966
21036
|
converterConfig,
|
|
20967
21037
|
warn
|
|
20968
21038
|
}),
|
|
20969
|
-
type: hookType,
|
|
21039
|
+
type: converterConfig.hookTypeNames?.[hookType] ?? hookType,
|
|
20970
21040
|
...command !== void 0 && command !== null && { command },
|
|
20971
|
-
...def.timeout !== void 0 && def.timeout !== null && { timeout:
|
|
21041
|
+
...def.timeout !== void 0 && def.timeout !== null && { timeout: emitTimeout({
|
|
21042
|
+
timeout: def.timeout,
|
|
21043
|
+
converterConfig
|
|
21044
|
+
}) },
|
|
20972
21045
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt },
|
|
20973
21046
|
...emitTypePayloadFields({
|
|
20974
21047
|
def,
|
|
@@ -21090,6 +21163,20 @@ const IMPORTED_HOOK_TYPES = /* @__PURE__ */ new Set([
|
|
|
21090
21163
|
function isImportedHookType(value) {
|
|
21091
21164
|
return typeof value === "string" && IMPORTED_HOOK_TYPES.has(value);
|
|
21092
21165
|
}
|
|
21166
|
+
/**
|
|
21167
|
+
* The canonical hook type a tool-side `type` value denotes: the tool's own
|
|
21168
|
+
* spelling from {@link ToolHooksConverterConfig.hookTypeNames} when it has
|
|
21169
|
+
* one, otherwise the value itself when it is a canonical type, and `command`
|
|
21170
|
+
* for anything else (the same coercion as before the renames existed).
|
|
21171
|
+
*/
|
|
21172
|
+
function resolveImportedHookType({ value, converterConfig }) {
|
|
21173
|
+
const names = converterConfig.hookTypeNames;
|
|
21174
|
+
if (names !== void 0 && typeof value === "string") {
|
|
21175
|
+
for (const [canonical, tool] of Object.entries(names)) if (tool === value) return canonical;
|
|
21176
|
+
if (Object.hasOwn(names, value)) return "command";
|
|
21177
|
+
}
|
|
21178
|
+
return isImportedHookType(value) ? value : "command";
|
|
21179
|
+
}
|
|
21093
21180
|
function isStringRecord(value) {
|
|
21094
21181
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
21095
21182
|
return Object.values(value).every((v) => typeof v === "string");
|
|
@@ -21255,6 +21342,14 @@ function importAllPassthroughFields({ h, hookType, converterConfig, warn }) {
|
|
|
21255
21342
|
isValid: isEmittableRecord,
|
|
21256
21343
|
describeInvalid: describeInvalidRecord,
|
|
21257
21344
|
warn
|
|
21345
|
+
}),
|
|
21346
|
+
...importPassthroughFields({
|
|
21347
|
+
h,
|
|
21348
|
+
hookType,
|
|
21349
|
+
fields: converterConfig.objectPassthroughFields ?? [],
|
|
21350
|
+
isValid: isImportableObject,
|
|
21351
|
+
describeInvalid: describeInvalidObject,
|
|
21352
|
+
warn
|
|
21258
21353
|
})
|
|
21259
21354
|
};
|
|
21260
21355
|
}
|
|
@@ -21262,7 +21357,10 @@ function importAllPassthroughFields({ h, hookType, converterConfig, warn }) {
|
|
|
21262
21357
|
* Convert a single tool hook record into a canonical hook definition.
|
|
21263
21358
|
*/
|
|
21264
21359
|
function toolHookToCanonical({ h, rawEntry, converterConfig, warn }) {
|
|
21265
|
-
const hookType =
|
|
21360
|
+
const hookType = resolveImportedHookType({
|
|
21361
|
+
value: h.type,
|
|
21362
|
+
converterConfig
|
|
21363
|
+
});
|
|
21266
21364
|
const command = importCanonicalString({
|
|
21267
21365
|
value: stripCommandPrefix({
|
|
21268
21366
|
command: h.command,
|
|
@@ -21271,7 +21369,10 @@ function toolHookToCanonical({ h, rawEntry, converterConfig, warn }) {
|
|
|
21271
21369
|
canonical: "command",
|
|
21272
21370
|
warn
|
|
21273
21371
|
});
|
|
21274
|
-
const timeout = typeof h.timeout === "number" ?
|
|
21372
|
+
const timeout = typeof h.timeout === "number" ? importTimeout({
|
|
21373
|
+
timeout: h.timeout,
|
|
21374
|
+
converterConfig
|
|
21375
|
+
}) : void 0;
|
|
21275
21376
|
const prompt = importCanonicalString({
|
|
21276
21377
|
value: h.prompt,
|
|
21277
21378
|
canonical: "prompt",
|
|
@@ -21404,7 +21505,10 @@ function toolMatcherEntryToCanonical({ rawEntry, converterConfig, warn }) {
|
|
|
21404
21505
|
const skipReason = describeHookSkipReason({
|
|
21405
21506
|
h,
|
|
21406
21507
|
rawEntry,
|
|
21407
|
-
hookType:
|
|
21508
|
+
hookType: resolveImportedHookType({
|
|
21509
|
+
value: h.type,
|
|
21510
|
+
converterConfig
|
|
21511
|
+
}),
|
|
21408
21512
|
converterConfig
|
|
21409
21513
|
});
|
|
21410
21514
|
if (skipReason !== void 0) {
|
|
@@ -21889,6 +21993,7 @@ const AUGMENTCODE_CONVERTER_CONFIG = {
|
|
|
21889
21993
|
"beforeSubmitPrompt"
|
|
21890
21994
|
]),
|
|
21891
21995
|
supportedHookTypes: /* @__PURE__ */ new Set(["command"]),
|
|
21996
|
+
timeoutUnit: "milliseconds",
|
|
21892
21997
|
arrayPassthroughFields: [{
|
|
21893
21998
|
canonical: "args",
|
|
21894
21999
|
tool: "args"
|
|
@@ -22487,9 +22592,12 @@ const BOB_SPEC = {
|
|
|
22487
22592
|
noMatcherEvents: /* @__PURE__ */ new Set([
|
|
22488
22593
|
"sessionStart",
|
|
22489
22594
|
"beforeSubmitPrompt",
|
|
22595
|
+
"preCompact",
|
|
22596
|
+
"postCompact",
|
|
22490
22597
|
"stop"
|
|
22491
22598
|
]),
|
|
22492
|
-
supportedHookTypes: /* @__PURE__ */ new Set(["command"]),
|
|
22599
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command", "http"]),
|
|
22600
|
+
hookTypeNames: { http: "https" },
|
|
22493
22601
|
wildcardMatcherMeansAll: true
|
|
22494
22602
|
}
|
|
22495
22603
|
};
|
|
@@ -22500,10 +22608,13 @@ const BOB_SPEC = {
|
|
|
22500
22608
|
* `<project>/.bob/settings.json` (project scope) and
|
|
22501
22609
|
* `~/.bob/settings/settings.json` (user scope) — in the Claude-Code shape:
|
|
22502
22610
|
* `{ "<Event>": [{ "matcher"?: "<regex>", "hooks": [{ "type": "command",
|
|
22503
|
-
* "command": "...", "timeout"?: <seconds> }] }] }
|
|
22504
|
-
*
|
|
22505
|
-
*
|
|
22611
|
+
* "command": "...", "timeout"?: <seconds> }] }] }`, where a handler may
|
|
22612
|
+
* instead be `{ "type": "https", "url": "...", "timeout"?: <seconds> }`. The
|
|
22613
|
+
* file also holds settings rulesync does not own, so generation merges the
|
|
22614
|
+
* `hooks` key into it (see `SHARED_CONFIG_OWNERSHIP`) instead of overwriting
|
|
22615
|
+
* the file.
|
|
22506
22616
|
*
|
|
22617
|
+
* @see https://bob.ibm.com/docs/shell/configuration/lifecycle-hooks
|
|
22507
22618
|
* @see https://bob.ibm.com/docs/ide/configuration/lifecycle-hooks
|
|
22508
22619
|
*/
|
|
22509
22620
|
var BobHooks = class extends SettingsJsonHooks {
|
|
@@ -23933,6 +24044,11 @@ const CORTEXCODE_SPEC = {
|
|
|
23933
24044
|
booleanPassthroughFields: [{
|
|
23934
24045
|
canonical: "enabled",
|
|
23935
24046
|
tool: "enabled"
|
|
24047
|
+
}],
|
|
24048
|
+
objectPassthroughFields: [{
|
|
24049
|
+
canonical: "source",
|
|
24050
|
+
tool: "source",
|
|
24051
|
+
commandOnly: true
|
|
23936
24052
|
}]
|
|
23937
24053
|
}
|
|
23938
24054
|
};
|
|
@@ -23943,8 +24059,9 @@ const CORTEXCODE_SPEC = {
|
|
|
23943
24059
|
* (project scope) and of the dedicated `~/.snowflake/cortex/hooks.json` (user
|
|
23944
24060
|
* scope), both in the Claude-Code shape: `{ "<Event>": [{ "matcher"?:
|
|
23945
24061
|
* "<regex>", "hooks": [{ "type": "command" | "prompt", ..., "timeout"?:
|
|
23946
|
-
* <seconds>, "enabled"?: <boolean
|
|
23947
|
-
* settings rulesync does not own, so generation
|
|
24062
|
+
* <seconds>, "enabled"?: <boolean>, "source"?: { "source", "ref"? } }] }] }`.
|
|
24063
|
+
* The project file also holds settings rulesync does not own, so generation
|
|
24064
|
+
* merges the `hooks` key into
|
|
23948
24065
|
* either file (see `SHARED_CONFIG_OWNERSHIP`) instead of overwriting it, and
|
|
23949
24066
|
* neither file is removed wholesale (hooks.json sits in the CLI-owned
|
|
23950
24067
|
* `~/.snowflake/cortex/` tree).
|
|
@@ -28590,7 +28707,7 @@ const toolHooksFactories = /* @__PURE__ */ new Map([
|
|
|
28590
28707
|
supportsImport: true
|
|
28591
28708
|
},
|
|
28592
28709
|
supportedEvents: BOB_HOOK_EVENTS,
|
|
28593
|
-
supportedHookTypes: ["command"],
|
|
28710
|
+
supportedHookTypes: ["command", "http"],
|
|
28594
28711
|
supportsMatcher: true,
|
|
28595
28712
|
matcherEvents: ["preToolUse", "postToolUse"]
|
|
28596
28713
|
}],
|
|
@@ -31404,6 +31521,50 @@ function parseBobMcpConfig({ fileContent, relativePath }) {
|
|
|
31404
31521
|
/** The `type` Bob IDE writes for a streamable HTTP server. */
|
|
31405
31522
|
const BOB_STREAMABLE_HTTP_TYPE = "streamable-http";
|
|
31406
31523
|
/**
|
|
31524
|
+
* The OAuth keys Bob reads flat on a server entry, next to `oauth` (a
|
|
31525
|
+
* boolean: `true` forces the flow on, `false` off, absent lets Bob detect it).
|
|
31526
|
+
* The canonical shape is Claude Code's nested `oauth: { clientId, ... }`
|
|
31527
|
+
* object, so the two are translated in both directions.
|
|
31528
|
+
* @see https://bob.ibm.com/docs/ide/configuration/mcp/mcp-oauth
|
|
31529
|
+
*/
|
|
31530
|
+
const BOB_FLAT_OAUTH_KEYS = [
|
|
31531
|
+
"clientId",
|
|
31532
|
+
"clientSecret",
|
|
31533
|
+
"scope"
|
|
31534
|
+
];
|
|
31535
|
+
/**
|
|
31536
|
+
* Flatten the canonical `oauth` object onto a Bob server entry: `oauth: true`
|
|
31537
|
+
* plus the string-valued keys Bob documents. A flat key the server already
|
|
31538
|
+
* carries (authored in Bob's own spelling) is kept over the nested one. Other
|
|
31539
|
+
* nested keys (`callbackPort`, `redirectUri`) have no Bob counterpart and are
|
|
31540
|
+
* dropped rather than nested under a key Bob reads as a boolean.
|
|
31541
|
+
*/
|
|
31542
|
+
function flattenOauthForBob({ oauth, converted }) {
|
|
31543
|
+
converted.oauth = true;
|
|
31544
|
+
for (const key of BOB_FLAT_OAUTH_KEYS) {
|
|
31545
|
+
const value = oauth[key];
|
|
31546
|
+
if (typeof value === "string" && converted[key] === void 0) converted[key] = value;
|
|
31547
|
+
}
|
|
31548
|
+
}
|
|
31549
|
+
/**
|
|
31550
|
+
* Reverse of {@link flattenOauthForBob}: gather Bob's flat OAuth keys into the
|
|
31551
|
+
* canonical `oauth` object. `oauth: true` always folds (even with no keys, so
|
|
31552
|
+
* the explicit enable survives the round-trip as an empty object); with no
|
|
31553
|
+
* `oauth` key at all the fold happens only when a flat key is present, since
|
|
31554
|
+
* that is what makes the entry an OAuth one for Bob; `oauth: false` and
|
|
31555
|
+
* anything else leave the entry as it is.
|
|
31556
|
+
*/
|
|
31557
|
+
function nestOauthFromBob(converted) {
|
|
31558
|
+
const flat = BOB_FLAT_OAUTH_KEYS.filter((key) => typeof converted[key] === "string");
|
|
31559
|
+
if (!(converted.oauth === true || converted.oauth === void 0 && flat.length > 0)) return;
|
|
31560
|
+
const oauth = {};
|
|
31561
|
+
for (const key of flat) {
|
|
31562
|
+
oauth[key] = converted[key];
|
|
31563
|
+
delete converted[key];
|
|
31564
|
+
}
|
|
31565
|
+
converted.oauth = oauth;
|
|
31566
|
+
}
|
|
31567
|
+
/**
|
|
31407
31568
|
* The remote transport Bob IDE reads a server as, spelled the way it writes
|
|
31408
31569
|
* it: `streamable-http` needs an explicit `type`, while SSE (legacy) is a bare
|
|
31409
31570
|
* `url` with no `type`. `http` is the canonical rulesync alias for streamable
|
|
@@ -31426,7 +31587,9 @@ function asBobRemoteType(stated, url) {
|
|
|
31426
31587
|
* `headers`, `timeout`, `alwaysAllow` and `disabled` pass through, as Bob
|
|
31427
31588
|
* documents all of them, with prototype-pollution keys dropped at every
|
|
31428
31589
|
* nesting level (Bob spreads `env` and `headers` into the process environment
|
|
31429
|
-
* and the HTTP requests).
|
|
31590
|
+
* and the HTTP requests). The canonical `oauth` object is flattened onto the
|
|
31591
|
+
* entry as `oauth: true` plus `clientId` / `clientSecret` / `scope`, the keys
|
|
31592
|
+
* Bob reads; a boolean `oauth` passes through as Bob's own on/off switch.
|
|
31430
31593
|
*
|
|
31431
31594
|
* Bob Shell documents the same file with an `httpURL` key instead of
|
|
31432
31595
|
* `type` + `url` for streamable HTTP. rulesync writes the IDE spelling (the two
|
|
@@ -31492,10 +31655,16 @@ function convertToBobFormat(mcpServers, logger) {
|
|
|
31492
31655
|
converted.command = command;
|
|
31493
31656
|
if (args.length > 0) converted.args = args;
|
|
31494
31657
|
}
|
|
31495
|
-
|
|
31658
|
+
const { oauth, ...passthrough } = rest;
|
|
31659
|
+
for (const [key, value] of Object.entries(passthrough)) {
|
|
31496
31660
|
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
31497
31661
|
converted[key] = omitPrototypePollutionKeysDeep(value);
|
|
31498
31662
|
}
|
|
31663
|
+
if (isRecord$1(oauth)) flattenOauthForBob({
|
|
31664
|
+
oauth,
|
|
31665
|
+
converted
|
|
31666
|
+
});
|
|
31667
|
+
else if (oauth !== void 0) converted.oauth = oauth;
|
|
31499
31668
|
result[serverName] = converted;
|
|
31500
31669
|
}
|
|
31501
31670
|
return result;
|
|
@@ -31505,9 +31674,10 @@ function convertToBobFormat(mcpServers, logger) {
|
|
|
31505
31674
|
* (`type: "streamable-http"` + `url`) is already canonical and passes through;
|
|
31506
31675
|
* the Bob Shell spelling `httpURL` becomes `url` with `type: "http"`; a bare
|
|
31507
31676
|
* `url` is an SSE server in Bob, so it gains `type: "sse"` to keep that reading
|
|
31508
|
-
* on the next generate.
|
|
31509
|
-
*
|
|
31510
|
-
*
|
|
31677
|
+
* on the next generate. Bob's flat OAuth keys are gathered back into the
|
|
31678
|
+
* canonical `oauth` object (see {@link nestOauthFromBob}). Every other field
|
|
31679
|
+
* passes through with its prototype-pollution keys dropped at every nesting
|
|
31680
|
+
* level, mirroring the generate side's handling of `env` / `headers`.
|
|
31511
31681
|
*/
|
|
31512
31682
|
function convertFromBobFormat(mcpServers) {
|
|
31513
31683
|
if (!isMcpServers(mcpServers)) return {};
|
|
@@ -31528,6 +31698,7 @@ function convertFromBobFormat(mcpServers) {
|
|
|
31528
31698
|
converted.url = httpURL;
|
|
31529
31699
|
converted.type = "http";
|
|
31530
31700
|
} else if (typeof converted.url === "string" && converted.type === void 0) converted.type = "sse";
|
|
31701
|
+
nestOauthFromBob(converted);
|
|
31531
31702
|
result[serverName] = converted;
|
|
31532
31703
|
}
|
|
31533
31704
|
return result;
|
|
@@ -32552,7 +32723,10 @@ function asContinueRemoteType(stated, url) {
|
|
|
32552
32723
|
* file with a strict union — one server that matches neither shape (an
|
|
32553
32724
|
* unknown transport, a non-string `env` value) makes Continue drop every
|
|
32554
32725
|
* server in the file — so only the documented keys are emitted and anything
|
|
32555
|
-
* else
|
|
32726
|
+
* else is left out. The canonical keys a user would expect to take effect
|
|
32727
|
+
* (`cwd`, `timeout`, `oauth`) are dropped with a warning, since the JSON
|
|
32728
|
+
* schema has no place for them (the YAML block form does, but Rulesync writes
|
|
32729
|
+
* the JSON file); rulesync-only fields are dropped silently. `envFile` is
|
|
32556
32730
|
* accepted by Continue's schema but ignored with a warning at load time, so
|
|
32557
32731
|
* it is dropped here with a warning instead of being written as if it worked.
|
|
32558
32732
|
*
|
|
@@ -32588,6 +32762,17 @@ function convertToContinueFormat(mcpServers, logger) {
|
|
|
32588
32762
|
}
|
|
32589
32763
|
return result;
|
|
32590
32764
|
}
|
|
32765
|
+
/**
|
|
32766
|
+
* Warn for each canonical key Continue's JSON MCP schema cannot carry, so a
|
|
32767
|
+
* dropped `cwd`, `timeout` or `oauth` does not go unnoticed in a config that
|
|
32768
|
+
* otherwise looks complete.
|
|
32769
|
+
*/
|
|
32770
|
+
function warnUnsupportedContinueKeys({ serverName, serverConfig, keys, logger }) {
|
|
32771
|
+
for (const key of keys) {
|
|
32772
|
+
if (serverConfig[key] === void 0) continue;
|
|
32773
|
+
logger?.warn(`Continue's MCP config has no "${key}" field, so the ${key} of server ${quoteValueForWarning(serverName)} was not written.`);
|
|
32774
|
+
}
|
|
32775
|
+
}
|
|
32591
32776
|
function convertRemoteServer({ serverName, serverConfig, logger }) {
|
|
32592
32777
|
const url = resolveRemoteMcpUrl(serverConfig);
|
|
32593
32778
|
if (!url) {
|
|
@@ -32615,6 +32800,12 @@ function convertRemoteServer({ serverName, serverConfig, logger }) {
|
|
|
32615
32800
|
url
|
|
32616
32801
|
};
|
|
32617
32802
|
if (isRecord$1(serverConfig.headers)) converted.headers = omitPrototypePollutionKeys(serverConfig.headers);
|
|
32803
|
+
warnUnsupportedContinueKeys({
|
|
32804
|
+
serverName,
|
|
32805
|
+
serverConfig,
|
|
32806
|
+
keys: ["timeout", "oauth"],
|
|
32807
|
+
logger
|
|
32808
|
+
});
|
|
32618
32809
|
return converted;
|
|
32619
32810
|
}
|
|
32620
32811
|
function convertStdioServer({ serverName, serverConfig, logger }) {
|
|
@@ -32635,6 +32826,12 @@ function convertStdioServer({ serverName, serverConfig, logger }) {
|
|
|
32635
32826
|
if (args.length > 0) converted.args = args;
|
|
32636
32827
|
if (isRecord$1(serverConfig.env)) converted.env = omitPrototypePollutionKeys(serverConfig.env);
|
|
32637
32828
|
if (typeof serverConfig.envFile === "string") logger?.warn(`Continue ignores "envFile" for MCP servers, so the envFile of server ${quoteValueForWarning(serverName)} was not written; put the variables in "env" instead.`);
|
|
32829
|
+
warnUnsupportedContinueKeys({
|
|
32830
|
+
serverName,
|
|
32831
|
+
serverConfig,
|
|
32832
|
+
keys: ["cwd", "timeout"],
|
|
32833
|
+
logger
|
|
32834
|
+
});
|
|
32638
32835
|
return converted;
|
|
32639
32836
|
}
|
|
32640
32837
|
/**
|
|
@@ -45133,6 +45330,27 @@ const DEEPAGENTS_EXTENSION_TRUST_POLICIES = [
|
|
|
45133
45330
|
* @see https://github.com/langchain-ai/deepagents `config_manifest.py`
|
|
45134
45331
|
*/
|
|
45135
45332
|
const DEEPAGENTS_EXTENSIONS_ENABLED_DEFAULT = true;
|
|
45333
|
+
/**
|
|
45334
|
+
* `[mcp]` holds dcode's per-server trust for the MCP servers a project's
|
|
45335
|
+
* `.mcp.json` / `.deepagents/.mcp.json` declares. `load_mcp_server_trust_lists`
|
|
45336
|
+
* reads it from the user-level `config.toml` only — never from a project file —
|
|
45337
|
+
* so the global adapter is the one place rulesync can author it.
|
|
45338
|
+
*/
|
|
45339
|
+
const MCP_TABLE_KEY = "mcp";
|
|
45340
|
+
/**
|
|
45341
|
+
* Keys lifted back into the override on import. `disabled_project_servers` is
|
|
45342
|
+
* the deny list: a name on it is always rejected, over any approval or trust.
|
|
45343
|
+
*/
|
|
45344
|
+
const DEEPAGENTS_MCP_KEYS = ["disabled_project_servers"];
|
|
45345
|
+
const MCP_DISABLED_PROJECT_SERVERS_KEY = "disabled_project_servers";
|
|
45346
|
+
/**
|
|
45347
|
+
* dcode's own store of the project servers the user approved at the prompt,
|
|
45348
|
+
* each bound to a repository or worktree and a definition fingerprint. It is
|
|
45349
|
+
* machine-local state and a way to pre-approve a project's servers, so a
|
|
45350
|
+
* repository's `.rulesync/permissions.jsonc` must not reach it: generate drops
|
|
45351
|
+
* the key here, and import never lifts it (`DEEPAGENTS_MCP_KEYS`).
|
|
45352
|
+
*/
|
|
45353
|
+
const MCP_APPROVALS_KEY = "enabled_project_server_approvals";
|
|
45136
45354
|
const ALLOW_ALL_SENTINEL = "all";
|
|
45137
45355
|
const RECOMMENDED_SENTINEL = "recommended";
|
|
45138
45356
|
const GLOB_CHARACTERS_PATTERN = /[*?[\]]/;
|
|
@@ -45205,7 +45423,9 @@ const TRAILING_ARGUMENT_WILDCARD_PATTERN = /:\*$/;
|
|
|
45205
45423
|
* lifted back into the override on import. The same override carries
|
|
45206
45424
|
* `[extensions].enabled` and `[extensions].trust` (`ask` / `always` / `never`),
|
|
45207
45425
|
* which decide whether the Python in a checked-out project's
|
|
45208
|
-
* `.deepagents/extensions/` is imported into the agent process
|
|
45426
|
+
* `.deepagents/extensions/` is imported into the agent process, and
|
|
45427
|
+
* `[mcp].disabled_project_servers`, the names of project MCP servers dcode
|
|
45428
|
+
* always rejects.
|
|
45209
45429
|
*
|
|
45210
45430
|
* On **import** the allowlist comes back as `bash` `allow` rules named by the
|
|
45211
45431
|
* executable — skipping any entry dcode could not match in the first place, so
|
|
@@ -45303,17 +45523,9 @@ var DeepagentsPermissions = class DeepagentsPermissions extends ToolPermissions
|
|
|
45303
45523
|
if (Object.keys(shell).length > 0) settings[SHELL_TABLE_KEY] = shell;
|
|
45304
45524
|
else delete settings[SHELL_TABLE_KEY];
|
|
45305
45525
|
}
|
|
45306
|
-
|
|
45307
|
-
if (isPlainObject$1(startupOverride) && Object.keys(startupOverride).length > 0) mergeStartupOverride({
|
|
45526
|
+
mergeDeepagentsOverrides({
|
|
45308
45527
|
settings,
|
|
45309
|
-
|
|
45310
|
-
filePath,
|
|
45311
|
-
logger
|
|
45312
|
-
});
|
|
45313
|
-
const extensionsOverride = config.deepagents?.extensions;
|
|
45314
|
-
if (isPlainObject$1(extensionsOverride) && Object.keys(extensionsOverride).length > 0) mergeExtensionsOverride({
|
|
45315
|
-
settings,
|
|
45316
|
-
extensionsOverride,
|
|
45528
|
+
override: config.deepagents,
|
|
45317
45529
|
filePath,
|
|
45318
45530
|
logger
|
|
45319
45531
|
});
|
|
@@ -45345,10 +45557,15 @@ var DeepagentsPermissions = class DeepagentsPermissions extends ToolPermissions
|
|
|
45345
45557
|
extensions: isPlainObject$1(settings[EXTENSIONS_TABLE_KEY]) ? settings[EXTENSIONS_TABLE_KEY] : {},
|
|
45346
45558
|
selfPath
|
|
45347
45559
|
});
|
|
45560
|
+
const mcpOverride = liftMcpOverride({
|
|
45561
|
+
mcp: isPlainObject$1(settings[MCP_TABLE_KEY]) ? settings[MCP_TABLE_KEY] : {},
|
|
45562
|
+
selfPath
|
|
45563
|
+
});
|
|
45348
45564
|
const result = { ...config };
|
|
45349
45565
|
const deepagents = {};
|
|
45350
45566
|
if (Object.keys(startupOverride).length > 0) deepagents.startup = startupOverride;
|
|
45351
45567
|
if (Object.keys(extensionsOverride).length > 0) deepagents.extensions = extensionsOverride;
|
|
45568
|
+
if (Object.keys(mcpOverride).length > 0) deepagents.mcp = mcpOverride;
|
|
45352
45569
|
if (Object.keys(deepagents).length > 0) result.deepagents = deepagents;
|
|
45353
45570
|
return RulesyncPermissions.fromImportedFileContent({
|
|
45354
45571
|
outputRoot: getDeepagentsRulesyncOutputRoot({
|
|
@@ -45456,7 +45673,7 @@ function warnAboutUnwrittenBashRules({ allowAll, requestedAllowAll, askPatterns,
|
|
|
45456
45673
|
* read — a wrapper rather than the bare value, so a legitimately falsy setting
|
|
45457
45674
|
* is not mistaken for a rejection.
|
|
45458
45675
|
*/
|
|
45459
|
-
function liftOverrideTable({ table, tableKey, keys, normalize, selfPath }) {
|
|
45676
|
+
function liftOverrideTable({ table, tableKey, keys, normalize, selfPath, describeRejection = `deepagents-cli falls back to its own default for a '[${tableKey}]' value it cannot read` }) {
|
|
45460
45677
|
const override = {};
|
|
45461
45678
|
const rejected = [];
|
|
45462
45679
|
for (const key of keys) {
|
|
@@ -45469,7 +45686,7 @@ function liftOverrideTable({ table, tableKey, keys, normalize, selfPath }) {
|
|
|
45469
45686
|
if (normalized) override[key] = normalized.value;
|
|
45470
45687
|
else rejected.push(`${key} = ${JSON.stringify(value)}`);
|
|
45471
45688
|
}
|
|
45472
|
-
if (rejected.length > 0) warnWithFallback(void 0,
|
|
45689
|
+
if (rejected.length > 0) warnWithFallback(void 0, `${describeRejection}, so ${rejected.join(", ")} in ${selfPath} ${rejected.length === 1 ? "was" : "were"} not imported.`);
|
|
45473
45690
|
return override;
|
|
45474
45691
|
}
|
|
45475
45692
|
/**
|
|
@@ -45517,6 +45734,37 @@ function liftExtensionsOverride({ extensions, selfPath }) {
|
|
|
45517
45734
|
});
|
|
45518
45735
|
}
|
|
45519
45736
|
/**
|
|
45737
|
+
* Read a `[mcp]` name list the way `_toml_str_list` reads it: a bare string
|
|
45738
|
+
* is split on commas, names are trimmed and empty ones dropped, and a
|
|
45739
|
+
* non-string element of a list is dropped while the names around it survive.
|
|
45740
|
+
* Anything else (a number, a table, a bool) is a value dcode cannot read as
|
|
45741
|
+
* names at all, so `null` says to leave it behind.
|
|
45742
|
+
*/
|
|
45743
|
+
function readMcpServerNames(value) {
|
|
45744
|
+
if (typeof value === "string") return value.split(",").map((name) => name.trim()).filter((name) => name.length > 0);
|
|
45745
|
+
if (!Array.isArray(value)) return null;
|
|
45746
|
+
return value.filter((name) => typeof name === "string").map((name) => name.trim()).filter((name) => name.length > 0);
|
|
45747
|
+
}
|
|
45748
|
+
/**
|
|
45749
|
+
* Lift the `[mcp]` keys rulesync models back into the `deepagents` override.
|
|
45750
|
+
* The deny list comes back as the array dcode resolves it to, so the
|
|
45751
|
+
* comma-separated string form it also accepts does not survive as one bogus
|
|
45752
|
+
* name in a permissions file the canonical schema types as `string[]`.
|
|
45753
|
+
*/
|
|
45754
|
+
function liftMcpOverride({ mcp, selfPath }) {
|
|
45755
|
+
return liftOverrideTable({
|
|
45756
|
+
table: mcp,
|
|
45757
|
+
tableKey: MCP_TABLE_KEY,
|
|
45758
|
+
keys: DEEPAGENTS_MCP_KEYS,
|
|
45759
|
+
normalize: ({ value }) => {
|
|
45760
|
+
const names = readMcpServerNames(value);
|
|
45761
|
+
return names ? { value: names } : null;
|
|
45762
|
+
},
|
|
45763
|
+
selfPath,
|
|
45764
|
+
describeRejection: `deepagents-cli treats a '[${MCP_TABLE_KEY}]' value it cannot read as a broken trust policy and rejects every project MCP server until it is fixed`
|
|
45765
|
+
});
|
|
45766
|
+
}
|
|
45767
|
+
/**
|
|
45520
45768
|
* Merge one block of the `deepagents` override into its `config.toml` table,
|
|
45521
45769
|
* preserving every other key of that table. A table that is not a table at all
|
|
45522
45770
|
* is something rulesync did not write and cannot merge into, so it is left
|
|
@@ -45565,6 +45813,38 @@ function warnAboutUncheckedKeys({ tableKey, knownKeys, writtenKeys, filePath, lo
|
|
|
45565
45813
|
if (unknownKeys.length === 0) return;
|
|
45566
45814
|
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.`);
|
|
45567
45815
|
}
|
|
45816
|
+
/** An override block with something in it to write. */
|
|
45817
|
+
function isSet(block) {
|
|
45818
|
+
return isPlainObject$1(block) && Object.keys(block).length > 0;
|
|
45819
|
+
}
|
|
45820
|
+
/**
|
|
45821
|
+
* Merge each block of the `deepagents` override into its `config.toml` table.
|
|
45822
|
+
* A block that is absent, not a table, or empty has nothing to write and is
|
|
45823
|
+
* skipped without touching the table it would have gone into.
|
|
45824
|
+
*/
|
|
45825
|
+
function mergeDeepagentsOverrides({ settings, override, filePath, logger }) {
|
|
45826
|
+
const startupOverride = override?.startup;
|
|
45827
|
+
if (isSet(startupOverride)) mergeStartupOverride({
|
|
45828
|
+
settings,
|
|
45829
|
+
startupOverride,
|
|
45830
|
+
filePath,
|
|
45831
|
+
logger
|
|
45832
|
+
});
|
|
45833
|
+
const extensionsOverride = override?.extensions;
|
|
45834
|
+
if (isSet(extensionsOverride)) mergeExtensionsOverride({
|
|
45835
|
+
settings,
|
|
45836
|
+
extensionsOverride,
|
|
45837
|
+
filePath,
|
|
45838
|
+
logger
|
|
45839
|
+
});
|
|
45840
|
+
const mcpOverride = override?.mcp;
|
|
45841
|
+
if (isSet(mcpOverride)) mergeMcpOverride({
|
|
45842
|
+
settings,
|
|
45843
|
+
mcpOverride,
|
|
45844
|
+
filePath,
|
|
45845
|
+
logger
|
|
45846
|
+
});
|
|
45847
|
+
}
|
|
45568
45848
|
/**
|
|
45569
45849
|
* Merge the `deepagents.startup` override into `[startup]`.
|
|
45570
45850
|
*/
|
|
@@ -45598,6 +45878,40 @@ function mergeExtensionsOverride({ settings, extensionsOverride, filePath, logge
|
|
|
45598
45878
|
});
|
|
45599
45879
|
}
|
|
45600
45880
|
/**
|
|
45881
|
+
* Merge the `deepagents.mcp` override into `[mcp]`. The approval store is
|
|
45882
|
+
* dropped (see `MCP_APPROVALS_KEY`); the deprecated flat
|
|
45883
|
+
* `enabled_project_servers` is not modeled but passes through like any other
|
|
45884
|
+
* unknown key, named by the unchecked-key warning — dcode ignores it anyway.
|
|
45885
|
+
*/
|
|
45886
|
+
function mergeMcpOverride({ settings, mcpOverride, filePath, logger }) {
|
|
45887
|
+
mergeOverrideTable({
|
|
45888
|
+
settings,
|
|
45889
|
+
tableKey: MCP_TABLE_KEY,
|
|
45890
|
+
override: mcpOverride,
|
|
45891
|
+
knownKeys: DEEPAGENTS_MCP_KEYS,
|
|
45892
|
+
isDroppedKey: (key) => key === MCP_APPROVALS_KEY,
|
|
45893
|
+
warnAboutRelaxations: warnAboutMcpRelaxations,
|
|
45894
|
+
filePath,
|
|
45895
|
+
logger
|
|
45896
|
+
});
|
|
45897
|
+
}
|
|
45898
|
+
/**
|
|
45899
|
+
* Warn when the `deepagents` mcp override re-enables project MCP servers the
|
|
45900
|
+
* machine's global config had rejected. The deny list is written as a whole,
|
|
45901
|
+
* so a shorter list from a repository's `.rulesync/permissions.jsonc` would
|
|
45902
|
+
* otherwise silently lift a rejection the user had put in place — the very
|
|
45903
|
+
* fail-open dcode's own env merge refuses to allow.
|
|
45904
|
+
*/
|
|
45905
|
+
function warnAboutMcpRelaxations({ override, previous, filePath, logger }) {
|
|
45906
|
+
if (override[MCP_APPROVALS_KEY] !== void 0) warnWithFallback(logger, `The deepagents mcp override's '${MCP_APPROVALS_KEY}' was not written to ${filePath}: dcode builds that approval store itself from the project MCP servers you accept at launch, so a permissions file cannot pre-approve them.`);
|
|
45907
|
+
const written = override[MCP_DISABLED_PROJECT_SERVERS_KEY];
|
|
45908
|
+
if (written === void 0 || written === null) return;
|
|
45909
|
+
const kept = new Set(readMcpServerNames(written) ?? []);
|
|
45910
|
+
const reEnabled = (readMcpServerNames(previous[MCP_DISABLED_PROJECT_SERVERS_KEY]) ?? []).filter((name) => !kept.has(name));
|
|
45911
|
+
if (reEnabled.length === 0) return;
|
|
45912
|
+
warnWithFallback(logger, `The deepagents mcp override removed ${reEnabled.map((name) => JSON.stringify(name)).join(", ")} from [${MCP_TABLE_KEY}].${MCP_DISABLED_PROJECT_SERVERS_KEY} in ${filePath}, which is your global deepagents-cli config: dcode no longer rejects ${reEnabled.length === 1 ? "that project MCP server" : "those project MCP servers"} outright, for every project on this machine, not just this one.`);
|
|
45913
|
+
}
|
|
45914
|
+
/**
|
|
45601
45915
|
* Name the value an override key replaces, so a setting the user had turned
|
|
45602
45916
|
* down is visible as such rather than reported as a bare new value.
|
|
45603
45917
|
*/
|
|
@@ -57350,7 +57664,12 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
57350
57664
|
//#region src/features/skills/commandcode-skill.ts
|
|
57351
57665
|
const CommandcodeSkillFrontmatterSchema = z.looseObject({
|
|
57352
57666
|
name: z.string(),
|
|
57353
|
-
description: z.string()
|
|
57667
|
+
description: z.string(),
|
|
57668
|
+
license: z.optional(z.string()),
|
|
57669
|
+
compatibility: z.optional(z.union([z.string(), z.looseObject({})])),
|
|
57670
|
+
metadata: z.optional(z.looseObject({})),
|
|
57671
|
+
"disable-model-invocation": z.optional(z.boolean()),
|
|
57672
|
+
"user-invocable": z.optional(z.boolean())
|
|
57354
57673
|
});
|
|
57355
57674
|
/**
|
|
57356
57675
|
* Represents a Command Code skill directory.
|
|
@@ -57433,10 +57752,35 @@ var CommandcodeSkill = class CommandcodeSkill extends ToolSkill {
|
|
|
57433
57752
|
const settablePaths = CommandcodeSkill.getSettablePaths({ global });
|
|
57434
57753
|
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
|
|
57435
57754
|
const { name: _sectionName, description: _sectionDescription, ...commandcodeSection } = rulesyncFrontmatter.commandcode ?? {};
|
|
57755
|
+
const license = resolveLicense({
|
|
57756
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
57757
|
+
section: commandcodeSection
|
|
57758
|
+
});
|
|
57759
|
+
const compatibility = resolveCompatibility({
|
|
57760
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
57761
|
+
section: commandcodeSection
|
|
57762
|
+
});
|
|
57763
|
+
const metadata = resolveMetadata({
|
|
57764
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
57765
|
+
section: commandcodeSection
|
|
57766
|
+
});
|
|
57767
|
+
const disableModelInvocation = resolveDisableModelInvocation({
|
|
57768
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
57769
|
+
section: commandcodeSection
|
|
57770
|
+
});
|
|
57771
|
+
const userInvocable = resolveUserInvocable({
|
|
57772
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
57773
|
+
section: commandcodeSection
|
|
57774
|
+
});
|
|
57436
57775
|
const commandcodeFrontmatter = {
|
|
57437
57776
|
...commandcodeSection,
|
|
57438
57777
|
name: rulesyncFrontmatter.name,
|
|
57439
|
-
description: rulesyncFrontmatter.description
|
|
57778
|
+
description: rulesyncFrontmatter.description,
|
|
57779
|
+
...license !== void 0 && { license },
|
|
57780
|
+
...compatibility !== void 0 && { compatibility },
|
|
57781
|
+
...metadata !== void 0 && { metadata },
|
|
57782
|
+
...disableModelInvocation !== void 0 && { "disable-model-invocation": disableModelInvocation },
|
|
57783
|
+
...userInvocable !== void 0 && { "user-invocable": userInvocable }
|
|
57440
57784
|
};
|
|
57441
57785
|
return new CommandcodeSkill({
|
|
57442
57786
|
outputRoot,
|
|
@@ -64809,6 +65153,35 @@ const CommandcodeSubagentFrontmatterSchema = z.looseObject({
|
|
|
64809
65153
|
showOutput: z.optional(z.boolean())
|
|
64810
65154
|
});
|
|
64811
65155
|
/**
|
|
65156
|
+
* Names Command Code's built-in agents own. The loader runs the frontmatter
|
|
65157
|
+
* `name` (or the file stem when it has none) through `sanitizeAgentName`,
|
|
65158
|
+
* which rewrites every character outside `[a-zA-Z0-9_-]` to `_`, lowercases
|
|
65159
|
+
* it, and skips the file outright when the result is one of these
|
|
65160
|
+
* (`isReservedAgentName`) — with no message. Verified in the `command-code`
|
|
65161
|
+
* 1.54.2 bundle.
|
|
65162
|
+
* @see https://commandcode.ai/docs/agents
|
|
65163
|
+
*/
|
|
65164
|
+
const COMMANDCODE_RESERVED_AGENT_NAMES = /* @__PURE__ */ new Set([
|
|
65165
|
+
"explore",
|
|
65166
|
+
"plan",
|
|
65167
|
+
"review",
|
|
65168
|
+
"general"
|
|
65169
|
+
]);
|
|
65170
|
+
/** The name Command Code compares against its reserved list. */
|
|
65171
|
+
function toCommandcodeAgentName(name) {
|
|
65172
|
+
return name.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase();
|
|
65173
|
+
}
|
|
65174
|
+
/**
|
|
65175
|
+
* The subagent is still generated under the reserved name — the name is the
|
|
65176
|
+
* user's to change, and a rename here would make it diverge from the other
|
|
65177
|
+
* targets — but Command Code would drop it without a visible word, so say so
|
|
65178
|
+
* now (the same courtesy `VibeSkill` extends to its reserved skill names).
|
|
65179
|
+
*/
|
|
65180
|
+
function warnAboutReservedAgentName({ name, relativeFilePath, logger }) {
|
|
65181
|
+
if (!COMMANDCODE_RESERVED_AGENT_NAMES.has(toCommandcodeAgentName(name))) return;
|
|
65182
|
+
logger?.warn(`Command Code subagent ${relativeFilePath}: the name ${quoteValueForWarning(name)} is reserved for a Command Code built-in agent, so Command Code ignores a custom agent by that name when it loads agents. Rename the subagent for it to be available in Command Code.`);
|
|
65183
|
+
}
|
|
65184
|
+
/**
|
|
64812
65185
|
* Command Code custom agent: a Markdown file with YAML frontmatter under
|
|
64813
65186
|
* `.commandcode/agents/` (project) or `~/.commandcode/agents/` (user); the
|
|
64814
65187
|
* body is the agent's system prompt.
|
|
@@ -64855,7 +65228,7 @@ var CommandcodeSubagent = class CommandcodeSubagent extends ToolSubagent {
|
|
|
64855
65228
|
validate: true
|
|
64856
65229
|
});
|
|
64857
65230
|
}
|
|
64858
|
-
static fromRulesyncSubagent({ outputRoot = process.cwd(), rulesyncSubagent, validate = true, global = false }) {
|
|
65231
|
+
static fromRulesyncSubagent({ outputRoot = process.cwd(), rulesyncSubagent, validate = true, global = false, logger }) {
|
|
64859
65232
|
const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
|
|
64860
65233
|
const commandcodeSection = rulesyncFrontmatter.commandcode ?? {};
|
|
64861
65234
|
const commandcodeSubagentFrontmatter = {
|
|
@@ -64863,6 +65236,11 @@ var CommandcodeSubagent = class CommandcodeSubagent extends ToolSubagent {
|
|
|
64863
65236
|
description: rulesyncFrontmatter.description,
|
|
64864
65237
|
...commandcodeSection
|
|
64865
65238
|
};
|
|
65239
|
+
warnAboutReservedAgentName({
|
|
65240
|
+
name: commandcodeSubagentFrontmatter.name,
|
|
65241
|
+
relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
|
|
65242
|
+
logger
|
|
65243
|
+
});
|
|
64866
65244
|
const body = rulesyncSubagent.getBody();
|
|
64867
65245
|
const fileContent = stringifyFrontmatter(body, commandcodeSubagentFrontmatter, { avoidBlockScalars: true });
|
|
64868
65246
|
const paths = this.getSettablePaths({ global });
|
|
@@ -71235,8 +71613,12 @@ var CodebuddyRule = class CodebuddyRule extends ToolRule {
|
|
|
71235
71613
|
* | `false` | none | not supported; the rule is dropped |
|
|
71236
71614
|
*
|
|
71237
71615
|
* The default being `true` is the opposite of Cursor, which the adapter was
|
|
71238
|
-
* modeled on
|
|
71239
|
-
*
|
|
71616
|
+
* modeled on. The shipped loader (`@tencent-ai/codebuddy-code` 2.151.0,
|
|
71617
|
+
* `dist/codebuddy.js`) is looser than the table — it resolves
|
|
71618
|
+
* `alwaysApply = fm.alwaysApply === true || (!hasPaths && fm.alwaysApply !== false)`,
|
|
71619
|
+
* so `paths` without `alwaysApply` is already MANUAL — but the explicit
|
|
71620
|
+
* `alwaysApply: false` is written anyway: it is correct under both readings
|
|
71621
|
+
* and the documented one is what a reader of the file goes by.
|
|
71240
71622
|
*
|
|
71241
71623
|
* @see https://www.codebuddy.ai/docs/cli/memory
|
|
71242
71624
|
*/
|
|
@@ -71311,9 +71693,9 @@ var CodebuddyRule = class CodebuddyRule extends ToolRule {
|
|
|
71311
71693
|
});
|
|
71312
71694
|
}
|
|
71313
71695
|
const sourcePaths = normalizeCodebuddyPaths(this.frontmatter.paths) ?? [];
|
|
71314
|
-
const isAlways = this.frontmatter.alwaysApply !== false;
|
|
71696
|
+
const isAlways = this.frontmatter.alwaysApply === true || sourcePaths.length === 0 && this.frontmatter.alwaysApply !== false;
|
|
71315
71697
|
const globs = sourcePaths.length === 0 && isAlways ? ["**/*"] : sourcePaths;
|
|
71316
|
-
const alwaysApply = this.frontmatter.alwaysApply
|
|
71698
|
+
const alwaysApply = this.frontmatter.alwaysApply;
|
|
71317
71699
|
const rulesyncFrontmatter = {
|
|
71318
71700
|
targets,
|
|
71319
71701
|
root: false,
|
|
@@ -76004,6 +76386,15 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
76004
76386
|
collisionPolicy: "fold"
|
|
76005
76387
|
}
|
|
76006
76388
|
}],
|
|
76389
|
+
["pool", {
|
|
76390
|
+
class: PoolRule,
|
|
76391
|
+
meta: {
|
|
76392
|
+
extension: "md",
|
|
76393
|
+
supportsGlobal: true,
|
|
76394
|
+
ruleDiscoveryMode: "auto",
|
|
76395
|
+
collisionPolicy: "fold"
|
|
76396
|
+
}
|
|
76397
|
+
}],
|
|
76007
76398
|
["qwencode", {
|
|
76008
76399
|
class: QwencodeRule,
|
|
76009
76400
|
meta: {
|
|
@@ -76127,15 +76518,6 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
76127
76518
|
ruleDiscoveryMode: "auto"
|
|
76128
76519
|
}
|
|
76129
76520
|
}],
|
|
76130
|
-
["pool", {
|
|
76131
|
-
class: PoolRule,
|
|
76132
|
-
meta: {
|
|
76133
|
-
extension: "md",
|
|
76134
|
-
supportsGlobal: true,
|
|
76135
|
-
ruleDiscoveryMode: "auto",
|
|
76136
|
-
collisionPolicy: "fold"
|
|
76137
|
-
}
|
|
76138
|
-
}],
|
|
76139
76521
|
["dsh", {
|
|
76140
76522
|
class: DshRule,
|
|
76141
76523
|
meta: {
|
|
@@ -79321,6 +79703,6 @@ async function importChecksCore(params) {
|
|
|
79321
79703
|
return writtenCount;
|
|
79322
79704
|
}
|
|
79323
79705
|
//#endregion
|
|
79324
|
-
export {
|
|
79706
|
+
export { RulesyncCommand as $, toPosixPath as $t, CLAUDECODE_MEMORIES_DIR_NAME as A, RULESYNC_XDG_CONFIG_HOME_DEFAULT_DIR_NAME as An, checkPathTraversal as At, RulesyncSubagent as B, stripControlCharacters as Bn, listDirectoryEntryNames as Bt, COMMANDCODE_DIR as C, RULESYNC_PERMISSIONS_SCHEMA_URL as Cn, withWarnOnceScope as Ct, CODEXCLI_DIR as D, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as Dn, assertDirectoryIfExists as Dt, CODEXCLI_BASH_RULES_FILE_NAME as E, RULESYNC_SKILLS_RELATIVE_DIR_PATH as En, applyFileMode as Et, caseFoldIdentity as F, formatError as Fn, getFileSize as Ft, RulesyncRuleFrontmatterSchema as G, readFileContentOrNull as Gt, RulesyncSkill as H, stripHiddenCharacters as Hn, listSubdirectoryNames as Ht, groupSpellingsByCaseFoldedIdentity as I, truncateText as In, getHomeDirectory as It, RulesyncIgnore as J, removeFile as Jt, RulesyncPermissions as K, removeDirectory as Kt, AUGMENTCODE_DIR as L, hasDeceptiveHiddenCharacters as Ln, isFileNotFoundError as Lt, CLAUDECODE_SKILLS_DIR_PATH as M, ALL_FEATURES as Mn, directoryExists as Mt, FACTORYDROID_DIR as N, ALL_FEATURES_WITH_WILDCARD as Nn, ensureDir as Nt, CLAUDECODE_DIR as O, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as On, assertTreeContainsNoSymlinks as Ot, FACTORYDROID_SETTINGS_LOCAL_FILE_NAME as P, DEPRECATED_FEATURE_REPLACEMENTS as Pn, fileExists as Pt, parseJsonc as Q, runWithDirectoryRollback as Qt, AUGMENTCODE_SETTINGS_LOCAL_FILE_NAME as R, hasEnclosingMarkOutsideKeycap as Rn, isFileSystemError as Rt, QWENCODE_LOCAL_RULE_FILE_NAME as S, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as Sn, resetRunWarningState as St, ChecksProcessor as T, RULESYNC_RULES_RELATIVE_DIR_PATH as Tn, ErrorCodes as Tt, RulesyncSkillFrontmatterSchema as U, pathEscapesRoot as Ut, RulesyncSubagentFrontmatterSchema as V, stripControlCharactersKeepingLineFeeds as Vn, listFilePathsRecursively as Vt, RulesyncRule as W, readFileContent as Wt, getRulesyncSourceCandidates as X, removeTempDirectory as Xt, RulesyncHooks as Y, removeFileStrict as Yt, resolveRulesyncSourceWritePath as Z, resolvePath as Zt, IgnoreProcessor as _, RULESYNC_IGNORE_RELATIVE_FILE_PATH as _n, JsonLogger as _t, getProcessorRegistryEntry as a, ToolTargetSchema as an, SHARED_USER_MANAGED_CONFIG_PATHS as at, CommandsProcessor as b, RULESYNC_MCP_SCHEMA_URL as bn, warnOnConflictingFlags as bt, RulesProcessor as c, MAX_FILE_SIZE as cn, mergeInputRootConfigs as ct, CODEBUDDY_DIR as d, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as dn, ConfigFileSchema as dt, writeFileBuffer as en, RulesyncCommandFrontmatterSchema as et, CODEBUDDY_LOCAL_RULE_FILE_NAME as f, RULESYNC_CONFIG_RELATIVE_FILE_PATH as fn, GITIGNORE_DESTINATION_KEY as ft, McpProcessor as g, RULESYNC_HOOKS_RELATIVE_FILE_PATH as gn, ConsoleLogger as gt, shortenToWidth as h, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as hn, findControlCharacter as ht, inspectInputRoots as i, PACKAGING_TOOL_TARGETS as in, loadYaml as it, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as j, parseCommaSeparatedList as jn, createTempDirectory as jt, CLAUDECODE_LOCAL_RULE_FILE_NAME as k, RULESYNC_USER_CONFIG_DIR_NAME as kn, assertWritablePathInsideRoot as kt, SubagentsProcessor as l, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as ln, resolveEffectiveInputRoots as lt, displayWidthOf as m, RULESYNC_CURATED_RULES_RELATIVE_DIR_PATH as mn, assertTargetsFeaturesExclusive as mt, formatSourceLoadFailure as n, ALL_TOOL_TARGETS as nn, RulesyncCheckFrontmatterSchema as nt, convertFromTool as o, CURATED_RULES_FEATURE_SUBDIR as on, SKILL_FILE_NAME as ot, ELLIPSIS_WIDTH as p, RULESYNC_CONFIG_SCHEMA_URL as pn, SourceEntrySchema as pt, RulesyncMcp as q, removeDirectoryStrict as qt, generate as r, ALL_TOOL_TARGETS_WITH_WILDCARD as rn, stringifyFrontmatter as rt, isPackagingToolTarget as s, FEATURE_SOURCE_TREE_ENTRIES as sn, ConfigResolver as st, importFromTool as t, writeFileContent as tn, RulesyncCheck as tt, SkillsProcessor as u, RULESYNC_CHECKS_RELATIVE_DIR_PATH as un, CONFLICTING_TARGET_PAIRS as ut, HooksProcessor as v, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as vn, WarningCollectingLogger as vt, COMMANDCODE_SETTINGS_LOCAL_FILE_NAME as w, RULESYNC_RELATIVE_DIR_PATH as wn, CLIError as wt, QWENCODE_DIR as x, RULESYNC_NPM_SOURCES_LOCK_RELATIVE_FILE_PATH as xn, withFallbackLoggerTarget as xt, CRUSH_LOCAL_RULE_FILE_NAME as y, RULESYNC_MCP_RELATIVE_FILE_PATH as yn, fallbackLogger as yt, getLocalSkillDirNames as z, quoteForLog as zn, isSymlink as zt };
|
|
79325
79707
|
|
|
79326
|
-
//# sourceMappingURL=import-
|
|
79708
|
+
//# sourceMappingURL=import-DxRza3o_.js.map
|