nexarch 0.1.5 → 0.1.6
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/README.md +2 -1
- package/dist/commands/init-agent.js +221 -2
- package/dist/index.js +3 -1
- package/dist/lib/mcp.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,8 @@ npx nexarch setup
|
|
|
19
19
|
| `nexarch setup` | Auto-configure detected MCP clients |
|
|
20
20
|
| `nexarch mcp-config [client]` | Print config block for manual setup (`claude-desktop`, `cursor`, `windsurf`) |
|
|
21
21
|
| `nexarch mcp-proxy` | stdio→HTTP bridge used internally by MCP clients |
|
|
22
|
-
| `nexarch init-agent [--json] [--strict]` | Run onboarding handshake
|
|
22
|
+
| `nexarch init-agent [--json] [--strict] [--agent-id <id>]` | Run onboarding handshake and mandatory `agent` entity registration in graph |
|
|
23
|
+
| `nexarch init-agent --bind-to-external-key <key> [--bind-relationship-type <code>]` | Optionally bind the agent node to an existing graph external key |
|
|
23
24
|
|
|
24
25
|
## Requirements
|
|
25
26
|
|
|
@@ -1,15 +1,75 @@
|
|
|
1
|
+
import { hostname, userInfo } from "os";
|
|
2
|
+
import { requireCredentials } from "../lib/credentials.js";
|
|
1
3
|
import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
|
|
4
|
+
const CLI_VERSION = "0.1.6";
|
|
2
5
|
function parseFlag(args, flag) {
|
|
3
6
|
return args.includes(flag);
|
|
4
7
|
}
|
|
8
|
+
function parseOptionValue(args, option) {
|
|
9
|
+
const idx = args.indexOf(option);
|
|
10
|
+
if (idx === -1)
|
|
11
|
+
return null;
|
|
12
|
+
const value = args[idx + 1];
|
|
13
|
+
if (!value || value.startsWith("--"))
|
|
14
|
+
return null;
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
5
17
|
function parseToolText(result) {
|
|
6
18
|
const text = result.content?.[0]?.text ?? "{}";
|
|
7
19
|
return JSON.parse(text);
|
|
8
20
|
}
|
|
21
|
+
function getDefaultAgentId() {
|
|
22
|
+
const osUser = process.env.USERNAME || process.env.USER || userInfo().username || "unknown";
|
|
23
|
+
const host = hostname() || "unknown-host";
|
|
24
|
+
return `nexarch-cli:${osUser}@${host}`;
|
|
25
|
+
}
|
|
26
|
+
async function emitInitObservation(params) {
|
|
27
|
+
if (!params.policyBundleHash)
|
|
28
|
+
return;
|
|
29
|
+
const nowIso = new Date().toISOString();
|
|
30
|
+
try {
|
|
31
|
+
await callMcpTool("nexarch_emit_observations", {
|
|
32
|
+
observations: [
|
|
33
|
+
{
|
|
34
|
+
kind: "entity",
|
|
35
|
+
externalKey: `agent:${params.agentId}`,
|
|
36
|
+
message: params.message,
|
|
37
|
+
confidence: params.confidence ?? 0.6,
|
|
38
|
+
evidence: { source: "nexarch init-agent", timestamp: nowIso },
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
agentContext: {
|
|
42
|
+
agentId: params.agentId,
|
|
43
|
+
agentRunId: `init-agent-${Date.now()}`,
|
|
44
|
+
repoRef: "nexarch-cli/init-agent",
|
|
45
|
+
observedAt: nowIso,
|
|
46
|
+
source: "nexarch-cli",
|
|
47
|
+
model: "n/a",
|
|
48
|
+
provider: "n/a",
|
|
49
|
+
},
|
|
50
|
+
policyContext: {
|
|
51
|
+
policyBundleHash: params.policyBundleHash,
|
|
52
|
+
alignmentSummary: {
|
|
53
|
+
score: 1,
|
|
54
|
+
violations: [],
|
|
55
|
+
waivers: [],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// non-fatal telemetry path
|
|
62
|
+
}
|
|
63
|
+
}
|
|
9
64
|
export async function initAgent(args) {
|
|
10
65
|
const asJson = parseFlag(args, "--json");
|
|
11
66
|
const strict = parseFlag(args, "--strict");
|
|
67
|
+
const explicitAgentId = parseOptionValue(args, "--agent-id");
|
|
68
|
+
const bindToExternalKey = parseOptionValue(args, "--bind-to-external-key");
|
|
69
|
+
const bindRelationshipType = parseOptionValue(args, "--bind-relationship-type") ?? "depends_on";
|
|
70
|
+
const agentId = explicitAgentId ?? getDefaultAgentId();
|
|
12
71
|
const checks = [];
|
|
72
|
+
const creds = requireCredentials();
|
|
13
73
|
const init = await mcpInitialize();
|
|
14
74
|
checks.push({
|
|
15
75
|
name: "mcp.initialize",
|
|
@@ -23,6 +83,7 @@ export async function initAgent(args) {
|
|
|
23
83
|
"nexarch_get_ingest_contract",
|
|
24
84
|
"nexarch_upsert_entities",
|
|
25
85
|
"nexarch_upsert_relationships",
|
|
86
|
+
"nexarch_emit_observations",
|
|
26
87
|
];
|
|
27
88
|
const missing = required.filter((name) => !toolNames.has(name));
|
|
28
89
|
checks.push({
|
|
@@ -46,6 +107,154 @@ export async function initAgent(args) {
|
|
|
46
107
|
ok: Boolean(contract.contractVersion),
|
|
47
108
|
detail: `version=${contract.contractVersion ?? "unknown"}; entities=${contract.ontology?.entityCodes?.length ?? 0}; relationships=${contract.ontology?.relationshipCodes?.length ?? 0}`,
|
|
48
109
|
});
|
|
110
|
+
const hasAgentType = (contract.ontology?.entityCodes ?? []).some((code) => code.toLowerCase() === "agent");
|
|
111
|
+
checks.push({
|
|
112
|
+
name: "ontology.agent-type",
|
|
113
|
+
ok: hasAgentType,
|
|
114
|
+
detail: hasAgentType
|
|
115
|
+
? "entity type 'agent' is enabled"
|
|
116
|
+
: "entity type 'agent' is not enabled for this workspace ontology",
|
|
117
|
+
});
|
|
118
|
+
const preflightPassed = checks.every((c) => c.ok);
|
|
119
|
+
let registration = {
|
|
120
|
+
ok: false,
|
|
121
|
+
detail: "registration not attempted",
|
|
122
|
+
};
|
|
123
|
+
let binding = {
|
|
124
|
+
attempted: false,
|
|
125
|
+
ok: true,
|
|
126
|
+
detail: "not requested",
|
|
127
|
+
};
|
|
128
|
+
if (preflightPassed && policies.policyBundleHash) {
|
|
129
|
+
const nowIso = new Date().toISOString();
|
|
130
|
+
const upsertRaw = await callMcpTool("nexarch_upsert_entities", {
|
|
131
|
+
entities: [
|
|
132
|
+
{
|
|
133
|
+
externalKey: `agent:${agentId}`,
|
|
134
|
+
entityTypeCode: "agent",
|
|
135
|
+
name: `Agent ${agentId}`,
|
|
136
|
+
description: "Agent identity registered from nexarch init-agent handshake",
|
|
137
|
+
confidence: 1,
|
|
138
|
+
attributes: {
|
|
139
|
+
kind: "ai_agent",
|
|
140
|
+
client: "nexarch-cli",
|
|
141
|
+
version: CLI_VERSION,
|
|
142
|
+
companyId: creds.companyId,
|
|
143
|
+
handshake: {
|
|
144
|
+
completedAt: nowIso,
|
|
145
|
+
source: "init-agent",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
agentContext: {
|
|
151
|
+
agentId,
|
|
152
|
+
agentRunId: `init-agent-${Date.now()}`,
|
|
153
|
+
repoRef: "nexarch-cli/init-agent",
|
|
154
|
+
observedAt: nowIso,
|
|
155
|
+
source: "nexarch-cli",
|
|
156
|
+
model: "n/a",
|
|
157
|
+
provider: "n/a",
|
|
158
|
+
},
|
|
159
|
+
policyContext: {
|
|
160
|
+
policyBundleHash: policies.policyBundleHash,
|
|
161
|
+
alignmentSummary: {
|
|
162
|
+
score: 1,
|
|
163
|
+
violations: [],
|
|
164
|
+
waivers: [],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
dryRun: false,
|
|
168
|
+
});
|
|
169
|
+
const upsert = parseToolText(upsertRaw);
|
|
170
|
+
const firstResult = upsert.results?.[0];
|
|
171
|
+
const failed = Number(upsert.summary?.failed ?? 0) > 0;
|
|
172
|
+
registration = {
|
|
173
|
+
ok: !failed,
|
|
174
|
+
detail: failed
|
|
175
|
+
? `failed to register agent entry (${upsert.errors?.[0]?.error ?? "unknown"})`
|
|
176
|
+
: `agent entry ${firstResult?.action ?? "upserted"}`,
|
|
177
|
+
graphEntityId: firstResult?.graphEntityId ?? null,
|
|
178
|
+
action: firstResult?.action ?? null,
|
|
179
|
+
errors: upsert.errors,
|
|
180
|
+
};
|
|
181
|
+
if (!registration.ok) {
|
|
182
|
+
await emitInitObservation({
|
|
183
|
+
agentId,
|
|
184
|
+
policyBundleHash: policies.policyBundleHash,
|
|
185
|
+
message: `init-agent registration failed: ${registration.detail}`,
|
|
186
|
+
confidence: 1,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (registration.ok && bindToExternalKey) {
|
|
190
|
+
binding.attempted = true;
|
|
191
|
+
const relRaw = await callMcpTool("nexarch_upsert_relationships", {
|
|
192
|
+
relationships: [
|
|
193
|
+
{
|
|
194
|
+
relationshipTypeCode: bindRelationshipType,
|
|
195
|
+
fromEntityExternalKey: `agent:${agentId}`,
|
|
196
|
+
toEntityExternalKey: bindToExternalKey,
|
|
197
|
+
confidence: 1,
|
|
198
|
+
attributes: {
|
|
199
|
+
source: "nexarch-cli-init-agent",
|
|
200
|
+
createdAt: nowIso,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
agentContext: {
|
|
205
|
+
agentId,
|
|
206
|
+
agentRunId: `init-agent-bind-${Date.now()}`,
|
|
207
|
+
repoRef: "nexarch-cli/init-agent",
|
|
208
|
+
observedAt: nowIso,
|
|
209
|
+
source: "nexarch-cli",
|
|
210
|
+
model: "n/a",
|
|
211
|
+
provider: "n/a",
|
|
212
|
+
},
|
|
213
|
+
policyContext: {
|
|
214
|
+
policyBundleHash: policies.policyBundleHash,
|
|
215
|
+
alignmentSummary: {
|
|
216
|
+
score: 1,
|
|
217
|
+
violations: [],
|
|
218
|
+
waivers: [],
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
dryRun: false,
|
|
222
|
+
});
|
|
223
|
+
const rel = parseToolText(relRaw);
|
|
224
|
+
const relResult = rel.results?.[0];
|
|
225
|
+
const relFailed = Number(rel.summary?.failed ?? 0) > 0;
|
|
226
|
+
binding = {
|
|
227
|
+
attempted: true,
|
|
228
|
+
ok: !relFailed,
|
|
229
|
+
detail: relFailed
|
|
230
|
+
? `failed to bind agent (${rel.errors?.[0]?.error ?? "unknown"})`
|
|
231
|
+
: `agent bound via ${bindRelationshipType}`,
|
|
232
|
+
graphRelationshipId: relResult?.graphRelationshipId ?? null,
|
|
233
|
+
action: relResult?.action ?? null,
|
|
234
|
+
errors: rel.errors,
|
|
235
|
+
};
|
|
236
|
+
if (!binding.ok) {
|
|
237
|
+
await emitInitObservation({
|
|
238
|
+
agentId,
|
|
239
|
+
policyBundleHash: policies.policyBundleHash,
|
|
240
|
+
message: `init-agent binding failed: ${binding.detail}`,
|
|
241
|
+
confidence: 1,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
checks.push({
|
|
247
|
+
name: "agent.registration",
|
|
248
|
+
ok: registration.ok,
|
|
249
|
+
detail: registration.detail,
|
|
250
|
+
});
|
|
251
|
+
if (binding.attempted) {
|
|
252
|
+
checks.push({
|
|
253
|
+
name: "agent.binding",
|
|
254
|
+
ok: binding.ok,
|
|
255
|
+
detail: binding.detail,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
49
258
|
const allPassed = checks.every((c) => c.ok);
|
|
50
259
|
if (asJson) {
|
|
51
260
|
const output = {
|
|
@@ -60,6 +269,10 @@ export async function initAgent(args) {
|
|
|
60
269
|
},
|
|
61
270
|
policyBundleHash: policies.policyBundleHash ?? null,
|
|
62
271
|
contractVersion: contract.contractVersion ?? null,
|
|
272
|
+
agentId,
|
|
273
|
+
registration,
|
|
274
|
+
binding,
|
|
275
|
+
companyId: creds.companyId,
|
|
63
276
|
};
|
|
64
277
|
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
65
278
|
if (strict && !allPassed)
|
|
@@ -72,12 +285,18 @@ export async function initAgent(args) {
|
|
|
72
285
|
if (check.detail)
|
|
73
286
|
console.log(` ${check.detail}`);
|
|
74
287
|
}
|
|
288
|
+
if (registration.graphEntityId) {
|
|
289
|
+
console.log(`\nRegistered graph entity: ${registration.graphEntityId}`);
|
|
290
|
+
}
|
|
291
|
+
if (binding.attempted && binding.graphRelationshipId) {
|
|
292
|
+
console.log(`Bound relationship id: ${binding.graphRelationshipId}`);
|
|
293
|
+
}
|
|
75
294
|
console.log("");
|
|
76
295
|
if (allPassed) {
|
|
77
|
-
console.log("✅ Agent handshake
|
|
296
|
+
console.log("✅ Agent handshake + registration completed.");
|
|
78
297
|
}
|
|
79
298
|
else {
|
|
80
|
-
console.log("⚠ Handshake completed with issues.");
|
|
299
|
+
console.log("⚠ Handshake/registration completed with issues.");
|
|
81
300
|
if (strict) {
|
|
82
301
|
console.log("Strict mode enabled, exiting non-zero.");
|
|
83
302
|
process.exitCode = 1;
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,9 @@ Usage:
|
|
|
29
29
|
nexarch setup Auto-configure your MCP client (Claude Desktop, Cursor, etc.)
|
|
30
30
|
nexarch mcp-config Print MCP server config block for manual setup
|
|
31
31
|
nexarch mcp-proxy Run as stdio MCP proxy (used by MCP clients)
|
|
32
|
-
nexarch init-agent Run
|
|
32
|
+
nexarch init-agent Run handshake + mandatory agent registration in graph
|
|
33
|
+
Options: --agent-id <id> --bind-to-external-key <key>
|
|
34
|
+
--bind-relationship-type <code> --json --strict
|
|
33
35
|
`);
|
|
34
36
|
process.exit(command ? 1 : 0);
|
|
35
37
|
}
|
package/dist/lib/mcp.js
CHANGED
|
@@ -61,7 +61,7 @@ export async function mcpInitialize() {
|
|
|
61
61
|
return callMcpRpc("initialize", {
|
|
62
62
|
protocolVersion: "2024-11-05",
|
|
63
63
|
capabilities: {},
|
|
64
|
-
clientInfo: { name: "nexarch-cli", version: "0.1.
|
|
64
|
+
clientInfo: { name: "nexarch-cli", version: "0.1.6" },
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
export async function mcpListTools() {
|