@agentxm/extension-discovery 0.28.4-bootstrap.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +110 -0
  2. package/dist/src/discover.d.ts +34 -0
  3. package/dist/src/discover.js +133 -0
  4. package/dist/src/index.d.ts +13 -0
  5. package/dist/src/index.js +12 -0
  6. package/dist/src/internal/environment.d.ts +14 -0
  7. package/dist/src/internal/environment.js +15 -0
  8. package/dist/src/packaging/bazel.d.ts +27 -0
  9. package/dist/src/packaging/bazel.js +125 -0
  10. package/dist/src/packaging/cargo.d.ts +32 -0
  11. package/dist/src/packaging/cargo.js +270 -0
  12. package/dist/src/packaging/cocoapods.d.ts +26 -0
  13. package/dist/src/packaging/cocoapods.js +187 -0
  14. package/dist/src/packaging/composer.d.ts +26 -0
  15. package/dist/src/packaging/composer.js +144 -0
  16. package/dist/src/packaging/conan.d.ts +30 -0
  17. package/dist/src/packaging/conan.js +238 -0
  18. package/dist/src/packaging/conda.d.ts +26 -0
  19. package/dist/src/packaging/conda.js +320 -0
  20. package/dist/src/packaging/cpan.d.ts +29 -0
  21. package/dist/src/packaging/cpan.js +189 -0
  22. package/dist/src/packaging/cran.d.ts +29 -0
  23. package/dist/src/packaging/cran.js +176 -0
  24. package/dist/src/packaging/detect.d.ts +16 -0
  25. package/dist/src/packaging/detect.js +25 -0
  26. package/dist/src/packaging/detected-package.d.ts +14 -0
  27. package/dist/src/packaging/detected-package.js +20 -0
  28. package/dist/src/packaging/docker.d.ts +27 -0
  29. package/dist/src/packaging/docker.js +256 -0
  30. package/dist/src/packaging/gem.d.ts +26 -0
  31. package/dist/src/packaging/gem.js +234 -0
  32. package/dist/src/packaging/golang.d.ts +26 -0
  33. package/dist/src/packaging/golang.js +169 -0
  34. package/dist/src/packaging/hackage.d.ts +26 -0
  35. package/dist/src/packaging/hackage.js +305 -0
  36. package/dist/src/packaging/hex.d.ts +28 -0
  37. package/dist/src/packaging/hex.js +186 -0
  38. package/dist/src/packaging/huggingface.d.ts +20 -0
  39. package/dist/src/packaging/huggingface.js +112 -0
  40. package/dist/src/packaging/index.d.ts +44 -0
  41. package/dist/src/packaging/index.js +120 -0
  42. package/dist/src/packaging/jsr.d.ts +30 -0
  43. package/dist/src/packaging/jsr.js +227 -0
  44. package/dist/src/packaging/julia.d.ts +27 -0
  45. package/dist/src/packaging/julia.js +165 -0
  46. package/dist/src/packaging/luarocks.d.ts +28 -0
  47. package/dist/src/packaging/luarocks.js +159 -0
  48. package/dist/src/packaging/maven.d.ts +27 -0
  49. package/dist/src/packaging/maven.js +471 -0
  50. package/dist/src/packaging/mojo.d.ts +29 -0
  51. package/dist/src/packaging/mojo.js +148 -0
  52. package/dist/src/packaging/npm.d.ts +26 -0
  53. package/dist/src/packaging/npm.js +190 -0
  54. package/dist/src/packaging/nuget.d.ts +26 -0
  55. package/dist/src/packaging/nuget.js +240 -0
  56. package/dist/src/packaging/opam.d.ts +27 -0
  57. package/dist/src/packaging/opam.js +287 -0
  58. package/dist/src/packaging/pub.d.ts +26 -0
  59. package/dist/src/packaging/pub.js +357 -0
  60. package/dist/src/packaging/pypi.d.ts +23 -0
  61. package/dist/src/packaging/pypi.js +448 -0
  62. package/dist/src/packaging/read.d.ts +20 -0
  63. package/dist/src/packaging/read.js +31 -0
  64. package/dist/src/packaging/reader-io.d.ts +29 -0
  65. package/dist/src/packaging/reader-io.js +29 -0
  66. package/dist/src/packaging/swift.d.ts +26 -0
  67. package/dist/src/packaging/swift.js +141 -0
  68. package/dist/src/packaging/types.d.ts +43 -0
  69. package/dist/src/packaging/types.js +8 -0
  70. package/dist/src/packaging/zig.d.ts +32 -0
  71. package/dist/src/packaging/zig.js +151 -0
  72. package/package.json +54 -0
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Swift package detector and reader for package-compatibility discovery.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ * @packageDocumentation
6
+ */
7
+ import * as Effect from "effect/Effect";
8
+ import * as Option from "effect/Option";
9
+ import * as Path from "effect/Path";
10
+ import * as Result from "effect/Result";
11
+ import * as Schema from "effect/Schema";
12
+ import { PackageTypeSchema } from "@agentxm/extension-model/unstable/packaging/package-type";
13
+ import { PackageUrlPartsSchema, } from "@agentxm/extension-model/unstable/packaging/package-url";
14
+ import { decodeAxmMeta, parseJsonOptional, readFileOptional } from "./reader-io.js";
15
+ const swiftType = Schema.decodeUnknownSync(PackageTypeSchema)("swift");
16
+ const makePackageUrlParts = Schema.decodeUnknownSync(PackageUrlPartsSchema);
17
+ /**
18
+ * Regex to match `exact: "version"` in a package declaration.
19
+ */
20
+ const EXACT_VERSION_REGEX = /exact:\s*"([^"]+)"/;
21
+ /**
22
+ * Parse a Swift package URL into namespace and name parts.
23
+ * URL format: https://github.com/Owner/RepoName.git
24
+ * namespace = host/org, name = repo (without .git)
25
+ */
26
+ const parseSwiftUrl = (url) => {
27
+ try {
28
+ const parsed = new URL(url);
29
+ const pathParts = parsed.pathname.split("/").filter((p) => p.length > 0);
30
+ if (pathParts.length < 2)
31
+ return undefined;
32
+ const host = parsed.hostname;
33
+ // All segments except the last form the org path
34
+ const orgParts = pathParts.slice(0, -1);
35
+ const rawName = pathParts[pathParts.length - 1];
36
+ if (rawName === undefined)
37
+ return undefined;
38
+ // Strip .git suffix
39
+ const name = rawName.endsWith(".git") ? rawName.slice(0, -4) : rawName;
40
+ const namespace = `${host}/${orgParts.join("/")}`;
41
+ return { namespace, name };
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ };
47
+ /**
48
+ * Extract the version requirement from a package declaration line/context.
49
+ * Returns the exact version if specified, undefined otherwise (ranges are versionless).
50
+ */
51
+ const extractVersion = (packageContext) => {
52
+ const exactMatch = EXACT_VERSION_REGEX.exec(packageContext);
53
+ if (exactMatch?.[1] !== undefined)
54
+ return exactMatch[1];
55
+ return undefined;
56
+ };
57
+ /**
58
+ * Build PackageUrlParts directly for swift packages.
59
+ * packageurl-js v2 requires a version for swift type purls, but we need
60
+ * versionless purls for range dependencies. We construct parts directly
61
+ * through the PackageUrlPartsSchema to bypass purl-string validation.
62
+ */
63
+ const buildSwiftPurlParts = (namespace, name, version) => makePackageUrlParts(version !== undefined
64
+ ? { type: "swift", namespace, name, version }
65
+ : { type: "swift", namespace, name });
66
+ /**
67
+ * Parse Package.swift content and extract dependencies using regex.
68
+ * Since running `swift package dump-package` requires the Swift CLI,
69
+ * we use simple regex to extract `.package(url: "...")` dependencies.
70
+ */
71
+ const parsePackageSwift = (content, source) => {
72
+ const results = [];
73
+ // Find all .package(url: "...") declarations
74
+ // We search for the entire package(...) block to extract version info too
75
+ const packageBlockRegex = /\.package\([^)]*url:\s*"([^"]+)"[^)]*\)/g;
76
+ let match;
77
+ while ((match = packageBlockRegex.exec(content)) !== null) {
78
+ const url = match[1];
79
+ if (url === undefined)
80
+ continue;
81
+ const parsed = parseSwiftUrl(url);
82
+ if (parsed === undefined)
83
+ continue;
84
+ // Extract version from the full match context
85
+ const version = extractVersion(match[0]);
86
+ const purlParts = buildSwiftPurlParts(parsed.namespace, parsed.name, version);
87
+ results.push({ purl: purlParts, type: swiftType, source });
88
+ }
89
+ return results;
90
+ };
91
+ /**
92
+ * Swift package detector.
93
+ *
94
+ * Scans `Package.swift` in the project directory and extracts `.package(url: ...)`
95
+ * dependencies using regex pattern matching.
96
+ *
97
+ * @experimental This API is unstable and may change without notice.
98
+ */
99
+ export const swiftDetector = {
100
+ type: swiftType,
101
+ detect: Effect.fn("detect.swift")(function* (projectDir) {
102
+ const path = yield* Path.Path;
103
+ const manifestPath = path.join(projectDir, "Package.swift");
104
+ const content = yield* readFileOptional(manifestPath);
105
+ if (Option.isNone(content))
106
+ return [];
107
+ const deps = parsePackageSwift(content.value, manifestPath);
108
+ return deps;
109
+ }, Effect.annotateLogs({ detector: "swift" }), Effect.withSpan("detect.swift")),
110
+ };
111
+ /**
112
+ * Swift package reader.
113
+ *
114
+ * Reads `.build/checkouts/<package-name>/axm.json` for each detected SwiftPM
115
+ * package and extracts recommendation metadata.
116
+ *
117
+ * @experimental This API is unstable and may change without notice.
118
+ */
119
+ export const swiftReader = {
120
+ type: swiftType,
121
+ read: Effect.fn("read.swift")(function* (pkg) {
122
+ const path = yield* Path.Path;
123
+ // Derive project directory from the source manifest path
124
+ const projectDir = path.dirname(pkg.source);
125
+ const axmJsonPath = path.join(projectDir, ".build", "checkouts", pkg.purl.name, "axm.json");
126
+ const content = yield* readFileOptional(axmJsonPath);
127
+ if (Option.isNone(content))
128
+ return Option.none();
129
+ const parsed = yield* parseJsonOptional(content.value, `${pkg.purl.name}/axm.json`);
130
+ if (Option.isNone(parsed))
131
+ return Option.none();
132
+ // Validate axm metadata structure
133
+ const metaResult = decodeAxmMeta(parsed.value);
134
+ if (Result.isFailure(metaResult)) {
135
+ yield* Effect.logWarning(`Invalid axm metadata in ${pkg.purl.name}: schema validation failed`);
136
+ return Option.none();
137
+ }
138
+ return Option.some(metaResult.success.extensions);
139
+ }, Effect.annotateLogs({ reader: "swift" }), Effect.withSpan("read.swift")),
140
+ };
141
+ //# sourceMappingURL=swift.js.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Detector and reader interfaces for package-compatibility discovery.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ * @packageDocumentation
6
+ */
7
+ import type * as Effect from "effect/Effect";
8
+ import type * as Option from "effect/Option";
9
+ import type * as FileSystem from "effect/FileSystem";
10
+ import type * as Path from "effect/Path";
11
+ import type { PackageExtensionDeclaration } from "@agentxm/registry-client";
12
+ import type { PackageType } from "@agentxm/extension-model/unstable/packaging/package-type";
13
+ import type { PackageUrlParts } from "@agentxm/extension-model/unstable/packaging/package-url";
14
+ /**
15
+ * A package detected in a project directory.
16
+ *
17
+ * @experimental This API is unstable and may change without notice.
18
+ */
19
+ export interface DetectedPackage {
20
+ readonly purl: PackageUrlParts;
21
+ readonly type: PackageType;
22
+ /** File that produced this purl (for diagnostics). */
23
+ readonly source: string;
24
+ }
25
+ /**
26
+ * Scans a project directory for packages of a specific type.
27
+ *
28
+ * @experimental This API is unstable and may change without notice.
29
+ */
30
+ export interface PackageDetector {
31
+ readonly type: PackageType;
32
+ readonly detect: (projectDir: string) => Effect.Effect<ReadonlyArray<DetectedPackage>, never, FileSystem.FileSystem | Path.Path>;
33
+ }
34
+ /**
35
+ * Reads local recommendation data from a detected package.
36
+ *
37
+ * @experimental This API is unstable and may change without notice.
38
+ */
39
+ export interface PackageReader {
40
+ readonly type: PackageType;
41
+ readonly read: (pkg: DetectedPackage) => Effect.Effect<Option.Option<ReadonlyArray<PackageExtensionDeclaration>>, never, FileSystem.FileSystem | Path.Path>;
42
+ }
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Detector and reader interfaces for package-compatibility discovery.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ * @packageDocumentation
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Zig package detector and reader for package-compatibility discovery.
3
+ *
4
+ * Parses `build.zig.zon` for URL-based dependencies and reads axm metadata
5
+ * from the Zig package cache at `~/.cache/zig/`.
6
+ *
7
+ * @experimental This API is unstable and may change without notice.
8
+ * @packageDocumentation
9
+ */
10
+ import type { PackageDetector, PackageReader } from "./types.js";
11
+ /**
12
+ * Zig package detector.
13
+ *
14
+ * Scans `build.zig.zon` in the project directory and extracts dependency
15
+ * names from the `.dependencies` field, producing `pkg:zig/<name>` purls.
16
+ *
17
+ * @experimental This API is unstable and may change without notice.
18
+ */
19
+ export declare const zigDetector: PackageDetector;
20
+ /**
21
+ * Zig package reader.
22
+ *
23
+ * Reads `axm.json` sidecar files from `~/.cache/zig/p/<hash>/` for each
24
+ * detected Zig package and extracts recommendation metadata.
25
+ *
26
+ * Since Zig uses content-addressed hashes for packages rather than named
27
+ * directories, the reader does a best-effort scan of the cache.
28
+ *
29
+ * @experimental This API is unstable and may change without notice.
30
+ */
31
+ export declare const zigReader: PackageReader;
32
+ //# sourceMappingURL=zig.d.ts.map
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Zig package detector and reader for package-compatibility discovery.
3
+ *
4
+ * Parses `build.zig.zon` for URL-based dependencies and reads axm metadata
5
+ * from the Zig package cache at `~/.cache/zig/`.
6
+ *
7
+ * @experimental This API is unstable and may change without notice.
8
+ * @packageDocumentation
9
+ */
10
+ // Intentional escape hatch: node:os homedir() has no @effect/platform equivalent.
11
+ import * as os from "node:os";
12
+ import * as Effect from "effect/Effect";
13
+ import * as FileSystem from "effect/FileSystem";
14
+ import * as Option from "effect/Option";
15
+ import * as Path from "effect/Path";
16
+ import * as Result from "effect/Result";
17
+ import * as Schema from "effect/Schema";
18
+ import { PackageURL } from "packageurl-js";
19
+ import { PackageTypeSchema } from "@agentxm/extension-model/unstable/packaging/package-type";
20
+ import { decodeAxmMeta, decodePurl, parseJsonOptional, readFileOptional } from "./reader-io.js";
21
+ const zigType = Schema.decodeUnknownSync(PackageTypeSchema)("zig");
22
+ /**
23
+ * Extract dependency names from build.zig.zon content.
24
+ *
25
+ * Zon uses a struct-like syntax:
26
+ * ```
27
+ * .dependencies = .{
28
+ * .zap = .{ .url = "...", .hash = "..." },
29
+ * .mach = .{ .url = "...", .hash = "..." },
30
+ * },
31
+ * ```
32
+ *
33
+ * We extract the dependency names (keys) using regex.
34
+ */
35
+ const parseZonDependencies = (content) => {
36
+ // Find the start of the .dependencies block
37
+ const startIdx = content.indexOf(".dependencies");
38
+ if (startIdx === -1)
39
+ return [];
40
+ // Find the opening .{ after .dependencies =
41
+ const openBrace = content.indexOf(".{", startIdx);
42
+ if (openBrace === -1)
43
+ return [];
44
+ // Track brace depth to find the matching closing }
45
+ let depth = 0;
46
+ let endIdx = openBrace;
47
+ for (let i = openBrace; i < content.length; i++) {
48
+ if (content[i] === "{")
49
+ depth++;
50
+ if (content[i] === "}") {
51
+ depth--;
52
+ if (depth === 0) {
53
+ endIdx = i;
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ const depsBlock = content.slice(openBrace, endIdx + 1);
59
+ const names = [];
60
+ // Match dependency names: .name = .{ ... }
61
+ // Also support quoted names: .@"name-with-dashes" = .{ ... }
62
+ const depPattern = /\.(?:@"([^"]+)"|([a-zA-Z_][a-zA-Z0-9_]*))\s*=\s*\.?\{/g;
63
+ let match = depPattern.exec(depsBlock);
64
+ while (match !== null) {
65
+ const name = match[1] ?? match[2];
66
+ if (name !== undefined) {
67
+ names.push(name);
68
+ }
69
+ match = depPattern.exec(depsBlock);
70
+ }
71
+ return names;
72
+ };
73
+ /**
74
+ * Zig package detector.
75
+ *
76
+ * Scans `build.zig.zon` in the project directory and extracts dependency
77
+ * names from the `.dependencies` field, producing `pkg:zig/<name>` purls.
78
+ *
79
+ * @experimental This API is unstable and may change without notice.
80
+ */
81
+ export const zigDetector = {
82
+ type: zigType,
83
+ detect: Effect.fn("detect.zig")(function* (projectDir) {
84
+ const path = yield* Path.Path;
85
+ const manifestPath = path.join(projectDir, "build.zig.zon");
86
+ const content = yield* readFileOptional(manifestPath);
87
+ if (Option.isNone(content))
88
+ return [];
89
+ const names = parseZonDependencies(content.value);
90
+ if (names.length === 0) {
91
+ // Check if the file looks like it should have dependencies but we couldn't parse
92
+ if (content.value.includes(".dependencies") &&
93
+ !content.value.includes(".dependencies = .{")) {
94
+ yield* Effect.logWarning("Malformed build.zig.zon: could not parse .dependencies, skipping");
95
+ }
96
+ return [];
97
+ }
98
+ const results = [];
99
+ for (const name of names) {
100
+ const purl = new PackageURL("zig", null, name, null, null, null);
101
+ const purlParts = decodePurl(purl.toString());
102
+ results.push({ purl: purlParts, type: zigType, source: manifestPath });
103
+ }
104
+ return results;
105
+ }, Effect.annotateLogs({ detector: "zig" }), Effect.withSpan("detect.zig")),
106
+ };
107
+ /**
108
+ * Zig package reader.
109
+ *
110
+ * Reads `axm.json` sidecar files from `~/.cache/zig/p/<hash>/` for each
111
+ * detected Zig package and extracts recommendation metadata.
112
+ *
113
+ * Since Zig uses content-addressed hashes for packages rather than named
114
+ * directories, the reader does a best-effort scan of the cache.
115
+ *
116
+ * @experimental This API is unstable and may change without notice.
117
+ */
118
+ export const zigReader = {
119
+ type: zigType,
120
+ read: Effect.fn("read.zig")(function* (pkg) {
121
+ const path = yield* Path.Path;
122
+ const fs = yield* FileSystem.FileSystem;
123
+ const cacheDir = path.join(os.homedir(), ".cache", "zig", "p");
124
+ // Check if cache directory exists
125
+ const cacheDirExists = yield* fs.exists(cacheDir).pipe(Effect.option);
126
+ if (Option.isNone(cacheDirExists) || !cacheDirExists.value)
127
+ return Option.none();
128
+ // Scan cache directory entries for axm.json
129
+ const entries = yield* fs.readDirectory(cacheDir).pipe(Effect.option);
130
+ if (Option.isNone(entries))
131
+ return Option.none();
132
+ // Check each cache entry for axm.json with matching package name
133
+ for (const entry of entries.value) {
134
+ const axmJsonPath = path.join(cacheDir, entry, "axm.json");
135
+ const content = yield* readFileOptional(axmJsonPath);
136
+ if (Option.isNone(content))
137
+ continue;
138
+ const parsed = yield* parseJsonOptional(content.value, `${pkg.purl.name}/axm.json`);
139
+ if (Option.isNone(parsed))
140
+ continue;
141
+ const metaResult = decodeAxmMeta(parsed.value);
142
+ if (Result.isFailure(metaResult)) {
143
+ yield* Effect.logWarning(`Invalid axm metadata in zig cache for ${pkg.purl.name}: schema validation failed`);
144
+ continue;
145
+ }
146
+ return Option.some(metaResult.success.extensions);
147
+ }
148
+ return Option.none();
149
+ }, Effect.annotateLogs({ reader: "zig" }), Effect.withSpan("read.zig")),
150
+ };
151
+ //# sourceMappingURL=zig.js.map
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@agentxm/extension-discovery",
3
+ "version": "0.28.4-bootstrap.0",
4
+ "description": "AXM extension-discovery feature: project package detectors, local extension declarations, Registry recommendations, and discovery results for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
5
+ "type": "module",
6
+ "license": "FSL-1.1-MIT",
7
+ "homepage": "https://axm.sh",
8
+ "bugs": {
9
+ "url": "https://github.com/agentxm/axm/issues"
10
+ },
11
+ "author": "AgentXM <hello@agentxm.ai> (https://agentxm.ai)",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/agentxm/axm.git",
15
+ "directory": "packages/extension-discovery"
16
+ },
17
+ "sideEffects": false,
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/src/index.d.ts",
21
+ "default": "./dist/src/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist/src/",
26
+ "!**/*.map"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "engines": {
32
+ "node": ">=22.19.0"
33
+ },
34
+ "nx": {
35
+ "includedScripts": []
36
+ },
37
+ "dependencies": {
38
+ "effect": "4.0.0-rc.112",
39
+ "packageurl-js": "^2.0.1",
40
+ "yaml": "^2.9.0",
41
+ "@agentxm/extension-model": "^0.28.4-bootstrap.0",
42
+ "@agentxm/registry-client": "^0.28.4-bootstrap.0",
43
+ "@agentxm/registry-protocol": "^0.28.4-bootstrap.0",
44
+ "@agentxm/extension-workspace": "^0.28.4-bootstrap.0"
45
+ },
46
+ "devDependencies": {
47
+ "@effect/platform-node": "4.0.0-rc.112",
48
+ "@effect/vitest": "4.0.0-rc.112",
49
+ "@types/bun": "^1.3.14",
50
+ "@typescript/native": "npm:typescript@^7.0.2",
51
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
52
+ "vitest": "^4.1.10"
53
+ }
54
+ }