@vibe-agent-toolkit/claude-marketplace 0.1.15-rc.1
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/compatibility-analyzer.d.ts +13 -0
- package/dist/compatibility-analyzer.d.ts.map +1 -0
- package/dist/compatibility-analyzer.js +205 -0
- package/dist/compatibility-analyzer.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/scanners/code-block-scanner.d.ts +7 -0
- package/dist/scanners/code-block-scanner.d.ts.map +1 -0
- package/dist/scanners/code-block-scanner.js +33 -0
- package/dist/scanners/code-block-scanner.js.map +1 -0
- package/dist/scanners/command-classifier.d.ts +26 -0
- package/dist/scanners/command-classifier.d.ts.map +1 -0
- package/dist/scanners/command-classifier.js +74 -0
- package/dist/scanners/command-classifier.js.map +1 -0
- package/dist/scanners/frontmatter-scanner.d.ts +7 -0
- package/dist/scanners/frontmatter-scanner.d.ts.map +1 -0
- package/dist/scanners/frontmatter-scanner.js +79 -0
- package/dist/scanners/frontmatter-scanner.js.map +1 -0
- package/dist/scanners/hook-scanner.d.ts +7 -0
- package/dist/scanners/hook-scanner.d.ts.map +1 -0
- package/dist/scanners/hook-scanner.js +35 -0
- package/dist/scanners/hook-scanner.js.map +1 -0
- package/dist/scanners/index.d.ts +7 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +7 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/mcp-config-scanner.d.ts +7 -0
- package/dist/scanners/mcp-config-scanner.d.ts.map +1 -0
- package/dist/scanners/mcp-config-scanner.js +31 -0
- package/dist/scanners/mcp-config-scanner.js.map +1 -0
- package/dist/scanners/script-file-scanner.d.ts +14 -0
- package/dist/scanners/script-file-scanner.d.ts.map +1 -0
- package/dist/scanners/script-file-scanner.js +241 -0
- package/dist/scanners/script-file-scanner.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CompatibilityResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Analyze a Claude plugin directory for compatibility across all target surfaces.
|
|
4
|
+
*
|
|
5
|
+
* Walks the plugin directory, runs relevant scanners on each file,
|
|
6
|
+
* and aggregates evidence into per-target verdicts.
|
|
7
|
+
*
|
|
8
|
+
* @param pluginDir - Absolute path to the plugin root directory
|
|
9
|
+
* @returns Aggregated compatibility result with evidence and verdicts
|
|
10
|
+
* @throws If the directory does not contain a valid .claude-plugin/plugin.json
|
|
11
|
+
*/
|
|
12
|
+
export declare function analyzeCompatibility(pluginDir: string): Promise<CompatibilityResult>;
|
|
13
|
+
//# sourceMappingURL=compatibility-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compatibility-analyzer.d.ts","sourceRoot":"","sources":["../src/compatibility-analyzer.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAyB,mBAAmB,EAAgC,MAAM,YAAY,CAAC;AAkM3G;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+C1F"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { extname, join, relative } from 'node:path';
|
|
3
|
+
import { toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
4
|
+
import { classifyScriptFile, scanCodeBlocks, scanFrontmatter, scanHooksConfig, scanMcpConfig, scanPythonImports, } from './scanners/index.js';
|
|
5
|
+
import { ALL_TARGETS } from './types.js';
|
|
6
|
+
/** File extensions treated as scripts by the scanner */
|
|
7
|
+
const SCRIPT_EXTENSIONS = new Set(['.py', '.sh', '.bash', '.mjs', '.js', '.cjs']);
|
|
8
|
+
/** File extensions that are markdown (skills, agents, commands) */
|
|
9
|
+
const MARKDOWN_EXTENSIONS = new Set(['.md']);
|
|
10
|
+
/**
|
|
11
|
+
* Read and parse .claude-plugin/plugin.json from the plugin directory.
|
|
12
|
+
* Throws if the file does not exist or is invalid JSON.
|
|
13
|
+
*/
|
|
14
|
+
async function readPluginManifest(pluginDir) {
|
|
15
|
+
const manifestPath = join(pluginDir, '.claude-plugin', 'plugin.json');
|
|
16
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path constructed from join(pluginDir, ...)
|
|
17
|
+
const raw = await readFile(manifestPath, 'utf8');
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
if (!parsed['name'] || typeof parsed['name'] !== 'string') {
|
|
20
|
+
throw new Error(`plugin.json missing required "name" field in ${manifestPath}`);
|
|
21
|
+
}
|
|
22
|
+
const manifest = { name: parsed['name'] };
|
|
23
|
+
if (typeof parsed['version'] === 'string') {
|
|
24
|
+
manifest.version = parsed['version'];
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(parsed['targets'])) {
|
|
27
|
+
manifest.targets = parsed['targets'];
|
|
28
|
+
}
|
|
29
|
+
return manifest;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Recursively collect all file paths relative to the root directory.
|
|
33
|
+
* Skips the .claude-plugin directory itself (manifest is read separately).
|
|
34
|
+
*/
|
|
35
|
+
async function collectFiles(rootDir) {
|
|
36
|
+
const files = [];
|
|
37
|
+
async function walk(dir) {
|
|
38
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- recursive walk of user-provided plugin directory
|
|
39
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
const fullPath = join(dir, entry.name);
|
|
42
|
+
const relativePath = toForwardSlash(relative(rootDir, fullPath));
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
// Skip the .claude-plugin metadata directory
|
|
45
|
+
if (entry.name === '.claude-plugin')
|
|
46
|
+
continue;
|
|
47
|
+
await walk(fullPath);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
files.push(relativePath);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
await walk(rootDir);
|
|
55
|
+
return files;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Determine if an evidence item has meaningful impact (not all-ok).
|
|
59
|
+
* Evidence where every target is 'ok' is informational noise and gets filtered out.
|
|
60
|
+
*/
|
|
61
|
+
function hasNonOkImpact(evidence) {
|
|
62
|
+
return ALL_TARGETS.some(target => evidence.impact[target] !== 'ok');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Aggregate evidence into a per-target verdict.
|
|
66
|
+
* Worst impact wins: any 'incompatible' -> incompatible, any 'needs-review' -> needs-review.
|
|
67
|
+
*/
|
|
68
|
+
function aggregateVerdicts(evidence) {
|
|
69
|
+
const result = {
|
|
70
|
+
'claude-desktop': 'compatible',
|
|
71
|
+
cowork: 'compatible',
|
|
72
|
+
'claude-code': 'compatible',
|
|
73
|
+
};
|
|
74
|
+
for (const item of evidence) {
|
|
75
|
+
for (const target of ALL_TARGETS) {
|
|
76
|
+
const impact = item.impact[target];
|
|
77
|
+
if (impact === 'incompatible') {
|
|
78
|
+
result[target] = 'incompatible';
|
|
79
|
+
}
|
|
80
|
+
else if (impact === 'needs-review' && result[target] !== 'incompatible') {
|
|
81
|
+
result[target] = 'needs-review';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Scan a single markdown file for compatibility evidence.
|
|
89
|
+
*/
|
|
90
|
+
async function scanMarkdownFile(fullPath, relativePath) {
|
|
91
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from collectFiles walk
|
|
92
|
+
const content = await readFile(fullPath, 'utf8');
|
|
93
|
+
return [
|
|
94
|
+
...scanCodeBlocks(content, relativePath),
|
|
95
|
+
...scanFrontmatter(content, relativePath),
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Scan a script file for compatibility evidence.
|
|
100
|
+
* For Python files, also scans imports for third-party dependencies.
|
|
101
|
+
*/
|
|
102
|
+
async function scanScriptFile(fullPath, relativePath) {
|
|
103
|
+
const evidence = [];
|
|
104
|
+
const classification = classifyScriptFile(relativePath);
|
|
105
|
+
if (classification) {
|
|
106
|
+
evidence.push(classification);
|
|
107
|
+
}
|
|
108
|
+
if (extname(relativePath).toLowerCase() === '.py') {
|
|
109
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from collectFiles walk
|
|
110
|
+
const content = await readFile(fullPath, 'utf8');
|
|
111
|
+
evidence.push(...scanPythonImports(content, relativePath));
|
|
112
|
+
}
|
|
113
|
+
return evidence;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Scan a hooks JSON file for compatibility evidence.
|
|
117
|
+
*/
|
|
118
|
+
async function scanHooksFile(fullPath, relativePath) {
|
|
119
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from collectFiles walk
|
|
120
|
+
const raw = await readFile(fullPath, 'utf8');
|
|
121
|
+
const config = JSON.parse(raw);
|
|
122
|
+
return scanHooksConfig(config, relativePath);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Scan an MCP config file for compatibility evidence.
|
|
126
|
+
*/
|
|
127
|
+
async function scanMcpFile(fullPath, relativePath) {
|
|
128
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from collectFiles walk
|
|
129
|
+
const raw = await readFile(fullPath, 'utf8');
|
|
130
|
+
const config = JSON.parse(raw);
|
|
131
|
+
return scanMcpConfig(config, relativePath);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if a file path matches a hooks config pattern.
|
|
135
|
+
* Matches: hooks.json, hooks/hooks.json, hooks/*.json
|
|
136
|
+
*/
|
|
137
|
+
function isHooksFile(relativePath) {
|
|
138
|
+
if (relativePath === 'hooks.json')
|
|
139
|
+
return true;
|
|
140
|
+
// eslint-disable-next-line local/no-path-startswith -- relativePath already normalized via toForwardSlash in collectFiles
|
|
141
|
+
return relativePath.startsWith('hooks/') && relativePath.endsWith('.json');
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check if a file path is an MCP config file.
|
|
145
|
+
*/
|
|
146
|
+
function isMcpConfigFile(relativePath) {
|
|
147
|
+
return relativePath === '.mcp.json';
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Analyze a Claude plugin directory for compatibility across all target surfaces.
|
|
151
|
+
*
|
|
152
|
+
* Walks the plugin directory, runs relevant scanners on each file,
|
|
153
|
+
* and aggregates evidence into per-target verdicts.
|
|
154
|
+
*
|
|
155
|
+
* @param pluginDir - Absolute path to the plugin root directory
|
|
156
|
+
* @returns Aggregated compatibility result with evidence and verdicts
|
|
157
|
+
* @throws If the directory does not contain a valid .claude-plugin/plugin.json
|
|
158
|
+
*/
|
|
159
|
+
export async function analyzeCompatibility(pluginDir) {
|
|
160
|
+
const manifest = await readPluginManifest(pluginDir);
|
|
161
|
+
const files = await collectFiles(pluginDir);
|
|
162
|
+
const allEvidence = [];
|
|
163
|
+
const counts = {
|
|
164
|
+
totalFiles: files.length,
|
|
165
|
+
skillFiles: 0,
|
|
166
|
+
scriptFiles: 0,
|
|
167
|
+
hookFiles: 0,
|
|
168
|
+
mcpConfigs: 0,
|
|
169
|
+
};
|
|
170
|
+
for (const relativePath of files) {
|
|
171
|
+
const fullPath = join(pluginDir, relativePath);
|
|
172
|
+
const ext = extname(relativePath).toLowerCase();
|
|
173
|
+
if (MARKDOWN_EXTENSIONS.has(ext)) {
|
|
174
|
+
counts.skillFiles++;
|
|
175
|
+
const evidence = await scanMarkdownFile(fullPath, relativePath);
|
|
176
|
+
allEvidence.push(...evidence);
|
|
177
|
+
}
|
|
178
|
+
else if (SCRIPT_EXTENSIONS.has(ext)) {
|
|
179
|
+
counts.scriptFiles++;
|
|
180
|
+
const evidence = await scanScriptFile(fullPath, relativePath);
|
|
181
|
+
allEvidence.push(...evidence);
|
|
182
|
+
}
|
|
183
|
+
else if (isHooksFile(relativePath)) {
|
|
184
|
+
counts.hookFiles++;
|
|
185
|
+
const evidence = await scanHooksFile(fullPath, relativePath);
|
|
186
|
+
allEvidence.push(...evidence);
|
|
187
|
+
}
|
|
188
|
+
else if (isMcpConfigFile(relativePath)) {
|
|
189
|
+
counts.mcpConfigs++;
|
|
190
|
+
const evidence = await scanMcpFile(fullPath, relativePath);
|
|
191
|
+
allEvidence.push(...evidence);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Filter out evidence where all targets are 'ok' (informational noise)
|
|
195
|
+
const meaningfulEvidence = allEvidence.filter(hasNonOkImpact);
|
|
196
|
+
return {
|
|
197
|
+
plugin: manifest.name,
|
|
198
|
+
version: manifest.version,
|
|
199
|
+
declared: manifest.targets,
|
|
200
|
+
analyzed: aggregateVerdicts(meaningfulEvidence),
|
|
201
|
+
evidence: meaningfulEvidence,
|
|
202
|
+
summary: counts,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=compatibility-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compatibility-analyzer.js","sourceRoot":"","sources":["../src/compatibility-analyzer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vibe-agent-toolkit/claude-marketplace
|
|
3
|
+
* Claude plugin marketplace tools: compatibility analysis, provenance tracking, enterprise config
|
|
4
|
+
*/
|
|
5
|
+
export type { CompatibilityEvidence, CompatibilityResult, EvidenceSource, Target, Verdict, } from './types.js';
|
|
6
|
+
export { ALL_TARGETS } from './types.js';
|
|
7
|
+
export { analyzeCompatibility } from './compatibility-analyzer.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,MAAM,EACN,OAAO,GACR,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vibe-agent-toolkit/claude-marketplace
|
|
3
|
+
* Claude plugin marketplace tools: compatibility analysis, provenance tracking, enterprise config
|
|
4
|
+
*/
|
|
5
|
+
export { ALL_TARGETS } from './types.js';
|
|
6
|
+
export { analyzeCompatibility } from './compatibility-analyzer.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CompatibilityEvidence } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan markdown content for fenced code blocks containing command invocations.
|
|
4
|
+
* Only scans blocks with executable languages (bash, sh, shell, zsh, unlabeled).
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanCodeBlocks(content: string, filePath: string): CompatibilityEvidence[];
|
|
7
|
+
//# sourceMappingURL=code-block-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-scanner.d.ts","sourceRoot":"","sources":["../../src/scanners/code-block-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AASzD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CA0BzF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { COMMAND_RULES } from './command-classifier.js';
|
|
2
|
+
const EXECUTABLE_LANGUAGES = new Set(['bash', 'sh', 'shell', 'zsh', '']);
|
|
3
|
+
/** Regex to extract fenced code blocks: ```lang\ncontent\n``` */
|
|
4
|
+
const CODE_BLOCK_RE = /^```(\w*)\n([\s\S]*?)^```/gm;
|
|
5
|
+
/**
|
|
6
|
+
* Scan markdown content for fenced code blocks containing command invocations.
|
|
7
|
+
* Only scans blocks with executable languages (bash, sh, shell, zsh, unlabeled).
|
|
8
|
+
*/
|
|
9
|
+
export function scanCodeBlocks(content, filePath) {
|
|
10
|
+
const evidence = [];
|
|
11
|
+
for (const match of content.matchAll(CODE_BLOCK_RE)) {
|
|
12
|
+
const language = match[1] ?? '';
|
|
13
|
+
const blockContent = match[2] ?? '';
|
|
14
|
+
const blockStartOffset = match.index ?? 0;
|
|
15
|
+
const blockLine = content.slice(0, blockStartOffset).split('\n').length;
|
|
16
|
+
if (!EXECUTABLE_LANGUAGES.has(language))
|
|
17
|
+
continue;
|
|
18
|
+
for (const rule of COMMAND_RULES) {
|
|
19
|
+
if (rule.pattern.test(blockContent)) {
|
|
20
|
+
evidence.push({
|
|
21
|
+
source: 'code-block',
|
|
22
|
+
file: filePath,
|
|
23
|
+
line: blockLine,
|
|
24
|
+
signal: rule.signal,
|
|
25
|
+
detail: `Found "${rule.signal}" command in ${language || 'unlabeled'} code block`,
|
|
26
|
+
impact: { ...rule.impact },
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return evidence;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=code-block-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-scanner.js","sourceRoot":"","sources":["../../src/scanners/code-block-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;AAEzE,iEAAiE;AACjE,MAAM,aAAa,GAAG,6BAA6B,CAAC;AAEpD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,QAAgB;IAC9D,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAE7C,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAExE,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QAElD,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBACpC,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,YAAY;oBACpB,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,MAAM,EAAE,UAAU,IAAI,CAAC,MAAM,gBAAgB,QAAQ,IAAI,WAAW,aAAa;oBACjF,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ImpactLevel, Target } from '../types.js';
|
|
2
|
+
export interface CommandRule {
|
|
3
|
+
pattern: RegExp;
|
|
4
|
+
signal: string;
|
|
5
|
+
impact: Record<Target, ImpactLevel>;
|
|
6
|
+
}
|
|
7
|
+
/** Commands and their impact on each target */
|
|
8
|
+
export declare const COMMAND_RULES: readonly CommandRule[];
|
|
9
|
+
/**
|
|
10
|
+
* Classify a command string against known command patterns.
|
|
11
|
+
* Returns the first matching rule or undefined.
|
|
12
|
+
*/
|
|
13
|
+
export declare function classifyCommand(command: string): {
|
|
14
|
+
signal: string;
|
|
15
|
+
impact: Record<Target, ImpactLevel>;
|
|
16
|
+
} | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Classify a standalone binary name (e.g., "python3", "node", "uv").
|
|
19
|
+
* Unlike classifyCommand which matches regex patterns against full command strings,
|
|
20
|
+
* this performs an exact lookup for MCP server command binaries.
|
|
21
|
+
*/
|
|
22
|
+
export declare function classifyCommandBinary(binary: string): {
|
|
23
|
+
signal: string;
|
|
24
|
+
impact: Record<Target, ImpactLevel>;
|
|
25
|
+
} | undefined;
|
|
26
|
+
//# sourceMappingURL=command-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-classifier.d.ts","sourceRoot":"","sources":["../../src/scanners/command-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGvD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrC;AAaD,+CAA+C;AAC/C,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAqCtC,CAAC;AAEX;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,GACd;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CAAE,GAAG,SAAS,CAOrE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GACb;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CAAE,GAAG,SAAS,CAIrE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { IMPACT_ALL_OK, IMPACT_INCOMPATIBLE_DESKTOP, IMPACT_NEEDS_REVIEW_DESKTOP } from '../types.js';
|
|
2
|
+
/** Maps known binary names to their compatibility impact */
|
|
3
|
+
const BINARY_IMPACTS = {
|
|
4
|
+
bash: { signal: 'bash', impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP } },
|
|
5
|
+
node: { signal: 'node', impact: { ...IMPACT_ALL_OK } },
|
|
6
|
+
npx: { signal: 'npx', impact: { ...IMPACT_ALL_OK } },
|
|
7
|
+
python: { signal: 'python3', impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP } },
|
|
8
|
+
python3: { signal: 'python3', impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP } },
|
|
9
|
+
sh: { signal: 'sh', impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP } },
|
|
10
|
+
uv: { signal: 'uv', impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP } },
|
|
11
|
+
};
|
|
12
|
+
/** Commands and their impact on each target */
|
|
13
|
+
export const COMMAND_RULES = [
|
|
14
|
+
{
|
|
15
|
+
pattern: /\bpip3?\s+install\b/,
|
|
16
|
+
signal: 'pip install',
|
|
17
|
+
impact: { ...IMPACT_INCOMPATIBLE_DESKTOP },
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
pattern: /\bnpm\s+install\b/,
|
|
21
|
+
signal: 'npm install',
|
|
22
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: /\buv\s+(?:run|pip|sync)\b/,
|
|
26
|
+
signal: 'uv',
|
|
27
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
pattern: /\bpython3?\s+/,
|
|
31
|
+
signal: 'python3',
|
|
32
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
pattern: /\bbash\s+/,
|
|
36
|
+
signal: 'bash',
|
|
37
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
// The `sh` pattern avoids matching file extensions like `.sh`
|
|
41
|
+
pattern: /(?<!\.)(?:^|[\s;|&])sh\s+/m,
|
|
42
|
+
signal: 'sh',
|
|
43
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
pattern: /\bnode\s+/,
|
|
47
|
+
signal: 'node',
|
|
48
|
+
impact: { ...IMPACT_ALL_OK },
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* Classify a command string against known command patterns.
|
|
53
|
+
* Returns the first matching rule or undefined.
|
|
54
|
+
*/
|
|
55
|
+
export function classifyCommand(command) {
|
|
56
|
+
for (const rule of COMMAND_RULES) {
|
|
57
|
+
if (rule.pattern.test(command)) {
|
|
58
|
+
return { signal: rule.signal, impact: { ...rule.impact } };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Classify a standalone binary name (e.g., "python3", "node", "uv").
|
|
65
|
+
* Unlike classifyCommand which matches regex patterns against full command strings,
|
|
66
|
+
* this performs an exact lookup for MCP server command binaries.
|
|
67
|
+
*/
|
|
68
|
+
export function classifyCommandBinary(binary) {
|
|
69
|
+
const entry = BINARY_IMPACTS[binary];
|
|
70
|
+
if (!entry)
|
|
71
|
+
return undefined;
|
|
72
|
+
return { signal: entry.signal, impact: { ...entry.impact } };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=command-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-classifier.js","sourceRoot":"","sources":["../../src/scanners/command-classifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAQtG,4DAA4D;AAC5D,MAAM,cAAc,GAA4E;IAC9F,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE,EAAE;IACpE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,EAAE,EAAE;IACtD,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,EAAE,EAAE;IACpD,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE,EAAE;IACzE,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE,EAAE;IAC1E,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE,EAAE;IAChE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE,EAAE;CACjE,CAAC;AAEF,+CAA+C;AAC/C,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD;QACE,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE;KAC3C;IACD;QACE,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE;KAC3C;IACD;QACE,OAAO,EAAE,2BAA2B;QACpC,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE;KAC3C;IACD;QACE,OAAO,EAAE,eAAe;QACxB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE;KAC3C;IACD;QACE,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE;KAC3C;IACD;QACE,8DAA8D;QAC9D,OAAO,EAAE,4BAA4B;QACrC,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,EAAE,GAAG,2BAA2B,EAAE;KAC3C;IACD;QACE,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,EAAE,GAAG,aAAa,EAAE;KAC7B;CACO,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAe;IAEf,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAC7D,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAc;IAEd,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CompatibilityEvidence } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan SKILL.md frontmatter for compatibility-relevant declarations.
|
|
4
|
+
* Checks `allowed-tools` for restricted tools and `targets` for author-declared surfaces.
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanFrontmatter(content: string, filePath: string): CompatibilityEvidence[];
|
|
7
|
+
//# sourceMappingURL=frontmatter-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter-scanner.d.ts","sourceRoot":"","sources":["../../src/scanners/frontmatter-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,aAAa,CAAC;AAuD9E;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAgC1F"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { parse as parseYaml } from 'yaml';
|
|
2
|
+
import { ALL_TARGETS, IMPACT_ALL_OK, IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW } from '../types.js';
|
|
3
|
+
/** Tools that require local environment access */
|
|
4
|
+
const RESTRICTED_TOOLS = {
|
|
5
|
+
Bash: { impact: { ...IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW } },
|
|
6
|
+
Edit: { impact: { ...IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW } },
|
|
7
|
+
Write: { impact: { ...IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW } },
|
|
8
|
+
NotebookEdit: { impact: { ...IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW } },
|
|
9
|
+
};
|
|
10
|
+
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---/;
|
|
11
|
+
function scanAllowedTools(allowedTools, filePath) {
|
|
12
|
+
const evidence = [];
|
|
13
|
+
for (const tool of allowedTools) {
|
|
14
|
+
const toolName = String(tool);
|
|
15
|
+
const restriction = RESTRICTED_TOOLS[toolName];
|
|
16
|
+
if (restriction) {
|
|
17
|
+
evidence.push({
|
|
18
|
+
source: 'frontmatter',
|
|
19
|
+
file: filePath,
|
|
20
|
+
signal: `allowed-tools: ${toolName}`,
|
|
21
|
+
detail: `Skill requires "${toolName}" tool which needs local environment access`,
|
|
22
|
+
impact: { ...restriction.impact },
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return evidence;
|
|
27
|
+
}
|
|
28
|
+
function scanTargetsDeclaration(targets, filePath) {
|
|
29
|
+
const declaredTargets = new Set(targets.map(String));
|
|
30
|
+
const excludedTargets = ALL_TARGETS.filter(t => !declaredTargets.has(t));
|
|
31
|
+
if (excludedTargets.length === 0)
|
|
32
|
+
return undefined;
|
|
33
|
+
const impact = { ...IMPACT_ALL_OK };
|
|
34
|
+
for (const t of excludedTargets) {
|
|
35
|
+
impact[t] = 'incompatible';
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
source: 'declaration',
|
|
39
|
+
file: filePath,
|
|
40
|
+
signal: `targets: [${targets.map(String).join(', ')}]`,
|
|
41
|
+
detail: `Author declares plugin targets: ${targets.map(String).join(', ')}. Not listed: ${excludedTargets.join(', ')}`,
|
|
42
|
+
impact,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Scan SKILL.md frontmatter for compatibility-relevant declarations.
|
|
47
|
+
* Checks `allowed-tools` for restricted tools and `targets` for author-declared surfaces.
|
|
48
|
+
*/
|
|
49
|
+
export function scanFrontmatter(content, filePath) {
|
|
50
|
+
const fmMatch = FRONTMATTER_RE.exec(content);
|
|
51
|
+
if (!fmMatch)
|
|
52
|
+
return [];
|
|
53
|
+
const rawYaml = fmMatch[1];
|
|
54
|
+
if (rawYaml === undefined)
|
|
55
|
+
return [];
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = parseYaml(rawYaml);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
if (!parsed || typeof parsed !== 'object')
|
|
64
|
+
return [];
|
|
65
|
+
const evidence = [];
|
|
66
|
+
const allowedTools = parsed['allowed-tools'];
|
|
67
|
+
if (Array.isArray(allowedTools)) {
|
|
68
|
+
evidence.push(...scanAllowedTools(allowedTools, filePath));
|
|
69
|
+
}
|
|
70
|
+
const targets = parsed['targets'];
|
|
71
|
+
if (Array.isArray(targets)) {
|
|
72
|
+
const targetEvidence = scanTargetsDeclaration(targets, filePath);
|
|
73
|
+
if (targetEvidence) {
|
|
74
|
+
evidence.push(targetEvidence);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return evidence;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=frontmatter-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter-scanner.js","sourceRoot":"","sources":["../../src/scanners/frontmatter-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,yCAAyC,EAAE,MAAM,aAAa,CAAC;AAEpG,kDAAkD;AAClD,MAAM,gBAAgB,GAA4D;IAChF,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,yCAAyC,EAAE,EAAE;IAClE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,yCAAyC,EAAE,EAAE;IAClE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,yCAAyC,EAAE,EAAE;IACnE,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,yCAAyC,EAAE,EAAE;CAC3E,CAAC;AAEF,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAE/C,SAAS,gBAAgB,CACvB,YAAuB,EACvB,QAAgB;IAEhB,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,WAAW,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,aAAa;gBACrB,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,kBAAkB,QAAQ,EAAE;gBACpC,MAAM,EAAE,mBAAmB,QAAQ,6CAA6C;gBAChF,MAAM,EAAE,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE;aAClC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAkB,EAClB,QAAgB;IAEhB,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEnD,MAAM,MAAM,GAAgC,EAAE,GAAG,aAAa,EAAE,CAAC;IACjE,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;IAC7B,CAAC;IACD,OAAO;QACL,MAAM,EAAE,aAAa;QACrB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,aAAa,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACtD,MAAM,EAAE,mCAAmC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACtH,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,QAAgB;IAC/D,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAErC,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,OAAO,CAA4B,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAErD,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAE7C,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;IAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,cAAc,GAAG,sBAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjE,IAAI,cAAc,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CompatibilityEvidence } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan a hooks config object for command handlers that indicate runtime requirements.
|
|
4
|
+
* Expects the parsed JSON from a hooks.json file.
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanHooksConfig(config: Record<string, unknown>, filePath: string): CompatibilityEvidence[];
|
|
7
|
+
//# sourceMappingURL=hook-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-scanner.d.ts","sourceRoot":"","sources":["../../src/scanners/hook-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAIzD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CA6B1G"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { classifyCommand } from './command-classifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan a hooks config object for command handlers that indicate runtime requirements.
|
|
4
|
+
* Expects the parsed JSON from a hooks.json file.
|
|
5
|
+
*/
|
|
6
|
+
export function scanHooksConfig(config, filePath) {
|
|
7
|
+
const evidence = [];
|
|
8
|
+
const hooks = config['hooks'];
|
|
9
|
+
if (!hooks || typeof hooks !== 'object')
|
|
10
|
+
return evidence;
|
|
11
|
+
for (const [eventName, handlers] of Object.entries(hooks)) {
|
|
12
|
+
if (!Array.isArray(handlers))
|
|
13
|
+
continue;
|
|
14
|
+
for (const handler of handlers) {
|
|
15
|
+
if (!handler || typeof handler !== 'object')
|
|
16
|
+
continue;
|
|
17
|
+
const h = handler;
|
|
18
|
+
if (h['type'] !== 'command' || typeof h['command'] !== 'string')
|
|
19
|
+
continue;
|
|
20
|
+
const command = h['command'];
|
|
21
|
+
const classification = classifyCommand(command);
|
|
22
|
+
if (classification) {
|
|
23
|
+
evidence.push({
|
|
24
|
+
source: 'hook',
|
|
25
|
+
file: filePath,
|
|
26
|
+
signal: `hook-command: ${classification.signal}`,
|
|
27
|
+
detail: `Hook "${eventName}" runs command: ${command}`,
|
|
28
|
+
impact: classification.impact,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return evidence;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=hook-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-scanner.js","sourceRoot":"","sources":["../../src/scanners/hook-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAA+B,EAAE,QAAgB;IAC/E,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAE7C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAEzD,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAkC,CAAC,EAAE,CAAC;QACvF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEvC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;gBAAE,SAAS;YACtD,MAAM,CAAC,GAAG,OAAkC,CAAC;YAC7C,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,QAAQ;gBAAE,SAAS;YAE1E,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;YAC7B,MAAM,cAAc,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAChD,IAAI,cAAc,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,QAAQ;oBACd,MAAM,EAAE,iBAAiB,cAAc,CAAC,MAAM,EAAE;oBAChD,MAAM,EAAE,SAAS,SAAS,mBAAmB,OAAO,EAAE;oBACtD,MAAM,EAAE,cAAc,CAAC,MAAM;iBAC9B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { scanCodeBlocks } from './code-block-scanner.js';
|
|
2
|
+
export { classifyCommand, classifyCommandBinary, COMMAND_RULES } from './command-classifier.js';
|
|
3
|
+
export { scanFrontmatter } from './frontmatter-scanner.js';
|
|
4
|
+
export { scanHooksConfig } from './hook-scanner.js';
|
|
5
|
+
export { scanMcpConfig } from './mcp-config-scanner.js';
|
|
6
|
+
export { classifyScriptFile, PYTHON_STDLIB_MODULES, scanPythonImports } from './script-file-scanner.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanners/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { scanCodeBlocks } from './code-block-scanner.js';
|
|
2
|
+
export { classifyCommand, classifyCommandBinary, COMMAND_RULES } from './command-classifier.js';
|
|
3
|
+
export { scanFrontmatter } from './frontmatter-scanner.js';
|
|
4
|
+
export { scanHooksConfig } from './hook-scanner.js';
|
|
5
|
+
export { scanMcpConfig } from './mcp-config-scanner.js';
|
|
6
|
+
export { classifyScriptFile, PYTHON_STDLIB_MODULES, scanPythonImports } from './script-file-scanner.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanners/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CompatibilityEvidence } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan an MCP config object for server runtime requirements.
|
|
4
|
+
* Expects the parsed JSON from a .mcp.json file.
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanMcpConfig(config: Record<string, unknown>, filePath: string): CompatibilityEvidence[];
|
|
7
|
+
//# sourceMappingURL=mcp-config-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config-scanner.d.ts","sourceRoot":"","sources":["../../src/scanners/mcp-config-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAIzD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAyBxG"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { classifyCommandBinary } from './command-classifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan an MCP config object for server runtime requirements.
|
|
4
|
+
* Expects the parsed JSON from a .mcp.json file.
|
|
5
|
+
*/
|
|
6
|
+
export function scanMcpConfig(config, filePath) {
|
|
7
|
+
const evidence = [];
|
|
8
|
+
const servers = config['mcpServers'];
|
|
9
|
+
if (!servers || typeof servers !== 'object')
|
|
10
|
+
return evidence;
|
|
11
|
+
for (const [serverName, serverConfig] of Object.entries(servers)) {
|
|
12
|
+
if (!serverConfig || typeof serverConfig !== 'object')
|
|
13
|
+
continue;
|
|
14
|
+
const sc = serverConfig;
|
|
15
|
+
const command = sc['command'];
|
|
16
|
+
if (typeof command !== 'string')
|
|
17
|
+
continue;
|
|
18
|
+
const classification = classifyCommandBinary(command);
|
|
19
|
+
if (classification) {
|
|
20
|
+
evidence.push({
|
|
21
|
+
source: 'mcp-server',
|
|
22
|
+
file: filePath,
|
|
23
|
+
signal: `mcp-server: ${classification.signal}`,
|
|
24
|
+
detail: `MCP server "${serverName}" uses command: ${command}`,
|
|
25
|
+
impact: classification.impact,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return evidence;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=mcp-config-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config-scanner.js","sourceRoot":"","sources":["../../src/scanners/mcp-config-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAA+B,EAAE,QAAgB;IAC7E,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAE7C,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE7D,KAAK,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAkC,CAAC,EAAE,CAAC;QAC5F,IAAI,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ;YAAE,SAAS;QAChE,MAAM,EAAE,GAAG,YAAuC,CAAC;QACnD,MAAM,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9B,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,SAAS;QAE1C,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,cAAc,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,YAAY;gBACpB,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,eAAe,cAAc,CAAC,MAAM,EAAE;gBAC9C,MAAM,EAAE,eAAe,UAAU,mBAAmB,OAAO,EAAE;gBAC7D,MAAM,EAAE,cAAc,CAAC,MAAM;aAC9B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CompatibilityEvidence } from '../types.js';
|
|
2
|
+
/** Python 3.10+ standard library modules */
|
|
3
|
+
export declare const PYTHON_STDLIB_MODULES: ReadonlySet<string>;
|
|
4
|
+
/**
|
|
5
|
+
* Classify a script file by its extension and return compatibility evidence.
|
|
6
|
+
* Returns undefined for non-script files.
|
|
7
|
+
*/
|
|
8
|
+
export declare function classifyScriptFile(relativePath: string): CompatibilityEvidence | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Parse Python source content for import statements and return evidence
|
|
11
|
+
* for any third-party (non-stdlib) imports found.
|
|
12
|
+
*/
|
|
13
|
+
export declare function scanPythonImports(content: string, filePath: string): CompatibilityEvidence[];
|
|
14
|
+
//# sourceMappingURL=script-file-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-file-scanner.d.ts","sourceRoot":"","sources":["../../src/scanners/script-file-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,aAAa,CAAC;AAG9E,4CAA4C;AAC5C,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,CAwJpD,CAAC;AAuCH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAe1F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAoC5F"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { extname } from 'node:path';
|
|
2
|
+
import { IMPACT_ALL_OK, IMPACT_NEEDS_REVIEW_DESKTOP } from '../types.js';
|
|
3
|
+
/** Python 3.10+ standard library modules */
|
|
4
|
+
export const PYTHON_STDLIB_MODULES = new Set([
|
|
5
|
+
'_thread',
|
|
6
|
+
'abc',
|
|
7
|
+
'argparse',
|
|
8
|
+
'ast',
|
|
9
|
+
'asyncio',
|
|
10
|
+
'base64',
|
|
11
|
+
'bisect',
|
|
12
|
+
'builtins',
|
|
13
|
+
'calendar',
|
|
14
|
+
'cmath',
|
|
15
|
+
'cmd',
|
|
16
|
+
'codecs',
|
|
17
|
+
'collections',
|
|
18
|
+
'colorsys',
|
|
19
|
+
'compileall',
|
|
20
|
+
'concurrent',
|
|
21
|
+
'configparser',
|
|
22
|
+
'contextlib',
|
|
23
|
+
'contextvars',
|
|
24
|
+
'copy',
|
|
25
|
+
'copyreg',
|
|
26
|
+
'cProfile',
|
|
27
|
+
'csv',
|
|
28
|
+
'ctypes',
|
|
29
|
+
'curses',
|
|
30
|
+
'dataclasses',
|
|
31
|
+
'datetime',
|
|
32
|
+
'decimal',
|
|
33
|
+
'difflib',
|
|
34
|
+
'dis',
|
|
35
|
+
'email',
|
|
36
|
+
'enum',
|
|
37
|
+
'errno',
|
|
38
|
+
'faulthandler',
|
|
39
|
+
'filecmp',
|
|
40
|
+
'fileinput',
|
|
41
|
+
'fnmatch',
|
|
42
|
+
'fractions',
|
|
43
|
+
'ftplib',
|
|
44
|
+
'functools',
|
|
45
|
+
'gc',
|
|
46
|
+
'getopt',
|
|
47
|
+
'getpass',
|
|
48
|
+
'gettext',
|
|
49
|
+
'glob',
|
|
50
|
+
'graphlib',
|
|
51
|
+
'gzip',
|
|
52
|
+
'hashlib',
|
|
53
|
+
'heapq',
|
|
54
|
+
'hmac',
|
|
55
|
+
'html',
|
|
56
|
+
'http',
|
|
57
|
+
'idlelib',
|
|
58
|
+
'imaplib',
|
|
59
|
+
'importlib',
|
|
60
|
+
'inspect',
|
|
61
|
+
'io',
|
|
62
|
+
'ipaddress',
|
|
63
|
+
'itertools',
|
|
64
|
+
'json',
|
|
65
|
+
'keyword',
|
|
66
|
+
'linecache',
|
|
67
|
+
'locale',
|
|
68
|
+
'logging',
|
|
69
|
+
'lzma',
|
|
70
|
+
'mailbox',
|
|
71
|
+
'math',
|
|
72
|
+
'mimetypes',
|
|
73
|
+
'modulefinder',
|
|
74
|
+
'multiprocessing',
|
|
75
|
+
'netrc',
|
|
76
|
+
'numbers',
|
|
77
|
+
'operator',
|
|
78
|
+
'os',
|
|
79
|
+
'pathlib',
|
|
80
|
+
'pdb',
|
|
81
|
+
'pickle',
|
|
82
|
+
'pickletools',
|
|
83
|
+
'platform',
|
|
84
|
+
'plistlib',
|
|
85
|
+
'poplib',
|
|
86
|
+
'posixpath',
|
|
87
|
+
'pprint',
|
|
88
|
+
'profile',
|
|
89
|
+
'pstats',
|
|
90
|
+
'py_compile',
|
|
91
|
+
'pyclbr',
|
|
92
|
+
'pydoc',
|
|
93
|
+
'queue',
|
|
94
|
+
'quopri',
|
|
95
|
+
'random',
|
|
96
|
+
're',
|
|
97
|
+
'readline',
|
|
98
|
+
'reprlib',
|
|
99
|
+
'runpy',
|
|
100
|
+
'sched',
|
|
101
|
+
'secrets',
|
|
102
|
+
'select',
|
|
103
|
+
'selectors',
|
|
104
|
+
'shelve',
|
|
105
|
+
'shlex',
|
|
106
|
+
'shutil',
|
|
107
|
+
'signal',
|
|
108
|
+
'site',
|
|
109
|
+
'smtplib',
|
|
110
|
+
'socket',
|
|
111
|
+
'socketserver',
|
|
112
|
+
'sqlite3',
|
|
113
|
+
'ssl',
|
|
114
|
+
'stat',
|
|
115
|
+
'statistics',
|
|
116
|
+
'string',
|
|
117
|
+
'stringprep',
|
|
118
|
+
'struct',
|
|
119
|
+
'subprocess',
|
|
120
|
+
'sys',
|
|
121
|
+
'sysconfig',
|
|
122
|
+
'syslog',
|
|
123
|
+
'tabnanny',
|
|
124
|
+
'tarfile',
|
|
125
|
+
'tempfile',
|
|
126
|
+
'test',
|
|
127
|
+
'textwrap',
|
|
128
|
+
'threading',
|
|
129
|
+
'time',
|
|
130
|
+
'timeit',
|
|
131
|
+
'tkinter',
|
|
132
|
+
'token',
|
|
133
|
+
'tokenize',
|
|
134
|
+
'tomllib',
|
|
135
|
+
'trace',
|
|
136
|
+
'traceback',
|
|
137
|
+
'tracemalloc',
|
|
138
|
+
'turtle',
|
|
139
|
+
'types',
|
|
140
|
+
'typing',
|
|
141
|
+
'unicodedata',
|
|
142
|
+
'unittest',
|
|
143
|
+
'urllib',
|
|
144
|
+
'uuid',
|
|
145
|
+
'venv',
|
|
146
|
+
'warnings',
|
|
147
|
+
'wave',
|
|
148
|
+
'weakref',
|
|
149
|
+
'webbrowser',
|
|
150
|
+
'xml',
|
|
151
|
+
'xmlrpc',
|
|
152
|
+
'zipapp',
|
|
153
|
+
'zipfile',
|
|
154
|
+
'zipimport',
|
|
155
|
+
'zlib',
|
|
156
|
+
]);
|
|
157
|
+
const SIGNAL_NODE_SCRIPT = 'node-script';
|
|
158
|
+
const SIGNAL_SHELL_SCRIPT = 'shell-script';
|
|
159
|
+
/** Script extension classification rules */
|
|
160
|
+
const SCRIPT_RULES = {
|
|
161
|
+
'.py': {
|
|
162
|
+
signal: 'python-script',
|
|
163
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
164
|
+
},
|
|
165
|
+
'.sh': {
|
|
166
|
+
signal: SIGNAL_SHELL_SCRIPT,
|
|
167
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
168
|
+
},
|
|
169
|
+
'.bash': {
|
|
170
|
+
signal: SIGNAL_SHELL_SCRIPT,
|
|
171
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
172
|
+
},
|
|
173
|
+
'.mjs': {
|
|
174
|
+
signal: SIGNAL_NODE_SCRIPT,
|
|
175
|
+
impact: { ...IMPACT_ALL_OK },
|
|
176
|
+
},
|
|
177
|
+
'.js': {
|
|
178
|
+
signal: SIGNAL_NODE_SCRIPT,
|
|
179
|
+
impact: { ...IMPACT_ALL_OK },
|
|
180
|
+
},
|
|
181
|
+
'.cjs': {
|
|
182
|
+
signal: SIGNAL_NODE_SCRIPT,
|
|
183
|
+
impact: { ...IMPACT_ALL_OK },
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
/** Regex for `import X` and `import X as Y` */
|
|
187
|
+
const IMPORT_RE = /^import\s+(\w+)/;
|
|
188
|
+
/** Regex for `from X import Y` and `from X.sub import Y` */
|
|
189
|
+
const FROM_IMPORT_RE = /^from\s+(\w+)/;
|
|
190
|
+
/**
|
|
191
|
+
* Classify a script file by its extension and return compatibility evidence.
|
|
192
|
+
* Returns undefined for non-script files.
|
|
193
|
+
*/
|
|
194
|
+
export function classifyScriptFile(relativePath) {
|
|
195
|
+
const ext = extname(relativePath).toLowerCase();
|
|
196
|
+
const rule = SCRIPT_RULES[ext];
|
|
197
|
+
if (!rule) {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
source: 'script',
|
|
202
|
+
file: relativePath,
|
|
203
|
+
signal: rule.signal,
|
|
204
|
+
detail: `Script file detected: ${relativePath}`,
|
|
205
|
+
impact: { ...rule.impact },
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Parse Python source content for import statements and return evidence
|
|
210
|
+
* for any third-party (non-stdlib) imports found.
|
|
211
|
+
*/
|
|
212
|
+
export function scanPythonImports(content, filePath) {
|
|
213
|
+
const thirdPartyModules = new Set();
|
|
214
|
+
for (const line of content.split('\n')) {
|
|
215
|
+
const trimmed = line.trim();
|
|
216
|
+
let moduleName;
|
|
217
|
+
const importMatch = IMPORT_RE.exec(trimmed);
|
|
218
|
+
if (importMatch) {
|
|
219
|
+
moduleName = importMatch[1];
|
|
220
|
+
}
|
|
221
|
+
const fromMatch = FROM_IMPORT_RE.exec(trimmed);
|
|
222
|
+
if (fromMatch) {
|
|
223
|
+
moduleName = fromMatch[1];
|
|
224
|
+
}
|
|
225
|
+
if (moduleName && !PYTHON_STDLIB_MODULES.has(moduleName)) {
|
|
226
|
+
thirdPartyModules.add(moduleName);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const evidence = [];
|
|
230
|
+
for (const moduleName of thirdPartyModules) {
|
|
231
|
+
evidence.push({
|
|
232
|
+
source: 'script-import',
|
|
233
|
+
file: filePath,
|
|
234
|
+
signal: `third-party-import:${moduleName}`,
|
|
235
|
+
detail: `Third-party Python import "${moduleName}" requires pip install`,
|
|
236
|
+
impact: { ...IMPACT_NEEDS_REVIEW_DESKTOP },
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
return evidence;
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=script-file-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-file-scanner.js","sourceRoot":"","sources":["../../src/scanners/script-file-scanner.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for Claude plugin compatibility analysis.
|
|
3
|
+
*
|
|
4
|
+
* Three Claude surfaces with different runtime capabilities:
|
|
5
|
+
* - claude-desktop: Most restrictive (MCP servers only, no local scripts)
|
|
6
|
+
* - cowork: Middle ground (VM with Python 3.10 + Node.js 22, restricted network)
|
|
7
|
+
* - claude-code: Least restrictive (full local environment)
|
|
8
|
+
*/
|
|
9
|
+
/** Claude surface where plugins can run */
|
|
10
|
+
export type Target = 'claude-desktop' | 'cowork' | 'claude-code';
|
|
11
|
+
/** All targets in order of restrictiveness (most to least) */
|
|
12
|
+
export declare const ALL_TARGETS: readonly Target[];
|
|
13
|
+
/** Per-target impact level used in evidence records */
|
|
14
|
+
export type ImpactLevel = 'ok' | 'needs-review' | 'incompatible';
|
|
15
|
+
/** Common impact patterns reused across scanners */
|
|
16
|
+
export declare const IMPACT_NEEDS_REVIEW_DESKTOP: Record<Target, ImpactLevel>;
|
|
17
|
+
export declare const IMPACT_ALL_OK: Record<Target, ImpactLevel>;
|
|
18
|
+
export declare const IMPACT_INCOMPATIBLE_DESKTOP: Record<Target, ImpactLevel>;
|
|
19
|
+
export declare const IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW: Record<Target, ImpactLevel>;
|
|
20
|
+
/**
|
|
21
|
+
* Three-tier verdict to handle ambiguity in static analysis.
|
|
22
|
+
* - compatible: High confidence this works on the target
|
|
23
|
+
* - needs-review: Signals detected but uncertain — curator decides
|
|
24
|
+
* - incompatible: Definitive evidence it cannot work on the target
|
|
25
|
+
*/
|
|
26
|
+
export type Verdict = 'compatible' | 'needs-review' | 'incompatible';
|
|
27
|
+
/** Where a compatibility signal was detected */
|
|
28
|
+
export type EvidenceSource = 'declaration' | 'frontmatter' | 'code-block' | 'script' | 'script-import' | 'hook' | 'mcp-server';
|
|
29
|
+
/**
|
|
30
|
+
* A single piece of compatibility evidence found during analysis.
|
|
31
|
+
* Each evidence item records what was found, where, and how it impacts each target.
|
|
32
|
+
*/
|
|
33
|
+
export interface CompatibilityEvidence {
|
|
34
|
+
/** What type of source produced this evidence */
|
|
35
|
+
source: EvidenceSource;
|
|
36
|
+
/** File where the signal was found (relative to plugin root) */
|
|
37
|
+
file: string;
|
|
38
|
+
/** Line number within the file (1-based, when applicable) */
|
|
39
|
+
line?: number | undefined;
|
|
40
|
+
/** Short description of the signal (e.g., "python3 command", "pip install") */
|
|
41
|
+
signal: string;
|
|
42
|
+
/** Human-readable detail explaining what was found */
|
|
43
|
+
detail: string;
|
|
44
|
+
/** Impact on each target surface */
|
|
45
|
+
impact: Record<Target, ImpactLevel>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Aggregated compatibility result for a single plugin.
|
|
49
|
+
* Plugin verdict = worst verdict across all evidence for each target.
|
|
50
|
+
*/
|
|
51
|
+
export interface CompatibilityResult {
|
|
52
|
+
/** Plugin name from plugin.json */
|
|
53
|
+
plugin: string;
|
|
54
|
+
/** Plugin version from plugin.json (if present) */
|
|
55
|
+
version?: string | undefined;
|
|
56
|
+
/** Author-declared target surfaces (if present in plugin.json) */
|
|
57
|
+
declared?: Target[] | undefined;
|
|
58
|
+
/** Analyzed verdict per target */
|
|
59
|
+
analyzed: Record<Target, Verdict>;
|
|
60
|
+
/** All evidence collected during analysis */
|
|
61
|
+
evidence: CompatibilityEvidence[];
|
|
62
|
+
/** Summary counts for quick assessment */
|
|
63
|
+
summary: {
|
|
64
|
+
totalFiles: number;
|
|
65
|
+
skillFiles: number;
|
|
66
|
+
scriptFiles: number;
|
|
67
|
+
hookFiles: number;
|
|
68
|
+
mcpConfigs: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,MAAM,GAAG,gBAAgB,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEjE,8DAA8D;AAC9D,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAAyD,CAAC;AAEnG,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,cAAc,GAAG,cAAc,CAAC;AAEjE,oDAAoD;AACpD,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAI1D,CAAC;AAEX,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAI5C,CAAC;AAEX,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAI1D,CAAC;AAEX,eAAO,MAAM,yCAAyC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAIxE,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,CAAC;AAErE,gDAAgD;AAChD,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,YAAY,GACZ,QAAQ,GACR,eAAe,GACf,MAAM,GACN,YAAY,CAAC;AAEjB;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,MAAM,EAAE,cAAc,CAAC;IACvB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAChC,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,6CAA6C;IAC7C,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,0CAA0C;IAC1C,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for Claude plugin compatibility analysis.
|
|
3
|
+
*
|
|
4
|
+
* Three Claude surfaces with different runtime capabilities:
|
|
5
|
+
* - claude-desktop: Most restrictive (MCP servers only, no local scripts)
|
|
6
|
+
* - cowork: Middle ground (VM with Python 3.10 + Node.js 22, restricted network)
|
|
7
|
+
* - claude-code: Least restrictive (full local environment)
|
|
8
|
+
*/
|
|
9
|
+
/** All targets in order of restrictiveness (most to least) */
|
|
10
|
+
export const ALL_TARGETS = ['claude-desktop', 'cowork', 'claude-code'];
|
|
11
|
+
/** Common impact patterns reused across scanners */
|
|
12
|
+
export const IMPACT_NEEDS_REVIEW_DESKTOP = {
|
|
13
|
+
'claude-desktop': 'needs-review',
|
|
14
|
+
cowork: 'ok',
|
|
15
|
+
'claude-code': 'ok',
|
|
16
|
+
};
|
|
17
|
+
export const IMPACT_ALL_OK = {
|
|
18
|
+
'claude-desktop': 'ok',
|
|
19
|
+
cowork: 'ok',
|
|
20
|
+
'claude-code': 'ok',
|
|
21
|
+
};
|
|
22
|
+
export const IMPACT_INCOMPATIBLE_DESKTOP = {
|
|
23
|
+
'claude-desktop': 'incompatible',
|
|
24
|
+
cowork: 'ok',
|
|
25
|
+
'claude-code': 'ok',
|
|
26
|
+
};
|
|
27
|
+
export const IMPACT_DESKTOP_INCOMPATIBLE_COWORK_REVIEW = {
|
|
28
|
+
'claude-desktop': 'incompatible',
|
|
29
|
+
cowork: 'needs-review',
|
|
30
|
+
'claude-code': 'ok',
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAsB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,aAAa,CAAU,CAAC;AAKnG,oDAAoD;AACpD,MAAM,CAAC,MAAM,2BAA2B,GAAgC;IACtE,gBAAgB,EAAE,cAAc;IAChC,MAAM,EAAE,IAAI;IACZ,aAAa,EAAE,IAAI;CACX,CAAC;AAEX,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,gBAAgB,EAAE,IAAI;IACtB,MAAM,EAAE,IAAI;IACZ,aAAa,EAAE,IAAI;CACX,CAAC;AAEX,MAAM,CAAC,MAAM,2BAA2B,GAAgC;IACtE,gBAAgB,EAAE,cAAc;IAChC,MAAM,EAAE,IAAI;IACZ,aAAa,EAAE,IAAI;CACX,CAAC;AAEX,MAAM,CAAC,MAAM,yCAAyC,GAAgC;IACpF,gBAAgB,EAAE,cAAc;IAChC,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,IAAI;CACX,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vibe-agent-toolkit/claude-marketplace",
|
|
3
|
+
"version": "0.1.15-rc.1",
|
|
4
|
+
"description": "Claude plugin marketplace tools: compatibility analysis, provenance tracking, enterprise config",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc --build",
|
|
20
|
+
"build:watch": "tsc --build --watch",
|
|
21
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest watch",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@vibe-agent-toolkit/utils": "0.1.15-rc.1",
|
|
29
|
+
"yaml": "^2.6.1"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
33
|
+
"typescript": "~5.7.2",
|
|
34
|
+
"vitest": "^3.0.3"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"claude",
|
|
38
|
+
"marketplace",
|
|
39
|
+
"plugin",
|
|
40
|
+
"compatibility",
|
|
41
|
+
"enterprise"
|
|
42
|
+
],
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/jdutton/vibe-agent-toolkit.git",
|
|
46
|
+
"directory": "packages/claude-marketplace"
|
|
47
|
+
},
|
|
48
|
+
"author": "Jeff Dutton",
|
|
49
|
+
"license": "MIT"
|
|
50
|
+
}
|