@lyupro/skillforge-mcp 1.3.0 → 1.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +25 -0
- package/README.md +2 -1
- package/dist/cli/dispatcher.d.ts.map +1 -1
- package/dist/cli/dispatcher.js +13 -10
- package/dist/cli/dispatcher.js.map +1 -1
- package/dist/cli/folders-handlers.js +1 -1
- package/dist/cli/folders-handlers.js.map +1 -1
- package/dist/cli/skills-format.d.ts +15 -0
- package/dist/cli/skills-format.d.ts.map +1 -0
- package/dist/cli/skills-format.js +84 -0
- package/dist/cli/skills-format.js.map +1 -0
- package/dist/cli/skills-handlers.d.ts +15 -0
- package/dist/cli/skills-handlers.d.ts.map +1 -0
- package/dist/cli/skills-handlers.js +112 -0
- package/dist/cli/skills-handlers.js.map +1 -0
- package/dist/cli/skills-shared.d.ts +32 -0
- package/dist/cli/skills-shared.d.ts.map +1 -0
- package/dist/cli/skills-shared.js +90 -0
- package/dist/cli/skills-shared.js.map +1 -0
- package/dist/cli/skills.d.ts +46 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +107 -0
- package/dist/cli/skills.js.map +1 -0
- package/dist/config/config-schema.d.ts +246 -142
- package/dist/config/config-schema.d.ts.map +1 -1
- package/dist/config/config-schema.js +28 -14
- package/dist/config/config-schema.js.map +1 -1
- package/dist/detect/skill-source-conflict.d.ts +24 -7
- package/dist/detect/skill-source-conflict.d.ts.map +1 -1
- package/dist/detect/skill-source-conflict.js +62 -10
- package/dist/detect/skill-source-conflict.js.map +1 -1
- package/dist/reconcile.d.ts +5 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +20 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/runtime.d.ts +14 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +29 -0
- package/dist/runtime.js.map +1 -0
- package/dist/server-deps.d.ts +3 -1
- package/dist/server-deps.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -8
- package/dist/server.js.map +1 -1
- package/dist/tools/configure.d.ts.map +1 -1
- package/dist/tools/configure.js +8 -25
- package/dist/tools/configure.js.map +1 -1
- package/dist/watcher/config-watcher.d.ts +25 -0
- package/dist/watcher/config-watcher.d.ts.map +1 -0
- package/dist/watcher/config-watcher.js +92 -0
- package/dist/watcher/config-watcher.js.map +1 -0
- package/dist/watcher/index.d.ts +2 -0
- package/dist/watcher/index.d.ts.map +1 -1
- package/dist/watcher/index.js +1 -0
- package/dist/watcher/index.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Why: camelCase keys match TS identifiers 1:1 — no key transforms needed between code and JSON.
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
const folderEntrySchema = z
|
|
3
|
+
const folderEntrySchema = z
|
|
4
|
+
.object({
|
|
4
5
|
path: z.string().min(1),
|
|
5
6
|
priority: z.number().int().default(100),
|
|
6
7
|
enabled: z.boolean().default(true),
|
|
@@ -11,8 +12,10 @@ const folderEntrySchema = z.object({
|
|
|
11
12
|
.string()
|
|
12
13
|
.regex(/^[a-z0-9]+(-[a-z0-9]+)*$/)
|
|
13
14
|
.optional(),
|
|
14
|
-
})
|
|
15
|
-
|
|
15
|
+
})
|
|
16
|
+
.passthrough();
|
|
17
|
+
const securitySchema = z
|
|
18
|
+
.object({
|
|
16
19
|
autoAudit: z.boolean().default(true),
|
|
17
20
|
auditPatterns: z
|
|
18
21
|
.array(z.string())
|
|
@@ -20,26 +23,36 @@ const securitySchema = z.object({
|
|
|
20
23
|
allowScripts: z.boolean().default(false),
|
|
21
24
|
sandboxScripts: z.boolean().default(true),
|
|
22
25
|
sandboxRestrictedPaths: z.array(z.string()).default(['~/.ssh', '~/.aws', '~/.gnupg']),
|
|
23
|
-
})
|
|
24
|
-
|
|
26
|
+
})
|
|
27
|
+
.passthrough();
|
|
28
|
+
const cacheSchema = z
|
|
29
|
+
.object({
|
|
25
30
|
metadataTtlMs: z.number().nonnegative().default(300_000),
|
|
26
31
|
contentTtlMs: z.number().nonnegative().default(300_000),
|
|
27
32
|
maxSizeMb: z.number().nonnegative().default(50),
|
|
28
|
-
})
|
|
29
|
-
|
|
33
|
+
})
|
|
34
|
+
.passthrough();
|
|
35
|
+
const watcherSchema = z
|
|
36
|
+
.object({
|
|
30
37
|
enabled: z.boolean().default(true),
|
|
31
38
|
debounceMs: z.number().nonnegative().default(500),
|
|
32
|
-
})
|
|
33
|
-
|
|
39
|
+
})
|
|
40
|
+
.passthrough();
|
|
41
|
+
const loggingSchema = z
|
|
42
|
+
.object({
|
|
34
43
|
level: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
|
|
35
44
|
file: z.string().nullable().default(null),
|
|
36
|
-
})
|
|
37
|
-
|
|
45
|
+
})
|
|
46
|
+
.passthrough();
|
|
47
|
+
const invocationSchema = z
|
|
48
|
+
.object({
|
|
38
49
|
defaultTimeoutMs: z.number().nonnegative().default(30_000),
|
|
39
50
|
cacheTtlMs: z.number().nonnegative().default(60_000),
|
|
40
51
|
cacheMaxEntries: z.number().nonnegative().default(128),
|
|
41
|
-
})
|
|
42
|
-
|
|
52
|
+
})
|
|
53
|
+
.passthrough();
|
|
54
|
+
export const configSchema = z
|
|
55
|
+
.object({
|
|
43
56
|
version: z.literal('1.0').default('1.0'),
|
|
44
57
|
folders: z.array(folderEntrySchema).default([]),
|
|
45
58
|
blacklist: z.array(z.string()).default([]),
|
|
@@ -48,7 +61,8 @@ export const configSchema = z.object({
|
|
|
48
61
|
watcher: watcherSchema.default({}),
|
|
49
62
|
logging: loggingSchema.default({}),
|
|
50
63
|
invocation: invocationSchema.default({}),
|
|
51
|
-
})
|
|
64
|
+
})
|
|
65
|
+
.passthrough();
|
|
52
66
|
export function defaultConfig() {
|
|
53
67
|
return configSchema.parse({});
|
|
54
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/config/config-schema.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,iBAAiB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/config/config-schema.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,iBAAiB,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IACvC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,0EAA0E;IAC1E,uDAAuD;IACvD,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,KAAK,CAAC,0BAA0B,CAAC;SACjC,QAAQ,EAAE;CACd,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACpC,aAAa,EAAE,CAAC;SACb,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,OAAO,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACtE,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACzC,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;CACtF,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IACxD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IACvD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAChD,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;CAClD,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC1C,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACpD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;CACvD,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC/C,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;IACpC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9B,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;IAClC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;IAClC,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;CACzC,CAAC;KACD,WAAW,EAAE,CAAC;AAKjB,MAAM,UAAU,aAAa;IAC3B,OAAO,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -7,11 +7,19 @@
|
|
|
7
7
|
* user can disable one source. We NEVER mutate another tool's config: this is
|
|
8
8
|
* detection + hint only.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* For Claude Code plugins, the detector reads ~/.claude/settings.json to check
|
|
11
|
+
* whether the plugin is actually enabled. The home directory and the settings
|
|
12
|
+
* reader are both injectable so tests never touch real host files.
|
|
12
13
|
*/
|
|
13
14
|
/** A host CLI whose native plugin/extension system can double-load skills. */
|
|
14
15
|
export type ConflictHost = 'claude' | 'gemini';
|
|
16
|
+
/**
|
|
17
|
+
* Whether the conflicting host plugin/extension is currently enabled.
|
|
18
|
+
* - 'enabled' — key present in host settings with value true.
|
|
19
|
+
* - 'disabled' — key present in host settings with value false.
|
|
20
|
+
* - 'unknown' — settings file missing, unreadable, malformed, or no state API.
|
|
21
|
+
*/
|
|
22
|
+
export type PluginEnabledState = 'enabled' | 'disabled' | 'unknown';
|
|
15
23
|
export interface SkillSourceConflict {
|
|
16
24
|
/** The host CLI that natively serves skills from this path. */
|
|
17
25
|
host: ConflictHost;
|
|
@@ -21,6 +29,8 @@ export interface SkillSourceConflict {
|
|
|
21
29
|
name: string;
|
|
22
30
|
/** The absolute folder path that triggered the conflict. */
|
|
23
31
|
folderPath: string;
|
|
32
|
+
/** Whether the conflicting plugin/extension is currently enabled in host settings. */
|
|
33
|
+
enabledState: PluginEnabledState;
|
|
24
34
|
}
|
|
25
35
|
/**
|
|
26
36
|
* Detect whether `folderPath` is served by a host CLI's native plugin or
|
|
@@ -28,20 +38,27 @@ export interface SkillSourceConflict {
|
|
|
28
38
|
*
|
|
29
39
|
* - Claude Code — `~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/...`
|
|
30
40
|
* The plugin name is the `<plugin>` segment (the marketplace prefix is
|
|
31
|
-
* included when present for a clearer label).
|
|
41
|
+
* included when present for a clearer label). The enabled state is read from
|
|
42
|
+
* `~/.claude/settings.json` via the injectable `readPluginEnabled` resolver.
|
|
43
|
+
* When the plugin is DISABLED, returns null (no conflict).
|
|
32
44
|
* - Gemini CLI — `~/.gemini/extensions/<extension>/...`
|
|
33
|
-
* The extension name is the first segment after `extensions/`.
|
|
45
|
+
* The extension name is the first segment after `extensions/`. No reliable
|
|
46
|
+
* enabled-state file is available; always returns `enabledState: 'unknown'`.
|
|
34
47
|
*
|
|
35
48
|
* Codex and Cursor have no native skill system — they never conflict.
|
|
36
49
|
*
|
|
37
|
-
* @param folderPath
|
|
38
|
-
* @param home
|
|
50
|
+
* @param folderPath Absolute folder path being registered.
|
|
51
|
+
* @param home Home directory root, injectable for tests.
|
|
52
|
+
* @param readPluginEnabled Injectable resolver for Claude plugin enabled state.
|
|
39
53
|
* @returns A conflict descriptor, or null when there is no conflict.
|
|
40
54
|
*/
|
|
41
|
-
export declare function detectSkillSourceConflict(folderPath: string, home?: string): SkillSourceConflict | null
|
|
55
|
+
export declare function detectSkillSourceConflict(folderPath: string, home?: string, readPluginEnabled?: (home: string, pluginKey: string) => Promise<PluginEnabledState>): Promise<SkillSourceConflict | null>;
|
|
42
56
|
/**
|
|
43
57
|
* Build the user-facing warning for a detected conflict. SkillForge prints
|
|
44
58
|
* this as an informational hint — it does not disable anything itself.
|
|
59
|
+
*
|
|
60
|
+
* - enabledState 'enabled' → direct "disable it" wording.
|
|
61
|
+
* - enabledState 'unknown' → conditional "IF enabled" wording.
|
|
45
62
|
*/
|
|
46
63
|
export declare function formatConflictHint(conflict: SkillSourceConflict): string;
|
|
47
64
|
//# sourceMappingURL=skill-source-conflict.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-source-conflict.d.ts","sourceRoot":"","sources":["../../src/detect/skill-source-conflict.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skill-source-conflict.d.ts","sourceRoot":"","sources":["../../src/detect/skill-source-conflict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,IAAI,EAAE,YAAY,CAAC;IACnB,4EAA4E;IAC5E,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAmED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,MAAkB,EACxB,iBAAiB,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAA4B,GAC7G,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAkCrC;AAeD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,CAaxE"}
|
|
@@ -7,15 +7,50 @@
|
|
|
7
7
|
* user can disable one source. We NEVER mutate another tool's config: this is
|
|
8
8
|
* detection + hint only.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* For Claude Code plugins, the detector reads ~/.claude/settings.json to check
|
|
11
|
+
* whether the plugin is actually enabled. The home directory and the settings
|
|
12
|
+
* reader are both injectable so tests never touch real host files.
|
|
12
13
|
*/
|
|
13
14
|
import { homedir } from 'node:os';
|
|
14
15
|
import { resolve, sep } from 'node:path';
|
|
16
|
+
import { readFile } from 'node:fs/promises';
|
|
15
17
|
/** Normalise to an absolute path with consistent separators for prefix tests. */
|
|
16
18
|
function normalize(p) {
|
|
17
19
|
return resolve(p);
|
|
18
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Read the Claude Code plugin enabled state from ~/.claude/settings.json.
|
|
23
|
+
* The key in `enabledPlugins` is `"<plugin>@<marketplace>"`.
|
|
24
|
+
* Returns 'disabled' | 'enabled' | 'unknown'.
|
|
25
|
+
*/
|
|
26
|
+
async function readClaudePluginEnabled(settingsPath, pluginKey) {
|
|
27
|
+
try {
|
|
28
|
+
const raw = await readFile(settingsPath, 'utf8');
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (parsed === null ||
|
|
31
|
+
typeof parsed !== 'object' ||
|
|
32
|
+
!('enabledPlugins' in parsed) ||
|
|
33
|
+
typeof parsed.enabledPlugins !== 'object' ||
|
|
34
|
+
parsed.enabledPlugins === null) {
|
|
35
|
+
return 'unknown';
|
|
36
|
+
}
|
|
37
|
+
const enabledPlugins = parsed.enabledPlugins;
|
|
38
|
+
if (!(pluginKey in enabledPlugins))
|
|
39
|
+
return 'unknown';
|
|
40
|
+
return enabledPlugins[pluginKey] === false ? 'disabled' : 'enabled';
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return 'unknown';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Default implementation of the injectable plugin-state resolver for Claude Code.
|
|
48
|
+
* Reads the real ~/.claude/settings.json on the host machine.
|
|
49
|
+
*/
|
|
50
|
+
async function defaultReadPluginEnabled(home, pluginKey) {
|
|
51
|
+
const settingsPath = resolve(home, '.claude', 'settings.json');
|
|
52
|
+
return readClaudePluginEnabled(settingsPath, pluginKey);
|
|
53
|
+
}
|
|
19
54
|
/**
|
|
20
55
|
* Return the path segments of `child` that follow `root`, or null when
|
|
21
56
|
* `child` is not inside `root`. Comparison is done on resolved absolute
|
|
@@ -38,17 +73,21 @@ function segmentsUnder(child, root) {
|
|
|
38
73
|
*
|
|
39
74
|
* - Claude Code — `~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/...`
|
|
40
75
|
* The plugin name is the `<plugin>` segment (the marketplace prefix is
|
|
41
|
-
* included when present for a clearer label).
|
|
76
|
+
* included when present for a clearer label). The enabled state is read from
|
|
77
|
+
* `~/.claude/settings.json` via the injectable `readPluginEnabled` resolver.
|
|
78
|
+
* When the plugin is DISABLED, returns null (no conflict).
|
|
42
79
|
* - Gemini CLI — `~/.gemini/extensions/<extension>/...`
|
|
43
|
-
* The extension name is the first segment after `extensions/`.
|
|
80
|
+
* The extension name is the first segment after `extensions/`. No reliable
|
|
81
|
+
* enabled-state file is available; always returns `enabledState: 'unknown'`.
|
|
44
82
|
*
|
|
45
83
|
* Codex and Cursor have no native skill system — they never conflict.
|
|
46
84
|
*
|
|
47
|
-
* @param folderPath
|
|
48
|
-
* @param home
|
|
85
|
+
* @param folderPath Absolute folder path being registered.
|
|
86
|
+
* @param home Home directory root, injectable for tests.
|
|
87
|
+
* @param readPluginEnabled Injectable resolver for Claude plugin enabled state.
|
|
49
88
|
* @returns A conflict descriptor, or null when there is no conflict.
|
|
50
89
|
*/
|
|
51
|
-
export function detectSkillSourceConflict(folderPath, home = homedir()) {
|
|
90
|
+
export async function detectSkillSourceConflict(folderPath, home = homedir(), readPluginEnabled = defaultReadPluginEnabled) {
|
|
52
91
|
const claudeCacheRoot = resolve(home, '.claude', 'plugins', 'cache');
|
|
53
92
|
const claudeSegments = segmentsUnder(folderPath, claudeCacheRoot);
|
|
54
93
|
if (claudeSegments !== null && claudeSegments.length > 0) {
|
|
@@ -57,11 +96,16 @@ export function detectSkillSourceConflict(folderPath, home = homedir()) {
|
|
|
57
96
|
const marketplace = claudeSegments[0];
|
|
58
97
|
const plugin = claudeSegments[1];
|
|
59
98
|
const name = plugin !== undefined ? `${marketplace}/${plugin}` : marketplace;
|
|
99
|
+
const pluginKey = plugin !== undefined ? `${plugin}@${marketplace}` : marketplace;
|
|
100
|
+
const enabledState = await readPluginEnabled(home, pluginKey);
|
|
101
|
+
if (enabledState === 'disabled')
|
|
102
|
+
return null;
|
|
60
103
|
return {
|
|
61
104
|
host: 'claude',
|
|
62
105
|
kind: 'plugin',
|
|
63
106
|
name,
|
|
64
107
|
folderPath: normalize(folderPath),
|
|
108
|
+
enabledState,
|
|
65
109
|
};
|
|
66
110
|
}
|
|
67
111
|
const geminiExtRoot = resolve(home, '.gemini', 'extensions');
|
|
@@ -72,6 +116,7 @@ export function detectSkillSourceConflict(folderPath, home = homedir()) {
|
|
|
72
116
|
kind: 'extension',
|
|
73
117
|
name: geminiSegments[0],
|
|
74
118
|
folderPath: normalize(folderPath),
|
|
119
|
+
enabledState: 'unknown',
|
|
75
120
|
};
|
|
76
121
|
}
|
|
77
122
|
return null;
|
|
@@ -90,10 +135,17 @@ function disableCommand(conflict) {
|
|
|
90
135
|
/**
|
|
91
136
|
* Build the user-facing warning for a detected conflict. SkillForge prints
|
|
92
137
|
* this as an informational hint — it does not disable anything itself.
|
|
138
|
+
*
|
|
139
|
+
* - enabledState 'enabled' → direct "disable it" wording.
|
|
140
|
+
* - enabledState 'unknown' → conditional "IF enabled" wording.
|
|
93
141
|
*/
|
|
94
142
|
export function formatConflictHint(conflict) {
|
|
95
|
-
|
|
96
|
-
`${hostLabel(conflict.host)} ${conflict.kind} "${conflict.name}"
|
|
97
|
-
|
|
143
|
+
const prefix = `Warning: ${conflict.folderPath} is also served by the ` +
|
|
144
|
+
`${hostLabel(conflict.host)} ${conflict.kind} "${conflict.name}".`;
|
|
145
|
+
if (conflict.enabledState === 'unknown') {
|
|
146
|
+
return (`${prefix} IF that ${conflict.kind} is enabled, skills load twice — ` +
|
|
147
|
+
`check ${conflict.host === 'claude' ? '/plugin' : `/extensions disable ${conflict.name}`}`);
|
|
148
|
+
}
|
|
149
|
+
return (`${prefix} To avoid loading these skills twice, disable it: ${disableCommand(conflict)}`);
|
|
98
150
|
}
|
|
99
151
|
//# sourceMappingURL=skill-source-conflict.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-source-conflict.js","sourceRoot":"","sources":["../../src/detect/skill-source-conflict.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skill-source-conflict.js","sourceRoot":"","sources":["../../src/detect/skill-source-conflict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AA0B5C,iFAAiF;AACjF,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,uBAAuB,CACpC,YAAoB,EACpB,SAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IACE,MAAM,KAAK,IAAI;YACf,OAAO,MAAM,KAAK,QAAQ;YAC1B,CAAC,CAAC,gBAAgB,IAAI,MAAM,CAAC;YAC7B,OAAQ,MAAkC,CAAC,cAAc,KAAK,QAAQ;YACrE,MAAkC,CAAC,cAAc,KAAK,IAAI,EAC3D,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,cAAc,GAAI,MAAkC,CAAC,cAG1D,CAAC;QACF,IAAI,CAAC,CAAC,SAAS,IAAI,cAAc,CAAC;YAAE,OAAO,SAAS,CAAC;QACrD,OAAO,cAAc,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,wBAAwB,CACrC,IAAY,EACZ,SAAiB;IAEjB,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC/D,OAAO,uBAAuB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,IAAY;IAChD,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC;IACpE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,QAAQ;SACZ,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;SACzB,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,UAAkB,EAClB,OAAe,OAAO,EAAE,EACxB,oBAAsF,wBAAwB;IAE9G,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACrE,MAAM,cAAc,GAAG,aAAa,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAClE,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,2EAA2E;QAC3E,6DAA6D;QAC7D,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAE,CAAC;QACvC,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QAC7E,MAAM,SAAS,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QAClF,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC9D,IAAI,YAAY,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC;QAC7C,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;YACd,IAAI;YACJ,UAAU,EAAE,SAAS,CAAC,UAAU,CAAC;YACjC,YAAY;SACb,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC7D,MAAM,cAAc,GAAG,aAAa,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAChE,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAE;YACxB,UAAU,EAAE,SAAS,CAAC,UAAU,CAAC;YACjC,YAAY,EAAE,SAAS;SACxB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mDAAmD;AACnD,SAAS,SAAS,CAAC,IAAkB;IACnC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;AAC1D,CAAC;AAED,iFAAiF;AACjF,SAAS,cAAc,CAAC,QAA6B;IACnD,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,gCAAgC,QAAQ,CAAC,IAAI,UAAU,CAAC;IACjE,CAAC;IACD,OAAO,uBAAuB,QAAQ,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAA6B;IAC9D,MAAM,MAAM,GACV,YAAY,QAAQ,CAAC,UAAU,yBAAyB;QACxD,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC;IACrE,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,CACL,GAAG,MAAM,YAAY,QAAQ,CAAC,IAAI,mCAAmC;YACrE,SAAS,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,uBAAuB,QAAQ,CAAC,IAAI,EAAE,EAAE,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,CACL,GAAG,MAAM,qDAAqD,cAAc,CAAC,QAAQ,CAAC,EAAE,CACzF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ServerDeps } from './server-deps.js';
|
|
2
|
+
import type { PersistedConfig } from './config/index.js';
|
|
3
|
+
/** Recompute resolved folders from env + persisted config, then splice deps.folders in place. */
|
|
4
|
+
export declare function reconcileFolders(deps: ServerDeps): Promise<PersistedConfig>;
|
|
5
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,iGAAiG;AACjG,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAcjF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { loadResolvedConfig } from './config.js';
|
|
2
|
+
import { ensureRegistryFresh } from './tools/loader.js';
|
|
3
|
+
/** Recompute resolved folders from env + persisted config, then splice deps.folders in place. */
|
|
4
|
+
export async function reconcileFolders(deps) {
|
|
5
|
+
const persisted = await deps.configStore.load();
|
|
6
|
+
const resolved = await loadResolvedConfig(process.env, deps.configStore);
|
|
7
|
+
// Splice in-place so all references to deps.folders see the new list.
|
|
8
|
+
deps.folders.splice(0, deps.folders.length, ...resolved.folders);
|
|
9
|
+
deps.blacklistFilter.setManualBlacklist(persisted.blacklist);
|
|
10
|
+
deps.metadataCache.invalidate();
|
|
11
|
+
try {
|
|
12
|
+
await deps.folderWatcher.setFolders(deps.folders);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
console.error(`[skillforge:configure] watcher setFolders failed: ${String(err)}`);
|
|
16
|
+
}
|
|
17
|
+
await ensureRegistryFresh(deps);
|
|
18
|
+
return persisted;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=reconcile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAgB;IACrD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzE,sEAAsE;IACtE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjE,IAAI,CAAC,eAAe,CAAC,kBAAkB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7D,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,qDAAqD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ServerDeps } from './server-deps.js';
|
|
2
|
+
/**
|
|
3
|
+
* Starts the long-lived background watchers for a running MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Both startup paths — `server.ts` `main()` and `cli/dispatcher.ts`
|
|
6
|
+
* `defaultStartServe()` — call this so the watcher wiring lives in one place.
|
|
7
|
+
* The MCP transport itself is connected by the caller before this runs.
|
|
8
|
+
*/
|
|
9
|
+
export declare function startRuntime(deps: ServerDeps): Promise<void>;
|
|
10
|
+
/** Stops all background watchers. Safe to call once on SIGTERM/SIGINT. */
|
|
11
|
+
export declare function stopRuntime(deps: ServerDeps): Promise<void>;
|
|
12
|
+
/** Registers SIGTERM/SIGINT handlers that tear the runtime down gracefully. */
|
|
13
|
+
export declare function registerShutdown(deps: ServerDeps): void;
|
|
14
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;AAED,0EAA0E;AAC1E,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAUvD"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starts the long-lived background watchers for a running MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Both startup paths — `server.ts` `main()` and `cli/dispatcher.ts`
|
|
5
|
+
* `defaultStartServe()` — call this so the watcher wiring lives in one place.
|
|
6
|
+
* The MCP transport itself is connected by the caller before this runs.
|
|
7
|
+
*/
|
|
8
|
+
export async function startRuntime(deps) {
|
|
9
|
+
await deps.folderWatcher.start();
|
|
10
|
+
await deps.configWatcher.start();
|
|
11
|
+
}
|
|
12
|
+
/** Stops all background watchers. Safe to call once on SIGTERM/SIGINT. */
|
|
13
|
+
export async function stopRuntime(deps) {
|
|
14
|
+
await deps.folderWatcher.stop();
|
|
15
|
+
await deps.configWatcher.stop();
|
|
16
|
+
}
|
|
17
|
+
/** Registers SIGTERM/SIGINT handlers that tear the runtime down gracefully. */
|
|
18
|
+
export function registerShutdown(deps) {
|
|
19
|
+
const shutdown = async () => {
|
|
20
|
+
await stopRuntime(deps);
|
|
21
|
+
};
|
|
22
|
+
process.once('SIGTERM', () => {
|
|
23
|
+
void shutdown();
|
|
24
|
+
});
|
|
25
|
+
process.once('SIGINT', () => {
|
|
26
|
+
void shutdown();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAgB;IACjD,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IACjC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AACnC,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAgB;IAChD,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,IAAgB;IAC/C,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;QAC3B,KAAK,QAAQ,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC1B,KAAK,QAAQ,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/server-deps.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { FrontmatterParser, FileScanner } from './parser/index.js';
|
|
|
3
3
|
import type { StrategyFactory } from './factory/index.js';
|
|
4
4
|
import type { BlacklistFilter } from './security/index.js';
|
|
5
5
|
import type { ConfigStore } from './config/index.js';
|
|
6
|
-
import type { FolderWatcher } from './watcher/index.js';
|
|
6
|
+
import type { FolderWatcher, ConfigWatcher } from './watcher/index.js';
|
|
7
7
|
import type { Logger } from './decorators/index.js';
|
|
8
8
|
import type { SandboxRunner } from './security/sandbox-runner.js';
|
|
9
9
|
import type { DecoratorChain } from './decorators/index.js';
|
|
@@ -21,6 +21,8 @@ export interface ServerDeps {
|
|
|
21
21
|
factory: StrategyFactory;
|
|
22
22
|
blacklistFilter: BlacklistFilter;
|
|
23
23
|
folderWatcher: FolderWatcher;
|
|
24
|
+
/** Watches config.json for out-of-process edits (e.g. the folders CLI). */
|
|
25
|
+
configWatcher: ConfigWatcher;
|
|
24
26
|
logger: Logger;
|
|
25
27
|
sandboxRunner: SandboxRunner;
|
|
26
28
|
decoratorChain: DecoratorChain;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-deps.d.ts","sourceRoot":"","sources":["../src/server-deps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC3G,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server-deps.d.ts","sourceRoot":"","sources":["../src/server-deps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC3G,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB;mFAC+E;IAC/E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,kBAAkB,CAAC;IAClC,YAAY,EAAE,iBAAiB,CAAC;IAChC,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,2EAA2E;IAC3E,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,cAAc,CAAC;CAChC"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqBpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAcnD,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAmGvD;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CA8ErD"}
|
package/dist/server.js
CHANGED
|
@@ -9,7 +9,9 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
9
9
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
10
|
import { loadResolvedConfig, buildPatternScanner } from './config.js';
|
|
11
11
|
import { ConfigStore, defaultConfigPath } from './config/index.js';
|
|
12
|
-
import { FolderWatcher } from './watcher/index.js';
|
|
12
|
+
import { FolderWatcher, ConfigWatcher } from './watcher/index.js';
|
|
13
|
+
import { reconcileFolders } from './reconcile.js';
|
|
14
|
+
import { startRuntime, registerShutdown } from './runtime.js';
|
|
13
15
|
import { SkillRegistry, SkillResolver, SkillMetadataCache, SkillContentCache, } from './core/index.js';
|
|
14
16
|
import { FrontmatterParser, FileScanner } from './parser/index.js';
|
|
15
17
|
import { PromptStrategy } from './handlers/index.js';
|
|
@@ -110,6 +112,21 @@ export async function buildDeps() {
|
|
|
110
112
|
debounceMs: resolved.persisted.watcher.debounceMs,
|
|
111
113
|
onBatch: () => metadataCache.invalidate(),
|
|
112
114
|
});
|
|
115
|
+
// The config CLI runs as a separate process and rewrites config.json on disk.
|
|
116
|
+
// This watcher reconciles a running server with those out-of-process edits.
|
|
117
|
+
// `deps` is assigned at the end of buildDeps; the closure runs only after start().
|
|
118
|
+
let deps;
|
|
119
|
+
const configWatcher = new ConfigWatcher({
|
|
120
|
+
configPath: defaultConfigPath(),
|
|
121
|
+
onChange: async () => {
|
|
122
|
+
try {
|
|
123
|
+
await reconcileFolders(deps);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
console.error(`[skillforge:config-watcher] reconcile failed, skipping event: ${String(err)}`);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
});
|
|
113
130
|
const logger = stderrLogger;
|
|
114
131
|
const sandboxRunner = new SandboxRunner({ logger });
|
|
115
132
|
// allowScripts flag captured from initial config load. A ref object is used
|
|
@@ -135,7 +152,7 @@ export async function buildDeps() {
|
|
|
135
152
|
cacheTtlMs: invocation.cacheTtlMs,
|
|
136
153
|
cacheMaxEntries: invocation.cacheMaxEntries,
|
|
137
154
|
});
|
|
138
|
-
|
|
155
|
+
deps = {
|
|
139
156
|
folders: resolved.folders,
|
|
140
157
|
configStore,
|
|
141
158
|
registry: new SkillRegistry(),
|
|
@@ -147,21 +164,19 @@ export async function buildDeps() {
|
|
|
147
164
|
factory,
|
|
148
165
|
blacklistFilter,
|
|
149
166
|
folderWatcher,
|
|
167
|
+
configWatcher,
|
|
150
168
|
logger,
|
|
151
169
|
sandboxRunner,
|
|
152
170
|
decoratorChain,
|
|
153
171
|
};
|
|
172
|
+
return deps;
|
|
154
173
|
}
|
|
155
174
|
async function main() {
|
|
156
175
|
const deps = await buildDeps();
|
|
157
176
|
const server = buildServer(deps);
|
|
158
177
|
await server.connect(new StdioServerTransport());
|
|
159
|
-
await deps
|
|
160
|
-
|
|
161
|
-
await deps.folderWatcher.stop();
|
|
162
|
-
};
|
|
163
|
-
process.once('SIGTERM', () => { void shutdown(); });
|
|
164
|
-
process.once('SIGINT', () => { void shutdown(); });
|
|
178
|
+
await startRuntime(deps);
|
|
179
|
+
registerShutdown(deps);
|
|
165
180
|
}
|
|
166
181
|
// Only run main() when invoked directly, not when imported by tests.
|
|
167
182
|
// This is the canonical ESM "is this the entry point?" check.
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../src/tools/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../src/tools/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AASpD,eAAO,MAAM,oBAAoB;;;;;CAYvB,CAAC;AAEX,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,eAAe,GACf,cAAc,GACd,eAAe,GACf,eAAe,GACf,OAAO,CAAC;AAEZ,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uDAAuD;IACvD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACvF,OAAO,CAAC,eAAe,CAAC,CAgH1B"}
|
package/dist/tools/configure.js
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { defaultConfig } from '../config/index.js';
|
|
4
4
|
import { loadResolvedConfig } from '../config.js';
|
|
5
|
-
import {
|
|
5
|
+
import { reconcileFolders } from '../reconcile.js';
|
|
6
6
|
import { detectSkillSourceConflict, formatConflictHint, } from '../detect/skill-source-conflict.js';
|
|
7
7
|
export const configureInputSchema = {
|
|
8
8
|
action: z.enum([
|
|
@@ -17,39 +17,22 @@ export const configureInputSchema = {
|
|
|
17
17
|
alias: z.string().optional(),
|
|
18
18
|
blacklist: z.array(z.string()).optional(),
|
|
19
19
|
};
|
|
20
|
-
/** Recompute resolved folders from env + persisted config, then splice deps.folders in place. */
|
|
21
|
-
async function reconcileFolders(deps) {
|
|
22
|
-
const persisted = await deps.configStore.load();
|
|
23
|
-
const resolved = await loadResolvedConfig(process.env, deps.configStore);
|
|
24
|
-
// Splice in-place so all references to deps.folders see the new list.
|
|
25
|
-
deps.folders.splice(0, deps.folders.length, ...resolved.folders);
|
|
26
|
-
deps.blacklistFilter.setManualBlacklist(persisted.blacklist);
|
|
27
|
-
deps.metadataCache.invalidate();
|
|
28
|
-
try {
|
|
29
|
-
await deps.folderWatcher.setFolders(deps.folders);
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
console.error(`[skillforge:configure] watcher setFolders failed: ${String(err)}`);
|
|
33
|
-
}
|
|
34
|
-
await ensureRegistryFresh(deps);
|
|
35
|
-
return persisted;
|
|
36
|
-
}
|
|
37
20
|
export async function handleConfigure(deps, args) {
|
|
38
21
|
const { action } = args;
|
|
39
22
|
try {
|
|
40
23
|
if (action === 'list_folders') {
|
|
41
|
-
const
|
|
24
|
+
const resolved = await loadResolvedConfig(process.env, deps.configStore);
|
|
42
25
|
return {
|
|
43
|
-
folders:
|
|
44
|
-
blacklist: persisted.blacklist,
|
|
26
|
+
folders: resolved.folders,
|
|
27
|
+
blacklist: resolved.persisted.blacklist,
|
|
45
28
|
totalSkills: deps.registry.size,
|
|
46
29
|
};
|
|
47
30
|
}
|
|
48
31
|
if (action === 'get_blacklist') {
|
|
49
|
-
const
|
|
32
|
+
const resolved = await loadResolvedConfig(process.env, deps.configStore);
|
|
50
33
|
return {
|
|
51
|
-
folders:
|
|
52
|
-
blacklist: persisted.blacklist,
|
|
34
|
+
folders: resolved.folders,
|
|
35
|
+
blacklist: resolved.persisted.blacklist,
|
|
53
36
|
totalSkills: deps.registry.size,
|
|
54
37
|
};
|
|
55
38
|
}
|
|
@@ -81,7 +64,7 @@ export async function handleConfigure(deps, args) {
|
|
|
81
64
|
// Why: always save even on no-op — simpler than branching, atomic write is cheap.
|
|
82
65
|
await deps.configStore.save(persisted);
|
|
83
66
|
const finalPersisted = await reconcileFolders(deps);
|
|
84
|
-
const conflict = detectSkillSourceConflict(absPath);
|
|
67
|
+
const conflict = await detectSkillSourceConflict(absPath);
|
|
85
68
|
return {
|
|
86
69
|
folders: [...deps.folders],
|
|
87
70
|
blacklist: finalPersisted.blacklist,
|