rulesync 43.2.0 → 43.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.cjs +274 -66
- package/dist/cli/index.js +274 -66
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-DAT3ge4z.cjs → import-BU6Goa-J.cjs} +415 -108
- package/dist/{import-DPXjeK8q.js → import-D2mUPFM0.js} +416 -109
- package/dist/{import-DPXjeK8q.js.map → import-D2mUPFM0.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +14 -14
|
@@ -5613,11 +5613,28 @@ const POOL_TO_CANONICAL_EVENT_NAMES = invertEventNames(CANONICAL_TO_POOL_EVENT_N
|
|
|
5613
5613
|
/**
|
|
5614
5614
|
* Hook events supported by Crush.
|
|
5615
5615
|
*
|
|
5616
|
-
* Crush
|
|
5617
|
-
*
|
|
5618
|
-
*
|
|
5616
|
+
* Crush v0.99.0 fires 13 events under its `hooks` config block (Claude
|
|
5617
|
+
* Code-compatible payload; `matcher` is a regex on the tool name and is only
|
|
5618
|
+
* accepted on tool events). Twelve of them have a canonical counterpart;
|
|
5619
|
+
* `PermissionResult` has none and is authored under the `crush.hooks`
|
|
5620
|
+
* override.
|
|
5621
|
+
* @see https://github.com/charmbracelet/crush/blob/v0.99.0/docs/hooks/README.md
|
|
5622
|
+
* @see https://github.com/charmbracelet/crush/blob/v0.99.0/internal/hooks/events.go
|
|
5619
5623
|
*/
|
|
5620
|
-
const CRUSH_HOOK_EVENTS = [
|
|
5624
|
+
const CRUSH_HOOK_EVENTS = [
|
|
5625
|
+
"preToolUse",
|
|
5626
|
+
"postToolUse",
|
|
5627
|
+
"postToolUseFailure",
|
|
5628
|
+
"permissionRequest",
|
|
5629
|
+
"sessionStart",
|
|
5630
|
+
"sessionEnd",
|
|
5631
|
+
"beforeSubmitPrompt",
|
|
5632
|
+
"stop",
|
|
5633
|
+
"stopFailure",
|
|
5634
|
+
"stopCancelled",
|
|
5635
|
+
"preCompact",
|
|
5636
|
+
"postCompact"
|
|
5637
|
+
];
|
|
5621
5638
|
/**
|
|
5622
5639
|
* Hook events supported by JetBrains Junie CLI.
|
|
5623
5640
|
*
|
|
@@ -5882,9 +5899,10 @@ const ZCODE_TO_CANONICAL_EVENT_NAMES = invertEventNames(CANONICAL_TO_ZCODE_EVENT
|
|
|
5882
5899
|
* Bob reads `hooks` from `.bob/settings.json` (project) and
|
|
5883
5900
|
* `~/.bob/settings/settings.json` (user) in the Claude-Code shape and fires
|
|
5884
5901
|
* seven events: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse,
|
|
5885
|
-
* PreCompact, PostCompact (
|
|
5886
|
-
* are `command` or `
|
|
5887
|
-
*
|
|
5902
|
+
* PreCompact, PostCompact and Stop (Bob IDE and Bob Shell list the same
|
|
5903
|
+
* seven). Handlers are `command` or `http` hooks. `matcher` is a regex matched
|
|
5904
|
+
* against the tool name on PreToolUse / PostToolUse, `source` on SessionStart
|
|
5905
|
+
* and `trigger` on PreCompact / PostCompact; the other events ignore it.
|
|
5888
5906
|
*
|
|
5889
5907
|
* @see https://bob.ibm.com/docs/shell/configuration/lifecycle-hooks
|
|
5890
5908
|
* @see https://bob.ibm.com/docs/ide/configuration/lifecycle-hooks
|
|
@@ -7066,10 +7084,38 @@ const CANONICAL_TO_CODEWHALE_EVENT_NAMES = {
|
|
|
7066
7084
|
const CODEWHALE_TO_CANONICAL_EVENT_NAMES = invertEventNames(CANONICAL_TO_CODEWHALE_EVENT_NAMES);
|
|
7067
7085
|
/**
|
|
7068
7086
|
* Canonical -> Crush event names. Crush spells its events the Claude Code
|
|
7069
|
-
* way (`PreToolUse`)
|
|
7070
|
-
*
|
|
7087
|
+
* way (`PreToolUse`), but names the turn events `TurnStart` (Claude Code's
|
|
7088
|
+
* `UserPromptSubmit`) and `TurnEnd` (Claude Code's `Stop`), and the
|
|
7089
|
+
* user-cancelled turn `Interrupt`.
|
|
7090
|
+
* @see https://github.com/charmbracelet/crush/blob/v0.99.0/docs/hooks/README.md
|
|
7091
|
+
*/
|
|
7092
|
+
const CANONICAL_TO_CRUSH_EVENT_NAMES = {
|
|
7093
|
+
preToolUse: "PreToolUse",
|
|
7094
|
+
postToolUse: "PostToolUse",
|
|
7095
|
+
postToolUseFailure: "PostToolUseFailure",
|
|
7096
|
+
permissionRequest: "PermissionRequest",
|
|
7097
|
+
sessionStart: "SessionStart",
|
|
7098
|
+
sessionEnd: "SessionEnd",
|
|
7099
|
+
beforeSubmitPrompt: "TurnStart",
|
|
7100
|
+
stop: "TurnEnd",
|
|
7101
|
+
stopFailure: "StopFailure",
|
|
7102
|
+
stopCancelled: "Interrupt",
|
|
7103
|
+
preCompact: "PreCompact",
|
|
7104
|
+
postCompact: "PostCompact"
|
|
7105
|
+
};
|
|
7106
|
+
/**
|
|
7107
|
+
* Crush events that carry a tool call, the only ones whose hooks may set a
|
|
7108
|
+
* `matcher` (Crush's `EventHasTool`). A matcher on any other event makes
|
|
7109
|
+
* Crush reject the whole config at load time.
|
|
7110
|
+
* @see https://github.com/charmbracelet/crush/blob/v0.99.0/internal/config/hooks.go
|
|
7071
7111
|
*/
|
|
7072
|
-
const
|
|
7112
|
+
const CRUSH_TOOL_EVENTS = [
|
|
7113
|
+
"PreToolUse",
|
|
7114
|
+
"PostToolUse",
|
|
7115
|
+
"PostToolUseFailure",
|
|
7116
|
+
"PermissionRequest",
|
|
7117
|
+
"PermissionResult"
|
|
7118
|
+
];
|
|
7073
7119
|
const CRUSH_TO_CANONICAL_EVENT_NAMES = invertEventNames(CANONICAL_TO_CRUSH_EVENT_NAMES);
|
|
7074
7120
|
/**
|
|
7075
7121
|
* Map canonical camelCase event names to Qwen Code PascalCase.
|
|
@@ -7613,14 +7659,18 @@ const toolScopedMcpSchema = z.looseObject({ mcpServers: z.optional(z.record(z.st
|
|
|
7613
7659
|
* server opts out. Per-server `startupTimeoutMs` / `toolTimeoutMs` / `deferred`
|
|
7614
7660
|
* in `mcpServers` still win. `defaultDeferred` only takes effect when Kimi's
|
|
7615
7661
|
* experimental `tool-select` flag is on, and is captured when a server connects
|
|
7616
|
-
* (MoonshotAI/kimi-code#4210).
|
|
7662
|
+
* (MoonshotAI/kimi-code#4210). `reconnectInitialDelayMs` / `reconnectMaxDelayMs`
|
|
7663
|
+
* (Kimi Code 2.4.0) set the first delay and the cap of the automatic reconnect
|
|
7664
|
+
* backoff for workspace-level servers (MoonshotAI/kimi-code#4283).
|
|
7617
7665
|
*
|
|
7618
7666
|
* @see https://moonshotai.github.io/kimi-code/en/configuration/config-files.html#mcp
|
|
7619
7667
|
*/
|
|
7620
7668
|
const kimiCodeScopedMcpSchema = z.extend(toolScopedMcpSchema, {
|
|
7621
7669
|
startupTimeoutMs: z.optional(z.number()),
|
|
7622
7670
|
toolTimeoutMs: z.optional(z.number()),
|
|
7623
|
-
defaultDeferred: z.optional(z.boolean())
|
|
7671
|
+
defaultDeferred: z.optional(z.boolean()),
|
|
7672
|
+
reconnectInitialDelayMs: z.optional(z.int().check(z.nonnegative())),
|
|
7673
|
+
reconnectMaxDelayMs: z.optional(z.int().check(z.nonnegative()))
|
|
7624
7674
|
});
|
|
7625
7675
|
/**
|
|
7626
7676
|
* Qwen Code's tool-scoped block also carries the server-level allow/deny lists
|
|
@@ -11446,6 +11496,7 @@ const piSkillSectionSchema = z.looseObject({
|
|
|
11446
11496
|
});
|
|
11447
11497
|
const antigravitySkillSectionSchema = z.looseObject({
|
|
11448
11498
|
"disable-slash-command": z.optional(z.boolean()),
|
|
11499
|
+
"disable-model-invocation": z.optional(z.boolean()),
|
|
11449
11500
|
metadata: z.optional(z.looseObject({}))
|
|
11450
11501
|
});
|
|
11451
11502
|
const RulesyncSkillFrontmatterSchema = z.looseObject({
|
|
@@ -11646,7 +11697,8 @@ const RulesyncSkillFrontmatterSchema = z.looseObject({
|
|
|
11646
11697
|
license: z.optional(z.string()),
|
|
11647
11698
|
compatibility: z.optional(z.union([z.string(), z.looseObject({})])),
|
|
11648
11699
|
metadata: z.optional(z.looseObject({})),
|
|
11649
|
-
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())]))
|
|
11700
|
+
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())])),
|
|
11701
|
+
"disable-model-invocation": z.optional(z.boolean())
|
|
11650
11702
|
})),
|
|
11651
11703
|
hermesagent: z.optional(z.looseObject({})),
|
|
11652
11704
|
vibe: z.optional(z.looseObject({
|
|
@@ -16204,8 +16256,9 @@ var ToolSkill = class extends AiDir {
|
|
|
16204
16256
|
* {@link AntigravitySharedSkill.getToolTarget}.
|
|
16205
16257
|
*
|
|
16206
16258
|
* Frontmatter beyond `name`/`description` (e.g. `disable-slash-command`,
|
|
16207
|
-
* `metadata`) comes from the rulesync section named
|
|
16208
|
-
* root-level `user-invocable` /
|
|
16259
|
+
* `disable-model-invocation`, `metadata`) comes from the rulesync section named
|
|
16260
|
+
* after that target, with the root-level `user-invocable` /
|
|
16261
|
+
* `disable-model-invocation` / `metadata` as defaults. On the shared project
|
|
16209
16262
|
* `.agents/skills/` tree both targets merge the `antigravity-ide` and
|
|
16210
16263
|
* `antigravity-cli` sections so their output never diverges.
|
|
16211
16264
|
*/
|
|
@@ -16278,6 +16331,8 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
16278
16331
|
const { name: _name, description: _description, ...sectionFields } = section;
|
|
16279
16332
|
const sectionDisableSlashCommand = sectionFields["disable-slash-command"];
|
|
16280
16333
|
const disableSlashCommand = typeof sectionDisableSlashCommand === "boolean" ? sectionDisableSlashCommand : rulesyncFrontmatter["user-invocable"] === false ? true : void 0;
|
|
16334
|
+
const sectionDisableModelInvocation = sectionFields["disable-model-invocation"];
|
|
16335
|
+
const disableModelInvocation = typeof sectionDisableModelInvocation === "boolean" ? sectionDisableModelInvocation : rulesyncFrontmatter["disable-model-invocation"];
|
|
16281
16336
|
const metadata = resolveMetadata({
|
|
16282
16337
|
rootFrontmatter: rulesyncFrontmatter,
|
|
16283
16338
|
section: sectionFields
|
|
@@ -16287,6 +16342,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
16287
16342
|
name: rulesyncFrontmatter.name,
|
|
16288
16343
|
description: rulesyncFrontmatter.description,
|
|
16289
16344
|
...disableSlashCommand !== void 0 && { "disable-slash-command": disableSlashCommand },
|
|
16345
|
+
...disableModelInvocation !== void 0 && { "disable-model-invocation": disableModelInvocation },
|
|
16290
16346
|
...metadata !== void 0 && { metadata }
|
|
16291
16347
|
};
|
|
16292
16348
|
return new this({
|
|
@@ -19600,7 +19656,8 @@ const AgentsSkillsSkillFrontmatterSchema = z.looseObject({
|
|
|
19600
19656
|
license: z.optional(z.string()),
|
|
19601
19657
|
compatibility: z.optional(z.union([z.string(), z.looseObject({})])),
|
|
19602
19658
|
metadata: z.optional(z.looseObject({})),
|
|
19603
|
-
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())]))
|
|
19659
|
+
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())])),
|
|
19660
|
+
"disable-model-invocation": z.optional(z.boolean())
|
|
19604
19661
|
});
|
|
19605
19662
|
const COMPATIBILITY_MAX_LENGTH = 500;
|
|
19606
19663
|
const AGENT_SKILLS_SPEC = "the Agent Skills spec";
|
|
@@ -19741,6 +19798,38 @@ function toSpecConformantAgentSkillFields(section, { coerceMetadata = true } = {
|
|
|
19741
19798
|
...allowedTools !== void 0 && allowedTools.length > 0 && { "allowed-tools": allowedTools }
|
|
19742
19799
|
};
|
|
19743
19800
|
}
|
|
19801
|
+
/**
|
|
19802
|
+
* The opt-in `disable-model-invocation` flag of the `agentsskills` block.
|
|
19803
|
+
*
|
|
19804
|
+
* The key is not part of the Agent Skills specification, so `skills-ref
|
|
19805
|
+
* validate` rejects a `SKILL.md` that carries it, but several clients reading
|
|
19806
|
+
* `.agents/skills/` (e.g. pi) honor it. To keep the default output
|
|
19807
|
+
* spec-conformant, only an explicit `agentsskills.disable-model-invocation`
|
|
19808
|
+
* value is written; the root-level rulesync flag is deliberately not inherited.
|
|
19809
|
+
*
|
|
19810
|
+
* Kept apart from {@link toSpecConformantAgentSkillFields} because that helper
|
|
19811
|
+
* is shared with writers of other tools' own locations, which have their own
|
|
19812
|
+
* sections for tool-specific keys. Only writers of the shared `.agents/skills/`
|
|
19813
|
+
* root (see {@link isSharedAgentSkillsRoot}) — the native target, GitLab Duo's
|
|
19814
|
+
* project scope and the simulated `agentsmd` — spread this, so they all emit
|
|
19815
|
+
* the same frontmatter for that file.
|
|
19816
|
+
*/
|
|
19817
|
+
function toAgentsSkillsInvocationField(section) {
|
|
19818
|
+
const value = section?.["disable-model-invocation"];
|
|
19819
|
+
return value === void 0 ? {} : { "disable-model-invocation": value };
|
|
19820
|
+
}
|
|
19821
|
+
/**
|
|
19822
|
+
* Whether a skill directory lives in the cross-client `.agents/skills/` root
|
|
19823
|
+
* (project, or `~/.agents/skills/` in global scope). The
|
|
19824
|
+
* `agentsskills.disable-model-invocation` opt-in exists for the clients that
|
|
19825
|
+
* read that root, so it is written and imported only there — not by the
|
|
19826
|
+
* subclasses that reuse this class for a tool's own location (Trae, Qoder, Xum,
|
|
19827
|
+
* …), where the key would otherwise leak into the `agentsskills` section on
|
|
19828
|
+
* import and from there into every `.agents/skills/` output.
|
|
19829
|
+
*/
|
|
19830
|
+
function isSharedAgentSkillsRoot(relativeDirPath) {
|
|
19831
|
+
return toPosixPath(relativeDirPath) === toPosixPath(AGENTSMD_SKILLS_DIR_PATH);
|
|
19832
|
+
}
|
|
19744
19833
|
/** The `SKILL.md` a diagnostic should point at, in the scope it is written to. */
|
|
19745
19834
|
function agentSkillFilePath({ outputRoot, relativeDirPath, dirName }) {
|
|
19746
19835
|
return join(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME);
|
|
@@ -19822,7 +19911,8 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
19822
19911
|
...frontmatter.license !== void 0 && { license: frontmatter.license },
|
|
19823
19912
|
...frontmatter.compatibility !== void 0 && { compatibility: frontmatter.compatibility },
|
|
19824
19913
|
...frontmatter.metadata !== void 0 && { metadata: frontmatter.metadata },
|
|
19825
|
-
...allowedTools !== void 0 && allowedTools.length > 0 && { "allowed-tools": allowedTools }
|
|
19914
|
+
...allowedTools !== void 0 && allowedTools.length > 0 && { "allowed-tools": allowedTools },
|
|
19915
|
+
...isSharedAgentSkillsRoot(this.getRelativeDirPath()) && frontmatter["disable-model-invocation"] !== void 0 && { "disable-model-invocation": frontmatter["disable-model-invocation"] }
|
|
19826
19916
|
};
|
|
19827
19917
|
const rulesyncFrontmatter = {
|
|
19828
19918
|
name: frontmatter.name,
|
|
@@ -19848,7 +19938,8 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
19848
19938
|
const agentsSkillsFrontmatter = {
|
|
19849
19939
|
name: rulesyncFrontmatter.name,
|
|
19850
19940
|
description: rulesyncFrontmatter.description,
|
|
19851
|
-
...toSpecConformantAgentSkillFields(resolveAgentsSkillsSection(rulesyncFrontmatter))
|
|
19941
|
+
...toSpecConformantAgentSkillFields(resolveAgentsSkillsSection(rulesyncFrontmatter)),
|
|
19942
|
+
...isSharedAgentSkillsRoot(settablePaths.relativeDirPath) && toAgentsSkillsInvocationField(rulesyncFrontmatter.agentsskills)
|
|
19852
19943
|
};
|
|
19853
19944
|
AgentsSkillsSkill.reportSpecViolations({
|
|
19854
19945
|
outputRoot,
|
|
@@ -24922,7 +25013,8 @@ var AgentsmdSkill = class AgentsmdSkill extends SimulatedSkill {
|
|
|
24922
25013
|
const relativeDirPath = this.getSettablePaths().relativeDirPath;
|
|
24923
25014
|
const frontmatter = {
|
|
24924
25015
|
...defaults.frontmatter,
|
|
24925
|
-
...toSpecConformantAgentSkillFields(resolveAgentsSkillsSection(params.rulesyncSkill.getFrontmatter()))
|
|
25016
|
+
...toSpecConformantAgentSkillFields(resolveAgentsSkillsSection(params.rulesyncSkill.getFrontmatter())),
|
|
25017
|
+
...toAgentsSkillsInvocationField(params.rulesyncSkill.getFrontmatter().agentsskills)
|
|
24926
25018
|
};
|
|
24927
25019
|
AgentsSkillsSkill.reportSpecViolations({
|
|
24928
25020
|
outputRoot: params.outputRoot ?? process.cwd(),
|
|
@@ -31679,16 +31771,17 @@ const VibeSkillFrontmatterSchema = z.looseObject({
|
|
|
31679
31771
|
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())]))
|
|
31680
31772
|
});
|
|
31681
31773
|
/**
|
|
31682
|
-
* Skill names Vibe's built-in skills occupy. `SkillManager`
|
|
31683
|
-
* reserved: a project or user skill whose frontmatter `name`
|
|
31684
|
-
* skipped at load time with only a debug log ("Skipping skill
|
|
31685
|
-
* because builtin skill names are reserved"), so a generated
|
|
31686
|
-
* name is silently never offered.
|
|
31687
|
-
*
|
|
31688
|
-
*
|
|
31689
|
-
*
|
|
31690
|
-
* @see https://github.com/mistralai/mistral-vibe/blob/
|
|
31691
|
-
* @see https://github.com/mistralai/mistral-vibe/blob/
|
|
31774
|
+
* Skill names Vibe's built-in skills occupy. Before v3.0.4, `SkillManager`
|
|
31775
|
+
* treats them as reserved: a project or user skill whose frontmatter `name`
|
|
31776
|
+
* matches one is skipped at load time with only a debug log ("Skipping skill
|
|
31777
|
+
* '<name>' ... because builtin skill names are reserved"), so a generated
|
|
31778
|
+
* skill by that name is silently never offered. v3.0.4 removed
|
|
31779
|
+
* `_reserved_builtins` and that skip ("A user skill named vibe or
|
|
31780
|
+
* skill-creator is no longer silently skipped"), so the warning below is
|
|
31781
|
+
* scoped to older Vibe releases.
|
|
31782
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v3.0.3/vibe/core/skills/manager.py
|
|
31783
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v3.0.4/vibe/core/skills/manager.py
|
|
31784
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v3.0.4/CHANGELOG.md
|
|
31692
31785
|
*/
|
|
31693
31786
|
const VIBE_RESERVED_SKILL_NAMES = /* @__PURE__ */ new Set(["vibe", "skill-creator"]);
|
|
31694
31787
|
/**
|
|
@@ -31731,11 +31824,12 @@ function buildVibeFrontmatter(rulesyncFrontmatter) {
|
|
|
31731
31824
|
/**
|
|
31732
31825
|
* The skill is still generated under the reserved name — the name is the
|
|
31733
31826
|
* user's to change, and a rename here would make it diverge from the other
|
|
31734
|
-
* targets — but Vibe would drop it without a visible word, so
|
|
31827
|
+
* targets — but Vibe before v3.0.4 would drop it without a visible word, so
|
|
31828
|
+
* say so now.
|
|
31735
31829
|
*/
|
|
31736
31830
|
function warnAboutReservedSkillName({ name, logger }) {
|
|
31737
31831
|
if (!VIBE_RESERVED_SKILL_NAMES.has(name)) return;
|
|
31738
|
-
logger?.warn(`Vibe skills: the skill name ${quoteValueForWarning(name)}
|
|
31832
|
+
logger?.warn(`Vibe skills: the skill name ${quoteValueForWarning(name)} matches a Vibe built-in skill. Vibe before v3.0.4 skips a project or user skill by that name when it loads skills; upgrade Vibe to v3.0.4 or later, or rename the skill, for it to be available.`);
|
|
31739
31833
|
}
|
|
31740
31834
|
var VibeSkill = class VibeSkill extends ToolSkill {
|
|
31741
31835
|
constructor({ outputRoot = process.cwd(), relativeDirPath = VibeSkill.getSettablePaths().relativeDirPath, dirName, frontmatter, body, otherFiles = [], validate = true, global = false }) {
|
|
@@ -42703,20 +42797,35 @@ const OPENCODE_KNOWN_SERVER_KEYS = /* @__PURE__ */ new Set([
|
|
|
42703
42797
|
"disabledTools"
|
|
42704
42798
|
]);
|
|
42705
42799
|
function convertFromOpencodeFormat(opencodeMcp, tools, remoteType) {
|
|
42800
|
+
const serverNames = Object.keys(opencodeMcp);
|
|
42706
42801
|
return {
|
|
42707
|
-
...orphanMcpToolFiltersToRulesync(opencodeMcp, tools)
|
|
42802
|
+
...orphanMcpToolFiltersToRulesync(opencodeMcp, Object.fromEntries(Object.entries(tools ?? {}).filter(([key]) => !findOpencodeToolOwner({
|
|
42803
|
+
key,
|
|
42804
|
+
serverNames
|
|
42805
|
+
})))),
|
|
42708
42806
|
...convertOpencodeServers(opencodeMcp, tools, remoteType)
|
|
42709
42807
|
};
|
|
42710
42808
|
}
|
|
42809
|
+
/** Recognize both OpenCode's sanitized names and keys older rulesync versions wrote. */
|
|
42810
|
+
function findOpencodeToolOwner({ key, serverNames }) {
|
|
42811
|
+
return findOpencodeMcpToolKeyOwner({
|
|
42812
|
+
key,
|
|
42813
|
+
serverNames,
|
|
42814
|
+
builtinKeys: /* @__PURE__ */ new Set(),
|
|
42815
|
+
acceptRawPrefix: true
|
|
42816
|
+
});
|
|
42817
|
+
}
|
|
42711
42818
|
/** Split the shared top-level `tools` map into this server's own two lists. */
|
|
42712
|
-
function splitOpencodeServerTools(serverName, tools) {
|
|
42819
|
+
function splitOpencodeServerTools(serverName, serverNames, tools) {
|
|
42713
42820
|
const enabledTools = [];
|
|
42714
42821
|
const disabledTools = [];
|
|
42715
|
-
const prefix = `${serverName}_`;
|
|
42716
42822
|
for (const [toolName, enabled] of Object.entries(tools ?? {})) {
|
|
42717
|
-
|
|
42718
|
-
|
|
42719
|
-
|
|
42823
|
+
const owner = findOpencodeToolOwner({
|
|
42824
|
+
key: toolName,
|
|
42825
|
+
serverNames
|
|
42826
|
+
});
|
|
42827
|
+
if (owner?.serverName !== serverName) continue;
|
|
42828
|
+
(enabled ? enabledTools : disabledTools).push(owner.toolName);
|
|
42720
42829
|
}
|
|
42721
42830
|
return {
|
|
42722
42831
|
enabledTools,
|
|
@@ -42726,7 +42835,7 @@ function splitOpencodeServerTools(serverName, tools) {
|
|
|
42726
42835
|
function convertOpencodeServers(opencodeMcp, tools, remoteType) {
|
|
42727
42836
|
return Object.fromEntries(Object.entries(opencodeMcp).map(([serverName, serverConfig]) => {
|
|
42728
42837
|
const extraFields = Object.fromEntries(Object.entries(serverConfig).filter(([key]) => !OPENCODE_KNOWN_SERVER_KEYS.has(key)));
|
|
42729
|
-
const { enabledTools, disabledTools } = splitOpencodeServerTools(serverName, tools);
|
|
42838
|
+
const { enabledTools, disabledTools } = splitOpencodeServerTools(serverName, Object.keys(opencodeMcp), tools);
|
|
42730
42839
|
if (!isOpencodeTransportServer(serverConfig)) return [serverName, {
|
|
42731
42840
|
...extraFields,
|
|
42732
42841
|
disabled: serverConfig.enabled === false,
|
|
@@ -42862,8 +42971,8 @@ function convertToOpencodeFormat(mcpServers, existingMcp, configShape, logger) {
|
|
|
42862
42971
|
return {
|
|
42863
42972
|
mcp: Object.fromEntries(Object.entries(mcpServers).map(([serverName, serverConfig]) => {
|
|
42864
42973
|
const converted = convertServerToOpencodeFormat(serverName, serverConfig, existingMcp[serverName], configShape, logger);
|
|
42865
|
-
if (serverConfig.enabledTools) for (const tool of serverConfig.enabledTools) tools[
|
|
42866
|
-
if (serverConfig.disabledTools) for (const tool of serverConfig.disabledTools) tools[
|
|
42974
|
+
if (serverConfig.enabledTools) for (const tool of serverConfig.enabledTools) tools[opencodeMcpToolPermissionKey(serverName, tool)] = true;
|
|
42975
|
+
if (serverConfig.disabledTools) for (const tool of serverConfig.disabledTools) tools[opencodeMcpToolPermissionKey(serverName, tool)] = false;
|
|
42867
42976
|
return converted === null ? null : [serverName, converted];
|
|
42868
42977
|
}).filter((entry) => entry !== null)),
|
|
42869
42978
|
tools
|
|
@@ -55891,12 +56000,23 @@ function buildEffectiveHooks$1({ config, toolOverrideHooks, supportedEvents }) {
|
|
|
55891
56000
|
* into separate groups, so a restricting field is never inherited by a hook
|
|
55892
56001
|
* that did not ask for it.
|
|
55893
56002
|
*/
|
|
55894
|
-
function groupDefinitionsByMatcher({ definitions, converterConfig }) {
|
|
56003
|
+
function groupDefinitionsByMatcher({ definitions, eventName, converterConfig, warn }) {
|
|
55895
56004
|
const subdividingFields = (converterConfig.groupPassthroughFields ?? []).filter(({ subdividesGroup }) => subdividesGroup);
|
|
55896
56005
|
const byMatcher = /* @__PURE__ */ new Map();
|
|
56006
|
+
const translatedMatchers = /* @__PURE__ */ new Map();
|
|
55897
56007
|
for (const def of definitions) {
|
|
55898
56008
|
const rawMatcher = def.matcher ?? "";
|
|
55899
|
-
const
|
|
56009
|
+
const normalizedMatcher = converterConfig.wildcardMatcherMeansAll && rawMatcher === "*" ? "" : rawMatcher;
|
|
56010
|
+
const translation = converterConfig.matcherTranslation;
|
|
56011
|
+
let matcher = normalizedMatcher;
|
|
56012
|
+
if (translation && normalizedMatcher && !converterConfig.noMatcherEvents?.has(eventName)) {
|
|
56013
|
+
matcher = translatedMatchers.get(normalizedMatcher) ?? translation.toTool({
|
|
56014
|
+
matcher: normalizedMatcher,
|
|
56015
|
+
eventName,
|
|
56016
|
+
warn
|
|
56017
|
+
});
|
|
56018
|
+
translatedMatchers.set(normalizedMatcher, matcher);
|
|
56019
|
+
}
|
|
55900
56020
|
const key = [matcher, ...subdividingFields.map(({ canonical, valueType }) => {
|
|
55901
56021
|
const value = def[canonical];
|
|
55902
56022
|
return isGroupPassthroughValue(value, valueType) ? stableJson(value) : "";
|
|
@@ -56406,7 +56526,7 @@ function buildToolHooks({ defs, eventName, converterConfig, warn }) {
|
|
|
56406
56526
|
converterConfig,
|
|
56407
56527
|
warn
|
|
56408
56528
|
}),
|
|
56409
|
-
type:
|
|
56529
|
+
type: hookType,
|
|
56410
56530
|
...command !== void 0 && command !== null && { command },
|
|
56411
56531
|
...def.timeout !== void 0 && def.timeout !== null && { timeout: emitTimeout({
|
|
56412
56532
|
timeout: def.timeout,
|
|
@@ -56456,7 +56576,9 @@ function canonicalToToolHooks({ config, toolOverrideHooks, converterConfig, logg
|
|
|
56456
56576
|
}) ?? eventName;
|
|
56457
56577
|
const byMatcher = groupDefinitionsByMatcher({
|
|
56458
56578
|
definitions,
|
|
56459
|
-
|
|
56579
|
+
eventName,
|
|
56580
|
+
converterConfig,
|
|
56581
|
+
warn
|
|
56460
56582
|
});
|
|
56461
56583
|
const entries = [];
|
|
56462
56584
|
const isNoMatcherEvent = converterConfig.noMatcherEvents?.has(eventName) ?? false;
|
|
@@ -56535,16 +56657,19 @@ function isImportedHookType(value) {
|
|
|
56535
56657
|
return typeof value === "string" && IMPORTED_HOOK_TYPES.has(value);
|
|
56536
56658
|
}
|
|
56537
56659
|
/**
|
|
56538
|
-
* The canonical hook type a tool-side `type` value denotes: the
|
|
56539
|
-
*
|
|
56540
|
-
* one, otherwise the value itself when it is a canonical type, and
|
|
56541
|
-
* for anything else
|
|
56660
|
+
* The canonical hook type a tool-side `type` value denotes: the canonical type
|
|
56661
|
+
* an {@link ToolHooksConverterConfig.importedHookTypeAliases} entry maps it to
|
|
56662
|
+
* when it has one, otherwise the value itself when it is a canonical type, and
|
|
56663
|
+
* `command` for anything else.
|
|
56542
56664
|
*/
|
|
56543
56665
|
function resolveImportedHookType({ value, converterConfig }) {
|
|
56544
|
-
const
|
|
56545
|
-
if (
|
|
56546
|
-
|
|
56547
|
-
|
|
56666
|
+
const aliases = converterConfig.importedHookTypeAliases;
|
|
56667
|
+
if (aliases !== void 0 && typeof value === "string") {
|
|
56668
|
+
const aliased = lookupOwn({
|
|
56669
|
+
record: aliases,
|
|
56670
|
+
key: value
|
|
56671
|
+
});
|
|
56672
|
+
if (aliased !== void 0) return aliased;
|
|
56548
56673
|
}
|
|
56549
56674
|
return isImportedHookType(value) ? value : "command";
|
|
56550
56675
|
}
|
|
@@ -56772,7 +56897,7 @@ function toolHookToCanonical({ h, rawEntry, eventName, converterConfig, warn })
|
|
|
56772
56897
|
canonical: "description",
|
|
56773
56898
|
warn
|
|
56774
56899
|
});
|
|
56775
|
-
const matcher = rawEntry.matcher;
|
|
56900
|
+
const matcher = typeof rawEntry.matcher === "string" && converterConfig.matcherTranslation ? converterConfig.matcherTranslation.toCanonical(rawEntry.matcher) : rawEntry.matcher;
|
|
56776
56901
|
return {
|
|
56777
56902
|
type: hookType,
|
|
56778
56903
|
...command !== void 0 && command !== null && { command },
|
|
@@ -58270,15 +58395,9 @@ const BOB_SPEC = {
|
|
|
58270
58395
|
canonicalToToolEventNames: CANONICAL_TO_BOB_EVENT_NAMES,
|
|
58271
58396
|
toolToCanonicalEventNames: BOB_TO_CANONICAL_EVENT_NAMES,
|
|
58272
58397
|
projectDirVar: "",
|
|
58273
|
-
noMatcherEvents: /* @__PURE__ */ new Set([
|
|
58274
|
-
"sessionStart",
|
|
58275
|
-
"beforeSubmitPrompt",
|
|
58276
|
-
"preCompact",
|
|
58277
|
-
"postCompact",
|
|
58278
|
-
"stop"
|
|
58279
|
-
]),
|
|
58398
|
+
noMatcherEvents: /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"]),
|
|
58280
58399
|
supportedHookTypes: /* @__PURE__ */ new Set(["command", "http"]),
|
|
58281
|
-
|
|
58400
|
+
importedHookTypeAliases: { https: "http" },
|
|
58282
58401
|
wildcardMatcherMeansAll: true
|
|
58283
58402
|
}
|
|
58284
58403
|
};
|
|
@@ -58290,7 +58409,7 @@ const BOB_SPEC = {
|
|
|
58290
58409
|
* `~/.bob/settings/settings.json` (user scope) — in the Claude-Code shape:
|
|
58291
58410
|
* `{ "<Event>": [{ "matcher"?: "<regex>", "hooks": [{ "type": "command",
|
|
58292
58411
|
* "command": "...", "timeout"?: <seconds> }] }] }`, where a handler may
|
|
58293
|
-
* instead be `{ "type": "
|
|
58412
|
+
* instead be `{ "type": "http", "url": "https://...", "timeout"?: <seconds> }`. The
|
|
58294
58413
|
* file also holds settings rulesync does not own, so generation merges the
|
|
58295
58414
|
* `hooks` key into it (see `SHARED_CONFIG_OWNERSHIP`) instead of overwriting
|
|
58296
58415
|
* the file.
|
|
@@ -60232,6 +60351,32 @@ var CopilotcliHooks = class CopilotcliHooks extends ToolHooks {
|
|
|
60232
60351
|
}
|
|
60233
60352
|
};
|
|
60234
60353
|
// src/features/hooks/cortexcode-hooks.ts
|
|
60354
|
+
const CORTEXCODE_NO_MATCHER_EVENTS = /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"]);
|
|
60355
|
+
const CANONICAL_TO_CORTEXCODE_TOOL_NAMES = {
|
|
60356
|
+
Bash: "bash",
|
|
60357
|
+
Read: "read",
|
|
60358
|
+
Write: "write",
|
|
60359
|
+
Edit: "edit",
|
|
60360
|
+
Grep: "grep",
|
|
60361
|
+
Glob: "glob"
|
|
60362
|
+
};
|
|
60363
|
+
const CORTEXCODE_TO_CANONICAL_TOOL_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_CORTEXCODE_TOOL_NAMES).map(([canonical, tool]) => [tool, canonical]));
|
|
60364
|
+
const MATCHER_TOKEN_PATTERN = /\\.|\[(?:\\.|[^\]\\])*\]|(?<=^|[^\w\\]|\\\w)[A-Za-z_]\w*(?!\w)/gs;
|
|
60365
|
+
function isMatcherName(token) {
|
|
60366
|
+
return !token.startsWith("\\") && !token.startsWith("[");
|
|
60367
|
+
}
|
|
60368
|
+
function replaceMatcherNames(matcher, names) {
|
|
60369
|
+
return matcher.replace(MATCHER_TOKEN_PATTERN, (token) => isMatcherName(token) && Object.hasOwn(names, token) ? names[token] ?? token : token);
|
|
60370
|
+
}
|
|
60371
|
+
function canonicalToCortexcodeMatcher({ matcher, eventName, warn }) {
|
|
60372
|
+
const translated = replaceMatcherNames(matcher, CANONICAL_TO_CORTEXCODE_TOOL_NAMES);
|
|
60373
|
+
const unmatched = [...translated.matchAll(MATCHER_TOKEN_PATTERN)].map(([token]) => token).filter((token) => isMatcherName(token) && /^[A-Z]/.test(token));
|
|
60374
|
+
if (unmatched.length > 0) warn(`Cortex Code matches hook matchers case-sensitively against lowercase runtime tool names, and ${[...new Set(unmatched)].map((name) => quoteValueForWarning(name)).join(", ")} in the "${eventName}" matcher ${quoteValueForWarning(matcher)} is not a tool Cortex Code documents a runtime ID for, so it is written as-is and will likely never match. Replace it with the lowercase name Cortex Code uses for that tool, if it has one.`);
|
|
60375
|
+
return translated;
|
|
60376
|
+
}
|
|
60377
|
+
function cortexcodeToCanonicalMatcher(matcher) {
|
|
60378
|
+
return replaceMatcherNames(matcher, CORTEXCODE_TO_CANONICAL_TOOL_NAMES);
|
|
60379
|
+
}
|
|
60235
60380
|
const CORTEXCODE_SPEC = {
|
|
60236
60381
|
displayName: "Cortex Code",
|
|
60237
60382
|
overrideKey: "cortexcode",
|
|
@@ -60241,7 +60386,7 @@ const CORTEXCODE_SPEC = {
|
|
|
60241
60386
|
toolToCanonicalEventNames: CORTEXCODE_TO_CANONICAL_EVENT_NAMES,
|
|
60242
60387
|
projectDirVar: "$CORTEX_PROJECT_DIR",
|
|
60243
60388
|
prefixDotRelativeCommandsOnly: true,
|
|
60244
|
-
noMatcherEvents:
|
|
60389
|
+
noMatcherEvents: CORTEXCODE_NO_MATCHER_EVENTS,
|
|
60245
60390
|
supportedHookTypes: /* @__PURE__ */ new Set(["command", "prompt"]),
|
|
60246
60391
|
booleanPassthroughFields: [{
|
|
60247
60392
|
canonical: "enabled",
|
|
@@ -60256,7 +60401,11 @@ const CORTEXCODE_SPEC = {
|
|
|
60256
60401
|
canonical: "source",
|
|
60257
60402
|
tool: "source",
|
|
60258
60403
|
commandOnly: true
|
|
60259
|
-
}]
|
|
60404
|
+
}],
|
|
60405
|
+
matcherTranslation: {
|
|
60406
|
+
toTool: canonicalToCortexcodeMatcher,
|
|
60407
|
+
toCanonical: cortexcodeToCanonicalMatcher
|
|
60408
|
+
}
|
|
60260
60409
|
}
|
|
60261
60410
|
};
|
|
60262
60411
|
/**
|
|
@@ -60437,35 +60586,80 @@ const NORMALIZED_CRUSH_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entr
|
|
|
60437
60586
|
function normalizeCrushEventName(event) {
|
|
60438
60587
|
return event.replaceAll("_", "").toLowerCase();
|
|
60439
60588
|
}
|
|
60589
|
+
/** Crush tool events, by normalized spelling, on which a `matcher` is valid. */
|
|
60590
|
+
const NORMALIZED_CRUSH_TOOL_EVENTS = new Set(CRUSH_TOOL_EVENTS.map((event) => normalizeCrushEventName(event)));
|
|
60591
|
+
/**
|
|
60592
|
+
* Resolve a `crush.hooks` override key to the canonical event it names, or
|
|
60593
|
+
* null when it names no canonical event. The key may be spelled the canonical
|
|
60594
|
+
* way (`stop`) or in any spelling Crush accepts for the event (`TurnEnd`,
|
|
60595
|
+
* `turn_end`), so an override an earlier import filed under a Crush name still
|
|
60596
|
+
* lands on the same event as the shared hooks.
|
|
60597
|
+
*/
|
|
60598
|
+
function resolveOverrideCanonicalEvent(key) {
|
|
60599
|
+
if (lookupOwn({
|
|
60600
|
+
record: CANONICAL_TO_CRUSH_EVENT_NAMES,
|
|
60601
|
+
key
|
|
60602
|
+
}) !== void 0) return key;
|
|
60603
|
+
return lookupOwn({
|
|
60604
|
+
record: NORMALIZED_CRUSH_TO_CANONICAL_EVENT_NAMES,
|
|
60605
|
+
key: normalizeCrushEventName(key)
|
|
60606
|
+
}) ?? null;
|
|
60607
|
+
}
|
|
60440
60608
|
/**
|
|
60441
60609
|
* Build the `hooks` block of `crush.json` from a canonical hooks config.
|
|
60442
60610
|
* Crush keys a flat array of `{name, matcher, command, timeout}` entries by
|
|
60443
60611
|
* event name; `matcher` is a regex tested against the (lower-case) Crush tool
|
|
60444
60612
|
* name and `timeout` is in seconds. Only `type: "command"` canonical hooks are
|
|
60445
60613
|
* emitted, since a Crush hook is a shell command. A shared canonical event
|
|
60446
|
-
* Crush does not fire is skipped (the HooksProcessor reports it)
|
|
60447
|
-
*
|
|
60448
|
-
*
|
|
60614
|
+
* Crush does not fire is skipped (the HooksProcessor reports it).
|
|
60615
|
+
*
|
|
60616
|
+
* Every `crush.hooks` override key is resolved to its event first, whatever
|
|
60617
|
+
* spelling it uses: the override replaces the shared entries of that event
|
|
60618
|
+
* (as for every other tool's override), and override keys that name the same
|
|
60619
|
+
* event are concatenated in order, the way Crush itself merges them. A key
|
|
60620
|
+
* that names no canonical event — such as `PermissionResult`, or one an
|
|
60621
|
+
* import filed there — is written verbatim so it round-trips; keys of that
|
|
60622
|
+
* kind that Crush reads as the same event are concatenated under the first
|
|
60623
|
+
* spelling. A `matcher` is only written on a tool event: Crush rejects the
|
|
60624
|
+
* whole config when one appears anywhere else.
|
|
60449
60625
|
*/
|
|
60450
60626
|
function canonicalToCrushHooks({ config, toolOverride, logger }) {
|
|
60451
|
-
const
|
|
60452
|
-
for (const [event, defs] of Object.entries(config.hooks))
|
|
60453
|
-
|
|
60454
|
-
...sharedHooks,
|
|
60455
|
-
...toolOverride
|
|
60456
|
-
};
|
|
60457
|
-
const hooks = {};
|
|
60458
|
-
for (const [event, defs] of Object.entries(effective)) {
|
|
60459
|
-
if (isPrototypePollutionKey(event)) continue;
|
|
60460
|
-
const crushEvent = lookupOwn({
|
|
60627
|
+
const shared = /* @__PURE__ */ new Map();
|
|
60628
|
+
for (const [event, defs] of Object.entries(config.hooks)) {
|
|
60629
|
+
const crushEvent = SUPPORTED_CRUSH_EVENTS.has(event) ? lookupOwn({
|
|
60461
60630
|
record: CANONICAL_TO_CRUSH_EVENT_NAMES,
|
|
60462
60631
|
key: event
|
|
60463
|
-
})
|
|
60632
|
+
}) : void 0;
|
|
60633
|
+
if (crushEvent !== void 0) shared.set(crushEvent, defs);
|
|
60634
|
+
}
|
|
60635
|
+
const override = /* @__PURE__ */ new Map();
|
|
60636
|
+
const verbatimSpellings = /* @__PURE__ */ new Map();
|
|
60637
|
+
for (const [key, defs] of Object.entries(toolOverride ?? {})) {
|
|
60638
|
+
if (isPrototypePollutionKey(key) || !Array.isArray(defs)) continue;
|
|
60639
|
+
const canonical = resolveOverrideCanonicalEvent(key);
|
|
60640
|
+
let crushEvent;
|
|
60641
|
+
if (canonical !== null) crushEvent = lookupOwn({
|
|
60642
|
+
record: CANONICAL_TO_CRUSH_EVENT_NAMES,
|
|
60643
|
+
key: canonical
|
|
60644
|
+
}) ?? key;
|
|
60645
|
+
else {
|
|
60646
|
+
const normalized = normalizeCrushEventName(key);
|
|
60647
|
+
crushEvent = verbatimSpellings.get(normalized) ?? key;
|
|
60648
|
+
verbatimSpellings.set(normalized, crushEvent);
|
|
60649
|
+
}
|
|
60650
|
+
override.set(crushEvent, [...override.get(crushEvent) ?? [], ...defs]);
|
|
60651
|
+
}
|
|
60652
|
+
const effective = new Map(shared);
|
|
60653
|
+
for (const [crushEvent, defs] of override) effective.set(crushEvent, defs);
|
|
60654
|
+
const hooks = {};
|
|
60655
|
+
for (const [crushEvent, defs] of effective) {
|
|
60656
|
+
const allowsMatcher = NORMALIZED_CRUSH_TOOL_EVENTS.has(normalizeCrushEventName(crushEvent));
|
|
60464
60657
|
const entries = [];
|
|
60465
60658
|
for (const def of defs) {
|
|
60466
60659
|
const entry = canonicalDefToCrushEntry({
|
|
60467
60660
|
def,
|
|
60468
|
-
event,
|
|
60661
|
+
event: crushEvent,
|
|
60662
|
+
allowsMatcher,
|
|
60469
60663
|
logger
|
|
60470
60664
|
});
|
|
60471
60665
|
if (entry !== null) entries.push(entry);
|
|
@@ -60475,7 +60669,7 @@ function canonicalToCrushHooks({ config, toolOverride, logger }) {
|
|
|
60475
60669
|
return hooks;
|
|
60476
60670
|
}
|
|
60477
60671
|
/** Convert one canonical hook definition to a Crush entry, or null to skip. */
|
|
60478
|
-
function canonicalDefToCrushEntry({ def, event, logger }) {
|
|
60672
|
+
function canonicalDefToCrushEntry({ def, event, allowsMatcher, logger }) {
|
|
60479
60673
|
if ((def.type ?? "command") !== "command") return null;
|
|
60480
60674
|
if (typeof def.command !== "string" || def.command === "") {
|
|
60481
60675
|
logger?.warn(`Crush hook ${quoteValueForWarning(def.name ?? "")} under "${event}" has no "command", which Crush would discard, so it was skipped.`);
|
|
@@ -60483,7 +60677,10 @@ function canonicalDefToCrushEntry({ def, event, logger }) {
|
|
|
60483
60677
|
}
|
|
60484
60678
|
const entry = { command: def.command };
|
|
60485
60679
|
if (typeof def.name === "string" && def.name !== "") entry.name = def.name;
|
|
60486
|
-
if (typeof def.matcher === "string" && def.matcher !== "" && def.matcher !== "*")
|
|
60680
|
+
if (typeof def.matcher === "string" && def.matcher !== "" && def.matcher !== "*") {
|
|
60681
|
+
if (allowsMatcher) entry.matcher = def.matcher;
|
|
60682
|
+
else logger?.warn(`matcher ${quoteValueForWarning(def.matcher)} on "${event}" hook will be ignored — Crush only accepts a matcher on tool events.`);
|
|
60683
|
+
}
|
|
60487
60684
|
if (typeof def.timeout === "number") entry.timeout = Math.ceil(def.timeout);
|
|
60488
60685
|
return entry;
|
|
60489
60686
|
}
|
|
@@ -60530,12 +60727,13 @@ function crushHooksToCanonical(hooksBlock) {
|
|
|
60530
60727
|
* `<project>/crush.json` (or an existing `.crush.json`; Crush merges the pair,
|
|
60531
60728
|
* lists concatenated) at project scope and `~/.config/crush/crush.json` at
|
|
60532
60729
|
* user scope — as
|
|
60533
|
-
* `hooks.<Event>: [{name?, matcher?, command, timeout?}]`.
|
|
60534
|
-
*
|
|
60730
|
+
* `hooks.<Event>: [{name?, matcher?, command, timeout?}]`. `matcher` is only
|
|
60731
|
+
* valid on tool events (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`,
|
|
60732
|
+
* `PermissionRequest`, `PermissionResult`). The `hooks` key is owned outright; every other top-level key
|
|
60535
60733
|
* of the file is preserved and the file is never deleted.
|
|
60536
60734
|
*
|
|
60537
|
-
* @see https://github.com/charmbracelet/crush/blob/
|
|
60538
|
-
* @see https://github.com/charmbracelet/crush/blob/
|
|
60735
|
+
* @see https://github.com/charmbracelet/crush/blob/v0.99.0/docs/hooks/README.md
|
|
60736
|
+
* @see https://github.com/charmbracelet/crush/blob/v0.99.0/internal/config/hooks.go
|
|
60539
60737
|
*/
|
|
60540
60738
|
var CrushHooks = class CrushHooks extends ToolHooks {
|
|
60541
60739
|
json;
|
|
@@ -63381,8 +63579,11 @@ var LettacodeHooks = class LettacodeHooks extends ToolHooks {
|
|
|
63381
63579
|
* OpenCode 2.x no longer runs V1 plugin modules: a plugin must default-export
|
|
63382
63580
|
* `{ id, setup(ctx) }`. Inside `setup` hooks are registered per domain
|
|
63383
63581
|
* (`await ctx.tool.hook("execute.before", handler)`), and lifecycle events
|
|
63384
|
-
* are read from `ctx.event.subscribe({ signal })`, an async iterable of
|
|
63385
|
-
* public event stream whose payload lives under `event.data`.
|
|
63582
|
+
* are read from `ctx.event.subscribe({ types, signal })`, an async iterable of
|
|
63583
|
+
* the public event stream whose payload lives under `event.data`. `types`
|
|
63584
|
+
* narrows the stream to the event types the plugin handles (a newer 2.x
|
|
63585
|
+
* option; the per-type checks inside the loop stay, so an older 2.x that
|
|
63586
|
+
* ignores it still runs each command only for its own event).
|
|
63386
63587
|
*
|
|
63387
63588
|
* Commands run through a private Bun Shell instance (`new Bun.$.Shell()`, the
|
|
63388
63589
|
* plugin runs inside the Bun-built OpenCode binary) whose working directory is
|
|
@@ -63485,13 +63686,18 @@ function buildHookRegistrationLines(hookPoint, handlers) {
|
|
|
63485
63686
|
}
|
|
63486
63687
|
/**
|
|
63487
63688
|
* Emit the event-stream loop. Each command is isolated in its own try/catch so
|
|
63488
|
-
* a failing hook neither skips its siblings nor ends the subscription.
|
|
63689
|
+
* a failing hook neither skips its siblings nor ends the subscription. The
|
|
63690
|
+
* subscription passes `types` so the server delivers only the handled events.
|
|
63489
63691
|
*/
|
|
63490
63692
|
function buildEventLoopLines(eventHandlers) {
|
|
63491
63693
|
const lines = [];
|
|
63694
|
+
const types = [...eventHandlers.keys()].map((eventType) => JSON.stringify(eventType)).join(", ");
|
|
63492
63695
|
lines.push("const __rulesyncEvents = new AbortController();");
|
|
63493
63696
|
lines.push("void (async () => {");
|
|
63494
|
-
lines.push(" for await (const event of ctx.event.subscribe({
|
|
63697
|
+
lines.push(" for await (const event of ctx.event.subscribe({");
|
|
63698
|
+
lines.push(` types: [${types}],`);
|
|
63699
|
+
lines.push(" signal: __rulesyncEvents.signal,");
|
|
63700
|
+
lines.push(" })) {");
|
|
63495
63701
|
let isFirst = true;
|
|
63496
63702
|
for (const [eventType, handlers] of eventHandlers) {
|
|
63497
63703
|
lines.push(` ${isFirst ? "if" : "} else if"} (event.type === "${eventType}") {`);
|
|
@@ -65625,7 +65831,12 @@ var VibeHooks = class extends ToolHooks {
|
|
|
65625
65831
|
* resolves inside the bundle and is written as is. The file is loaded only
|
|
65626
65832
|
* when `plugin.json` declares the `ai.mistral.vibe` extension.
|
|
65627
65833
|
*
|
|
65834
|
+
* Plugin hooks run on Vibe v2.x and on v3.0.4+. v3.0.0 through v3.0.3 do not
|
|
65835
|
+
* run them (v3.0.4 Fixed: "Hooks shipped in a native Vibe plugin's
|
|
65836
|
+
* `ai.mistral.vibe/hooks.toml` now run"). The output is the same either way.
|
|
65837
|
+
*
|
|
65628
65838
|
* @see https://github.com/mistralai/mistral-vibe/blob/v2.25.8/vibe/core/plugins/_native.py
|
|
65839
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v3.0.4/CHANGELOG.md
|
|
65629
65840
|
*/
|
|
65630
65841
|
var VibePluginHooks = class extends VibeHooks {
|
|
65631
65842
|
static getSettablePaths() {
|
|
@@ -65709,6 +65920,14 @@ const ZCODE_CONVERTER_CONFIG = {
|
|
|
65709
65920
|
tool: "shell",
|
|
65710
65921
|
commandOnly: true
|
|
65711
65922
|
}],
|
|
65923
|
+
keywordPassthroughFields: [{
|
|
65924
|
+
canonical: "failClosed",
|
|
65925
|
+
tool: "onError",
|
|
65926
|
+
trueValue: "deny",
|
|
65927
|
+
falseValue: "allow",
|
|
65928
|
+
events: /* @__PURE__ */ new Set(["preToolUse"]),
|
|
65929
|
+
ignoredWhenFlags: ["async"]
|
|
65930
|
+
}],
|
|
65712
65931
|
wildcardMatcherMeansAll: true
|
|
65713
65932
|
};
|
|
65714
65933
|
/**
|
|
@@ -73849,9 +74068,21 @@ function toGitlabduoServer({ serverName, serverConfig, logger }) {
|
|
|
73849
74068
|
...rest
|
|
73850
74069
|
};
|
|
73851
74070
|
}
|
|
74071
|
+
/**
|
|
74072
|
+
* GitLab Duo CLI reserves the MCP server name `duo` for its first-party server
|
|
74073
|
+
* (gitlab-lsp v9.33.0+): a workspace, user or plugin entry named exactly `duo`
|
|
74074
|
+
* (case-sensitive) is dropped with only a log line, so it would never load.
|
|
74075
|
+
*
|
|
74076
|
+
* @see https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/commit/0572967c915465c1ac94ca38ef57676eb44e16d6
|
|
74077
|
+
*/
|
|
74078
|
+
const GITLABDUO_RESERVED_MCP_SERVER_NAME = "duo";
|
|
73852
74079
|
function toGitlabduoServers(servers, logger) {
|
|
73853
74080
|
const result = {};
|
|
73854
74081
|
for (const [serverName, serverConfig] of Object.entries(servers)) {
|
|
74082
|
+
if (serverName === GITLABDUO_RESERVED_MCP_SERVER_NAME) {
|
|
74083
|
+
logger?.warn(`GitLab Duo CLI MCP: skipping "${serverName}" because GitLab Duo CLI 9.33.0+ reserves that name for its first-party server and never loads a config entry with it. Rename the server to use it with GitLab Duo CLI.`);
|
|
74084
|
+
continue;
|
|
74085
|
+
}
|
|
73855
74086
|
const converted = toGitlabduoServer({
|
|
73856
74087
|
serverName,
|
|
73857
74088
|
serverConfig,
|
|
@@ -75097,24 +75328,47 @@ async function readKimiCodeConfig({ outputRoot }) {
|
|
|
75097
75328
|
}
|
|
75098
75329
|
}
|
|
75099
75330
|
/**
|
|
75331
|
+
* Kimi's reconnect delays are millisecond counts, so only a non-negative safe
|
|
75332
|
+
* integer is passed through. Anything else (a negative, a fraction, a string)
|
|
75333
|
+
* is dropped with a warning rather than written into, or lifted out of, the
|
|
75334
|
+
* shared global `config.toml`.
|
|
75335
|
+
*/
|
|
75336
|
+
function toKimiCodeReconnectDelay({ value, key, logger }) {
|
|
75337
|
+
if (value === void 0) return;
|
|
75338
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) return value;
|
|
75339
|
+
warnWithFallback(logger, `Kimi Code MCP: dropping ${key} because it is not a non-negative integer number of milliseconds.`);
|
|
75340
|
+
}
|
|
75341
|
+
/**
|
|
75100
75342
|
* Read the `[mcp]` defaults back out of the shared user `config.toml` so a
|
|
75101
75343
|
* generate → import round trip keeps them. Absent or unparseable content yields
|
|
75102
75344
|
* no defaults rather than failing the import: this file belongs to three
|
|
75103
75345
|
* features plus the user.
|
|
75104
75346
|
*/
|
|
75105
|
-
async function readKimiCodeMcpDefaults({ outputRoot }) {
|
|
75347
|
+
async function readKimiCodeMcpDefaults({ outputRoot, logger }) {
|
|
75106
75348
|
const config = await readKimiCodeConfig({ outputRoot });
|
|
75107
75349
|
if (!config.parsed) return {};
|
|
75350
|
+
const reconnectInitialDelayMs = toKimiCodeReconnectDelay({
|
|
75351
|
+
value: config.mcp.reconnect_initial_delay_ms,
|
|
75352
|
+
key: "[mcp] reconnect_initial_delay_ms",
|
|
75353
|
+
logger
|
|
75354
|
+
});
|
|
75355
|
+
const reconnectMaxDelayMs = toKimiCodeReconnectDelay({
|
|
75356
|
+
value: config.mcp.reconnect_max_delay_ms,
|
|
75357
|
+
key: "[mcp] reconnect_max_delay_ms",
|
|
75358
|
+
logger
|
|
75359
|
+
});
|
|
75108
75360
|
return {
|
|
75109
75361
|
...typeof config.mcp.startup_timeout_ms === "number" && { startupTimeoutMs: config.mcp.startup_timeout_ms },
|
|
75110
75362
|
...typeof config.mcp.tool_timeout_ms === "number" && { toolTimeoutMs: config.mcp.tool_timeout_ms },
|
|
75111
|
-
...typeof config.mcp.default_deferred === "boolean" && { defaultDeferred: config.mcp.default_deferred }
|
|
75363
|
+
...typeof config.mcp.default_deferred === "boolean" && { defaultDeferred: config.mcp.default_deferred },
|
|
75364
|
+
...reconnectInitialDelayMs !== void 0 && { reconnectInitialDelayMs },
|
|
75365
|
+
...reconnectMaxDelayMs !== void 0 && { reconnectMaxDelayMs }
|
|
75112
75366
|
};
|
|
75113
75367
|
}
|
|
75114
75368
|
/**
|
|
75115
75369
|
* Kimi's `[mcp]` section in the shared user config sets the default connect and
|
|
75116
|
-
* per-tool-call timeouts,
|
|
75117
|
-
* server, including ones rulesync did not write. Per-server values in
|
|
75370
|
+
* per-tool-call timeouts, whether tools load on demand, and the automatic
|
|
75371
|
+
* reconnect backoff for *every* MCP server, including ones rulesync did not write. Per-server values in
|
|
75118
75372
|
* `mcp.json` still take precedence; this only moves the default.
|
|
75119
75373
|
*
|
|
75120
75374
|
* Written as an auxiliary file so it goes through the normal write phase and
|
|
@@ -75152,7 +75406,9 @@ var KimiCodeMcpConfigToml = class KimiCodeMcpConfigToml extends ToolFile {
|
|
|
75152
75406
|
...existingSection,
|
|
75153
75407
|
...defaults.startupTimeoutMs !== void 0 && { startup_timeout_ms: defaults.startupTimeoutMs },
|
|
75154
75408
|
...defaults.toolTimeoutMs !== void 0 && { tool_timeout_ms: defaults.toolTimeoutMs },
|
|
75155
|
-
...defaults.defaultDeferred !== void 0 && { default_deferred: defaults.defaultDeferred }
|
|
75409
|
+
...defaults.defaultDeferred !== void 0 && { default_deferred: defaults.defaultDeferred },
|
|
75410
|
+
...defaults.reconnectInitialDelayMs !== void 0 && { reconnect_initial_delay_ms: defaults.reconnectInitialDelayMs },
|
|
75411
|
+
...defaults.reconnectMaxDelayMs !== void 0 && { reconnect_max_delay_ms: defaults.reconnectMaxDelayMs }
|
|
75156
75412
|
} },
|
|
75157
75413
|
filePath: relativeConfigPath
|
|
75158
75414
|
});
|
|
@@ -75201,7 +75457,10 @@ var KimiCodeMcp = class KimiCodeMcp extends ToolMcp {
|
|
|
75201
75457
|
fileContent,
|
|
75202
75458
|
validate,
|
|
75203
75459
|
global,
|
|
75204
|
-
configDefaults: global ? await readKimiCodeMcpDefaults({
|
|
75460
|
+
configDefaults: global ? await readKimiCodeMcpDefaults({
|
|
75461
|
+
outputRoot,
|
|
75462
|
+
logger
|
|
75463
|
+
}) : {},
|
|
75205
75464
|
logger
|
|
75206
75465
|
});
|
|
75207
75466
|
}
|
|
@@ -75251,7 +75510,17 @@ var KimiCodeMcp = class KimiCodeMcp extends ToolMcp {
|
|
|
75251
75510
|
const startupTimeoutMs = typeof block.startupTimeoutMs === "number" ? block.startupTimeoutMs : void 0;
|
|
75252
75511
|
const toolTimeoutMs = typeof block.toolTimeoutMs === "number" ? block.toolTimeoutMs : void 0;
|
|
75253
75512
|
const defaultDeferred = typeof block.defaultDeferred === "boolean" ? block.defaultDeferred : void 0;
|
|
75254
|
-
|
|
75513
|
+
const reconnectInitialDelayMs = toKimiCodeReconnectDelay({
|
|
75514
|
+
value: block.reconnectInitialDelayMs,
|
|
75515
|
+
key: "kimi-code.reconnectInitialDelayMs",
|
|
75516
|
+
logger
|
|
75517
|
+
});
|
|
75518
|
+
const reconnectMaxDelayMs = toKimiCodeReconnectDelay({
|
|
75519
|
+
value: block.reconnectMaxDelayMs,
|
|
75520
|
+
key: "kimi-code.reconnectMaxDelayMs",
|
|
75521
|
+
logger
|
|
75522
|
+
});
|
|
75523
|
+
if (startupTimeoutMs === void 0 && toolTimeoutMs === void 0 && defaultDeferred === void 0 && reconnectInitialDelayMs === void 0 && reconnectMaxDelayMs === void 0) return [];
|
|
75255
75524
|
const existing = await readKimiCodeConfig({ outputRoot });
|
|
75256
75525
|
if (!existing.parsed) {
|
|
75257
75526
|
const paths = kimiCodeConfigRelativePath();
|
|
@@ -75263,7 +75532,9 @@ var KimiCodeMcp = class KimiCodeMcp extends ToolMcp {
|
|
|
75263
75532
|
defaults: {
|
|
75264
75533
|
startupTimeoutMs,
|
|
75265
75534
|
toolTimeoutMs,
|
|
75266
|
-
defaultDeferred
|
|
75535
|
+
defaultDeferred,
|
|
75536
|
+
reconnectInitialDelayMs,
|
|
75537
|
+
reconnectMaxDelayMs
|
|
75267
75538
|
},
|
|
75268
75539
|
existing
|
|
75269
75540
|
})];
|
|
@@ -85614,6 +85885,7 @@ const CLAUDECODE_ENV_IGNORED_IN_EVERY_FILE = /* @__PURE__ */ new Set([
|
|
|
85614
85885
|
"CLAUDE_CODE_DISABLE_MOUNTED_DRIVE_RM_PROMPT",
|
|
85615
85886
|
"CLAUDE_CODE_DISABLE_POWERSHELL_CMD_RM_DENY",
|
|
85616
85887
|
"CLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT",
|
|
85888
|
+
"CLAUDE_CODE_EVEN_MORE_DANGEROUSLY_SKIP_PERMISSIONS",
|
|
85617
85889
|
"CLAUDE_CODE_MESSAGING_SOCKET",
|
|
85618
85890
|
"CLAUDE_CODE_MESSAGING_TOKEN",
|
|
85619
85891
|
"CLAUDE_CODE_PROJECT_DIR_NAME",
|
|
@@ -104859,32 +105131,59 @@ function buildChecksStrategy(ctx) {
|
|
|
104859
105131
|
}
|
|
104860
105132
|
// src/features/shared/antigravity-plugin-manifest.ts
|
|
104861
105133
|
const ANTIGRAVITY_PLUGIN_NAME_PATTERN = /^[a-zA-Z0-9-_]+$/;
|
|
105134
|
+
const ANTIGRAVITY_PLUGIN_STRICT_NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
105135
|
+
/**
|
|
105136
|
+
* Lower-case a directory name and turn `_` into `-` (collapsing repeated and
|
|
105137
|
+
* trimming edge hyphens), so `My_Plugin` becomes `my-plugin`.
|
|
105138
|
+
*/
|
|
105139
|
+
function toStrictAntigravityPluginName(name) {
|
|
105140
|
+
return name.toLowerCase().replace(/[-_]+/g, "-").replace(/^-+|-+$/g, "");
|
|
105141
|
+
}
|
|
104862
105142
|
/**
|
|
104863
105143
|
* Create the `plugin.json` manifest Antigravity requires before it treats a
|
|
104864
105144
|
* directory as a plugin, so a tree generated from scratch actually loads.
|
|
104865
105145
|
*
|
|
104866
|
-
*
|
|
104867
|
-
*
|
|
104868
|
-
*
|
|
104869
|
-
*
|
|
105146
|
+
* Only the required `name` is written, derived from the plugin directory's
|
|
105147
|
+
* name and normalized to the lowercase kebab-case form `agy plugin validate
|
|
105148
|
+
* --strict` and the Marketplace require; the other manifest fields (such as
|
|
105149
|
+
* `description`, `version` or `author`) have no rulesync source. An existing
|
|
105150
|
+
* manifest is never rewritten: it may carry hand-authored fields. Its `name` is
|
|
105151
|
+
* read only to report a collision with another output root's name. A
|
|
104870
105152
|
* manifest kept in one of the manifest folders counts as present too, so no
|
|
104871
105153
|
* root stub is written next to it.
|
|
104872
105154
|
*/
|
|
104873
105155
|
async function ensureAntigravityPluginManifests({ outputRoots, dryRun, logger }) {
|
|
104874
105156
|
const paths = [];
|
|
105157
|
+
const seenNames = /* @__PURE__ */ new Map();
|
|
105158
|
+
const noteName = (name, manifestPath) => {
|
|
105159
|
+
const previousPath = seenNames.get(name);
|
|
105160
|
+
if (previousPath === void 0) {
|
|
105161
|
+
seenNames.set(name, manifestPath);
|
|
105162
|
+
return;
|
|
105163
|
+
}
|
|
105164
|
+
warnOnceWithFallback(logger, `The Antigravity plugin manifests ${quoteForLog(manifestPath)} and ${quoteForLog(previousPath)} both name the plugin ${quoteForLog(name)}, so the plugins collide in Antigravity. Rename one of the directories or set a distinct "name" by hand.`);
|
|
105165
|
+
};
|
|
104875
105166
|
for (const outputRoot of outputRoots) {
|
|
104876
105167
|
const filePath = join(outputRoot, ANTIGRAVITY_PLUGIN_MANIFEST_FILE_NAME);
|
|
104877
|
-
|
|
105168
|
+
const existingManifestPath = await findAntigravityPluginManifest(outputRoot);
|
|
105169
|
+
if (existingManifestPath !== void 0) {
|
|
105170
|
+
const existingName = await readManifestName(existingManifestPath);
|
|
105171
|
+
if (existingName !== void 0) noteName(existingName, existingManifestPath);
|
|
105172
|
+
continue;
|
|
105173
|
+
}
|
|
104878
105174
|
if (await refusesWriteOutsideRoot({
|
|
104879
105175
|
logger,
|
|
104880
105176
|
rootPath: outputRoot,
|
|
104881
105177
|
targetPath: filePath
|
|
104882
105178
|
})) continue;
|
|
104883
|
-
const
|
|
104884
|
-
|
|
104885
|
-
|
|
105179
|
+
const dirName = basename(resolve(outputRoot));
|
|
105180
|
+
const name = toStrictAntigravityPluginName(dirName);
|
|
105181
|
+
if (!ANTIGRAVITY_PLUGIN_NAME_PATTERN.test(dirName) || !ANTIGRAVITY_PLUGIN_STRICT_NAME_PATTERN.test(name)) {
|
|
105182
|
+
warnOnceWithFallback(logger, `Cannot derive an Antigravity plugin name from the directory ${quoteForLog(dirName)}: it must contain only letters, digits, "-" and "_", and at least one letter or digit, so that it normalizes to ${ANTIGRAVITY_PLUGIN_STRICT_NAME_PATTERN.source}. Create ${quoteForLog(filePath)} by hand with a valid "name".`);
|
|
104886
105183
|
continue;
|
|
104887
105184
|
}
|
|
105185
|
+
if (name !== dirName) warnOnceWithFallback(logger, `The Antigravity plugin directory ${quoteForLog(dirName)} is not lowercase kebab-case, which \`agy plugin validate --strict\` and the Marketplace reject, so ${quoteForLog(filePath)} names the plugin ${quoteForLog(name)}.`);
|
|
105186
|
+
noteName(name, filePath);
|
|
104888
105187
|
const content = addTrailingNewline(JSON.stringify({ name }, null, 2));
|
|
104889
105188
|
if (dryRun) logger.info(`[DRY RUN] Would write: ${stripControlCharacters(filePath)}`);
|
|
104890
105189
|
else await writeFileContent(filePath, content);
|
|
@@ -104897,10 +105196,18 @@ async function ensureAntigravityPluginManifests({ outputRoots, dryRun, logger })
|
|
|
104897
105196
|
sourceLoadFailed: false
|
|
104898
105197
|
};
|
|
104899
105198
|
}
|
|
104900
|
-
async function
|
|
105199
|
+
async function findAntigravityPluginManifest(outputRoot) {
|
|
104901
105200
|
const candidates = [join(outputRoot, ANTIGRAVITY_PLUGIN_MANIFEST_FILE_NAME), ...ANTIGRAVITY_PLUGIN_MANIFEST_FOLDERS.map((folder) => join(outputRoot, folder, ANTIGRAVITY_PLUGIN_MANIFEST_FILE_NAME))];
|
|
104902
|
-
for (const candidate of candidates) if (await fileExists(candidate)) return
|
|
104903
|
-
|
|
105201
|
+
for (const candidate of candidates) if (await fileExists(candidate)) return candidate;
|
|
105202
|
+
}
|
|
105203
|
+
/** The manifest's string `name`, or `undefined` when it is unreadable or absent. */
|
|
105204
|
+
async function readManifestName(manifestPath) {
|
|
105205
|
+
try {
|
|
105206
|
+
const parsed = JSON.parse(await readFileContent(manifestPath));
|
|
105207
|
+
return isRecord(parsed) && typeof parsed.name === "string" ? parsed.name : void 0;
|
|
105208
|
+
} catch {
|
|
105209
|
+
return;
|
|
105210
|
+
}
|
|
104904
105211
|
}
|
|
104905
105212
|
// src/features/shared/hermes-project-plugin-activation.ts
|
|
104906
105213
|
function mergeEnabledPlugins({ existingContent, filePath, pluginNames }) {
|
|
@@ -107003,4 +107310,4 @@ async function importChecksCore(params) {
|
|
|
107003
107310
|
}
|
|
107004
107311
|
export { RulesyncPermissions as $, formatError as $n, isSymlink as $t, CODEBUDDY_DIR as A, MAX_FILE_SIZE as An, withFallbackLoggerTarget as At, CLAUDECODE_LOCAL_RULE_FILE_NAME as B, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as Bn, assertTreeContainsNoSymlinks as Bt, QWENCODE_LOCAL_RULE_FILE_NAME as C, PACKAGING_TOOL_TARGETS as Cn, getSourceTransport as Ct, FACTORYDROID_SETTINGS_LOCAL_FILE_NAME as D, DEPRECATED_FEATURE_REPLACEMENTS as Dn, WarningCollectingLogger as Dt, FACTORYDROID_DIR as E, ALL_FEATURES_WITH_WILDCARD as En, JsonLogger as Et, groupSpellingsByCaseFoldedIdentity as F, RULESYNC_CONFIG_SCHEMA_URL as Fn, PathOutsideRootError as Ft, toInstructionBudgetFile as G, RULESYNC_PERMISSIONS_SCHEMA_URL as Gn, ensureDir as Gt, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as H, RULESYNC_MCP_SCHEMA_URL as Hn, checkPathTraversal as Ht, CODEXCLI_BASH_RULES_FILE_NAME as I, RULESYNC_CURATED_RULES_RELATIVE_DIR_PATH as In, applyFileMode as It, RulesyncSubagentFrontmatterSchema as J, RULESYNC_SKILLS_RELATIVE_DIR_PATH as Jn, findFilesByGlobs as Jt, getLocalSkillDirNames as K, RULESYNC_RELATIVE_DIR_PATH as Kn, fileExists as Kt, CODEXCLI_DIR as L, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as Ln, assertDirectoryIfExists as Lt, AUGMENTCODE_DIR as M, RULESYNC_CHECKS_RELATIVE_DIR_PATH as Mn, withWarnOnceScope as Mt, AUGMENTCODE_SETTINGS_LOCAL_FILE_NAME as N, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as Nn, CLIError as Nt, COMMANDCODE_DIR as O, CURATED_RULES_FEATURE_SUBDIR as On, fallbackLogger as Ot, caseFoldIdentity as P, RULESYNC_CONFIG_RELATIVE_FILE_PATH as Pn, ErrorCodes as Pt, RulesyncRuleFrontmatterSchema as Q, RULESYNC_XDG_CONFIG_HOME_DEFAULT_DIR_NAME as Qn, isFileSystemError as Qt, CLAUDECODE_AGENT_MEMORY_LOCAL_DIR_NAME as R, RULESYNC_HOOKS_RELATIVE_FILE_PATH as Rn, assertNoSymlinkBelowRoot as Rt, QWENCODE_DIR as S, ALL_TOOL_TARGETS_WITH_WILDCARD as Sn, assertTargetsFeaturesExclusive as St, LETTACODE_SETTINGS_LOCAL_FILE_NAME as T, ALL_FEATURES as Tn, ConsoleLogger as Tt, CLAUDECODE_SKILLS_DIR_PATH as U, RULESYNC_NPM_SOURCES_LOCK_RELATIVE_FILE_PATH as Un, createTempDirectory as Ut, CLAUDECODE_MEMORIES_DIR_NAME as V, RULESYNC_MCP_RELATIVE_FILE_PATH as Vn, assertWritablePathInsideRoot as Vt, findProjectInstructionBudgetFindings as W, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as Wn, directoryExists as Wt, RulesyncSkillFrontmatterSchema as X, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as Xn, getHomeDirectory as Xt, RulesyncSkill as Y, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as Yn, getFileSizeAndExecutableBit as Yt, RulesyncRule as Z, RULESYNC_USER_CONFIG_DIR_NAME as Zn, isFileNotFoundError as Zt, SubagentsProcessor as _, toPosixPath as _n, resolveEffectiveInputRoots as _t, convertFromTool as a, readFileContent as an, stripControlCharactersKeepingLineFeeds as ar, parseJsonc as at, CommandsProcessor as b, mapWithConcurrency as bn, GITIGNORE_DESTINATION_KEY as bt, parseCommaSeparatedList as c, removeDirectoryStrict as cn, RulesyncCheck as ct, shortenToWidth as d, removeFileWithoutFollowingSymlinks as dn, loadYaml as dt, listDirectoryEntryNames as en, truncateText as er, RulesyncMcp as et, McpProcessor as f, removeTempDirectory as fn, isRecord as ft, RulesProcessor as g, splitPathSegments as gn, mergeInputRootConfigs as gt, ChecksProcessor as h, runWithDirectoryRollback as hn, ConfigResolver as ht, inspectInputRoots as i, posixRelativePathEscapesRoot as in, stripControlCharacters as ir, resolveRulesyncSourceWritePath as it, CODEBUDDY_LOCAL_RULE_FILE_NAME as j, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as jn, resetRunWarningState as jt, COMMANDCODE_SETTINGS_LOCAL_FILE_NAME as k, FEATURE_SOURCE_TREE_ENTRIES as kn, warnOnConflictingFlags as kt, ELLIPSIS_WIDTH as l, removeFile as ln, RulesyncCheckFrontmatterSchema as lt, HooksProcessor as m, resolvedRelativePath as mn, SKILL_FILE_NAME as mt, formatSourceLoadFailure as n, listSubdirectoryNames as nn, hasEnclosingMarkOutsideKeycap as nr, RulesyncHooks as nt, isPackagingToolTarget as o, readFileContentOrNull as on, stripControlCharactersKeepingLineFeedsAndTabs as or, RulesyncCommand as ot, IgnoreProcessor as p, resolvePath as pn, SHARED_USER_MANAGED_CONFIG_PATHS as pt, RulesyncSubagent as q, RULESYNC_RULES_RELATIVE_DIR_PATH as qn, fileExistsStrict as qt, generate as r, pathEscapesRoot as rn, quoteForLog as rr, getRulesyncSourceCandidates as rt, getProcessorRegistryEntry as s, removeDirectory as sn, stripHiddenCharacters as sr, RulesyncCommandFrontmatterSchema as st, importFromTool as t, listFilePathsRecursively as tn, hasDeceptiveHiddenCharacters as tr, RulesyncIgnore as tt, displayWidthOf as u, removeFileStrict as un, stringifyFrontmatter as ut, SkillsProcessor as v, writeFileBuffer as vn, CONFLICTING_TARGET_PAIRS as vt, LETTACODE_DIR as w, ToolTargetSchema as wn, findControlCharacter as wt, REASONIX_LOCAL_RULE_FILE_NAME as x, ALL_TOOL_TARGETS as xn, SourceEntrySchema as xt, CRUSH_LOCAL_RULE_FILE_NAME as y, writeFileContent as yn, ConfigFileSchema as yt, CLAUDECODE_DIR as z, RULESYNC_IGNORE_RELATIVE_FILE_PATH as zn, assertPathResolvesInsideRoot as zt };
|
|
107005
107312
|
|
|
107006
|
-
//# sourceMappingURL=import-
|
|
107313
|
+
//# sourceMappingURL=import-D2mUPFM0.js.map
|