library-skills 0.0.7 → 0.0.10
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/package.json +1 -1
- package/ts/dist/{chunk-DKDHRFD4.js → chunk-JRJ32CKR.js} +3 -0
- package/ts/dist/cli.js +281 -44
- package/ts/dist/deps.cjs +29 -6
- package/ts/dist/deps.d.cts +3 -1
- package/ts/dist/deps.d.ts +3 -1
- package/ts/dist/deps.js +28 -7
- package/ts/dist/python-env.cjs +211 -33
- package/ts/dist/python-env.js +205 -27
- package/ts/dist/scanner.cjs +3 -0
- package/ts/dist/scanner.js +1 -1
- package/ts/dist/cli.d.ts +0 -94
package/package.json
CHANGED
|
@@ -100,6 +100,9 @@ function iterNodePackageRoots(nodeModules) {
|
|
|
100
100
|
if (!isDirectory(fullPath)) {
|
|
101
101
|
continue;
|
|
102
102
|
}
|
|
103
|
+
if (entry.startsWith(".")) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
103
106
|
if (entry.startsWith("@")) {
|
|
104
107
|
for (const scopedEntry of readdirSync(fullPath).sort()) {
|
|
105
108
|
const scopedPath = join(fullPath, scopedEntry);
|
package/ts/dist/cli.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// ts/src/cli.ts
|
|
4
4
|
import checkbox from "@inquirer/checkbox";
|
|
5
5
|
import { Command } from "commander";
|
|
6
|
-
import { realpathSync as realpathSync2, statSync as
|
|
7
|
-
import { isAbsolute as isAbsolute3, relative as
|
|
6
|
+
import { realpathSync as realpathSync2, statSync as statSync5 } from "fs";
|
|
7
|
+
import { isAbsolute as isAbsolute3, relative as relative4, resolve as resolve5 } from "path";
|
|
8
8
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9
9
|
|
|
10
10
|
// ts/src/deps.ts
|
|
@@ -114,6 +114,9 @@ function iterNodePackageRoots(nodeModules) {
|
|
|
114
114
|
if (!isDirectory(fullPath)) {
|
|
115
115
|
continue;
|
|
116
116
|
}
|
|
117
|
+
if (entry.startsWith(".")) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
117
120
|
if (entry.startsWith("@")) {
|
|
118
121
|
for (const scopedEntry of readdirSync(fullPath).sort()) {
|
|
119
122
|
const scopedPath = join(fullPath, scopedEntry);
|
|
@@ -468,13 +471,30 @@ function getPythonTopLevelDeps(projectRoot) {
|
|
|
468
471
|
if (!existsSync2(pyproject)) {
|
|
469
472
|
return null;
|
|
470
473
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
474
|
+
return getPythonTopLevelDepsFromFiles([pyproject]);
|
|
475
|
+
}
|
|
476
|
+
function getPythonTopLevelDepsFromFiles(pyprojects) {
|
|
477
|
+
if (pyprojects.length === 0) {
|
|
475
478
|
return null;
|
|
476
479
|
}
|
|
477
480
|
const deps = /* @__PURE__ */ new Set();
|
|
481
|
+
let found = false;
|
|
482
|
+
for (const pyproject of pyprojects) {
|
|
483
|
+
if (!existsSync2(pyproject)) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
let data;
|
|
487
|
+
try {
|
|
488
|
+
data = parse2(readFileSync2(pyproject, "utf8"));
|
|
489
|
+
} catch {
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
found = true;
|
|
493
|
+
extractPythonTopLevelDeps(data, deps);
|
|
494
|
+
}
|
|
495
|
+
return found ? deps : null;
|
|
496
|
+
}
|
|
497
|
+
function extractPythonTopLevelDeps(data, deps) {
|
|
478
498
|
const project = data["project"];
|
|
479
499
|
if (isRecord2(project)) {
|
|
480
500
|
const dependencies = project["dependencies"];
|
|
@@ -496,7 +516,6 @@ function getPythonTopLevelDeps(projectRoot) {
|
|
|
496
516
|
extractDepsFromDependencyGroup(groupName, dependencyGroups, deps, /* @__PURE__ */ new Set());
|
|
497
517
|
}
|
|
498
518
|
}
|
|
499
|
-
return deps;
|
|
500
519
|
}
|
|
501
520
|
function getNodeTopLevelDeps(projectRoot) {
|
|
502
521
|
const packageJson = join2(projectRoot, "package.json");
|
|
@@ -539,12 +558,15 @@ function getTopLevelDeps(projectRoot) {
|
|
|
539
558
|
}
|
|
540
559
|
return new Set(dependencySets.flatMap((deps) => [...deps]));
|
|
541
560
|
}
|
|
561
|
+
function getWorkspaceTopLevelDeps(pyprojects) {
|
|
562
|
+
return getPythonTopLevelDepsFromFiles(pyprojects);
|
|
563
|
+
}
|
|
542
564
|
function extractDepsFromSpecs(depSpecs, deps) {
|
|
543
565
|
for (const depSpec of depSpecs) {
|
|
544
566
|
if (typeof depSpec !== "string") {
|
|
545
567
|
continue;
|
|
546
568
|
}
|
|
547
|
-
const packageName = depSpec.split(/[
|
|
569
|
+
const packageName = depSpec.split(/[~>=<![\];,\s]/)[0]?.trim();
|
|
548
570
|
if (packageName && !packageName.startsWith("#")) {
|
|
549
571
|
deps.add(normalizePackageName(packageName));
|
|
550
572
|
}
|
|
@@ -688,17 +710,201 @@ function isDirectory2(path) {
|
|
|
688
710
|
}
|
|
689
711
|
|
|
690
712
|
// ts/src/python-env.ts
|
|
691
|
-
import { readFileSync as
|
|
692
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join4, resolve as
|
|
693
|
-
|
|
713
|
+
import { readFileSync as readFileSync4, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
|
|
714
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join4, resolve as resolve4, sep as sep2 } from "path";
|
|
715
|
+
|
|
716
|
+
// ts/src/workspace.ts
|
|
717
|
+
import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
|
|
718
|
+
import { relative as relative3, resolve as resolve3, sep } from "path";
|
|
719
|
+
import { parse as parse3 } from "smol-toml";
|
|
720
|
+
function findUvWorkspace(cwd) {
|
|
694
721
|
for (const directory of ancestors(cwd)) {
|
|
695
|
-
|
|
722
|
+
const pyproject = `${directory}/pyproject.toml`;
|
|
723
|
+
if (!existsSync4(pyproject)) {
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
const data = readPyproject(pyproject);
|
|
727
|
+
if (!hasUvWorkspace(data)) {
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
const members = findWorkspaceMembers(directory, data);
|
|
731
|
+
return {
|
|
732
|
+
root: directory,
|
|
733
|
+
members,
|
|
734
|
+
currentMember: findCurrentMember(cwd, members)
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
function workspaceDependencyFiles(workspace) {
|
|
740
|
+
if (workspace.currentMember !== null) {
|
|
741
|
+
return [`${workspace.currentMember}/pyproject.toml`];
|
|
742
|
+
}
|
|
743
|
+
return [
|
|
744
|
+
`${workspace.root}/pyproject.toml`,
|
|
745
|
+
...workspace.members.map((member) => `${member}/pyproject.toml`)
|
|
746
|
+
].filter((path) => existsSync4(path));
|
|
747
|
+
}
|
|
748
|
+
function readPyproject(path) {
|
|
749
|
+
try {
|
|
750
|
+
const data = parse3(readFileSync3(path, "utf8"));
|
|
751
|
+
return isRecord3(data) ? data : {};
|
|
752
|
+
} catch {
|
|
753
|
+
return {};
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function hasUvWorkspace(data) {
|
|
757
|
+
const tool = data["tool"];
|
|
758
|
+
if (!isRecord3(tool)) {
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
const uv = tool["uv"];
|
|
762
|
+
if (!isRecord3(uv)) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
return isRecord3(uv["workspace"]);
|
|
766
|
+
}
|
|
767
|
+
function findWorkspaceMembers(root, data) {
|
|
768
|
+
const workspace = getWorkspaceTable(data);
|
|
769
|
+
if (workspace === null || !Array.isArray(workspace["members"])) {
|
|
770
|
+
return [];
|
|
771
|
+
}
|
|
772
|
+
const excludes = Array.isArray(workspace["exclude"]) ? workspace["exclude"].filter(
|
|
773
|
+
(value) => typeof value === "string"
|
|
774
|
+
) : [];
|
|
775
|
+
const members = /* @__PURE__ */ new Set();
|
|
776
|
+
for (const memberGlob of workspace["members"]) {
|
|
777
|
+
if (typeof memberGlob !== "string") {
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
for (const member of expandMemberGlob(root, memberGlob)) {
|
|
781
|
+
const relativePath = relative3(root, member).split(sep).join("/");
|
|
782
|
+
if (isExcluded(relativePath, excludes)) {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
if (isFile(`${member}/pyproject.toml`)) {
|
|
786
|
+
members.add(resolve3(member));
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return [...members].sort();
|
|
791
|
+
}
|
|
792
|
+
function getWorkspaceTable(data) {
|
|
793
|
+
const tool = data["tool"];
|
|
794
|
+
if (!isRecord3(tool)) {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
const uv = tool["uv"];
|
|
798
|
+
if (!isRecord3(uv)) {
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
801
|
+
const workspace = uv["workspace"];
|
|
802
|
+
return isRecord3(workspace) ? workspace : null;
|
|
803
|
+
}
|
|
804
|
+
function expandMemberGlob(root, pattern) {
|
|
805
|
+
const parts = pattern.split("/");
|
|
806
|
+
const results = [];
|
|
807
|
+
walkGlob(root, parts, results);
|
|
808
|
+
return results;
|
|
809
|
+
}
|
|
810
|
+
function walkGlob(directory, parts, results) {
|
|
811
|
+
if (parts.length === 0) {
|
|
812
|
+
if (isDirectory3(directory)) {
|
|
813
|
+
results.push(directory);
|
|
814
|
+
}
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
const [part, ...rest] = parts;
|
|
818
|
+
if (part === "*") {
|
|
819
|
+
for (const entry of readDirSafe(directory)) {
|
|
820
|
+
const child = `${directory}/${entry}`;
|
|
821
|
+
if (isDirectory3(child)) {
|
|
822
|
+
walkGlob(child, rest, results);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
walkGlob(`${directory}/${part}`, rest, results);
|
|
828
|
+
}
|
|
829
|
+
function isExcluded(relativePath, excludes) {
|
|
830
|
+
return excludes.some(
|
|
831
|
+
(pattern) => globMatches(relativePath, pattern.replace(/\/$/, ""))
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
function globMatches(value, pattern) {
|
|
835
|
+
if (pattern === value) {
|
|
836
|
+
return true;
|
|
837
|
+
}
|
|
838
|
+
const regex = new RegExp(`^${pattern.split("*").map(escapeRegex).join(".*")}$`);
|
|
839
|
+
return regex.test(value);
|
|
840
|
+
}
|
|
841
|
+
function findCurrentMember(cwd, members) {
|
|
842
|
+
const resolvedCwd = resolve3(cwd);
|
|
843
|
+
const matches = members.filter((member) => isRelativeTo2(resolvedCwd, member));
|
|
844
|
+
if (matches.length === 0) {
|
|
845
|
+
return null;
|
|
846
|
+
}
|
|
847
|
+
return matches.sort((left, right) => right.length - left.length)[0] ?? null;
|
|
848
|
+
}
|
|
849
|
+
function ancestors(start) {
|
|
850
|
+
const result = [];
|
|
851
|
+
let directory = resolve3(start);
|
|
852
|
+
while (true) {
|
|
853
|
+
result.push(directory);
|
|
854
|
+
const parent = resolve3(directory, "..");
|
|
855
|
+
if (parent === directory) {
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
directory = parent;
|
|
859
|
+
}
|
|
860
|
+
return result;
|
|
861
|
+
}
|
|
862
|
+
function isRelativeTo2(path, parent) {
|
|
863
|
+
const normalizedPath = resolve3(path);
|
|
864
|
+
const normalizedParent = resolve3(parent);
|
|
865
|
+
return normalizedPath === normalizedParent || normalizedPath.startsWith(`${normalizedParent}${sep}`);
|
|
866
|
+
}
|
|
867
|
+
function isRecord3(value) {
|
|
868
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
869
|
+
}
|
|
870
|
+
function isFile(path) {
|
|
871
|
+
try {
|
|
872
|
+
return statSync3(path).isFile();
|
|
873
|
+
} catch {
|
|
874
|
+
return false;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function isDirectory3(path) {
|
|
878
|
+
try {
|
|
879
|
+
return statSync3(path).isDirectory();
|
|
880
|
+
} catch {
|
|
881
|
+
return false;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function readDirSafe(path) {
|
|
885
|
+
try {
|
|
886
|
+
return isDirectory3(path) ? readdirSync3(path) : [];
|
|
887
|
+
} catch {
|
|
888
|
+
return [];
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
var escapeRegex = (value) => value.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
892
|
+
|
|
893
|
+
// ts/src/python-env.ts
|
|
894
|
+
function findProjectRoot(cwd) {
|
|
895
|
+
const workspace = findUvWorkspace(cwd);
|
|
896
|
+
if (workspace !== null) {
|
|
897
|
+
return workspace.root;
|
|
898
|
+
}
|
|
899
|
+
for (const directory of ancestors2(cwd)) {
|
|
900
|
+
if (isFile2(join4(directory, "pyproject.toml")) || isFile2(join4(directory, "uv.lock")) || venvFromDotVenv(directory) !== null || isFile2(join4(directory, "package.json")) || isDirectory4(join4(directory, "node_modules"))) {
|
|
696
901
|
return directory;
|
|
697
902
|
}
|
|
698
903
|
}
|
|
699
904
|
return null;
|
|
700
905
|
}
|
|
701
906
|
function findVenv(cwd = process.cwd()) {
|
|
907
|
+
const workspace = findUvWorkspace(cwd);
|
|
702
908
|
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
703
909
|
const uvProjectEnvironment = process.env["UV_PROJECT_ENVIRONMENT"];
|
|
704
910
|
if (uvProjectEnvironment) {
|
|
@@ -707,35 +913,38 @@ function findVenv(cwd = process.cwd()) {
|
|
|
707
913
|
return path;
|
|
708
914
|
}
|
|
709
915
|
}
|
|
710
|
-
|
|
916
|
+
if (workspace !== null) {
|
|
917
|
+
return venvFromDotVenv(workspace.root);
|
|
918
|
+
}
|
|
919
|
+
for (const directory of ancestors2(cwd)) {
|
|
711
920
|
const venv = venvFromDotVenv(directory);
|
|
712
921
|
if (venv !== null) {
|
|
713
922
|
return venv;
|
|
714
923
|
}
|
|
715
924
|
}
|
|
716
925
|
const virtualEnv = process.env["VIRTUAL_ENV"];
|
|
717
|
-
if (virtualEnv && isVenvDir(virtualEnv) &&
|
|
926
|
+
if (virtualEnv && isVenvDir(virtualEnv) && isRelativeTo3(virtualEnv, projectRoot)) {
|
|
718
927
|
return virtualEnv;
|
|
719
928
|
}
|
|
720
929
|
const condaPrefix = process.env["CONDA_PREFIX"];
|
|
721
|
-
if (condaPrefix &&
|
|
930
|
+
if (condaPrefix && isDirectory4(condaPrefix)) {
|
|
722
931
|
return condaPrefix;
|
|
723
932
|
}
|
|
724
933
|
return null;
|
|
725
934
|
}
|
|
726
935
|
function getSitePackagesDir(venvPath) {
|
|
727
936
|
const windowsSitePackages = join4(venvPath, "Lib", "site-packages");
|
|
728
|
-
if (
|
|
937
|
+
if (isDirectory4(windowsSitePackages)) {
|
|
729
938
|
return windowsSitePackages;
|
|
730
939
|
}
|
|
731
940
|
for (const libName of ["lib", "lib64"]) {
|
|
732
941
|
const libDir = join4(venvPath, libName);
|
|
733
|
-
if (!
|
|
942
|
+
if (!isDirectory4(libDir)) {
|
|
734
943
|
continue;
|
|
735
944
|
}
|
|
736
|
-
for (const child of
|
|
945
|
+
for (const child of readdirSync4(libDir).sort().reverse()) {
|
|
737
946
|
const sitePackages = join4(libDir, child, "site-packages");
|
|
738
|
-
if (child.startsWith("python") &&
|
|
947
|
+
if (child.startsWith("python") && isDirectory4(sitePackages)) {
|
|
739
948
|
return sitePackages;
|
|
740
949
|
}
|
|
741
950
|
}
|
|
@@ -743,23 +952,23 @@ function getSitePackagesDir(venvPath) {
|
|
|
743
952
|
return null;
|
|
744
953
|
}
|
|
745
954
|
function findNodeModules(cwd = process.cwd()) {
|
|
746
|
-
for (const directory of
|
|
955
|
+
for (const directory of ancestors2(cwd)) {
|
|
747
956
|
const nodeModules = join4(directory, "node_modules");
|
|
748
|
-
if (
|
|
957
|
+
if (isDirectory4(nodeModules)) {
|
|
749
958
|
return nodeModules;
|
|
750
959
|
}
|
|
751
960
|
}
|
|
752
961
|
return null;
|
|
753
962
|
}
|
|
754
963
|
function isVenvDir(directory) {
|
|
755
|
-
return
|
|
964
|
+
return isFile2(join4(directory, "pyvenv.cfg"));
|
|
756
965
|
}
|
|
757
966
|
function venvFromDotVenv(projectRoot) {
|
|
758
967
|
const dotVenv = join4(projectRoot, ".venv");
|
|
759
|
-
if (
|
|
968
|
+
if (isDirectory4(dotVenv)) {
|
|
760
969
|
return isVenvDir(dotVenv) ? dotVenv : null;
|
|
761
970
|
}
|
|
762
|
-
if (
|
|
971
|
+
if (isFile2(dotVenv)) {
|
|
763
972
|
return readVenvRedirectFile(dotVenv);
|
|
764
973
|
}
|
|
765
974
|
return null;
|
|
@@ -767,7 +976,7 @@ function venvFromDotVenv(projectRoot) {
|
|
|
767
976
|
function readVenvRedirectFile(path) {
|
|
768
977
|
let content;
|
|
769
978
|
try {
|
|
770
|
-
content =
|
|
979
|
+
content = readFileSync4(path, "utf8");
|
|
771
980
|
} catch {
|
|
772
981
|
return null;
|
|
773
982
|
}
|
|
@@ -778,9 +987,9 @@ function readVenvRedirectFile(path) {
|
|
|
778
987
|
const venv = isAbsolute2(redirect) ? redirect : join4(dirname3(path), redirect);
|
|
779
988
|
return isVenvDir(venv) ? venv : null;
|
|
780
989
|
}
|
|
781
|
-
function
|
|
990
|
+
function ancestors2(start) {
|
|
782
991
|
const result = [];
|
|
783
|
-
let directory =
|
|
992
|
+
let directory = resolve4(start);
|
|
784
993
|
while (true) {
|
|
785
994
|
result.push(directory);
|
|
786
995
|
const parent = dirname3(directory);
|
|
@@ -791,21 +1000,21 @@ function ancestors(start) {
|
|
|
791
1000
|
}
|
|
792
1001
|
return result;
|
|
793
1002
|
}
|
|
794
|
-
function
|
|
795
|
-
const normalizedPath =
|
|
796
|
-
const normalizedParent =
|
|
797
|
-
return normalizedPath === normalizedParent || normalizedPath.startsWith(`${normalizedParent}${
|
|
1003
|
+
function isRelativeTo3(path, parent) {
|
|
1004
|
+
const normalizedPath = resolve4(path);
|
|
1005
|
+
const normalizedParent = resolve4(parent);
|
|
1006
|
+
return normalizedPath === normalizedParent || normalizedPath.startsWith(`${normalizedParent}${sep2}`);
|
|
798
1007
|
}
|
|
799
|
-
function
|
|
1008
|
+
function isFile2(path) {
|
|
800
1009
|
try {
|
|
801
|
-
return
|
|
1010
|
+
return statSync4(path).isFile();
|
|
802
1011
|
} catch {
|
|
803
1012
|
return false;
|
|
804
1013
|
}
|
|
805
1014
|
}
|
|
806
|
-
function
|
|
1015
|
+
function isDirectory4(path) {
|
|
807
1016
|
try {
|
|
808
|
-
return
|
|
1017
|
+
return statSync4(path).isDirectory();
|
|
809
1018
|
} catch {
|
|
810
1019
|
return false;
|
|
811
1020
|
}
|
|
@@ -813,11 +1022,20 @@ function isDirectory3(path) {
|
|
|
813
1022
|
|
|
814
1023
|
// ts/src/cli.ts
|
|
815
1024
|
function getProjectContext(cwd = process.cwd()) {
|
|
816
|
-
const
|
|
1025
|
+
const workspace = findUvWorkspace(cwd);
|
|
1026
|
+
const projectRoot = workspace?.root ?? findProjectRoot(cwd) ?? cwd;
|
|
817
1027
|
const targetEnvironment = findVenv(cwd);
|
|
818
1028
|
const sitePackagesDir = targetEnvironment === null ? null : getSitePackagesDir(targetEnvironment);
|
|
819
1029
|
const nodeModulesDir = findNodeModules(cwd);
|
|
820
|
-
return {
|
|
1030
|
+
return {
|
|
1031
|
+
cwd,
|
|
1032
|
+
projectRoot,
|
|
1033
|
+
targetEnvironment,
|
|
1034
|
+
sitePackagesDir,
|
|
1035
|
+
nodeModulesDir,
|
|
1036
|
+
workspace,
|
|
1037
|
+
dependencyFiles: workspace ? workspaceDependencyFiles(workspace) : []
|
|
1038
|
+
};
|
|
821
1039
|
}
|
|
822
1040
|
function scanContext(context) {
|
|
823
1041
|
const result = {
|
|
@@ -830,6 +1048,14 @@ function scanContext(context) {
|
|
|
830
1048
|
result.skills.push(...pythonResult.skills);
|
|
831
1049
|
result.warnings.push(...pythonResult.warnings);
|
|
832
1050
|
}
|
|
1051
|
+
if (context.workspace?.currentMember) {
|
|
1052
|
+
const memberVenv = `${context.workspace.currentMember}/.venv`;
|
|
1053
|
+
if (exists(memberVenv)) {
|
|
1054
|
+
result.warnings.push(
|
|
1055
|
+
`Ignoring member-local .venv in uv workspace: ${memberVenv}`
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
833
1059
|
if (context.nodeModulesDir !== null) {
|
|
834
1060
|
const nodeResult = scanNodePackages(context.nodeModulesDir);
|
|
835
1061
|
result.skills.push(...nodeResult.skills);
|
|
@@ -851,11 +1077,13 @@ function topLevelSkills({
|
|
|
851
1077
|
return skills;
|
|
852
1078
|
}
|
|
853
1079
|
const topLevelDeps = getTopLevelDeps(context.projectRoot);
|
|
854
|
-
|
|
1080
|
+
const workspaceTopLevelDeps = context.workspace === null ? null : getWorkspaceTopLevelDeps(context.dependencyFiles);
|
|
1081
|
+
const selectedTopLevelDeps = context.workspace === null ? topLevelDeps : workspaceTopLevelDeps;
|
|
1082
|
+
if (selectedTopLevelDeps === null) {
|
|
855
1083
|
return skills;
|
|
856
1084
|
}
|
|
857
1085
|
return skills.filter(
|
|
858
|
-
(skill) =>
|
|
1086
|
+
(skill) => selectedTopLevelDeps.has(normalizePackageName(skill.packageName))
|
|
859
1087
|
);
|
|
860
1088
|
}
|
|
861
1089
|
function printWarnings(warnings) {
|
|
@@ -867,7 +1095,7 @@ function displayPath(path, projectRoot) {
|
|
|
867
1095
|
if (!path) {
|
|
868
1096
|
return "";
|
|
869
1097
|
}
|
|
870
|
-
const relativePath =
|
|
1098
|
+
const relativePath = relative4(resolve5(projectRoot), resolve5(path));
|
|
871
1099
|
if (relativePath === "") {
|
|
872
1100
|
return ".";
|
|
873
1101
|
}
|
|
@@ -878,6 +1106,12 @@ function displayPath(path, projectRoot) {
|
|
|
878
1106
|
}
|
|
879
1107
|
function printContext(context) {
|
|
880
1108
|
console.log(`Project root: ${context.projectRoot}`);
|
|
1109
|
+
if (context.workspace !== null) {
|
|
1110
|
+
console.log(`Workspace root: ${context.workspace.root}`);
|
|
1111
|
+
if (context.workspace.currentMember !== null) {
|
|
1112
|
+
console.log(`Workspace member: ${context.workspace.currentMember}`);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
881
1115
|
console.log(
|
|
882
1116
|
`Target Python environment: ${context.targetEnvironment ? displayPath(context.targetEnvironment, context.projectRoot) : "not found"}`
|
|
883
1117
|
);
|
|
@@ -917,6 +1151,9 @@ function scanJsonPayload({
|
|
|
917
1151
|
}) {
|
|
918
1152
|
return {
|
|
919
1153
|
project_root: context.projectRoot,
|
|
1154
|
+
workspace_root: context.workspace?.root ?? "",
|
|
1155
|
+
workspace_member: context.workspace?.currentMember ?? "",
|
|
1156
|
+
dependency_files: context.dependencyFiles,
|
|
920
1157
|
target_environment: context.targetEnvironment ?? "",
|
|
921
1158
|
node_modules: context.nodeModulesDir ?? "",
|
|
922
1159
|
skills: skills.map((skill) => ({
|
|
@@ -972,13 +1209,13 @@ function installedStatuses({
|
|
|
972
1209
|
skills
|
|
973
1210
|
}) {
|
|
974
1211
|
const skillsByDir = new Map(
|
|
975
|
-
skills.map((skill) => [
|
|
1212
|
+
skills.map((skill) => [resolve5(skill.skillDir), skill])
|
|
976
1213
|
);
|
|
977
1214
|
const skillsByName = new Map(skills.map((skill) => [skill.name, skill]));
|
|
978
1215
|
const statuses = [];
|
|
979
1216
|
for (const target of targets) {
|
|
980
1217
|
for (const installed of listInstalledSkills(target.path)) {
|
|
981
|
-
const skill = installed.target ? skillsByDir.get(
|
|
1218
|
+
const skill = installed.target ? skillsByDir.get(resolve5(installed.target)) : null;
|
|
982
1219
|
let matchedSkill = skill ?? null;
|
|
983
1220
|
let status = "hand-authored";
|
|
984
1221
|
if (installed.type === "symlink") {
|
|
@@ -1342,13 +1579,13 @@ function collect(value, previous) {
|
|
|
1342
1579
|
}
|
|
1343
1580
|
function exists(path) {
|
|
1344
1581
|
try {
|
|
1345
|
-
|
|
1582
|
+
statSync5(path);
|
|
1346
1583
|
return true;
|
|
1347
1584
|
} catch {
|
|
1348
1585
|
return false;
|
|
1349
1586
|
}
|
|
1350
1587
|
}
|
|
1351
|
-
if (process.argv[1] && realpathSync2(fileURLToPath2(import.meta.url)) === realpathSync2(
|
|
1588
|
+
if (process.argv[1] && realpathSync2(fileURLToPath2(import.meta.url)) === realpathSync2(resolve5(process.argv[1]))) {
|
|
1352
1589
|
main().catch((error) => {
|
|
1353
1590
|
console.error(error);
|
|
1354
1591
|
process.exit(1);
|
package/ts/dist/deps.cjs
CHANGED
|
@@ -22,7 +22,9 @@ var deps_exports = {};
|
|
|
22
22
|
__export(deps_exports, {
|
|
23
23
|
getNodeTopLevelDeps: () => getNodeTopLevelDeps,
|
|
24
24
|
getPythonTopLevelDeps: () => getPythonTopLevelDeps,
|
|
25
|
+
getPythonTopLevelDepsFromFiles: () => getPythonTopLevelDepsFromFiles,
|
|
25
26
|
getTopLevelDeps: () => getTopLevelDeps,
|
|
27
|
+
getWorkspaceTopLevelDeps: () => getWorkspaceTopLevelDeps,
|
|
26
28
|
testing: () => testing
|
|
27
29
|
});
|
|
28
30
|
module.exports = __toCommonJS(deps_exports);
|
|
@@ -45,13 +47,30 @@ function getPythonTopLevelDeps(projectRoot) {
|
|
|
45
47
|
if (!(0, import_node_fs2.existsSync)(pyproject)) {
|
|
46
48
|
return null;
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
return getPythonTopLevelDepsFromFiles([pyproject]);
|
|
51
|
+
}
|
|
52
|
+
function getPythonTopLevelDepsFromFiles(pyprojects) {
|
|
53
|
+
if (pyprojects.length === 0) {
|
|
52
54
|
return null;
|
|
53
55
|
}
|
|
54
56
|
const deps = /* @__PURE__ */ new Set();
|
|
57
|
+
let found = false;
|
|
58
|
+
for (const pyproject of pyprojects) {
|
|
59
|
+
if (!(0, import_node_fs2.existsSync)(pyproject)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
let data;
|
|
63
|
+
try {
|
|
64
|
+
data = (0, import_smol_toml.parse)((0, import_node_fs2.readFileSync)(pyproject, "utf8"));
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
found = true;
|
|
69
|
+
extractPythonTopLevelDeps(data, deps);
|
|
70
|
+
}
|
|
71
|
+
return found ? deps : null;
|
|
72
|
+
}
|
|
73
|
+
function extractPythonTopLevelDeps(data, deps) {
|
|
55
74
|
const project = data["project"];
|
|
56
75
|
if (isRecord(project)) {
|
|
57
76
|
const dependencies = project["dependencies"];
|
|
@@ -73,7 +92,6 @@ function getPythonTopLevelDeps(projectRoot) {
|
|
|
73
92
|
extractDepsFromDependencyGroup(groupName, dependencyGroups, deps, /* @__PURE__ */ new Set());
|
|
74
93
|
}
|
|
75
94
|
}
|
|
76
|
-
return deps;
|
|
77
95
|
}
|
|
78
96
|
function getNodeTopLevelDeps(projectRoot) {
|
|
79
97
|
const packageJson = (0, import_node_path2.join)(projectRoot, "package.json");
|
|
@@ -116,12 +134,15 @@ function getTopLevelDeps(projectRoot) {
|
|
|
116
134
|
}
|
|
117
135
|
return new Set(dependencySets.flatMap((deps) => [...deps]));
|
|
118
136
|
}
|
|
137
|
+
function getWorkspaceTopLevelDeps(pyprojects) {
|
|
138
|
+
return getPythonTopLevelDepsFromFiles(pyprojects);
|
|
139
|
+
}
|
|
119
140
|
function extractDepsFromSpecs(depSpecs, deps) {
|
|
120
141
|
for (const depSpec of depSpecs) {
|
|
121
142
|
if (typeof depSpec !== "string") {
|
|
122
143
|
continue;
|
|
123
144
|
}
|
|
124
|
-
const packageName = depSpec.split(/[
|
|
145
|
+
const packageName = depSpec.split(/[~>=<![\];,\s]/)[0]?.trim();
|
|
125
146
|
if (packageName && !packageName.startsWith("#")) {
|
|
126
147
|
deps.add(normalizePackageName(packageName));
|
|
127
148
|
}
|
|
@@ -164,6 +185,8 @@ var testing = {
|
|
|
164
185
|
0 && (module.exports = {
|
|
165
186
|
getNodeTopLevelDeps,
|
|
166
187
|
getPythonTopLevelDeps,
|
|
188
|
+
getPythonTopLevelDepsFromFiles,
|
|
167
189
|
getTopLevelDeps,
|
|
190
|
+
getWorkspaceTopLevelDeps,
|
|
168
191
|
testing
|
|
169
192
|
});
|
package/ts/dist/deps.d.cts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
declare function getPythonTopLevelDeps(projectRoot: string): Set<string> | null;
|
|
2
|
+
declare function getPythonTopLevelDepsFromFiles(pyprojects: string[]): Set<string> | null;
|
|
2
3
|
declare function getNodeTopLevelDeps(projectRoot: string): Set<string> | null;
|
|
3
4
|
declare function getTopLevelDeps(projectRoot: string): Set<string> | null;
|
|
5
|
+
declare function getWorkspaceTopLevelDeps(pyprojects: string[]): Set<string> | null;
|
|
4
6
|
declare function extractDepsFromSpecs(depSpecs: unknown[], deps: Set<string>): void;
|
|
5
7
|
declare function extractDepsFromDependencyGroup(groupName: unknown, dependencyGroups: Record<string, unknown>, deps: Set<string>, visited: Set<unknown>): void;
|
|
6
8
|
declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
@@ -10,4 +12,4 @@ declare const testing: {
|
|
|
10
12
|
isRecord: typeof isRecord;
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
export { getNodeTopLevelDeps, getPythonTopLevelDeps, getTopLevelDeps, testing };
|
|
15
|
+
export { getNodeTopLevelDeps, getPythonTopLevelDeps, getPythonTopLevelDepsFromFiles, getTopLevelDeps, getWorkspaceTopLevelDeps, testing };
|
package/ts/dist/deps.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
declare function getPythonTopLevelDeps(projectRoot: string): Set<string> | null;
|
|
2
|
+
declare function getPythonTopLevelDepsFromFiles(pyprojects: string[]): Set<string> | null;
|
|
2
3
|
declare function getNodeTopLevelDeps(projectRoot: string): Set<string> | null;
|
|
3
4
|
declare function getTopLevelDeps(projectRoot: string): Set<string> | null;
|
|
5
|
+
declare function getWorkspaceTopLevelDeps(pyprojects: string[]): Set<string> | null;
|
|
4
6
|
declare function extractDepsFromSpecs(depSpecs: unknown[], deps: Set<string>): void;
|
|
5
7
|
declare function extractDepsFromDependencyGroup(groupName: unknown, dependencyGroups: Record<string, unknown>, deps: Set<string>, visited: Set<unknown>): void;
|
|
6
8
|
declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
@@ -10,4 +12,4 @@ declare const testing: {
|
|
|
10
12
|
isRecord: typeof isRecord;
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
export { getNodeTopLevelDeps, getPythonTopLevelDeps, getTopLevelDeps, testing };
|
|
15
|
+
export { getNodeTopLevelDeps, getPythonTopLevelDeps, getPythonTopLevelDepsFromFiles, getTopLevelDeps, getWorkspaceTopLevelDeps, testing };
|