rulesync 16.10.0 → 16.12.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 +2 -1
- package/dist/cli/index.cjs +473 -113
- package/dist/cli/index.js +473 -113
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-danhPI2x.cjs → import-BwdPcfzS.cjs} +337 -82
- package/dist/{import-CXJwVed1.js → import-zGCKgpdt.js} +338 -83
- package/dist/import-zGCKgpdt.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-CXJwVed1.js.map +0 -1
|
@@ -866,6 +866,7 @@ const ErrorCodes = {
|
|
|
866
866
|
INIT_FAILED: "INIT_FAILED",
|
|
867
867
|
MCP_FAILED: "MCP_FAILED",
|
|
868
868
|
DOCTOR_FAILED: "DOCTOR_FAILED",
|
|
869
|
+
RELEASE_NOTES_FAILED: "RELEASE_NOTES_FAILED",
|
|
869
870
|
UNKNOWN_ERROR: "UNKNOWN_ERROR"
|
|
870
871
|
};
|
|
871
872
|
/**
|
|
@@ -2452,38 +2453,67 @@ const AMP_HOOK_EVENTS = [
|
|
|
2452
2453
|
];
|
|
2453
2454
|
/**
|
|
2454
2455
|
* Hook events supported by Cline's file-based hooks. Cline resolves one
|
|
2455
|
-
* executable per lifecycle event from its hooks directory, and the
|
|
2456
|
-
*
|
|
2457
|
-
*
|
|
2458
|
-
*
|
|
2459
|
-
* `
|
|
2456
|
+
* executable per lifecycle event from its hooks directory, and the accepted
|
|
2457
|
+
* event names come from two runtimes that read the same directory:
|
|
2458
|
+
*
|
|
2459
|
+
* - The VS Code extension fixes them in `VALID_HOOK_TYPES`
|
|
2460
|
+
* (`apps/vscode/src/core/hooks/utils.ts`): `TaskStart`, `TaskResume`,
|
|
2461
|
+
* `TaskCancel`, `TaskComplete`, `PreToolUse`, `PostToolUse`,
|
|
2462
|
+
* `UserPromptSubmit`, `Notification` and `PreCompact`.
|
|
2463
|
+
* - The SDK/CLI fixes them in `HookConfigFileName`
|
|
2464
|
+
* (`sdk/packages/core/src/hooks/hook-file-config.ts`), which drops
|
|
2465
|
+
* `Notification` but adds `TaskError` (→ `agent_error`) and
|
|
2466
|
+
* `SessionShutdown` (→ `session_shutdown`).
|
|
2467
|
+
*
|
|
2468
|
+
* This set is the union, because `.clinerules/hooks` is in both runtimes'
|
|
2469
|
+
* search paths and a script named for an event the running one does not know
|
|
2470
|
+
* is simply never spawned. That holds for unknown *names* only: for an event a
|
|
2471
|
+
* runtime does know, the SDK/CLI spawns both the extensionless script and its
|
|
2472
|
+
* `.ps1` twin, so each generated script opens with a guard that stands down on
|
|
2473
|
+
* the platform the other one owns — see `generateClineHookScript` and
|
|
2474
|
+
* `generateClineHookPowerShellScript`.
|
|
2460
2475
|
*
|
|
2461
2476
|
* `TaskResume` and `TaskCancel` have no canonical counterpart and stay
|
|
2462
2477
|
* unmapped rather than being approximated by `sessionEnd` / `stop`, whose
|
|
2463
2478
|
* semantics differ.
|
|
2464
2479
|
*
|
|
2465
2480
|
* @see https://github.com/cline/cline/blob/main/apps/vscode/src/core/hooks/utils.ts
|
|
2481
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/hooks/hook-file-config.ts
|
|
2466
2482
|
*/
|
|
2467
2483
|
const CLINE_HOOK_EVENTS = [
|
|
2468
2484
|
"sessionStart",
|
|
2485
|
+
"sessionEnd",
|
|
2469
2486
|
"preToolUse",
|
|
2470
2487
|
"postToolUse",
|
|
2471
2488
|
"beforeSubmitPrompt",
|
|
2472
2489
|
"preCompact",
|
|
2473
2490
|
"notification",
|
|
2474
|
-
"taskCompleted"
|
|
2491
|
+
"taskCompleted",
|
|
2492
|
+
"afterError"
|
|
2475
2493
|
];
|
|
2476
2494
|
/**
|
|
2477
2495
|
* Hook events supported by GitHub Copilot (cloud coding agent).
|
|
2478
2496
|
*
|
|
2479
|
-
*
|
|
2497
|
+
* The events rulesync writes to `.github/hooks/*.json`:
|
|
2480
2498
|
* `sessionStart`, `sessionEnd`, `userPromptSubmitted` ← `beforeSubmitPrompt`,
|
|
2481
|
-
* `preToolUse`, `postToolUse`, `agentStop` ← `stop`,
|
|
2482
|
-
* `errorOccurred` ← `afterError
|
|
2483
|
-
*
|
|
2499
|
+
* `preToolUse`, `postToolUse`, `postToolUseFailure`, `agentStop` ← `stop`,
|
|
2500
|
+
* `subagentStart`, `subagentStop`, `errorOccurred` ← `afterError`,
|
|
2501
|
+
* `preCompact`, and `userPromptTransformed` ← `userPromptExpansion`.
|
|
2502
|
+
*
|
|
2503
|
+
* `preCompact` and `subagentStart` are authorable because the unified hooks
|
|
2504
|
+
* reference's per-event "Cloud agent" column says both fire there. That column
|
|
2505
|
+
* is the authority for this set: the older cloud-agent concept page still
|
|
2506
|
+
* lists only the eight events this set began as, and re-narrowing to it would
|
|
2507
|
+
* undo that. `notification` and `permissionRequest` stay out because the same
|
|
2508
|
+
* column is explicit that they do not fire on the cloud agent.
|
|
2509
|
+
*
|
|
2510
|
+
* `postToolUseFailure` and `userPromptTransformed` are shared with
|
|
2511
|
+
* {@link COPILOTCLI_HOOK_EVENTS}; the same column records both as firing on the
|
|
2512
|
+
* cloud agent, so they are authorable here too. The event surfaces overlap but
|
|
2513
|
+
* the config surfaces do not: `copilot` emits `command` hooks only, while the
|
|
2514
|
+
* CLI adapter also handles `http` and `prompt`.
|
|
2484
2515
|
*
|
|
2485
|
-
* @see https://docs.github.com/en/copilot/
|
|
2486
|
-
* @see https://docs.github.com/en/copilot/concepts/agents/hooks
|
|
2516
|
+
* @see https://docs.github.com/en/copilot/reference/hooks-reference
|
|
2487
2517
|
*/
|
|
2488
2518
|
const COPILOT_HOOK_EVENTS = [
|
|
2489
2519
|
"sessionStart",
|
|
@@ -2491,9 +2521,13 @@ const COPILOT_HOOK_EVENTS = [
|
|
|
2491
2521
|
"beforeSubmitPrompt",
|
|
2492
2522
|
"preToolUse",
|
|
2493
2523
|
"postToolUse",
|
|
2524
|
+
"postToolUseFailure",
|
|
2494
2525
|
"stop",
|
|
2526
|
+
"subagentStart",
|
|
2495
2527
|
"subagentStop",
|
|
2496
|
-
"afterError"
|
|
2528
|
+
"afterError",
|
|
2529
|
+
"preCompact",
|
|
2530
|
+
"userPromptExpansion"
|
|
2497
2531
|
];
|
|
2498
2532
|
/**
|
|
2499
2533
|
* Hook events supported by the GitHub Copilot CLI (`copilotcli-hooks.ts`).
|
|
@@ -3209,15 +3243,21 @@ const CANONICAL_TO_AMP_EVENT_NAMES = {
|
|
|
3209
3243
|
beforeSubmitPrompt: "agent.start",
|
|
3210
3244
|
stop: "agent.end"
|
|
3211
3245
|
};
|
|
3212
|
-
/**
|
|
3246
|
+
/**
|
|
3247
|
+
* Map canonical hook events to Cline's hook script file names — the union of
|
|
3248
|
+
* the VS Code extension's `VALID_HOOK_TYPES` and the SDK/CLI's
|
|
3249
|
+
* `HookConfigFileName`, see {@link CLINE_HOOK_EVENTS}.
|
|
3250
|
+
*/
|
|
3213
3251
|
const CANONICAL_TO_CLINE_EVENT_NAMES = {
|
|
3214
3252
|
sessionStart: "TaskStart",
|
|
3253
|
+
sessionEnd: "SessionShutdown",
|
|
3215
3254
|
preToolUse: "PreToolUse",
|
|
3216
3255
|
postToolUse: "PostToolUse",
|
|
3217
3256
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
3218
3257
|
preCompact: "PreCompact",
|
|
3219
3258
|
notification: "Notification",
|
|
3220
|
-
taskCompleted: "TaskComplete"
|
|
3259
|
+
taskCompleted: "TaskComplete",
|
|
3260
|
+
afterError: "TaskError"
|
|
3221
3261
|
};
|
|
3222
3262
|
/**
|
|
3223
3263
|
* Map canonical camelCase event names to Copilot camelCase.
|
|
@@ -3228,9 +3268,13 @@ const CANONICAL_TO_COPILOT_EVENT_NAMES = {
|
|
|
3228
3268
|
beforeSubmitPrompt: "userPromptSubmitted",
|
|
3229
3269
|
preToolUse: "preToolUse",
|
|
3230
3270
|
postToolUse: "postToolUse",
|
|
3271
|
+
postToolUseFailure: "postToolUseFailure",
|
|
3231
3272
|
stop: "agentStop",
|
|
3273
|
+
subagentStart: "subagentStart",
|
|
3232
3274
|
subagentStop: "subagentStop",
|
|
3233
|
-
afterError: "errorOccurred"
|
|
3275
|
+
afterError: "errorOccurred",
|
|
3276
|
+
preCompact: "preCompact",
|
|
3277
|
+
userPromptExpansion: "userPromptTransformed"
|
|
3234
3278
|
};
|
|
3235
3279
|
/**
|
|
3236
3280
|
* Map Copilot camelCase event names to canonical camelCase.
|
|
@@ -5455,6 +5499,7 @@ const RulesyncSkillFrontmatterSchema = z.looseObject({
|
|
|
5455
5499
|
})),
|
|
5456
5500
|
cline: z.optional(z.looseObject({})),
|
|
5457
5501
|
roo: z.optional(z.looseObject({})),
|
|
5502
|
+
amp: z.optional(z.looseObject({})),
|
|
5458
5503
|
devin: z.optional(z.looseObject({
|
|
5459
5504
|
"argument-hint": z.optional(z.string()),
|
|
5460
5505
|
model: z.optional(z.string()),
|
|
@@ -11687,7 +11732,8 @@ const KiloCommandFrontmatterSchema = z.looseObject({
|
|
|
11687
11732
|
description: z.optional(z.string()),
|
|
11688
11733
|
agent: z.optional(z.string()),
|
|
11689
11734
|
subtask: z.optional(z.boolean()),
|
|
11690
|
-
model: z.optional(z.string())
|
|
11735
|
+
model: z.optional(z.string()),
|
|
11736
|
+
variant: z.optional(z.string())
|
|
11691
11737
|
});
|
|
11692
11738
|
var KiloCommand = class KiloCommand extends ToolCommand {
|
|
11693
11739
|
frontmatter;
|
|
@@ -15369,6 +15415,13 @@ function generateClineHookScript({ event, commands }) {
|
|
|
15369
15415
|
`# ${event} hook generated by rulesync — edit .rulesync/hooks.jsonc and regenerate.`,
|
|
15370
15416
|
`# ${CLINE_HOOK_SCRIPT_MARKER}`,
|
|
15371
15417
|
"",
|
|
15418
|
+
"case \"${OSTYPE:-$(uname -s 2>/dev/null || true)}\" in",
|
|
15419
|
+
" msys*|MSYS*|cygwin*|CYGWIN*|MINGW*|mingw*)",
|
|
15420
|
+
` printf '{"cancel": false, "contextModification": "", "errorMessage": ""}\\n'`,
|
|
15421
|
+
" exit 0",
|
|
15422
|
+
" ;;",
|
|
15423
|
+
"esac",
|
|
15424
|
+
"",
|
|
15372
15425
|
"payload=$(cat)",
|
|
15373
15426
|
"cancel=false",
|
|
15374
15427
|
"error_message=''",
|
|
@@ -15382,15 +15435,39 @@ function generateClineHookScript({ event, commands }) {
|
|
|
15382
15435
|
return lines.join("\n");
|
|
15383
15436
|
}
|
|
15384
15437
|
/**
|
|
15385
|
-
* The PowerShell twin of {@link generateClineHookScript}. On Windows
|
|
15386
|
-
* resolves only `<Event>.ps1` and runs it through `powershell -File`,
|
|
15387
|
-
* spellings are written and the platform picks one.
|
|
15438
|
+
* The PowerShell twin of {@link generateClineHookScript}. On Windows the VS Code
|
|
15439
|
+
* extension resolves only `<Event>.ps1` and runs it through `powershell -File`,
|
|
15440
|
+
* so both spellings are written and the platform picks one.
|
|
15441
|
+
*
|
|
15442
|
+
* The SDK/CLI runtime does not pick one. `listHookConfigFiles` dedupes by path,
|
|
15443
|
+
* so `TaskError` and `TaskError.ps1` are two entries naming the same event, and
|
|
15444
|
+
* `createHookCommandMap` appends both to that event's command list without a
|
|
15445
|
+
* per-event dedupe — it then runs every command in the list, spawning a `.ps1`
|
|
15446
|
+
* through `pwsh` on Unix too. That produced noise rather than a second
|
|
15447
|
+
* execution (the body shells out through `cmd /c`, which Unix has no such
|
|
15448
|
+
* thing), but it is still a failure reported on every fire.
|
|
15449
|
+
*
|
|
15450
|
+
* Hence the leading platform guard: off Windows the script answers with the
|
|
15451
|
+
* neutral success payload and exits, leaving the POSIX twin to do the work.
|
|
15452
|
+
* Its counterpart at the top of {@link generateClineHookScript} covers the
|
|
15453
|
+
* quadrant where the duplication is real — Windows with a POSIX shell.
|
|
15454
|
+
* `$IsWindows` only exists in PowerShell 6+, and is `$null` under the Windows
|
|
15455
|
+
* PowerShell 5.1 that `powershell -File` starts — so the guard tests that it is
|
|
15456
|
+
* defined *and* false, rather than `-not $IsWindows`, which would be true on
|
|
15457
|
+
* 5.1 and would no-op the script on the one platform it exists for.
|
|
15458
|
+
*
|
|
15459
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/hooks/hook-file-hooks.ts
|
|
15388
15460
|
*/
|
|
15389
15461
|
function generateClineHookPowerShellScript({ event, commands }) {
|
|
15390
15462
|
const lines = [
|
|
15391
15463
|
`# ${event} hook generated by rulesync — edit .rulesync/hooks.jsonc and regenerate.`,
|
|
15392
15464
|
`# ${CLINE_HOOK_SCRIPT_MARKER}`,
|
|
15393
15465
|
"",
|
|
15466
|
+
"if ($null -ne $IsWindows -and -not $IsWindows) {",
|
|
15467
|
+
` Write-Output '{"cancel": false, "contextModification": "", "errorMessage": ""}'`,
|
|
15468
|
+
" exit 0",
|
|
15469
|
+
"}",
|
|
15470
|
+
"",
|
|
15394
15471
|
"$payload = [Console]::In.ReadToEnd()",
|
|
15395
15472
|
"$cancel = $false",
|
|
15396
15473
|
"$errorMessage = ''",
|
|
@@ -15452,10 +15529,14 @@ var ClineHookScript = class extends ToolFile {
|
|
|
15452
15529
|
* by the contract, so every generated script carries a marker line and a script
|
|
15453
15530
|
* without it is never overwritten.
|
|
15454
15531
|
*
|
|
15455
|
-
*
|
|
15456
|
-
*
|
|
15532
|
+
* The project hooks directory is in the search paths of both the VS Code
|
|
15533
|
+
* extension and the SDK/CLI, whose accepted event names differ slightly, so the
|
|
15534
|
+
* emitted set is their union ({@link CANONICAL_TO_CLINE_EVENT_NAMES}). Cline's
|
|
15535
|
+
* in-process hook surface (`AgentHooks` from `@cline/core`) is a separate
|
|
15536
|
+
* mechanism this adapter does not target.
|
|
15457
15537
|
*
|
|
15458
15538
|
* @see https://github.com/cline/cline/blob/main/apps/vscode/src/core/hooks/utils.ts
|
|
15539
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/hooks/hook-file-config.ts
|
|
15459
15540
|
*/
|
|
15460
15541
|
var ClineHooks = class ClineHooks extends ToolHooks {
|
|
15461
15542
|
scriptsByEvent;
|
|
@@ -15610,6 +15691,11 @@ const CODEXCLI_CONVERTER_CONFIG = {
|
|
|
15610
15691
|
numberPassthroughFields: [{
|
|
15611
15692
|
canonical: "additionalContextLimit",
|
|
15612
15693
|
tool: "additionalContextLimit"
|
|
15694
|
+
}],
|
|
15695
|
+
booleanPassthroughFields: [{
|
|
15696
|
+
canonical: "async",
|
|
15697
|
+
tool: "async",
|
|
15698
|
+
commandOnly: true
|
|
15613
15699
|
}]
|
|
15614
15700
|
};
|
|
15615
15701
|
/**
|
|
@@ -16736,6 +16822,16 @@ const FACTORYDROID_CONVERTER_CONFIG = {
|
|
|
16736
16822
|
subdividesGroup: true
|
|
16737
16823
|
}]
|
|
16738
16824
|
};
|
|
16825
|
+
/** Droid's nine event names, the keys a standalone `hooks.json` is made of. */
|
|
16826
|
+
const FACTORYDROID_EVENT_NAMES = new Set(Object.values(CANONICAL_TO_FACTORYDROID_EVENT_NAMES));
|
|
16827
|
+
/**
|
|
16828
|
+
* Whether a parsed hooks file is the standalone shape — keyed directly by event
|
|
16829
|
+
* name — rather than the `settings.json` shape that wraps the same map in a
|
|
16830
|
+
* `hooks` key.
|
|
16831
|
+
*/
|
|
16832
|
+
function hasFactorydroidEventKey(parsed) {
|
|
16833
|
+
return Object.keys(parsed).some((key) => FACTORYDROID_EVENT_NAMES.has(key));
|
|
16834
|
+
}
|
|
16739
16835
|
var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
16740
16836
|
constructor(params) {
|
|
16741
16837
|
super({
|
|
@@ -16763,14 +16859,6 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
16763
16859
|
}
|
|
16764
16860
|
static async fromRulesyncHooks({ outputRoot = process.cwd(), rulesyncHooks, validate = true, global = false, logger }) {
|
|
16765
16861
|
const paths = FactorydroidHooks.getSettablePaths({ global });
|
|
16766
|
-
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
16767
|
-
const existingContent = await readFileContentOrNull(filePath) ?? JSON.stringify({}, null, 2);
|
|
16768
|
-
let settings;
|
|
16769
|
-
try {
|
|
16770
|
-
settings = JSON.parse(existingContent);
|
|
16771
|
-
} catch (error) {
|
|
16772
|
-
throw new Error(`Failed to parse existing Factory Droid hooks file at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
16773
|
-
}
|
|
16774
16862
|
const config = rulesyncHooks.getJson();
|
|
16775
16863
|
const factorydroidHooks = canonicalToToolHooks({
|
|
16776
16864
|
config,
|
|
@@ -16778,11 +16866,7 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
16778
16866
|
converterConfig: FACTORYDROID_CONVERTER_CONFIG,
|
|
16779
16867
|
logger
|
|
16780
16868
|
});
|
|
16781
|
-
const
|
|
16782
|
-
...settings,
|
|
16783
|
-
hooks: factorydroidHooks
|
|
16784
|
-
};
|
|
16785
|
-
const fileContent = JSON.stringify(merged, null, 2);
|
|
16869
|
+
const fileContent = JSON.stringify(factorydroidHooks, null, 2);
|
|
16786
16870
|
return new FactorydroidHooks({
|
|
16787
16871
|
outputRoot,
|
|
16788
16872
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -16792,14 +16876,14 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
16792
16876
|
});
|
|
16793
16877
|
}
|
|
16794
16878
|
toRulesyncHooks({ logger } = {}) {
|
|
16795
|
-
let
|
|
16879
|
+
let parsed;
|
|
16796
16880
|
try {
|
|
16797
|
-
|
|
16881
|
+
parsed = JSON.parse(this.getFileContent());
|
|
16798
16882
|
} catch (error) {
|
|
16799
16883
|
throw new Error(`Failed to parse Factory Droid hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
16800
16884
|
}
|
|
16801
16885
|
const hooks = toolHooksToCanonical({
|
|
16802
|
-
hooks:
|
|
16886
|
+
hooks: hasFactorydroidEventKey(parsed) ? parsed : parsed.hooks,
|
|
16803
16887
|
converterConfig: FACTORYDROID_CONVERTER_CONFIG,
|
|
16804
16888
|
logger
|
|
16805
16889
|
});
|
|
@@ -16934,18 +17018,7 @@ const GROKCLI_CONVERTER_CONFIG = {
|
|
|
16934
17018
|
tool: "env",
|
|
16935
17019
|
commandOnly: true
|
|
16936
17020
|
}],
|
|
16937
|
-
noMatcherEvents: /* @__PURE__ */ new Set([
|
|
16938
|
-
"sessionStart",
|
|
16939
|
-
"sessionEnd",
|
|
16940
|
-
"beforeSubmitPrompt",
|
|
16941
|
-
"stop",
|
|
16942
|
-
"stopFailure",
|
|
16943
|
-
"notification",
|
|
16944
|
-
"subagentStart",
|
|
16945
|
-
"subagentStop",
|
|
16946
|
-
"preCompact",
|
|
16947
|
-
"postCompact"
|
|
16948
|
-
])
|
|
17021
|
+
noMatcherEvents: /* @__PURE__ */ new Set(["stop", "beforeSubmitPrompt"])
|
|
16949
17022
|
};
|
|
16950
17023
|
/**
|
|
16951
17024
|
* Hooks generator for Grok CLI (xAI Grok Build).
|
|
@@ -17045,6 +17118,13 @@ var GrokcliHooks = class GrokcliHooks extends ToolHooks {
|
|
|
17045
17118
|
* @see https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/hooks.md
|
|
17046
17119
|
*/
|
|
17047
17120
|
const HERMESAGENT_MATCHER_EVENTS = /* @__PURE__ */ new Set(["pre_tool_call", "post_tool_call"]);
|
|
17121
|
+
/**
|
|
17122
|
+
* The only Hermes event that can block, and therefore the only one whose
|
|
17123
|
+
* entries accept `fail_closed`. Upstream warns and ignores the key on every
|
|
17124
|
+
* other event ("only blocking-capable events can fail closed").
|
|
17125
|
+
* @see https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/hooks.md
|
|
17126
|
+
*/
|
|
17127
|
+
const HERMESAGENT_FAIL_CLOSED_EVENT = "pre_tool_call";
|
|
17048
17128
|
const HERMESAGENT_CANONICAL_EVENTS = new Set(HERMESAGENT_HOOK_EVENTS);
|
|
17049
17129
|
const HERMESAGENT_NATIVE_EVENTS = new Set(HERMESAGENT_NATIVE_HOOK_EVENTS);
|
|
17050
17130
|
/**
|
|
@@ -17078,7 +17158,9 @@ function isHermesHookEventEntry(key, value) {
|
|
|
17078
17158
|
* unsupported hook types centrally). `matcher` is only carried through for
|
|
17079
17159
|
* `pre_tool_call`/`post_tool_call`; on any other event it is dropped with a
|
|
17080
17160
|
* warning, mirroring how other adapters (e.g. AugmentCode) handle
|
|
17081
|
-
* matcher-less lifecycle events.
|
|
17161
|
+
* matcher-less lifecycle events. The canonical `failClosed` field (shared with
|
|
17162
|
+
* Cursor, whose semantics Hermes copied) becomes `fail_closed`, which upstream
|
|
17163
|
+
* only honours on `pre_tool_call`.
|
|
17082
17164
|
*/
|
|
17083
17165
|
function definitionsToHermesEntries({ event, sourceEvent = event, definitions, logger }) {
|
|
17084
17166
|
const supportsMatcher = HERMESAGENT_MATCHER_EVENTS.has(event);
|
|
@@ -17089,6 +17171,10 @@ function definitionsToHermesEntries({ event, sourceEvent = event, definitions, l
|
|
|
17089
17171
|
if (typeof definition.matcher === "string" && definition.matcher !== "") if (supportsMatcher) entry.matcher = definition.matcher;
|
|
17090
17172
|
else logger?.warn(`matcher "${definition.matcher}" on "${sourceEvent}" hook will be ignored — Hermes Agent only supports matchers on pre_tool_call/post_tool_call`);
|
|
17091
17173
|
if (typeof definition.timeout === "number") entry.timeout = definition.timeout;
|
|
17174
|
+
if (typeof definition.failClosed === "boolean") {
|
|
17175
|
+
if (event === HERMESAGENT_FAIL_CLOSED_EVENT) entry.fail_closed = definition.failClosed;
|
|
17176
|
+
else if (definition.failClosed) logger?.warn(`failClosed on "${sourceEvent}" hook will be ignored — Hermes Agent only supports fail_closed on pre_tool_call`);
|
|
17177
|
+
}
|
|
17092
17178
|
entries.push(entry);
|
|
17093
17179
|
}
|
|
17094
17180
|
return entries;
|
|
@@ -17140,6 +17226,37 @@ function canonicalToHermesHooks({ config, toolOverrideHooks, logger }) {
|
|
|
17140
17226
|
return result;
|
|
17141
17227
|
}
|
|
17142
17228
|
/**
|
|
17229
|
+
* Reads a hook entry's fail-closed flag. Upstream accepts its own `fail_closed`
|
|
17230
|
+
* and the Cursor/Claude Code `failClosed` spelling alike, so both have to be
|
|
17231
|
+
* read back into the single canonical field.
|
|
17232
|
+
*/
|
|
17233
|
+
function readHermesFailClosed(entry) {
|
|
17234
|
+
if (typeof entry.fail_closed === "boolean") return entry.fail_closed;
|
|
17235
|
+
if (typeof entry.failClosed === "boolean") return entry.failClosed;
|
|
17236
|
+
}
|
|
17237
|
+
/**
|
|
17238
|
+
* Converts one serialized Hermes hook entry back into a canonical definition,
|
|
17239
|
+
* or `undefined` when it is not a hook rulesync models (no string `command`).
|
|
17240
|
+
* `matcher` and `fail_closed` are read only on the events upstream honours them
|
|
17241
|
+
* on, so an imported value is never one the next generate warns about and drops.
|
|
17242
|
+
*/
|
|
17243
|
+
function hermesEntryToDefinition({ nativeEvent, raw }) {
|
|
17244
|
+
if (!isRecord$1(raw)) return;
|
|
17245
|
+
const entry = raw;
|
|
17246
|
+
if (typeof entry.command !== "string") return;
|
|
17247
|
+
const def = {
|
|
17248
|
+
type: "command",
|
|
17249
|
+
command: entry.command
|
|
17250
|
+
};
|
|
17251
|
+
if (HERMESAGENT_MATCHER_EVENTS.has(nativeEvent) && typeof entry.matcher === "string" && entry.matcher !== "") def.matcher = entry.matcher;
|
|
17252
|
+
if (typeof entry.timeout === "number") def.timeout = entry.timeout;
|
|
17253
|
+
if (nativeEvent === HERMESAGENT_FAIL_CLOSED_EVENT) {
|
|
17254
|
+
const failClosed = readHermesFailClosed(entry);
|
|
17255
|
+
if (failClosed !== void 0) def.failClosed = failClosed;
|
|
17256
|
+
}
|
|
17257
|
+
return def;
|
|
17258
|
+
}
|
|
17259
|
+
/**
|
|
17143
17260
|
* Reverse {@link canonicalToHermesHooks}: parse Hermes's native
|
|
17144
17261
|
* `hooks: { <event>: [...] }` map back into a canonical event → definition[]
|
|
17145
17262
|
* record. Native events with no canonical equivalent (`pre_verify`,
|
|
@@ -17153,19 +17270,10 @@ function hermesHooksToCanonical(hooks) {
|
|
|
17153
17270
|
if (PROTOTYPE_POLLUTION_KEYS.has(nativeEvent) || !Array.isArray(entries)) continue;
|
|
17154
17271
|
if (!isHermesHookEventEntry(nativeEvent, entries)) continue;
|
|
17155
17272
|
const rulesyncEvent = HERMESAGENT_TO_CANONICAL_EVENT_NAMES[nativeEvent] ?? nativeEvent;
|
|
17156
|
-
const defs =
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
if (typeof entry.command !== "string") continue;
|
|
17161
|
-
const def = {
|
|
17162
|
-
type: "command",
|
|
17163
|
-
command: entry.command
|
|
17164
|
-
};
|
|
17165
|
-
if (HERMESAGENT_MATCHER_EVENTS.has(nativeEvent) && typeof entry.matcher === "string" && entry.matcher !== "") def.matcher = entry.matcher;
|
|
17166
|
-
if (typeof entry.timeout === "number") def.timeout = entry.timeout;
|
|
17167
|
-
defs.push(def);
|
|
17168
|
-
}
|
|
17273
|
+
const defs = entries.map((raw) => hermesEntryToDefinition({
|
|
17274
|
+
nativeEvent,
|
|
17275
|
+
raw
|
|
17276
|
+
})).filter((def) => def !== void 0);
|
|
17169
17277
|
if (defs.length > 0) canonical[rulesyncEvent] = defs;
|
|
17170
17278
|
}
|
|
17171
17279
|
return canonical;
|
|
@@ -23091,6 +23199,78 @@ var CursorMcp = class CursorMcp extends ToolMcp {
|
|
|
23091
23199
|
};
|
|
23092
23200
|
//#endregion
|
|
23093
23201
|
//#region src/features/mcp/deepagents-mcp.ts
|
|
23202
|
+
const TOOL_NAME = "deepagents";
|
|
23203
|
+
/**
|
|
23204
|
+
* Map a canonical transport onto the three dcode accepts.
|
|
23205
|
+
*
|
|
23206
|
+
* `_resolve_server_type` takes `stdio`, `sse` and `http`, plus the aliases
|
|
23207
|
+
* `streamable_http` / `streamable-http` → `http`. Rulesync's canonical
|
|
23208
|
+
* vocabulary is wider: `local` and `ws` are spellings dcode rejects outright,
|
|
23209
|
+
* and a rejected server is dropped at load time with only a log line. `local`
|
|
23210
|
+
* has an exact equivalent so it is translated; `ws` has none and is skipped at
|
|
23211
|
+
* generate time instead, where the warning can still reach the author.
|
|
23212
|
+
*
|
|
23213
|
+
* @see https://docs.langchain.com/oss/deepagents/code/mcp-tools
|
|
23214
|
+
*/
|
|
23215
|
+
function normalizeDeepagentsTransport(transport) {
|
|
23216
|
+
switch (transport) {
|
|
23217
|
+
case "local":
|
|
23218
|
+
case "stdio": return "stdio";
|
|
23219
|
+
case "streamable-http":
|
|
23220
|
+
case "streamable_http":
|
|
23221
|
+
case "http": return "http";
|
|
23222
|
+
case "sse": return "sse";
|
|
23223
|
+
default: return;
|
|
23224
|
+
}
|
|
23225
|
+
}
|
|
23226
|
+
/**
|
|
23227
|
+
* Translate one canonical server into dcode's `.mcp.json` shape, or `null` to
|
|
23228
|
+
* skip it.
|
|
23229
|
+
*
|
|
23230
|
+
* Two upstream constraints from `_validate_tool_filter_fields` are enforced
|
|
23231
|
+
* here, because breaking either one makes dcode drop the whole server: the two
|
|
23232
|
+
* filters are mutually exclusive on a single server, and neither may be an
|
|
23233
|
+
* empty list.
|
|
23234
|
+
*/
|
|
23235
|
+
function toDeepagentsServer({ name, server, logger }) {
|
|
23236
|
+
const rawTransport = server.transport ?? server.type;
|
|
23237
|
+
if (rawTransport === "ws") return warnAndSkipMcpServer({
|
|
23238
|
+
toolName: TOOL_NAME,
|
|
23239
|
+
serverName: name,
|
|
23240
|
+
reason: "the WebSocket transport, which deepagents does not support",
|
|
23241
|
+
logger
|
|
23242
|
+
});
|
|
23243
|
+
const { enabledTools, disabledTools, type: _type, transport, ...rest } = server;
|
|
23244
|
+
const converted = { ...rest };
|
|
23245
|
+
const normalized = normalizeDeepagentsTransport(rawTransport);
|
|
23246
|
+
if (normalized !== void 0) if (transport !== void 0) converted.transport = normalized;
|
|
23247
|
+
else converted.type = normalized;
|
|
23248
|
+
if (enabledTools !== void 0 && disabledTools !== void 0) return warnAndSkipMcpServer({
|
|
23249
|
+
toolName: TOOL_NAME,
|
|
23250
|
+
serverName: name,
|
|
23251
|
+
reason: "both enabledTools and disabledTools, which deepagents rejects — pick one",
|
|
23252
|
+
logger
|
|
23253
|
+
});
|
|
23254
|
+
if (enabledTools !== void 0) {
|
|
23255
|
+
if (enabledTools.length === 0) return warnAndSkipMcpServer({
|
|
23256
|
+
toolName: TOOL_NAME,
|
|
23257
|
+
serverName: name,
|
|
23258
|
+
reason: "an empty enabledTools list, which allows no tools at all and which deepagents rejects",
|
|
23259
|
+
logger
|
|
23260
|
+
});
|
|
23261
|
+
converted.allowedTools = enabledTools;
|
|
23262
|
+
} else if (disabledTools !== void 0) if (disabledTools.length === 0) logger?.warn(`${TOOL_NAME} MCP: dropping the empty disabledTools list on "${name}"; it denies nothing, and deepagents rejects the empty form.`);
|
|
23263
|
+
else converted.disabledTools = disabledTools;
|
|
23264
|
+
return converted;
|
|
23265
|
+
}
|
|
23266
|
+
/** Lift dcode's spellings back into the canonical model. */
|
|
23267
|
+
function toRulesyncServer(server) {
|
|
23268
|
+
const { allowedTools, ...rest } = server;
|
|
23269
|
+
const converted = { ...rest };
|
|
23270
|
+
for (const key of ["type", "transport"]) if (converted[key] === "streamable_http" || converted[key] === "streamable-http") converted[key] = "http";
|
|
23271
|
+
if (Array.isArray(allowedTools)) converted.enabledTools = allowedTools;
|
|
23272
|
+
return converted;
|
|
23273
|
+
}
|
|
23094
23274
|
var DeepagentsMcp = class DeepagentsMcp extends ToolMcp {
|
|
23095
23275
|
json;
|
|
23096
23276
|
constructor(params) {
|
|
@@ -23125,12 +23305,22 @@ var DeepagentsMcp = class DeepagentsMcp extends ToolMcp {
|
|
|
23125
23305
|
validate
|
|
23126
23306
|
});
|
|
23127
23307
|
}
|
|
23128
|
-
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
23308
|
+
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false, logger }) {
|
|
23129
23309
|
const paths = this.getSettablePaths({ global });
|
|
23130
23310
|
const fileContent = await readFileContentOrNull(join(outputRoot, paths.relativeDirPath, paths.relativeFilePath)) ?? JSON.stringify({ mcpServers: {} }, null, 2);
|
|
23311
|
+
const json = JSON.parse(fileContent);
|
|
23312
|
+
const mcpServers = {};
|
|
23313
|
+
for (const [name, server] of Object.entries(rulesyncMcp.getMcpServers())) {
|
|
23314
|
+
const converted = toDeepagentsServer({
|
|
23315
|
+
name,
|
|
23316
|
+
server,
|
|
23317
|
+
logger
|
|
23318
|
+
});
|
|
23319
|
+
if (converted !== null) mcpServers[name] = converted;
|
|
23320
|
+
}
|
|
23131
23321
|
const mcpJson = {
|
|
23132
|
-
...
|
|
23133
|
-
mcpServers
|
|
23322
|
+
...json,
|
|
23323
|
+
mcpServers
|
|
23134
23324
|
};
|
|
23135
23325
|
return new DeepagentsMcp({
|
|
23136
23326
|
outputRoot,
|
|
@@ -23141,7 +23331,9 @@ var DeepagentsMcp = class DeepagentsMcp extends ToolMcp {
|
|
|
23141
23331
|
});
|
|
23142
23332
|
}
|
|
23143
23333
|
toRulesyncMcp() {
|
|
23144
|
-
|
|
23334
|
+
const servers = isRecord$1(this.json.mcpServers) ? this.json.mcpServers : {};
|
|
23335
|
+
const mcpServers = Object.fromEntries(Object.entries(servers).map(([name, server]) => [name, isRecord$1(server) ? toRulesyncServer(server) : server]));
|
|
23336
|
+
return this.toRulesyncMcpDefault({ fileContent: JSON.stringify({ mcpServers }, null, 2) });
|
|
23145
23337
|
}
|
|
23146
23338
|
validate() {
|
|
23147
23339
|
return {
|
|
@@ -23846,7 +24038,7 @@ function resolveHermesTimeout(config) {
|
|
|
23846
24038
|
* alias — `auth` (`oauth` for OAuth 2.1/PKCE), mTLS `client_cert` (string PEM
|
|
23847
24039
|
* path, or `[cert, key]`/`[cert, key, password]` list) and `client_key`,
|
|
23848
24040
|
* `connect_timeout` (seconds), `supports_parallel_tool_calls`,
|
|
23849
|
-
* `keepalive_interval`, and `
|
|
24041
|
+
* `keepalive_interval`, `elicitation`, `trust`, and `identity_header` — verbatim
|
|
23850
24042
|
* from `source` to `target`. Field names are identical on both sides (the
|
|
23851
24043
|
* canonical `McpServerSchema` is a `looseObject`), so this serves export and
|
|
23852
24044
|
* import alike. See the Hermes mcp-config-reference.
|
|
@@ -23915,6 +24107,14 @@ function copyHermesAdvancedFields(source, target) {
|
|
|
23915
24107
|
target.elicitation = omitPrototypePollutionKeys(structuredClone(source.elicitation));
|
|
23916
24108
|
copied = true;
|
|
23917
24109
|
}
|
|
24110
|
+
if (typeof source.trust === "string") {
|
|
24111
|
+
target.trust = source.trust;
|
|
24112
|
+
copied = true;
|
|
24113
|
+
}
|
|
24114
|
+
if (isPlainObject$1(source.identity_header)) {
|
|
24115
|
+
target.identity_header = omitPrototypePollutionKeys(structuredClone(source.identity_header));
|
|
24116
|
+
copied = true;
|
|
24117
|
+
}
|
|
23918
24118
|
return copied;
|
|
23919
24119
|
}
|
|
23920
24120
|
/**
|
|
@@ -27148,8 +27348,8 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27148
27348
|
meta: {
|
|
27149
27349
|
supportsProject: true,
|
|
27150
27350
|
supportsGlobal: true,
|
|
27151
|
-
supportsEnabledTools:
|
|
27152
|
-
supportsDisabledTools:
|
|
27351
|
+
supportsEnabledTools: true,
|
|
27352
|
+
supportsDisabledTools: true
|
|
27153
27353
|
}
|
|
27154
27354
|
}],
|
|
27155
27355
|
["factorydroid", {
|
|
@@ -27158,7 +27358,7 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27158
27358
|
supportsProject: true,
|
|
27159
27359
|
supportsGlobal: true,
|
|
27160
27360
|
supportsEnabledTools: false,
|
|
27161
|
-
supportsDisabledTools:
|
|
27361
|
+
supportsDisabledTools: true
|
|
27162
27362
|
}
|
|
27163
27363
|
}],
|
|
27164
27364
|
["goose", {
|
|
@@ -27284,7 +27484,7 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27284
27484
|
supportsProject: true,
|
|
27285
27485
|
supportsGlobal: false,
|
|
27286
27486
|
supportsEnabledTools: false,
|
|
27287
|
-
supportsDisabledTools:
|
|
27487
|
+
supportsDisabledTools: true
|
|
27288
27488
|
}
|
|
27289
27489
|
}],
|
|
27290
27490
|
["zoocode", {
|
|
@@ -27293,7 +27493,7 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27293
27493
|
supportsProject: true,
|
|
27294
27494
|
supportsGlobal: false,
|
|
27295
27495
|
supportsEnabledTools: false,
|
|
27296
|
-
supportsDisabledTools:
|
|
27496
|
+
supportsDisabledTools: true
|
|
27297
27497
|
}
|
|
27298
27498
|
}],
|
|
27299
27499
|
["rovodev", {
|
|
@@ -31220,6 +31420,7 @@ function convertGoosePermissionConfigToRulesync(userPermission) {
|
|
|
31220
31420
|
const GROKCLI_UI_KEY = "ui";
|
|
31221
31421
|
const GROKCLI_PERMISSION_MODE_KEY = "permission_mode";
|
|
31222
31422
|
const GROKCLI_PERMISSION_KEY = "permission";
|
|
31423
|
+
const GROKCLI_AUTO_PERMISSION_MODE = "auto";
|
|
31223
31424
|
const CATCH_ALL_PATTERN$2 = "*";
|
|
31224
31425
|
const MCP_CANONICAL_PREFIX$1 = "mcp__";
|
|
31225
31426
|
const CATEGORY_TO_GROK_TOOL = {
|
|
@@ -31433,8 +31634,9 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
31433
31634
|
deny: buckets.deny,
|
|
31434
31635
|
ask: buckets.ask
|
|
31435
31636
|
};
|
|
31436
|
-
const
|
|
31437
|
-
|
|
31637
|
+
const existingUi = isRecord$1(parsed[GROKCLI_UI_KEY]) ? parsed[GROKCLI_UI_KEY] : {};
|
|
31638
|
+
const uiPatch = global && existingUi[GROKCLI_PERMISSION_MODE_KEY] !== GROKCLI_AUTO_PERMISSION_MODE ? { [GROKCLI_UI_KEY]: {
|
|
31639
|
+
...existingUi,
|
|
31438
31640
|
[GROKCLI_PERMISSION_MODE_KEY]: deriveGrokPermissionMode(config)
|
|
31439
31641
|
} } : {};
|
|
31440
31642
|
return new GrokcliPermissions({
|
|
@@ -36719,11 +36921,12 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
36719
36921
|
};
|
|
36720
36922
|
}
|
|
36721
36923
|
toRulesyncSkill() {
|
|
36722
|
-
const
|
|
36924
|
+
const { name, description, ...ampSection } = this.getFrontmatter();
|
|
36723
36925
|
const rulesyncFrontmatter = {
|
|
36724
|
-
name
|
|
36725
|
-
description
|
|
36726
|
-
targets: ["*"]
|
|
36926
|
+
name,
|
|
36927
|
+
description,
|
|
36928
|
+
targets: ["*"],
|
|
36929
|
+
...Object.keys(ampSection).length > 0 && { amp: ampSection }
|
|
36727
36930
|
};
|
|
36728
36931
|
return new RulesyncSkill({
|
|
36729
36932
|
outputRoot: this.outputRoot,
|
|
@@ -36740,6 +36943,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
36740
36943
|
const settablePaths = AmpSkill.getSettablePaths({ global });
|
|
36741
36944
|
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
|
|
36742
36945
|
const ampFrontmatter = {
|
|
36946
|
+
...rulesyncFrontmatter.amp,
|
|
36743
36947
|
name: rulesyncFrontmatter.name,
|
|
36744
36948
|
description: rulesyncFrontmatter.description
|
|
36745
36949
|
};
|
|
@@ -39166,6 +39370,47 @@ const JunieSkillFrontmatterSchema = z.looseObject({
|
|
|
39166
39370
|
name: z.string(),
|
|
39167
39371
|
description: z.string()
|
|
39168
39372
|
});
|
|
39373
|
+
/** An ATX markdown heading line (`#` … `######`). */
|
|
39374
|
+
const HEADING_LINE = /^#{1,6}(\s|$)/;
|
|
39375
|
+
/**
|
|
39376
|
+
* Junie's own fallback for a `SKILL.md` with no `description`: "If
|
|
39377
|
+
* `description` is not provided in the frontmatter, Junie CLI extracts the
|
|
39378
|
+
* first paragraph of the body content as the description." Headings do not
|
|
39379
|
+
* count as that paragraph — "If the body is also empty or contains only
|
|
39380
|
+
* headings, the skill will fail to load."
|
|
39381
|
+
*
|
|
39382
|
+
* This is import-only. The canonical `RulesyncSkillFrontmatter` requires a
|
|
39383
|
+
* description, so without the fallback a skill Junie itself loads fine aborts
|
|
39384
|
+
* the whole import; generation keeps emitting an explicit description, which
|
|
39385
|
+
* the same docs recommend.
|
|
39386
|
+
*
|
|
39387
|
+
* Heading lines are therefore skipped rather than taken: a body opening with
|
|
39388
|
+
* `# Skill Name` would otherwise import that title as the description and —
|
|
39389
|
+
* because the next generate writes it out explicitly — replace Junie's own
|
|
39390
|
+
* correct fallback with the wrong value everywhere, canonical config included.
|
|
39391
|
+
*
|
|
39392
|
+
* A paragraph runs to the first blank line or heading, and is collapsed onto
|
|
39393
|
+
* one line because it becomes a YAML frontmatter value. A fenced code block is
|
|
39394
|
+
* not treated specially: it is ordinary content, so a body whose first
|
|
39395
|
+
* paragraph is a fence yields the fence text. Returns an empty string when the
|
|
39396
|
+
* body holds no such paragraph, which the caller turns into a skipped skill.
|
|
39397
|
+
*
|
|
39398
|
+
* @see https://junie.jetbrains.com/docs/agent-skills.html
|
|
39399
|
+
*/
|
|
39400
|
+
function deriveDescriptionFromBody(body) {
|
|
39401
|
+
const paragraph = [];
|
|
39402
|
+
for (const rawLine of body.split(/\r?\n/)) {
|
|
39403
|
+
const line = rawLine.trim();
|
|
39404
|
+
if (paragraph.length === 0) {
|
|
39405
|
+
if (line === "" || HEADING_LINE.test(line)) continue;
|
|
39406
|
+
paragraph.push(line);
|
|
39407
|
+
continue;
|
|
39408
|
+
}
|
|
39409
|
+
if (line === "" || HEADING_LINE.test(line)) break;
|
|
39410
|
+
paragraph.push(line);
|
|
39411
|
+
}
|
|
39412
|
+
return paragraph.join(" ").trim();
|
|
39413
|
+
}
|
|
39169
39414
|
/**
|
|
39170
39415
|
* Represents a JetBrains Junie skill directory.
|
|
39171
39416
|
* Skills are stored under the .junie/skills directory with SKILL.md files.
|
|
@@ -39262,7 +39507,16 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
39262
39507
|
...params,
|
|
39263
39508
|
getSettablePaths: JunieSkill.getSettablePaths
|
|
39264
39509
|
});
|
|
39265
|
-
|
|
39510
|
+
let frontmatter = loaded.frontmatter;
|
|
39511
|
+
if (isRecord$1(frontmatter) && frontmatter.description === void 0) {
|
|
39512
|
+
const derived = deriveDescriptionFromBody(loaded.body);
|
|
39513
|
+
if (derived === "") throw new Error(`Cannot import ${join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME)}: it has no description and its body has no paragraph to derive one from, so Junie cannot load it either. Add a description to the frontmatter.`);
|
|
39514
|
+
frontmatter = {
|
|
39515
|
+
...frontmatter,
|
|
39516
|
+
description: derived
|
|
39517
|
+
};
|
|
39518
|
+
}
|
|
39519
|
+
const result = JunieSkillFrontmatterSchema.safeParse(frontmatter);
|
|
39266
39520
|
if (!result.success) {
|
|
39267
39521
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
39268
39522
|
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
@@ -41727,7 +41981,8 @@ const toolSkillFactories = /* @__PURE__ */ new Map([
|
|
|
41727
41981
|
meta: {
|
|
41728
41982
|
supportsProject: true,
|
|
41729
41983
|
supportsSimulated: false,
|
|
41730
|
-
supportsGlobal: true
|
|
41984
|
+
supportsGlobal: true,
|
|
41985
|
+
lenientImport: true
|
|
41731
41986
|
}
|
|
41732
41987
|
}],
|
|
41733
41988
|
["kilo", {
|
|
@@ -54666,4 +54921,4 @@ async function importChecksCore(params) {
|
|
|
54666
54921
|
//#endregion
|
|
54667
54922
|
export { JsonLogger as $, RULESYNC_PERMISSIONS_LEGACY_FILE_NAME as $t, RulesyncRuleFrontmatterSchema as A, ALL_TOOL_TARGETS_WITH_WILDCARD as At, RulesyncCheck as B, RULESYNC_CURATED_RULES_RELATIVE_DIR_PATH as Bt, CODEXCLI_DIR as C, removeTempDirectory as Ct, RulesyncSkill as D, writeFileBuffer as Dt, RulesyncSubagentFrontmatterSchema as E, toPosixPath as Et, getRulesyncSourceCandidates as F, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as Ft, SKILL_FILE_NAME as G, RULESYNC_IGNORE_RELATIVE_FILE_PATH as Gt, stringifyFrontmatter as H, RULESYNC_HOOKS_FILE_NAME as Ht, resolveRulesyncSourceWritePath as I, RULESYNC_CHECKS_RELATIVE_DIR_PATH as It, ConfigFileSchema as J, RULESYNC_MCP_LEGACY_FILE_NAME as Jt, ConfigResolver as K, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as Kt, parseJsonc as L, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as Lt, RulesyncMcp as M, ToolTargetSchema as Mt, RulesyncIgnore as N, MAX_FILE_SIZE as Nt, RulesyncSkillFrontmatterSchema as O, writeFileContent as Ot, RulesyncHooks as P, RULESYNC_AIIGNORE_FILE_NAME as Pt, ConsoleLogger as Q, RULESYNC_PERMISSIONS_FILE_NAME as Qt, RulesyncCommand as R, RULESYNC_CONFIG_RELATIVE_FILE_PATH as Rt, CODEXCLI_BASH_RULES_FILE_NAME as S, removeFileStrict as St, RulesyncSubagent as T, runWithDirectoryRollback as Tt, loadYaml as U, RULESYNC_HOOKS_LEGACY_FILE_NAME as Ut, RulesyncCheckFrontmatterSchema as V, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as Vt, SHARED_USER_MANAGED_CONFIG_PATHS as W, RULESYNC_HOOKS_RELATIVE_FILE_PATH as Wt, SourceEntrySchema as X, RULESYNC_MCP_SCHEMA_URL as Xt, GITIGNORE_DESTINATION_KEY as Y, RULESYNC_MCP_RELATIVE_FILE_PATH as Yt, findControlCharacter as Z, RULESYNC_NPM_SOURCES_LOCK_RELATIVE_FILE_PATH as Zt, CLAUDECODE_LOCAL_RULE_FILE_NAME as _, readFileContent as _t, convertFromTool as a, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as an, assertTreeContainsNoSymlinks as at, CLAUDECODE_SKILLS_DIR_PATH as b, removeDirectoryStrict as bt, SubagentsProcessor as c, ALL_FEATURES_WITH_WILDCARD as cn, createTempDirectory as ct, IgnoreProcessor as d, fileExists as dt, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as en, fallbackLogger as et, HooksProcessor as f, findFilesByGlobs as ft, CLAUDECODE_DIR as g, listDirectoryFiles as gt, QWENCODE_LOCAL_RULE_FILE_NAME as h, isSymlink as ht, getProcessorRegistryEntry as i, RULESYNC_SKILLS_RELATIVE_DIR_PATH as in, assertDirectoryIfExists as it, RulesyncPermissions as j, PACKAGING_TOOL_TARGETS as jt, RulesyncRule as k, ALL_TOOL_TARGETS as kt, SkillsProcessor as l, DEPRECATED_FEATURE_REPLACEMENTS as ln, directoryExists as lt, QWENCODE_DIR as m, getHomeDirectory as mt, checkRulesyncDirExists as n, RULESYNC_RELATIVE_DIR_PATH as nn, CLIError as nt, isPackagingToolTarget as o, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as on, assertWritablePathInsideRoot as ot, CommandsProcessor as p, getFileSize as pt, CONFLICTING_TARGET_PAIRS as q, RULESYNC_MCP_FILE_NAME as qt, generate as r, RULESYNC_RULES_RELATIVE_DIR_PATH as rn, ErrorCodes as rt, RulesProcessor as s, ALL_FEATURES as sn, checkPathTraversal as st, importFromTool as t, RULESYNC_PERMISSIONS_SCHEMA_URL as tn, warnOnConflictingFlags as tt, McpProcessor as u, formatError as un, ensureDir as ut, CLAUDECODE_MEMORIES_DIR_NAME as v, readFileContentOrNull as vt, getLocalSkillDirNames as w, resolvePath as wt, ChecksProcessor as x, removeFile as xt, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as y, removeDirectory as yt, RulesyncCommandFrontmatterSchema as z, RULESYNC_CONFIG_SCHEMA_URL as zt };
|
|
54668
54923
|
|
|
54669
|
-
//# sourceMappingURL=import-
|
|
54924
|
+
//# sourceMappingURL=import-zGCKgpdt.js.map
|