nex-code 0.3.3 → 0.3.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.
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
19
19
  <img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg" alt="Node >= 18">
20
20
  <img src="https://img.shields.io/badge/dependencies-2-green.svg" alt="Dependencies: 2">
21
- <img src="https://img.shields.io/badge/tests-1780-blue.svg" alt="Tests: 1780">
21
+ <img src="https://img.shields.io/badge/tests-1783-blue.svg" alt="Tests: 1783">
22
22
  </p>
23
23
 
24
24
  ---
@@ -55,7 +55,7 @@ That's it. You'll see the banner, your project context, and the `>` prompt. Star
55
55
  | **Multi-provider** | 5 providers, swap at runtime | Anthropic only | Multi-provider | Multi-provider |
56
56
  | **Free local models** | Ollama (no API key) | — | Ollama | — |
57
57
  | **Runtime dependencies** | 2 (axios, dotenv) | Heavy | Heavy | Electron |
58
- | **Test coverage** | 1780 tests, 90% coverage | — | — | — |
58
+ | **Test coverage** | 1783 tests, 90% coverage | — | — | — |
59
59
  | **Tool tiers** | Auto-adapts tools per model | Fixed | Fixed | Fixed |
60
60
  | **No lock-in** | `/model openai:gpt-4o` ↔ `/model local:llama3` | Anthropic only | Config change | Config change |
61
61
 
@@ -327,6 +327,7 @@ On startup, the CLI reads your project and injects context into the system promp
327
327
  - `README.md` — first 50 lines
328
328
  - Git info — branch, status, recent commits
329
329
  - `.gitignore` content
330
+ - **Merge conflicts** — detected and shown as a red warning; included in LLM context so the agent avoids editing conflicted files
330
331
 
331
332
  ### Context Engine
332
333
  Automatic token management with compression when the context window gets full. Tracks token usage across system prompt, conversation, tool results, and tool definitions.
@@ -338,6 +339,7 @@ Three tiers of protection:
338
339
  - **SSH read-only safe list**: Common read-only SSH commands (`systemctl status`, `journalctl`, `tail`, `cat`, `git pull`, etc.) skip the dangerous-command confirmation
339
340
  - **Path protection**: Sensitive paths (`.ssh/`, `.aws/`, `.env`, credentials) are blocked from file operations
340
341
  - **Pre-push secret detection**: Git hook scans diffs for API keys, private keys, hardcoded secrets, SSH+IP patterns, and `.env` leaks before allowing push
342
+ - **Post-merge automation**: Auto-bumps patch version on `devel→main` merge; runs `npm install` when `package.json` changes
341
343
 
342
344
  ### Sessions
343
345
  Save and restore conversations:
@@ -687,7 +689,7 @@ npm test # Run all tests with coverage
687
689
  npm run test:watch # Watch mode
