gitnexus 1.6.3-rc.34 → 1.6.3-rc.35

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 CHANGED
@@ -166,11 +166,11 @@ gitnexus wiki [path] # Generate LLM-powered docs from knowledge grap
166
166
  gitnexus wiki --model <model> # Wiki with custom LLM model (default: gpt-4o-mini)
167
167
 
168
168
  # Repository groups (multi-repo / monorepo service tracking)
169
- gitnexus group create <name> # Create a repository group
170
- gitnexus group add <name> <repo> # Add a repo to a group
171
- gitnexus group remove <name> <repo> # Remove a repo from a group
172
- gitnexus group list [name] # List groups, or show one group's config
173
- gitnexus group sync <name> # Extract contracts and match across repos/services
169
+ gitnexus group create <name> # Create a repository group
170
+ gitnexus group add <group> <groupPath> <registryName> # Add a repo to a group. <groupPath> is a hierarchy path (e.g. hr/hiring/backend); <registryName> is the repo's name from the registry (see `gitnexus list`)
171
+ gitnexus group remove <group> <groupPath> # Remove a repo from a group by its hierarchy path
172
+ gitnexus group list [name] # List groups, or show one group's config
173
+ gitnexus group sync <name> # Extract contracts and match across repos/services
174
174
  gitnexus group contracts <name> # Inspect extracted contracts and cross-links
175
175
  gitnexus group query <name> <q> # Search execution flows across all repos in a group
176
176
  gitnexus group status <name> # Check staleness of repos in a group
package/dist/cli/setup.js CHANGED
@@ -12,6 +12,7 @@ import { execFile, execFileSync } from 'child_process';
12
12
  import { promisify } from 'util';
13
13
  import { fileURLToPath } from 'url';
14
14
  import { glob } from 'glob';
15
+ import { parseTree, modify, applyEdits } from 'jsonc-parser';
15
16
  import { getGlobalDir } from '../storage/repo-manager.js';
16
17
  const __filename = fileURLToPath(import.meta.url);
17
18
  const __dirname = path.dirname(__filename);
@@ -63,6 +64,20 @@ function getMcpEntry() {
63
64
  args: ['-y', 'gitnexus@latest', 'mcp'],
64
65
  };
65
66
  }
67
+ /**
68
+ * OpenCode uses a different MCP format: { type: "local", command: [...] }
69
+ * where command is a flat array (command + args combined).
70
+ */
71
+ function getOpenCodeMcpEntry() {
72
+ const bin = resolveGitnexusBin();
73
+ if (bin) {
74
+ return { type: 'local', command: [bin, 'mcp'] };
75
+ }
76
+ if (process.platform === 'win32') {
77
+ return { type: 'local', command: ['cmd', '/c', 'npx', '-y', 'gitnexus@latest', 'mcp'] };
78
+ }
79
+ return { type: 'local', command: ['npx', '-y', 'gitnexus@latest', 'mcp'] };
80
+ }
66
81
  /**
67
82
  * Merge gitnexus entry into an existing MCP config JSON object.
68
83
  * Returns the updated config.
@@ -96,6 +111,56 @@ async function writeJsonFile(filePath, data) {
96
111
  await fs.mkdir(path.dirname(filePath), { recursive: true });
97
112
  await fs.writeFile(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
98
113
  }
114
+ /**
115
+ * Detect indentation style from file content.
116
+ * Returns formatting options matching the file's existing style.
117
+ */
118
+ function detectIndentation(raw) {
119
+ const firstIndented = raw.match(/^( +|\t)/m);
120
+ if (!firstIndented)
121
+ return { tabSize: 2, insertSpaces: true };
122
+ if (firstIndented[1] === '\t')
123
+ return { tabSize: 1, insertSpaces: false };
124
+ return { tabSize: firstIndented[1].length, insertSpaces: true };
125
+ }
126
+ /**
127
+ * Merge a key/value pair into a JSONC config file, preserving comments and formatting.
128
+ * If the file is genuinely corrupt (not valid JSONC), leaves it untouched.
129
+ */
130
+ async function mergeJsoncFile(filePath, keyPath, value) {
131
+ let raw;
132
+ try {
133
+ raw = await fs.readFile(filePath, 'utf-8');
134
+ }
135
+ catch {
136
+ raw = '';
137
+ }
138
+ if (raw.trim().length === 0) {
139
+ const config = {};
140
+ let parent = config;
141
+ for (let i = 0; i < keyPath.length; i++) {
142
+ if (i === keyPath.length - 1) {
143
+ parent[keyPath[i]] = value;
144
+ }
145
+ else {
146
+ parent[keyPath[i]] = {};
147
+ parent = parent[keyPath[i]];
148
+ }
149
+ }
150
+ await writeJsonFile(filePath, config);
151
+ return true;
152
+ }
153
+ const parseErrors = [];
154
+ const tree = parseTree(raw, parseErrors);
155
+ if (tree && tree.type === 'object' && parseErrors.length === 0) {
156
+ const formattingOptions = detectIndentation(raw);
157
+ const edits = modify(raw, keyPath, value, { formattingOptions });
158
+ const result = applyEdits(raw, edits);
159
+ await fs.writeFile(filePath, result, 'utf-8');
160
+ return true;
161
+ }
162
+ return false;
163
+ }
99
164
  /**
100
165
  * Check if a directory exists
101
166
  */
@@ -226,13 +291,13 @@ async function setupOpenCode(result) {
226
291
  }
227
292
  const configPath = path.join(opencodeDir, 'opencode.json');
228
293
  try {
229
- const existing = await readJsonFile(configPath);
230
- const config = existing || {};
231
- if (!config.mcp)
232
- config.mcp = {};
233
- config.mcp.gitnexus = getMcpEntry();
234
- await writeJsonFile(configPath, config);
235
- result.configured.push('OpenCode');
294
+ const ok = await mergeJsoncFile(configPath, ['mcp', 'gitnexus'], getOpenCodeMcpEntry());
295
+ if (ok) {
296
+ result.configured.push('OpenCode');
297
+ }
298
+ else {
299
+ result.errors.push('OpenCode: opencode.json is corrupt — skipping to preserve existing content');
300
+ }
236
301
  }
237
302
  catch (err) {
238
303
  result.errors.push(`OpenCode: ${err.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.3-rc.34",
3
+ "version": "1.6.3-rc.35",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",
@@ -65,6 +65,7 @@
65
65
  "graphology-utils": "^2.3.0",
66
66
  "ignore": "^7.0.5",
67
67
  "js-yaml": "^4.1.1",
68
+ "jsonc-parser": "^3.3.1",
68
69
  "lru-cache": "^11.0.0",
69
70
  "mnemonist": "^0.40.3",
70
71
  "onnxruntime-node": "^1.24.0",