aizen-ai-cli 2.4.2__tar.gz → 2.5.0__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 (48) hide show
  1. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/PKG-INFO +8 -2
  2. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/README.md +7 -1
  3. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/commands.py +25 -3
  4. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/config.py +1 -1
  5. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/context.py +8 -8
  6. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/main.py +7 -16
  7. aizen_ai_cli-2.5.0/aizen/rag.py +709 -0
  8. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/tools/commands.py +3 -3
  9. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/tools/dispatcher.py +38 -1
  10. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/tools/helpers.py +0 -5
  11. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen_ai_cli.egg-info/PKG-INFO +8 -2
  12. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen_ai_cli.egg-info/SOURCES.txt +2 -0
  13. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/pyproject.toml +1 -1
  14. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/setup.py +1 -1
  15. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_agent.py +23 -23
  16. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_dispatcher.py +1 -7
  17. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_file_ops.py +1 -6
  18. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_helpers.py +0 -8
  19. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_plugins.py +4 -6
  20. aizen_ai_cli-2.5.0/tests/test_rag_search.py +1472 -0
  21. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_retry.py +7 -8
  22. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_search.py +0 -7
  23. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/MANIFEST.in +0 -0
  24. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/__init__.py +0 -0
  25. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/agent.py +0 -0
  26. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/exceptions.py +0 -0
  27. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/logging_config.py +0 -0
  28. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/mcp.py +0 -0
  29. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/plugins.py +0 -0
  30. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/retry.py +0 -0
  31. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/session.py +0 -0
  32. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/tools/__init__.py +0 -0
  33. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/tools/file_ops.py +3 -3
  34. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/tools/search.py +1 -1
  35. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen/utils.py +0 -0
  36. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen_ai_cli.egg-info/dependency_links.txt +0 -0
  37. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen_ai_cli.egg-info/entry_points.txt +0 -0
  38. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen_ai_cli.egg-info/requires.txt +0 -0
  39. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/aizen_ai_cli.egg-info/top_level.txt +0 -0
  40. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/requirements.txt +0 -0
  41. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/setup.cfg +0 -0
  42. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_commands.py +0 -0
  43. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_config.py +0 -0
  44. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_context.py +0 -0
  45. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_main.py +0 -0
  46. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_mcp.py +0 -0
  47. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_session.py +0 -0
  48. {aizen_ai_cli-2.4.2 → aizen_ai_cli-2.5.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aizen-ai-cli
3
- Version: 2.4.2
3
+ Version: 2.5.0
4
4
  Summary: Aizen AI Agent — A professional-grade AI coding assistant for your terminal.
5
5
  Author: Irtaza Malik
6
6
  License: MIT
@@ -52,6 +52,7 @@ Aizen is a powerful, asynchronous AI assistant that integrates seamlessly into y
52
52
  - **Cost‑Aware Usage** — Real‑time cost estimation for all major LLMs.
53
53
  - **Persistent Sessions** — Save and restore conversations with checkpoints.
54
54
  - **Rich Visual Feedback** — Stream responses with live previews and animated thought indicators.
55
+ - **Semantic Codebase Search** — Fast local RAG (Retrieval-Augmented Generation) using the `/search` command.
55
56
  - **Extensible Architecture** — Custom plugins and project‑specific rules tailor Aizen to your workflow.
56
57
  - **Comprehensive Logging** — Rotating logs with optional verbose output for debugging.
57
58
 
@@ -72,6 +73,9 @@ Aizen is a powerful, asynchronous AI assistant that integrates seamlessly into y
72
73
  ### Vision Support
73
74
  - Native image handling and encoding for Vision APIs (e.g., GPT‑4o, Claude 3.5 Sonnet).
74
75
 
76
+ ### Local Codebase RAG
77
+ - Intelligent semantic search across your entire codebase using local embeddings and SQLite vector caching, accessible via the `/search` command and available to the agent.
78
+
75
79
  ### Real‑Time Command Streaming
76
80
  - Background command execution with async streaming of stdout/stderr; use `run_command --background`.
77
81
 
@@ -88,8 +92,10 @@ Aizen is a powerful, asynchronous AI assistant that integrates seamlessly into y
88
92
  - Current cost estimate shown in the CLI status bar.
89
93
  - Supports Anthropic (Claude 3.5/3.7 Sonnet, Opus, Haiku), Google (Gemini 2.5 Pro/Flash), and OpenAI (GPT‑4o, o1, o3‑mini).
90
94
 
91
- ## 📌 Session Management
95
+ ## 📌 Session Management & Search
92
96
 
97
+ - `/search [query]` — Perform semantic search across your codebase.
98
+ - `/reindex [dir]` — Manually trigger indexing for local semantic search.
93
99
  - `/checkpoint [name]` — Save conversation snapshots.
94
100
  - `/restore [name]` — Restore a previous checkpoint.
95
101
 
@@ -12,6 +12,7 @@ Aizen is a powerful, asynchronous AI assistant that integrates seamlessly into y
12
12
  - **Cost‑Aware Usage** — Real‑time cost estimation for all major LLMs.
13
13
  - **Persistent Sessions** — Save and restore conversations with checkpoints.
14
14
  - **Rich Visual Feedback** — Stream responses with live previews and animated thought indicators.
15
+ - **Semantic Codebase Search** — Fast local RAG (Retrieval-Augmented Generation) using the `/search` command.
15
16
  - **Extensible Architecture** — Custom plugins and project‑specific rules tailor Aizen to your workflow.
16
17
  - **Comprehensive Logging** — Rotating logs with optional verbose output for debugging.
17
18
 
@@ -32,6 +33,9 @@ Aizen is a powerful, asynchronous AI assistant that integrates seamlessly into y
32
33
  ### Vision Support
33
34
  - Native image handling and encoding for Vision APIs (e.g., GPT‑4o, Claude 3.5 Sonnet).
34
35
 
36
+ ### Local Codebase RAG
37
+ - Intelligent semantic search across your entire codebase using local embeddings and SQLite vector caching, accessible via the `/search` command and available to the agent.
38
+
35
39
  ### Real‑Time Command Streaming
36
40
  - Background command execution with async streaming of stdout/stderr; use `run_command --background`.
37
41
 
@@ -48,8 +52,10 @@ Aizen is a powerful, asynchronous AI assistant that integrates seamlessly into y
48
52
  - Current cost estimate shown in the CLI status bar.
49
53
  - Supports Anthropic (Claude 3.5/3.7 Sonnet, Opus, Haiku), Google (Gemini 2.5 Pro/Flash), and OpenAI (GPT‑4o, o1, o3‑mini).
50
54
 
51
- ## 📌 Session Management
55
+ ## 📌 Session Management & Search
52
56
 
57
+ - `/search [query]` — Perform semantic search across your codebase.
58
+ - `/reindex [dir]` — Manually trigger indexing for local semantic search.
53
59
  - `/checkpoint [name]` — Save conversation snapshots.
54
60
  - `/restore [name]` — Restore a previous checkpoint.
55
61
 
@@ -6,9 +6,7 @@ import subprocess
6
6
  from datetime import datetime
7
7
 
8
8
  import questionary
9
-
10
9
  from prompt_toolkit.completion import Completer, Completion
11
- from prompt_toolkit import PromptSession
12
10
  from rich.table import Table
13
11
 
14
12
  from .config import (
@@ -47,6 +45,8 @@ SLASH_COMMANDS = [
47
45
  ("/commit", "Auto-generate and commit changes"),
48
46
  ("/diff", "Show all uncommitted changes"),
49
47
  ("/auto", "Enter autonomous agentic mode for a complex task"),
48
+ ("/search", "Search the codebase using semantic (RAG) search"),
49
+ ("/reindex", "Reindex the codebase for semantic search"),
50
50
  ]
51
51
 
52
52
  # In-memory checkpoint storage for conversation branching
@@ -69,7 +69,7 @@ class AizenCompleter(Completer):
69
69
  if stripped.startswith("/"):
70
70
  if " " not in stripped:
71
71
  query = stripped.lower()
72
- cmds_with_args = {"/model", "/save", "/load", "/export", "/checkpoint", "/restore"}
72
+ cmds_with_args = {"/model", "/save", "/load", "/export", "/checkpoint", "/restore", "/search", "/reindex"}
73
73
  for cmd, description in SLASH_COMMANDS:
74
74
  if cmd.startswith(query):
75
75
  completion_text = cmd + " " if cmd in cmds_with_args else cmd
@@ -287,6 +287,11 @@ async def handle_slash_command(
287
287
  help_table.add_row(" 🔀 /commit", "Auto-generate and commit changes")
288
288
  help_table.add_row(" 📊 /diff", "Show all uncommitted changes")
289
289
 
290
+ # ── Search & RAG ──
291
+ help_table.add_row(f"[bold {Theme.MUTED}]── Search & RAG ──[/bold {Theme.MUTED}]", "")
292
+ help_table.add_row(" 🔍 /search [query]", "Search the codebase using semantic (RAG) search")
293
+ help_table.add_row(" 🔄 /reindex [dir]", "Reindex the codebase for semantic search")
294
+
290
295
  # ── Agent ──
291
296
  help_table.add_row(f"[bold {Theme.MUTED}]── Agent ──[/bold {Theme.MUTED}]", "")
292
297
  help_table.add_row(" 🤖 /auto [task]", "Enter autonomous mode for a complex task (max iterations apply)")
@@ -732,6 +737,23 @@ async def handle_slash_command(
732
737
  except Exception as e:
733
738
  console.print(f" [{Theme.ERROR}]Error showing diff: {e}[/{Theme.ERROR}]\n")
734
739
 
740
+ elif cmd == "/search":
741
+ from .rag import get_global_vector_store, get_global_embedding_generator, SlashCommandRunner
742
+ runner = SlashCommandRunner(get_global_vector_store(), get_global_embedding_generator())
743
+ runner.run(command_str, console)
744
+ console.print()
745
+
746
+ elif cmd == "/reindex":
747
+ import asyncio
748
+ from .rag import reindex_directory
749
+ target_dir = arg if arg else "."
750
+ console.print(f" [{Theme.MUTED}]Re-indexing codebase directory '{target_dir}' in background...[/{Theme.MUTED}]")
751
+ try:
752
+ await asyncio.to_thread(reindex_directory, target_dir)
753
+ console.print(f" [{Theme.SUCCESS}]✓ Reindexing complete.[/{Theme.SUCCESS}]\n")
754
+ except Exception as e:
755
+ console.print(f" [{Theme.ERROR}]Error during reindexing: {e}[/{Theme.ERROR}]\n")
756
+
735
757
  else:
736
758
  console.print(
737
759
  f" [{Theme.ERROR}]Unknown command: {cmd}[/{Theme.ERROR}] — type [bold {Theme.ACCENT}]/help[/bold {Theme.ACCENT}] for commands.\n"
@@ -20,7 +20,7 @@ logger = logging.getLogger("aizen")
20
20
 
21
21
  # Read version from installed package metadata (stays in sync with pyproject.toml).
22
22
  # Falls back to a hardcoded value only when running from source without installing.
23
- _FALLBACK_VERSION = "2.4.2"
23
+ _FALLBACK_VERSION = "2.5.0"
24
24
  try:
25
25
  VERSION = _pkg_version("aizen-ai-cli")
26
26
  except PackageNotFoundError:
@@ -184,7 +184,7 @@ class ContextPruner:
184
184
  """
185
185
  import re
186
186
  dropped_count = 0
187
-
187
+
188
188
  # Keep the system prompt and the last couple of turns intact
189
189
  if len(messages) <= 3:
190
190
  return 0
@@ -200,7 +200,7 @@ class ContextPruner:
200
200
  if old_content != new_content:
201
201
  msg["content"] = new_content
202
202
  dropped_count += 1
203
-
203
+
204
204
  return dropped_count
205
205
 
206
206
  @staticmethod
@@ -215,20 +215,20 @@ class ContextPruner:
215
215
  system_msg = messages[0]
216
216
  recent = messages[-recent_count:]
217
217
  middle = messages[1:-recent_count]
218
-
218
+
219
219
  user_topics = [
220
- m["content"][:100].replace('\n', ' ')
221
- for m in middle
220
+ m["content"][:100].replace('\n', ' ')
221
+ for m in middle
222
222
  if m.get("role") == "user" and m.get("content")
223
223
  ]
224
-
224
+
225
225
  summary = "Previous conversation summary: The user and assistant discussed " + "; ".join(user_topics[:5]) + ". The assistant helped with these requests."
226
-
226
+
227
227
  messages[:] = [
228
228
  system_msg,
229
229
  {"role": "user", "content": f"Previous conversation summary:\n{summary}"},
230
230
  {"role": "assistant", "content": "Understood. I have the context. How can I continue helping?"},
231
231
  ] + recent
232
-
232
+
233
233
  return summary
234
234
 
@@ -6,28 +6,20 @@ Aizen AI Agent — A professional-grade AI coding assistant for your terminal.
6
6
  import argparse
7
7
  import asyncio
8
8
  import base64
9
- import json
10
9
  import mimetypes
11
10
  import os
12
- import random
13
11
  import re
14
12
  import subprocess
15
13
  import sys
16
- from typing import Any
17
14
 
18
- from openai import APIConnectionError as OpenAIConnectionError
19
- from openai import APITimeoutError, AsyncOpenAI, AuthenticationError, BadRequestError
20
- from openai import RateLimitError as OpenAIRateLimitError
15
+ from openai import AsyncOpenAI
21
16
  from prompt_toolkit import PromptSession
22
17
  from prompt_toolkit.filters import completion_is_selected, has_completions
23
18
  from prompt_toolkit.formatted_text import FormattedText
24
19
  from prompt_toolkit.key_binding import KeyBindings
25
20
  from prompt_toolkit.styles import Style
26
- from rich.live import Live
27
- from rich.markdown import Markdown
28
- from rich.spinner import Spinner
29
- from rich.text import Text
30
21
 
22
+ from .agent import AgentRunner
31
23
  from .commands import AizenCompleter, handle_slash_command
32
24
  from .config import (
33
25
  AIZEN_ASCII,
@@ -52,9 +44,8 @@ from .mcp import MCPManager
52
44
  from .plugins import plugin_manager
53
45
  from .retry import retry_with_backoff
54
46
  from .session import save_session
55
- from .tools import backup_manager, execute_tool, tools
56
- from .agent import AgentRunner
57
- from .utils import Struct, TokenTracker, fetch_url_content, generate_directory_tree, truncate_output
47
+ from .tools import backup_manager, tools
48
+ from .utils import TokenTracker, fetch_url_content, generate_directory_tree
58
49
 
59
50
 
60
51
  def inject_file_context(user_input: str) -> str:
@@ -420,7 +411,7 @@ async def main_loop():
420
411
  # ── Auto-compact if context is critically full ──
421
412
  if context_manager.needs_auto_compact() and len(messages) > 4:
422
413
  console.print("[dim yellow]⚡ Context limit reached. Attempting smart pruning...[/dim yellow]")
423
-
414
+
424
415
  dropped_count = ContextPruner.prune_attached_contexts(messages)
425
416
  estimated_total = context_manager.estimate_messages_tokens(messages, token_tracker.estimate_tokens)
426
417
  context_manager.update(estimated_total)
@@ -447,10 +438,10 @@ async def main_loop():
447
438
  auto_iteration_count=auto_iteration_count,
448
439
  max_auto_iterations=max_auto_iterations,
449
440
  )
450
-
441
+
451
442
  try:
452
443
  await runner.run_turn(messages)
453
-
444
+
454
445
  # Update state back from runner (if it changed during auto mode)
455
446
  is_auto_mode = runner.is_auto_mode
456
447
  auto_iteration_count = runner.auto_iteration_count