@nimblebrain/mpak 0.1.0 → 0.2.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.
Files changed (151) hide show
  1. package/LICENSE +10 -198
  2. package/README.md +50 -383
  3. package/dist/index.d.ts +0 -2
  4. package/dist/index.js +2113 -4
  5. package/dist/index.js.map +1 -1
  6. package/package.json +32 -29
  7. package/.claude/settings.local.json +0 -19
  8. package/.env.example +0 -13
  9. package/.github/workflows/ci.yml +0 -27
  10. package/CLAUDE.md +0 -283
  11. package/dist/commands/config.d.ts +0 -31
  12. package/dist/commands/config.d.ts.map +0 -1
  13. package/dist/commands/config.js +0 -129
  14. package/dist/commands/config.js.map +0 -1
  15. package/dist/commands/packages/pull.d.ts +0 -11
  16. package/dist/commands/packages/pull.d.ts.map +0 -1
  17. package/dist/commands/packages/pull.js +0 -72
  18. package/dist/commands/packages/pull.js.map +0 -1
  19. package/dist/commands/packages/run.d.ts +0 -47
  20. package/dist/commands/packages/run.d.ts.map +0 -1
  21. package/dist/commands/packages/run.js +0 -419
  22. package/dist/commands/packages/run.js.map +0 -1
  23. package/dist/commands/packages/search.d.ts +0 -12
  24. package/dist/commands/packages/search.d.ts.map +0 -1
  25. package/dist/commands/packages/search.js +0 -63
  26. package/dist/commands/packages/search.js.map +0 -1
  27. package/dist/commands/packages/show.d.ts +0 -8
  28. package/dist/commands/packages/show.d.ts.map +0 -1
  29. package/dist/commands/packages/show.js +0 -109
  30. package/dist/commands/packages/show.js.map +0 -1
  31. package/dist/commands/search.d.ts +0 -12
  32. package/dist/commands/search.d.ts.map +0 -1
  33. package/dist/commands/search.js +0 -144
  34. package/dist/commands/search.js.map +0 -1
  35. package/dist/commands/skills/index.d.ts +0 -8
  36. package/dist/commands/skills/index.d.ts.map +0 -1
  37. package/dist/commands/skills/index.js +0 -8
  38. package/dist/commands/skills/index.js.map +0 -1
  39. package/dist/commands/skills/install.d.ts +0 -9
  40. package/dist/commands/skills/install.d.ts.map +0 -1
  41. package/dist/commands/skills/install.js +0 -110
  42. package/dist/commands/skills/install.js.map +0 -1
  43. package/dist/commands/skills/list.d.ts +0 -8
  44. package/dist/commands/skills/list.d.ts.map +0 -1
  45. package/dist/commands/skills/list.js +0 -89
  46. package/dist/commands/skills/list.js.map +0 -1
  47. package/dist/commands/skills/pack.d.ts +0 -22
  48. package/dist/commands/skills/pack.d.ts.map +0 -1
  49. package/dist/commands/skills/pack.js +0 -116
  50. package/dist/commands/skills/pack.js.map +0 -1
  51. package/dist/commands/skills/pull.d.ts +0 -9
  52. package/dist/commands/skills/pull.d.ts.map +0 -1
  53. package/dist/commands/skills/pull.js +0 -68
  54. package/dist/commands/skills/pull.js.map +0 -1
  55. package/dist/commands/skills/search.d.ts +0 -14
  56. package/dist/commands/skills/search.d.ts.map +0 -1
  57. package/dist/commands/skills/search.js +0 -53
  58. package/dist/commands/skills/search.js.map +0 -1
  59. package/dist/commands/skills/show.d.ts +0 -8
  60. package/dist/commands/skills/show.d.ts.map +0 -1
  61. package/dist/commands/skills/show.js +0 -64
  62. package/dist/commands/skills/show.js.map +0 -1
  63. package/dist/commands/skills/validate.d.ts +0 -25
  64. package/dist/commands/skills/validate.d.ts.map +0 -1
  65. package/dist/commands/skills/validate.js +0 -191
  66. package/dist/commands/skills/validate.js.map +0 -1
  67. package/dist/index.d.ts.map +0 -1
  68. package/dist/lib/api/registry-client.d.ts +0 -63
  69. package/dist/lib/api/registry-client.d.ts.map +0 -1
  70. package/dist/lib/api/registry-client.js +0 -167
  71. package/dist/lib/api/registry-client.js.map +0 -1
  72. package/dist/lib/api/skills-client.d.ts +0 -30
  73. package/dist/lib/api/skills-client.d.ts.map +0 -1
  74. package/dist/lib/api/skills-client.js +0 -110
  75. package/dist/lib/api/skills-client.js.map +0 -1
  76. package/dist/program.d.ts +0 -12
  77. package/dist/program.d.ts.map +0 -1
  78. package/dist/program.js +0 -186
  79. package/dist/program.js.map +0 -1
  80. package/dist/schemas/generated/api-responses.d.ts +0 -541
  81. package/dist/schemas/generated/api-responses.d.ts.map +0 -1
  82. package/dist/schemas/generated/api-responses.js +0 -313
  83. package/dist/schemas/generated/api-responses.js.map +0 -1
  84. package/dist/schemas/generated/auth.d.ts +0 -18
  85. package/dist/schemas/generated/auth.d.ts.map +0 -1
  86. package/dist/schemas/generated/auth.js +0 -18
  87. package/dist/schemas/generated/auth.js.map +0 -1
  88. package/dist/schemas/generated/index.d.ts +0 -5
  89. package/dist/schemas/generated/index.d.ts.map +0 -1
  90. package/dist/schemas/generated/index.js +0 -6
  91. package/dist/schemas/generated/index.js.map +0 -1
  92. package/dist/schemas/generated/package.d.ts +0 -43
  93. package/dist/schemas/generated/package.d.ts.map +0 -1
  94. package/dist/schemas/generated/package.js +0 -20
  95. package/dist/schemas/generated/package.js.map +0 -1
  96. package/dist/schemas/generated/skill.d.ts +0 -381
  97. package/dist/schemas/generated/skill.d.ts.map +0 -1
  98. package/dist/schemas/generated/skill.js +0 -216
  99. package/dist/schemas/generated/skill.js.map +0 -1
  100. package/dist/utils/config-manager.d.ts +0 -66
  101. package/dist/utils/config-manager.d.ts.map +0 -1
  102. package/dist/utils/config-manager.js +0 -193
  103. package/dist/utils/config-manager.js.map +0 -1
  104. package/dist/utils/errors.d.ts +0 -12
  105. package/dist/utils/errors.d.ts.map +0 -1
  106. package/dist/utils/errors.js +0 -27
  107. package/dist/utils/errors.js.map +0 -1
  108. package/dist/utils/version.d.ts +0 -5
  109. package/dist/utils/version.d.ts.map +0 -1
  110. package/dist/utils/version.js +0 -19
  111. package/dist/utils/version.js.map +0 -1
  112. package/eslint.config.js +0 -63
  113. package/src/commands/config.ts +0 -162
  114. package/src/commands/packages/pull.ts +0 -96
  115. package/src/commands/packages/run.test.ts +0 -261
  116. package/src/commands/packages/run.ts +0 -536
  117. package/src/commands/packages/search.ts +0 -83
  118. package/src/commands/packages/show.ts +0 -128
  119. package/src/commands/search.ts +0 -191
  120. package/src/commands/skills/index.ts +0 -7
  121. package/src/commands/skills/install.ts +0 -129
  122. package/src/commands/skills/list.ts +0 -116
  123. package/src/commands/skills/pack.test.ts +0 -260
  124. package/src/commands/skills/pack.ts +0 -145
  125. package/src/commands/skills/pull.ts +0 -88
  126. package/src/commands/skills/search.ts +0 -73
  127. package/src/commands/skills/show.ts +0 -72
  128. package/src/commands/skills/validate.test.ts +0 -466
  129. package/src/commands/skills/validate.ts +0 -227
  130. package/src/index.ts +0 -11
  131. package/src/lib/api/registry-client.ts +0 -223
  132. package/src/lib/api/schema.d.ts +0 -520
  133. package/src/lib/api/skills-client.ts +0 -148
  134. package/src/program.test.ts +0 -22
  135. package/src/program.ts +0 -226
  136. package/src/schemas/config.v1.schema.json +0 -37
  137. package/src/schemas/generated/api-responses.ts +0 -386
  138. package/src/schemas/generated/auth.ts +0 -21
  139. package/src/schemas/generated/index.ts +0 -5
  140. package/src/schemas/generated/package.ts +0 -29
  141. package/src/schemas/generated/skill.ts +0 -271
  142. package/src/utils/config-manager.test.ts +0 -330
  143. package/src/utils/config-manager.ts +0 -272
  144. package/src/utils/errors.test.ts +0 -25
  145. package/src/utils/errors.ts +0 -33
  146. package/src/utils/version.test.ts +0 -16
  147. package/src/utils/version.ts +0 -18
  148. package/test/integration/registry-client.test.ts +0 -180
  149. package/tsconfig.check.json +0 -9
  150. package/tsconfig.json +0 -25
  151. package/vitest.config.ts +0 -14
