@socketsecurity/lib 6.0.8 → 6.0.9
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/CHANGELOG.md +22 -0
- package/dist/ai/route.d.mts +21 -8
- package/dist/ai/route.js +21 -6
- package/dist/ai/spawn.d.mts +32 -0
- package/dist/ai/spawn.js +91 -2
- package/dist/ai/types.d.mts +10 -0
- package/dist/bin/prim.cjs +18797 -13627
- package/dist/bin/resolve.js +1 -1
- package/dist/cache/ttl/store.js +1 -1
- package/dist/compression/brotli.js +1 -1
- package/dist/compression/gzip.js +1 -1
- package/dist/config/layers.d.ts +53 -0
- package/dist/config/layers.js +83 -0
- package/dist/constants/socket.js +1 -1
- package/dist/debug/caller-info.js +1 -1
- package/dist/dlx/binary-cache.js +1 -1
- package/dist/dlx/binary-resolution.js +1 -1
- package/dist/dlx/firewall.js +1 -1
- package/dist/dlx/lockfile.js +1 -1
- package/dist/eco/npm/npm/parse-lockfile.js +1 -1
- package/dist/eco/npm/yarnpkg/yarn/parse-lockfile.js +1 -1
- package/dist/env/rewire.d.ts +5 -3
- package/dist/env/rewire.js +6 -7
- package/dist/env/xdg.d.ts +17 -0
- package/dist/env/xdg.js +21 -1
- package/dist/errors/stack.js +1 -2
- package/dist/external/@npmcli/package-json.js +3455 -4881
- package/dist/external/@yarnpkg/extensions.js +1 -1
- package/dist/external/external-pack.js +1 -1
- package/dist/external/npm-pack.js +29164 -31799
- package/dist/external/tar-fs.js +63 -16
- package/dist/external-tools/jre/detect-platform-arch.js +1 -1
- package/dist/external-tools/manifest.js +1 -1
- package/dist/external-tools/python/asset-names.js +1 -1
- package/dist/external-tools/python/uv-install.d.ts +89 -0
- package/dist/external-tools/python/uv-install.js +165 -0
- package/dist/external-tools/skillspector/from-uv.d.ts +30 -0
- package/dist/external-tools/skillspector/from-uv.js +56 -0
- package/dist/external-tools/skillspector/resolve.d.ts +18 -3
- package/dist/external-tools/skillspector/resolve.js +21 -8
- package/dist/external-tools/skillspector/types.d.ts +3 -1
- package/dist/external-tools/uv/asset-names.d.ts +36 -0
- package/dist/external-tools/uv/asset-names.js +73 -0
- package/dist/external-tools/uv/from-download.d.ts +17 -0
- package/dist/external-tools/uv/from-download.js +50 -0
- package/dist/external-tools/uv/from-path.d.ts +5 -0
- package/dist/external-tools/uv/from-path.js +22 -0
- package/dist/external-tools/uv/from-vfs.d.ts +7 -0
- package/dist/external-tools/uv/from-vfs.js +26 -0
- package/dist/external-tools/uv/resolve.d.ts +25 -0
- package/dist/external-tools/uv/resolve.js +61 -0
- package/dist/external-tools/uv/types.d.ts +24 -0
- package/dist/external-tools/uv/types.js +2 -0
- package/dist/fleet/repo-config.d.ts +53 -0
- package/dist/fleet/repo-config.js +79 -0
- package/dist/fs/allowed-dirs-cache.js +3 -5
- package/dist/fs/copy.d.ts +88 -0
- package/dist/fs/copy.js +89 -0
- package/dist/fs/safe.js +1 -1
- package/dist/git/_internal.js +2 -2
- package/dist/github/refs.js +10 -15
- package/dist/globs/_internal.js +1 -1
- package/dist/http-request/browser.js +1 -1
- package/dist/http-request/checksum-file.js +1 -1
- package/dist/http-request/headers.js +1 -1
- package/dist/integrity.d.ts +125 -78
- package/dist/integrity.js +168 -84
- package/dist/logger/colors.d.ts +1 -2
- package/dist/logger/colors.js +2 -2
- package/dist/logger/symbols-builder.js +7 -8
- package/dist/logger/symbols.js +8 -8
- package/dist/node/module.d.ts +73 -2
- package/dist/node/module.js +97 -12
- package/dist/objects/predicates.js +1 -1
- package/dist/packages/exports.js +2 -2
- package/dist/packages/isolation.js +1 -1
- package/dist/packages/manifest.d.ts +29 -0
- package/dist/packages/manifest.js +38 -2
- package/dist/packages/normalize.js +1 -1
- package/dist/packages/provenance.js +2 -2
- package/dist/packages/specs.js +1 -1
- package/dist/paths/_internal.d.ts +1 -7
- package/dist/paths/_internal.js +9 -15
- package/dist/paths/conversion.js +1 -1
- package/dist/paths/normalize.js +1 -1
- package/dist/paths/predicates.js +2 -1
- package/dist/paths/socket.d.ts +74 -23
- package/dist/paths/socket.js +97 -23
- package/dist/perf/metrics.js +1 -1
- package/dist/perf/report.js +1 -1
- package/dist/regexps/spec.js +1 -1
- package/dist/schema/validate.js +1 -1
- package/dist/secrets/broker.d.ts +35 -0
- package/dist/secrets/broker.js +72 -0
- package/dist/secrets/find.d.ts +6 -4
- package/dist/secrets/find.js +15 -1
- package/dist/secrets/rc.js +1 -1
- package/dist/smol/detect.js +1 -1
- package/dist/smol/http.js +1 -1
- package/dist/smol/https.js +1 -1
- package/dist/smol/manifest.js +1 -1
- package/dist/smol/path.js +1 -1
- package/dist/smol/primordial.js +1 -1
- package/dist/smol/purl.js +1 -1
- package/dist/smol/versions.js +1 -1
- package/dist/smol/vfs.js +1 -1
- package/dist/sorts/_internal.d.ts +1 -2
- package/dist/sorts/_internal.js +2 -6
- package/dist/sorts/semver.js +2 -2
- package/dist/spinner/create-spinner-class.js +1 -1
- package/dist/stdio/progress.js +1 -1
- package/dist/stdio/prompts.d.ts +0 -8
- package/dist/stdio/prompts.js +10 -23
- package/dist/strings/format.js +1 -1
- package/dist/strings/search.js +1 -1
- package/dist/themes/context.d.ts +5 -3
- package/dist/themes/context.js +5 -6
- package/llms.txt +750 -0
- package/package.json +79 -13
package/dist/external/tar-fs.js
CHANGED
|
@@ -121,7 +121,7 @@ var require_fast_fifo = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
121
121
|
}));
|
|
122
122
|
|
|
123
123
|
//#endregion
|
|
124
|
-
//#region node_modules/.pnpm/b4a@1.8.
|
|
124
|
+
//#region node_modules/.pnpm/b4a@1.8.1/node_modules/b4a/index.js
|
|
125
125
|
var require_b4a = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
126
126
|
function isBuffer(value) {
|
|
127
127
|
return _p_BufferIsBuffer(value) || value instanceof Uint8Array;
|
|
@@ -499,13 +499,51 @@ var require_text_decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
499
499
|
}));
|
|
500
500
|
|
|
501
501
|
//#endregion
|
|
502
|
-
//#region node_modules/.pnpm/streamx@2.
|
|
502
|
+
//#region node_modules/.pnpm/streamx@2.27.0/node_modules/streamx/lib/errors.js
|
|
503
|
+
var require_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
504
|
+
module.exports = class StreamError extends Error {
|
|
505
|
+
constructor(msg, code, fn = StreamError) {
|
|
506
|
+
super(msg);
|
|
507
|
+
this.code = code;
|
|
508
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, fn);
|
|
509
|
+
}
|
|
510
|
+
static isStreamDestroyed(err) {
|
|
511
|
+
return err && err.code === "STREAM_DESTROYED";
|
|
512
|
+
}
|
|
513
|
+
static isPrematureClose(err) {
|
|
514
|
+
return err && err.code === "PREMATURE_CLOSE";
|
|
515
|
+
}
|
|
516
|
+
static isAborted(err) {
|
|
517
|
+
return err && err.code === "ABORTED";
|
|
518
|
+
}
|
|
519
|
+
static isBadArgument(err) {
|
|
520
|
+
return err && err.code === "BAD_ARGUMENT";
|
|
521
|
+
}
|
|
522
|
+
get name() {
|
|
523
|
+
return "StreamError";
|
|
524
|
+
}
|
|
525
|
+
static STREAM_DESTROYED() {
|
|
526
|
+
return new StreamError("Stream was destroyed", "STREAM_DESTROYED", StreamError.STREAM_DESTROYED);
|
|
527
|
+
}
|
|
528
|
+
static PREMATURE_CLOSE(msg = "Premature close") {
|
|
529
|
+
return new StreamError(msg, "PREMATURE_CLOSE", StreamError.PREMATURE_CLOSE);
|
|
530
|
+
}
|
|
531
|
+
static ABORTED() {
|
|
532
|
+
return new StreamError("Stream aborted", "ABORTED", StreamError.ABORTED);
|
|
533
|
+
}
|
|
534
|
+
static BAD_ARGUMENT(msg = "Bad argument") {
|
|
535
|
+
return new StreamError(msg, "BAD_ARGUMENT", StreamError.BAD_ARGUMENT);
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
}));
|
|
539
|
+
|
|
540
|
+
//#endregion
|
|
541
|
+
//#region node_modules/.pnpm/streamx@2.27.0/node_modules/streamx/index.js
|
|
503
542
|
var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
504
543
|
const { EventEmitter } = require_default();
|
|
505
|
-
const STREAM_DESTROYED = /* @__PURE__ */ new _p_ErrorCtor("Stream was destroyed");
|
|
506
|
-
const PREMATURE_CLOSE = /* @__PURE__ */ new _p_ErrorCtor("Premature close");
|
|
507
544
|
const FIFO = require_fast_fifo();
|
|
508
545
|
const TextDecoder = require_text_decoder();
|
|
546
|
+
const StreamError = require_errors();
|
|
509
547
|
const qmt = typeof queueMicrotask === "undefined" ? (fn) => global.process.nextTick(fn) : queueMicrotask;
|
|
510
548
|
const OPENING = 1;
|
|
511
549
|
const PREDESTROYING = 2;
|
|
@@ -709,7 +747,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
709
747
|
return (this.stream._duplexState & READ_DONE) !== 0;
|
|
710
748
|
}
|
|
711
749
|
pipe(pipeTo, cb) {
|
|
712
|
-
if (this.pipeTo !== null) throw
|
|
750
|
+
if (this.pipeTo !== null) throw StreamError.BAD_ARGUMENT("Can only pipe to one destination");
|
|
713
751
|
if (typeof cb !== "function") cb = null;
|
|
714
752
|
this.stream._duplexState |= READ_PIPE_DRAINED;
|
|
715
753
|
this.pipeTo = pipeTo;
|
|
@@ -868,14 +906,14 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
868
906
|
if (stream === this.to) {
|
|
869
907
|
this.to = null;
|
|
870
908
|
if (this.from !== null) {
|
|
871
|
-
if ((this.from._duplexState & READ_DONE) === 0 || !this.pipeToFinished) this.from.destroy(this.error ||
|
|
909
|
+
if ((this.from._duplexState & READ_DONE) === 0 || !this.pipeToFinished) this.from.destroy(this.error || StreamError.PREMATURE_CLOSE("Writable stream closed"));
|
|
872
910
|
return;
|
|
873
911
|
}
|
|
874
912
|
}
|
|
875
913
|
if (stream === this.from) {
|
|
876
914
|
this.from = null;
|
|
877
915
|
if (this.to !== null) {
|
|
878
|
-
if ((stream._duplexState & READ_DONE) === 0) this.to.destroy(this.error ||
|
|
916
|
+
if ((stream._duplexState & READ_DONE) === 0) this.to.destroy(this.error || StreamError.PREMATURE_CLOSE("Readable stream closed"));
|
|
879
917
|
return;
|
|
880
918
|
}
|
|
881
919
|
}
|
|
@@ -901,7 +939,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
901
939
|
}
|
|
902
940
|
function afterDestroy(err) {
|
|
903
941
|
const stream = this.stream;
|
|
904
|
-
if (!err && this.error
|
|
942
|
+
if (!err && !StreamError.isStreamDestroyed(this.error)) err = this.error;
|
|
905
943
|
if (err) stream.emit("error", err);
|
|
906
944
|
stream._duplexState |= DESTROYED;
|
|
907
945
|
stream.emit("close");
|
|
@@ -1017,7 +1055,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1017
1055
|
}
|
|
1018
1056
|
destroy(err) {
|
|
1019
1057
|
if ((this._duplexState & DESTROY_STATUS) === 0) {
|
|
1020
|
-
if (!err) err = STREAM_DESTROYED;
|
|
1058
|
+
if (!err) err = StreamError.STREAM_DESTROYED();
|
|
1021
1059
|
this._duplexState = (this._duplexState | DESTROYING) & NON_PRIMARY;
|
|
1022
1060
|
if (this._readableState !== null) {
|
|
1023
1061
|
this._readableState.highWaterMark = 0;
|
|
@@ -1047,6 +1085,15 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1047
1085
|
if (opts.encoding) this.setEncoding(opts.encoding);
|
|
1048
1086
|
}
|
|
1049
1087
|
}
|
|
1088
|
+
static deferred(fn, opts) {
|
|
1089
|
+
const out = new PassThrough(opts);
|
|
1090
|
+
fn().then((src) => {
|
|
1091
|
+
if (src === null) return out.end();
|
|
1092
|
+
if (out.destroying) return;
|
|
1093
|
+
pipeline(src, out, noop);
|
|
1094
|
+
}).catch((err) => out.destroy(err));
|
|
1095
|
+
return out;
|
|
1096
|
+
}
|
|
1050
1097
|
setEncoding(encoding) {
|
|
1051
1098
|
const dec = new TextDecoder(encoding);
|
|
1052
1099
|
const map = this._readableState.map || echo;
|
|
@@ -1165,7 +1212,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1165
1212
|
function ondata(data) {
|
|
1166
1213
|
if (promiseReject === null) return;
|
|
1167
1214
|
if (error) promiseReject(error);
|
|
1168
|
-
else if (data === null && (stream._duplexState & READ_DONE) === 0) promiseReject(STREAM_DESTROYED);
|
|
1215
|
+
else if (data === null && (stream._duplexState & READ_DONE) === 0) promiseReject(StreamError.STREAM_DESTROYED());
|
|
1169
1216
|
else promiseResolve({
|
|
1170
1217
|
value: data,
|
|
1171
1218
|
done: data === null
|
|
@@ -1339,7 +1386,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1339
1386
|
function pipeline(stream, ...streams) {
|
|
1340
1387
|
const all = _p_ArrayIsArray(stream) ? [...stream, ...streams] : [stream, ...streams];
|
|
1341
1388
|
const done = all.length && typeof all[all.length - 1] === "function" ? all.pop() : null;
|
|
1342
|
-
if (all.length < 2) throw
|
|
1389
|
+
if (all.length < 2) throw StreamError.BAD_ARGUMENT("Pipeline requires at least 2 streams");
|
|
1343
1390
|
let src = all[0];
|
|
1344
1391
|
let dest = null;
|
|
1345
1392
|
let error = null;
|
|
@@ -1362,15 +1409,15 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1362
1409
|
fin = true;
|
|
1363
1410
|
if (!autoDestroy) done(error);
|
|
1364
1411
|
});
|
|
1365
|
-
if (autoDestroy) dest.on("close", () => done(error || (fin ? null : PREMATURE_CLOSE)));
|
|
1412
|
+
if (autoDestroy) dest.on("close", () => done(error || (fin ? null : StreamError.PREMATURE_CLOSE())));
|
|
1366
1413
|
}
|
|
1367
1414
|
return dest;
|
|
1368
1415
|
function errorHandle(s, rd, wr, onerror) {
|
|
1369
1416
|
s.on("error", onerror);
|
|
1370
1417
|
s.on("close", onclose);
|
|
1371
1418
|
function onclose() {
|
|
1372
|
-
if (rd && s._readableState && !s._readableState.ended) return onerror(PREMATURE_CLOSE);
|
|
1373
|
-
if (wr && s._writableState && !s._writableState.ended) return onerror(PREMATURE_CLOSE);
|
|
1419
|
+
if (rd && s._readableState && !s._readableState.ended) return onerror(StreamError.PREMATURE_CLOSE());
|
|
1420
|
+
if (wr && s._writableState && !s._writableState.ended) return onerror(StreamError.PREMATURE_CLOSE());
|
|
1374
1421
|
}
|
|
1375
1422
|
}
|
|
1376
1423
|
function onerror(err) {
|
|
@@ -1402,7 +1449,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1402
1449
|
}
|
|
1403
1450
|
function getStreamError(stream, opts = {}) {
|
|
1404
1451
|
const err = stream._readableState && stream._readableState.error || stream._writableState && stream._writableState.error;
|
|
1405
|
-
return !opts.all && err
|
|
1452
|
+
return !opts.all && StreamError.isStreamDestroyed(err) ? null : err;
|
|
1406
1453
|
}
|
|
1407
1454
|
function isReadStreamx(stream) {
|
|
1408
1455
|
return isStreamx(stream) && stream.readable;
|
|
@@ -1418,7 +1465,7 @@ var require_streamx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1418
1465
|
}
|
|
1419
1466
|
function noop() {}
|
|
1420
1467
|
function abort() {
|
|
1421
|
-
this.destroy(
|
|
1468
|
+
this.destroy(StreamError.ABORTED());
|
|
1422
1469
|
}
|
|
1423
1470
|
function isWritev(s) {
|
|
1424
1471
|
return s._writev !== Writable.prototype._writev && s._writev !== Duplex.prototype._writev;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/* Socket Lib - Built with rolldown */
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_runtime = require('../../_virtual/_rolldown/runtime.js');
|
|
5
|
-
const require_constants_platform = require('../../constants/platform.js');
|
|
6
5
|
const require_primordials_object = require('../../primordials/object.js');
|
|
6
|
+
const require_constants_platform = require('../../constants/platform.js');
|
|
7
7
|
let node_process = require("node:process");
|
|
8
8
|
node_process = require_runtime.__toESM(node_process);
|
|
9
9
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/* Socket Lib - Built with rolldown */
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_primordials_error = require('../primordials/error.js');
|
|
5
|
-
const require_integrity = require('../integrity.js');
|
|
6
5
|
const require_primordials_object = require('../primordials/object.js');
|
|
7
6
|
const require_primordials_string = require('../primordials/string.js');
|
|
7
|
+
const require_integrity = require('../integrity.js');
|
|
8
8
|
const require_primordials_array = require('../primordials/array.js');
|
|
9
9
|
const require_fs_read_json = require('../fs/read-json.js');
|
|
10
10
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/* Socket Lib - Built with rolldown */
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_runtime = require('../../_virtual/_rolldown/runtime.js');
|
|
5
|
-
const require_constants_platform = require('../../constants/platform.js');
|
|
6
5
|
const require_primordials_object = require('../../primordials/object.js');
|
|
6
|
+
const require_constants_platform = require('../../constants/platform.js');
|
|
7
7
|
let node_process = require("node:process");
|
|
8
8
|
node_process = require_runtime.__toESM(node_process);
|
|
9
9
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Uv project install helpers — the locked-source-of-truth half of the
|
|
3
|
+
* "uv project + dlx materialize" model.
|
|
4
|
+
* uv (Astral's Python package manager) drives a uv PROJECT — a directory with
|
|
5
|
+
* `pyproject.toml` + `uv.lock` (+ optional `[tool.uv] exclude-newer`). The
|
|
6
|
+
* lock manifests every transitive version, so the project is the most
|
|
7
|
+
* locked-down, most-version-pinned form a Python tool install can take.
|
|
8
|
+
* Two entry points, used together:
|
|
9
|
+
*
|
|
10
|
+
* 1. `uvSyncProject` — `uv sync --locked --project <dir>`. Installs the lock's
|
|
11
|
+
* exact closure into the project's own `.venv` and FAILS if `uv.lock` is
|
|
12
|
+
* out of date vs `pyproject.toml` (the `--locked` gate). This is the
|
|
13
|
+
* verification-grade install: it proves the lock resolves.
|
|
14
|
+
* 2. `uvExportMaterialize` — `uv export --locked` → a flat, hash-pinned
|
|
15
|
+
* requirements list, then `uv pip install --target <dir>` into a
|
|
16
|
+
* content-addressed dlx dir (no venv → no symlinks / absolute `home=`, so
|
|
17
|
+
* the result is relocatable + SEA-VFS-embeddable). Mirrors
|
|
18
|
+
* `downloadPipPackage`'s lock-guarded, idempotent shape. Both take an
|
|
19
|
+
* explicit `uvBin` (typically `resolveUv().path`) and never mutate a
|
|
20
|
+
* shared interpreter — the project venv and the dlx target are
|
|
21
|
+
* self-contained.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Export a uv project's locked closure to a flat requirements list, then
|
|
25
|
+
* `uv pip install --target` it into a content-addressed dlx dir. The dlx dir
|
|
26
|
+
* holds plain files (no venv), so it is relocatable and embeddable in a smol
|
|
27
|
+
* binary's VFS — the bundle-safe analog of `uvSyncProject`'s `.venv`.
|
|
28
|
+
*
|
|
29
|
+
* Lock-guarded + idempotent (reuses `pip-install`'s `isAlreadyInstalled` /
|
|
30
|
+
* `isStaleLock`): a non-empty target dir short-circuits, and concurrent callers
|
|
31
|
+
* serialize on a `.installing` sentinel one level up from the target. Throws on
|
|
32
|
+
* a failed uv command or if the lock can't be acquired after MAX_RETRIES.
|
|
33
|
+
*/
|
|
34
|
+
export declare function uvExportMaterialize(options: UvExportMaterializeOptions, retryCount?: number): Promise<UvExportMaterializeResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Content-addressed dlx dir for a uv project's materialized closure:
|
|
37
|
+
* `~/.socket/_dlx/<cacheKey(projectDir)>/site-packages`. Keyed on the project
|
|
38
|
+
* dir so each project gets an isolated target; the analog of `pipPackageDir`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function uvProjectTargetDir(projectDir: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Run `uv sync --locked` against a uv project. Installs the lock's exact
|
|
43
|
+
* dependency closure into the project's `.venv`; the `--locked` flag turns a
|
|
44
|
+
* lock-vs-manifest drift into a hard failure (uv exits non-zero) rather than a
|
|
45
|
+
* silent re-resolution — this is what makes it verification-grade. Throws when
|
|
46
|
+
* uv exits non-zero (drift, missing lock, or a resolution failure).
|
|
47
|
+
*/
|
|
48
|
+
export declare function uvSyncProject(options: UvSyncProjectOptions): Promise<void>;
|
|
49
|
+
export interface UvSyncProjectOptions {
|
|
50
|
+
/**
|
|
51
|
+
* Absolute path to the `uv` executable (typically `resolveUv().path`).
|
|
52
|
+
*/
|
|
53
|
+
readonly uvBin: string;
|
|
54
|
+
/**
|
|
55
|
+
* Absolute path to the uv project dir (holds `pyproject.toml` + `uv.lock`).
|
|
56
|
+
*/
|
|
57
|
+
readonly projectDir: string;
|
|
58
|
+
/**
|
|
59
|
+
* Default true — pass `--locked` so a lock-vs-manifest drift fails hard.
|
|
60
|
+
* Set false ONLY to bootstrap/refresh a lock (never in a verify path).
|
|
61
|
+
*/
|
|
62
|
+
readonly locked?: boolean | undefined;
|
|
63
|
+
}
|
|
64
|
+
export interface UvExportMaterializeOptions {
|
|
65
|
+
/**
|
|
66
|
+
* Absolute path to the `uv` executable.
|
|
67
|
+
*/
|
|
68
|
+
readonly uvBin: string;
|
|
69
|
+
/**
|
|
70
|
+
* Absolute path to the uv project dir to export from.
|
|
71
|
+
*/
|
|
72
|
+
readonly projectDir: string;
|
|
73
|
+
/**
|
|
74
|
+
* Override the content-addressed target dir. Defaults to
|
|
75
|
+
* `uvProjectTargetDir(projectDir)`.
|
|
76
|
+
*/
|
|
77
|
+
readonly targetDir?: string | undefined;
|
|
78
|
+
}
|
|
79
|
+
export interface UvExportMaterializeResult {
|
|
80
|
+
/**
|
|
81
|
+
* `true` when this call ran uv; `false` when an existing install was reused.
|
|
82
|
+
*/
|
|
83
|
+
readonly installed: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Directory the closure was installed into. Put this on `PYTHONPATH` to run
|
|
86
|
+
* the tool: `python -m <module>`.
|
|
87
|
+
*/
|
|
88
|
+
readonly targetDir: string;
|
|
89
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Socket Lib - Built with rolldown */
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
const require_runtime = require('../../_virtual/_rolldown/runtime.js');
|
|
5
|
+
const require_constants_platform = require('../../constants/platform.js');
|
|
6
|
+
const require_process_spawn_child = require('../../process/spawn/child.js');
|
|
7
|
+
const require_paths_socket = require('../../paths/socket.js');
|
|
8
|
+
const require_fs_safe = require('../../fs/safe.js');
|
|
9
|
+
const require_dlx_cache = require('../../dlx/cache.js');
|
|
10
|
+
const require_external_tools_python_pip_install = require('./pip-install.js');
|
|
11
|
+
let node_fs = require("node:fs");
|
|
12
|
+
let node_process = require("node:process");
|
|
13
|
+
node_process = require_runtime.__toESM(node_process);
|
|
14
|
+
let node_path = require("node:path");
|
|
15
|
+
node_path = require_runtime.__toESM(node_path);
|
|
16
|
+
|
|
17
|
+
//#region src/external-tools/python/uv-install.ts
|
|
18
|
+
/**
|
|
19
|
+
* @file Uv project install helpers — the locked-source-of-truth half of the
|
|
20
|
+
* "uv project + dlx materialize" model.
|
|
21
|
+
* uv (Astral's Python package manager) drives a uv PROJECT — a directory with
|
|
22
|
+
* `pyproject.toml` + `uv.lock` (+ optional `[tool.uv] exclude-newer`). The
|
|
23
|
+
* lock manifests every transitive version, so the project is the most
|
|
24
|
+
* locked-down, most-version-pinned form a Python tool install can take.
|
|
25
|
+
* Two entry points, used together:
|
|
26
|
+
*
|
|
27
|
+
* 1. `uvSyncProject` — `uv sync --locked --project <dir>`. Installs the lock's
|
|
28
|
+
* exact closure into the project's own `.venv` and FAILS if `uv.lock` is
|
|
29
|
+
* out of date vs `pyproject.toml` (the `--locked` gate). This is the
|
|
30
|
+
* verification-grade install: it proves the lock resolves.
|
|
31
|
+
* 2. `uvExportMaterialize` — `uv export --locked` → a flat, hash-pinned
|
|
32
|
+
* requirements list, then `uv pip install --target <dir>` into a
|
|
33
|
+
* content-addressed dlx dir (no venv → no symlinks / absolute `home=`, so
|
|
34
|
+
* the result is relocatable + SEA-VFS-embeddable). Mirrors
|
|
35
|
+
* `downloadPipPackage`'s lock-guarded, idempotent shape. Both take an
|
|
36
|
+
* explicit `uvBin` (typically `resolveUv().path`) and never mutate a
|
|
37
|
+
* shared interpreter — the project venv and the dlx target are
|
|
38
|
+
* self-contained.
|
|
39
|
+
*/
|
|
40
|
+
const MAX_RETRIES = 3;
|
|
41
|
+
const WAIT_TICKS = 30;
|
|
42
|
+
/**
|
|
43
|
+
* Export a uv project's locked closure to a flat requirements list, then
|
|
44
|
+
* `uv pip install --target` it into a content-addressed dlx dir. The dlx dir
|
|
45
|
+
* holds plain files (no venv), so it is relocatable and embeddable in a smol
|
|
46
|
+
* binary's VFS — the bundle-safe analog of `uvSyncProject`'s `.venv`.
|
|
47
|
+
*
|
|
48
|
+
* Lock-guarded + idempotent (reuses `pip-install`'s `isAlreadyInstalled` /
|
|
49
|
+
* `isStaleLock`): a non-empty target dir short-circuits, and concurrent callers
|
|
50
|
+
* serialize on a `.installing` sentinel one level up from the target. Throws on
|
|
51
|
+
* a failed uv command or if the lock can't be acquired after MAX_RETRIES.
|
|
52
|
+
*/
|
|
53
|
+
async function uvExportMaterialize(options, retryCount = 0) {
|
|
54
|
+
const opts = {
|
|
55
|
+
__proto__: null,
|
|
56
|
+
...options
|
|
57
|
+
};
|
|
58
|
+
const { projectDir, uvBin } = opts;
|
|
59
|
+
const targetDir = opts.targetDir ?? uvProjectTargetDir(projectDir);
|
|
60
|
+
if (retryCount >= MAX_RETRIES) throw new Error(`uvExportMaterialize: could not acquire install lock after ${MAX_RETRIES} retries for ${targetDir}; a peer may be stuck or the lock is stale — remove it and retry`);
|
|
61
|
+
if (await require_external_tools_python_pip_install.isAlreadyInstalled(targetDir)) return {
|
|
62
|
+
installed: false,
|
|
63
|
+
targetDir
|
|
64
|
+
};
|
|
65
|
+
const lockDir = node_path.default.dirname(targetDir);
|
|
66
|
+
await require_fs_safe.safeMkdir(lockDir, { recursive: true });
|
|
67
|
+
const lockFile = node_path.default.join(lockDir, ".installing");
|
|
68
|
+
try {
|
|
69
|
+
await node_fs.promises.writeFile(lockFile, node_process.default.pid.toString(), { flag: "wx" });
|
|
70
|
+
} catch (e) {
|
|
71
|
+
if (e.code !== "EEXIST") throw e;
|
|
72
|
+
let stale = false;
|
|
73
|
+
try {
|
|
74
|
+
stale = require_external_tools_python_pip_install.isStaleLock(Number.parseInt((await node_fs.promises.readFile(lockFile, "utf8")).trim(), 10));
|
|
75
|
+
} catch {
|
|
76
|
+
stale = true;
|
|
77
|
+
}
|
|
78
|
+
if (stale) {
|
|
79
|
+
await require_fs_safe.safeDelete(lockFile, { force: true });
|
|
80
|
+
return uvExportMaterialize(options, retryCount + 1);
|
|
81
|
+
}
|
|
82
|
+
for (let i = 0; i < WAIT_TICKS; i += 1) {
|
|
83
|
+
await new Promise((resolve) => {
|
|
84
|
+
setTimeout(resolve, 1e3);
|
|
85
|
+
});
|
|
86
|
+
if (await require_external_tools_python_pip_install.isAlreadyInstalled(targetDir)) return {
|
|
87
|
+
installed: false,
|
|
88
|
+
targetDir
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return uvExportMaterialize(options, retryCount + 1);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
await require_fs_safe.safeMkdir(targetDir, { recursive: true });
|
|
95
|
+
const requirementsPath = node_path.default.join(lockDir, "requirements.locked.txt");
|
|
96
|
+
await require_process_spawn_child.spawn(uvBin, [
|
|
97
|
+
"export",
|
|
98
|
+
"--locked",
|
|
99
|
+
"--no-emit-project",
|
|
100
|
+
"--no-dev",
|
|
101
|
+
"--project",
|
|
102
|
+
projectDir,
|
|
103
|
+
"--output-file",
|
|
104
|
+
requirementsPath
|
|
105
|
+
], {
|
|
106
|
+
shell: require_constants_platform.WIN32,
|
|
107
|
+
stdio: "inherit"
|
|
108
|
+
});
|
|
109
|
+
await require_process_spawn_child.spawn(uvBin, [
|
|
110
|
+
"pip",
|
|
111
|
+
"install",
|
|
112
|
+
"--target",
|
|
113
|
+
targetDir,
|
|
114
|
+
"--requirement",
|
|
115
|
+
requirementsPath
|
|
116
|
+
], {
|
|
117
|
+
shell: require_constants_platform.WIN32,
|
|
118
|
+
stdio: "inherit"
|
|
119
|
+
});
|
|
120
|
+
await require_fs_safe.safeDelete(requirementsPath, { force: true });
|
|
121
|
+
if (!await require_external_tools_python_pip_install.isAlreadyInstalled(targetDir)) throw new Error(`uvExportMaterialize: uv pip install --target ${targetDir} reported success but the target is still empty`);
|
|
122
|
+
return {
|
|
123
|
+
installed: true,
|
|
124
|
+
targetDir
|
|
125
|
+
};
|
|
126
|
+
} finally {
|
|
127
|
+
await require_fs_safe.safeDelete(lockFile, { force: true });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Content-addressed dlx dir for a uv project's materialized closure:
|
|
132
|
+
* `~/.socket/_dlx/<cacheKey(projectDir)>/site-packages`. Keyed on the project
|
|
133
|
+
* dir so each project gets an isolated target; the analog of `pipPackageDir`.
|
|
134
|
+
*/
|
|
135
|
+
function uvProjectTargetDir(projectDir) {
|
|
136
|
+
return node_path.default.join(require_paths_socket.getSocketDlxDir(), require_dlx_cache.generateCacheKey(projectDir), "site-packages");
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Run `uv sync --locked` against a uv project. Installs the lock's exact
|
|
140
|
+
* dependency closure into the project's `.venv`; the `--locked` flag turns a
|
|
141
|
+
* lock-vs-manifest drift into a hard failure (uv exits non-zero) rather than a
|
|
142
|
+
* silent re-resolution — this is what makes it verification-grade. Throws when
|
|
143
|
+
* uv exits non-zero (drift, missing lock, or a resolution failure).
|
|
144
|
+
*/
|
|
145
|
+
async function uvSyncProject(options) {
|
|
146
|
+
const opts = {
|
|
147
|
+
__proto__: null,
|
|
148
|
+
...options
|
|
149
|
+
};
|
|
150
|
+
const { projectDir, uvBin } = opts;
|
|
151
|
+
await require_process_spawn_child.spawn(uvBin, [
|
|
152
|
+
"sync",
|
|
153
|
+
...opts.locked === false ? [] : ["--locked"],
|
|
154
|
+
"--project",
|
|
155
|
+
projectDir
|
|
156
|
+
], {
|
|
157
|
+
shell: require_constants_platform.WIN32,
|
|
158
|
+
stdio: "inherit"
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
exports.uvExportMaterialize = uvExportMaterialize;
|
|
164
|
+
exports.uvProjectTargetDir = uvProjectTargetDir;
|
|
165
|
+
exports.uvSyncProject = uvSyncProject;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file `skillspectorFromUv()` — locked-uv-project tier of SkillSpector
|
|
3
|
+
* resolution. Given a uv project dir (a `pyproject.toml` + `uv.lock` that pin
|
|
4
|
+
* the upstream git SHA + its full transitive closure) and a resolved `uv`
|
|
5
|
+
* binary, runs `uv sync --locked` to install that exact closure into the
|
|
6
|
+
* project's `.venv` and returns the `skillspector` entry point. This is the
|
|
7
|
+
* most locked-down tier — every dependency version is manifested in uv.lock,
|
|
8
|
+
* and `--locked` hard-fails on lock drift (vs. `from-dlx`'s pip-from-git-SHA
|
|
9
|
+
* venv, which re-resolves the closure freshly). Returns `undefined` when:
|
|
10
|
+
*
|
|
11
|
+
* - No project dir / uv binary is supplied (the caller didn't opt in).
|
|
12
|
+
* - The project files are absent, or `uv sync --locked` fails (lock drift, no
|
|
13
|
+
* network, missing Python). Idempotent: a second call hits the synced venv
|
|
14
|
+
* (`uv sync` is a no-op when the venv already matches the lock).
|
|
15
|
+
*/
|
|
16
|
+
import type { ResolvedSkillSpector } from './types';
|
|
17
|
+
export interface SkillSpectorFromUvOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Absolute path to the `uv` executable (typically `resolveUv().path`).
|
|
20
|
+
*/
|
|
21
|
+
readonly uvBin: string;
|
|
22
|
+
/**
|
|
23
|
+
* Absolute path to the SkillSpector uv project dir (holds `pyproject.toml` +
|
|
24
|
+
* `uv.lock`). The fleet ships this under
|
|
25
|
+
* `setup-security-tools/skillspector/`.
|
|
26
|
+
*/
|
|
27
|
+
readonly projectDir: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function skillspectorFromUv(options: SkillSpectorFromUvOptions): Promise<ResolvedSkillSpector | undefined>;
|
|
30
|
+
export declare function venvEntryPoint(projectDir: string): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Socket Lib - Built with rolldown */
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
const require_runtime = require('../../_virtual/_rolldown/runtime.js');
|
|
5
|
+
const require_external_tools_python_uv_install = require('../python/uv-install.js');
|
|
6
|
+
let node_fs = require("node:fs");
|
|
7
|
+
let node_process = require("node:process");
|
|
8
|
+
node_process = require_runtime.__toESM(node_process);
|
|
9
|
+
let node_path = require("node:path");
|
|
10
|
+
node_path = require_runtime.__toESM(node_path);
|
|
11
|
+
|
|
12
|
+
//#region src/external-tools/skillspector/from-uv.ts
|
|
13
|
+
/**
|
|
14
|
+
* @file `skillspectorFromUv()` — locked-uv-project tier of SkillSpector
|
|
15
|
+
* resolution. Given a uv project dir (a `pyproject.toml` + `uv.lock` that pin
|
|
16
|
+
* the upstream git SHA + its full transitive closure) and a resolved `uv`
|
|
17
|
+
* binary, runs `uv sync --locked` to install that exact closure into the
|
|
18
|
+
* project's `.venv` and returns the `skillspector` entry point. This is the
|
|
19
|
+
* most locked-down tier — every dependency version is manifested in uv.lock,
|
|
20
|
+
* and `--locked` hard-fails on lock drift (vs. `from-dlx`'s pip-from-git-SHA
|
|
21
|
+
* venv, which re-resolves the closure freshly). Returns `undefined` when:
|
|
22
|
+
*
|
|
23
|
+
* - No project dir / uv binary is supplied (the caller didn't opt in).
|
|
24
|
+
* - The project files are absent, or `uv sync --locked` fails (lock drift, no
|
|
25
|
+
* network, missing Python). Idempotent: a second call hits the synced venv
|
|
26
|
+
* (`uv sync` is a no-op when the venv already matches the lock).
|
|
27
|
+
*/
|
|
28
|
+
async function skillspectorFromUv(options) {
|
|
29
|
+
const { projectDir, uvBin } = {
|
|
30
|
+
__proto__: null,
|
|
31
|
+
...options
|
|
32
|
+
};
|
|
33
|
+
if (!projectDir || !uvBin) return;
|
|
34
|
+
if (!(0, node_fs.existsSync)(node_path.default.join(projectDir, "pyproject.toml")) || !(0, node_fs.existsSync)(node_path.default.join(projectDir, "uv.lock"))) return;
|
|
35
|
+
try {
|
|
36
|
+
await require_external_tools_python_uv_install.uvSyncProject({
|
|
37
|
+
projectDir,
|
|
38
|
+
uvBin
|
|
39
|
+
});
|
|
40
|
+
} catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const entry = venvEntryPoint(projectDir);
|
|
44
|
+
if (!(0, node_fs.existsSync)(entry)) return;
|
|
45
|
+
return {
|
|
46
|
+
path: entry,
|
|
47
|
+
source: "uv"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function venvEntryPoint(projectDir) {
|
|
51
|
+
return node_process.default.platform === "win32" ? node_path.default.join(projectDir, ".venv", "Scripts", "skillspector.exe") : node_path.default.join(projectDir, ".venv", "bin", "skillspector");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
exports.skillspectorFromUv = skillspectorFromUv;
|
|
56
|
+
exports.venvEntryPoint = venvEntryPoint;
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
* 1. VFS — smol binary's embedded skillspector (if packed)
|
|
6
6
|
* 2. PATH — `which skillspector` (pipx-installed binaries land here too; the
|
|
7
7
|
* source field distinguishes `'pipx'` vs `'path'`)
|
|
8
|
-
* 3.
|
|
8
|
+
* 3. UV-project — `uv sync --locked` against a uv project (the most locked-down
|
|
9
|
+
* tier; every transitive version pinned in uv.lock). Only runs when
|
|
10
|
+
* `uvProjectDir` + `uvBin` are supplied.
|
|
11
|
+
* 4. DLX-venv — `~/.socket/_dlx/skillspector/<sha>/` with the pinned SHA (the
|
|
12
|
+
* pip-from-git-SHA fallback when no uv project is available). Returns
|
|
9
13
|
* `undefined` when all enabled sources miss. Memoized per
|
|
10
|
-
* sha+cacheDir+localOnly tuple.
|
|
14
|
+
* sha+cacheDir+uvProjectDir+localOnly tuple.
|
|
11
15
|
*/
|
|
12
16
|
import type { ResolvedSkillSpector } from './types';
|
|
13
17
|
export interface ResolveSkillSpectorOptions {
|
|
@@ -17,9 +21,20 @@ export interface ResolveSkillSpectorOptions {
|
|
|
17
21
|
*/
|
|
18
22
|
readonly sha?: string | undefined;
|
|
19
23
|
/**
|
|
20
|
-
*
|
|
24
|
+
* DLX cache override. Defaults to `~/.socket/_dlx/skillspector/<sha>`.
|
|
21
25
|
*/
|
|
22
26
|
readonly cacheDir?: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* UV-project tier: absolute path to a uv project dir (a `pyproject.toml` +
|
|
29
|
+
* `uv.lock` pinning the SHA + its closure). When set together with `uvBin`,
|
|
30
|
+
* the locked-uv tier runs ahead of the DLX-venv tier.
|
|
31
|
+
*/
|
|
32
|
+
readonly uvProjectDir?: string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* UV-project tier: absolute path to the `uv` executable
|
|
35
|
+
* (typically `resolveUv().path`). Required to run the locked-uv tier.
|
|
36
|
+
*/
|
|
37
|
+
readonly uvBin?: string | undefined;
|
|
23
38
|
/**
|
|
24
39
|
* When true, only the VFS + PATH tiers run. Use for check-mode invocations
|
|
25
40
|
* that want to fail-fast if the tool isn't already installed.
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4
4
|
const require_primordials_map_set = require('../../primordials/map-set.js');
|
|
5
5
|
const require_external_tools_skillspector_from_dlx = require('./from-dlx.js');
|
|
6
6
|
const require_external_tools_skillspector_from_path = require('./from-path.js');
|
|
7
|
+
const require_external_tools_skillspector_from_uv = require('./from-uv.js');
|
|
7
8
|
const require_external_tools_skillspector_from_vfs = require('./from-vfs.js');
|
|
8
9
|
|
|
9
10
|
//#region src/external-tools/skillspector/resolve.ts
|
|
@@ -14,20 +15,24 @@ const require_external_tools_skillspector_from_vfs = require('./from-vfs.js');
|
|
|
14
15
|
* 1. VFS — smol binary's embedded skillspector (if packed)
|
|
15
16
|
* 2. PATH — `which skillspector` (pipx-installed binaries land here too; the
|
|
16
17
|
* source field distinguishes `'pipx'` vs `'path'`)
|
|
17
|
-
* 3.
|
|
18
|
+
* 3. UV-project — `uv sync --locked` against a uv project (the most locked-down
|
|
19
|
+
* tier; every transitive version pinned in uv.lock). Only runs when
|
|
20
|
+
* `uvProjectDir` + `uvBin` are supplied.
|
|
21
|
+
* 4. DLX-venv — `~/.socket/_dlx/skillspector/<sha>/` with the pinned SHA (the
|
|
22
|
+
* pip-from-git-SHA fallback when no uv project is available). Returns
|
|
18
23
|
* `undefined` when all enabled sources miss. Memoized per
|
|
19
|
-
* sha+cacheDir+localOnly tuple.
|
|
24
|
+
* sha+cacheDir+uvProjectDir+localOnly tuple.
|
|
20
25
|
*/
|
|
21
26
|
const resolutionCache = new require_primordials_map_set.MapCtor();
|
|
22
27
|
function cacheKey(options) {
|
|
23
|
-
|
|
28
|
+
const opts = {
|
|
24
29
|
__proto__: null,
|
|
25
30
|
...options
|
|
26
31
|
};
|
|
27
|
-
return `${
|
|
32
|
+
return `${opts.sha ?? ""}|${opts.cacheDir ?? ""}|${opts.uvProjectDir ?? ""}|${opts.localOnly ? "local" : "full"}`;
|
|
28
33
|
}
|
|
29
34
|
async function doResolveSkillSpector(options) {
|
|
30
|
-
|
|
35
|
+
const opts = {
|
|
31
36
|
__proto__: null,
|
|
32
37
|
...options
|
|
33
38
|
};
|
|
@@ -37,10 +42,18 @@ async function doResolveSkillSpector(options) {
|
|
|
37
42
|
/* c8 ignore stop */
|
|
38
43
|
const fromPath = await require_external_tools_skillspector_from_path.skillspectorFromPath();
|
|
39
44
|
if (fromPath) return fromPath;
|
|
40
|
-
if (
|
|
45
|
+
if (opts.localOnly) return;
|
|
46
|
+
if (opts.uvProjectDir && opts.uvBin) {
|
|
47
|
+
const fromUv = await require_external_tools_skillspector_from_uv.skillspectorFromUv({
|
|
48
|
+
projectDir: opts.uvProjectDir,
|
|
49
|
+
uvBin: opts.uvBin
|
|
50
|
+
});
|
|
51
|
+
if (fromUv) return fromUv;
|
|
52
|
+
}
|
|
53
|
+
if (!opts.sha) return;
|
|
41
54
|
return require_external_tools_skillspector_from_dlx.skillspectorFromDlx({
|
|
42
|
-
sha:
|
|
43
|
-
cacheDir:
|
|
55
|
+
sha: opts.sha,
|
|
56
|
+
cacheDir: opts.cacheDir
|
|
44
57
|
});
|
|
45
58
|
}
|
|
46
59
|
/**
|