@nimblebrain/mpak-sdk 0.1.0 → 0.1.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/index.cjs +496 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1245 -0
- package/dist/index.d.ts +1241 -35
- package/dist/index.js +454 -35
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/dist/client.d.ts +0 -138
- package/dist/client.d.ts.map +0 -1
- package/dist/client.integration.test.d.ts +0 -11
- package/dist/client.integration.test.d.ts.map +0 -1
- package/dist/client.integration.test.js +0 -121
- package/dist/client.integration.test.js.map +0 -1
- package/dist/client.js +0 -430
- package/dist/client.js.map +0 -1
- package/dist/client.test.d.ts +0 -2
- package/dist/client.test.d.ts.map +0 -1
- package/dist/client.test.js +0 -344
- package/dist/client.test.js.map +0 -1
- package/dist/errors.d.ts +0 -30
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -46
- package/dist/errors.js.map +0 -1
- package/dist/errors.test.d.ts +0 -2
- package/dist/errors.test.d.ts.map +0 -1
- package/dist/errors.test.js +0 -136
- package/dist/errors.test.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types.d.ts +0 -146
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -7
- package/dist/types.js.map +0 -1
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
MpakClient: () => MpakClient,
|
|
34
|
+
MpakError: () => MpakError,
|
|
35
|
+
MpakIntegrityError: () => MpakIntegrityError,
|
|
36
|
+
MpakNetworkError: () => MpakNetworkError,
|
|
37
|
+
MpakNotFoundError: () => MpakNotFoundError
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
40
|
+
|
|
41
|
+
// src/client.ts
|
|
42
|
+
var import_crypto = require("crypto");
|
|
43
|
+
|
|
44
|
+
// src/errors.ts
|
|
45
|
+
var MpakError = class extends Error {
|
|
46
|
+
code;
|
|
47
|
+
statusCode;
|
|
48
|
+
constructor(message, code, statusCode) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = "MpakError";
|
|
51
|
+
this.code = code;
|
|
52
|
+
this.statusCode = statusCode;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var MpakNotFoundError = class extends MpakError {
|
|
56
|
+
constructor(resource) {
|
|
57
|
+
super(`Resource not found: ${resource}`, "NOT_FOUND", 404);
|
|
58
|
+
this.name = "MpakNotFoundError";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var MpakIntegrityError = class extends MpakError {
|
|
62
|
+
expected;
|
|
63
|
+
actual;
|
|
64
|
+
constructor(expected, actual) {
|
|
65
|
+
super(
|
|
66
|
+
`Integrity mismatch: expected ${expected}, got ${actual}`,
|
|
67
|
+
"INTEGRITY_MISMATCH"
|
|
68
|
+
);
|
|
69
|
+
this.name = "MpakIntegrityError";
|
|
70
|
+
this.expected = expected;
|
|
71
|
+
this.actual = actual;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var MpakNetworkError = class extends MpakError {
|
|
75
|
+
constructor(message) {
|
|
76
|
+
super(message, "NETWORK_ERROR");
|
|
77
|
+
this.name = "MpakNetworkError";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// src/client.ts
|
|
82
|
+
var DEFAULT_REGISTRY_URL = "https://api.mpak.dev";
|
|
83
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
84
|
+
var MpakClient = class {
|
|
85
|
+
registryUrl;
|
|
86
|
+
timeout;
|
|
87
|
+
constructor(config = {}) {
|
|
88
|
+
this.registryUrl = config.registryUrl ?? DEFAULT_REGISTRY_URL;
|
|
89
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
90
|
+
}
|
|
91
|
+
// ===========================================================================
|
|
92
|
+
// Bundle API
|
|
93
|
+
// ===========================================================================
|
|
94
|
+
/**
|
|
95
|
+
* Search for bundles
|
|
96
|
+
*/
|
|
97
|
+
async searchBundles(params = {}) {
|
|
98
|
+
const searchParams = new URLSearchParams();
|
|
99
|
+
if (params.q) searchParams.set("q", params.q);
|
|
100
|
+
if (params.type) searchParams.set("type", params.type);
|
|
101
|
+
if (params.sort) searchParams.set("sort", params.sort);
|
|
102
|
+
if (params.limit) searchParams.set("limit", String(params.limit));
|
|
103
|
+
if (params.offset) searchParams.set("offset", String(params.offset));
|
|
104
|
+
const queryString = searchParams.toString();
|
|
105
|
+
const url = `${this.registryUrl}/v1/bundles/search${queryString ? `?${queryString}` : ""}`;
|
|
106
|
+
const response = await this.fetchWithTimeout(url);
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
throw new MpakNetworkError(`Failed to search bundles: HTTP ${response.status}`);
|
|
109
|
+
}
|
|
110
|
+
return response.json();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get bundle details
|
|
114
|
+
*/
|
|
115
|
+
async getBundle(name) {
|
|
116
|
+
this.validateScopedName(name);
|
|
117
|
+
const url = `${this.registryUrl}/v1/bundles/${name}`;
|
|
118
|
+
const response = await this.fetchWithTimeout(url);
|
|
119
|
+
if (response.status === 404) {
|
|
120
|
+
throw new MpakNotFoundError(name);
|
|
121
|
+
}
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new MpakNetworkError(`Failed to get bundle: HTTP ${response.status}`);
|
|
124
|
+
}
|
|
125
|
+
return response.json();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get all versions of a bundle
|
|
129
|
+
*/
|
|
130
|
+
async getBundleVersions(name) {
|
|
131
|
+
this.validateScopedName(name);
|
|
132
|
+
const url = `${this.registryUrl}/v1/bundles/${name}/versions`;
|
|
133
|
+
const response = await this.fetchWithTimeout(url);
|
|
134
|
+
if (response.status === 404) {
|
|
135
|
+
throw new MpakNotFoundError(name);
|
|
136
|
+
}
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
throw new MpakNetworkError(`Failed to get bundle versions: HTTP ${response.status}`);
|
|
139
|
+
}
|
|
140
|
+
return response.json();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get a specific version of a bundle
|
|
144
|
+
*/
|
|
145
|
+
async getBundleVersion(name, version) {
|
|
146
|
+
this.validateScopedName(name);
|
|
147
|
+
const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}`;
|
|
148
|
+
const response = await this.fetchWithTimeout(url);
|
|
149
|
+
if (response.status === 404) {
|
|
150
|
+
throw new MpakNotFoundError(`${name}@${version}`);
|
|
151
|
+
}
|
|
152
|
+
if (!response.ok) {
|
|
153
|
+
throw new MpakNetworkError(`Failed to get bundle version: HTTP ${response.status}`);
|
|
154
|
+
}
|
|
155
|
+
return response.json();
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get download info for a bundle
|
|
159
|
+
*/
|
|
160
|
+
async getBundleDownload(name, version, platform) {
|
|
161
|
+
this.validateScopedName(name);
|
|
162
|
+
const params = new URLSearchParams();
|
|
163
|
+
if (platform) {
|
|
164
|
+
params.set("os", platform.os);
|
|
165
|
+
params.set("arch", platform.arch);
|
|
166
|
+
}
|
|
167
|
+
const queryString = params.toString();
|
|
168
|
+
const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}/download${queryString ? `?${queryString}` : ""}`;
|
|
169
|
+
const response = await this.fetchWithTimeout(url, {
|
|
170
|
+
headers: { Accept: "application/json" }
|
|
171
|
+
});
|
|
172
|
+
if (response.status === 404) {
|
|
173
|
+
throw new MpakNotFoundError(`${name}@${version}`);
|
|
174
|
+
}
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
throw new MpakNetworkError(`Failed to get bundle download: HTTP ${response.status}`);
|
|
177
|
+
}
|
|
178
|
+
return response.json();
|
|
179
|
+
}
|
|
180
|
+
// ===========================================================================
|
|
181
|
+
// Skill API
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
/**
|
|
184
|
+
* Search for skills
|
|
185
|
+
*/
|
|
186
|
+
async searchSkills(params = {}) {
|
|
187
|
+
const searchParams = new URLSearchParams();
|
|
188
|
+
if (params.q) searchParams.set("q", params.q);
|
|
189
|
+
if (params.tags) searchParams.set("tags", params.tags);
|
|
190
|
+
if (params.category) searchParams.set("category", params.category);
|
|
191
|
+
if (params.surface) searchParams.set("surface", params.surface);
|
|
192
|
+
if (params.sort) searchParams.set("sort", params.sort);
|
|
193
|
+
if (params.limit) searchParams.set("limit", String(params.limit));
|
|
194
|
+
if (params.offset) searchParams.set("offset", String(params.offset));
|
|
195
|
+
const queryString = searchParams.toString();
|
|
196
|
+
const url = `${this.registryUrl}/v1/skills/search${queryString ? `?${queryString}` : ""}`;
|
|
197
|
+
const response = await this.fetchWithTimeout(url);
|
|
198
|
+
if (!response.ok) {
|
|
199
|
+
throw new MpakNetworkError(`Failed to search skills: HTTP ${response.status}`);
|
|
200
|
+
}
|
|
201
|
+
return response.json();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get skill details
|
|
205
|
+
*/
|
|
206
|
+
async getSkill(name) {
|
|
207
|
+
this.validateScopedName(name);
|
|
208
|
+
const url = `${this.registryUrl}/v1/skills/${name}`;
|
|
209
|
+
const response = await this.fetchWithTimeout(url);
|
|
210
|
+
if (response.status === 404) {
|
|
211
|
+
throw new MpakNotFoundError(name);
|
|
212
|
+
}
|
|
213
|
+
if (!response.ok) {
|
|
214
|
+
throw new MpakNetworkError(`Failed to get skill: HTTP ${response.status}`);
|
|
215
|
+
}
|
|
216
|
+
return response.json();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get download info for a skill (latest version)
|
|
220
|
+
*/
|
|
221
|
+
async getSkillDownload(name) {
|
|
222
|
+
this.validateScopedName(name);
|
|
223
|
+
const url = `${this.registryUrl}/v1/skills/${name}/download`;
|
|
224
|
+
const response = await this.fetchWithTimeout(url, {
|
|
225
|
+
headers: { Accept: "application/json" }
|
|
226
|
+
});
|
|
227
|
+
if (response.status === 404) {
|
|
228
|
+
throw new MpakNotFoundError(name);
|
|
229
|
+
}
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);
|
|
232
|
+
}
|
|
233
|
+
return response.json();
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Get download info for a specific skill version
|
|
237
|
+
*/
|
|
238
|
+
async getSkillVersionDownload(name, version) {
|
|
239
|
+
this.validateScopedName(name);
|
|
240
|
+
const url = `${this.registryUrl}/v1/skills/${name}/versions/${version}/download`;
|
|
241
|
+
const response = await this.fetchWithTimeout(url, {
|
|
242
|
+
headers: { Accept: "application/json" }
|
|
243
|
+
});
|
|
244
|
+
if (response.status === 404) {
|
|
245
|
+
throw new MpakNotFoundError(`${name}@${version}`);
|
|
246
|
+
}
|
|
247
|
+
if (!response.ok) {
|
|
248
|
+
throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);
|
|
249
|
+
}
|
|
250
|
+
return response.json();
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Download skill content and verify integrity
|
|
254
|
+
*
|
|
255
|
+
* @throws {MpakIntegrityError} If expectedSha256 is provided and doesn't match (fail-closed)
|
|
256
|
+
*/
|
|
257
|
+
async downloadSkillContent(downloadUrl, expectedSha256) {
|
|
258
|
+
const response = await this.fetchWithTimeout(downloadUrl);
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
throw new MpakNetworkError(`Failed to download skill: HTTP ${response.status}`);
|
|
261
|
+
}
|
|
262
|
+
const content = await response.text();
|
|
263
|
+
if (expectedSha256) {
|
|
264
|
+
const actualHash = this.computeSha256(content);
|
|
265
|
+
if (actualHash !== expectedSha256) {
|
|
266
|
+
throw new MpakIntegrityError(expectedSha256, actualHash);
|
|
267
|
+
}
|
|
268
|
+
return { content, verified: true };
|
|
269
|
+
}
|
|
270
|
+
return { content, verified: false };
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Resolve a skill reference to actual content
|
|
274
|
+
*
|
|
275
|
+
* Supports mpak, github, and url sources. This is the main method for
|
|
276
|
+
* fetching skill content from any supported source.
|
|
277
|
+
*
|
|
278
|
+
* @throws {MpakNotFoundError} If skill not found
|
|
279
|
+
* @throws {MpakIntegrityError} If integrity check fails (fail-closed)
|
|
280
|
+
* @throws {MpakNetworkError} For network failures
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* // Resolve from mpak registry
|
|
285
|
+
* const skill = await client.resolveSkillRef({
|
|
286
|
+
* source: 'mpak',
|
|
287
|
+
* name: '@nimblebraininc/folk-crm',
|
|
288
|
+
* version: '1.3.0',
|
|
289
|
+
* });
|
|
290
|
+
*
|
|
291
|
+
* // Resolve from GitHub
|
|
292
|
+
* const skill = await client.resolveSkillRef({
|
|
293
|
+
* source: 'github',
|
|
294
|
+
* name: '@example/my-skill',
|
|
295
|
+
* version: 'v1.0.0',
|
|
296
|
+
* repo: 'owner/repo',
|
|
297
|
+
* path: 'skills/my-skill/SKILL.md',
|
|
298
|
+
* });
|
|
299
|
+
*
|
|
300
|
+
* // Resolve from URL
|
|
301
|
+
* const skill = await client.resolveSkillRef({
|
|
302
|
+
* source: 'url',
|
|
303
|
+
* name: '@example/custom',
|
|
304
|
+
* version: '1.0.0',
|
|
305
|
+
* url: 'https://example.com/skill.md',
|
|
306
|
+
* });
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
async resolveSkillRef(ref) {
|
|
310
|
+
switch (ref.source) {
|
|
311
|
+
case "mpak":
|
|
312
|
+
return this.resolveMpakSkill(ref);
|
|
313
|
+
case "github":
|
|
314
|
+
return this.resolveGithubSkill(ref);
|
|
315
|
+
case "url":
|
|
316
|
+
return this.resolveUrlSkill(ref);
|
|
317
|
+
default: {
|
|
318
|
+
const _exhaustive = ref;
|
|
319
|
+
throw new Error(`Unknown skill source: ${_exhaustive.source}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Resolve a skill from mpak registry
|
|
325
|
+
*
|
|
326
|
+
* The API returns a ZIP bundle containing SKILL.md and metadata.
|
|
327
|
+
*/
|
|
328
|
+
async resolveMpakSkill(ref) {
|
|
329
|
+
const url = `${this.registryUrl}/v1/skills/${ref.name}/versions/${ref.version}/download`;
|
|
330
|
+
const response = await this.fetchWithTimeout(url);
|
|
331
|
+
if (response.status === 404) {
|
|
332
|
+
throw new MpakNotFoundError(`${ref.name}@${ref.version}`);
|
|
333
|
+
}
|
|
334
|
+
if (!response.ok) {
|
|
335
|
+
throw new MpakNetworkError(`Failed to fetch skill: HTTP ${response.status}`);
|
|
336
|
+
}
|
|
337
|
+
const zipBuffer = await response.arrayBuffer();
|
|
338
|
+
const content = await this.extractSkillFromZip(zipBuffer, ref.name);
|
|
339
|
+
if (ref.integrity) {
|
|
340
|
+
this.verifyIntegrityOrThrow(content, ref.integrity);
|
|
341
|
+
return { content, version: ref.version, source: "mpak", verified: true };
|
|
342
|
+
}
|
|
343
|
+
return { content, version: ref.version, source: "mpak", verified: false };
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Resolve a skill from GitHub releases
|
|
347
|
+
*/
|
|
348
|
+
async resolveGithubSkill(ref) {
|
|
349
|
+
const url = `https://github.com/${ref.repo}/releases/download/${ref.version}/${ref.path}`;
|
|
350
|
+
const response = await this.fetchWithTimeout(url);
|
|
351
|
+
if (!response.ok) {
|
|
352
|
+
throw new MpakNotFoundError(`github:${ref.repo}/${ref.path}@${ref.version}`);
|
|
353
|
+
}
|
|
354
|
+
const content = await response.text();
|
|
355
|
+
if (ref.integrity) {
|
|
356
|
+
this.verifyIntegrityOrThrow(content, ref.integrity);
|
|
357
|
+
return { content, version: ref.version, source: "github", verified: true };
|
|
358
|
+
}
|
|
359
|
+
return { content, version: ref.version, source: "github", verified: false };
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Resolve a skill from a direct URL
|
|
363
|
+
*/
|
|
364
|
+
async resolveUrlSkill(ref) {
|
|
365
|
+
const response = await this.fetchWithTimeout(ref.url);
|
|
366
|
+
if (!response.ok) {
|
|
367
|
+
throw new MpakNotFoundError(`url:${ref.url}`);
|
|
368
|
+
}
|
|
369
|
+
const content = await response.text();
|
|
370
|
+
if (ref.integrity) {
|
|
371
|
+
this.verifyIntegrityOrThrow(content, ref.integrity);
|
|
372
|
+
return { content, version: ref.version, source: "url", verified: true };
|
|
373
|
+
}
|
|
374
|
+
return { content, version: ref.version, source: "url", verified: false };
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Extract SKILL.md content from a skill bundle ZIP
|
|
378
|
+
*/
|
|
379
|
+
async extractSkillFromZip(zipBuffer, skillName) {
|
|
380
|
+
const JSZip = (await import("jszip")).default;
|
|
381
|
+
const zip = await JSZip.loadAsync(zipBuffer);
|
|
382
|
+
const folderName = skillName.split("/").pop() ?? skillName;
|
|
383
|
+
const skillPath = `${folderName}/SKILL.md`;
|
|
384
|
+
const skillFile = zip.file(skillPath);
|
|
385
|
+
if (!skillFile) {
|
|
386
|
+
const altFile = zip.file("SKILL.md");
|
|
387
|
+
if (!altFile) {
|
|
388
|
+
throw new MpakNotFoundError(`SKILL.md not found in bundle for ${skillName}`);
|
|
389
|
+
}
|
|
390
|
+
return altFile.async("string");
|
|
391
|
+
}
|
|
392
|
+
return skillFile.async("string");
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Verify content integrity and throw if mismatch (fail-closed)
|
|
396
|
+
*/
|
|
397
|
+
verifyIntegrityOrThrow(content, integrity) {
|
|
398
|
+
const expectedHash = this.extractHash(integrity);
|
|
399
|
+
const actualHash = this.computeSha256(content);
|
|
400
|
+
if (actualHash !== expectedHash) {
|
|
401
|
+
throw new MpakIntegrityError(expectedHash, actualHash);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Extract hash from integrity string (removes prefix)
|
|
406
|
+
*/
|
|
407
|
+
extractHash(integrity) {
|
|
408
|
+
if (integrity.startsWith("sha256:")) {
|
|
409
|
+
return integrity.slice(7);
|
|
410
|
+
}
|
|
411
|
+
if (integrity.startsWith("sha256-")) {
|
|
412
|
+
return integrity.slice(7);
|
|
413
|
+
}
|
|
414
|
+
return integrity;
|
|
415
|
+
}
|
|
416
|
+
// ===========================================================================
|
|
417
|
+
// Utility Methods
|
|
418
|
+
// ===========================================================================
|
|
419
|
+
/**
|
|
420
|
+
* Detect the current platform
|
|
421
|
+
*/
|
|
422
|
+
static detectPlatform() {
|
|
423
|
+
const nodePlatform = process.platform;
|
|
424
|
+
const nodeArch = process.arch;
|
|
425
|
+
let os;
|
|
426
|
+
switch (nodePlatform) {
|
|
427
|
+
case "darwin":
|
|
428
|
+
os = "darwin";
|
|
429
|
+
break;
|
|
430
|
+
case "win32":
|
|
431
|
+
os = "win32";
|
|
432
|
+
break;
|
|
433
|
+
case "linux":
|
|
434
|
+
os = "linux";
|
|
435
|
+
break;
|
|
436
|
+
default:
|
|
437
|
+
os = "any";
|
|
438
|
+
}
|
|
439
|
+
let arch;
|
|
440
|
+
switch (nodeArch) {
|
|
441
|
+
case "x64":
|
|
442
|
+
arch = "x64";
|
|
443
|
+
break;
|
|
444
|
+
case "arm64":
|
|
445
|
+
arch = "arm64";
|
|
446
|
+
break;
|
|
447
|
+
default:
|
|
448
|
+
arch = "any";
|
|
449
|
+
}
|
|
450
|
+
return { os, arch };
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Compute SHA256 hash of content
|
|
454
|
+
*/
|
|
455
|
+
computeSha256(content) {
|
|
456
|
+
return (0, import_crypto.createHash)("sha256").update(content, "utf8").digest("hex");
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Validate that a name is scoped (@scope/name)
|
|
460
|
+
*/
|
|
461
|
+
validateScopedName(name) {
|
|
462
|
+
if (!name.startsWith("@")) {
|
|
463
|
+
throw new Error("Package name must be scoped (e.g., @scope/package-name)");
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Fetch with timeout support
|
|
468
|
+
*/
|
|
469
|
+
async fetchWithTimeout(url, init) {
|
|
470
|
+
const controller = new AbortController();
|
|
471
|
+
const timeoutId = setTimeout(() => {
|
|
472
|
+
controller.abort();
|
|
473
|
+
}, this.timeout);
|
|
474
|
+
try {
|
|
475
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
476
|
+
} catch (error) {
|
|
477
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
478
|
+
throw new MpakNetworkError(`Request timeout after ${this.timeout}ms`);
|
|
479
|
+
}
|
|
480
|
+
throw new MpakNetworkError(
|
|
481
|
+
error instanceof Error ? error.message : "Network error"
|
|
482
|
+
);
|
|
483
|
+
} finally {
|
|
484
|
+
clearTimeout(timeoutId);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
489
|
+
0 && (module.exports = {
|
|
490
|
+
MpakClient,
|
|
491
|
+
MpakError,
|
|
492
|
+
MpakIntegrityError,
|
|
493
|
+
MpakNetworkError,
|
|
494
|
+
MpakNotFoundError
|
|
495
|
+
});
|
|
496
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/errors.ts"],"sourcesContent":["/**\n * @nimblebrain/mpak-sdk\n *\n * TypeScript SDK for mpak registry - MCPB bundles and Agent Skills\n *\n * Requires Node.js 18+ for native fetch support.\n *\n * @example\n * ```typescript\n * import { MpakClient, SkillReference } from '@nimblebrain/mpak-sdk';\n *\n * const client = new MpakClient();\n *\n * // Search for bundles\n * const bundles = await client.searchBundles({ q: 'mcp' });\n *\n * // Get bundle details\n * const bundle = await client.getBundle('@nimbletools/echo');\n *\n * // Search for skills\n * const skills = await client.searchSkills({ q: 'crm' });\n *\n * // Resolve a skill reference to content (recommended)\n * const ref: SkillReference = {\n * source: 'mpak',\n * name: '@nimblebraininc/folk-crm',\n * version: '1.3.0',\n * };\n * const resolved = await client.resolveSkillRef(ref);\n * console.log(resolved.content); // Skill markdown content\n * ```\n */\n\nexport { MpakClient } from './client.js';\n\n// Configuration\nexport type { MpakClientConfig } from './types.js';\n\n// Bundle types\nexport type {\n BundleSearchResponse,\n BundleDetailResponse,\n BundleVersionsResponse,\n BundleVersionResponse,\n BundleDownloadResponse,\n BundleIndexResponse,\n BundleSearchParams,\n Bundle,\n BundleDetail,\n BundleVersion,\n BundleArtifact,\n BundleDownloadInfo,\n} from './types.js';\n\n// Skill types\nexport type {\n SkillSearchResponse,\n SkillDetailResponse,\n SkillDownloadResponse,\n SkillSearchParams,\n Skill,\n SkillDetail,\n SkillDownloadInfo,\n SkillVersion,\n // Skill reference types (for resolveSkillRef)\n SkillReference,\n MpakSkillReference,\n GithubSkillReference,\n UrlSkillReference,\n ResolvedSkill,\n} from './types.js';\n\n// Common types\nexport type {\n Platform,\n Pagination,\n Provenance,\n Author,\n} from './types.js';\n\n// Errors\nexport {\n MpakError,\n MpakNotFoundError,\n MpakIntegrityError,\n MpakNetworkError,\n} from './errors.js';\n","import { createHash } from 'crypto';\nimport type {\n MpakClientConfig,\n BundleSearchResponse,\n BundleDetailResponse,\n BundleVersionsResponse,\n BundleVersionResponse,\n BundleDownloadResponse,\n BundleSearchParams,\n SkillSearchResponse,\n SkillDetailResponse,\n SkillDownloadResponse,\n SkillSearchParams,\n Platform,\n SkillReference,\n GithubSkillReference,\n UrlSkillReference,\n ResolvedSkill,\n} from './types.js';\nimport {\n MpakNotFoundError,\n MpakIntegrityError,\n MpakNetworkError,\n} from './errors.js';\n\nconst DEFAULT_REGISTRY_URL = 'https://api.mpak.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\n/**\n * Client for interacting with the mpak registry\n *\n * Zero runtime dependencies - uses native fetch and crypto only.\n * Requires Node.js 18+ for native fetch support.\n */\nexport class MpakClient {\n private readonly registryUrl: string;\n private readonly timeout: number;\n\n constructor(config: MpakClientConfig = {}) {\n this.registryUrl = config.registryUrl ?? DEFAULT_REGISTRY_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n // ===========================================================================\n // Bundle API\n // ===========================================================================\n\n /**\n * Search for bundles\n */\n async searchBundles(params: BundleSearchParams = {}): Promise<BundleSearchResponse> {\n const searchParams = new URLSearchParams();\n if (params.q) searchParams.set('q', params.q);\n if (params.type) searchParams.set('type', params.type);\n if (params.sort) searchParams.set('sort', params.sort);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n const queryString = searchParams.toString();\n const url = `${this.registryUrl}/v1/bundles/search${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to search bundles: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleSearchResponse>;\n }\n\n /**\n * Get bundle details\n */\n async getBundle(name: string): Promise<BundleDetailResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleDetailResponse>;\n }\n\n /**\n * Get all versions of a bundle\n */\n async getBundleVersions(name: string): Promise<BundleVersionsResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}/versions`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle versions: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleVersionsResponse>;\n }\n\n /**\n * Get a specific version of a bundle\n */\n async getBundleVersion(name: string, version: string): Promise<BundleVersionResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle version: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleVersionResponse>;\n }\n\n /**\n * Get download info for a bundle\n */\n async getBundleDownload(\n name: string,\n version: string,\n platform?: Platform\n ): Promise<BundleDownloadResponse> {\n this.validateScopedName(name);\n\n const params = new URLSearchParams();\n if (platform) {\n params.set('os', platform.os);\n params.set('arch', platform.arch);\n }\n\n const queryString = params.toString();\n const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}/download${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleDownloadResponse>;\n }\n\n // ===========================================================================\n // Skill API\n // ===========================================================================\n\n /**\n * Search for skills\n */\n async searchSkills(params: SkillSearchParams = {}): Promise<SkillSearchResponse> {\n const searchParams = new URLSearchParams();\n if (params.q) searchParams.set('q', params.q);\n if (params.tags) searchParams.set('tags', params.tags);\n if (params.category) searchParams.set('category', params.category);\n if (params.surface) searchParams.set('surface', params.surface);\n if (params.sort) searchParams.set('sort', params.sort);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n const queryString = searchParams.toString();\n const url = `${this.registryUrl}/v1/skills/search${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to search skills: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillSearchResponse>;\n }\n\n /**\n * Get skill details\n */\n async getSkill(name: string): Promise<SkillDetailResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDetailResponse>;\n }\n\n /**\n * Get download info for a skill (latest version)\n */\n async getSkillDownload(name: string): Promise<SkillDownloadResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}/download`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDownloadResponse>;\n }\n\n /**\n * Get download info for a specific skill version\n */\n async getSkillVersionDownload(name: string, version: string): Promise<SkillDownloadResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}/versions/${version}/download`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDownloadResponse>;\n }\n\n /**\n * Download skill content and verify integrity\n *\n * @throws {MpakIntegrityError} If expectedSha256 is provided and doesn't match (fail-closed)\n */\n async downloadSkillContent(\n downloadUrl: string,\n expectedSha256?: string\n ): Promise<{ content: string; verified: boolean }> {\n const response = await this.fetchWithTimeout(downloadUrl);\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to download skill: HTTP ${response.status}`);\n }\n\n const content = await response.text();\n\n if (expectedSha256) {\n const actualHash = this.computeSha256(content);\n if (actualHash !== expectedSha256) {\n throw new MpakIntegrityError(expectedSha256, actualHash);\n }\n return { content, verified: true };\n }\n\n return { content, verified: false };\n }\n\n /**\n * Resolve a skill reference to actual content\n *\n * Supports mpak, github, and url sources. This is the main method for\n * fetching skill content from any supported source.\n *\n * @throws {MpakNotFoundError} If skill not found\n * @throws {MpakIntegrityError} If integrity check fails (fail-closed)\n * @throws {MpakNetworkError} For network failures\n *\n * @example\n * ```typescript\n * // Resolve from mpak registry\n * const skill = await client.resolveSkillRef({\n * source: 'mpak',\n * name: '@nimblebraininc/folk-crm',\n * version: '1.3.0',\n * });\n *\n * // Resolve from GitHub\n * const skill = await client.resolveSkillRef({\n * source: 'github',\n * name: '@example/my-skill',\n * version: 'v1.0.0',\n * repo: 'owner/repo',\n * path: 'skills/my-skill/SKILL.md',\n * });\n *\n * // Resolve from URL\n * const skill = await client.resolveSkillRef({\n * source: 'url',\n * name: '@example/custom',\n * version: '1.0.0',\n * url: 'https://example.com/skill.md',\n * });\n * ```\n */\n async resolveSkillRef(ref: SkillReference): Promise<ResolvedSkill> {\n switch (ref.source) {\n case 'mpak':\n return this.resolveMpakSkill(ref);\n case 'github':\n return this.resolveGithubSkill(ref);\n case 'url':\n return this.resolveUrlSkill(ref);\n default: {\n const _exhaustive: never = ref;\n throw new Error(`Unknown skill source: ${(_exhaustive as SkillReference).source}`);\n }\n }\n }\n\n /**\n * Resolve a skill from mpak registry\n *\n * The API returns a ZIP bundle containing SKILL.md and metadata.\n */\n private async resolveMpakSkill(ref: SkillReference & { source: 'mpak' }): Promise<ResolvedSkill> {\n const url = `${this.registryUrl}/v1/skills/${ref.name}/versions/${ref.version}/download`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${ref.name}@${ref.version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to fetch skill: HTTP ${response.status}`);\n }\n\n // Response is a ZIP file - extract SKILL.md\n const zipBuffer = await response.arrayBuffer();\n const content = await this.extractSkillFromZip(zipBuffer, ref.name);\n\n if (ref.integrity) {\n this.verifyIntegrityOrThrow(content, ref.integrity);\n return { content, version: ref.version, source: 'mpak', verified: true };\n }\n\n return { content, version: ref.version, source: 'mpak', verified: false };\n }\n\n /**\n * Resolve a skill from GitHub releases\n */\n private async resolveGithubSkill(ref: GithubSkillReference): Promise<ResolvedSkill> {\n const url = `https://github.com/${ref.repo}/releases/download/${ref.version}/${ref.path}`;\n const response = await this.fetchWithTimeout(url);\n\n if (!response.ok) {\n throw new MpakNotFoundError(`github:${ref.repo}/${ref.path}@${ref.version}`);\n }\n\n const content = await response.text();\n\n if (ref.integrity) {\n this.verifyIntegrityOrThrow(content, ref.integrity);\n return { content, version: ref.version, source: 'github', verified: true };\n }\n\n return { content, version: ref.version, source: 'github', verified: false };\n }\n\n /**\n * Resolve a skill from a direct URL\n */\n private async resolveUrlSkill(ref: UrlSkillReference): Promise<ResolvedSkill> {\n const response = await this.fetchWithTimeout(ref.url);\n\n if (!response.ok) {\n throw new MpakNotFoundError(`url:${ref.url}`);\n }\n\n const content = await response.text();\n\n if (ref.integrity) {\n this.verifyIntegrityOrThrow(content, ref.integrity);\n return { content, version: ref.version, source: 'url', verified: true };\n }\n\n return { content, version: ref.version, source: 'url', verified: false };\n }\n\n /**\n * Extract SKILL.md content from a skill bundle ZIP\n */\n private async extractSkillFromZip(zipBuffer: ArrayBuffer, skillName: string): Promise<string> {\n const JSZip = (await import('jszip')).default;\n const zip = await JSZip.loadAsync(zipBuffer);\n\n // Skill name format: @scope/name -> folder is just 'name'\n const folderName = skillName.split('/').pop() ?? skillName;\n const skillPath = `${folderName}/SKILL.md`;\n\n const skillFile = zip.file(skillPath);\n if (!skillFile) {\n // Try without folder prefix\n const altFile = zip.file('SKILL.md');\n if (!altFile) {\n throw new MpakNotFoundError(`SKILL.md not found in bundle for ${skillName}`);\n }\n return altFile.async('string');\n }\n\n return skillFile.async('string');\n }\n\n /**\n * Verify content integrity and throw if mismatch (fail-closed)\n */\n private verifyIntegrityOrThrow(content: string, integrity: string): void {\n const expectedHash = this.extractHash(integrity);\n const actualHash = this.computeSha256(content);\n\n if (actualHash !== expectedHash) {\n throw new MpakIntegrityError(expectedHash, actualHash);\n }\n }\n\n /**\n * Extract hash from integrity string (removes prefix)\n */\n private extractHash(integrity: string): string {\n if (integrity.startsWith('sha256:')) {\n return integrity.slice(7);\n }\n if (integrity.startsWith('sha256-')) {\n return integrity.slice(7);\n }\n return integrity;\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Detect the current platform\n */\n static detectPlatform(): Platform {\n const nodePlatform = process.platform;\n const nodeArch = process.arch;\n\n let os: string;\n switch (nodePlatform) {\n case 'darwin':\n os = 'darwin';\n break;\n case 'win32':\n os = 'win32';\n break;\n case 'linux':\n os = 'linux';\n break;\n default:\n os = 'any';\n }\n\n let arch: string;\n switch (nodeArch) {\n case 'x64':\n arch = 'x64';\n break;\n case 'arm64':\n arch = 'arm64';\n break;\n default:\n arch = 'any';\n }\n\n return { os, arch };\n }\n\n /**\n * Compute SHA256 hash of content\n */\n private computeSha256(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n }\n\n /**\n * Validate that a name is scoped (@scope/name)\n */\n private validateScopedName(name: string): void {\n if (!name.startsWith('@')) {\n throw new Error('Package name must be scoped (e.g., @scope/package-name)');\n }\n }\n\n /**\n * Fetch with timeout support\n */\n private async fetchWithTimeout(\n url: string,\n init?: RequestInit\n ): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, this.timeout);\n\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new MpakNetworkError(`Request timeout after ${this.timeout}ms`);\n }\n throw new MpakNetworkError(\n error instanceof Error ? error.message : 'Network error'\n );\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * Base error class for mpak SDK errors\n */\nexport class MpakError extends Error {\n code: string;\n statusCode?: number;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'MpakError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Thrown when a requested resource is not found (404)\n */\nexport class MpakNotFoundError extends MpakError {\n constructor(resource: string) {\n super(`Resource not found: ${resource}`, 'NOT_FOUND', 404);\n this.name = 'MpakNotFoundError';\n }\n}\n\n/**\n * Thrown when integrity verification fails (hash mismatch)\n * This is a fail-closed error - content is NOT returned when this is thrown\n */\nexport class MpakIntegrityError extends MpakError {\n expected: string;\n actual: string;\n\n constructor(expected: string, actual: string) {\n super(\n `Integrity mismatch: expected ${expected}, got ${actual}`,\n 'INTEGRITY_MISMATCH'\n );\n this.name = 'MpakIntegrityError';\n this.expected = expected;\n this.actual = actual;\n }\n}\n\n/**\n * Thrown for network-related failures (timeouts, connection errors)\n */\nexport class MpakNetworkError extends MpakError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'MpakNetworkError';\n }\n}\n"],"mappings":"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","names":[]}
|