@@ -1,260 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs';
3
- import { join, basename } from 'path';
4
- import { tmpdir } from 'os';
5
- import { packSkill } from './pack.js';
6
- import { execSync } from 'child_process';
7
-
8
- describe('packSkill', () => {
9
- let testDir: string;
10
-
11
- beforeEach(() => {
12
- testDir = join(tmpdir(), `skill-pack-test-${Date.now()}`);
13
- mkdirSync(testDir, { recursive: true });
14
- });
15
-
16
- afterEach(() => {
17
- rmSync(testDir, { recursive: true, force: true });
18
- });
19
-
20
- describe('validation before packing', () => {
21
- it('fails for invalid skill', async () => {
22
- const skillDir = join(testDir, 'invalid-skill');
23
- mkdirSync(skillDir);
24
- // No SKILL.md
25
-
26
- const result = await packSkill(skillDir);
27
- expect(result.success).toBe(false);
28
- expect(result.error).toContain('Validation failed');
29
- });
30
-
31
- it('fails when name format is invalid', async () => {
32
- const skillDir = join(testDir, 'BadName');
33
- mkdirSync(skillDir);
34
- writeFileSync(
35
- join(skillDir, 'SKILL.md'),
36
- `---
37
- name: BadName
38
- description: Invalid name
39
- ---
40
- # Bad`
41
- );
42
-
43
- const result = await packSkill(skillDir);
44
- expect(result.success).toBe(false);
45
- expect(result.error).toContain('Validation failed');
46
- });
47
- });
48
-
49
- describe('successful packing', () => {
50
- it('creates a .skill bundle', async () => {
51
- const skillDir = join(testDir, 'test-skill');
52
- mkdirSync(skillDir);
53
- writeFileSync(
54
- join(skillDir, 'SKILL.md'),
55
- `---
56
- name: test-skill
57
- description: A test skill for packing
58
- metadata:
59
- version: "1.0.0"
60
- ---
61
- # Test Skill
62
-
63
- Instructions here.`
64
- );
65
-
66
- const outputPath = join(testDir, 'test-skill-1.0.0.skill');
67
- const result = await packSkill(skillDir, outputPath);
68
-
69
- expect(result.success).toBe(true);
70
- expect(result.name).toBe('test-skill');
71
- expect(result.version).toBe('1.0.0');
72
- expect(result.path).toBe(outputPath);
73
- expect(result.path!.endsWith('.skill')).toBe(true);
74
- expect(result.sha256).toMatch(/^[a-f0-9]{64}$/);
75
- expect(result.size).toBeGreaterThan(0);
76
-
77
- // Verify bundle exists
78
- expect(existsSync(result.path!)).toBe(true);
79
- });
80
-
81
- it('uses 0.0.0 version when metadata version is missing', async () => {
82
- const skillDir = join(testDir, 'no-version');
83
- mkdirSync(skillDir);
84
- writeFileSync(
85
- join(skillDir, 'SKILL.md'),
86
- `---
87
- name: no-version
88
- description: A skill without version
89
- ---
90
- # No Version`
91
- );
92
-
93
- const outputPath = join(testDir, 'no-version-0.0.0.skill');
94
- const result = await packSkill(skillDir, outputPath);
95
-
96
- expect(result.success).toBe(true);
97
- expect(result.version).toBe('0.0.0');
98
- expect(basename(result.path!)).toBe('no-version-0.0.0.skill');
99
- });
100
-
101
- it('creates bundle in current directory by default', async () => {
102
- const skillDir = join(testDir, 'output-test');
103
- mkdirSync(skillDir);
104
- writeFileSync(
105
- join(skillDir, 'SKILL.md'),
106
- `---
107
- name: output-test
108
- description: Testing output path
109
- metadata:
110
- version: "1.0.0"
111
- ---
112
- # Output Test`
113
- );
114
-
115
- // Change to temp directory to test default output location
116
- const originalCwd = process.cwd();
117
- process.chdir(testDir);
118
-
119
- try {
120
- const result = await packSkill(skillDir);
121
-
122
- expect(result.success).toBe(true);
123
- expect(result.path).toContain(testDir);
124
- } finally {
125
- process.chdir(originalCwd);
126
- }
127
- });
128
-
129
- it('uses custom output path when provided', async () => {
130
- const skillDir = join(testDir, 'custom-output');
131
- mkdirSync(skillDir);
132
- writeFileSync(
133
- join(skillDir, 'SKILL.md'),
134
- `---
135
- name: custom-output
136
- description: Custom output path test
137
- metadata:
138
- version: "2.0.0"
139
- ---
140
- # Custom Output`
141
- );
142
-
143
- const outputPath = join(testDir, 'custom-name.skill');
144
- const result = await packSkill(skillDir, outputPath);
145
-
146
- expect(result.success).toBe(true);
147
- expect(result.path).toBe(outputPath);
148
- expect(existsSync(outputPath)).toBe(true);
149
- });
150
-
151
- it('includes skill directory structure in bundle', async () => {
152
- const skillDir = join(testDir, 'structured-skill');
153
- mkdirSync(skillDir);
154
- mkdirSync(join(skillDir, 'scripts'));
155
- mkdirSync(join(skillDir, 'references'));
156
-
157
- writeFileSync(
158
- join(skillDir, 'SKILL.md'),
159
- `---
160
- name: structured-skill
161
- description: A skill with structure
162
- metadata:
163
- version: "1.0.0"
164
- ---
165
- # Structured Skill`
166
- );
167
- writeFileSync(join(skillDir, 'scripts', 'helper.py'), '# Python helper');
168
- writeFileSync(join(skillDir, 'references', 'PATTERNS.md'), '# Patterns');
169
-
170
- const outputPath = join(testDir, 'structured-skill-1.0.0.skill');
171
- const result = await packSkill(skillDir, outputPath);
172
-
173
- expect(result.success).toBe(true);
174
-
175
- // Verify bundle contents using unzip -l
176
- try {
177
- const listing = execSync(`unzip -l "${result.path}"`, { encoding: 'utf-8' });
178
- expect(listing).toContain('structured-skill/SKILL.md');
179
- expect(listing).toContain('structured-skill/scripts/helper.py');
180
- expect(listing).toContain('structured-skill/references/PATTERNS.md');
181
- } catch {
182
- // unzip may not be available, skip this check
183
- }
184
- });
185
-
186
- it('calculates correct SHA256', async () => {
187
- const skillDir = join(testDir, 'hash-test');
188
- mkdirSync(skillDir);
189
- writeFileSync(
190
- join(skillDir, 'SKILL.md'),
191
- `---
192
- name: hash-test
193
- description: Testing SHA256 calculation
194
- metadata:
195
- version: "1.0.0"
196
- ---
197
- # Hash Test`
198
- );
199
-
200
- const outputPath = join(testDir, 'hash-test-1.0.0.skill');
201
- const result = await packSkill(skillDir, outputPath);
202
-
203
- expect(result.success).toBe(true);
204
- expect(result.sha256).toHaveLength(64);
205
-
206
- // Verify hash using shasum if available
207
- try {
208
- const shasum = execSync(`shasum -a 256 "${result.path}"`, { encoding: 'utf-8' });
209
- const computedHash = shasum.split(' ')[0];
210
- expect(result.sha256).toBe(computedHash);
211
- } catch {
212
- // shasum may not be available, skip this check
213
- }
214
- });
215
- });
216
-
217
- describe('bundle naming', () => {
218
- it('creates bundle with name-version.skill format', async () => {
219
- const skillDir = join(testDir, 'naming-test');
220
- mkdirSync(skillDir);
221
- writeFileSync(
222
- join(skillDir, 'SKILL.md'),
223
- `---
224
- name: naming-test
225
- description: Testing bundle naming
226
- metadata:
227
- version: "3.2.1"
228
- ---
229
- # Naming Test`
230
- );
231
-
232
- const outputPath = join(testDir, 'naming-test-3.2.1.skill');
233
- const result = await packSkill(skillDir, outputPath);
234
-
235
- expect(result.success).toBe(true);
236
- expect(basename(result.path!)).toBe('naming-test-3.2.1.skill');
237
- });
238
-
239
- it('handles prerelease versions', async () => {
240
- const skillDir = join(testDir, 'prerelease-test');
241
- mkdirSync(skillDir);
242
- writeFileSync(
243
- join(skillDir, 'SKILL.md'),
244
- `---
245
- name: prerelease-test
246
- description: Testing prerelease version
247
- metadata:
248
- version: "1.0.0-beta.1"
249
- ---
250
- # Prerelease Test`
251
- );
252
-
253
- const outputPath = join(testDir, 'prerelease-test-1.0.0-beta.1.skill');
254
- const result = await packSkill(skillDir, outputPath);
255
-
256
- expect(result.success).toBe(true);
257
- expect(basename(result.path!)).toBe('prerelease-test-1.0.0-beta.1.skill');
258
- });
259
- });
260
- });
@@ -1,145 +0,0 @@
1
- import { createWriteStream, createReadStream } from 'fs';
2
- import { createHash } from 'crypto';
3
- import { basename, join, resolve } from 'path';
4
- import archiver from 'archiver';
5
- import { validateSkillDirectory, formatValidationResult } from './validate.js';
6
-
7
- export interface PackResult {
8
- success: boolean;
9
- path: string | null;
10
- name: string | null;
11
- version: string | null;
12
- size: number | null;
13
- sha256: string | null;
14
- error: string | null;
15
- }
16
-
17
- /**
18
- * Create a .skill bundle from a skill directory
19
- */
20
- export async function packSkill(skillPath: string, outputPath?: string): Promise<PackResult> {
21
- // Validate first
22
- const validation = validateSkillDirectory(skillPath);
23
-
24
- if (!validation.valid) {
25
- return {
26
- success: false,
27
- path: null,
28
- name: null,
29
- version: null,
30
- size: null,
31
- sha256: null,
32
- error: `Validation failed:\n${formatValidationResult(validation)}`,
33
- };
34
- }
35
-
36
- const skillName = validation.name!;
37
- const version = validation.frontmatter?.metadata?.version || '0.0.0';
38
-
39
- // Determine output path
40
- const bundleName = `${skillName}-${version}.skill`;
41
- const finalOutputPath = outputPath || join(process.cwd(), bundleName);
42
-
43
- // Create the zip archive
44
- return new Promise((resolvePromise) => {
45
- const output = createWriteStream(finalOutputPath);
46
- const archive = archiver('zip', { zlib: { level: 9 } });
47
-
48
- let size = 0;
49
-
50
- output.on('close', async () => {
51
- size = archive.pointer();
52
-
53
- // Calculate SHA256
54
- const hash = createHash('sha256');
55
- const stream = createReadStream(finalOutputPath);
56
-
57
- stream.on('data', (chunk) => hash.update(chunk));
58
- stream.on('end', () => {
59
- const sha256 = hash.digest('hex');
60
-
61
- resolvePromise({
62
- success: true,
63
- path: finalOutputPath,
64
- name: skillName,
65
- version,
66
- size,
67
- sha256,
68
- error: null,
69
- });
70
- });
71
- stream.on('error', (err) => {
72
- resolvePromise({
73
- success: false,
74
- path: null,
75
- name: skillName,
76
- version,
77
- size: null,
78
- sha256: null,
79
- error: `Failed to calculate SHA256: ${err.message}`,
80
- });
81
- });
82
- });
83
-
84
- archive.on('error', (err) => {
85
- resolvePromise({
86
- success: false,
87
- path: null,
88
- name: skillName,
89
- version,
90
- size: null,
91
- sha256: null,
92
- error: `Archive error: ${err.message}`,
93
- });
94
- });
95
-
96
- archive.pipe(output);
97
-
98
- // Add the skill directory to the archive
99
- // The archive should contain: skillName/SKILL.md, skillName/scripts/, etc.
100
- const dirName = basename(resolve(skillPath));
101
- archive.directory(skillPath, dirName);
102
-
103
- archive.finalize();
104
- });
105
- }
106
-
107
- /**
108
- * Format file size for display
109
- */
110
- function formatSize(bytes: number): string {
111
- if (bytes < 1024) return `${bytes} B`;
112
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
113
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
114
- }
115
-
116
- export interface PackOptions {
117
- output?: string;
118
- json?: boolean;
119
- }
120
-
121
- /**
122
- * Handle the pack command
123
- */
124
- export async function handleSkillPack(skillPath: string, options: PackOptions): Promise<void> {
125
- console.log('');
126
- console.log(`Validating ${skillPath}...`);
127
-
128
- const result = await packSkill(skillPath, options.output);
129
-
130
- if (options.json) {
131
- console.log(JSON.stringify(result, null, 2));
132
- } else if (result.success) {
133
- console.log(`\u2713 Valid: ${result.name}`);
134
- console.log('');
135
- console.log('Creating bundle...');
136
- console.log(`\u2713 Created: ${basename(result.path!)} (${formatSize(result.size!)})`);
137
- console.log(` SHA256: ${result.sha256}`);
138
- } else {
139
- console.log(result.error);
140
- }
141
-
142
- if (!result.success) {
143
- process.exit(1);
144
- }
145
- }
@@ -1,88 +0,0 @@
1
- import { writeFileSync } from 'fs';
2
- import { basename, join } from 'path';
3
- import { getSkillDownloadInfo, downloadSkillBundle } from '../../lib/api/skills-client.js';
4
-
5
- /**
6
- * Parse skill spec into name and version
7
- * Examples: @scope/name, @scope/name@1.0.0
8
- */
9
- function parseSkillSpec(spec: string): { name: string; version?: string } {
10
- // Handle @scope/name@version format
11
- const atIndex = spec.lastIndexOf('@');
12
-
13
- // If @ is at position 0, it's just the scope prefix
14
- if (atIndex <= 0) {
15
- return { name: spec };
16
- }
17
-
18
- // Check if the @ is part of version (after the /)
19
- const slashIndex = spec.indexOf('/');
20
- if (atIndex > slashIndex) {
21
- return {
22
- name: spec.slice(0, atIndex),
23
- version: spec.slice(atIndex + 1),
24
- };
25
- }
26
-
27
- return { name: spec };
28
- }
29
-
30
- export interface PullOptions {
31
- output?: string;
32
- json?: boolean;
33
- }
34
-
35
- /**
36
- * Handle the skill pull command
37
- */
38
- export async function handleSkillPull(skillSpec: string, options: PullOptions): Promise<void> {
39
- try {
40
- const { name, version } = parseSkillSpec(skillSpec);
41
-
42
- // Get download info
43
- const downloadInfo = await getSkillDownloadInfo(name, version);
44
-
45
- console.log(
46
- `Pulling ${downloadInfo.skill.name}@${downloadInfo.skill.version}...`
47
- );
48
-
49
- // Download the bundle
50
- const buffer = await downloadSkillBundle(downloadInfo.url, downloadInfo.skill.sha256);
51
-
52
- // Determine output path
53
- const filename = `${basename(downloadInfo.skill.name.replace('@', '').replace('/', '-'))}-${downloadInfo.skill.version}.skill`;
54
- const outputPath = options.output || join(process.cwd(), filename);
55
-
56
- // Write to disk
57
- writeFileSync(outputPath, buffer);
58
-
59
- if (options.json) {
60
- console.log(
61
- JSON.stringify(
62
- {
63
- path: outputPath,
64
- name: downloadInfo.skill.name,
65
- version: downloadInfo.skill.version,
66
- size: downloadInfo.skill.size,
67
- sha256: downloadInfo.skill.sha256,
68
- },
69
- null,
70
- 2
71
- )
72
- );
73
- } else {
74
- console.log(`Downloaded ${filename} (${formatSize(downloadInfo.skill.size)})`);
75
- console.log(` SHA256: ${downloadInfo.skill.sha256}`);
76
- console.log(` Path: ${outputPath}`);
77
- }
78
- } catch (err) {
79
- console.error(`Error: ${err instanceof Error ? err.message : err}`);
80
- process.exit(1);
81
- }
82
- }
83
-
84
- function formatSize(bytes: number): string {
85
- if (bytes < 1024) return `${bytes} B`;
86
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
87
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
88
- }
@@ -1,73 +0,0 @@
1
- import { searchSkills } from '../../lib/api/skills-client.js';
2
-
3
- export interface SearchOptions {
4
- tags?: string;
5
- category?: string;
6
- surface?: string;
7
- sort?: string;
8
- limit?: number;
9
- offset?: number;
10
- json?: boolean;
11
- }
12
-
13
- /**
14
- * Handle the skill search command
15
- */
16
- export async function handleSkillSearch(query: string, options: SearchOptions): Promise<void> {
17
- try {
18
- const result = await searchSkills({
19
- q: query,
20
- tags: options.tags,
21
- category: options.category as any,
22
- surface: options.surface as any,
23
- sort: options.sort as any,
24
- limit: options.limit,
25
- offset: options.offset,
26
- });
27
-
28
- if (options.json) {
29
- console.log(JSON.stringify(result, null, 2));
30
- return;
31
- }
32
-
33
- if (result.skills.length === 0) {
34
- console.log(`No skills found for "${query}"`);
35
- return;
36
- }
37
-
38
- // Table header
39
- const nameWidth = 45;
40
- const categoryWidth = 12;
41
- const downloadsWidth = 10;
42
-
43
- console.log('');
44
- console.log(
45
- 'NAME'.padEnd(nameWidth) +
46
- 'CATEGORY'.padEnd(categoryWidth) +
47
- 'DOWNLOADS'.padStart(downloadsWidth)
48
- );
49
-
50
- // Table rows
51
- for (const skill of result.skills) {
52
- const name = skill.name.length > nameWidth - 2
53
- ? skill.name.slice(0, nameWidth - 5) + '...'
54
- : skill.name;
55
- const category = skill.category || '-';
56
- const downloads = skill.downloads.toLocaleString();
57
-
58
- console.log(
59
- name.padEnd(nameWidth) +
60
- category.padEnd(categoryWidth) +
61
- downloads.padStart(downloadsWidth)
62
- );
63
- }
64
-
65
- if (result.pagination.has_more) {
66
- console.log('');
67
- console.log(`Showing ${result.skills.length} of ${result.total} results. Use --offset to see more.`);
68
- }
69
- } catch (err) {
70
- console.error(`Error: ${err instanceof Error ? err.message : err}`);
71
- process.exit(1);
72
- }
73
- }
@@ -1,72 +0,0 @@
1
- import { getSkillDetails } from '../../lib/api/skills-client.js';
2
-
3
- export interface ShowOptions {
4
- json?: boolean;
5
- }
6
-
7
- /**
8
- * Handle the skill show command
9
- */
10
- export async function handleSkillShow(name: string, options: ShowOptions): Promise<void> {
11
- try {
12
- const skill = await getSkillDetails(name);
13
-
14
- if (options.json) {
15
- console.log(JSON.stringify(skill, null, 2));
16
- return;
17
- }
18
-
19
- console.log('');
20
- console.log(`${skill.name}@${skill.latest_version}`);
21
- console.log('');
22
- console.log(skill.description);
23
- console.log('');
24
-
25
- // Metadata section
26
- console.log('Metadata:');
27
- if (skill.license) console.log(` License: ${skill.license}`);
28
- if (skill.category) console.log(` Category: ${skill.category}`);
29
- if (skill.tags && skill.tags.length > 0) console.log(` Tags: ${skill.tags.join(', ')}`);
30
- if (skill.surfaces && skill.surfaces.length > 0)
31
- console.log(` Surfaces: ${skill.surfaces.join(', ')}`);
32
- if (skill.author) console.log(` Author: ${skill.author.name}${skill.author.url ? ` (${skill.author.url})` : ''}`);
33
- console.log(` Downloads: ${skill.downloads.toLocaleString()}`);
34
- console.log(` Published: ${new Date(skill.published_at).toLocaleDateString()}`);
35
-
36
- // Triggers
37
- if (skill.triggers && skill.triggers.length > 0) {
38
- console.log('');
39
- console.log('Triggers:');
40
- skill.triggers.forEach((t: string) => console.log(` - ${t}`));
41
- }
42
-
43
- // Examples
44
- if (skill.examples && skill.examples.length > 0) {
45
- console.log('');
46
- console.log('Examples:');
47
- skill.examples.forEach((ex: { prompt: string; context?: string }) => {
48
- console.log(` - "${ex.prompt}"${ex.context ? ` (${ex.context})` : ''}`);
49
- });
50
- }
51
-
52
- // Versions
53
- if (skill.versions && skill.versions.length > 0) {
54
- console.log('');
55
- console.log('Versions:');
56
- skill.versions.slice(0, 5).forEach((v: { version: string; published_at: string; downloads: number }) => {
57
- console.log(
58
- ` ${v.version.padEnd(12)} ${new Date(v.published_at).toLocaleDateString().padEnd(12)} ${v.downloads.toLocaleString()} downloads`
59
- );
60
- });
61
- if (skill.versions.length > 5) {
62
- console.log(` ... and ${skill.versions.length - 5} more`);
63
- }
64
- }
65
-
66
- console.log('');
67
- console.log(`Install: mpak skill install ${skill.name}`);
68
- } catch (err) {
69
- console.error(`Error: ${err instanceof Error ? err.message : err}`);
70
- process.exit(1);
71
- }
72
- }