Skip to content

Dev#14

Merged
ayusrjn merged 7 commits into
mainfrom
dev
Apr 11, 2026
Merged

Dev#14
ayusrjn merged 7 commits into
mainfrom
dev

Conversation

@ayusrjn
Copy link
Copy Markdown
Member

@ayusrjn ayusrjn commented Apr 11, 2026

Summary by CodeRabbit

  • New Features

    • Parallel sub-agent execution for delegating independent tasks and showing progress/results in the terminal.
    • Hot-swappable language models via a /models endpoint and a Rich-powered CLI experience.
  • Documentation

    • Rebranded to "Lambda Agent"; updated overview, key features, built-in slash commands, and usage.
    • First-run, installation (PyPI, Python 3.10+), config (~/.config/lambda-agent/config.env) and attribution/license updated.
  • Bug Fixes

    • Faster, more reliable repository search implementation.
  • Chores

    • Added rich dependency for improved CLI.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 11, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds a Gemini-driven CLI agent rebrand and docs updates, a new disposable SubAgent system with parallel execution, integrates subagent tools into the tool registry, refactors repository search to use grep, and updates packaging metadata and rich dependency.

Changes

Cohort / File(s) Summary
Docs & Packaging
README.md, pyproject.toml
Rebranded project to "Lambda Agent", updated installation/usage and feature docs (slash commands, scratchpad, attribution); added author, classifiers, project URLs, and rich>=13.7.0 dependency.
Agent Prompt & UI
lambda_agent/agent.py
Expanded system prompt with sub-agent guidance and adjusted tool-call rendering to skip the standard display for dispatch_subagent.
Sub-Agent Implementation
lambda_agent/subagent.py
New module: SubAgent class, dispatch_subagent function, thread-safe ID generator, thread-pooled execution (max 4), tool allowlist parsing, iteration budget and result clipping, exported SUBAGENT_EXECUTORS/SUBAGENT_FUNCTIONS, and constants MAX_SUBAGENT_ITERATIONS/RESULT_MAX_CHARS.
Tools & Search
lambda_agent/tools.py
Merged subagent executors/functions into TOOL_EXECUTORS/TOOL_FUNCTIONS; replaced Python os.walk search with grep -rnIF invocation, improved result parsing, limit/truncation, and error handling for grep absence.

Sequence Diagram(s)

sequenceDiagram
    participant Agent as Main Agent
    participant Dispatcher as dispatch_subagent
    participant Pool as ThreadPoolExecutor
    participant Sub as SubAgent
    participant Gemini as Gemini API
    participant Tools as Restricted Tools

    Agent->>Dispatcher: dispatch_subagent(task, context, tools)
    Dispatcher->>Pool: submit(Sub.run) (max 4 workers)
    Pool->>Sub: run() (concurrent)
    Sub->>Gemini: send initial prompt
    Gemini-->>Sub: respond (may include tool calls)
    Sub->>Tools: execute allowed tool call(s)
    Tools-->>Sub: return tool results
    Sub->>Gemini: send tool results / next iteration
    Gemini-->>Sub: final response or more calls
    Sub-->>Dispatcher: return clipped final text (or timeout)
    Dispatcher-->>Agent: display progress/result panel
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Dev #7 — Modifies lambda_agent/tools.py (search implementation and tool registries), overlapping with the search refactor and tool registry changes here.

Poem

🐰 I scurried threads into a tidy swarm,

sub-agents hum and grep keeps code warm,
Panels glow with progress, results unfurl,
Tiny hops, big leaps — a faster world,
— your rabbit celebrant, ears all a-flutter.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Dev' is too vague and does not meaningfully describe the substantial changes in this pull request, which include a major refactor adding sub-agent functionality, reimplementing search_repo with grep, and updating project documentation. Replace the title with a more descriptive summary of the main changes, such as 'Add sub-agent framework with parallel task delegation' or 'Implement subagent module and refactor search_repo'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lambda_agent/subagent.py`:
- Around line 243-246: The current code calls _executor.submit(agent.run) then
immediately blocks on future.result(timeout=120), which forces serial execution
of same-turn sub-agent dispatches; change dispatch_subagent so it submits each
agent.run to the executor and returns/collects the Future instead of awaiting it
immediately (stop calling future.result in dispatch_subagent), then in the
caller (the tool-dispatch loop in lambda_agent/agent.py) batch-submit all
dispatch_subagent calls, store their Futures, and only after the loop await each
Future.result with the desired timeout and handle exceptions; update references
to _executor.submit(agent.run) and future.result(timeout=120) to reflect this
non-blocking submit-and-collect behavior.

