nexarch 0.9.1 → 0.9.3
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.
|
@@ -8,7 +8,15 @@ import { fetchAgentRegistryOrThrow } from "../lib/agent-registry.js";
|
|
|
8
8
|
import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
|
|
9
9
|
import { buildVersionAttributes } from "../lib/version-normalization.js";
|
|
10
10
|
import { requestTrustAttestation } from "../lib/trust.js";
|
|
11
|
-
const CLI_VERSION =
|
|
11
|
+
const CLI_VERSION = (() => {
|
|
12
|
+
try {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8"));
|
|
14
|
+
return typeof pkg.version === "string" && pkg.version.trim() ? pkg.version.trim() : "unknown";
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return "unknown";
|
|
18
|
+
}
|
|
19
|
+
})();
|
|
12
20
|
const AGENT_ENTITY_TYPE = "agent";
|
|
13
21
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
14
22
|
function parseFlag(args, flag) {
|
|
@@ -23,6 +23,11 @@ function parseToolText(result) {
|
|
|
23
23
|
const text = result.content?.[0]?.text ?? "{}";
|
|
24
24
|
return JSON.parse(text);
|
|
25
25
|
}
|
|
26
|
+
function formatMs(ms) {
|
|
27
|
+
if (ms < 1000)
|
|
28
|
+
return `${ms}ms`;
|
|
29
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
30
|
+
}
|
|
26
31
|
function slugify(name) {
|
|
27
32
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
28
33
|
}
|
|
@@ -951,6 +956,12 @@ async function promptApplicationChoice(matches, allApps, suggested) {
|
|
|
951
956
|
export async function initProject(args) {
|
|
952
957
|
const asJson = parseFlag(args, "--json");
|
|
953
958
|
const dryRun = parseFlag(args, "--dry-run");
|
|
959
|
+
const commandStartedAt = Date.now();
|
|
960
|
+
const logProgress = (phase, details) => {
|
|
961
|
+
const elapsed = formatMs(Date.now() - commandStartedAt);
|
|
962
|
+
const line = details ? `[init-project +${elapsed}] ${phase} — ${details}` : `[init-project +${elapsed}] ${phase}`;
|
|
963
|
+
process.stderr.write(`${line}\n`);
|
|
964
|
+
};
|
|
954
965
|
const dirArg = parseOptionValue(args, "--dir") ?? process.cwd();
|
|
955
966
|
const dir = resolvePath(dirArg);
|
|
956
967
|
const nameOverride = parseOptionValue(args, "--name");
|
|
@@ -966,7 +977,9 @@ export async function initProject(args) {
|
|
|
966
977
|
const mcpOpts = { companyId: creds.companyId };
|
|
967
978
|
if (!asJson)
|
|
968
979
|
console.log(`Scanning ${dir}…`);
|
|
980
|
+
logProgress("scan.start", dir);
|
|
969
981
|
const { projectName, packageJsonCount, detectedNames, rootDepNames, rootDepVersions, subPackages, detectedEcosystems } = scanProject(dir);
|
|
982
|
+
logProgress("scan.done", `packages=${packageJsonCount}, detectedNames=${detectedNames.length}, subPackages=${subPackages.length}`);
|
|
970
983
|
const detectedRepo = detectSourceRepository(dir);
|
|
971
984
|
const displayName = nameOverride ?? projectName;
|
|
972
985
|
const projectSlug = slugify(displayName);
|
|
@@ -978,11 +991,11 @@ export async function initProject(args) {
|
|
|
978
991
|
for (const sp of subPackages) {
|
|
979
992
|
const nameSlug = slugify(sp.name);
|
|
980
993
|
const needsPrefix = !sp.name.includes("/") && !nameSlug.startsWith(projectSlug);
|
|
981
|
-
let keySlug = needsPrefix ? `${projectSlug}
|
|
994
|
+
let keySlug = needsPrefix ? `${projectSlug}_${nameSlug}` : nameSlug;
|
|
982
995
|
// Avoid key collision with the top-level project (e.g. sub-package named "nexarch").
|
|
983
996
|
if (`${sp.entityType}:${keySlug}` === projectExternalKey) {
|
|
984
|
-
const relSlug = slugify(sp.relativePath.replace(/\//g, "
|
|
985
|
-
keySlug = relSlug ? `${projectSlug}
|
|
997
|
+
const relSlug = slugify(sp.relativePath.replace(/\//g, "_"));
|
|
998
|
+
keySlug = relSlug ? `${projectSlug}_${relSlug}` : `${projectSlug}_${nameSlug}_sub`;
|
|
986
999
|
}
|
|
987
1000
|
sp.externalKey = `${sp.entityType}:${keySlug}`;
|
|
988
1001
|
}
|
|
@@ -1004,12 +1017,15 @@ export async function initProject(args) {
|
|
|
1004
1017
|
console.log("\nResolving against reference library…");
|
|
1005
1018
|
const allResolveResults = [];
|
|
1006
1019
|
const BATCH_SIZE = 200;
|
|
1020
|
+
logProgress("resolve.start", `count=${detectedNames.length}, batchSize=${BATCH_SIZE}`);
|
|
1007
1021
|
for (let i = 0; i < detectedNames.length; i += BATCH_SIZE) {
|
|
1008
1022
|
const batch = detectedNames.slice(i, i + BATCH_SIZE);
|
|
1023
|
+
logProgress("resolve.batch", `${Math.floor(i / BATCH_SIZE) + 1}/${Math.ceil(detectedNames.length / BATCH_SIZE)} size=${batch.length}`);
|
|
1009
1024
|
const raw = await callMcpTool("nexarch_resolve_reference", { names: batch, companyId: creds.companyId }, mcpOpts);
|
|
1010
1025
|
const data = parseToolText(raw);
|
|
1011
1026
|
allResolveResults.push(...data.results);
|
|
1012
1027
|
}
|
|
1028
|
+
logProgress("resolve.done", `resolved=${allResolveResults.filter((r) => r.resolved).length}`);
|
|
1013
1029
|
const resolvedItems = allResolveResults.filter((r) => r.resolved);
|
|
1014
1030
|
const unresolvedItems = allResolveResults.filter((r) => !r.resolved);
|
|
1015
1031
|
if (!asJson) {
|
|
@@ -1044,6 +1060,7 @@ export async function initProject(args) {
|
|
|
1044
1060
|
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
1045
1061
|
return;
|
|
1046
1062
|
}
|
|
1063
|
+
logProgress("preflight.onboarding.check");
|
|
1047
1064
|
const onboardingRaw = await callMcpTool("nexarch_get_company_onboarding", {}, mcpOpts);
|
|
1048
1065
|
const onboarding = parseToolText(onboardingRaw);
|
|
1049
1066
|
if (onboarding.isComplete !== true) {
|
|
@@ -1056,6 +1073,7 @@ export async function initProject(args) {
|
|
|
1056
1073
|
throw new Error(message);
|
|
1057
1074
|
}
|
|
1058
1075
|
// Policy bootstrap
|
|
1076
|
+
logProgress("preflight.policies.check");
|
|
1059
1077
|
const policiesRaw = await callMcpTool("nexarch_get_applied_policies", {}, mcpOpts);
|
|
1060
1078
|
const policies = parseToolText(policiesRaw);
|
|
1061
1079
|
const policyBundleHash = policies.policyBundleHash ?? null;
|
|
@@ -1091,7 +1109,7 @@ export async function initProject(args) {
|
|
|
1091
1109
|
.sort((a, b) => b.score - a.score);
|
|
1092
1110
|
const suggested = matches.length > 0 ? matches[0] : null;
|
|
1093
1111
|
const highConfidence = suggested && suggested.score >= 0.85;
|
|
1094
|
-
const interactiveAllowed = !
|
|
1112
|
+
const interactiveAllowed = !nonInteractive && process.stdin.isTTY;
|
|
1095
1113
|
if (autoMapApplication && highConfidence) {
|
|
1096
1114
|
projectExternalKey = suggested.entityRef;
|
|
1097
1115
|
if (!asJson)
|
|
@@ -1125,6 +1143,7 @@ export async function initProject(args) {
|
|
|
1125
1143
|
}
|
|
1126
1144
|
}
|
|
1127
1145
|
}
|
|
1146
|
+
logProgress("application.target", projectExternalKey);
|
|
1128
1147
|
const agentContext = {
|
|
1129
1148
|
agentId: "nexarch-cli:init-project",
|
|
1130
1149
|
agentRunId: `init-project-${Date.now()}`,
|
|
@@ -1294,13 +1313,17 @@ export async function initProject(args) {
|
|
|
1294
1313
|
if (!asJson)
|
|
1295
1314
|
console.log(`\nWriting to graph…`);
|
|
1296
1315
|
// Upsert entities
|
|
1316
|
+
logProgress("upsert.entities.start", `count=${entities.length}`);
|
|
1297
1317
|
const entitiesRaw = await callMcpTool("nexarch_upsert_entities", { entities, agentContext, policyContext }, mcpOpts);
|
|
1298
1318
|
const entitiesResult = parseToolText(entitiesRaw);
|
|
1319
|
+
logProgress("upsert.entities.done", `succeeded=${entitiesResult.summary?.succeeded ?? 0}, failed=${entitiesResult.summary?.failed ?? 0}`);
|
|
1299
1320
|
// Upsert relationships
|
|
1300
1321
|
let relsResult = null;
|
|
1301
1322
|
if (relationships.length > 0) {
|
|
1323
|
+
logProgress("upsert.relationships.start", `count=${relationships.length}`);
|
|
1302
1324
|
const relsRaw = await callMcpTool("nexarch_upsert_relationships", { relationships, agentContext, policyContext }, mcpOpts);
|
|
1303
1325
|
relsResult = parseToolText(relsRaw);
|
|
1326
|
+
logProgress("upsert.relationships.done", `succeeded=${relsResult.summary?.succeeded ?? 0}, failed=${relsResult.summary?.failed ?? 0}`);
|
|
1304
1327
|
}
|
|
1305
1328
|
// Build structured enrichment task (included in JSON output and printed in human mode)
|
|
1306
1329
|
const readmeHints = ["README.md", "README.mdx", "docs/README.md", "docs/index.md"]
|
|
@@ -1552,6 +1575,7 @@ ${subPkgSection}${adrSection}${gapCheckSection}`;
|
|
|
1552
1575
|
enrichmentTask,
|
|
1553
1576
|
};
|
|
1554
1577
|
if (asJson) {
|
|
1578
|
+
logProgress("complete", `ok=${output.ok}`);
|
|
1555
1579
|
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
1556
1580
|
if (!output.ok)
|
|
1557
1581
|
process.exitCode = 1;
|
|
@@ -1571,4 +1595,5 @@ ${subPkgSection}${adrSection}${gapCheckSection}`;
|
|
|
1571
1595
|
}
|
|
1572
1596
|
// ─── Enrichment task ────────────────────────────────────────────────────────
|
|
1573
1597
|
console.log(enrichmentTask.instructions);
|
|
1598
|
+
logProgress("complete", `ok=${output.ok}`);
|
|
1574
1599
|
}
|