nex-code 0.3.2 → 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,9 +18,15 @@
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
+ ---
25
+ ## Demo
26
+
27
+ https://github.com/user-attachments/assets/634e70eb-645c-42f7-a604-824f17e49840
28
+
29
+
24
30
  ---
25
31
 
26
32
  ## Quickstart
@@ -49,7 +55,7 @@ That's it. You'll see the banner, your project context, and the `>` prompt. Star
49
55
  | **Multi-provider** | 5 providers, swap at runtime | Anthropic only | Multi-provider | Multi-provider |
50
56
  | **Free local models** | Ollama (no API key) | — | Ollama | — |
51
57
  | **Runtime dependencies** | 2 (axios, dotenv) | Heavy | Heavy | Electron |
52
- | **Test coverage** | 1780 tests, 90% coverage | — | — | — |
58
+ | **Test coverage** | 1783 tests, 90% coverage | — | — | — |
53
59
  | **Tool tiers** | Auto-adapts tools per model | Fixed | Fixed | Fixed |
54
60
  | **No lock-in** | `/model openai:gpt-4o` ↔ `/model local:llama3` | Anthropic only | Config change | Config change |
55
61
 
@@ -321,6 +327,7 @@ On startup, the CLI reads your project and injects context into the system promp
321
327
  - `README.md` — first 50 lines
322
328
  - Git info — branch, status, recent commits
323
329
  - `.gitignore` content
330
+ - **Merge conflicts** — detected and shown as a red warning; included in LLM context so the agent avoids editing conflicted files
324
331
 
325
332
  ### Context Engine
326
333
  Automatic token management with compression when the context window gets full. Tracks token usage across system prompt, conversation, tool results, and tool definitions.
@@ -332,6 +339,7 @@ Three tiers of protection:
332
339
  - **SSH read-only safe list**: Common read-only SSH commands (`systemctl status`, `journalctl`, `tail`, `cat`, `git pull`, etc.) skip the dangerous-command confirmation
333
340
  - **Path protection**: Sensitive paths (`.ssh/`, `.aws/`, `.env`, credentials) are blocked from file operations
334
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
335
343
 
336
344
  ### Sessions
337
345
  Save and restore conversations:
@@ -681,7 +689,7 @@ npm test # Run all tests with coverage
681
689
  npm run test:watch # Watch mode
682
690
  ```
683
691
 
684
- 43 test suites, 1780 tests, 90% statement / 83% branch coverage.
692
+ 43 test suites, 1783 tests, 90% statement / 83% branch coverage.
685
693
 
686
694
  CI runs on GitHub Actions (Node 18/20/22).
687
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)) {
@@ -72,9 +80,18 @@ function printContext(cwd) {
72
80
 
73
81
  const branch = safe(() => execSync('git branch --show-current', { cwd, encoding: 'utf-8', stdio: 'pipe' }).trim());
74
82
 
75
- console.log(`${C.dim} cwd: ${cwd}${C.reset}`);
76
83
  if (project) console.log(`${C.dim} project: ${project}${C.reset}`);
77
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
+
78
95
  console.log();
79
96
  }
80
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/cli/ui.js CHANGED
@@ -66,7 +66,7 @@ function banner(modelName, cwd, opts = {}) {
66
66
 
67
67
  console.log(`
68
68
  ${logo}
69
- ${d}Agentic Coding CLI v0.3.0${r}
69
+ ${d}Agentic Coding CLI v${require('../package.json').version}${r}
70
70
  ${d}Model: ${modelName}${r} ${d}· /help${r}${yoloTag}
71
71
  `);
72
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nex-code",
3
- "version": "0.3.2",
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": [