nexarch 0.5.2 → 0.5.4
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.
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { arch, homedir, hostname, platform, release, type as osType, userInfo } from "os";
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
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
|
-
const CLI_VERSION = "0.5.
|
|
8
|
+
const CLI_VERSION = "0.5.4";
|
|
9
9
|
const AGENT_ENTITY_TYPE = "agent";
|
|
10
10
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
11
11
|
function parseFlag(args, flag) {
|
|
@@ -47,6 +47,32 @@ function getRuntimeMode() {
|
|
|
47
47
|
return "ci";
|
|
48
48
|
return "interactive";
|
|
49
49
|
}
|
|
50
|
+
function detectLikelyApplicationInCwd() {
|
|
51
|
+
const cwd = process.cwd();
|
|
52
|
+
const files = [
|
|
53
|
+
"package.json",
|
|
54
|
+
"pyproject.toml",
|
|
55
|
+
"requirements.txt",
|
|
56
|
+
"go.mod",
|
|
57
|
+
"Cargo.toml",
|
|
58
|
+
"Gemfile",
|
|
59
|
+
"composer.json",
|
|
60
|
+
"pom.xml",
|
|
61
|
+
"build.gradle",
|
|
62
|
+
"build.gradle.kts",
|
|
63
|
+
];
|
|
64
|
+
const evidence = files.filter((file) => existsSync(join(cwd, file)));
|
|
65
|
+
try {
|
|
66
|
+
const entries = readdirSync(cwd);
|
|
67
|
+
if (entries.some((name) => name.toLowerCase().endsWith(".csproj"))) {
|
|
68
|
+
evidence.push("*.csproj");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// non-fatal; ignore
|
|
73
|
+
}
|
|
74
|
+
return { detected: evidence.length > 0, evidence };
|
|
75
|
+
}
|
|
50
76
|
function getSanitizedHostname(redactHostname) {
|
|
51
77
|
const raw = hostname() || "unknown-host";
|
|
52
78
|
return redactHostname ? "redacted" : raw;
|
|
@@ -245,6 +271,7 @@ function injectGenericAgentConfig(registry) {
|
|
|
245
271
|
export async function initAgent(args) {
|
|
246
272
|
const asJson = parseFlag(args, "--json");
|
|
247
273
|
const strict = parseFlag(args, "--strict");
|
|
274
|
+
const fromSetup = parseFlag(args, "--from-setup");
|
|
248
275
|
const redactHostname = parseFlag(args, "--redact-hostname");
|
|
249
276
|
const explicitAgentId = parseOptionValue(args, "--agent-id");
|
|
250
277
|
const bindToExternalKey = parseOptionValue(args, "--bind-to-external-key");
|
|
@@ -287,13 +314,23 @@ export async function initAgent(args) {
|
|
|
287
314
|
});
|
|
288
315
|
const policiesRaw = await callMcpTool("nexarch_get_applied_policies", {}, { companyId: selectedCompanyId });
|
|
289
316
|
const policies = parseToolText(policiesRaw);
|
|
317
|
+
const onboardingReady = Boolean(policies.policyBundleHash);
|
|
290
318
|
checks.push({
|
|
291
319
|
name: "governance.bootstrap",
|
|
292
|
-
ok:
|
|
320
|
+
ok: onboardingReady,
|
|
293
321
|
detail: policies.policyBundleHash
|
|
294
|
-
? `policyBundleHash=${policies.policyBundleHash.slice(0, 12)}
|
|
322
|
+
? `policyBundleHash=${policies.policyBundleHash.slice(0, 12)}…`
|
|
295
323
|
: "missing policyBundleHash",
|
|
296
324
|
});
|
|
325
|
+
if (!onboardingReady) {
|
|
326
|
+
const onboardingMessage = "Company onboarding is incomplete (missing policy bootstrap). Complete onboarding before running init-agent or init-project.";
|
|
327
|
+
if (asJson) {
|
|
328
|
+
process.stdout.write(`${JSON.stringify({ ok: false, error: "COMPANY_ONBOARDING_INCOMPLETE", message: onboardingMessage }, null, 2)}\n`);
|
|
329
|
+
process.exitCode = 1;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
throw new Error(onboardingMessage);
|
|
333
|
+
}
|
|
297
334
|
const contractRaw = await callMcpTool("nexarch_get_ingest_contract", {}, { companyId: selectedCompanyId });
|
|
298
335
|
const contract = parseToolText(contractRaw);
|
|
299
336
|
checks.push({
|
|
@@ -718,6 +755,7 @@ export async function initAgent(args) {
|
|
|
718
755
|
});
|
|
719
756
|
}
|
|
720
757
|
const allPassed = checks.every((c) => c.ok);
|
|
758
|
+
const appDetection = detectLikelyApplicationInCwd();
|
|
721
759
|
const identifyPrompt = [
|
|
722
760
|
"Please identify your runtime so the workspace can register richer metadata.",
|
|
723
761
|
"Return ONLY the completed command below with real values (no markdown):",
|
|
@@ -751,6 +789,17 @@ export async function initAgent(args) {
|
|
|
751
789
|
detail: "Prompt the coding agent to self-identify and submit via nexarch agent identify",
|
|
752
790
|
prompt: identifyPrompt,
|
|
753
791
|
submitCommandTemplate: `nexarch agent identify --agent-id \"${agentId}\" --provider \"<provider>\" --model \"<model>\" --client \"<client>\" --framework \"<openclaw|n8n|m365-agent-framework|other>\" --session-id \"<session-id>\" --tool-version \"<tool-version>\" --capabilities \"<capability1,capability2>\" --notes \"<optional notes>\" --json`,
|
|
792
|
+
initProjectSuggestion: appDetection.detected
|
|
793
|
+
? {
|
|
794
|
+
shouldPromptUser: true,
|
|
795
|
+
reason: `Detected likely project manifests in cwd: ${appDetection.evidence.join(", ")}`,
|
|
796
|
+
userPrompt: "I found a likely application in this directory. Do you want me to run init-project next?",
|
|
797
|
+
suggestedCommand: "npx nexarch@latest init-project --dir . --json",
|
|
798
|
+
}
|
|
799
|
+
: {
|
|
800
|
+
shouldPromptUser: false,
|
|
801
|
+
reason: "No common application manifest files detected in current directory.",
|
|
802
|
+
},
|
|
754
803
|
},
|
|
755
804
|
companyId: creds.companyId,
|
|
756
805
|
registry: { version: registry.release.version, registryVersion: registry.registryVersion, publishedAt: registry.release.publishedAt },
|
|
@@ -784,9 +833,11 @@ export async function initAgent(args) {
|
|
|
784
833
|
}
|
|
785
834
|
const hasInjectedAgentInstructions = agentConfigResults.some((r) => r.status === "injected" || r.status === "updated");
|
|
786
835
|
if (hasInjectedAgentInstructions) {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
836
|
+
if (!fromSetup) {
|
|
837
|
+
console.log("\n➡ Next step: in your coding agent, run:");
|
|
838
|
+
console.log("\nrun npx nexarch@latest init-agent\n");
|
|
839
|
+
console.log(" (Registration instructions were already written into your agent config file.)");
|
|
840
|
+
}
|
|
790
841
|
}
|
|
791
842
|
else {
|
|
792
843
|
console.log("\n➡ Next step (required): complete agent identity in your coding agent");
|
|
@@ -5,7 +5,6 @@ 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 { CURATED_AGENT_ICON_NAMES } from "../lib/application-icons.js";
|
|
9
8
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
10
9
|
function parseFlag(args, flag) {
|
|
11
10
|
return args.includes(flag);
|
|
@@ -817,6 +816,15 @@ export async function initProject(args) {
|
|
|
817
816
|
const policiesRaw = await callMcpTool("nexarch_get_applied_policies", {}, mcpOpts);
|
|
818
817
|
const policies = parseToolText(policiesRaw);
|
|
819
818
|
const policyBundleHash = policies.policyBundleHash ?? null;
|
|
819
|
+
if (!policyBundleHash) {
|
|
820
|
+
const message = "Company onboarding is incomplete (missing policy bootstrap). Complete onboarding before running init-project.";
|
|
821
|
+
if (asJson) {
|
|
822
|
+
process.stdout.write(`${JSON.stringify({ ok: false, error: "COMPANY_ONBOARDING_INCOMPLETE", message }, null, 2)}\n`);
|
|
823
|
+
process.exitCode = 1;
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
throw new Error(message);
|
|
827
|
+
}
|
|
820
828
|
const nowIso = new Date().toISOString();
|
|
821
829
|
const repoRef = repoRefOverride ?? detectedRepo?.rawRef ?? dir;
|
|
822
830
|
const repoPath = repoPathOverride ?? dir;
|
|
@@ -988,7 +996,6 @@ export async function initProject(args) {
|
|
|
988
996
|
const ecosystemLabel = detectedEcosystems.length > 0
|
|
989
997
|
? detectedEcosystems.join(", ")
|
|
990
998
|
: "unknown";
|
|
991
|
-
const curatedIconList = CURATED_AGENT_ICON_NAMES.join(", ");
|
|
992
999
|
const manifestHint = detectedEcosystems.includes("nodejs")
|
|
993
1000
|
? "package.json"
|
|
994
1001
|
: detectedEcosystems.includes("python")
|
|
@@ -1022,9 +1029,9 @@ ${subPackages.map((sp) => ` • ${sp.name} (${sp.relativePath})`).join("\n")
|
|
|
1022
1029
|
→ --entity-type technology_component --subtype tech_library
|
|
1023
1030
|
|
|
1024
1031
|
ICON ASSIGNMENT (applications only):
|
|
1025
|
-
• Pick one icon from
|
|
1032
|
+
• Pick one icon from the full Lucide icon set for each application/sub-app.
|
|
1026
1033
|
• If confidence is low, skip --icon rather than guessing.
|
|
1027
|
-
•
|
|
1034
|
+
• Use kebab-case icon names (example: server, workflow, shield-check).
|
|
1028
1035
|
|
|
1029
1036
|
For each sub-package, run update-entity to register it:
|
|
1030
1037
|
|
|
@@ -1034,7 +1041,7 @@ ${subPackages.map((sp) => ` • ${sp.name} (${sp.relativePath})`).join("\n")
|
|
|
1034
1041
|
--subtype "<chosen subtype>" \\
|
|
1035
1042
|
--name "<human readable name>" \\
|
|
1036
1043
|
--description "<what this package does and its role in the project>" \\
|
|
1037
|
-
--icon "<
|
|
1044
|
+
--icon "<lucide icon>" # applications only
|
|
1038
1045
|
|
|
1039
1046
|
Then register it as a resolvable alias so future scans don't re-surface it as a candidate:
|
|
1040
1047
|
|
|
@@ -1158,8 +1165,7 @@ ${subPkgSection}${gapCheckSection}`;
|
|
|
1158
1165
|
instructions: buildEnrichmentInstructions(),
|
|
1159
1166
|
iconHints: {
|
|
1160
1167
|
provider: "lucide",
|
|
1161
|
-
|
|
1162
|
-
note: "Use curated list for agent-selected enrichment icons; omit icon when low confidence.",
|
|
1168
|
+
note: "Use any Lucide icon name for agent-selected enrichment icons; omit icon when low confidence.",
|
|
1163
1169
|
},
|
|
1164
1170
|
projectEntity: {
|
|
1165
1171
|
externalKey: projectExternalKey,
|
package/dist/commands/setup.js
CHANGED
|
@@ -59,6 +59,9 @@ export async function setup(args) {
|
|
|
59
59
|
console.log("\nDone. Restart your MCP client for the changes to take effect.");
|
|
60
60
|
}
|
|
61
61
|
console.log("\nRegistering this runtime as a Nexarch agent…\n");
|
|
62
|
-
|
|
62
|
+
const initAgentArgs = args.includes("--strict") ? [...args] : [...args, "--strict"];
|
|
63
|
+
if (!initAgentArgs.includes("--from-setup"))
|
|
64
|
+
initAgentArgs.push("--from-setup");
|
|
65
|
+
await initAgent(initAgentArgs);
|
|
63
66
|
console.log("\nSetup complete: MCP client config + agent registration are now in place.");
|
|
64
67
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import process from "process";
|
|
2
2
|
import { requireCredentials } from "../lib/credentials.js";
|
|
3
3
|
import { callMcpTool } from "../lib/mcp.js";
|
|
4
|
-
import { CURATED_AGENT_ICON_SET } from "../lib/application-icons.js";
|
|
5
4
|
function parseFlag(args, flag) {
|
|
6
5
|
return args.includes(flag);
|
|
7
6
|
}
|
|
@@ -52,10 +51,6 @@ export async function updateEntity(args) {
|
|
|
52
51
|
const policyContext = policyBundleHash
|
|
53
52
|
? { policyBundleHash, alignmentSummary: { score: 1, violations: [], waivers: [] } }
|
|
54
53
|
: undefined;
|
|
55
|
-
if (iconName && !CURATED_AGENT_ICON_SET.has(iconName)) {
|
|
56
|
-
console.error(`error: --icon must be one of the curated agent icons (got '${iconName}')`);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
54
|
const entity = {
|
|
60
55
|
externalKey,
|
|
61
56
|
entityTypeCode,
|
package/dist/index.js
CHANGED
|
@@ -87,7 +87,7 @@ Usage:
|
|
|
87
87
|
--description <text>
|
|
88
88
|
--entity-type <code> (default: application)
|
|
89
89
|
--subtype <code>
|
|
90
|
-
--icon <lucide-name> (
|
|
90
|
+
--icon <lucide-name> (full Lucide set; for agent enrichment)
|
|
91
91
|
--json
|
|
92
92
|
nexarch add-relationship
|
|
93
93
|
Add a relationship between two existing graph entities.
|