In `@lambda_agent/tools.py`:
- Around line 131-143: The command list building in lambda_agent/tools.py
(variable name command) can misinterpret user/model-provided query or path that
start with '-' as grep options; fix by inserting the end-of-options marker "--"
into the command list immediately before the positional arguments so the items
query and path are always treated literally (i.e., place "--" right before query
and path in the command list construction for the grep invocation).
- Around line 145-167: The grep subprocess call in the search routine uses
subprocess.run(...) without a timeout which can hang; update the call to pass a
timeout (use the same timeout constant or helper used by run_command, e.g.,
RUN_COMMAND_TIMEOUT or a timeout parameter) and handle subprocess.TimeoutExpired
in the surrounding try/except to return a clear timeout error message; modify
the block around subprocess.run in the function that builds/runs the grep
command and add timeout=RUN_COMMAND_TIMEOUT (or accept a timeout arg) and a new
except subprocess.TimeoutExpired branch to return something like "Search timed
out".

In `@README.md`:
- Around line 36-37: Update the README to match the actual scratchpad
implementation described in lambda_agent/agent.py: replace mentions of
`.scratchpad/` and the `append_scratchpad` tool with the correct
`.agent/scratchpad.md` path and the actual tool names `read_scratchpad`,
`write_scratchpad`, `update_scratchpad`, and `clear_scratchpad` (also update the
duplicate text at lines 72-80); ensure the README wording and examples reference
`.agent/scratchpad.md` and the four real functions so users are pointed to the
correct directory and API.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b9dc95e0-0887-4ecb-87b6-757c700ca366

📥 Commits

Reviewing files that changed from the base of the PR and between 533d5f4 and bba3539.

📒 Files selected for processing (5)
  • README.md
  • lambda_agent/agent.py
  • lambda_agent/subagent.py
  • lambda_agent/tools.py
  • pyproject.toml

Comment thread lambda_agent/subagent.py
Comment thread lambda_agent/tools.py
Comment thread lambda_agent/tools.py
Comment on lines +145 to +167
result = subprocess.run(command, capture_output=True, text=True)

if result.returncode == 0:
# grep output is already in the format we want (file:line: content)
# but we strip it to clean it up lightly
results = result.stdout.strip().split("\n")
if not results or not results[0]:
return f"No matches found for '{query}'"

if len(results) > 100:
return (
"\n".join(results[:100])
+ f"\n\n... and {len(results) - 100} more matches."
)
return "\n".join(results)
elif result.returncode == 1:
return f"No matches found for '{query}'"

# Truncate results if there are too many to avoid blowing up the context window
if len(results) > 100:
return (
"\n".join(results[:100])
+ f"\n\n... and {len(results) - 100} more matches."
)

return "\n".join(results)
else:
return f"Error searching repository: {result.stderr.strip()}"
except FileNotFoundError:
return "Error: 'grep' is not installed or available in PATH."
except Exception as e:
return f"Error searching repository: {str(e)}"
return f"Error executing search: {str(e)}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add a timeout to the grep subprocess.

This tool is callable by both the main agent and sub-agents, so an unbounded subprocess.run() can stall the entire session on a large or unintended search scope. The command path needs the same timeout guard you already apply in run_command.

Suggested fix
-        result = subprocess.run(command, capture_output=True, text=True)
+        result = subprocess.run(
+            command,
+            capture_output=True,
+            text=True,
+            timeout=30,
+        )
@@
     except FileNotFoundError:
         return "Error: 'grep' is not installed or available in PATH."
+    except subprocess.TimeoutExpired:
+        return "Error: Search timed out after 30 seconds."
     except Exception as e:
         return f"Error executing search: {str(e)}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