688
690
  ```
689
691
 
690
- 43 test suites, 1780 tests, 90% statement / 83% branch coverage.
692
+ 43 test suites, 1783 tests, 90% statement / 83% branch coverage.
691
693
 
692
694
  CI runs on GitHub Actions (Node 18/20/22).
693
695
 
package/cli/context.js CHANGED
@@ -6,6 +6,7 @@ const fs = require('fs');
6
6
  const path = require('path');
7
7
  const { execSync } = require('child_process');
8
8
  const { C } = require('./ui');
9
+ const { getMergeConflicts } = require('./git');
9
10
 
10
11
  function safe(fn) {
11
12
  try {
@@ -50,6 +51,13 @@ function gatherProjectContext(cwd) {
50
51
  );
51
52
  if (log) parts.push(`RECENT COMMITS:\n${log}`);
52
53
 
54
+ // Merge conflicts
55
+ const conflicts = getMergeConflicts();
56
+ if (conflicts.length > 0) {
57
+ const conflictFiles = conflicts.map(c => ` ${c.file}`).join('\n');
58
+ parts.push(`MERGE CONFLICTS (resolve before editing these files):\n${conflictFiles}`);
59
+ }
60
+
53
61
  // .gitignore
54
62
  const giPath = path.join(cwd, '.gitignore');
55
63
  if (fs.existsSync(giPath)) {
@@ -74,6 +82,16 @@ function printContext(cwd) {
74
82
 
75
83
  if (project) console.log(`${C.dim} project: ${project}${C.reset}`);
76
84
  if (branch) console.log(`${C.dim} branch: ${branch}${C.reset}`);
85
+
86
+ const conflicts = getMergeConflicts();
87
+ if (conflicts.length > 0) {
88
+ console.log(`${C.red} ⚠ ${conflicts.length} unresolved merge conflict(s):${C.reset}`);
89
+ for (const c of conflicts) {
90
+ console.log(`${C.red} ${c.file}${C.reset}`);
91
+ }
92
+ console.log(`${C.yellow} → Resolve conflicts before starting tasks${C.reset}`);
93
+ }
94
+
77
95
  console.log();
78
96
  }
79
97
 
package/cli/git.js CHANGED
@@ -168,6 +168,14 @@ function formatDiffSummary() {
168
168
  return lines.join('\n');
169
169
  }
170
170
 
171
+ /**
172
+ * Get files with unresolved merge conflicts (UU, AA, DD)
173
+ */
174
+ function getMergeConflicts() {
175
+ const status = getStatus();
176
+ return status.filter(s => s.status === 'UU' || s.status === 'AA' || s.status === 'DD');
177
+ }
178
+
171
179
  /**
172
180
  * Get diff-aware context (only changed files' content)
173
181
  * For use when the user is working on git-related tasks
@@ -199,4 +207,5 @@ module.exports = {
199
207
  commit,
200
208
  formatDiffSummary,
201
209
  getDiffContext,
210
+ getMergeConflicts,
202
211
  };
package/cli/sub-agent.js CHANGED
@@ -48,7 +48,6 @@ function isRetryableError(err) {
48
48
  return false;
49
49
  }
50
50
 
51
- <<<<<<< Updated upstream
52
51
  async function callWithRetry(messages, tools, options) {
53
52
  let lastError;
54
53
  for (let attempt = 0; attempt <= MAX_CHAT_RETRIES; attempt++) {
@@ -56,13 +55,6 @@ async function callWithRetry(messages, tools, options) {
56
55
  // Use callStream (stream:true) — more reliable than callChat (stream:false)
57
56
  // with Ollama Cloud. Silently collect the full response via no-op onToken.
58
57
  return await callStream(messages, tools, { ...options, onToken: () => {} });
59
- =======
60
- async function callChatWithRetry(messages, tools, options) {
61
- let lastError;
62
- for (let attempt = 0; attempt <= MAX_CHAT_RETRIES; attempt++) {
63
- try {
64
- return await callChat(messages, tools, options);
65
- >>>>>>> Stashed changes
66
58
  } catch (err) {
67
59
  lastError = err;
68
60
  if (attempt < MAX_CHAT_RETRIES && isRetryableError(err)) {
@@ -224,11 +216,7 @@ ERROR RECOVERY:
224
216
 
225
217
  try {
226
218
  for (let i = 0; i < maxIter; i++) {
227
- <<<<<<< Updated upstream
228
219
  const result = await callWithRetry(messages, availableTools, chatOptions);
229
- =======
230
- const result = await callChatWithRetry(messages, availableTools, chatOptions);
231
- >>>>>>> Stashed changes
232
220
 
233
221
  // Guard against null/undefined responses
234
222
  if (!result || typeof result !== 'object') {
@@ -434,8 +422,4 @@ async function executeSpawnAgents(args) {
434
422
  }
435
423
  }
436
424
 
437
- <<<<<<< Updated upstream
438
425
  module.exports = { runSubAgent, executeSpawnAgents, clearAllLocks, classifyTask, pickModelForTier, resolveSubAgentModel, isRetryableError, callWithRetry };
439
- =======
440
- module.exports = { runSubAgent, executeSpawnAgents, clearAllLocks, classifyTask, pickModelForTier, resolveSubAgentModel, isRetryableError, callChatWithRetry };
441
- >>>>>>> Stashed changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nex-code",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Nex Code — Agentic Coding CLI with Multi-Provider Support",
5
5
  "bin": {
6
6
  "nex-code": "./bin/nex-code.js"
@@ -19,7 +19,7 @@
19
19
  "test": "jest --coverage",
20
20
  "test:watch": "jest --watch",
21
21
  "format": "prettier --write .",
22
- "install-hooks": "ln -sf ../../hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push && echo 'pre-push hook installed.'",
22
+ "install-hooks": "ln -sf ../../hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push && ln -sf ../../hooks/post-merge .git/hooks/post-merge && chmod +x .git/hooks/post-merge && echo 'Hooks installed (pre-push, post-merge).'",
23
23
  "prepublishOnly": "npm test"
24
24
  },
25
25
  "keywords": [