nexarch 0.1.25 → 0.1.28
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/dist/commands/init-agent.js +1 -1
- package/dist/commands/init-project.js +102 -68
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { join } from "path";
|
|
|
4
4
|
import process from "process";
|
|
5
5
|
import { requireCredentials } from "../lib/credentials.js";
|
|
6
6
|
import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
|
|
7
|
-
const CLI_VERSION = "0.1.
|
|
7
|
+
const CLI_VERSION = "0.1.28";
|
|
8
8
|
const AGENT_ENTITY_TYPE = "agent";
|
|
9
9
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
10
10
|
function parseFlag(args, flag) {
|
|
@@ -282,14 +282,19 @@ function scanProject(dir) {
|
|
|
282
282
|
return { projectName, packageJsonCount: pkgPaths.length, detectedNames: Array.from(names), rootDepNames, subPackages };
|
|
283
283
|
}
|
|
284
284
|
// ─── Relationship type selection ──────────────────────────────────────────────
|
|
285
|
-
function pickRelationshipType(
|
|
286
|
-
switch (
|
|
285
|
+
function pickRelationshipType(toEntityTypeCode, fromEntityTypeCode = "application") {
|
|
286
|
+
switch (toEntityTypeCode) {
|
|
287
287
|
case "model":
|
|
288
288
|
return "uses_model";
|
|
289
289
|
case "platform":
|
|
290
290
|
case "platform_component":
|
|
291
291
|
case "skill":
|
|
292
292
|
return "uses";
|
|
293
|
+
case "technology_component":
|
|
294
|
+
// tech→tech depends_on is not allowed by ontology; use "uses" instead
|
|
295
|
+
if (fromEntityTypeCode === "technology_component")
|
|
296
|
+
return "uses";
|
|
297
|
+
return "depends_on";
|
|
293
298
|
default:
|
|
294
299
|
return "depends_on";
|
|
295
300
|
}
|
|
@@ -454,7 +459,7 @@ export async function initProject(args) {
|
|
|
454
459
|
const r = resolvedByInput.get(depName);
|
|
455
460
|
if (!r?.canonicalExternalRef || !r.entityTypeCode)
|
|
456
461
|
continue;
|
|
457
|
-
addRel(pickRelationshipType(r.entityTypeCode), sp.externalKey, r.canonicalExternalRef);
|
|
462
|
+
addRel(pickRelationshipType(r.entityTypeCode, sp.entityType), sp.externalKey, r.canonicalExternalRef);
|
|
458
463
|
}
|
|
459
464
|
}
|
|
460
465
|
if (!asJson)
|
|
@@ -468,64 +473,11 @@ export async function initProject(args) {
|
|
|
468
473
|
const relsRaw = await callMcpTool("nexarch_upsert_relationships", { relationships, agentContext, policyContext }, mcpOpts);
|
|
469
474
|
relsResult = parseToolText(relsRaw);
|
|
470
475
|
}
|
|
471
|
-
|
|
472
|
-
ok: Number(entitiesResult.summary?.failed ?? 0) === 0,
|
|
473
|
-
project: { name: displayName, externalKey: projectExternalKey, entityType: entityTypeOverride },
|
|
474
|
-
entities: entitiesResult.summary ?? {},
|
|
475
|
-
relationships: relsResult?.summary ?? { requested: 0, succeeded: 0, failed: 0 },
|
|
476
|
-
resolved: resolvedItems.length,
|
|
477
|
-
unresolved: unresolvedItems.length,
|
|
478
|
-
unresolvedSample: unresolvedItems.slice(0, 10).map((r) => r.input),
|
|
479
|
-
entityErrors: entitiesResult.errors ?? [],
|
|
480
|
-
relationshipErrors: relsResult?.errors ?? [],
|
|
481
|
-
};
|
|
482
|
-
if (asJson) {
|
|
483
|
-
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
484
|
-
if (!output.ok)
|
|
485
|
-
process.exitCode = 1;
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
console.log(`\nDone.`);
|
|
489
|
-
console.log(` Entities : ${output.entities.succeeded ?? 0} written, ${output.entities.failed ?? 0} failed`);
|
|
490
|
-
console.log(` Relationships: ${output.relationships.succeeded ?? 0} written`);
|
|
491
|
-
if (unresolvedItems.length > 0) {
|
|
492
|
-
console.log(` Candidates : ${unresolvedItems.length} added to reference candidates`);
|
|
493
|
-
}
|
|
494
|
-
if (output.entityErrors.length > 0) {
|
|
495
|
-
console.log("\nEntity errors:");
|
|
496
|
-
for (const err of output.entityErrors) {
|
|
497
|
-
console.log(` ${err.externalKey}: ${err.error} — ${err.message}`);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
// ─── Enrichment task ────────────────────────────────────────────────────────
|
|
476
|
+
// Build structured enrichment task (included in JSON output and printed in human mode)
|
|
501
477
|
const readmeHints = ["README.md", "README.mdx", "docs/README.md", "docs/index.md"]
|
|
502
478
|
.filter((f) => existsSync(join(dir, f)));
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
║ ENRICHMENT TASK — action required ║
|
|
506
|
-
╚══════════════════════════════════════════════════════════════════╝
|
|
507
|
-
|
|
508
|
-
The mechanical scan has written a skeleton graph entry for this project.
|
|
509
|
-
You now need to enrich it with meaningful content.
|
|
510
|
-
|
|
511
|
-
PROJECT ENTITY : ${projectExternalKey}
|
|
512
|
-
PROJECT DIR : ${dir}
|
|
513
|
-
${readmeHints.length > 0 ? `README FILES : ${readmeHints.join(", ")}` : "README FILES : (none found — check docs/)"}
|
|
514
|
-
|
|
515
|
-
STEP 1 — Read the project README / docs and build your understanding of:
|
|
516
|
-
• What does this project do? (business purpose, key features)
|
|
517
|
-
• Who are the users?
|
|
518
|
-
• What is the high-level architecture?
|
|
519
|
-
• Any notable technical decisions or constraints?
|
|
520
|
-
|
|
521
|
-
STEP 2 — Enrich the project entity. Run this command with the description you've written:
|
|
522
|
-
|
|
523
|
-
npx nexarch update-entity \\
|
|
524
|
-
--key "${projectExternalKey}" \\
|
|
525
|
-
--entity-type "${entityTypeOverride}"${entityTypeOverride === "application" ? ' \\\n --subtype "app_custom_built"' : ""} \\
|
|
526
|
-
--name "<proper product name from README>" \\
|
|
527
|
-
--description "<2–4 sentence summary of what it does and why>"
|
|
528
|
-
${subPackages.length > 0 ? `
|
|
479
|
+
function buildEnrichmentInstructions() {
|
|
480
|
+
const subPkgSection = subPackages.length === 0 ? "" : `
|
|
529
481
|
STEP 3 — Classify and register each sub-package as its own entity.
|
|
530
482
|
The scanner found ${subPackages.length} workspace package(s):
|
|
531
483
|
|
|
@@ -588,13 +540,95 @@ ${subPackages.map((sp) => ` • ${sp.name} (${sp.relativePath})`).join("\n")
|
|
|
588
540
|
|
|
589
541
|
Pre-resolved dependencies per sub-package (wire these after registering each entity):
|
|
590
542
|
${subPackages.map((sp) => {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
543
|
+
const resolved = sp.depNames
|
|
544
|
+
.map((d) => resolvedByInput.get(d))
|
|
545
|
+
.filter((r) => !!r?.canonicalExternalRef);
|
|
546
|
+
if (resolved.length === 0)
|
|
547
|
+
return ` • ${sp.name}: (no pre-resolved deps — check package.json manually)`;
|
|
548
|
+
const lines = resolved.map((r) => ` --to "${r.canonicalExternalRef}" # ${r.canonicalName}`);
|
|
549
|
+
return ` • ${sp.name} (<sub-app-key> depends_on):\n${lines.join("\n")}`;
|
|
550
|
+
}).join("\n\n")}
|
|
551
|
+
`;
|
|
552
|
+
return `
|
|
553
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
554
|
+
║ ENRICHMENT TASK — action required ║
|
|
555
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
556
|
+
|
|
557
|
+
The mechanical scan has written a skeleton graph entry for this project.
|
|
558
|
+
You now need to enrich it with meaningful content.
|
|
559
|
+
|
|
560
|
+
PROJECT ENTITY : ${projectExternalKey}
|
|
561
|
+
PROJECT DIR : ${dir}
|
|
562
|
+
${readmeHints.length > 0 ? `README FILES : ${readmeHints.join(", ")}` : "README FILES : (none found — check docs/)"}
|
|
563
|
+
|
|
564
|
+
STEP 1 — Read the project README / docs and build your understanding of:
|
|
565
|
+
• What does this project do? (business purpose, key features)
|
|
566
|
+
• Who are the users?
|
|
567
|
+
• What is the high-level architecture?
|
|
568
|
+
• Any notable technical decisions or constraints?
|
|
569
|
+
|
|
570
|
+
STEP 2 — Enrich the project entity. Run this command with the description you've written:
|
|
571
|
+
|
|
572
|
+
npx nexarch update-entity \\
|
|
573
|
+
--key "${projectExternalKey}" \\
|
|
574
|
+
--entity-type "${entityTypeOverride}"${entityTypeOverride === "application" ? " \\\n --subtype \"app_custom_built\"" : ""} \\
|
|
575
|
+
--name "<proper product name from README>" \\
|
|
576
|
+
--description "<2–4 sentence summary of what it does and why>"
|
|
577
|
+
${subPkgSection}`;
|
|
578
|
+
}
|
|
579
|
+
const enrichmentTask = {
|
|
580
|
+
instructions: buildEnrichmentInstructions(),
|
|
581
|
+
projectEntity: {
|
|
582
|
+
externalKey: projectExternalKey,
|
|
583
|
+
entityType: entityTypeOverride,
|
|
584
|
+
readmeFiles: readmeHints,
|
|
585
|
+
},
|
|
586
|
+
subPackages: subPackages.map((sp) => {
|
|
587
|
+
const resolvedDeps = sp.depNames
|
|
588
|
+
.map((d) => resolvedByInput.get(d))
|
|
589
|
+
.filter((r) => !!r?.canonicalExternalRef)
|
|
590
|
+
.map((r) => ({ canonicalExternalRef: r.canonicalExternalRef, canonicalName: r.canonicalName, entityTypeCode: r.entityTypeCode }));
|
|
591
|
+
return {
|
|
592
|
+
name: sp.name,
|
|
593
|
+
relativePath: sp.relativePath,
|
|
594
|
+
externalKey: sp.externalKey,
|
|
595
|
+
inferredEntityType: sp.entityType,
|
|
596
|
+
inferredSubtype: sp.subtype,
|
|
597
|
+
resolvedDeps,
|
|
598
|
+
unresolvedDeps: sp.depNames.filter((d) => !resolvedByInput.has(d)),
|
|
599
|
+
};
|
|
600
|
+
}),
|
|
601
|
+
};
|
|
602
|
+
const output = {
|
|
603
|
+
ok: Number(entitiesResult.summary?.failed ?? 0) === 0,
|
|
604
|
+
project: { name: displayName, externalKey: projectExternalKey, entityType: entityTypeOverride },
|
|
605
|
+
entities: entitiesResult.summary ?? {},
|
|
606
|
+
relationships: relsResult?.summary ?? { requested: 0, succeeded: 0, failed: 0 },
|
|
607
|
+
resolved: resolvedItems.length,
|
|
608
|
+
unresolved: unresolvedItems.length,
|
|
609
|
+
unresolvedSample: unresolvedItems.slice(0, 10).map((r) => r.input),
|
|
610
|
+
entityErrors: entitiesResult.errors ?? [],
|
|
611
|
+
relationshipErrors: relsResult?.errors ?? [],
|
|
612
|
+
enrichmentTask,
|
|
613
|
+
};
|
|
614
|
+
if (asJson) {
|
|
615
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
616
|
+
if (!output.ok)
|
|
617
|
+
process.exitCode = 1;
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
console.log(`\nDone.`);
|
|
621
|
+
console.log(` Entities : ${output.entities.succeeded ?? 0} written, ${output.entities.failed ?? 0} failed`);
|
|
622
|
+
console.log(` Relationships: ${output.relationships.succeeded ?? 0} written`);
|
|
623
|
+
if (unresolvedItems.length > 0) {
|
|
624
|
+
console.log(` Candidates : ${unresolvedItems.length} added to reference candidates`);
|
|
625
|
+
}
|
|
626
|
+
if (output.entityErrors.length > 0) {
|
|
627
|
+
console.log("\nEntity errors:");
|
|
628
|
+
for (const err of output.entityErrors) {
|
|
629
|
+
console.log(` ${err.externalKey}: ${err.error} — ${err.message}`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
// ─── Enrichment task ────────────────────────────────────────────────────────
|
|
633
|
+
console.log(enrichmentTask.instructions);
|
|
600
634
|
}
|