skillshield 1.0.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/LICENSE +21 -0
- package/README.md +400 -0
- package/dist/channels/discord.d.ts +18 -0
- package/dist/channels/discord.d.ts.map +1 -0
- package/dist/channels/discord.js +275 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/index.d.ts +67 -0
- package/dist/channels/index.d.ts.map +1 -0
- package/dist/channels/index.js +127 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/channels/slack.d.ts +20 -0
- package/dist/channels/slack.d.ts.map +1 -0
- package/dist/channels/slack.js +296 -0
- package/dist/channels/slack.js.map +1 -0
- package/dist/channels/telegram.d.ts +20 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js +223 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/whatsapp.d.ts +25 -0
- package/dist/channels/whatsapp.d.ts.map +1 -0
- package/dist/channels/whatsapp.js +187 -0
- package/dist/channels/whatsapp.js.map +1 -0
- package/dist/cli/commands/badge.d.ts +11 -0
- package/dist/cli/commands/badge.d.ts.map +1 -0
- package/dist/cli/commands/badge.js +98 -0
- package/dist/cli/commands/badge.js.map +1 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +140 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +3 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +56 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +99 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +3 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +90 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +3 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +76 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/run.d.ts +3 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +160 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +3 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +133 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/search.d.ts +3 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +56 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +70 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/config.d.ts +167 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +398 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/parser.d.ts +34 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +462 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/runtime.d.ts +68 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +560 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/types.d.ts +525 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +44 -0
- package/dist/core/types.js.map +1 -0
- package/dist/guard/index.d.ts +57 -0
- package/dist/guard/index.d.ts.map +1 -0
- package/dist/guard/index.js +238 -0
- package/dist/guard/index.js.map +1 -0
- package/dist/guard/patterns.d.ts +21 -0
- package/dist/guard/patterns.d.ts.map +1 -0
- package/dist/guard/patterns.js +797 -0
- package/dist/guard/patterns.js.map +1 -0
- package/dist/hub/index.d.ts +44 -0
- package/dist/hub/index.d.ts.map +1 -0
- package/dist/hub/index.js +144 -0
- package/dist/hub/index.js.map +1 -0
- package/dist/hub/registry.d.ts +52 -0
- package/dist/hub/registry.d.ts.map +1 -0
- package/dist/hub/registry.js +192 -0
- package/dist/hub/registry.js.map +1 -0
- package/dist/i18n/index.d.ts +19 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +92 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/locales/en.d.ts +110 -0
- package/dist/i18n/locales/en.d.ts.map +1 -0
- package/dist/i18n/locales/en.js +123 -0
- package/dist/i18n/locales/en.js.map +1 -0
- package/dist/i18n/locales/es.d.ts +110 -0
- package/dist/i18n/locales/es.d.ts.map +1 -0
- package/dist/i18n/locales/es.js +123 -0
- package/dist/i18n/locales/es.js.map +1 -0
- package/dist/i18n/locales/pt.d.ts +110 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -0
- package/dist/i18n/locales/pt.js +123 -0
- package/dist/i18n/locales/pt.js.map +1 -0
- package/dist/i18n/locales/zh.d.ts +110 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -0
- package/dist/i18n/locales/zh.js +123 -0
- package/dist/i18n/locales/zh.js.map +1 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +275 -0
- package/dist/index.js.map +1 -0
- package/dist/router/index.d.ts +89 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +292 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/providers.d.ts +48 -0
- package/dist/router/providers.d.ts.map +1 -0
- package/dist/router/providers.js +733 -0
- package/dist/router/providers.js.map +1 -0
- package/dist/runtime/executor.d.ts +96 -0
- package/dist/runtime/executor.d.ts.map +1 -0
- package/dist/runtime/executor.js +389 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/sandbox/index.d.ts +52 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +248 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/security/skillguard.d.ts +25 -0
- package/dist/security/skillguard.d.ts.map +1 -0
- package/dist/security/skillguard.js +137 -0
- package/dist/security/skillguard.js.map +1 -0
- package/dist/tools/index.d.ts +55 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +276 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/web-engine.d.ts +158 -0
- package/dist/tools/web-engine.d.ts.map +1 -0
- package/dist/tools/web-engine.js +802 -0
- package/dist/tools/web-engine.js.map +1 -0
- package/dist/tools/web-tools.d.ts +173 -0
- package/dist/tools/web-tools.d.ts.map +1 -0
- package/dist/tools/web-tools.js +251 -0
- package/dist/tools/web-tools.js.map +1 -0
- package/dist/utils/errors.d.ts +44 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +130 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +121 -0
- package/dist/utils/logger.js.map +1 -0
- package/examples/basic-usage.ts +276 -0
- package/examples/code-reviewer.skill.md +83 -0
- package/examples/creative-writer.skill.md +80 -0
- package/examples/data-analyzer.skill.md +61 -0
- package/examples/hello-world.skill.md +36 -0
- package/examples/sample-skill.md +156 -0
- package/examples/summarizer.skill.md +62 -0
- package/examples/translator.skill.md +45 -0
- package/package.json +110 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { resolve } from 'path';
|
|
7
|
+
import { t } from '../../i18n/index.js';
|
|
8
|
+
export function init(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('init')
|
|
11
|
+
.description(chalk.cyan('Initialize SkillKit in your project'))
|
|
12
|
+
.option('--yes', 'Use default values without prompting')
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
try {
|
|
15
|
+
console.log(chalk.cyan.bold('\n⨠SkillKit Setup Wizard\n'));
|
|
16
|
+
const config = {
|
|
17
|
+
language: 'en',
|
|
18
|
+
provider: 'anthropic',
|
|
19
|
+
model: 'claude-3-5-sonnet',
|
|
20
|
+
apiKey: '',
|
|
21
|
+
registryUrl: 'https://clawhub.ai',
|
|
22
|
+
};
|
|
23
|
+
if (options.yes) {
|
|
24
|
+
// Use defaults
|
|
25
|
+
config.apiKey = process.env.SKILLKIT_API_KEY || '';
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Interactive prompts
|
|
29
|
+
const answers = await inquirer.prompt([
|
|
30
|
+
{
|
|
31
|
+
type: 'list',
|
|
32
|
+
name: 'language',
|
|
33
|
+
message: t('init.language'),
|
|
34
|
+
choices: [
|
|
35
|
+
{ name: 'English', value: 'en' },
|
|
36
|
+
{ name: 'EspaƱol', value: 'es' },
|
|
37
|
+
{ name: 'äøę', value: 'zh' },
|
|
38
|
+
{ name: 'PortuguĆŖs', value: 'pt' },
|
|
39
|
+
],
|
|
40
|
+
default: 'en',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'list',
|
|
44
|
+
name: 'provider',
|
|
45
|
+
message: t('init.provider'),
|
|
46
|
+
choices: [
|
|
47
|
+
{ name: 'Anthropic (Claude)', value: 'anthropic' },
|
|
48
|
+
{ name: 'OpenAI (GPT)', value: 'openai' },
|
|
49
|
+
{ name: 'Groq', value: 'groq' },
|
|
50
|
+
],
|
|
51
|
+
default: 'anthropic',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: 'input',
|
|
55
|
+
name: 'apiKey',
|
|
56
|
+
message: t('init.apiKey'),
|
|
57
|
+
mask: '*',
|
|
58
|
+
validate: (input) => input.length > 0 || t('init.apiKeyRequired'),
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
Object.assign(config, answers);
|
|
62
|
+
}
|
|
63
|
+
// Create ~/.skillkit/
|
|
64
|
+
const spinner = ora(t('init.creating')).start();
|
|
65
|
+
const globalConfigDir = resolve(homedir(), '.skillkit');
|
|
66
|
+
const projectConfigDir = resolve(process.cwd(), '.skillkit');
|
|
67
|
+
await fs.mkdir(globalConfigDir, { recursive: true });
|
|
68
|
+
await fs.mkdir(projectConfigDir, { recursive: true });
|
|
69
|
+
// Write global config
|
|
70
|
+
const globalConfigPath = resolve(globalConfigDir, 'config.json');
|
|
71
|
+
await fs.writeFile(globalConfigPath, JSON.stringify(config, null, 2));
|
|
72
|
+
// Write project config
|
|
73
|
+
const projectConfig = {
|
|
74
|
+
language: config.language,
|
|
75
|
+
provider: config.provider,
|
|
76
|
+
model: config.model,
|
|
77
|
+
};
|
|
78
|
+
const projectConfigPath = resolve(projectConfigDir, 'config.json');
|
|
79
|
+
await fs.writeFile(projectConfigPath, JSON.stringify(projectConfig, null, 2));
|
|
80
|
+
// Create skills directory
|
|
81
|
+
await fs.mkdir(resolve(projectConfigDir, 'skills'), { recursive: true });
|
|
82
|
+
// Create .gitignore
|
|
83
|
+
const gitignorePath = resolve(projectConfigDir, '.gitignore');
|
|
84
|
+
await fs.writeFile(gitignorePath, 'config.json\n.env\n');
|
|
85
|
+
spinner.succeed(chalk.green(t('init.success')));
|
|
86
|
+
console.log(chalk.bold.cyan('\nš Next Steps:\n'));
|
|
87
|
+
console.log(chalk.gray(` 1. ${t('init.nextSteps1')}`));
|
|
88
|
+
console.log(chalk.gray(` 2. ${t('init.nextSteps2')}`));
|
|
89
|
+
console.log(chalk.gray(` 3. ${t('init.nextSteps3')}`));
|
|
90
|
+
console.log(chalk.gray(` 4. ${t('init.nextSteps4')}`));
|
|
91
|
+
console.log(chalk.gray('\n For help: skillkit --help\n'));
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(chalk.red(t('error.initFailed')), error);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/install.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,QA+FvC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { t } from '../../i18n/index.js';
|
|
4
|
+
import { fetchSkill } from '../../hub/index.js';
|
|
5
|
+
import { installSkill as registryInstall } from '../../hub/registry.js';
|
|
6
|
+
import { scanSkill } from '../../runtime/executor.js';
|
|
7
|
+
export function install(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('install <skillRef>')
|
|
10
|
+
.description(chalk.cyan('Install a skill from ClawHub or URL'))
|
|
11
|
+
.option('--force', 'Skip security confirmation')
|
|
12
|
+
.option('--json', 'Output as JSON')
|
|
13
|
+
.action(async (skillRef, options) => {
|
|
14
|
+
try {
|
|
15
|
+
const spinner = ora(t('install.fetching')).start();
|
|
16
|
+
// Fetch skill
|
|
17
|
+
let skillContent;
|
|
18
|
+
let skillName;
|
|
19
|
+
if (skillRef.startsWith('http')) {
|
|
20
|
+
// From URL
|
|
21
|
+
const response = await fetch(skillRef);
|
|
22
|
+
if (!response.ok)
|
|
23
|
+
throw new Error(`HTTP ${response.status}`);
|
|
24
|
+
skillContent = await response.text();
|
|
25
|
+
skillName = new URL(skillRef).pathname.split('/').pop() || 'skill';
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// From ClawHub
|
|
29
|
+
const result = await fetchSkill(skillRef);
|
|
30
|
+
skillContent = result.content;
|
|
31
|
+
skillName = result.name;
|
|
32
|
+
}
|
|
33
|
+
spinner.succeed(chalk.green(t('install.fetched')));
|
|
34
|
+
// Security scan
|
|
35
|
+
let safeToInstall = true;
|
|
36
|
+
if (!options.force) {
|
|
37
|
+
const scanSpinner = ora(t('install.scanning')).start();
|
|
38
|
+
try {
|
|
39
|
+
const scanResult = await scanSkill(skillContent);
|
|
40
|
+
scanSpinner.succeed();
|
|
41
|
+
if (scanResult.score < 80) {
|
|
42
|
+
console.log(chalk.yellow(`\nā ļø Security Issues Found (Score: ${Math.round(scanResult.score)}%)\n`));
|
|
43
|
+
scanResult.threats.slice(0, 5).forEach((threat) => {
|
|
44
|
+
const severityColor = threat.severity === 'critical'
|
|
45
|
+
? chalk.red
|
|
46
|
+
: threat.severity === 'high'
|
|
47
|
+
? chalk.yellow
|
|
48
|
+
: chalk.blue;
|
|
49
|
+
console.log(` ${severityColor(`[${threat.severity.toUpperCase()}]`)} ${threat.description}`);
|
|
50
|
+
});
|
|
51
|
+
if (scanResult.threats.length > 5) {
|
|
52
|
+
console.log(chalk.gray(` ... and ${scanResult.threats.length - 5} more\n`));
|
|
53
|
+
}
|
|
54
|
+
// Prompt user
|
|
55
|
+
safeToInstall = await new Promise((resolve) => {
|
|
56
|
+
process.stdout.write(chalk.yellow('\nInstall anyway? (yes/no): '));
|
|
57
|
+
process.stdin.once('data', (data) => {
|
|
58
|
+
resolve(data.toString().trim().toLowerCase() === 'yes');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
scanSpinner.warn(chalk.yellow(t('install.scanWarning')));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!safeToInstall) {
|
|
68
|
+
console.log(chalk.gray(t('install.cancelled')));
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
// Install to local registry
|
|
72
|
+
const installSpinner = ora(t('install.installing')).start();
|
|
73
|
+
const installed = await registryInstall(skillName, skillContent, {
|
|
74
|
+
source: skillRef.startsWith('http') ? skillRef : 'clawhub',
|
|
75
|
+
});
|
|
76
|
+
installSpinner.succeed(chalk.green(`ā ${t('install.installed')}: ${chalk.cyan(installed.name)}`));
|
|
77
|
+
console.log(chalk.dim(`\nš Location: ${installed.path}`));
|
|
78
|
+
console.log(chalk.dim(`š
Installed: ${new Date(installed.installedAt).toLocaleString()}\n`));
|
|
79
|
+
console.log(chalk.dim(`š” Run with: skillkit run ${skillName}\n`));
|
|
80
|
+
if (options.json) {
|
|
81
|
+
console.log(JSON.stringify(installed, null, 2));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error(chalk.red(t('error.installFailed')), error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/cli/commands/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,IAAI,CAAC,OAAO,EAAE,OAAO,QAyFpC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { t } from '../../i18n/index.js';
|
|
4
|
+
import { listInstalled } from '../../hub/registry.js';
|
|
5
|
+
export function list(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('list')
|
|
8
|
+
.description(chalk.cyan('List installed skills'))
|
|
9
|
+
.option('--json', 'Output as JSON')
|
|
10
|
+
.option('-V, --verbose', 'Show detailed information')
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
try {
|
|
13
|
+
const spinner = ora(t('list.loading')).start();
|
|
14
|
+
const skills = await listInstalled();
|
|
15
|
+
spinner.stop();
|
|
16
|
+
if (skills.length === 0) {
|
|
17
|
+
console.log(chalk.yellow(`\n${t('list.noSkills')}\n`));
|
|
18
|
+
console.log(chalk.dim('Install your first skill with: skillkit install <skill-name>\n'));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
console.log(chalk.cyan.bold(`\nš Installed Skills (${skills.length})\n`));
|
|
22
|
+
if (options.verbose) {
|
|
23
|
+
// Detailed view
|
|
24
|
+
skills.forEach((skill) => {
|
|
25
|
+
console.log(chalk.bold(skill.name));
|
|
26
|
+
console.log(chalk.gray(` Path: ${skill.path}`));
|
|
27
|
+
console.log(chalk.gray(` Installed: ${new Date(skill.installedAt).toLocaleDateString()}`));
|
|
28
|
+
console.log(chalk.gray(` Source: ${skill.source}`));
|
|
29
|
+
if (skill.securityScore !== undefined) {
|
|
30
|
+
const scoreColor = skill.securityScore >= 80
|
|
31
|
+
? chalk.green
|
|
32
|
+
: skill.securityScore >= 50
|
|
33
|
+
? chalk.yellow
|
|
34
|
+
: chalk.red;
|
|
35
|
+
console.log(chalk.gray(` Security: ${scoreColor(Math.round(skill.securityScore) + '%')}`));
|
|
36
|
+
}
|
|
37
|
+
if (skill.usageCount) {
|
|
38
|
+
console.log(chalk.gray(` Uses: ${skill.usageCount}`));
|
|
39
|
+
}
|
|
40
|
+
console.log();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// Table view
|
|
45
|
+
console.log(chalk.gray('āāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā\n' +
|
|
46
|
+
'ā Name ā Security ā Last Used ā\n' +
|
|
47
|
+
'āāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¤'));
|
|
48
|
+
skills.forEach((skill) => {
|
|
49
|
+
const scoreColor = skill.securityScore !== undefined && skill.securityScore >= 80
|
|
50
|
+
? chalk.green
|
|
51
|
+
: skill.securityScore !== undefined && skill.securityScore >= 50
|
|
52
|
+
? chalk.yellow
|
|
53
|
+
: chalk.red;
|
|
54
|
+
const scoreBadge = skill.securityScore !== undefined
|
|
55
|
+
? scoreColor(Math.round(skill.securityScore) + '%')
|
|
56
|
+
: chalk.gray('-');
|
|
57
|
+
const lastUsed = skill.lastUsedAt
|
|
58
|
+
? new Date(skill.lastUsedAt).toLocaleDateString()
|
|
59
|
+
: '-';
|
|
60
|
+
const name = (skill.name || 'unknown').slice(0, 22).padEnd(22);
|
|
61
|
+
const score = String(scoreBadge).padEnd(8);
|
|
62
|
+
console.log(`ā ${name} ā ${score} ā ${lastUsed.padEnd(20)} ā`);
|
|
63
|
+
});
|
|
64
|
+
console.log(chalk.gray('āāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā\n'));
|
|
65
|
+
}
|
|
66
|
+
if (options.json) {
|
|
67
|
+
console.log(JSON.stringify(skills, null, 2));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(chalk.red(t('error.listFailed')), error);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,QAmKnC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { t } from '../../i18n/index.js';
|
|
4
|
+
import { scanSkill } from '../../runtime/executor.js';
|
|
5
|
+
import { loadSkill, executeSkill } from '../../runtime/executor.js';
|
|
6
|
+
export function run(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('run <skill>')
|
|
9
|
+
.description(chalk.cyan('Execute a skill with any AI model'))
|
|
10
|
+
.option('--model <model>', 'Model to use (e.g., deepseek-chat, ollama/qwen2.5, gpt-4o)')
|
|
11
|
+
.option('--provider <provider>', 'Force provider (openai, anthropic, deepseek, qwen, ollama, groq)')
|
|
12
|
+
.option('--input <prompt>', 'Input prompt for the skill')
|
|
13
|
+
.option('--no-scan', 'Skip security scan')
|
|
14
|
+
.option('--stream', 'Stream output token by token')
|
|
15
|
+
.option('--channel <type>', 'Run via messaging channel (whatsapp, telegram, discord, slack)')
|
|
16
|
+
.option('--json', 'Output as JSON')
|
|
17
|
+
.option('-V, --verbose', 'Verbose output')
|
|
18
|
+
.action(async (skill, cmdOptions, cmd) => {
|
|
19
|
+
try {
|
|
20
|
+
// Merge subcommand options with parent (global) options
|
|
21
|
+
const parentOpts = cmd.parent?.opts?.() || {};
|
|
22
|
+
const options = { ...parentOpts, ...cmdOptions };
|
|
23
|
+
// Step 1: Security scan (unless --no-scan)
|
|
24
|
+
if (options.noScan !== false) {
|
|
25
|
+
const scanSpinner = ora(t('run.scanning') || 'Scanning for threats...').start();
|
|
26
|
+
try {
|
|
27
|
+
// Load skill first to scan its content
|
|
28
|
+
const content = await loadSkill(skill);
|
|
29
|
+
const scanResult = await scanSkill(content);
|
|
30
|
+
if (scanResult.status === 'BLOCKED') {
|
|
31
|
+
scanSpinner.fail(chalk.red('BLOCKED ā Malicious skill detected'));
|
|
32
|
+
console.log(chalk.red(`\n SkillGuard Score: ${scanResult.score}/100`));
|
|
33
|
+
if (scanResult.hash) {
|
|
34
|
+
console.log(chalk.red(` Hash: ${scanResult.hash.slice(0, 16)}...`));
|
|
35
|
+
}
|
|
36
|
+
for (const threat of scanResult.threats) {
|
|
37
|
+
console.log(chalk.red(` [${threat.severity.toUpperCase()}] ${threat.description}`));
|
|
38
|
+
}
|
|
39
|
+
console.log(chalk.yellow('\nThis skill has been blocked for safety. Use --no-scan to override (NOT recommended).'));
|
|
40
|
+
console.log(chalk.gray('This hash has been added to your local blocklist to protect you in the future.'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
if (scanResult.status === 'REVIEW_REQUIRED') {
|
|
44
|
+
scanSpinner.warn(chalk.yellow(`Security: ${scanResult.score}/100 ā review recommended`));
|
|
45
|
+
for (const threat of scanResult.threats) {
|
|
46
|
+
const color = threat.severity === 'CRITICAL' ? chalk.red
|
|
47
|
+
: threat.severity === 'HIGH' ? chalk.yellow
|
|
48
|
+
: chalk.blue;
|
|
49
|
+
console.log(` ${color(`[${threat.severity}]`)} ${threat.description}`);
|
|
50
|
+
}
|
|
51
|
+
if (scanResult.sandboxRecommended) {
|
|
52
|
+
console.log(chalk.cyan('\n TIP: This skill has suspicious patterns. Consider running with --sandbox:'));
|
|
53
|
+
console.log(chalk.cyan(' skillkit run ' + skill + ' --sandbox'));
|
|
54
|
+
}
|
|
55
|
+
if (!options.json) {
|
|
56
|
+
const answer = await new Promise((resolve) => {
|
|
57
|
+
process.stdout.write(chalk.yellow('\nContinue anyway? (yes/no): '));
|
|
58
|
+
process.stdin.once('data', (data) => {
|
|
59
|
+
resolve(data.toString().trim().toLowerCase() === 'yes');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
if (!answer) {
|
|
63
|
+
console.log(chalk.gray('Cancelled'));
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
scanSpinner.succeed(chalk.green(`Security: ${scanResult.score}/100 ā safe`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
scanSpinner.warn(chalk.yellow('Security scan skipped (could not read skill)'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Step 2: Load skill
|
|
77
|
+
const loadSpinner = ora(t('run.loading') || 'Loading skill...').start();
|
|
78
|
+
const skillContent = await loadSkill(skill);
|
|
79
|
+
loadSpinner.succeed(chalk.green('Skill loaded'));
|
|
80
|
+
// Step 3: Show execution context
|
|
81
|
+
const modelDisplay = options.model || 'auto-detect';
|
|
82
|
+
const providerDisplay = options.provider || 'auto-detect';
|
|
83
|
+
console.log(chalk.dim(`\n Model: ${modelDisplay}`));
|
|
84
|
+
console.log(chalk.dim(` Provider: ${providerDisplay}`));
|
|
85
|
+
if (options.input) {
|
|
86
|
+
console.log(chalk.dim(` Input: "${options.input.slice(0, 80)}${options.input.length > 80 ? '...' : ''}"`));
|
|
87
|
+
}
|
|
88
|
+
// Step 4: Execute with REAL AI
|
|
89
|
+
const execSpinner = options.stream ? null : ora(t('run.executing') || 'Executing skill...').start();
|
|
90
|
+
if (options.stream) {
|
|
91
|
+
console.log(chalk.cyan.bold('\nš¤ Output:\n'));
|
|
92
|
+
}
|
|
93
|
+
const startTime = Date.now();
|
|
94
|
+
try {
|
|
95
|
+
const result = await executeSkill({
|
|
96
|
+
content: skillContent,
|
|
97
|
+
input: options.input || '',
|
|
98
|
+
model: options.model,
|
|
99
|
+
provider: options.provider,
|
|
100
|
+
channel: options.channel,
|
|
101
|
+
verbose: options.verbose,
|
|
102
|
+
stream: options.stream,
|
|
103
|
+
});
|
|
104
|
+
if (execSpinner) {
|
|
105
|
+
execSpinner.succeed(chalk.green(t('run.complete') || 'Execution complete'));
|
|
106
|
+
}
|
|
107
|
+
// Show output (non-streaming mode)
|
|
108
|
+
if (!options.stream) {
|
|
109
|
+
console.log(chalk.cyan.bold('\nš¤ Output:\n'));
|
|
110
|
+
console.log(result.output);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log(''); // newline after streamed output
|
|
114
|
+
}
|
|
115
|
+
// Show stats
|
|
116
|
+
const elapsed = (Date.now() - startTime) / 1000;
|
|
117
|
+
console.log(chalk.dim(`\nā±ļø Time: ${elapsed.toFixed(2)}s`));
|
|
118
|
+
console.log(chalk.dim(`š¤ Model: ${result.provider}/${result.model}`));
|
|
119
|
+
if (result.tokenUsage) {
|
|
120
|
+
console.log(chalk.dim(`š Tokens: ${result.tokenUsage.input} in / ${result.tokenUsage.output} out`));
|
|
121
|
+
}
|
|
122
|
+
// JSON output
|
|
123
|
+
if (options.json) {
|
|
124
|
+
console.log(JSON.stringify({
|
|
125
|
+
success: true,
|
|
126
|
+
output: result.output,
|
|
127
|
+
model: result.model,
|
|
128
|
+
provider: result.provider,
|
|
129
|
+
tokenUsage: result.tokenUsage,
|
|
130
|
+
duration: result.duration,
|
|
131
|
+
}, null, 2));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (execSpinner)
|
|
136
|
+
execSpinner.fail(chalk.red(t('run.failed') || 'Execution failed'));
|
|
137
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
138
|
+
// Helpful error messages
|
|
139
|
+
if (msg.includes('API key')) {
|
|
140
|
+
console.error(chalk.red(`\nā ${msg}`));
|
|
141
|
+
console.log(chalk.yellow('\nTip: Set your API key with:'));
|
|
142
|
+
console.log(chalk.cyan(' export DEEPSEEK_API_KEY=your-key # Free: deepseek.com'));
|
|
143
|
+
console.log(chalk.cyan(' export GROQ_API_KEY=your-key # Free: groq.com'));
|
|
144
|
+
console.log(chalk.cyan(' export ANTHROPIC_API_KEY=your-key # Paid: anthropic.com'));
|
|
145
|
+
console.log(chalk.yellow('\nOr use a free local model:'));
|
|
146
|
+
console.log(chalk.cyan(' skillkit run my-skill.md --model ollama/qwen2.5'));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.error(chalk.red(`\nā ${msg}`));
|
|
150
|
+
}
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,IAAI,CAAC,OAAO,EAAE,OAAO,QAgCpC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
import { t } from '../../i18n/index.js';
|
|
6
|
+
import { scanSkill } from '../../runtime/executor.js';
|
|
7
|
+
export function scan(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('scan <path>')
|
|
10
|
+
.description(chalk.cyan('Security audit of a skill file or directory'))
|
|
11
|
+
.option('--json', 'Output as JSON')
|
|
12
|
+
.option('--safe-only', 'Only show safe skills')
|
|
13
|
+
.option('-V, --verbose', 'Verbose output')
|
|
14
|
+
.action(async (path, options) => {
|
|
15
|
+
try {
|
|
16
|
+
const fullPath = resolve(process.cwd(), path);
|
|
17
|
+
const spinner = ora(t('scan.scanning')).start();
|
|
18
|
+
// Determine if path is file or directory
|
|
19
|
+
const stat = await fs.stat(fullPath);
|
|
20
|
+
if (stat.isDirectory()) {
|
|
21
|
+
// Scan directory
|
|
22
|
+
await scanDirectory(fullPath, options);
|
|
23
|
+
}
|
|
24
|
+
else if (stat.isFile()) {
|
|
25
|
+
// Scan single file
|
|
26
|
+
const result = await scanSkill(fullPath);
|
|
27
|
+
spinner.stop();
|
|
28
|
+
displayScanResult(result, fullPath, options);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
spinner.fail(chalk.red(t('error.invalidPath')));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error(chalk.red(t('error.scanFailed')), error);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async function scanDirectory(dir, options) {
|
|
42
|
+
const files = await fs.readdir(dir, { recursive: true });
|
|
43
|
+
const skillFiles = files.filter((f) => typeof f === 'string' && (f.endsWith('.md') || f.endsWith('.skill')));
|
|
44
|
+
if (skillFiles.length === 0) {
|
|
45
|
+
console.log(chalk.yellow(t('scan.noSkillsFound')));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(chalk.cyan.bold(`\nš Scanning ${skillFiles.length} skills...\n`));
|
|
49
|
+
const results = [];
|
|
50
|
+
for (const file of skillFiles) {
|
|
51
|
+
const spinner = ora(`Scanning ${file}`).start();
|
|
52
|
+
try {
|
|
53
|
+
const filePath = resolve(dir, file);
|
|
54
|
+
const result = await scanSkill(filePath);
|
|
55
|
+
if (!options.safeOnly || result.score >= 80) {
|
|
56
|
+
results.push({ file, result });
|
|
57
|
+
}
|
|
58
|
+
spinner.succeed();
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
spinner.warn(`Failed to scan ${file}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Display summary table
|
|
65
|
+
console.log(chalk.bold('\nš Scan Results:\n'));
|
|
66
|
+
console.log(chalk.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāā¬āāāāāāāāāāāāāāā\n' +
|
|
67
|
+
'ā Skill ā Score ā Threats ā\n' +
|
|
68
|
+
'āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāā¼āāāāāāāāāāāāāāā¤'));
|
|
69
|
+
results.forEach(({ file, result }) => {
|
|
70
|
+
const scoreColor = result.score >= 80 ? chalk.green : result.score >= 50 ? chalk.yellow : chalk.red;
|
|
71
|
+
const threatCount = result.threats.length;
|
|
72
|
+
const skillName = file.split('/').pop() || file;
|
|
73
|
+
console.log(`ā ${skillName.padEnd(27)} ā ${scoreColor(String(Math.round(result.score)).padEnd(6))} ā ${String(threatCount).padEnd(12)} ā`);
|
|
74
|
+
});
|
|
75
|
+
console.log(chalk.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāā“āāāāāāāāāāāāāāā\n'));
|
|
76
|
+
if (options.json) {
|
|
77
|
+
console.log(JSON.stringify(results.map(({ file, result }) => ({
|
|
78
|
+
file,
|
|
79
|
+
score: result.score,
|
|
80
|
+
threats: result.threats,
|
|
81
|
+
})), null, 2));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function displayScanResult(result, filePath, options) {
|
|
85
|
+
const fileName = filePath.split('/').pop() || filePath;
|
|
86
|
+
// Score badge
|
|
87
|
+
const scoreColor = result.score >= 80 ? chalk.bgGreen : result.score >= 50 ? chalk.bgYellow : chalk.bgRed;
|
|
88
|
+
const scoreLabel = result.score >= 80
|
|
89
|
+
? 'SAFE'
|
|
90
|
+
: result.score >= 50
|
|
91
|
+
? 'CAUTION'
|
|
92
|
+
: 'UNSAFE';
|
|
93
|
+
console.log(chalk.bold.cyan(`\nš Security Scan: ${fileName}\n`));
|
|
94
|
+
console.log(` Overall Score: ${scoreColor.black(` ${Math.round(result.score)} `)} (${scoreLabel})\n`);
|
|
95
|
+
// Threats
|
|
96
|
+
if (result.threats.length > 0) {
|
|
97
|
+
console.log(chalk.bold('ā ļø Detected Threats:\n'));
|
|
98
|
+
result.threats.forEach((threat, idx) => {
|
|
99
|
+
const severityColor = threat.severity === 'critical'
|
|
100
|
+
? chalk.bgRed.white
|
|
101
|
+
: threat.severity === 'high'
|
|
102
|
+
? chalk.bgYellow.black
|
|
103
|
+
: chalk.bgBlue.white;
|
|
104
|
+
console.log(` ${idx + 1}. ${severityColor(` ${threat.severity.toUpperCase()} `)}`);
|
|
105
|
+
console.log(` Description: ${threat.description}`);
|
|
106
|
+
console.log(` Line: ${threat.line}\n`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.log(chalk.green('ā No threats detected\n'));
|
|
111
|
+
}
|
|
112
|
+
// Recommendations
|
|
113
|
+
console.log(chalk.bold('š” Recommendations:\n'));
|
|
114
|
+
if (result.threats.length === 0) {
|
|
115
|
+
console.log(chalk.green(' ā This skill is safe to use'));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const critical = result.threats.filter((t) => t.severity === 'critical').length;
|
|
119
|
+
const high = result.threats.filter((t) => t.severity === 'high').length;
|
|
120
|
+
if (critical > 0) {
|
|
121
|
+
console.log(chalk.red(` ā Fix ${critical} critical issue(s) before using`));
|
|
122
|
+
}
|
|
123
|
+
if (high > 0) {
|
|
124
|
+
console.log(chalk.yellow(` ā Review ${high} high-severity issue(s)`));
|
|
125
|
+
}
|
|
126
|
+
console.log(' ⢠Run with --no-scan to bypass (not recommended)');
|
|
127
|
+
console.log(' ⢠Contact the skill author for fixes');
|
|
128
|
+
}
|
|
129
|
+
if (options.json) {
|
|
130
|
+
console.log(JSON.stringify(result, null, 2));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=scan.js.map
|