nexarch 0.1.20 → 0.1.22
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.
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import process from "process";
|
|
2
|
+
import { requireCredentials } from "../lib/credentials.js";
|
|
3
|
+
import { callMcpTool } from "../lib/mcp.js";
|
|
4
|
+
function parseFlag(args, flag) {
|
|
5
|
+
return args.includes(flag);
|
|
6
|
+
}
|
|
7
|
+
function parseOptionValue(args, option) {
|
|
8
|
+
const idx = args.indexOf(option);
|
|
9
|
+
if (idx === -1)
|
|
10
|
+
return null;
|
|
11
|
+
const value = args[idx + 1];
|
|
12
|
+
if (!value || value.startsWith("--"))
|
|
13
|
+
return null;
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function parseToolText(result) {
|
|
17
|
+
const text = result.content?.[0]?.text ?? "{}";
|
|
18
|
+
return JSON.parse(text);
|
|
19
|
+
}
|
|
20
|
+
export async function addRelationship(args) {
|
|
21
|
+
const asJson = parseFlag(args, "--json");
|
|
22
|
+
const fromKey = parseOptionValue(args, "--from");
|
|
23
|
+
const toKey = parseOptionValue(args, "--to");
|
|
24
|
+
const relType = parseOptionValue(args, "--type");
|
|
25
|
+
if (!fromKey) {
|
|
26
|
+
console.error("error: --from <externalKey> is required");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
if (!toKey) {
|
|
30
|
+
console.error("error: --to <externalKey> is required");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
if (!relType) {
|
|
34
|
+
console.error("error: --type <relationshipTypeCode> is required");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const creds = requireCredentials();
|
|
38
|
+
const mcpOpts = { companyId: creds.companyId };
|
|
39
|
+
const policiesRaw = await callMcpTool("nexarch_get_applied_policies", {}, mcpOpts);
|
|
40
|
+
const policies = parseToolText(policiesRaw);
|
|
41
|
+
const policyBundleHash = policies.policyBundleHash ?? null;
|
|
42
|
+
const nowIso = new Date().toISOString();
|
|
43
|
+
const agentContext = {
|
|
44
|
+
agentId: "nexarch-cli:add-relationship",
|
|
45
|
+
agentRunId: `add-relationship-${Date.now()}`,
|
|
46
|
+
repoRef: fromKey,
|
|
47
|
+
observedAt: nowIso,
|
|
48
|
+
source: "nexarch-cli",
|
|
49
|
+
model: "n/a",
|
|
50
|
+
provider: "n/a",
|
|
51
|
+
};
|
|
52
|
+
const policyContext = policyBundleHash
|
|
53
|
+
? { policyBundleHash, alignmentSummary: { score: 1, violations: [], waivers: [] } }
|
|
54
|
+
: undefined;
|
|
55
|
+
const relationship = {
|
|
56
|
+
relationshipTypeCode: relType,
|
|
57
|
+
fromEntityExternalKey: fromKey,
|
|
58
|
+
toEntityExternalKey: toKey,
|
|
59
|
+
confidence: 1,
|
|
60
|
+
};
|
|
61
|
+
const raw = await callMcpTool("nexarch_upsert_relationships", { relationships: [relationship], agentContext, policyContext }, mcpOpts);
|
|
62
|
+
const result = parseToolText(raw);
|
|
63
|
+
if (asJson) {
|
|
64
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
65
|
+
if (Number(result.summary?.failed ?? 0) > 0)
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const succeeded = result.summary?.succeeded ?? 0;
|
|
70
|
+
const failed = result.summary?.failed ?? 0;
|
|
71
|
+
if (failed > 0) {
|
|
72
|
+
console.error(`Failed to add relationship: ${fromKey} -[${relType}]-> ${toKey}`);
|
|
73
|
+
for (const err of result.errors ?? []) {
|
|
74
|
+
console.error(` ${err.error} — ${err.message}`);
|
|
75
|
+
}
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
console.log(`Added ${succeeded} relationship: ${fromKey} -[${relType}]-> ${toKey}`);
|
|
80
|
+
}
|
|
@@ -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.22";
|
|
8
8
|
const AGENT_ENTITY_TYPE = "agent";
|
|
9
9
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
10
10
|
function parseFlag(args, flag) {
|
|
@@ -445,29 +445,41 @@ STEP 2 — Enrich the project entity. Run this command with the description you'
|
|
|
445
445
|
--name "<proper product name from README>" \\
|
|
446
446
|
--description "<2–4 sentence summary of what it does and why>"
|
|
447
447
|
${subPackages.length > 0 ? `
|
|
448
|
-
STEP 3 —
|
|
449
|
-
The scanner found ${subPackages.length} workspace package(s)
|
|
450
|
-
README / package.json description, then run:
|
|
448
|
+
STEP 3 — Classify and register each sub-package as its own entity.
|
|
449
|
+
The scanner found ${subPackages.length} workspace package(s):
|
|
451
450
|
|
|
452
|
-
Sub-packages detected:
|
|
453
451
|
${subPackages.map((sp) => ` • ${sp.name} (${sp.relativePath})`).join("\n")}
|
|
454
452
|
|
|
455
|
-
For each
|
|
453
|
+
For each one, READ its package.json and any README to understand what it actually is,
|
|
454
|
+
then choose the correct entity type and subtype before running update-entity:
|
|
456
455
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
456
|
+
CLASSIFICATION GUIDE — pick the best fit:
|
|
457
|
+
Deployable web app (has a dev/start/build script, runs in a browser or as a server)
|
|
458
|
+
→ --entity-type application --subtype app_web
|
|
459
|
+
Deployable background service, worker, or data pipeline (runs as a process, no UI)
|
|
460
|
+
→ --entity-type application --subtype app_custom_built (or app_integration_service for crawlers/ETL)
|
|
461
|
+
Shared internal library or package (imported by other packages, not deployed on its own)
|
|
462
|
+
→ --entity-type technology_component --subtype tech_library
|
|
463
|
+
Shared UI component library
|
|
464
|
+
→ --entity-type technology_component --subtype tech_framework
|
|
465
|
+
Type definitions or utility package with no runtime
|
|
466
|
+
→ --entity-type technology_component --subtype tech_library
|
|
467
|
+
|
|
468
|
+
For each sub-package, run:
|
|
463
469
|
|
|
464
|
-
|
|
470
|
+
npx nexarch update-entity \\
|
|
471
|
+
--key "<entity-type>:<slugified-package-name>" \\
|
|
472
|
+
--entity-type "<chosen entity type>" \\
|
|
473
|
+
--subtype "<chosen subtype>" \\
|
|
474
|
+
--name "<human readable name>" \\
|
|
475
|
+
--description "<what this package does and its role in the project>"
|
|
465
476
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
--type "part_of"
|
|
477
|
+
Then wire it to the parent project using the appropriate relationship:
|
|
478
|
+
• Deployable apps → relationship type: part_of
|
|
479
|
+
• Shared libraries → relationship type: depends_on (parent depends on the library)
|
|
470
480
|
|
|
471
|
-
|
|
481
|
+
Relationship type reference:
|
|
482
|
+
part_of — deployable sub-app is structurally part of the parent product
|
|
483
|
+
depends_on — parent product depends on a shared library at runtime
|
|
472
484
|
` : ""}`);
|
|
473
485
|
}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { initAgent } from "./commands/init-agent.js";
|
|
|
12
12
|
import { agentIdentify } from "./commands/agent-identify.js";
|
|
13
13
|
import { initProject } from "./commands/init-project.js";
|
|
14
14
|
import { updateEntity } from "./commands/update-entity.js";
|
|
15
|
+
import { addRelationship } from "./commands/add-relationship.js";
|
|
15
16
|
const [, , command, ...args] = process.argv;
|
|
16
17
|
const commands = {
|
|
17
18
|
login,
|
|
@@ -24,6 +25,7 @@ const commands = {
|
|
|
24
25
|
"agent-identify": agentIdentify,
|
|
25
26
|
"init-project": initProject,
|
|
26
27
|
"update-entity": updateEntity,
|
|
28
|
+
"add-relationship": addRelationship,
|
|
27
29
|
};
|
|
28
30
|
async function main() {
|
|
29
31
|
if (command === "agent") {
|
|
@@ -93,6 +95,12 @@ Usage:
|
|
|
93
95
|
--entity-type <code> (default: application)
|
|
94
96
|
--subtype <code>
|
|
95
97
|
--json
|
|
98
|
+
nexarch add-relationship
|
|
99
|
+
Add a relationship between two existing graph entities.
|
|
100
|
+
Options: --from <externalKey> (required)
|
|
101
|
+
--to <externalKey> (required)
|
|
102
|
+
--type <code> (required, e.g. part_of, depends_on)
|
|
103
|
+
--json
|
|
96
104
|
`);
|
|
97
105
|
process.exit(command ? 1 : 0);
|
|
98
106
|
}
|