Skip to content

feat: Add Morph codebase search integration#699

Draft
DhruvBhatia0 wants to merge 2 commits intostitionai:mainfrom
DhruvBhatia0:feat/morph-codebase-search
Draft

feat: Add Morph codebase search integration#699
DhruvBhatia0 wants to merge 2 commits intostitionai:mainfrom
DhruvBhatia0:feat/morph-codebase-search

Conversation

@DhruvBhatia0
Copy link

Summary

  • Adds Morph as an optional codebase search backend, replacing the current approach of dumping the entire project into LLM context
  • When a Morph API key is configured, follow-up actions (bug fixes, features, answers) use targeted code search instead of full-project reads, significantly reducing token usage on large codebases
  • Gracefully falls back to the existing full-code-read behavior when no API key is set or when the search fails

Changes

File Change
src/services/morph.py New Morph API client with multi-turn tool loop (ripgrep, read, list_directory, finish)
src/services/morph_prompt.txt Search agent system prompt
src/config.py get_morph_api_key() / set_morph_api_key()
sample.config.toml MORPH key under [API_KEYS]
src/services/__init__.py Export Morph
src/filesystem/read_code.py search_code() method with fallback
src/agents/agent.py Lazy code loading — determines action type before loading context
ui/src/routes/settings/+page.svelte MORPH key in settings UI

How it works

  1. User sends a follow-up message (bug fix, feature, question)
  2. The Action agent classifies the intent
  3. For answer/feature/bug actions: ReadCode.search_code(prompt) calls the Morph WarpGrep API
  4. WarpGrep searches the codebase in up to 4 turns using ripgrep, file reads, and directory listings
  5. Returns the complete relevant files (preserving existing prompt contracts)
  6. For run/report actions: falls back to full code read (these need broader context)

Notes

  • No new pip dependencies — uses requests (already in requirements.txt) and stdlib (xml.etree.ElementTree, subprocess)
  • Requires rg (ripgrep) on the host for search tool execution; returns a clear message if unavailable
  • All file paths from the API are validated against the project root to prevent path traversal
  • Users bring their own Morph API key (configured via the settings UI)

Test plan

  • All Python files pass ast.parse syntax validation
  • Config getter/setter follow existing pattern exactly
  • _file_tree excludes .git, node_modules, __pycache__, binary files
  • _validate_path rejects ../../etc/passwd and absolute paths outside project root
  • _run_ripgrep finds matches with rg, returns clear message when unavailable
  • _read_file handles full reads, line ranges, single lines, and errors
  • _parse_tool_calls handles valid XML, malformed XML (regex fallback), and empty input
  • _read_full_files reads valid files and rejects path traversal attempts
  • search() returns [] when no API key is set
  • Full mock API e2e: ripgrep → finish flow returns correct files
  • ReadCode falls back to code_set_to_markdown() on empty results or exceptions
  • Agent lazy loading: action determined before code context loaded

🤖 Generated with Claude Code

DhruvBhatia0 and others added 2 commits March 5, 2026 23:51
Replace naive full-project-read with targeted Morph search for the
answer, feature, and bug actions in subsequent_execute(). Falls back
to full code read when the API key is unset or the search returns
empty results.

Made-with: Cursor
Use typing.List[Dict] instead of Python 3.9+ lowercase generics,
rename file handles to match repo convention, fix import grouping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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