nimcode 0.1.6__tar.gz → 0.1.12__tar.gz

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.
Files changed (34) hide show
  1. {nimcode-0.1.6 → nimcode-0.1.12}/PKG-INFO +1 -1
  2. nimcode-0.1.12/README.md +134 -0
  3. {nimcode-0.1.6 → nimcode-0.1.12}/setup.py +1 -1
  4. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/agent.py +20 -14
  5. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/repl.py +129 -78
  6. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode.egg-info/PKG-INFO +1 -1
  7. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_repl.py +1 -5
  8. nimcode-0.1.6/README.md +0 -68
  9. {nimcode-0.1.6 → nimcode-0.1.12}/setup.cfg +0 -0
  10. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/__init__.py +0 -0
  11. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/cli.py +0 -0
  12. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/config.py +0 -0
  13. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/lenient_parser.py +0 -0
  14. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/mcp_client.py +0 -0
  15. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/memory.py +0 -0
  16. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/nim_client.py +0 -0
  17. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/permissions.py +0 -0
  18. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode/tools.py +0 -0
  19. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode.egg-info/SOURCES.txt +0 -0
  20. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode.egg-info/dependency_links.txt +0 -0
  21. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode.egg-info/entry_points.txt +0 -0
  22. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode.egg-info/requires.txt +0 -0
  23. {nimcode-0.1.6 → nimcode-0.1.12}/src/nimcode.egg-info/top_level.txt +0 -0
  24. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_agent.py +0 -0
  25. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_cli.py +0 -0
  26. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_config.py +0 -0
  27. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_lenient_parser.py +0 -0
  28. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_mcp_client.py +0 -0
  29. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_memory.py +0 -0
  30. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_nim_client.py +0 -0
  31. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_permissions.py +0 -0
  32. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_repl_extra.py +0 -0
  33. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_repl_trust.py +0 -0
  34. {nimcode-0.1.6 → nimcode-0.1.12}/tests/test_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nimcode
3
- Version: 0.1.6
3
+ Version: 0.1.12
4
4
  Summary: A standalone, robust coding agent for NVIDIA NIM models.
5
5
  Author: Autonomous Agent
6
6
  Requires-Dist: httpx>=0.27.0
