nexarch 0.5.7 → 0.5.8
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.
|
@@ -5,7 +5,8 @@ import process from "process";
|
|
|
5
5
|
import { requireCredentials } from "../lib/credentials.js";
|
|
6
6
|
import { fetchAgentRegistryOrThrow } from "../lib/agent-registry.js";
|
|
7
7
|
import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
|
|
8
|
-
|
|
8
|
+
import { buildVersionAttributes } from "../lib/version-normalization.js";
|
|
9
|
+
const CLI_VERSION = "0.5.8";
|
|
9
10
|
const AGENT_ENTITY_TYPE = "agent";
|
|
10
11
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
11
12
|
function parseFlag(args, flag) {
|
|
@@ -516,7 +517,7 @@ export async function initAgent(args) {
|
|
|
516
517
|
attributes: {
|
|
517
518
|
kind: "runtime",
|
|
518
519
|
runtime: "nodejs",
|
|
519
|
-
|
|
520
|
+
...buildVersionAttributes(runtime.nodeVersion, "runtime_probe"),
|
|
520
521
|
},
|
|
521
522
|
},
|
|
522
523
|
],
|
|
@@ -582,7 +583,12 @@ export async function initAgent(args) {
|
|
|
582
583
|
fromEntityExternalKey: agentExternalKey,
|
|
583
584
|
toEntityExternalKey: nodeExternalKey,
|
|
584
585
|
confidence: 0.95,
|
|
585
|
-
attributes: {
|
|
586
|
+
attributes: {
|
|
587
|
+
source: "nexarch-cli-init-agent",
|
|
588
|
+
kind: "runtime",
|
|
589
|
+
createdAt: nowIso,
|
|
590
|
+
...buildVersionAttributes(runtime.nodeVersion, "runtime_probe"),
|
|
591
|
+
},
|
|
586
592
|
},
|
|
587
593
|
// Host runs on its OS — gives the host entity its own OS relationship
|
|
588
594
|
{
|
|
@@ -5,6 +5,7 @@ import { basename, join, relative, resolve as resolvePath } from "node:path";
|
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { requireCredentials } from "../lib/credentials.js";
|
|
7
7
|
import { callMcpTool } from "../lib/mcp.js";
|
|
8
|
+
import { buildVersionAttributes } from "../lib/version-normalization.js";
|
|
8
9
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
9
10
|
function parseFlag(args, flag) {
|
|
10
11
|
return args.includes(flag);
|
|
@@ -290,10 +291,15 @@ function collectPackageDeps(pkgPath) {
|
|
|
290
291
|
try {
|
|
291
292
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
292
293
|
// devDependencies are build/test/type tooling — no architectural value
|
|
293
|
-
|
|
294
|
+
const merged = {
|
|
294
295
|
...pkg.dependencies,
|
|
295
296
|
...pkg.peerDependencies,
|
|
296
|
-
}
|
|
297
|
+
};
|
|
298
|
+
return Object.entries(merged).map(([name, versionRaw]) => ({
|
|
299
|
+
name,
|
|
300
|
+
versionRaw: typeof versionRaw === "string" ? versionRaw : null,
|
|
301
|
+
source: "package_json",
|
|
302
|
+
}));
|
|
297
303
|
}
|
|
298
304
|
catch {
|
|
299
305
|
return [];
|
|
@@ -618,6 +624,7 @@ function scanProject(dir) {
|
|
|
618
624
|
let projectName = basename(dir);
|
|
619
625
|
const subPackages = [];
|
|
620
626
|
let rootDepNames = new Set();
|
|
627
|
+
const rootDepVersions = new Map();
|
|
621
628
|
const detectedEcosystems = [];
|
|
622
629
|
// ── npm / Node.js ──────────────────────────────────────────────────────────
|
|
623
630
|
const pkgPaths = findPackageJsonPaths(dir);
|
|
@@ -630,7 +637,9 @@ function scanProject(dir) {
|
|
|
630
637
|
if (pkgPath === rootPkgPath) {
|
|
631
638
|
if (pkg.name)
|
|
632
639
|
projectName = pkg.name;
|
|
633
|
-
rootDepNames = new Set(deps);
|
|
640
|
+
rootDepNames = new Set(deps.map((d) => d.name));
|
|
641
|
+
for (const dep of deps)
|
|
642
|
+
rootDepVersions.set(dep.name, dep);
|
|
634
643
|
}
|
|
635
644
|
else {
|
|
636
645
|
const relativePath = relative(dir, pkgPath)
|
|
@@ -642,14 +651,14 @@ function scanProject(dir) {
|
|
|
642
651
|
name: packageName,
|
|
643
652
|
relativePath,
|
|
644
653
|
packageJsonPath: pkgPath,
|
|
645
|
-
|
|
654
|
+
depSpecs: deps,
|
|
646
655
|
entityType,
|
|
647
656
|
subtype,
|
|
648
657
|
externalKey: "",
|
|
649
658
|
});
|
|
650
659
|
}
|
|
651
660
|
for (const dep of deps)
|
|
652
|
-
names.add(dep);
|
|
661
|
+
names.add(dep.name);
|
|
653
662
|
}
|
|
654
663
|
}
|
|
655
664
|
// ── Other ecosystems (Python, Go, Ruby, Rust) ──────────────────────────────
|
|
@@ -660,8 +669,12 @@ function scanProject(dir) {
|
|
|
660
669
|
if (!detectedEcosystems.includes(e))
|
|
661
670
|
detectedEcosystems.push(e);
|
|
662
671
|
// Root deps for non-npm ecosystems — treat all detected names as root-level
|
|
663
|
-
for (const n of ecosystemNames)
|
|
672
|
+
for (const n of ecosystemNames) {
|
|
664
673
|
rootDepNames.add(n);
|
|
674
|
+
if (!rootDepVersions.has(n)) {
|
|
675
|
+
rootDepVersions.set(n, { name: n, versionRaw: null, source: `${e}_manifest` });
|
|
676
|
+
}
|
|
677
|
+
}
|
|
665
678
|
}
|
|
666
679
|
// Try to infer project name from Python pyproject.toml if no package.json name
|
|
667
680
|
if (!detectedEcosystems.includes("nodejs") && existsSync(join(dir, "pyproject.toml"))) {
|
|
@@ -704,6 +717,7 @@ function scanProject(dir) {
|
|
|
704
717
|
packageJsonCount: pkgPaths.length,
|
|
705
718
|
detectedNames: Array.from(names),
|
|
706
719
|
rootDepNames,
|
|
720
|
+
rootDepVersions,
|
|
707
721
|
subPackages,
|
|
708
722
|
detectedEcosystems,
|
|
709
723
|
};
|
|
@@ -740,7 +754,7 @@ export async function initProject(args) {
|
|
|
740
754
|
const mcpOpts = { companyId: creds.companyId };
|
|
741
755
|
if (!asJson)
|
|
742
756
|
console.log(`Scanning ${dir}…`);
|
|
743
|
-
const { projectName, packageJsonCount, detectedNames, rootDepNames, subPackages, detectedEcosystems } = scanProject(dir);
|
|
757
|
+
const { projectName, packageJsonCount, detectedNames, rootDepNames, rootDepVersions, subPackages, detectedEcosystems } = scanProject(dir);
|
|
744
758
|
const detectedRepo = detectSourceRepository(dir);
|
|
745
759
|
const displayName = nameOverride ?? projectName;
|
|
746
760
|
const projectSlug = slugify(displayName);
|
|
@@ -944,12 +958,12 @@ export async function initProject(args) {
|
|
|
944
958
|
// - Sub-packages that are apps → part_of the top-level project
|
|
945
959
|
const relationships = [];
|
|
946
960
|
const seenRelPairs = new Set();
|
|
947
|
-
function addRel(type, from, to, confidence = 0.9) {
|
|
961
|
+
function addRel(type, from, to, confidence = 0.9, attributes) {
|
|
948
962
|
const key = `${type}::${from}::${to}`;
|
|
949
963
|
if (seenRelPairs.has(key))
|
|
950
964
|
return;
|
|
951
965
|
seenRelPairs.add(key);
|
|
952
|
-
relationships.push({ relationshipTypeCode: type, fromEntityExternalKey: from, toEntityExternalKey: to, confidence });
|
|
966
|
+
relationships.push({ relationshipTypeCode: type, fromEntityExternalKey: from, toEntityExternalKey: to, confidence, attributes });
|
|
953
967
|
}
|
|
954
968
|
// Root-level deps → top-level project
|
|
955
969
|
for (const r of resolvedItems) {
|
|
@@ -957,7 +971,12 @@ export async function initProject(args) {
|
|
|
957
971
|
continue;
|
|
958
972
|
if (!rootDepNames.has(r.input) && !rootDepNames.has(r.normalised))
|
|
959
973
|
continue;
|
|
960
|
-
|
|
974
|
+
const depSpec = rootDepVersions.get(r.input) ?? rootDepVersions.get(r.normalised);
|
|
975
|
+
addRel(pickRelationshipType(r.entityTypeCode), projectExternalKey, r.canonicalExternalRef, 0.9, {
|
|
976
|
+
source: depSpec?.source ?? "manifest_scan",
|
|
977
|
+
detected_at: nowIso,
|
|
978
|
+
...buildVersionAttributes(depSpec?.versionRaw ?? null, depSpec?.source ?? "manifest_scan"),
|
|
979
|
+
});
|
|
961
980
|
}
|
|
962
981
|
// Sub-package relationships
|
|
963
982
|
for (const sp of subPackages) {
|
|
@@ -969,11 +988,15 @@ export async function initProject(args) {
|
|
|
969
988
|
addRel("part_of", sp.externalKey, projectExternalKey);
|
|
970
989
|
}
|
|
971
990
|
// Wire each sub-package's resolved deps to itself
|
|
972
|
-
for (const
|
|
973
|
-
const r = resolvedByInput.get(
|
|
991
|
+
for (const dep of sp.depSpecs) {
|
|
992
|
+
const r = resolvedByInput.get(dep.name);
|
|
974
993
|
if (!r?.canonicalExternalRef || !r.entityTypeCode)
|
|
975
994
|
continue;
|
|
976
|
-
addRel(pickRelationshipType(r.entityTypeCode, sp.entityType), sp.externalKey, r.canonicalExternalRef
|
|
995
|
+
addRel(pickRelationshipType(r.entityTypeCode, sp.entityType), sp.externalKey, r.canonicalExternalRef, 0.9, {
|
|
996
|
+
source: dep.source,
|
|
997
|
+
detected_at: nowIso,
|
|
998
|
+
...buildVersionAttributes(dep.versionRaw, dep.source),
|
|
999
|
+
});
|
|
977
1000
|
}
|
|
978
1001
|
}
|
|
979
1002
|
// Company org is accountable_for the top-level project entity
|
|
@@ -1089,8 +1112,8 @@ ${subPackages.map((sp) => ` • ${sp.name} (${sp.relativePath})`).join("\n")
|
|
|
1089
1112
|
|
|
1090
1113
|
Pre-resolved dependencies per sub-package (wire these after registering each entity):
|
|
1091
1114
|
${subPackages.map((sp) => {
|
|
1092
|
-
const resolved = sp.
|
|
1093
|
-
.map((d) => resolvedByInput.get(d))
|
|
1115
|
+
const resolved = sp.depSpecs
|
|
1116
|
+
.map((d) => resolvedByInput.get(d.name))
|
|
1094
1117
|
.filter((r) => !!r?.canonicalExternalRef);
|
|
1095
1118
|
if (resolved.length === 0)
|
|
1096
1119
|
return ` • ${sp.name}: (no pre-resolved deps — check package.json manually)`;
|
|
@@ -1184,8 +1207,8 @@ ${subPkgSection}${gapCheckSection}`;
|
|
|
1184
1207
|
readmeFiles: readmeHints,
|
|
1185
1208
|
},
|
|
1186
1209
|
subPackages: subPackages.map((sp) => {
|
|
1187
|
-
const resolvedDeps = sp.
|
|
1188
|
-
.map((d) => resolvedByInput.get(d))
|
|
1210
|
+
const resolvedDeps = sp.depSpecs
|
|
1211
|
+
.map((d) => resolvedByInput.get(d.name))
|
|
1189
1212
|
.filter((r) => !!r?.canonicalExternalRef)
|
|
1190
1213
|
.map((r) => ({ canonicalExternalRef: r.canonicalExternalRef, canonicalName: r.canonicalName, entityTypeCode: r.entityTypeCode }));
|
|
1191
1214
|
return {
|
|
@@ -1195,7 +1218,7 @@ ${subPkgSection}${gapCheckSection}`;
|
|
|
1195
1218
|
inferredEntityType: sp.entityType,
|
|
1196
1219
|
inferredSubtype: sp.subtype,
|
|
1197
1220
|
resolvedDeps,
|
|
1198
|
-
unresolvedDeps: sp.
|
|
1221
|
+
unresolvedDeps: sp.depSpecs.map((d) => d.name).filter((d) => !resolvedByInput.has(d)),
|
|
1199
1222
|
};
|
|
1200
1223
|
}),
|
|
1201
1224
|
};
|
package/dist/lib/mcp.js
CHANGED
|
@@ -68,7 +68,7 @@ export async function mcpInitialize(options = {}) {
|
|
|
68
68
|
return callMcpRpc("initialize", {
|
|
69
69
|
protocolVersion: "2024-11-05",
|
|
70
70
|
capabilities: {},
|
|
71
|
-
clientInfo: { name: "nexarch-cli", version: "0.5.
|
|
71
|
+
clientInfo: { name: "nexarch-cli", version: "0.5.8" },
|
|
72
72
|
}, options);
|
|
73
73
|
}
|
|
74
74
|
export async function mcpListTools(options = {}) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function normalizeVersion(raw) {
|
|
2
|
+
const value = typeof raw === "string" ? raw.trim() : "";
|
|
3
|
+
if (!value) {
|
|
4
|
+
return {
|
|
5
|
+
versionRaw: null,
|
|
6
|
+
versionNormalized: null,
|
|
7
|
+
versionMajor: null,
|
|
8
|
+
versionMinor: null,
|
|
9
|
+
isExact: false,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const withoutV = value.replace(/^v/i, "");
|
|
13
|
+
const exactMatch = withoutV.match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:[-+][\w.-]+)?$/);
|
|
14
|
+
const majorMinorPatchMatch = withoutV.match(/(\d+)\.(\d+)(?:\.(\d+))?/);
|
|
15
|
+
const major = exactMatch?.[1] ?? majorMinorPatchMatch?.[1] ?? null;
|
|
16
|
+
const minor = exactMatch?.[2] ?? majorMinorPatchMatch?.[2] ?? null;
|
|
17
|
+
return {
|
|
18
|
+
versionRaw: value,
|
|
19
|
+
versionNormalized: exactMatch ? withoutV : (majorMinorPatchMatch ? majorMinorPatchMatch[0] : null),
|
|
20
|
+
versionMajor: major ? Number.parseInt(major, 10) : null,
|
|
21
|
+
versionMinor: minor ? Number.parseInt(minor, 10) : null,
|
|
22
|
+
isExact: Boolean(exactMatch),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function buildVersionAttributes(raw, source) {
|
|
26
|
+
const normalized = normalizeVersion(raw);
|
|
27
|
+
return {
|
|
28
|
+
version_raw: normalized.versionRaw,
|
|
29
|
+
version_normalized: normalized.versionNormalized,
|
|
30
|
+
version_major: normalized.versionMajor,
|
|
31
|
+
version_minor: normalized.versionMinor,
|
|
32
|
+
version_is_exact: normalized.isExact,
|
|
33
|
+
version_source: source,
|
|
34
|
+
};
|
|
35
|
+
}
|