nexarch 0.8.17 → 0.8.20

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,6 +1,6 @@
1
1
  import { arch, homedir, hostname, platform, release, type as osType, userInfo } from "os";
2
2
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
3
- import { join } from "path";
3
+ import { join, resolve } from "path";
4
4
  import * as readline from "node:readline/promises";
5
5
  import process from "process";
6
6
  import { requireCredentials } from "../lib/credentials.js";
@@ -8,7 +8,7 @@ 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 = "0.8.17";
11
+ const CLI_VERSION = "0.8.20";
12
12
  const AGENT_ENTITY_TYPE = "agent";
13
13
  const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
14
14
  function parseFlag(args, flag) {
@@ -301,14 +301,13 @@ function replaceManagedSection(existing, key, body) {
301
301
  const markers = managedMarkers(key);
302
302
  const escapedStart = markers.start.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
303
303
  const escapedEnd = markers.end.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
304
- const managedRegex = new RegExp(`${escapedStart}[\\s\\S]*?${escapedEnd}`, "gm");
304
+ const managedRegex = new RegExp(`${escapedStart}[\\s\\S]*?${escapedEnd}\\s*`, "gm");
305
305
  if (!managedRegex.test(existing))
306
306
  return existing;
307
307
  const canonicalBlock = wrapManagedSection(key, body);
308
- let replaced = existing.replace(managedRegex, canonicalBlock);
309
- // collapse accidental duplicates if multiple managed blocks exist
310
- replaced = replaced.replace(new RegExp(`(${escapedStart}[\\s\\S]*?${escapedEnd})(?:\\s*${escapedStart}[\\s\\S]*?${escapedEnd})+`, "gm"), "$1");
311
- return replaced.endsWith("\n") ? replaced : `${replaced}\n`;
308
+ const stripped = existing.replace(managedRegex, "").trimEnd();
309
+ const rebuilt = `${stripped}${stripped ? "\n\n" : ""}${canonicalBlock}\n`;
310
+ return rebuilt;
312
311
  }
313
312
  function replaceInjectedSection(existing, sectionHeading, sectionBody) {
314
313
  const escapedHeading = sectionHeading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -321,10 +320,15 @@ function replaceInjectedSection(existing, sectionHeading, sectionBody) {
321
320
  replaced = replaced.replace(/\n{3,}/g, "\n\n").trimEnd();
322
321
  return `${replaced}${replaced ? "\n\n" : ""}${canonicalBlock}`;
323
322
  }
323
+ function canonicalTargetKey(filePath) {
324
+ const abs = resolve(filePath);
325
+ return process.platform === "win32" || process.platform === "darwin" ? abs.toLowerCase() : abs;
326
+ }
324
327
  function injectAgentConfigs(registry) {
325
328
  const templateByCode = new Map(registry.instructionTemplates.map((t) => [t.code, t]));
326
329
  const targets = [...registry.instructionTargets].sort((a, b) => a.sortOrder - b.sortOrder || a.filePathPattern.localeCompare(b.filePathPattern));
327
330
  const results = [];
331
+ const seenTargets = new Set();
328
332
  for (const target of targets) {
329
333
  if (target.matchMode !== "exact")
330
334
  continue;
@@ -332,6 +336,10 @@ function injectAgentConfigs(registry) {
332
336
  if (!template)
333
337
  continue;
334
338
  const filePath = join(process.cwd(), target.filePathPattern);
339
+ const targetKey = canonicalTargetKey(filePath);
340
+ if (seenTargets.has(targetKey))
341
+ continue;
342
+ seenTargets.add(targetKey);
335
343
  if (!existsSync(filePath))
336
344
  continue;
337
345
  const existing = readFileSync(filePath, "utf8");
@@ -426,11 +434,16 @@ function injectGenericAgentConfig(registry) {
426
434
  const genericTargets = [...registry.instructionTargets]
427
435
  .filter((t) => t.runtimeCode === "generic" && t.matchMode === "exact")
428
436
  .sort((a, b) => a.sortOrder - b.sortOrder || a.filePathPattern.localeCompare(b.filePathPattern));
437
+ const seenTargets = new Set();
429
438
  for (const target of genericTargets) {
430
439
  const template = templateByCode.get(target.templateCode);
431
440
  if (!template)
432
441
  continue;
433
442
  const filePath = join(process.cwd(), target.filePathPattern);
443
+ const targetKey = canonicalTargetKey(filePath);
444
+ if (seenTargets.has(targetKey))
445
+ continue;
446
+ seenTargets.add(targetKey);
434
447
  const sectionBody = template.body.trim();
435
448
  const sectionHeading = target.sectionHeading ?? "## Nexarch Agent Registration";
436
449
  const managedBody = wrapManagedSection("agent-registration", sectionBody);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexarch",
3
- "version": "0.8.17",
3
+ "version": "0.8.20",
4
4
  "description": "Your architecture workspace for AI delivery.",
5
5
  "keywords": [
6
6
  "nexarch",