@tankpkg/cli 0.4.2
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/dist/bin/tank.d.ts +2 -0
- package/dist/bin/tank.js +279 -0
- package/dist/bin/tank.js.map +1 -0
- package/dist/commands/audit.d.ts +5 -0
- package/dist/commands/audit.js +185 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.js +164 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/info.d.ts +5 -0
- package/dist/commands/info.js +102 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +92 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +39 -0
- package/dist/commands/install.js +550 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/link.d.ts +5 -0
- package/dist/commands/link.js +79 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.js +87 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +9 -0
- package/dist/commands/logout.js +20 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/permissions.d.ts +4 -0
- package/dist/commands/permissions.js +199 -0
- package/dist/commands/permissions.js.map +1 -0
- package/dist/commands/publish.d.ts +25 -0
- package/dist/commands/publish.js +166 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +7 -0
- package/dist/commands/remove.js +163 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/search.d.ts +5 -0
- package/dist/commands/search.js +67 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/unlink.d.ts +5 -0
- package/dist/commands/unlink.js +42 -0
- package/dist/commands/unlink.js.map +1 -0
- package/dist/commands/update.d.ts +8 -0
- package/dist/commands/update.js +337 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/upgrade.d.ts +6 -0
- package/dist/commands/upgrade.js +100 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/verify.d.ts +22 -0
- package/dist/commands/verify.js +63 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/whoami.d.ts +4 -0
- package/dist/commands/whoami.js +57 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agents.d.ts +19 -0
- package/dist/lib/agents.js +84 -0
- package/dist/lib/agents.js.map +1 -0
- package/dist/lib/api-client.d.ts +14 -0
- package/dist/lib/api-client.js +63 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/config.d.ts +29 -0
- package/dist/lib/config.js +66 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/debug-logger.d.ts +9 -0
- package/dist/lib/debug-logger.js +77 -0
- package/dist/lib/debug-logger.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +11 -0
- package/dist/lib/frontmatter.js +89 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/linker.d.ts +45 -0
- package/dist/lib/linker.js +137 -0
- package/dist/lib/linker.js.map +1 -0
- package/dist/lib/links.d.ts +20 -0
- package/dist/lib/links.js +105 -0
- package/dist/lib/links.js.map +1 -0
- package/dist/lib/lockfile.d.ts +24 -0
- package/dist/lib/lockfile.js +135 -0
- package/dist/lib/lockfile.js.map +1 -0
- package/dist/lib/logger.d.ts +6 -0
- package/dist/lib/logger.js +8 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/packer.d.ts +21 -0
- package/dist/lib/packer.js +210 -0
- package/dist/lib/packer.js.map +1 -0
- package/dist/lib/upgrade-check.d.ts +1 -0
- package/dist/lib/upgrade-check.js +52 -0
- package/dist/lib/upgrade-check.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { detectInstalledAgents, getGlobalSkillsDir, getSupportedAgents } from '../lib/agents.js';
|
|
6
|
+
import { getSkillLinkStatus } from '../lib/linker.js';
|
|
7
|
+
import { readGlobalLinks } from '../lib/links.js';
|
|
8
|
+
const parseLockKey = (key) => {
|
|
9
|
+
const lastAt = key.lastIndexOf('@');
|
|
10
|
+
if (lastAt > 0) {
|
|
11
|
+
return key.slice(0, lastAt);
|
|
12
|
+
}
|
|
13
|
+
return key;
|
|
14
|
+
};
|
|
15
|
+
const getExtractDir = (baseDir, skillName) => {
|
|
16
|
+
if (skillName.startsWith('@')) {
|
|
17
|
+
const [scope, name] = skillName.split('/');
|
|
18
|
+
return path.join(baseDir, scope, name);
|
|
19
|
+
}
|
|
20
|
+
return path.join(baseDir, skillName);
|
|
21
|
+
};
|
|
22
|
+
const formatAgents = (agents, label) => {
|
|
23
|
+
if (agents.length === 0) {
|
|
24
|
+
return `${label}`;
|
|
25
|
+
}
|
|
26
|
+
return `${label} (${agents.map(agent => agent.agentName).join(', ')})`;
|
|
27
|
+
};
|
|
28
|
+
const summarizeStatus = (skillName, statuses, extractExists, scope) => {
|
|
29
|
+
if (statuses.length === 0) {
|
|
30
|
+
return {
|
|
31
|
+
statusText: chalk.yellow('⚠️ no agents detected'),
|
|
32
|
+
issues: [],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const brokenAgents = statuses.filter(status => status.linked && !status.targetValid);
|
|
36
|
+
const linkedAgents = statuses.filter(status => status.linked && status.targetValid);
|
|
37
|
+
if (brokenAgents.length > 0) {
|
|
38
|
+
const base = chalk.yellow('⚠️ broken link');
|
|
39
|
+
const text = formatAgents(brokenAgents, base);
|
|
40
|
+
const command = scope === 'dev'
|
|
41
|
+
? `Run \`tank link\` in the skill directory to fix ${skillName}`
|
|
42
|
+
: `Run \`tank install ${skillName}\` to fix broken link`;
|
|
43
|
+
return {
|
|
44
|
+
statusText: text,
|
|
45
|
+
issues: [command],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (linkedAgents.length > 0) {
|
|
49
|
+
if (!extractExists && scope !== 'dev') {
|
|
50
|
+
return {
|
|
51
|
+
statusText: chalk.yellow('⚠️ missing extract'),
|
|
52
|
+
issues: [`Run \`tank install ${skillName}\` to install missing extract`],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const text = formatAgents(linkedAgents, chalk.green('✅ linked'));
|
|
56
|
+
return { statusText: text, issues: [] };
|
|
57
|
+
}
|
|
58
|
+
if (!extractExists && scope !== 'dev') {
|
|
59
|
+
return {
|
|
60
|
+
statusText: chalk.yellow('⚠️ missing extract'),
|
|
61
|
+
issues: [`Run \`tank install ${skillName}\` to install missing extract`],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
statusText: chalk.red('❌ not linked'),
|
|
66
|
+
issues: [],
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
const printSectionHeader = (title) => {
|
|
70
|
+
console.log(`\n${chalk.bold(title)}:`);
|
|
71
|
+
};
|
|
72
|
+
export async function doctorCommand(options) {
|
|
73
|
+
try {
|
|
74
|
+
const directory = options?.directory ?? process.cwd();
|
|
75
|
+
const homedir = options?.homedir ?? os.homedir();
|
|
76
|
+
const supportedAgents = getSupportedAgents(homedir);
|
|
77
|
+
const installedAgents = detectInstalledAgents(homedir);
|
|
78
|
+
const installedIds = new Set(installedAgents.map(agent => agent.id));
|
|
79
|
+
const skillsJsonPath = path.join(directory, 'skills.json');
|
|
80
|
+
const localSkills = fs.existsSync(skillsJsonPath)
|
|
81
|
+
? Object.keys(JSON.parse(fs.readFileSync(skillsJsonPath, 'utf-8')).skills ?? {})
|
|
82
|
+
: [];
|
|
83
|
+
localSkills.sort();
|
|
84
|
+
const globalLockPath = path.join(homedir, '.tank', 'skills.lock');
|
|
85
|
+
const globalSkills = fs.existsSync(globalLockPath)
|
|
86
|
+
? Object.keys(JSON.parse(fs.readFileSync(globalLockPath, 'utf-8')).skills ?? {}).map(parseLockKey)
|
|
87
|
+
: [];
|
|
88
|
+
const uniqueGlobal = Array.from(new Set(globalSkills)).sort();
|
|
89
|
+
const globalLinks = readGlobalLinks(homedir);
|
|
90
|
+
const devLinks = Object.entries(globalLinks.links)
|
|
91
|
+
.filter(([, entry]) => entry.source === 'dev')
|
|
92
|
+
.map(([skillName]) => skillName)
|
|
93
|
+
.sort();
|
|
94
|
+
const suggestions = new Set();
|
|
95
|
+
console.log(chalk.bold('Tank Doctor Report'));
|
|
96
|
+
console.log(chalk.bold('=================='));
|
|
97
|
+
printSectionHeader('Detected Agents');
|
|
98
|
+
for (const agent of supportedAgents) {
|
|
99
|
+
const installed = installedIds.has(agent.id);
|
|
100
|
+
const icon = installed ? chalk.green('✅') : chalk.red('❌');
|
|
101
|
+
const details = installed ? agent.skillsDir : chalk.gray('(not found)');
|
|
102
|
+
console.log(` ${icon} ${agent.name} ${details}`);
|
|
103
|
+
}
|
|
104
|
+
if (installedAgents.length === 0) {
|
|
105
|
+
suggestions.add('No agents detected. Install an AI agent to enable skill linking.');
|
|
106
|
+
}
|
|
107
|
+
const localLinksDir = path.join(directory, '.tank');
|
|
108
|
+
printSectionHeader(`Local Skills (${localSkills.length})` + `: [project: ${directory}]`);
|
|
109
|
+
if (localSkills.length === 0) {
|
|
110
|
+
console.log(' none');
|
|
111
|
+
}
|
|
112
|
+
for (const skillName of localSkills) {
|
|
113
|
+
const extractDir = getExtractDir(path.join(directory, '.tank', 'skills'), skillName);
|
|
114
|
+
const extractExists = fs.existsSync(extractDir);
|
|
115
|
+
const statuses = getSkillLinkStatus({ skillName, linksDir: localLinksDir, homedir });
|
|
116
|
+
const summary = summarizeStatus(skillName, statuses, extractExists, 'local');
|
|
117
|
+
summary.issues.forEach(issue => suggestions.add(issue));
|
|
118
|
+
console.log(` ${skillName} ${summary.statusText}`);
|
|
119
|
+
}
|
|
120
|
+
const globalLinksDir = path.join(homedir, '.tank');
|
|
121
|
+
const globalSkillsDir = getGlobalSkillsDir(homedir);
|
|
122
|
+
printSectionHeader(`Global Skills (${uniqueGlobal.length})` + `: [${globalSkillsDir}]`);
|
|
123
|
+
if (uniqueGlobal.length === 0) {
|
|
124
|
+
console.log(' none');
|
|
125
|
+
}
|
|
126
|
+
for (const skillName of uniqueGlobal) {
|
|
127
|
+
const extractDir = getExtractDir(globalSkillsDir, skillName);
|
|
128
|
+
const extractExists = fs.existsSync(extractDir);
|
|
129
|
+
const statuses = getSkillLinkStatus({ skillName, linksDir: globalLinksDir, homedir });
|
|
130
|
+
const summary = summarizeStatus(skillName, statuses, extractExists, 'global');
|
|
131
|
+
summary.issues.forEach(issue => suggestions.add(issue));
|
|
132
|
+
console.log(` ${skillName} ${summary.statusText}`);
|
|
133
|
+
}
|
|
134
|
+
printSectionHeader(`Dev Links (${devLinks.length})` + ': [tank link]');
|
|
135
|
+
if (devLinks.length === 0) {
|
|
136
|
+
console.log(' none');
|
|
137
|
+
}
|
|
138
|
+
for (const skillName of devLinks) {
|
|
139
|
+
const statuses = getSkillLinkStatus({ skillName, linksDir: globalLinksDir, homedir });
|
|
140
|
+
const summary = summarizeStatus(skillName, statuses, true, 'dev');
|
|
141
|
+
summary.issues.forEach(issue => suggestions.add(issue));
|
|
142
|
+
console.log(` ${skillName} ${summary.statusText}`);
|
|
143
|
+
}
|
|
144
|
+
if (localSkills.length === 0 && uniqueGlobal.length === 0 && devLinks.length === 0) {
|
|
145
|
+
suggestions.add('Run `tank install @tank/typescript` to add your first skill');
|
|
146
|
+
}
|
|
147
|
+
printSectionHeader('Suggestions');
|
|
148
|
+
if (suggestions.size === 0) {
|
|
149
|
+
console.log(' none');
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
for (const suggestion of suggestions) {
|
|
153
|
+
console.log(` • ${suggestion}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
159
|
+
console.log(chalk.red(`Doctor report failed: ${message}`));
|
|
160
|
+
console.log('Suggestions:');
|
|
161
|
+
console.log(' • Run `tank install @tank/typescript` to add your first skill');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getConfig } from '../lib/config.js';
|
|
3
|
+
import { USER_AGENT } from '../version.js';
|
|
4
|
+
function formatDate(iso) {
|
|
5
|
+
try {
|
|
6
|
+
return iso.split('T')[0];
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return iso;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function labelValue(label, value) {
|
|
13
|
+
return `${chalk.dim(label.padEnd(14))}${value}`;
|
|
14
|
+
}
|
|
15
|
+
export async function infoCommand(options) {
|
|
16
|
+
const { name, configDir } = options;
|
|
17
|
+
const config = getConfig(configDir);
|
|
18
|
+
const encodedName = encodeURIComponent(name);
|
|
19
|
+
const metaUrl = `${config.registry}/api/v1/skills/${encodedName}`;
|
|
20
|
+
const headers = { 'User-Agent': USER_AGENT };
|
|
21
|
+
if (config.token) {
|
|
22
|
+
headers.Authorization = `Bearer ${config.token}`;
|
|
23
|
+
}
|
|
24
|
+
// 1. Fetch skill metadata
|
|
25
|
+
let metaRes;
|
|
26
|
+
try {
|
|
27
|
+
metaRes = await fetch(metaUrl, {
|
|
28
|
+
headers,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
throw new Error(`Network error fetching skill info: ${err instanceof Error ? err.message : String(err)}`);
|
|
33
|
+
}
|
|
34
|
+
if (metaRes.status === 404) {
|
|
35
|
+
console.log(`Skill not found: ${name}`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!metaRes.ok) {
|
|
39
|
+
const body = await metaRes.json().catch(() => ({}));
|
|
40
|
+
throw new Error(body.error ?? `Failed to fetch skill info: ${metaRes.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
const meta = await metaRes.json();
|
|
43
|
+
// 2. Fetch version details for permissions
|
|
44
|
+
const versionUrl = `${config.registry}/api/v1/skills/${encodedName}/${meta.latestVersion}`;
|
|
45
|
+
let versionRes;
|
|
46
|
+
try {
|
|
47
|
+
versionRes = await fetch(versionUrl, {
|
|
48
|
+
headers,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
throw new Error(`Network error fetching version details: ${err instanceof Error ? err.message : String(err)}`);
|
|
53
|
+
}
|
|
54
|
+
let versionData;
|
|
55
|
+
if (versionRes.ok) {
|
|
56
|
+
versionData = await versionRes.json();
|
|
57
|
+
}
|
|
58
|
+
// 3. Display info
|
|
59
|
+
console.log('');
|
|
60
|
+
console.log(chalk.bold(meta.name));
|
|
61
|
+
console.log('');
|
|
62
|
+
if (meta.description) {
|
|
63
|
+
console.log(labelValue('Description:', meta.description));
|
|
64
|
+
}
|
|
65
|
+
console.log(labelValue('Version:', meta.latestVersion));
|
|
66
|
+
if (meta.visibility) {
|
|
67
|
+
console.log(labelValue('Visibility:', meta.visibility));
|
|
68
|
+
}
|
|
69
|
+
console.log(labelValue('Publisher:', meta.publisher?.displayName ?? 'unknown'));
|
|
70
|
+
if (versionData?.auditScore != null) {
|
|
71
|
+
console.log(labelValue('Audit Score:', `${versionData.auditScore}/10`));
|
|
72
|
+
}
|
|
73
|
+
console.log(labelValue('Created:', formatDate(meta.createdAt)));
|
|
74
|
+
// 4. Display permissions
|
|
75
|
+
const perms = versionData?.permissions;
|
|
76
|
+
if (perms) {
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log(chalk.bold('Permissions:'));
|
|
79
|
+
const networkDomains = perms.network?.outbound;
|
|
80
|
+
if (networkDomains && networkDomains.length > 0) {
|
|
81
|
+
console.log(` ${chalk.dim('Network:'.padEnd(14))}${networkDomains.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
const fsRead = perms.filesystem?.read;
|
|
84
|
+
const fsWrite = perms.filesystem?.write;
|
|
85
|
+
if (fsRead || fsWrite) {
|
|
86
|
+
const parts = [];
|
|
87
|
+
if (fsRead && fsRead.length > 0) {
|
|
88
|
+
parts.push(`${fsRead.join(', ')} (read)`);
|
|
89
|
+
}
|
|
90
|
+
if (fsWrite && fsWrite.length > 0) {
|
|
91
|
+
parts.push(`${fsWrite.join(', ')} (write)`);
|
|
92
|
+
}
|
|
93
|
+
console.log(` ${chalk.dim('Filesystem:'.padEnd(14))}${parts.join(', ')}`);
|
|
94
|
+
}
|
|
95
|
+
const subprocess = perms.subprocess;
|
|
96
|
+
console.log(` ${chalk.dim('Subprocess:'.padEnd(14))}${subprocess ? 'yes' : 'no'}`);
|
|
97
|
+
}
|
|
98
|
+
// 5. Install hint
|
|
99
|
+
console.log('');
|
|
100
|
+
console.log(`Install: ${chalk.cyan(`tank install ${meta.name}`)}`);
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initCommand(): Promise<void>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { input, confirm } from '@inquirer/prompts';
|
|
4
|
+
import { skillsJsonSchema } from '@tank/shared';
|
|
5
|
+
import { getConfig } from '../lib/config.js';
|
|
6
|
+
import { logger } from '../lib/logger.js';
|
|
7
|
+
const NAME_PATTERN = /^(@[a-z0-9-]+\/)?[a-z0-9][a-z0-9-]*$/;
|
|
8
|
+
const SEMVER_PATTERN = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
|
|
9
|
+
const MAX_NAME_LENGTH = 214;
|
|
10
|
+
function validateName(value) {
|
|
11
|
+
if (!value)
|
|
12
|
+
return 'Name must not be empty';
|
|
13
|
+
if (value.length > MAX_NAME_LENGTH)
|
|
14
|
+
return `Name must be ${MAX_NAME_LENGTH} characters or fewer`;
|
|
15
|
+
if (!NAME_PATTERN.test(value))
|
|
16
|
+
return 'Name must be lowercase, alphanumeric + hyphens, optionally scoped (@org/name)';
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function validateVersion(value) {
|
|
20
|
+
if (!SEMVER_PATTERN.test(value))
|
|
21
|
+
return 'Version must be valid semver (e.g. 1.0.0)';
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
export async function initCommand() {
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
const filePath = path.join(cwd, 'skills.json');
|
|
27
|
+
// Check if skills.json already exists
|
|
28
|
+
if (fs.existsSync(filePath)) {
|
|
29
|
+
logger.warn('skills.json already exists in this directory.');
|
|
30
|
+
const overwrite = await confirm({
|
|
31
|
+
message: 'Overwrite existing skills.json?',
|
|
32
|
+
default: false,
|
|
33
|
+
});
|
|
34
|
+
if (!overwrite) {
|
|
35
|
+
logger.info('Aborted.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Get default author from config
|
|
40
|
+
const config = getConfig();
|
|
41
|
+
const defaultAuthor = config.user?.name ?? '';
|
|
42
|
+
// Prompt for values
|
|
43
|
+
const dirName = path.basename(cwd);
|
|
44
|
+
const name = await input({
|
|
45
|
+
message: 'Skill name:',
|
|
46
|
+
default: dirName,
|
|
47
|
+
validate: validateName,
|
|
48
|
+
});
|
|
49
|
+
const version = await input({
|
|
50
|
+
message: 'Version:',
|
|
51
|
+
default: '0.1.0',
|
|
52
|
+
validate: validateVersion,
|
|
53
|
+
});
|
|
54
|
+
const description = await input({
|
|
55
|
+
message: 'Description:',
|
|
56
|
+
default: '',
|
|
57
|
+
});
|
|
58
|
+
const privateChoice = await confirm({
|
|
59
|
+
message: 'Make this skill private?',
|
|
60
|
+
default: name.startsWith('@'),
|
|
61
|
+
});
|
|
62
|
+
const author = await input({
|
|
63
|
+
message: 'Author:',
|
|
64
|
+
default: defaultAuthor,
|
|
65
|
+
});
|
|
66
|
+
void author;
|
|
67
|
+
const manifest = {
|
|
68
|
+
name,
|
|
69
|
+
version,
|
|
70
|
+
...(description ? { description } : {}),
|
|
71
|
+
visibility: privateChoice ? 'private' : 'public',
|
|
72
|
+
skills: {},
|
|
73
|
+
permissions: {
|
|
74
|
+
network: { outbound: [] },
|
|
75
|
+
filesystem: { read: [], write: [] },
|
|
76
|
+
subprocess: false,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
// Validate against schema before writing
|
|
80
|
+
const result = skillsJsonSchema.safeParse(manifest);
|
|
81
|
+
if (!result.success) {
|
|
82
|
+
logger.error('Generated skills.json is invalid:');
|
|
83
|
+
for (const issue of result.error.issues) {
|
|
84
|
+
logger.error(` ${issue.path.join('.')}: ${issue.message}`);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Write file
|
|
89
|
+
fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2) + '\n');
|
|
90
|
+
logger.success('Created skills.json');
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface InstallOptions {
|
|
2
|
+
name: string;
|
|
3
|
+
versionRange?: string;
|
|
4
|
+
directory?: string;
|
|
5
|
+
configDir?: string;
|
|
6
|
+
global?: boolean;
|
|
7
|
+
homedir?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface LockfileInstallOptions {
|
|
10
|
+
directory?: string;
|
|
11
|
+
configDir?: string;
|
|
12
|
+
global?: boolean;
|
|
13
|
+
homedir?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface InstallAllOptions {
|
|
16
|
+
directory?: string;
|
|
17
|
+
configDir?: string;
|
|
18
|
+
global?: boolean;
|
|
19
|
+
homedir?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Install a skill from the Tank registry.
|
|
23
|
+
*
|
|
24
|
+
* Flow:
|
|
25
|
+
* 1. Read skills.json from directory (must exist)
|
|
26
|
+
* 2. Fetch available versions
|
|
27
|
+
* 3. Resolve best version using semver
|
|
28
|
+
* 4. Check if already installed (skip if same version in lockfile)
|
|
29
|
+
* 5. Fetch version metadata + download URL
|
|
30
|
+
* 6. Check permission budget
|
|
31
|
+
* 7. Download tarball
|
|
32
|
+
* 8. Verify integrity (sha512)
|
|
33
|
+
* 9. Extract tarball safely
|
|
34
|
+
* 10. Update skills.json
|
|
35
|
+
* 11. Update skills.lock
|
|
36
|
+
*/
|
|
37
|
+
export declare function installCommand(options: InstallOptions): Promise<void>;
|
|
38
|
+
export declare function installFromLockfile(options: LockfileInstallOptions): Promise<void>;
|
|
39
|
+
export declare function installAll(options: InstallAllOptions): Promise<void>;
|