@khanhcan148/mk 0.1.16 → 0.1.18
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/README.md +4 -2
- package/package.json +1 -1
- package/src/commands/init.js +13 -7
- package/src/commands/update.js +455 -436
- package/src/lib/auth.js +7 -1
- package/src/lib/checksum.js +21 -6
- package/src/lib/concurrency.js +36 -0
- package/src/lib/constants.js +8 -0
- package/src/lib/copy.js +335 -331
package/src/lib/auth.js
CHANGED
|
@@ -155,7 +155,13 @@ export async function startDeviceFlow(opts = {}) {
|
|
|
155
155
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
156
156
|
Accept: 'application/json'
|
|
157
157
|
},
|
|
158
|
-
|
|
158
|
+
// Use URLSearchParams to prevent parameter injection if device_code ever contains '&' chars
|
|
159
|
+
// (mirrors the same safe pattern used in Step 1 above for the initial device-code request).
|
|
160
|
+
body: new URLSearchParams({
|
|
161
|
+
client_id: GITHUB_CLIENT_ID,
|
|
162
|
+
device_code,
|
|
163
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code'
|
|
164
|
+
}).toString()
|
|
159
165
|
});
|
|
160
166
|
|
|
161
167
|
const tokenData = await tokenRes.json();
|
package/src/lib/checksum.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { createReadStream } from 'node:fs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Compute SHA-256 checksum of a file.
|
|
5
|
+
* Compute SHA-256 checksum of a file asynchronously using a streaming pipeline.
|
|
6
|
+
* Using createReadStream avoids loading the entire file into memory, which is
|
|
7
|
+
* important for large binary assets in the kit. Promise.all callers can parallelise
|
|
8
|
+
* multiple checksums without blocking the event loop.
|
|
9
|
+
*
|
|
6
10
|
* @param {string} filePath - Absolute path to file
|
|
7
|
-
* @returns {string} Checksum string prefixed with 'sha256:'
|
|
11
|
+
* @returns {Promise<string>} Checksum string prefixed with 'sha256:'
|
|
8
12
|
*/
|
|
9
13
|
export function computeChecksum(filePath) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const hash = createHash('sha256');
|
|
16
|
+
const stream = createReadStream(filePath);
|
|
17
|
+
stream.on('data', (chunk) => hash.update(chunk));
|
|
18
|
+
stream.on('end', () => resolve(`sha256:${hash.digest('hex')}`));
|
|
19
|
+
// H6: wrap the raw fs.Error so the absolute path in err.path never reaches
|
|
20
|
+
// user stderr while preserving the causal chain for debuggers. The top-level
|
|
21
|
+
// message is the errno code (callers branch on err.code; err.cause retains
|
|
22
|
+
// the original for stack-trace inspection when needed).
|
|
23
|
+
stream.on('error', (e) => {
|
|
24
|
+
const code = e && e.code ? e.code : 'checksum read failed';
|
|
25
|
+
reject(new Error(code, e ? { cause: e } : undefined));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
13
28
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default in-flight worker cap for `pLimit` over file-descriptor-bound tasks.
|
|
3
|
+
*
|
|
4
|
+
* 16 is 8× typical disk parallelism and well under macOS default `ulimit -n 256`.
|
|
5
|
+
* Chosen empirically — higher values don't meaningfully speed up SHA-256 of
|
|
6
|
+
* kit-sized files, and lower values serialise too aggressively on SSD.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_CONCURRENCY_CAP = 16;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Bounded-concurrency helper for fan-out over async tasks.
|
|
12
|
+
*
|
|
13
|
+
* M3 — `Promise.all(items.map(computeChecksum))` opens N file descriptors at
|
|
14
|
+
* once. On installs with hundreds of files this blows past the default
|
|
15
|
+
* `ulimit -n` (256 on macOS) and causes EMFILE. `pLimit` caps the in-flight
|
|
16
|
+
* worker pool; results preserve input order via explicit index assignment.
|
|
17
|
+
*
|
|
18
|
+
* @template T
|
|
19
|
+
* @param {Array<() => Promise<T>>} tasks Array of thunks. Each thunk is
|
|
20
|
+
* invoked at most once by exactly one worker.
|
|
21
|
+
* @param {number} cap Max concurrent workers (>=1).
|
|
22
|
+
* @returns {Promise<T[]>} Results indexed to match `tasks`.
|
|
23
|
+
*/
|
|
24
|
+
export async function pLimit(tasks, cap) {
|
|
25
|
+
const results = new Array(tasks.length);
|
|
26
|
+
let next = 0;
|
|
27
|
+
const workerCount = Math.max(1, Math.min(cap, tasks.length));
|
|
28
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
29
|
+
while (next < tasks.length) {
|
|
30
|
+
const idx = next++;
|
|
31
|
+
results[idx] = await tasks[idx]();
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
await Promise.all(workers);
|
|
35
|
+
return results;
|
|
36
|
+
}
|
package/src/lib/constants.js
CHANGED
|
@@ -8,6 +8,14 @@ export const KIT_SUBDIRS = ['agents', 'skills', 'workflows', 'hooks'];
|
|
|
8
8
|
*/
|
|
9
9
|
export const MANIFEST_FILENAME = '.mk-manifest.json';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Skills that are internal to the kit and must NOT be distributed to end users.
|
|
13
|
+
* Each entry is matched as a full directory segment: `/skills/<name>/`.
|
|
14
|
+
* The trailing `/` in the match pattern prevents false positives on substring names
|
|
15
|
+
* (e.g. `mk-selftest-extended` is NOT matched by `mk-selftest`).
|
|
16
|
+
*/
|
|
17
|
+
export const KIT_INTERNAL_SKILLS = ['mk-selftest'];
|
|
18
|
+
|
|
11
19
|
/**
|
|
12
20
|
* Files/patterns to exclude during copy
|
|
13
21
|
*/
|