result = subprocess.run(command, capture_output=True, text=True)
if result.returncode == 0:
# grep output is already in the format we want (file:line: content)
# but we strip it to clean it up lightly
results = result.stdout.strip().split("\n")
if not results or not results[0]:
return f"No matches found for '{query}'"
if len(results) > 100:
return (
"\n".join(results[:100])
+ f"\n\n... and {len(results) - 100} more matches."
)
return "\n".join(results)
elif result.returncode == 1:
return f"No matches found for '{query}'"
# Truncate results if there are too many to avoid blowing up the context window
if len(results) > 100:
return (
"\n".join(results[:100])
+ f"\n\n... and {len(results) - 100} more matches."
)
return "\n".join(results)
else:
return f"Error searching repository: {result.stderr.strip()}"
except FileNotFoundError:
return "Error: 'grep' is not installed or available in PATH."
except Exception as e:
return f"Error searching repository: {str(e)}"
return f"Error executing search: {str(e)}"
result = subprocess.run(
command,
capture_output=True,
text=True,
timeout=30,
)
if result.returncode == 0:
# grep output is already in the format we want (file:line: content)
# but we strip it to clean it up lightly
results = result.stdout.strip().split("\n")
if not results or not results[0]:
return f"No matches found for '{query}'"
if len(results) > 100:
return (
"\n".join(results[:100])
f"\n\n... and {len(results) - 100} more matches."
)
return "\n".join(results)
elif result.returncode == 1:
return f"No matches found for '{query}'"
else:
return f"Error searching repository: {result.stderr.strip()}"
except FileNotFoundError:
return "Error: 'grep' is not installed or available in PATH."
except subprocess.TimeoutExpired:
return "Error: Search timed out after 30 seconds."
except Exception as e:
return f"Error executing search: {str(e)}"
🧰 Tools
🪛 Ruff (0.15.9)

[error] 145-145: subprocess call: check for execution of untrusted input

(S603)


[warning] 166-166: Do not catch blind exception: Exception

(BLE001)


[warning] 167-167: Use explicit conversion flag

Replace with conversion flag

(RUF010)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lambda_agent/tools.py` around lines 145 - 167, The grep subprocess call in
the search routine uses subprocess.run(...) without a timeout which can hang;
update the call to pass a timeout (use the same timeout constant or helper used
by run_command, e.g., RUN_COMMAND_TIMEOUT or a timeout parameter) and handle
subprocess.TimeoutExpired in the surrounding try/except to return a clear
timeout error message; modify the block around subprocess.run in the function
that builds/runs the grep command and add timeout=RUN_COMMAND_TIMEOUT (or accept
a timeout arg) and a new except subprocess.TimeoutExpired branch to return
something like "Search timed out".

Comment thread README.md
Comment on lines +36 to +37
- **Agentic Scratchpad**: Lambda uses a hidden local scratchpad (`.scratchpad/`) to draft implementation plans, think through complex logic, and maintain context across long execution chains.
- **Stunning CLI Experience**: Built with [Rich](https://github.com/Textualize/rich), featuring distinct conversational bubbles, syntax highlighting, active token monitoring, and beautiful live spinners.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Scratchpad docs are out of sync with the implementation.

The README says Lambda uses .scratchpad/ and exposes append_scratchpad, but lambda_agent/agent.py documents .agent/scratchpad.md plus read_scratchpad / write_scratchpad / update_scratchpad / clear_scratchpad. As written, users will be pointed at the wrong directory and tool names.

Also applies to: 72-80

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 36 - 37, Update the README to match the actual
scratchpad implementation described in lambda_agent/agent.py: replace mentions
of `.scratchpad/` and the `append_scratchpad` tool with the correct
`.agent/scratchpad.md` path and the actual tool names `read_scratchpad`,
`write_scratchpad`, `update_scratchpad`, and `clear_scratchpad` (also update the
duplicate text at lines 72-80); ensure the README wording and examples reference
`.agent/scratchpad.md` and the four real functions so users are pointed to the
correct directory and API.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ayusrjn ayusrjn merged commit 4d154c7 into main Apr 11, 2026
2 of 3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Apr 12, 2026
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant