rulesync 16.11.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/dist/cli/index.cjs +473 -113
- package/dist/cli/index.js +473 -113
- package/dist/cli/index.js.map +1 -1
- package/dist/{import--_2cfZlH.cjs → import-BwdPcfzS.cjs} +265 -66
- package/dist/{import-Bgkf_jVN.js → import-zGCKgpdt.js} +266 -67
- 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-Bgkf_jVN.js.map +0 -1
|
@@ -891,6 +891,7 @@ const ErrorCodes = {
|
|
|
891
891
|
INIT_FAILED: "INIT_FAILED",
|
|
892
892
|
MCP_FAILED: "MCP_FAILED",
|
|
893
893
|
DOCTOR_FAILED: "DOCTOR_FAILED",
|
|
894
|
+
RELEASE_NOTES_FAILED: "RELEASE_NOTES_FAILED",
|
|
894
895
|
UNKNOWN_ERROR: "UNKNOWN_ERROR"
|
|
895
896
|
};
|
|
896
897
|
/**
|
|
@@ -2477,34 +2478,52 @@ const AMP_HOOK_EVENTS = [
|
|
|
2477
2478
|
];
|
|
2478
2479
|
/**
|
|
2479
2480
|
* Hook events supported by Cline's file-based hooks. Cline resolves one
|
|
2480
|
-
* executable per lifecycle event from its hooks directory, and the
|
|
2481
|
-
*
|
|
2482
|
-
*
|
|
2483
|
-
*
|
|
2484
|
-
* `
|
|
2481
|
+
* executable per lifecycle event from its hooks directory, and the accepted
|
|
2482
|
+
* event names come from two runtimes that read the same directory:
|
|
2483
|
+
*
|
|
2484
|
+
* - The VS Code extension fixes them in `VALID_HOOK_TYPES`
|
|
2485
|
+
* (`apps/vscode/src/core/hooks/utils.ts`): `TaskStart`, `TaskResume`,
|
|
2486
|
+
* `TaskCancel`, `TaskComplete`, `PreToolUse`, `PostToolUse`,
|
|
2487
|
+
* `UserPromptSubmit`, `Notification` and `PreCompact`.
|
|
2488
|
+
* - The SDK/CLI fixes them in `HookConfigFileName`
|
|
2489
|
+
* (`sdk/packages/core/src/hooks/hook-file-config.ts`), which drops
|
|
2490
|
+
* `Notification` but adds `TaskError` (→ `agent_error`) and
|
|
2491
|
+
* `SessionShutdown` (→ `session_shutdown`).
|
|
2492
|
+
*
|
|
2493
|
+
* This set is the union, because `.clinerules/hooks` is in both runtimes'
|
|
2494
|
+
* search paths and a script named for an event the running one does not know
|
|
2495
|
+
* is simply never spawned. That holds for unknown *names* only: for an event a
|
|
2496
|
+
* runtime does know, the SDK/CLI spawns both the extensionless script and its
|
|
2497
|
+
* `.ps1` twin, so each generated script opens with a guard that stands down on
|
|
2498
|
+
* the platform the other one owns — see `generateClineHookScript` and
|
|
2499
|
+
* `generateClineHookPowerShellScript`.
|
|
2485
2500
|
*
|
|
2486
2501
|
* `TaskResume` and `TaskCancel` have no canonical counterpart and stay
|
|
2487
2502
|
* unmapped rather than being approximated by `sessionEnd` / `stop`, whose
|
|
2488
2503
|
* semantics differ.
|
|
2489
2504
|
*
|
|
2490
2505
|
* @see https://github.com/cline/cline/blob/main/apps/vscode/src/core/hooks/utils.ts
|
|
2506
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/hooks/hook-file-config.ts
|
|
2491
2507
|
*/
|
|
2492
2508
|
const CLINE_HOOK_EVENTS = [
|
|
2493
2509
|
"sessionStart",
|
|
2510
|
+
"sessionEnd",
|
|
2494
2511
|
"preToolUse",
|
|
2495
2512
|
"postToolUse",
|
|
2496
2513
|
"beforeSubmitPrompt",
|
|
2497
2514
|
"preCompact",
|
|
2498
2515
|
"notification",
|
|
2499
|
-
"taskCompleted"
|
|
2516
|
+
"taskCompleted",
|
|
2517
|
+
"afterError"
|
|
2500
2518
|
];
|
|
2501
2519
|
/**
|
|
2502
2520
|
* Hook events supported by GitHub Copilot (cloud coding agent).
|
|
2503
2521
|
*
|
|
2504
2522
|
* The events rulesync writes to `.github/hooks/*.json`:
|
|
2505
2523
|
* `sessionStart`, `sessionEnd`, `userPromptSubmitted` ← `beforeSubmitPrompt`,
|
|
2506
|
-
* `preToolUse`, `postToolUse`, `agentStop` ← `stop`,
|
|
2507
|
-
* `subagentStop`, `errorOccurred` ← `afterError`,
|
|
2524
|
+
* `preToolUse`, `postToolUse`, `postToolUseFailure`, `agentStop` ← `stop`,
|
|
2525
|
+
* `subagentStart`, `subagentStop`, `errorOccurred` ← `afterError`,
|
|
2526
|
+
* `preCompact`, and `userPromptTransformed` ← `userPromptExpansion`.
|
|
2508
2527
|
*
|
|
2509
2528
|
* `preCompact` and `subagentStart` are authorable because the unified hooks
|
|
2510
2529
|
* reference's per-event "Cloud agent" column says both fire there. That column
|
|
@@ -2513,9 +2532,11 @@ const CLINE_HOOK_EVENTS = [
|
|
|
2513
2532
|
* undo that. `notification` and `permissionRequest` stay out because the same
|
|
2514
2533
|
* column is explicit that they do not fire on the cloud agent.
|
|
2515
2534
|
*
|
|
2516
|
-
*
|
|
2517
|
-
*
|
|
2518
|
-
* agent
|
|
2535
|
+
* `postToolUseFailure` and `userPromptTransformed` are shared with
|
|
2536
|
+
* {@link COPILOTCLI_HOOK_EVENTS}; the same column records both as firing on the
|
|
2537
|
+
* cloud agent, so they are authorable here too. The event surfaces overlap but
|
|
2538
|
+
* the config surfaces do not: `copilot` emits `command` hooks only, while the
|
|
2539
|
+
* CLI adapter also handles `http` and `prompt`.
|
|
2519
2540
|
*
|
|
2520
2541
|
* @see https://docs.github.com/en/copilot/reference/hooks-reference
|
|
2521
2542
|
*/
|
|
@@ -2525,11 +2546,13 @@ const COPILOT_HOOK_EVENTS = [
|
|
|
2525
2546
|
"beforeSubmitPrompt",
|
|
2526
2547
|
"preToolUse",
|
|
2527
2548
|
"postToolUse",
|
|
2549
|
+
"postToolUseFailure",
|
|
2528
2550
|
"stop",
|
|
2529
2551
|
"subagentStart",
|
|
2530
2552
|
"subagentStop",
|
|
2531
2553
|
"afterError",
|
|
2532
|
-
"preCompact"
|
|
2554
|
+
"preCompact",
|
|
2555
|
+
"userPromptExpansion"
|
|
2533
2556
|
];
|
|
2534
2557
|
/**
|
|
2535
2558
|
* Hook events supported by the GitHub Copilot CLI (`copilotcli-hooks.ts`).
|
|
@@ -3245,15 +3268,21 @@ const CANONICAL_TO_AMP_EVENT_NAMES = {
|
|
|
3245
3268
|
beforeSubmitPrompt: "agent.start",
|
|
3246
3269
|
stop: "agent.end"
|
|
3247
3270
|
};
|
|
3248
|
-
/**
|
|
3271
|
+
/**
|
|
3272
|
+
* Map canonical hook events to Cline's hook script file names — the union of
|
|
3273
|
+
* the VS Code extension's `VALID_HOOK_TYPES` and the SDK/CLI's
|
|
3274
|
+
* `HookConfigFileName`, see {@link CLINE_HOOK_EVENTS}.
|
|
3275
|
+
*/
|
|
3249
3276
|
const CANONICAL_TO_CLINE_EVENT_NAMES = {
|
|
3250
3277
|
sessionStart: "TaskStart",
|
|
3278
|
+
sessionEnd: "SessionShutdown",
|
|
3251
3279
|
preToolUse: "PreToolUse",
|
|
3252
3280
|
postToolUse: "PostToolUse",
|
|
3253
3281
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
3254
3282
|
preCompact: "PreCompact",
|
|
3255
3283
|
notification: "Notification",
|
|
3256
|
-
taskCompleted: "TaskComplete"
|
|
3284
|
+
taskCompleted: "TaskComplete",
|
|
3285
|
+
afterError: "TaskError"
|
|
3257
3286
|
};
|
|
3258
3287
|
/**
|
|
3259
3288
|
* Map canonical camelCase event names to Copilot camelCase.
|
|
@@ -3264,11 +3293,13 @@ const CANONICAL_TO_COPILOT_EVENT_NAMES = {
|
|
|
3264
3293
|
beforeSubmitPrompt: "userPromptSubmitted",
|
|
3265
3294
|
preToolUse: "preToolUse",
|
|
3266
3295
|
postToolUse: "postToolUse",
|
|
3296
|
+
postToolUseFailure: "postToolUseFailure",
|
|
3267
3297
|
stop: "agentStop",
|
|
3268
3298
|
subagentStart: "subagentStart",
|
|
3269
3299
|
subagentStop: "subagentStop",
|
|
3270
3300
|
afterError: "errorOccurred",
|
|
3271
|
-
preCompact: "preCompact"
|
|
3301
|
+
preCompact: "preCompact",
|
|
3302
|
+
userPromptExpansion: "userPromptTransformed"
|
|
3272
3303
|
};
|
|
3273
3304
|
/**
|
|
3274
3305
|
* Map Copilot camelCase event names to canonical camelCase.
|
|
@@ -5493,6 +5524,7 @@ const RulesyncSkillFrontmatterSchema = zod_mini.z.looseObject({
|
|
|
5493
5524
|
})),
|
|
5494
5525
|
cline: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
5495
5526
|
roo: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
5527
|
+
amp: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
5496
5528
|
devin: zod_mini.z.optional(zod_mini.z.looseObject({
|
|
5497
5529
|
"argument-hint": zod_mini.z.optional(zod_mini.z.string()),
|
|
5498
5530
|
model: zod_mini.z.optional(zod_mini.z.string()),
|
|
@@ -11725,7 +11757,8 @@ const KiloCommandFrontmatterSchema = zod_mini.z.looseObject({
|
|
|
11725
11757
|
description: zod_mini.z.optional(zod_mini.z.string()),
|
|
11726
11758
|
agent: zod_mini.z.optional(zod_mini.z.string()),
|
|
11727
11759
|
subtask: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
11728
|
-
model: zod_mini.z.optional(zod_mini.z.string())
|
|
11760
|
+
model: zod_mini.z.optional(zod_mini.z.string()),
|
|
11761
|
+
variant: zod_mini.z.optional(zod_mini.z.string())
|
|
11729
11762
|
});
|
|
11730
11763
|
var KiloCommand = class KiloCommand extends ToolCommand {
|
|
11731
11764
|
frontmatter;
|
|
@@ -15407,6 +15440,13 @@ function generateClineHookScript({ event, commands }) {
|
|
|
15407
15440
|
`# ${event} hook generated by rulesync — edit .rulesync/hooks.jsonc and regenerate.`,
|
|
15408
15441
|
`# ${CLINE_HOOK_SCRIPT_MARKER}`,
|
|
15409
15442
|
"",
|
|
15443
|
+
"case \"${OSTYPE:-$(uname -s 2>/dev/null || true)}\" in",
|
|
15444
|
+
" msys*|MSYS*|cygwin*|CYGWIN*|MINGW*|mingw*)",
|
|
15445
|
+
` printf '{"cancel": false, "contextModification": "", "errorMessage": ""}\\n'`,
|
|
15446
|
+
" exit 0",
|
|
15447
|
+
" ;;",
|
|
15448
|
+
"esac",
|
|
15449
|
+
"",
|
|
15410
15450
|
"payload=$(cat)",
|
|
15411
15451
|
"cancel=false",
|
|
15412
15452
|
"error_message=''",
|
|
@@ -15420,15 +15460,39 @@ function generateClineHookScript({ event, commands }) {
|
|
|
15420
15460
|
return lines.join("\n");
|
|
15421
15461
|
}
|
|
15422
15462
|
/**
|
|
15423
|
-
* The PowerShell twin of {@link generateClineHookScript}. On Windows
|
|
15424
|
-
* resolves only `<Event>.ps1` and runs it through `powershell -File`,
|
|
15425
|
-
* spellings are written and the platform picks one.
|
|
15463
|
+
* The PowerShell twin of {@link generateClineHookScript}. On Windows the VS Code
|
|
15464
|
+
* extension resolves only `<Event>.ps1` and runs it through `powershell -File`,
|
|
15465
|
+
* so both spellings are written and the platform picks one.
|
|
15466
|
+
*
|
|
15467
|
+
* The SDK/CLI runtime does not pick one. `listHookConfigFiles` dedupes by path,
|
|
15468
|
+
* so `TaskError` and `TaskError.ps1` are two entries naming the same event, and
|
|
15469
|
+
* `createHookCommandMap` appends both to that event's command list without a
|
|
15470
|
+
* per-event dedupe — it then runs every command in the list, spawning a `.ps1`
|
|
15471
|
+
* through `pwsh` on Unix too. That produced noise rather than a second
|
|
15472
|
+
* execution (the body shells out through `cmd /c`, which Unix has no such
|
|
15473
|
+
* thing), but it is still a failure reported on every fire.
|
|
15474
|
+
*
|
|
15475
|
+
* Hence the leading platform guard: off Windows the script answers with the
|
|
15476
|
+
* neutral success payload and exits, leaving the POSIX twin to do the work.
|
|
15477
|
+
* Its counterpart at the top of {@link generateClineHookScript} covers the
|
|
15478
|
+
* quadrant where the duplication is real — Windows with a POSIX shell.
|
|
15479
|
+
* `$IsWindows` only exists in PowerShell 6+, and is `$null` under the Windows
|
|
15480
|
+
* PowerShell 5.1 that `powershell -File` starts — so the guard tests that it is
|
|
15481
|
+
* defined *and* false, rather than `-not $IsWindows`, which would be true on
|
|
15482
|
+
* 5.1 and would no-op the script on the one platform it exists for.
|
|
15483
|
+
*
|
|
15484
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/hooks/hook-file-hooks.ts
|
|
15426
15485
|
*/
|
|
15427
15486
|
function generateClineHookPowerShellScript({ event, commands }) {
|
|
15428
15487
|
const lines = [
|
|
15429
15488
|
`# ${event} hook generated by rulesync — edit .rulesync/hooks.jsonc and regenerate.`,
|
|
15430
15489
|
`# ${CLINE_HOOK_SCRIPT_MARKER}`,
|
|
15431
15490
|
"",
|
|
15491
|
+
"if ($null -ne $IsWindows -and -not $IsWindows) {",
|
|
15492
|
+
` Write-Output '{"cancel": false, "contextModification": "", "errorMessage": ""}'`,
|
|
15493
|
+
" exit 0",
|
|
15494
|
+
"}",
|
|
15495
|
+
"",
|
|
15432
15496
|
"$payload = [Console]::In.ReadToEnd()",
|
|
15433
15497
|
"$cancel = $false",
|
|
15434
15498
|
"$errorMessage = ''",
|
|
@@ -15490,10 +15554,14 @@ var ClineHookScript = class extends ToolFile {
|
|
|
15490
15554
|
* by the contract, so every generated script carries a marker line and a script
|
|
15491
15555
|
* without it is never overwritten.
|
|
15492
15556
|
*
|
|
15493
|
-
*
|
|
15494
|
-
*
|
|
15557
|
+
* The project hooks directory is in the search paths of both the VS Code
|
|
15558
|
+
* extension and the SDK/CLI, whose accepted event names differ slightly, so the
|
|
15559
|
+
* emitted set is their union ({@link CANONICAL_TO_CLINE_EVENT_NAMES}). Cline's
|
|
15560
|
+
* in-process hook surface (`AgentHooks` from `@cline/core`) is a separate
|
|
15561
|
+
* mechanism this adapter does not target.
|
|
15495
15562
|
*
|
|
15496
15563
|
* @see https://github.com/cline/cline/blob/main/apps/vscode/src/core/hooks/utils.ts
|
|
15564
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/hooks/hook-file-config.ts
|
|
15497
15565
|
*/
|
|
15498
15566
|
var ClineHooks = class ClineHooks extends ToolHooks {
|
|
15499
15567
|
scriptsByEvent;
|
|
@@ -15648,6 +15716,11 @@ const CODEXCLI_CONVERTER_CONFIG = {
|
|
|
15648
15716
|
numberPassthroughFields: [{
|
|
15649
15717
|
canonical: "additionalContextLimit",
|
|
15650
15718
|
tool: "additionalContextLimit"
|
|
15719
|
+
}],
|
|
15720
|
+
booleanPassthroughFields: [{
|
|
15721
|
+
canonical: "async",
|
|
15722
|
+
tool: "async",
|
|
15723
|
+
commandOnly: true
|
|
15651
15724
|
}]
|
|
15652
15725
|
};
|
|
15653
15726
|
/**
|
|
@@ -16774,6 +16847,16 @@ const FACTORYDROID_CONVERTER_CONFIG = {
|
|
|
16774
16847
|
subdividesGroup: true
|
|
16775
16848
|
}]
|
|
16776
16849
|
};
|
|
16850
|
+
/** Droid's nine event names, the keys a standalone `hooks.json` is made of. */
|
|
16851
|
+
const FACTORYDROID_EVENT_NAMES = new Set(Object.values(CANONICAL_TO_FACTORYDROID_EVENT_NAMES));
|
|
16852
|
+
/**
|
|
16853
|
+
* Whether a parsed hooks file is the standalone shape — keyed directly by event
|
|
16854
|
+
* name — rather than the `settings.json` shape that wraps the same map in a
|
|
16855
|
+
* `hooks` key.
|
|
16856
|
+
*/
|
|
16857
|
+
function hasFactorydroidEventKey(parsed) {
|
|
16858
|
+
return Object.keys(parsed).some((key) => FACTORYDROID_EVENT_NAMES.has(key));
|
|
16859
|
+
}
|
|
16777
16860
|
var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
16778
16861
|
constructor(params) {
|
|
16779
16862
|
super({
|
|
@@ -16801,14 +16884,6 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
16801
16884
|
}
|
|
16802
16885
|
static async fromRulesyncHooks({ outputRoot = process.cwd(), rulesyncHooks, validate = true, global = false, logger }) {
|
|
16803
16886
|
const paths = FactorydroidHooks.getSettablePaths({ global });
|
|
16804
|
-
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
16805
|
-
const existingContent = await readFileContentOrNull(filePath) ?? JSON.stringify({}, null, 2);
|
|
16806
|
-
let settings;
|
|
16807
|
-
try {
|
|
16808
|
-
settings = JSON.parse(existingContent);
|
|
16809
|
-
} catch (error) {
|
|
16810
|
-
throw new Error(`Failed to parse existing Factory Droid hooks file at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
16811
|
-
}
|
|
16812
16887
|
const config = rulesyncHooks.getJson();
|
|
16813
16888
|
const factorydroidHooks = canonicalToToolHooks({
|
|
16814
16889
|
config,
|
|
@@ -16816,11 +16891,7 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
16816
16891
|
converterConfig: FACTORYDROID_CONVERTER_CONFIG,
|
|
16817
16892
|
logger
|
|
16818
16893
|
});
|
|
16819
|
-
const
|
|
16820
|
-
...settings,
|
|
16821
|
-
hooks: factorydroidHooks
|
|
16822
|
-
};
|
|
16823
|
-
const fileContent = JSON.stringify(merged, null, 2);
|
|
16894
|
+
const fileContent = JSON.stringify(factorydroidHooks, null, 2);
|
|
16824
16895
|
return new FactorydroidHooks({
|
|
16825
16896
|
outputRoot,
|
|
16826
16897
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -16830,14 +16901,14 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
16830
16901
|
});
|
|
16831
16902
|
}
|
|
16832
16903
|
toRulesyncHooks({ logger } = {}) {
|
|
16833
|
-
let
|
|
16904
|
+
let parsed;
|
|
16834
16905
|
try {
|
|
16835
|
-
|
|
16906
|
+
parsed = JSON.parse(this.getFileContent());
|
|
16836
16907
|
} catch (error) {
|
|
16837
16908
|
throw new Error(`Failed to parse Factory Droid hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
16838
16909
|
}
|
|
16839
16910
|
const hooks = toolHooksToCanonical({
|
|
16840
|
-
hooks:
|
|
16911
|
+
hooks: hasFactorydroidEventKey(parsed) ? parsed : parsed.hooks,
|
|
16841
16912
|
converterConfig: FACTORYDROID_CONVERTER_CONFIG,
|
|
16842
16913
|
logger
|
|
16843
16914
|
});
|
|
@@ -16972,18 +17043,7 @@ const GROKCLI_CONVERTER_CONFIG = {
|
|
|
16972
17043
|
tool: "env",
|
|
16973
17044
|
commandOnly: true
|
|
16974
17045
|
}],
|
|
16975
|
-
noMatcherEvents: /* @__PURE__ */ new Set([
|
|
16976
|
-
"sessionStart",
|
|
16977
|
-
"sessionEnd",
|
|
16978
|
-
"beforeSubmitPrompt",
|
|
16979
|
-
"stop",
|
|
16980
|
-
"stopFailure",
|
|
16981
|
-
"notification",
|
|
16982
|
-
"subagentStart",
|
|
16983
|
-
"subagentStop",
|
|
16984
|
-
"preCompact",
|
|
16985
|
-
"postCompact"
|
|
16986
|
-
])
|
|
17046
|
+
noMatcherEvents: /* @__PURE__ */ new Set(["stop", "beforeSubmitPrompt"])
|
|
16987
17047
|
};
|
|
16988
17048
|
/**
|
|
16989
17049
|
* Hooks generator for Grok CLI (xAI Grok Build).
|
|
@@ -23164,6 +23224,78 @@ var CursorMcp = class CursorMcp extends ToolMcp {
|
|
|
23164
23224
|
};
|
|
23165
23225
|
//#endregion
|
|
23166
23226
|
//#region src/features/mcp/deepagents-mcp.ts
|
|
23227
|
+
const TOOL_NAME = "deepagents";
|
|
23228
|
+
/**
|
|
23229
|
+
* Map a canonical transport onto the three dcode accepts.
|
|
23230
|
+
*
|
|
23231
|
+
* `_resolve_server_type` takes `stdio`, `sse` and `http`, plus the aliases
|
|
23232
|
+
* `streamable_http` / `streamable-http` → `http`. Rulesync's canonical
|
|
23233
|
+
* vocabulary is wider: `local` and `ws` are spellings dcode rejects outright,
|
|
23234
|
+
* and a rejected server is dropped at load time with only a log line. `local`
|
|
23235
|
+
* has an exact equivalent so it is translated; `ws` has none and is skipped at
|
|
23236
|
+
* generate time instead, where the warning can still reach the author.
|
|
23237
|
+
*
|
|
23238
|
+
* @see https://docs.langchain.com/oss/deepagents/code/mcp-tools
|
|
23239
|
+
*/
|
|
23240
|
+
function normalizeDeepagentsTransport(transport) {
|
|
23241
|
+
switch (transport) {
|
|
23242
|
+
case "local":
|
|
23243
|
+
case "stdio": return "stdio";
|
|
23244
|
+
case "streamable-http":
|
|
23245
|
+
case "streamable_http":
|
|
23246
|
+
case "http": return "http";
|
|
23247
|
+
case "sse": return "sse";
|
|
23248
|
+
default: return;
|
|
23249
|
+
}
|
|
23250
|
+
}
|
|
23251
|
+
/**
|
|
23252
|
+
* Translate one canonical server into dcode's `.mcp.json` shape, or `null` to
|
|
23253
|
+
* skip it.
|
|
23254
|
+
*
|
|
23255
|
+
* Two upstream constraints from `_validate_tool_filter_fields` are enforced
|
|
23256
|
+
* here, because breaking either one makes dcode drop the whole server: the two
|
|
23257
|
+
* filters are mutually exclusive on a single server, and neither may be an
|
|
23258
|
+
* empty list.
|
|
23259
|
+
*/
|
|
23260
|
+
function toDeepagentsServer({ name, server, logger }) {
|
|
23261
|
+
const rawTransport = server.transport ?? server.type;
|
|
23262
|
+
if (rawTransport === "ws") return warnAndSkipMcpServer({
|
|
23263
|
+
toolName: TOOL_NAME,
|
|
23264
|
+
serverName: name,
|
|
23265
|
+
reason: "the WebSocket transport, which deepagents does not support",
|
|
23266
|
+
logger
|
|
23267
|
+
});
|
|
23268
|
+
const { enabledTools, disabledTools, type: _type, transport, ...rest } = server;
|
|
23269
|
+
const converted = { ...rest };
|
|
23270
|
+
const normalized = normalizeDeepagentsTransport(rawTransport);
|
|
23271
|
+
if (normalized !== void 0) if (transport !== void 0) converted.transport = normalized;
|
|
23272
|
+
else converted.type = normalized;
|
|
23273
|
+
if (enabledTools !== void 0 && disabledTools !== void 0) return warnAndSkipMcpServer({
|
|
23274
|
+
toolName: TOOL_NAME,
|
|
23275
|
+
serverName: name,
|
|
23276
|
+
reason: "both enabledTools and disabledTools, which deepagents rejects — pick one",
|
|
23277
|
+
logger
|
|
23278
|
+
});
|
|
23279
|
+
if (enabledTools !== void 0) {
|
|
23280
|
+
if (enabledTools.length === 0) return warnAndSkipMcpServer({
|
|
23281
|
+
toolName: TOOL_NAME,
|
|
23282
|
+
serverName: name,
|
|
23283
|
+
reason: "an empty enabledTools list, which allows no tools at all and which deepagents rejects",
|
|
23284
|
+
logger
|
|
23285
|
+
});
|
|
23286
|
+
converted.allowedTools = enabledTools;
|
|
23287
|
+
} 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.`);
|
|
23288
|
+
else converted.disabledTools = disabledTools;
|
|
23289
|
+
return converted;
|
|
23290
|
+
}
|
|
23291
|
+
/** Lift dcode's spellings back into the canonical model. */
|
|
23292
|
+
function toRulesyncServer(server) {
|
|
23293
|
+
const { allowedTools, ...rest } = server;
|
|
23294
|
+
const converted = { ...rest };
|
|
23295
|
+
for (const key of ["type", "transport"]) if (converted[key] === "streamable_http" || converted[key] === "streamable-http") converted[key] = "http";
|
|
23296
|
+
if (Array.isArray(allowedTools)) converted.enabledTools = allowedTools;
|
|
23297
|
+
return converted;
|
|
23298
|
+
}
|
|
23167
23299
|
var DeepagentsMcp = class DeepagentsMcp extends ToolMcp {
|
|
23168
23300
|
json;
|
|
23169
23301
|
constructor(params) {
|
|
@@ -23198,12 +23330,22 @@ var DeepagentsMcp = class DeepagentsMcp extends ToolMcp {
|
|
|
23198
23330
|
validate
|
|
23199
23331
|
});
|
|
23200
23332
|
}
|
|
23201
|
-
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
23333
|
+
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false, logger }) {
|
|
23202
23334
|
const paths = this.getSettablePaths({ global });
|
|
23203
23335
|
const fileContent = await readFileContentOrNull((0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath)) ?? JSON.stringify({ mcpServers: {} }, null, 2);
|
|
23336
|
+
const json = JSON.parse(fileContent);
|
|
23337
|
+
const mcpServers = {};
|
|
23338
|
+
for (const [name, server] of Object.entries(rulesyncMcp.getMcpServers())) {
|
|
23339
|
+
const converted = toDeepagentsServer({
|
|
23340
|
+
name,
|
|
23341
|
+
server,
|
|
23342
|
+
logger
|
|
23343
|
+
});
|
|
23344
|
+
if (converted !== null) mcpServers[name] = converted;
|
|
23345
|
+
}
|
|
23204
23346
|
const mcpJson = {
|
|
23205
|
-
...
|
|
23206
|
-
mcpServers
|
|
23347
|
+
...json,
|
|
23348
|
+
mcpServers
|
|
23207
23349
|
};
|
|
23208
23350
|
return new DeepagentsMcp({
|
|
23209
23351
|
outputRoot,
|
|
@@ -23214,7 +23356,9 @@ var DeepagentsMcp = class DeepagentsMcp extends ToolMcp {
|
|
|
23214
23356
|
});
|
|
23215
23357
|
}
|
|
23216
23358
|
toRulesyncMcp() {
|
|
23217
|
-
|
|
23359
|
+
const servers = isRecord$1(this.json.mcpServers) ? this.json.mcpServers : {};
|
|
23360
|
+
const mcpServers = Object.fromEntries(Object.entries(servers).map(([name, server]) => [name, isRecord$1(server) ? toRulesyncServer(server) : server]));
|
|
23361
|
+
return this.toRulesyncMcpDefault({ fileContent: JSON.stringify({ mcpServers }, null, 2) });
|
|
23218
23362
|
}
|
|
23219
23363
|
validate() {
|
|
23220
23364
|
return {
|
|
@@ -27229,8 +27373,8 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27229
27373
|
meta: {
|
|
27230
27374
|
supportsProject: true,
|
|
27231
27375
|
supportsGlobal: true,
|
|
27232
|
-
supportsEnabledTools:
|
|
27233
|
-
supportsDisabledTools:
|
|
27376
|
+
supportsEnabledTools: true,
|
|
27377
|
+
supportsDisabledTools: true
|
|
27234
27378
|
}
|
|
27235
27379
|
}],
|
|
27236
27380
|
["factorydroid", {
|
|
@@ -27239,7 +27383,7 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27239
27383
|
supportsProject: true,
|
|
27240
27384
|
supportsGlobal: true,
|
|
27241
27385
|
supportsEnabledTools: false,
|
|
27242
|
-
supportsDisabledTools:
|
|
27386
|
+
supportsDisabledTools: true
|
|
27243
27387
|
}
|
|
27244
27388
|
}],
|
|
27245
27389
|
["goose", {
|
|
@@ -27365,7 +27509,7 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27365
27509
|
supportsProject: true,
|
|
27366
27510
|
supportsGlobal: false,
|
|
27367
27511
|
supportsEnabledTools: false,
|
|
27368
|
-
supportsDisabledTools:
|
|
27512
|
+
supportsDisabledTools: true
|
|
27369
27513
|
}
|
|
27370
27514
|
}],
|
|
27371
27515
|
["zoocode", {
|
|
@@ -27374,7 +27518,7 @@ const toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
27374
27518
|
supportsProject: true,
|
|
27375
27519
|
supportsGlobal: false,
|
|
27376
27520
|
supportsEnabledTools: false,
|
|
27377
|
-
supportsDisabledTools:
|
|
27521
|
+
supportsDisabledTools: true
|
|
27378
27522
|
}
|
|
27379
27523
|
}],
|
|
27380
27524
|
["rovodev", {
|
|
@@ -31301,6 +31445,7 @@ function convertGoosePermissionConfigToRulesync(userPermission) {
|
|
|
31301
31445
|
const GROKCLI_UI_KEY = "ui";
|
|
31302
31446
|
const GROKCLI_PERMISSION_MODE_KEY = "permission_mode";
|
|
31303
31447
|
const GROKCLI_PERMISSION_KEY = "permission";
|
|
31448
|
+
const GROKCLI_AUTO_PERMISSION_MODE = "auto";
|
|
31304
31449
|
const CATCH_ALL_PATTERN$2 = "*";
|
|
31305
31450
|
const MCP_CANONICAL_PREFIX$1 = "mcp__";
|
|
31306
31451
|
const CATEGORY_TO_GROK_TOOL = {
|
|
@@ -31514,8 +31659,9 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
31514
31659
|
deny: buckets.deny,
|
|
31515
31660
|
ask: buckets.ask
|
|
31516
31661
|
};
|
|
31517
|
-
const
|
|
31518
|
-
|
|
31662
|
+
const existingUi = isRecord$1(parsed[GROKCLI_UI_KEY]) ? parsed[GROKCLI_UI_KEY] : {};
|
|
31663
|
+
const uiPatch = global && existingUi[GROKCLI_PERMISSION_MODE_KEY] !== GROKCLI_AUTO_PERMISSION_MODE ? { [GROKCLI_UI_KEY]: {
|
|
31664
|
+
...existingUi,
|
|
31519
31665
|
[GROKCLI_PERMISSION_MODE_KEY]: deriveGrokPermissionMode(config)
|
|
31520
31666
|
} } : {};
|
|
31521
31667
|
return new GrokcliPermissions({
|
|
@@ -36800,11 +36946,12 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
36800
36946
|
};
|
|
36801
36947
|
}
|
|
36802
36948
|
toRulesyncSkill() {
|
|
36803
|
-
const
|
|
36949
|
+
const { name, description, ...ampSection } = this.getFrontmatter();
|
|
36804
36950
|
const rulesyncFrontmatter = {
|
|
36805
|
-
name
|
|
36806
|
-
description
|
|
36807
|
-
targets: ["*"]
|
|
36951
|
+
name,
|
|
36952
|
+
description,
|
|
36953
|
+
targets: ["*"],
|
|
36954
|
+
...Object.keys(ampSection).length > 0 && { amp: ampSection }
|
|
36808
36955
|
};
|
|
36809
36956
|
return new RulesyncSkill({
|
|
36810
36957
|
outputRoot: this.outputRoot,
|
|
@@ -36821,6 +36968,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
36821
36968
|
const settablePaths = AmpSkill.getSettablePaths({ global });
|
|
36822
36969
|
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
|
|
36823
36970
|
const ampFrontmatter = {
|
|
36971
|
+
...rulesyncFrontmatter.amp,
|
|
36824
36972
|
name: rulesyncFrontmatter.name,
|
|
36825
36973
|
description: rulesyncFrontmatter.description
|
|
36826
36974
|
};
|
|
@@ -39247,6 +39395,47 @@ const JunieSkillFrontmatterSchema = zod_mini.z.looseObject({
|
|
|
39247
39395
|
name: zod_mini.z.string(),
|
|
39248
39396
|
description: zod_mini.z.string()
|
|
39249
39397
|
});
|
|
39398
|
+
/** An ATX markdown heading line (`#` … `######`). */
|
|
39399
|
+
const HEADING_LINE = /^#{1,6}(\s|$)/;
|
|
39400
|
+
/**
|
|
39401
|
+
* Junie's own fallback for a `SKILL.md` with no `description`: "If
|
|
39402
|
+
* `description` is not provided in the frontmatter, Junie CLI extracts the
|
|
39403
|
+
* first paragraph of the body content as the description." Headings do not
|
|
39404
|
+
* count as that paragraph — "If the body is also empty or contains only
|
|
39405
|
+
* headings, the skill will fail to load."
|
|
39406
|
+
*
|
|
39407
|
+
* This is import-only. The canonical `RulesyncSkillFrontmatter` requires a
|
|
39408
|
+
* description, so without the fallback a skill Junie itself loads fine aborts
|
|
39409
|
+
* the whole import; generation keeps emitting an explicit description, which
|
|
39410
|
+
* the same docs recommend.
|
|
39411
|
+
*
|
|
39412
|
+
* Heading lines are therefore skipped rather than taken: a body opening with
|
|
39413
|
+
* `# Skill Name` would otherwise import that title as the description and —
|
|
39414
|
+
* because the next generate writes it out explicitly — replace Junie's own
|
|
39415
|
+
* correct fallback with the wrong value everywhere, canonical config included.
|
|
39416
|
+
*
|
|
39417
|
+
* A paragraph runs to the first blank line or heading, and is collapsed onto
|
|
39418
|
+
* one line because it becomes a YAML frontmatter value. A fenced code block is
|
|
39419
|
+
* not treated specially: it is ordinary content, so a body whose first
|
|
39420
|
+
* paragraph is a fence yields the fence text. Returns an empty string when the
|
|
39421
|
+
* body holds no such paragraph, which the caller turns into a skipped skill.
|
|
39422
|
+
*
|
|
39423
|
+
* @see https://junie.jetbrains.com/docs/agent-skills.html
|
|
39424
|
+
*/
|
|
39425
|
+
function deriveDescriptionFromBody(body) {
|
|
39426
|
+
const paragraph = [];
|
|
39427
|
+
for (const rawLine of body.split(/\r?\n/)) {
|
|
39428
|
+
const line = rawLine.trim();
|
|
39429
|
+
if (paragraph.length === 0) {
|
|
39430
|
+
if (line === "" || HEADING_LINE.test(line)) continue;
|
|
39431
|
+
paragraph.push(line);
|
|
39432
|
+
continue;
|
|
39433
|
+
}
|
|
39434
|
+
if (line === "" || HEADING_LINE.test(line)) break;
|
|
39435
|
+
paragraph.push(line);
|
|
39436
|
+
}
|
|
39437
|
+
return paragraph.join(" ").trim();
|
|
39438
|
+
}
|
|
39250
39439
|
/**
|
|
39251
39440
|
* Represents a JetBrains Junie skill directory.
|
|
39252
39441
|
* Skills are stored under the .junie/skills directory with SKILL.md files.
|
|
@@ -39343,7 +39532,16 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
39343
39532
|
...params,
|
|
39344
39533
|
getSettablePaths: JunieSkill.getSettablePaths
|
|
39345
39534
|
});
|
|
39346
|
-
|
|
39535
|
+
let frontmatter = loaded.frontmatter;
|
|
39536
|
+
if (isRecord$1(frontmatter) && frontmatter.description === void 0) {
|
|
39537
|
+
const derived = deriveDescriptionFromBody(loaded.body);
|
|
39538
|
+
if (derived === "") throw new Error(`Cannot import ${(0, node_path.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.`);
|
|
39539
|
+
frontmatter = {
|
|
39540
|
+
...frontmatter,
|
|
39541
|
+
description: derived
|
|
39542
|
+
};
|
|
39543
|
+
}
|
|
39544
|
+
const result = JunieSkillFrontmatterSchema.safeParse(frontmatter);
|
|
39347
39545
|
if (!result.success) {
|
|
39348
39546
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
39349
39547
|
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
@@ -41808,7 +42006,8 @@ const toolSkillFactories = /* @__PURE__ */ new Map([
|
|
|
41808
42006
|
meta: {
|
|
41809
42007
|
supportsProject: true,
|
|
41810
42008
|
supportsSimulated: false,
|
|
41811
|
-
supportsGlobal: true
|
|
42009
|
+
supportsGlobal: true,
|
|
42010
|
+
lenientImport: true
|
|
41812
42011
|
}
|
|
41813
42012
|
}],
|
|
41814
42013
|
["kilo", {
|