@@ -0,0 +1,134 @@
1
+ <div align="center">
2
+
3
+ # 🚀 NimCode
4
+
5
+ **The Autonomous AI Coding Assistant for the NVIDIA NIM Ecosystem**
6
+
7
+ [![PyPI version](https://badge.fury.io/py/nimcode.svg)](https://badge.fury.io/py/nimcode)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ *A powerful, standalone REPL and CLI agent that writes, edits, and plans code like a senior developer—powered by LLaMa 3.1 70B (and other cutting-edge models) and the lightning-fast NVIDIA NIM API.*
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ ## 🌟 Overview
17
+
18
+ NimCode is your autonomous coding pair-programmer. Built with a rich interactive terminal interface, it doesn't just autocomplete code—it plans architectures, executes terminal commands, writes complete files, formats code automatically, and manages your workspace.
19
+
20
+ ### 🛠️ What We've Built So Far
21
+ - **Robust Interactive REPL**: Multiline support (Alt+Enter), syntax highlighting, and beautiful `rich`-powered UI menus.
22
+ - **Smart Permission Engine**: Granular control over what the AI can do, with interactive diff previews for file modifications and the brand new `/trust` mode for unhindered execution.
23
+ - **Automated Workflows**: Automatic linting and formatting using `black`, `flake8`, and `prettier` behind the scenes with crash-resistant execution.
24
+ - **CI/CD Integration**: A complete automated pipeline pushing to PyPI and creating GitHub Releases automatically on version tags.
25
+ - **Extensive Tool Ecosystem**: The agent is equipped with Bash execution, AST Replacement, Semantic Search, Web Browsing, Interactive Terminal management, and much more.
26
+ - **Model Context Protocol (MCP)**: Native integration for MCP tools allowing infinite extensibility.
27
+
28
+ ### 🚀 What We're Working On (Roadmap)
29
+ - **Sub-agent Swarms**: Perfecting `/delegate` and `/swarm` to distribute complex tasks among specialized AI roles.
30
+ - **Advanced Diagnostics**: Refining `/bughunter`, `/security-review`, and `/doctor` for automated codebase auditing.
31
+ - **Test-Driven Development**: Upgrading `/tdd` and `/testgen` to automatically write tests and ensure 100% coverage before committing.
32
+ - **Infrastructure & DevOps**: Implementing `/terraform-god` and `/sql-tune` for automated cloud provisioning and database query optimization.
33
+
34
+ ---
35
+
36
+ ## 📦 Installation
37
+
38
+ NimCode is available globally via PyPI. You can install it anywhere in seconds:
39
+
40
+ ```bash
41
+ pip install nimcode
42
+ ```
43
+
44
+ ## 🚀 Quick Start
45
+
46
+ 1. **Get an API Key**: Grab a free NVIDIA API key from [build.nvidia.com](https://build.nvidia.com/).
47
+ 2. **Login**: Connect your local environment by running:
48
+ ```bash
49
+ nimcode login
50
+ ```
51
+ 3. **Start Coding**:
52
+ - Launch the interactive REPL:
53
+ ```bash
54
+ nimcode
55
+ ```
56
+ - Or run a one-off task directly from the command line:
57
+ ```bash
58
+ nimcode /plan "Build a classic Snake game using HTML5 Canvas"
59
+ ```
60
+
61
+ ---
62
+
63
+ ## 💻 Complete Command Reference
64
+
65
+ Inside the `nimcode` REPL, you can type natural language or use any of the following slash commands to trigger specific workflows:
66
+
67
+ ### Mode Toggles & Execution
68
+ - **`/code`**: Enter standard coding mode (default mode, prompts for dangerous actions).
69
+ - **`/plan`**: Enter planning mode (read-only safe mode). The AI will research and write a markdown plan before modifying code.
70
+ - **`/trust`**: Enter trust mode. The AI will run commands and edit files completely autonomously without asking for `(a)ccept / (r)eject`.
71
+ - **`/untrust`**: Disable trust mode and restore permission prompts.
72
+
73
+ ### Interface & Settings
74
+ - **`/models`**: Open an interactive UI to select your preferred NVIDIA NIM model (e.g., meta/llama-3.1-70b-instruct).
75
+ - **`/theme`**: Open an interactive UI to change your syntax highlighting theme (e.g., monokai, dracula, nord, github).
76
+ - **`/config`**: View and edit global NimCode configuration settings.
77
+
78
+ ### Workspace & Context Management
79
+ - **`/clear`**: Clear the current conversation history to reset context.
80
+ - **`/compact`**: Compact the context window to save tokens while keeping essential memories.
81
+ - **`/context`**: View and manage the loaded context window.
82
+ - **`/rewind`**: Rewind the conversation history by a few steps.
83
+ - **`/undo`**: Revert the last file modification made by the AI.
84
+
85
+ ### Project & Search
86
+ - **`/index`**: Index the current project files to enable lightning-fast Semantic Search.
87
+ - **`/map`**: Generate a high-level semantic architecture map of the codebase.
88
+ - **`/research`**: Enter deep-research mode for reading documentation or large files.
89
+
90
+ ### Automation & Git
91
+ - **`/commit`**: Analyze all staged git changes and automatically generate a conventional commit message.
92
+ - **`/fix`**: Run a specific shell command and let the AI automatically iterate to fix any resulting errors.
93
+ - **`/autofix-pr`**: Pulls the current active GitHub Pull Request, reads comments, and automatically fixes the mentioned issues.
94
+
95
+ ### Advanced Development Modes
96
+ - **`/testgen <file>`**: Generate unit tests for a specific file, aiming for 100% coverage.
97
+ - **`/tdd`**: Enter Test-Driven Development mode. The AI will write tests first, verify they fail, and then implement the code to pass them.
98
+ - **`/bughunter`**: Initiate an automated search for logical bugs and edge cases across the codebase.
99
+ - **`/security-review`**: Audit the codebase for common vulnerabilities (e.g., OWASP top 10).
100
+ - **`/sql-tune`**: Database telepathy mode. Analyzes and auto-tunes SQL queries for maximum performance.
101
+ - **`/terraform-god`**: Cloud architect mode. Auto-provisions scalable best-practice Terraform infrastructure.
102
+ - **`/decompile <binary>`**: Reverse engineering mode using tools like `objdump` and `radare2`.
103
+
104
+ ### AI & Agents
105
+ - **`/delegate <role> <task>`**: Spawn an independent sub-agent with a specific role to handle a background task.
106
+ - **`/swarm`**: Orchestrate multiple sub-agents to tackle a complex architectural epic simultaneously.
107
+ - **`/grill-me`**: Interrogation mode. The AI will ask *you* hard questions to refine your system design and edge cases.
108
+ - **`/learn`**: Teach NimCode a new persistent skill or framework rule that it will remember for future sessions.
109
+ - **`/vision`**: Capture the screen and analyze UI elements using Vision AI models.
110
+ - **`/voice`**: Record your voice for 5 seconds and transcribe it as a prompt.
111
+ - **`/mcp install`**: Install and configure new Model Context Protocol tools.
112
+
113
+ ---
114
+
115
+ ## ⚙️ How it Works
116
+
117
+ NimCode creates a `.nimcode` directory inside your projects. This directory acts as the "brain" for that specific workspace:
118
+ - `.nimcode/plans/`: All your generated step-by-step markdown plans live here.
119
+ - `.nimcode/skills/`: Any custom guidelines, framework rules, or memories you teach the agent.
120
+ - `.nimcode/history/`: File backups for `/undo` capabilities.
121
+
122
+ ## 🛡️ Requirements
123
+
124
+ - Python 3.8+
125
+ - An NVIDIA NIM API Key (`NIM_API_KEY`)
126
+
127
+ ## 🤝 Contributing
128
+
129
+ Contributions, issues, and feature requests are welcome! Feel free to check out our [issues page](#).
130
+
131
+ ---
132
+ <div align="center">
133
+ <i>Built with ❤️ for the open-source developer community.</i>
134
+ </div>
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="nimcode",
5
- version="0.1.6",
5
+ version="0.1.12",
6
6
  packages=find_packages(where="src"),
7
7
  package_dir={"": "src"},
8
8
  install_requires=[
@@ -333,23 +333,29 @@ class Agent:
333
333
  file_path = tool_call.get("args", {}).get("file_path", "")
334
334
  if file_path.endswith(".py"):
335
335
  import subprocess
336
- subprocess.run(["black", "-q", file_path], capture_output=True)
337
- lint = subprocess.run(["flake8", "--select=E9,F821,F822,F823", file_path], capture_output=True, text=True)
338
- if lint.returncode != 0:
339
- import sys
340
- if sys.stdin.isatty():
341
- from rich.prompt import Confirm
342
- c.print(f"\n[bold yellow]Linter found errors in {file_path}:[/bold yellow]\n{lint.stdout}")
343
- if Confirm.ask("Would you like to auto-fix these errors?"):
344
- result += f"\n\nAuto-Linter found errors:\n{lint.stdout}\nPlease fix them."
345
- c.print(f"[bold red]Auto-fixing...[/bold red]")
336
+ try:
337
+ subprocess.run(["black", "-q", file_path], capture_output=True, timeout=10)
338
+ lint = subprocess.run(["flake8", "--select=E9,F821,F822,F823", file_path], capture_output=True, text=True, timeout=10)
339
+ if lint.returncode != 0:
340
+ import sys
341
+ if sys.stdin.isatty():
342
+ from rich.prompt import Confirm
343
+ c.print(f"\n[bold yellow]Linter found errors in {file_path}:[/bold yellow]\n{lint.stdout}")
344
+ if Confirm.ask("Would you like to auto-fix these errors?"):
345
+ result += f"\n\nAuto-Linter found errors:\n{lint.stdout}\nPlease fix them."
346
+ c.print(f"[bold red]Auto-fixing...[/bold red]")
347
+ else:
348
+ c.print("[dim]Ignoring linter errors.[/dim]")
346
349
  else:
347
- c.print("[dim]Ignoring linter errors.[/dim]")
348
- else:
349
- result += f"\n\nAuto-Linter found errors:\n{lint.stdout}\nPlease fix them."
350
+ result += f"\n\nAuto-Linter found errors:\n{lint.stdout}\nPlease fix them."
351
+ except Exception as e:
352
+ pass
350
353
  elif file_path.endswith((".js", ".ts", ".jsx", ".tsx")):
351
354
  import subprocess
352
- subprocess.run(["npx", "prettier", "--write", file_path], capture_output=True)
355
+ try:
356
+ subprocess.run(["npx", "--yes", "prettier", "--write", file_path], capture_output=True, timeout=10)
357
+ except Exception:
358
+ pass
353
359
  except KeyboardInterrupt:
354
360
  c.print("\n[yellow]Tool execution interrupted by user.[/yellow]")
355
361
  result = "Tool execution was interrupted by the user via Ctrl+C. Ask the user what to do next."
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  import sys
3
+ import asyncio
3
4
  import shutil
4
5
  import json
5
6
  import logging
@@ -180,11 +181,21 @@ class NimcodeREPL:
180
181
  console.print()
181
182
 
182
183
  style = Style.from_dict({
183
- 'prompt': '#ffffff bold',
184
- 'bottom-toolbar': '#888888 bg:#222222',
185
- 'toolbar_title': '#ffffff bg:#4400aa bold',
186
- 'toolbar_text': '#cccccc bg:#222222',
187
- 'toolbar_shortcut': '#aaaaaa bg:#444444'
184
+ 'prompt': '#00ffff bold',
185
+ 'bottom-toolbar': '#999999 bg:#1e1e1e',
186
+ 'toolbar_title': '#ffffff bg:#5c2d91 bold',
187
+ 'toolbar_text': '#cccccc bg:#1e1e1e',
188
+ 'toolbar_shortcut': '#888888 bg:#2d2d2d',
189
+
190
+ # Claude Code inspired Autocompletion Menu
191
+ 'completion-menu': 'bg:#2b2b2b #eeeeee',
192
+ 'completion-menu.completion': 'bg:#2b2b2b #eeeeee',
193
+ 'completion-menu.completion.current': 'bg:#5c2d91 #ffffff bold',
194
+ 'scrollbar.background': 'bg:#1e1e1e',
195
+ 'scrollbar.button': 'bg:#5c2d91',
196
+
197
+ # Auto-suggestion (greyed out ghost text)
198
+ 'auto-suggestion': '#666666 italic',
188
199
  })
189
200
 
190
201
  from prompt_toolkit.key_binding import KeyBindings
@@ -228,51 +239,60 @@ class NimcodeREPL:
228
239
  ('class:toolbar_text', f' Model: {self.model} | Mode: {mode} | Tokens: {tokens} | Cost: ${cost:.4f} | Effort: {effort}{goal_ui}'),
229
240
  ('class:toolbar_shortcut', ' [Alt+Enter] multiline '),
230
241
  ]
231
- from prompt_toolkit.completion import NestedCompleter, WordCompleter, PathCompleter
242
+ from prompt_toolkit.completion import Completer, Completion, PathCompleter
232
243
 
233
- command_completer = NestedCompleter.from_nested_dict({
234
- '/help': None,
235
- '/plan': None,
236
- '/code': None,
237
- '/models': None,
238
- '/theme': WordCompleter(['monokai', 'dracula', 'nord', 'github']),
239
- '/clear': None,
240
- '/compact': None,
241
- '/commit': None,
242
- '/fix': None,
243
- '/testgen': PathCompleter(),
244
- '/vision': None,
245
- '/voice': None,
246
- '/index': None,
247
- '/exit': None,
248
- '/quit': None,
249
- '/learn': None,
250
- '/cost': None,
251
- '/effort': WordCompleter(['Low', 'Medium', 'High']),
252
- '/thinking': None,
253
- '/add': PathCompleter(),
254
- '/research': None,
255
- '/swarm': None,
256
- '/tdd': None,
257
- '/mcp': WordCompleter(['install']),
258
- '/rewind': None,
259
- '/fork': None,
260
- '/grill-me': None,
261
- '/teleport': PathCompleter(),
262
- '/buddy': None,
263
- '/ultraplan': None,
264
- '/bughunter': None,
265
- '/security-review': None,
266
- '/doctor': None,
267
- '/permissions': WordCompleter(['auto', 'bypass', 'default']),
268
- '/graph': None,
269
- '/guardian': None,
270
- '/thinkback': None,
271
- '/autofix-pr': None,
272
- '/terraform-god': None,
273
- '/sql-tune': None,
274
- '/decompile': PathCompleter(),
275
- })
244
+ class SlashCompleter(Completer):
245
+ def __init__(self):
246
+ self.commands = [
247
+ '/help', '/plan', '/code', '/models', '/theme', '/clear', '/compact',
248
+ '/commit', '/fix', '/testgen', '/vision', '/voice', '/index', '/exit',
249
+ '/quit', '/learn', '/cost', '/effort', '/thinking', '/add', '/research',
250
+ '/swarm', '/tdd', '/mcp', '/rewind', '/fork', '/grill-me', '/teleport',
251
+ '/buddy', '/ultraplan', '/bughunter', '/security-review', '/doctor',
252
+ '/permissions', '/graph', '/guardian', '/thinkback', '/autofix-pr',
253
+ '/terraform-god', '/sql-tune', '/decompile'
254
+ ]
255
+ self.subcommands = {
256
+ '/theme': ['monokai', 'dracula', 'nord', 'github'],
257
+ '/effort': ['Low', 'Medium', 'High'],
258
+ '/mcp': ['install'],
259
+ '/permissions': ['auto', 'bypass', 'default']
260
+ }
261
+ self.path_completer = PathCompleter()
262
+
263
+ def get_completions(self, document, complete_event):
264
+ text = document.text_before_cursor
265
+ parts = text.split()
266
+
267
+ if not parts:
268
+ return
269
+
270
+ if len(parts) == 1 or (len(parts) == 2 and text.endswith(' ')):
271
+ if not text.endswith(' '):
272
+ word = parts[0]
273
+ for c in self.commands:
274
+ if c.startswith(word):
275
+ yield Completion(c, start_position=-len(word))
276
+ else:
277
+ cmd = parts[0]
278
+ if cmd in self.subcommands:
279
+ for sub in self.subcommands[cmd]:
280
+ yield Completion(sub, start_position=0)
281
+ elif cmd in ['/testgen', '/add', '/teleport', '/decompile']:
282
+ yield from self.path_completer.get_completions(document, complete_event)
283
+
284
+ elif len(parts) >= 2:
285
+ cmd = parts[0]
286
+ word = parts[-1] if not text.endswith(' ') else ''
287
+
288
+ if cmd in self.subcommands:
289
+ for sub in self.subcommands[cmd]:
290
+ if sub.startswith(word):
291
+ yield Completion(sub, start_position=-len(word))
292
+ elif cmd in ['/testgen', '/add', '/teleport', '/decompile']:
293
+ yield from self.path_completer.get_completions(document, complete_event)
294
+
295
+ command_completer = SlashCompleter()
276
296
 
277
297
  from prompt_toolkit.lexers import PygmentsLexer
278
298
  from pygments.lexers.shell import BashLexer
@@ -290,7 +310,7 @@ class NimcodeREPL:
290
310
 
291
311
  while True:
292
312
  try:
293
- user_input = await session.prompt_async("> ")
313
+ user_input = await session.prompt_async("❯ ")
294
314
  if user_input.lower() in ["/exit", "/quit"]:
295
315
  self.agent.save_history()
296
316
  break
@@ -303,6 +323,8 @@ class NimcodeREPL:
303
323
  table.add_row("/help", "Show this help menu")
304
324
  table.add_row("/plan", "Enter planning mode (safe mode)")
305
325
  table.add_row("/code", "Enter coding mode (all tools enabled)")
326
+ table.add_row("/trust", "Enter trust mode (runs all tools without permission)")
327
+ table.add_row("/untrust", "Disable trust mode (ask for permission)")
306
328
  table.add_row("/models", "Select NVIDIA NIM model")
307
329
  table.add_row("/theme <name>", "Change syntax theme (e.g., monokai)")
308
330
  table.add_row("/clear", "Clear current context history")
@@ -530,6 +552,14 @@ class NimcodeREPL:
530
552
  console.print("[bold magenta]Entering Code mode.[/bold magenta] Standard permissions restored.")
531
553
  self.messages.append({"role": "system", "content": "You are now in coding mode. You may use all available tools."})
532
554
  continue
555
+ elif user_input.strip() == "/trust":
556
+ self.agent.permission_engine.mode = PermissionMode.BYPASS
557
+ console.print("[bold red]🚨 TRUST MODE ACTIVATED: NimCode will now run all tools without asking for permission! 🚨[/bold red]")
558
+ continue
559
+ elif user_input.strip() == "/untrust":
560
+ self.agent.permission_engine.mode = PermissionMode.DEFAULT
561
+ console.print("[bold green]🛡️ Trust mode disabled. NimCode will ask for permission again.[/bold green]")
562
+ continue
533
563
  elif user_input.strip().startswith("/theme"):
534
564
  parts = user_input.strip().split()
535
565
  if len(parts) > 1:
@@ -537,15 +567,22 @@ class NimcodeREPL:
537
567
  save_global_setting("theme", parts[1])
538
568
  console.print(f"[green]Theme updated to '{parts[1]}'[/green]")
539
569
  else:
540
- from prompt_toolkit.shortcuts import radiolist_dialog
570
+ from rich.table import Table
571
+ from rich.prompt import Prompt
572
+
541
573
  themes = ['monokai', 'dracula', 'nord', 'github']
542
- choices = [(t, t) for t in themes]
543
- selected_theme = await radiolist_dialog(
544
- title="Syntax Themes",
545
- text="Select a theme:",
546
- values=choices
547
- ).run_async()
548
- if selected_theme:
574
+ table = Table(title="🎨 Available Syntax Themes", show_header=True, header_style="bold magenta")
575
+ table.add_column("ID", style="cyan", width=4)
576
+ table.add_column("Theme Name", style="white")
577
+
578
+ for idx, t in enumerate(themes, 1):
579
+ table.add_row(str(idx), t)
580
+
581
+ console.print(table)
582
+
583
+ choice = Prompt.ask("Select a theme by ID", choices=[str(i) for i in range(1, len(themes) + 1)], default="1")
584
+ if choice:
585
+ selected_theme = themes[int(choice) - 1]
549
586
  self.settings["theme"] = selected_theme
550
587
  save_global_setting("theme", selected_theme)
551
588
  console.print(f"[green]Theme updated to '{selected_theme}'[/green]")
@@ -554,22 +591,36 @@ class NimcodeREPL:
554
591
  continue
555
592
  elif user_input.strip() == "/models":
556
593
  console.print("[bold yellow]Fetching available models from NVIDIA NIM...[/bold yellow]")
557
- models = await self.client.get_available_models()
558
- from prompt_toolkit.shortcuts import radiolist_dialog
559
- choices = [(m, m) for m in models]
560
- selected_model = await radiolist_dialog(
561
- title="NVIDIA NIM Models",
562
- text="Select a model for code generation:",
563
- values=choices
564
- ).run_async()
565
-
566
- if selected_model:
567
- self.client.model = selected_model
568
- self.model = selected_model
569
- save_global_setting("model", selected_model)
570
- console.print(f"[bold green]Model changed to: {selected_model}[/bold green]")
571
- else:
572
- console.print("[yellow]Model selection cancelled.[/yellow]")
594
+ try:
595
+ models = await self.client.get_available_models()
596
+ if not models:
597
+ console.print("[red]No models returned from API.[/red]")
598
+ continue
599
+
600
+ from rich.table import Table
601
+ from rich.prompt import Prompt
602
+
603
+ table = Table(title="🤖 Available NVIDIA NIM Models", show_header=True, header_style="bold magenta")
604
+ table.add_column("ID", style="cyan", width=4)
605
+ table.add_column("Model Name", style="white")
606
+
607
+ for idx, m in enumerate(models, 1):
608
+ table.add_row(str(idx), m)
609
+
610
+ console.print(table)
611
+
612
+ choice = Prompt.ask("Select a model by ID (or press Enter to cancel)", choices=[str(i) for i in range(1, len(models) + 1)] + [""], default="")
613
+
614
+ if choice:
615
+ selected_model = models[int(choice) - 1]
616
+ self.client.model = selected_model
617
+ self.model = selected_model
618
+ save_global_setting("model", selected_model)
619
+ console.print(f"[bold green]Model changed to: {selected_model}[/bold green]")
620
+ else:
621
+ console.print("[yellow]Model selection cancelled.[/yellow]")
622
+ except Exception as e:
623
+ console.print(f"[bold red]Failed to fetch models: {e}[/bold red]")
573
624
  continue
574
625
  elif user_input.strip() == "/commit":
575
626
  import subprocess
@@ -856,7 +907,6 @@ class NimcodeREPL:
856
907
  console.print(f"\n\n[bold magenta]🔬 Subagent Research Complete for '{q}'![/bold magenta]\n{result}\n")
857
908
  self.messages.append({"role": "system", "content": f"A background subagent completed research on '{q}'. Result:\n{result}"})
858
909
 
859
- import asyncio
860
910
  asyncio.create_task(bg_research(query))
861
911
  console.print("[dim italic]Subagent spawned in background. You can continue chatting![/dim italic]")
862
912
  continue
@@ -914,7 +964,6 @@ class NimcodeREPL:
914
964
 
915
965
  console.print(f"\n[bold magenta]🐝 Swarm Finished![/bold magenta]\n[bold]Review:[/bold]\n{review}")
916
966
 
917
- import asyncio
918
967
  asyncio.create_task(run_swarm(task))
919
968
  continue
920
969
  elif user_input.strip().startswith("/tdd "):
@@ -932,12 +981,11 @@ class NimcodeREPL:
932
981
  result = await tdd_agent.run_headless(feat, max_turns=10)
933
982
  console.print(f"\n[bold green]🧪 TDD Completed![/bold green]\n{result}")
934
983
 
935
- import asyncio
936
984
  asyncio.create_task(run_tdd(feature))
937
985
  continue
938
986
  elif user_input.strip().startswith("/"):
939
987
  import difflib
940
- valid_commands = ["/help", "/plan", "/code", "/models", "/theme", "/clear", "/compact", "/commit", "/fix", "/exit", "/quit", "/config", "/alias", "/add", "/rewind", "/fork", "/testgen", "/vision", "/voice", "/index", "/research", "/mcp install", "/swarm", "/tdd", "/learn", "/cost", "/effort", "/thinking", "/grill-me", "/teleport", "/buddy", "/ultraplan", "/bughunter", "/security-review", "/doctor", "/permissions", "/graph", "/guardian", "/thinkback", "/autofix-pr", "/terraform-god", "/sql-tune", "/decompile"]
988
+ valid_commands = ["/help", "/plan", "/code", "/trust", "/untrust", "/models", "/theme", "/clear", "/compact", "/commit", "/fix", "/exit", "/quit", "/config", "/alias", "/add", "/rewind", "/fork", "/testgen", "/vision", "/voice", "/index", "/research", "/mcp install", "/swarm", "/tdd", "/learn", "/cost", "/effort", "/thinking", "/grill-me", "/teleport", "/buddy", "/ultraplan", "/bughunter", "/security-review", "/doctor", "/permissions", "/graph", "/guardian", "/thinkback", "/autofix-pr", "/terraform-god", "/sql-tune", "/decompile"]
941
989
  cmd_name = user_input.strip().split()[0]
942
990
  matches = difflib.get_close_matches(cmd_name, valid_commands, n=1, cutoff=0.5)
943
991
  if matches:
@@ -958,6 +1006,9 @@ class NimcodeREPL:
958
1006
  except KeyboardInterrupt:
959
1007
  console.print("\n[bold yellow]⚠ Operation cancelled by user. (Press Ctrl+D to exit)[/bold yellow]")
960
1008
  continue
1009
+ except asyncio.CancelledError:
1010
+ console.print("\n[bold yellow]⚠ Operation cancelled by user. (Press Ctrl+D to exit)[/bold yellow]")
1011
+ continue
961
1012
  except EOFError:
962
1013
  break
963
1014
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nimcode
3
- Version: 0.1.6
3
+ Version: 0.1.12
4
4
  Summary: A standalone, robust coding agent for NVIDIA NIM models.
5
5
  Author: Autonomous Agent
6
6
  Requires-Dist: httpx>=0.27.0
@@ -189,11 +189,7 @@ async def test_start_repl_commands(agent):
189
189
  # Mock run to avoid actually executing queries
190
190
  agent.run = AsyncMock()
191
191
 
192
- class MockDialog:
193
- async def run_async(self):
194
- return "model1"
195
-
196
- with patch("prompt_toolkit.shortcuts.radiolist_dialog", return_value=MockDialog()):
192
+ with patch("rich.prompt.Prompt.ask", return_value="1"):
197
193
  try:
198
194
  from nimcode.repl import NimcodeREPL
199
195
  repl = NimcodeREPL(agent)
nimcode-0.1.6/README.md DELETED
@@ -1,68 +0,0 @@
1
- <div align="center">
2
-
3
- # 🚀 NimCode
4
-
5
- **The Autonomous AI Coding Assistant for the NVIDIA NIM Ecosystem**
6
-
7
- [![PyPI version](https://badge.fury.io/py/nimcode.svg)](https://badge.fury.io/py/nimcode)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
-
10
- *A powerful, standalone REPL and CLI agent that writes, edits, and plans code like a senior developer—powered by LLaMa 3.1 70B and the lightning-fast NVIDIA NIM API.*
11
-
12
- </div>
13
-
14
- ---
15
-
16
- ## 🌟 Features
17
-
18
- - 🧠 **Smart Planning (`/plan`)**: Generates comprehensive, step-by-step architectural plans directly into `.nimcode/plans/`.
19
- - 🛠️ **Autonomous Execution (`/code`)**: Reads, writes, and tests code across your entire workspace.
20
- - 📸 **Vision Support (`/vision`)**: Analyze screenshots to debug UI issues or write code from design mockups.
21
- - 🎙️ **Voice Commands (`/voice`)**: Speak your requirements and let the agent do the typing.
22
- - 💾 **Continuous Learning**: Saves custom rules and instructions to `.nimcode/skills/` so it gets smarter over time.
23
- - 🤖 **Auto-Commits (`/commit`)**: Automatically writes descriptive, conventional git commits for your changes.
24
-
25
- ## 📦 Installation
26
-
27
- NimCode is available globally via PyPI. You can install it anywhere in seconds:
28
-
29
- ```bash
30
- pip install nimcode
31
- ```
32
-
33
- ## 🚀 Quick Start
34
-
35
- 1. **Get an API Key**: Grab a free NVIDIA API key from [build.nvidia.com](https://build.nvidia.com/).
36
- 2. **Login**: Connect your local environment by running:
37
- ```bash
38
- nimcode login
39
- ```
40
- 3. **Start Coding**:
41
- - Launch the interactive REPL:
42
- ```bash
43
- nimcode
44
- ```
45
- - Or run a one-off task directly from the command line:
46
- ```bash
47
- nimcode /plan "Build a classic Snake game using HTML5 Canvas"
48
- ```
49
-
50
- ## ⚙️ How it Works
51
-
52
- NimCode creates a `.nimcode` directory inside your projects. This directory acts as the "brain" for that specific workspace:
53
- - `.nimcode/plans/`: All your generated step-by-step markdown plans live here.
54
- - `.nimcode/skills/`: Any custom guidelines, framework rules, or memories you teach the agent.
55
-
56
- ## 🛡️ Requirements
57
-
58
- - Python 3.8+
59
- - An NVIDIA NIM API Key (NIM_API_KEY)
60
-
61
- ## 🤝 Contributing
62
-
63
- Contributions, issues, and feature requests are welcome! Feel free to check out our [issues page](#).
64
-
65
- ---
66
- <div align="center">
67
- <i>Built with ❤️ for the open-source developer community.</i>
68
- </div>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes