This is page 3 of 18. Use http://codebase.md/shashankss1205/codegraphcontext?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .github
│ └── workflows
│ ├── e2e-tests.yml
│ ├── post_discord_invite.yml
│ ├── test.yml
│ └── update-contributors.yml
├── .gitignore
├── CONTRIBUTING.md
├── contributors.md
├── docs
│ ├── docs
│ │ ├── architecture.md
│ │ ├── cli.md
│ │ ├── contributing_languages.md
│ │ ├── contributing.md
│ │ ├── cookbook.md
│ │ ├── core.md
│ │ ├── future_work.md
│ │ ├── images
│ │ │ ├── 1.png
│ │ │ ├── 11.png
│ │ │ ├── 12.png
│ │ │ ├── 13.png
│ │ │ ├── 14.png
│ │ │ ├── 16.png
│ │ │ ├── 19.png
│ │ │ ├── 2.png
│ │ │ ├── 20.png
│ │ │ ├── 21.png
│ │ │ ├── 22.png
│ │ │ ├── 23.png
│ │ │ ├── 24.png
│ │ │ ├── 26.png
│ │ │ ├── 28.png
│ │ │ ├── 29.png
│ │ │ ├── 3.png
│ │ │ ├── 30.png
│ │ │ ├── 31.png
│ │ │ ├── 32.png
│ │ │ ├── 33.png
│ │ │ ├── 34.png
│ │ │ ├── 35.png
│ │ │ ├── 36.png
│ │ │ ├── 38.png
│ │ │ ├── 39.png
│ │ │ ├── 4.png
│ │ │ ├── 40.png
│ │ │ ├── 41.png
│ │ │ ├── 42.png
│ │ │ ├── 43.png
│ │ │ ├── 44.png
│ │ │ ├── 5.png
│ │ │ ├── 6.png
│ │ │ ├── 7.png
│ │ │ ├── 8.png
│ │ │ ├── 9.png
│ │ │ ├── Indexing.gif
│ │ │ ├── tool_images
│ │ │ │ ├── 1.png
│ │ │ │ ├── 2.png
│ │ │ │ └── 3.png
│ │ │ └── Usecase.gif
│ │ ├── index.md
│ │ ├── installation.md
│ │ ├── license.md
│ │ ├── server.md
│ │ ├── tools.md
│ │ ├── troubleshooting.md
│ │ └── use_cases.md
│ ├── mkdocs.yml
│ └── site
│ ├── 404.html
│ ├── architecture
│ │ └── index.html
│ ├── assets
│ │ ├── images
│ │ │ └── favicon.png
│ │ ├── javascripts
│ │ │ ├── bundle.f55a23d4.min.js
│ │ │ ├── bundle.f55a23d4.min.js.map
│ │ │ ├── lunr
│ │ │ │ ├── min
│ │ │ │ │ ├── lunr.ar.min.js
│ │ │ │ │ ├── lunr.da.min.js
│ │ │ │ │ ├── lunr.de.min.js
│ │ │ │ │ ├── lunr.du.min.js
│ │ │ │ │ ├── lunr.el.min.js
│ │ │ │ │ ├── lunr.es.min.js
│ │ │ │ │ ├── lunr.fi.min.js
│ │ │ │ │ ├── lunr.fr.min.js
│ │ │ │ │ ├── lunr.he.min.js
│ │ │ │ │ ├── lunr.hi.min.js
│ │ │ │ │ ├── lunr.hu.min.js
│ │ │ │ │ ├── lunr.hy.min.js
│ │ │ │ │ ├── lunr.it.min.js
│ │ │ │ │ ├── lunr.ja.min.js
│ │ │ │ │ ├── lunr.jp.min.js
│ │ │ │ │ ├── lunr.kn.min.js
│ │ │ │ │ ├── lunr.ko.min.js
│ │ │ │ │ ├── lunr.multi.min.js
│ │ │ │ │ ├── lunr.nl.min.js
│ │ │ │ │ ├── lunr.no.min.js
│ │ │ │ │ ├── lunr.pt.min.js
│ │ │ │ │ ├── lunr.ro.min.js
│ │ │ │ │ ├── lunr.ru.min.js
│ │ │ │ │ ├── lunr.sa.min.js
│ │ │ │ │ ├── lunr.stemmer.support.min.js
│ │ │ │ │ ├── lunr.sv.min.js
│ │ │ │ │ ├── lunr.ta.min.js
│ │ │ │ │ ├── lunr.te.min.js
│ │ │ │ │ ├── lunr.th.min.js
│ │ │ │ │ ├── lunr.tr.min.js
│ │ │ │ │ ├── lunr.vi.min.js
│ │ │ │ │ └── lunr.zh.min.js
│ │ │ │ ├── tinyseg.js
│ │ │ │ └── wordcut.js
│ │ │ └── workers
│ │ │ ├── search.973d3a69.min.js
│ │ │ └── search.973d3a69.min.js.map
│ │ └── stylesheets
│ │ ├── main.2a3383ac.min.css
│ │ ├── main.2a3383ac.min.css.map
│ │ ├── palette.06af60db.min.css
│ │ └── palette.06af60db.min.css.map
│ ├── cli
│ │ └── index.html
│ ├── contributing
│ │ └── index.html
│ ├── contributing_languages
│ │ └── index.html
│ ├── cookbook
│ │ └── index.html
│ ├── core
│ │ └── index.html
│ ├── future_work
│ │ └── index.html
│ ├── images
│ │ ├── 1.png
│ │ ├── 11.png
│ │ ├── 12.png
│ │ ├── 13.png
│ │ ├── 14.png
│ │ ├── 16.png
│ │ ├── 19.png
│ │ ├── 2.png
│ │ ├── 20.png
│ │ ├── 21.png
│ │ ├── 22.png
│ │ ├── 23.png
│ │ ├── 24.png
│ │ ├── 26.png
│ │ ├── 28.png
│ │ ├── 29.png
│ │ ├── 3.png
│ │ ├── 30.png
│ │ ├── 31.png
│ │ ├── 32.png
│ │ ├── 33.png
│ │ ├── 34.png
│ │ ├── 35.png
│ │ ├── 36.png
│ │ ├── 38.png
│ │ ├── 39.png
│ │ ├── 4.png
│ │ ├── 40.png
│ │ ├── 41.png
│ │ ├── 42.png
│ │ ├── 43.png
│ │ ├── 44.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ ├── 7.png
│ │ ├── 8.png
│ │ ├── 9.png
│ │ ├── Indexing.gif
│ │ ├── tool_images
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ └── 3.png
│ │ └── Usecase.gif
│ ├── index.html
│ ├── installation
│ │ └── index.html
│ ├── license
│ │ └── index.html
│ ├── search
│ │ └── search_index.json
│ ├── server
│ │ └── index.html
│ ├── sitemap.xml
│ ├── sitemap.xml.gz
│ ├── tools
│ │ └── index.html
│ ├── troubleshooting
│ │ └── index.html
│ └── use_cases
│ └── index.html
├── images
│ ├── 1.png
│ ├── 11.png
│ ├── 12.png
│ ├── 13.png
│ ├── 14.png
│ ├── 16.png
│ ├── 19.png
│ ├── 2.png
│ ├── 20.png
│ ├── 21.png
│ ├── 22.png
│ ├── 23.png
│ ├── 24.png
│ ├── 26.png
│ ├── 28.png
│ ├── 29.png
│ ├── 3.png
│ ├── 30.png
│ ├── 31.png
│ ├── 32.png
│ ├── 33.png
│ ├── 34.png
│ ├── 35.png
│ ├── 36.png
│ ├── 38.png
│ ├── 39.png
│ ├── 4.png
│ ├── 40.png
│ ├── 41.png
│ ├── 42.png
│ ├── 43.png
│ ├── 44.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ ├── 9.png
│ ├── Indexing.gif
│ ├── tool_images
│ │ ├── 1.png
│ │ ├── 2.png
│ │ └── 3.png
│ └── Usecase.gif
├── LICENSE
├── MANIFEST.in
├── organizer
│ ├── CONTRIBUTING_LANGUAGES.md
│ ├── cookbook.md
│ ├── docs.md
│ ├── language_specific_nodes.md
│ ├── Tools_Exploration.md
│ └── troubleshoot.md
├── package-lock.json
├── pyproject.toml
├── README.md
├── scripts
│ ├── generate_lang_contributors.py
│ └── post_install_fix.sh
├── SECURITY.md
├── src
│ └── codegraphcontext
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli
│ │ ├── __init__.py
│ │ ├── cli_helpers.py
│ │ ├── main.py
│ │ ├── setup_macos.py
│ │ └── setup_wizard.py
│ ├── core
│ │ ├── __init__.py
│ │ ├── database.py
│ │ ├── jobs.py
│ │ └── watcher.py
│ ├── prompts.py
│ ├── server.py
│ ├── tools
│ │ ├── __init__.py
│ │ ├── advanced_language_query_tool.py
│ │ ├── code_finder.py
│ │ ├── graph_builder.py
│ │ ├── languages
│ │ │ ├── c.py
│ │ │ ├── cpp.py
│ │ │ ├── go.py
│ │ │ ├── java.py
│ │ │ ├── javascript.py
│ │ │ ├── python.py
│ │ │ ├── ruby.py
│ │ │ ├── rust.py
│ │ │ └── typescript.py
│ │ ├── package_resolver.py
│ │ ├── query_tool_languages
│ │ │ ├── c_toolkit.py
│ │ │ ├── cpp_toolkit.py
│ │ │ ├── go_toolkit.py
│ │ │ ├── java_toolkit.py
│ │ │ ├── javascript_toolkit.py
│ │ │ ├── python_toolkit.py
│ │ │ ├── ruby_toolkit.py
│ │ │ ├── rust_toolkit.py
│ │ │ └── typescript_toolkit.py
│ │ └── system.py
│ └── utils
│ └── debug_log.py
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── sample_project
│ │ ├── advanced_calls.py
│ │ ├── advanced_classes.py
│ │ ├── advanced_classes2.py
│ │ ├── advanced_functions.py
│ │ ├── advanced_imports.py
│ │ ├── async_features.py
│ │ ├── callbacks_decorators.py
│ │ ├── circular1.py
│ │ ├── circular2.py
│ │ ├── class_instantiation.py
│ │ ├── cli_and_dunder.py
│ │ ├── complex_classes.py
│ │ ├── comprehensions_generators.py
│ │ ├── context_managers.py
│ │ ├── control_flow.py
│ │ ├── datatypes.py
│ │ ├── dynamic_dispatch.py
│ │ ├── dynamic_imports.py
│ │ ├── edge_cases
│ │ │ ├── comments_only.py
│ │ │ ├── docstring_only.py
│ │ │ ├── empty.py
│ │ │ ├── hardcoded_secrets.py
│ │ │ ├── long_functions.py
│ │ │ └── syntax_error.py
│ │ ├── function_chains.py
│ │ ├── generators.py
│ │ ├── import_reexports.py
│ │ ├── mapping_calls.py
│ │ ├── module_a.py
│ │ ├── module_b.py
│ │ ├── module_c
│ │ │ ├── __init__.py
│ │ │ ├── submodule1.py
│ │ │ └── submodule2.py
│ │ ├── namespace_pkg
│ │ │ └── ns_module.py
│ │ ├── pattern_matching.py
│ │ └── typing_examples.py
│ ├── sample_project_c
│ │ ├── cgc_sample
│ │ ├── include
│ │ │ ├── config.h
│ │ │ ├── math
│ │ │ │ └── vec.h
│ │ │ ├── module.h
│ │ │ ├── platform.h
│ │ │ └── util.h
│ │ ├── Makefile
│ │ ├── README.md
│ │ └── src
│ │ ├── main.c
│ │ ├── math
│ │ │ └── vec.c
│ │ ├── module.c
│ │ └── util.c
│ ├── sample_project_cpp
│ │ ├── class_features.cpp
│ │ ├── classes.cpp
│ │ ├── control_flow.cpp
│ │ ├── edge_cases.cpp
│ │ ├── enum_struct_union.cpp
│ │ ├── exceptions.cpp
│ │ ├── file_io.cpp
│ │ ├── function_chain.cpp
│ │ ├── function_chain.h
│ │ ├── function_types.cpp
│ │ ├── main.cpp
│ │ ├── main.exe
│ │ ├── namespaces.cpp
│ │ ├── raii_example.cpp
│ │ ├── README.md
│ │ ├── sample_project.exe
│ │ ├── stl_usage.cpp
│ │ ├── templates.cpp
│ │ └── types_variable_assignments.cpp
│ ├── sample_project_go
│ │ ├── advanced_types.go
│ │ ├── basic_functions.go
│ │ ├── embedded_composition.go
│ │ ├── error_handling.go
│ │ ├── generics.go
│ │ ├── go.mod
│ │ ├── goroutines_channels.go
│ │ ├── interfaces.go
│ │ ├── packages_imports.go
│ │ ├── README.md
│ │ ├── structs_methods.go
│ │ └── util
│ │ └── helpers.go
│ ├── sample_project_java
│ │ ├── out
│ │ │ └── com
│ │ │ └── example
│ │ │ └── app
│ │ │ ├── annotations
│ │ │ │ └── Logged.class
│ │ │ ├── Main.class
│ │ │ ├── misc
│ │ │ │ ├── Outer.class
│ │ │ │ └── Outer$Inner.class
│ │ │ ├── model
│ │ │ │ ├── Role.class
│ │ │ │ └── User.class
│ │ │ ├── service
│ │ │ │ ├── AbstractGreeter.class
│ │ │ │ ├── GreetingService.class
│ │ │ │ └── impl
│ │ │ │ └── GreetingServiceImpl.class
│ │ │ └── util
│ │ │ ├── CollectionUtils.class
│ │ │ └── IOHelper.class
│ │ ├── README.md
│ │ ├── sources.txt
│ │ └── src
│ │ └── com
│ │ └── example
│ │ └── app
│ │ ├── annotations
│ │ │ └── Logged.java
│ │ ├── Main.java
│ │ ├── misc
│ │ │ └── Outer.java
│ │ ├── model
│ │ │ ├── Role.java
│ │ │ └── User.java
│ │ ├── service
│ │ │ ├── AbstractGreeter.java
│ │ │ ├── GreetingService.java
│ │ │ └── impl
│ │ │ └── GreetingServiceImpl.java
│ │ └── util
│ │ ├── CollectionUtils.java
│ │ └── IOHelper.java
│ ├── sample_project_javascript
│ │ ├── arrays.js
│ │ ├── asyncAwait.js
│ │ ├── classes.js
│ │ ├── dom.js
│ │ ├── errorHandling.js
│ │ ├── events.js
│ │ ├── exporter.js
│ │ ├── fetchAPI.js
│ │ ├── fixtures
│ │ │ └── js
│ │ │ └── accessors.js
│ │ ├── functions.js
│ │ ├── importer.js
│ │ ├── objects.js
│ │ ├── promises.js
│ │ ├── README.md
│ │ └── variables.js
│ ├── sample_project_misc
│ │ ├── index.html
│ │ ├── README.md
│ │ ├── styles.css
│ │ ├── tables.css
│ │ └── tables.html
│ ├── sample_project_php
│ │ ├── classes_objects.php
│ │ ├── database.php
│ │ ├── edgecases.php
│ │ ├── error_handling.php
│ │ ├── file_handling.php
│ │ ├── functions.php
│ │ ├── generators_iterators.php
│ │ ├── globals_superglobals.php
│ │ ├── Inheritance.php
│ │ ├── interface_traits.php
│ │ └── README.md
│ ├── sample_project_ruby
│ │ ├── class_example.rb
│ │ ├── enumerables.rb
│ │ ├── error_handling.rb
│ │ ├── file_io.rb
│ │ ├── inheritance_example.rb
│ │ ├── main.rb
│ │ ├── metaprogramming.rb
│ │ ├── mixins_example.rb
│ │ ├── module_example.rb
│ │ └── tests
│ │ ├── test_mixins.py
│ │ └── test_sample.rb
│ ├── sample_project_rust
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ └── src
│ │ ├── basic_functions.rs
│ │ ├── concurrency.rs
│ │ ├── error_handling.rs
│ │ ├── generics.rs
│ │ ├── iterators_closures.rs
│ │ ├── lib.rs
│ │ ├── lifetimes_references.rs
│ │ ├── modules.rs
│ │ ├── smart_pointers.rs
│ │ ├── structs_enums.rs
│ │ └── traits.rs
│ ├── sample_project_typescript
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── advanced-types.ts
│ │ │ ├── async-promises.ts
│ │ │ ├── classes-inheritance.ts
│ │ │ ├── decorators-metadata.ts
│ │ │ ├── error-validation.ts
│ │ │ ├── functions-generics.ts
│ │ │ ├── index.ts
│ │ │ ├── modules-namespaces.ts
│ │ │ ├── types-interfaces.ts
│ │ │ └── utilities-helpers.ts
│ │ └── tsconfig.json
│ ├── test_cpp_parser.py
│ ├── test_database_validation.py
│ ├── test_end_to_end.py
│ ├── test_graph_indexing_js.py
│ ├── test_graph_indexing.py
│ ├── test_tree_sitter
│ │ ├── __init__.py
│ │ ├── class_instantiation.py
│ │ ├── complex_classes.py
│ │ └── test_file.py
│ └── test_typescript_parser.py
└── website
├── .example.env
├── .gitignore
├── api
│ └── pypi.ts
├── bun.lockb
├── components.json
├── eslint.config.js
├── index.html
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.ico
│ ├── placeholder.svg
│ └── robots.txt
├── README.md
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ ├── function-calls.png
│ │ ├── graph-total.png
│ │ ├── hero-graph.jpg
│ │ └── hierarchy.png
│ ├── components
│ │ ├── ComparisonTable.tsx
│ │ ├── CookbookSection.tsx
│ │ ├── DemoSection.tsx
│ │ ├── ExamplesSection.tsx
│ │ ├── FeaturesSection.tsx
│ │ ├── Footer.tsx
│ │ ├── HeroSection.tsx
│ │ ├── InstallationSection.tsx
│ │ ├── MoveToTop.tsx
│ │ ├── ShowDownloads.tsx
│ │ ├── ShowStarGraph.tsx
│ │ ├── TestimonialSection.tsx
│ │ ├── ThemeProvider.tsx
│ │ ├── ThemeToggle.tsx
│ │ └── ui
│ │ ├── accordion.tsx
│ │ ├── alert-dialog.tsx
│ │ ├── alert.tsx
│ │ ├── aspect-ratio.tsx
│ │ ├── avatar.tsx
│ │ ├── badge.tsx
│ │ ├── breadcrumb.tsx
│ │ ├── button.tsx
│ │ ├── calendar.tsx
│ │ ├── card.tsx
│ │ ├── carousel.tsx
│ │ ├── chart.tsx
│ │ ├── checkbox.tsx
│ │ ├── collapsible.tsx
│ │ ├── command.tsx
│ │ ├── context-menu.tsx
│ │ ├── dialog.tsx
│ │ ├── drawer.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── form.tsx
│ │ ├── hover-card.tsx
│ │ ├── input-otp.tsx
│ │ ├── input.tsx
│ │ ├── label.tsx
│ │ ├── menubar.tsx
│ │ ├── navigation-menu.tsx
│ │ ├── orbiting-circles.tsx
│ │ ├── pagination.tsx
│ │ ├── popover.tsx
│ │ ├── progress.tsx
│ │ ├── radio-group.tsx
│ │ ├── resizable.tsx
│ │ ├── scroll-area.tsx
│ │ ├── select.tsx
│ │ ├── separator.tsx
│ │ ├── sheet.tsx
│ │ ├── sidebar.tsx
│ │ ├── skeleton.tsx
│ │ ├── slider.tsx
│ │ ├── sonner.tsx
│ │ ├── switch.tsx
│ │ ├── table.tsx
│ │ ├── tabs.tsx
│ │ ├── textarea.tsx
│ │ ├── toast.tsx
│ │ ├── toaster.tsx
│ │ ├── toggle-group.tsx
│ │ ├── toggle.tsx
│ │ ├── tooltip.tsx
│ │ └── use-toast.ts
│ ├── hooks
│ │ ├── use-mobile.tsx
│ │ └── use-toast.ts
│ ├── index.css
│ ├── lib
│ │ └── utils.ts
│ ├── main.tsx
│ ├── pages
│ │ ├── Index.tsx
│ │ └── NotFound.tsx
│ └── vite-env.d.ts
├── tailwind.config.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── vercel.json
└── vite.config.ts
```
# Files
--------------------------------------------------------------------------------
/docs/docs/troubleshooting.md:
--------------------------------------------------------------------------------
```markdown
1 | # CodeGraphContext Troubleshooting Guide
2 |
3 | Use this checklist whenever `cgc setup` or `cgc start` doesn’t behave as expected. It keeps the happy path short, but includes the fallback steps when something goes wrong.
4 |
5 | ## 1. Prerequisites at a glance
6 |
7 | - **Windows + PowerShell** commands below assume the `py` launcher. Adapt to `python3` if you’re on macOS/Linux.
8 | - **Python 3.11** (recommended). Run `py -3.11 --version` to confirm.
9 | - **Neo4j account** (only required if you prefer Neo4j AuraDB instead of Docker).
10 |
11 | ## 2. Create and activate a virtual environment
12 |
13 | From the repository root (`CodeGraphContext/`):
14 |
15 | ```powershell
16 | py -3.11 -m venv venv
17 | .\venv\Scripts\python.exe -m pip install --upgrade pip
18 | ```
19 |
20 | - On Windows, Neo4j driver 6.x can crash with `AttributeError: socket.EAI_ADDRFAMILY`. If you see that, run:
21 | ```powershell
22 | .\venv\Scripts\python.exe -m pip install "neo4j<6"
23 | ```
24 |
25 | ## 3. Run the setup wizard (preferred)
26 |
27 | Launch the wizard:
28 |
29 | ```powershell
30 | .\venv\Scripts\cgc.exe setup
31 | ```
32 |
33 | > **Tip:** If you want the wizard to spin up a local Neo4j instance for you, make sure **Docker Desktop** is installed and running before you launch `cgc setup`. If Docker isn’t running, the setup wizard will fail when it tries to install Neo4j locally.
34 |
35 | What happens next:
36 |
37 | - The wizard checks for Docker. If it’s running, it can auto-provision a local Neo4j instance for you.
38 | - Alternatively, you can supply credentials for an existing Neo4j AuraDB database.
39 | - At the end, it generates:
40 | - `mcp.json` in your project directory (stores the MCP server command + env vars).
41 | - `~/.codegraphcontext/.env` containing `NEO4J_URI`, `NEO4J_USERNAME`, `NEO4J_PASSWORD`.
42 |
43 | Make sure the Docker container (or remote Neo4j) is still running before you start the server.
44 |
45 | ## 4. Start the MCP server
46 |
47 | Once the wizard completes successfully:
48 |
49 | ```powershell
50 | .\venv\Scripts\cgc.exe start
51 | ```
52 |
53 | Expected output includes:
54 |
55 | ```text
56 | Starting CodeGraphContext Server...
57 | ...
58 | MCP Server is running. Waiting for requests...
59 | ```
60 |
61 | If you instead see:
62 |
63 | ```text
64 | Configuration Error: Neo4j credentials must be set via environment variables
65 | ```
66 |
67 | then either no credentials were saved, or the wizard was skipped—see the manual alternative below.
68 |
69 | ## 5. Manual credential setup (fallback)
70 |
71 | If you prefer not to use the wizard or need to fix a broken configuration:
72 |
73 | 1. Create a `mcp.json` (or edit the one that exists) in the repository root:
74 |
75 | ```json
76 | {
77 | "mcpServers": {
78 | "CodeGraphContext": {
79 | "command": "cgc",
80 | "args": ["start"],
81 | "env": {
82 | "NEO4J_URI": "neo4j+s://YOUR-HOSTNAME:7687",
83 | "NEO4J_USERNAME": "neo4j",
84 | "NEO4J_PASSWORD": "super-secret-password"
85 | }
86 | }
87 | }
88 | }
89 | ```
90 |
91 | 2. (Optional) Also create `%USERPROFILE%\.codegraphcontext\.env` with the same key/value pairs. The CLI loads that file automatically.
92 |
93 | 3. Re-run:
94 |
95 | ```powershell
96 | .\venv\Scripts\cgc.exe start
97 | ```
98 |
99 | ## 6. Common issues & fixes
100 |
101 | | Symptom | Likely Cause | Fix |
102 | | --- | --- | --- |
103 | | `Configuration Error: Neo4j credentials must be set…` | `mcp.json`/`.env` missing or empty | Run `cgc setup` again **with Docker running**, or create the files manually (section 5). |
104 | | `AttributeError: socket.EAI_ADDRFAMILY` | Neo4j 6.x bug on Windows | Install the 5.x driver: `.\venv\Scripts\python.exe -m pip install "neo4j<6"` and retry. |
105 | | Setup wizard fails while pulling Docker image | Docker Desktop not running or Docker permissions missing | Start Docker Desktop, wait for it to report “Running”, then rerun `cgc setup`. |
106 | | Server exits immediately with no log | Neo4j instance is offline | Check Docker container status or AuraDB dashboard; restart Neo4j and call `cgc start` again. |
107 |
108 | ## 7. After the server is running
109 |
110 | - Keep the virtual environment active whenever you run `cgc` commands.
111 | - Use `pytest` from the same env to run tests:
112 |
113 | ```powershell
114 | .\venv\Scripts\pytest
115 | ```
116 |
117 | - Front-end website lives under `website/` if you need to run `npm run dev`.
118 |
119 | When in doubt, re-run the wizard with Docker active—it regenerates the configuration files without touching your code. Let me know if any section needs clarifying! :)
```
--------------------------------------------------------------------------------
/organizer/troubleshoot.md:
--------------------------------------------------------------------------------
```markdown
1 | # CodeGraphContext Troubleshooting Guide
2 |
3 | Use this checklist whenever `cgc setup` or `cgc start` doesn’t behave as expected. It keeps the happy path short, but includes the fallback steps when something goes wrong.
4 |
5 | ## 1. Prerequisites at a glance
6 |
7 | - **Windows + PowerShell** commands below assume the `py` launcher. Adapt to `python3` if you’re on macOS/Linux.
8 | - **Python 3.11** (recommended). Run `py -3.11 --version` to confirm.
9 | - **Git** for cloning the repository.
10 | - **Docker Desktop** installed *and running* before you launch `cgc setup` if you want the wizard to spin up a local Neo4j for you.
11 | - **Neo4j account** (only required if you prefer Neo4j AuraDB instead of Docker).
12 |
13 | > **Tip:** If Docker isn’t running, the setup wizard will fail when it tries to install Neo4j locally.
14 |
15 | ## 2. Create and activate a virtual environment
16 |
17 | From the repository root (`CodeGraphContext/`):
18 |
19 | ```powershell
20 | py -3.11 -m venv venv
21 | .\venv\Scripts\python.exe -m pip install --upgrade pip
22 | ```
23 |
24 | - On Windows, Neo4j driver 6.x can crash with `AttributeError: socket.EAI_ADDRFAMILY`. If you see that, run:
25 | ```powershell
26 | .\venv\Scripts\python.exe -m pip install "neo4j<6"
27 | ```
28 |
29 | ## 3. Run the setup wizard (preferred)
30 |
31 | Launch the wizard:
32 |
33 | ```powershell
34 | .\venv\Scripts\cgc.exe setup
35 | ```
36 |
37 | What happens next:
38 |
39 | - The wizard checks for Docker. If it’s running, it can auto-provision a local Neo4j instance for you.
40 | - Alternatively, you can supply credentials for an existing Neo4j AuraDB database.
41 | - At the end, it generates:
42 | - `mcp.json` in your project directory (stores the MCP server command + env vars).
43 | - `~/.codegraphcontext/.env` containing `NEO4J_URI`, `NEO4J_USERNAME`, `NEO4J_PASSWORD`.
44 |
45 | Make sure the Docker container (or remote Neo4j) is still running before you start the server.
46 |
47 | ## 4. Start the MCP server
48 |
49 | Once the wizard completes successfully:
50 |
51 | ```powershell
52 | .\venv\Scripts\cgc.exe start
53 | ```
54 |
55 | Expected output includes:
56 |
57 | ```text
58 | Starting CodeGraphContext Server...
59 | ...
60 | MCP Server is running. Waiting for requests...
61 | ```
62 |
63 | If you instead see:
64 |
65 | ```text
66 | Configuration Error: Neo4j credentials must be set via environment variables
67 | ```
68 |
69 | then either no credentials were saved, or the wizard was skipped—see the manual alternative below.
70 |
71 | ## 5. Manual credential setup (fallback)
72 |
73 | If you prefer not to use the wizard or need to fix a broken configuration:
74 |
75 | 1. Create a `mcp.json` (or edit the one that exists) in the repository root:
76 |
77 | ```json
78 | {
79 | "mcpServers": {
80 | "CodeGraphContext": {
81 | "command": "cgc",
82 | "args": ["start"],
83 | "env": {
84 | "NEO4J_URI": "neo4j+s://YOUR-HOSTNAME:7687",
85 | "NEO4J_USERNAME": "neo4j",
86 | "NEO4J_PASSWORD": "super-secret-password"
87 | }
88 | }
89 | }
90 | }
91 | ```
92 |
93 | 2. (Optional) Also create `%USERPROFILE%\.codegraphcontext\.env` with the same key/value pairs. The CLI loads that file automatically.
94 |
95 | 3. Re-run:
96 |
97 | ```powershell
98 | .\venv\Scripts\cgc.exe start
99 | ```
100 |
101 | ## 6. Common issues & fixes
102 |
103 | | Symptom | Likely Cause | Fix |
104 | | --- | --- | --- |
105 | | `Configuration Error: Neo4j credentials must be set…` | `mcp.json`/`.env` missing or empty | Run `cgc setup` again **with Docker running**, or create the files manually (section 5). |
106 | | `AttributeError: socket.EAI_ADDRFAMILY` | Neo4j 6.x bug on Windows | Install the 5.x driver: `.\venv\Scripts\python.exe -m pip install "neo4j<6"` and retry. |
107 | | Setup wizard fails while pulling Docker image | Docker Desktop not running or Docker permissions missing | Start Docker Desktop, wait for it to report “Running”, then rerun `cgc setup`. |
108 | | Server exits immediately with no log | Neo4j instance is offline | Check Docker container status or AuraDB dashboard; restart Neo4j and call `cgc start` again. |
109 |
110 | ## 7. After the server is running
111 |
112 | - Keep the virtual environment active whenever you run `cgc` commands.
113 | - Use `pytest` from the same env to run tests:
114 |
115 | ```powershell
116 | .\venv\Scripts\pytest
117 | ```
118 |
119 | - Front-end website lives under `website/` if you need to run `npm run dev`.
120 |
121 | When in doubt, re-run the wizard with Docker active—it regenerates the configuration files without touching your code. Let me know if any section needs clarifying! :)
122 |
```
--------------------------------------------------------------------------------
/website/src/components/ui/sheet.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import * as SheetPrimitive from "@radix-ui/react-dialog";
2 | import { cva, type VariantProps } from "class-variance-authority";
3 | import { X } from "lucide-react";
4 | import * as React from "react";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const Sheet = SheetPrimitive.Root;
9 |
10 | const SheetTrigger = SheetPrimitive.Trigger;
11 |
12 | const SheetClose = SheetPrimitive.Close;
13 |
14 | const SheetPortal = SheetPrimitive.Portal;
15 |
16 | const SheetOverlay = React.forwardRef<
17 | React.ElementRef<typeof SheetPrimitive.Overlay>,
18 | React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
19 | >(({ className, ...props }, ref) => (
20 | <SheetPrimitive.Overlay
21 | className={cn(
22 | "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
23 | className,
24 | )}
25 | {...props}
26 | ref={ref}
27 | />
28 | ));
29 | SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
30 |
31 | const sheetVariants = cva(
32 | "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
33 | {
34 | variants: {
35 | side: {
36 | top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
37 | bottom:
38 | "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
39 | left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
40 | right:
41 | "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
42 | },
43 | },
44 | defaultVariants: {
45 | side: "right",
46 | },
47 | },
48 | );
49 |
50 | interface SheetContentProps
51 | extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
52 | VariantProps<typeof sheetVariants> {}
53 |
54 | const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Content>, SheetContentProps>(
55 | ({ side = "right", className, children, ...props }, ref) => (
56 | <SheetPortal>
57 | <SheetOverlay />
58 | <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
59 | {children}
60 | <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-secondary hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
61 | <X className="h-4 w-4" />
62 | <span className="sr-only">Close</span>
63 | </SheetPrimitive.Close>
64 | </SheetPrimitive.Content>
65 | </SheetPortal>
66 | ),
67 | );
68 | SheetContent.displayName = SheetPrimitive.Content.displayName;
69 |
70 | const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
71 | <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
72 | );
73 | SheetHeader.displayName = "SheetHeader";
74 |
75 | const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
76 | <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} />
77 | );
78 | SheetFooter.displayName = "SheetFooter";
79 |
80 | const SheetTitle = React.forwardRef<
81 | React.ElementRef<typeof SheetPrimitive.Title>,
82 | React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
83 | >(({ className, ...props }, ref) => (
84 | <SheetPrimitive.Title ref={ref} className={cn("text-lg font-semibold text-foreground", className)} {...props} />
85 | ));
86 | SheetTitle.displayName = SheetPrimitive.Title.displayName;
87 |
88 | const SheetDescription = React.forwardRef<
89 | React.ElementRef<typeof SheetPrimitive.Description>,
90 | React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
91 | >(({ className, ...props }, ref) => (
92 | <SheetPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
93 | ));
94 | SheetDescription.displayName = SheetPrimitive.Description.displayName;
95 |
96 | export {
97 | Sheet,
98 | SheetClose,
99 | SheetContent,
100 | SheetDescription,
101 | SheetFooter,
102 | SheetHeader,
103 | SheetOverlay,
104 | SheetPortal,
105 | SheetTitle,
106 | SheetTrigger,
107 | };
108 |
```
--------------------------------------------------------------------------------
/tests/sample_project_go/interfaces.go:
--------------------------------------------------------------------------------
```go
1 | // interfaces.go - Demonstrates Go interfaces
2 | package main
3 |
4 | import (
5 | "fmt"
6 | "math"
7 | )
8 |
9 | // Shape is a basic interface
10 | type Shape interface {
11 | Area() float64
12 | Perimeter() float64
13 | }
14 |
15 | // Drawable extends Shape interface
16 | type Drawable interface {
17 | Shape
18 | Draw() string
19 | }
20 |
21 | // Named is a simple interface
22 | type Named interface {
23 | GetName() string
24 | }
25 |
26 | // Circle implements Shape
27 | type Circle struct {
28 | Radius float64
29 | Name string
30 | }
31 |
32 | // Rectangle implements Shape
33 | type Rectangle struct {
34 | Width float64
35 | Height float64
36 | Name string
37 | }
38 |
39 | // Triangle implements Shape
40 | type Triangle struct {
41 | A, B, C float64
42 | Name string
43 | }
44 |
45 | // Area implements Shape interface for Circle
46 | func (c Circle) Area() float64 {
47 | return math.Pi * c.Radius * c.Radius
48 | }
49 |
50 | // Perimeter implements Shape interface for Circle
51 | func (c Circle) Perimeter() float64 {
52 | return 2 * math.Pi * c.Radius
53 | }
54 |
55 | // Draw implements Drawable interface for Circle
56 | func (c Circle) Draw() string {
57 | return fmt.Sprintf("Drawing circle with radius %.2f", c.Radius)
58 | }
59 |
60 | // GetName implements Named interface for Circle
61 | func (c Circle) GetName() string {
62 | return c.Name
63 | }
64 |
65 | // Area implements Shape interface for Rectangle
66 | func (r Rectangle) Area() float64 {
67 | return r.Width * r.Height
68 | }
69 |
70 | // Perimeter implements Shape interface for Rectangle
71 | func (r Rectangle) Perimeter() float64 {
72 | return 2 * (r.Width + r.Height)
73 | }
74 |
75 | // Draw implements Drawable interface for Rectangle
76 | func (r Rectangle) Draw() string {
77 | return fmt.Sprintf("Drawing rectangle %.2fx%.2f", r.Width, r.Height)
78 | }
79 |
80 | // GetName implements Named interface for Rectangle
81 | func (r Rectangle) GetName() string {
82 | return r.Name
83 | }
84 |
85 | // Area implements Shape interface for Triangle
86 | func (t Triangle) Area() float64 {
87 | // Heron's formula
88 | s := (t.A + t.B + t.C) / 2
89 | return math.Sqrt(s * (s - t.A) * (s - t.B) * (s - t.C))
90 | }
91 |
92 | // Perimeter implements Shape interface for Triangle
93 | func (t Triangle) Perimeter() float64 {
94 | return t.A + t.B + t.C
95 | }
96 |
97 | // GetName implements Named interface for Triangle
98 | func (t Triangle) GetName() string {
99 | return t.Name
100 | }
101 |
102 | // CalculateTotalArea accepts interface and calculates total
103 | func CalculateTotalArea(shapes []Shape) float64 {
104 | total := 0.0
105 | for _, shape := range shapes {
106 | total += shape.Area()
107 | }
108 | return total
109 | }
110 |
111 | // PrintShapeInfo uses interface for polymorphism
112 | func PrintShapeInfo(s Shape) {
113 | fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
114 | }
115 |
116 | // DrawIfPossible uses type assertion
117 | func DrawIfPossible(s Shape) string {
118 | if drawable, ok := s.(Drawable); ok {
119 | return drawable.Draw()
120 | }
121 | return "Shape is not drawable"
122 | }
123 |
124 | // DescribeShape uses type switch
125 | func DescribeShape(s Shape) string {
126 | switch v := s.(type) {
127 | case Circle:
128 | return fmt.Sprintf("Circle with radius %.2f", v.Radius)
129 | case Rectangle:
130 | return fmt.Sprintf("Rectangle with dimensions %.2fx%.2f", v.Width, v.Height)
131 | case Triangle:
132 | return fmt.Sprintf("Triangle with sides %.2f, %.2f, %.2f", v.A, v.B, v.C)
133 | default:
134 | return "Unknown shape"
135 | }
136 | }
137 |
138 | // EmptyInterface demonstrates empty interface usage
139 | func EmptyInterface(data interface{}) string {
140 | switch v := data.(type) {
141 | case int:
142 | return fmt.Sprintf("Integer: %d", v)
143 | case string:
144 | return fmt.Sprintf("String: %s", v)
145 | case Shape:
146 | return fmt.Sprintf("Shape with area: %.2f", v.Area())
147 | default:
148 | return fmt.Sprintf("Unknown type: %T", v)
149 | }
150 | }
151 |
152 | // InterfaceComposition demonstrates interface embedding
153 | type ComplexShape interface {
154 | Shape
155 | Named
156 | Volume() float64
157 | }
158 |
159 | // ProcessShapes processes multiple shapes
160 | func ProcessShapes(shapes ...Shape) map[string]float64 {
161 | results := make(map[string]float64)
162 | totalArea := 0.0
163 | totalPerimeter := 0.0
164 |
165 | for _, shape := range shapes {
166 | totalArea += shape.Area()
167 | totalPerimeter += shape.Perimeter()
168 | }
169 |
170 | results["total_area"] = totalArea
171 | results["total_perimeter"] = totalPerimeter
172 | results["count"] = float64(len(shapes))
173 |
174 | return results
175 | }
176 |
177 | func demonstrateInterfaces() {
178 | circle := Circle{Radius: 5.0, Name: "MyCircle"}
179 | rectangle := Rectangle{Width: 10.0, Height: 5.0, Name: "MyRectangle"}
180 |
181 | shapes := []Shape{circle, rectangle}
182 | fmt.Printf("Total area: %.2f\n", CalculateTotalArea(shapes))
183 |
184 | fmt.Println(DescribeShape(circle))
185 | fmt.Println(DrawIfPossible(circle))
186 | }
187 |
188 |
```
--------------------------------------------------------------------------------
/website/src/components/ExamplesSection.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
2 | import { Badge } from "@/components/ui/badge";
3 | import { MessageCircle, Search, Eye, BarChart3 } from "lucide-react";
4 | import { motion } from "framer-motion";
5 |
6 | const examplesData = [
7 | {
8 | icon: MessageCircle,
9 | category: "Indexing",
10 | title: "Add Projects to Graph",
11 | examples: [
12 | "Please index the code in the `/path/to/my-project` directory.",
13 | "Add the project at `~/dev/my-app` to the code graph."
14 | ]
15 | },
16 | {
17 | icon: Search,
18 | category: "Analysis",
19 | title: "Code Relationships",
20 | examples: [
21 | "Show me all functions that call `process_data()`",
22 | "Find the class hierarchy for `BaseProcessor`"
23 | ]
24 | },
25 | {
26 | icon: Eye,
27 | category: "Monitoring",
28 | title: "Live Updates",
29 | examples: [
30 | "Watch the `/project` directory for changes.",
31 | "Keep the graph updated for my active development."
32 | ]
33 | },
34 | {
35 | icon: BarChart3,
36 | category: "Insights",
37 | title: "Code Quality",
38 | examples: [
39 | "Find dead code in my project",
40 | "Show the most complex functions by cyclomatic complexity"
41 | ]
42 | }
43 | ];
44 |
45 | const ExamplesSection = () => {
46 | return (
47 | <section className="py-24 px-4" data-aos="fade-in">
48 | <div className="container mx-auto max-w-6xl">
49 | <div className="text-center mb-16" data-aos="fade-down">
50 | <h2 className="text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-primary via-primary to-accent bg-clip-text text-transparent py-2">
51 | Natural Language Interface
52 | </h2>
53 | <p className="text-xl text-muted-foreground max-w-3xl mx-auto">
54 | Interact with your code graph using plain English. No complex queries or syntax to learn.
55 | </p>
56 | </div>
57 |
58 | <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
59 | {examplesData.map((example, index) => (
60 | <div key={index} data-aos="fade-up" data-aos-delay={index * 100}>
61 | <Card className="h-full border-border/50 group animate-float-up bg-white/95 dark:bg-card/50 shadow-sm hover:shadow-lg transition-shadow duration-300">
62 | <CardHeader>
63 | <div className="flex items-center gap-4 mb-4">
64 | <div className="p-3 rounded-xl bg-primary/5 border border-primary/15 group-hover:bg-primary/10 transition-colors dark:bg-primary/20 dark:border-primary/30">
65 | <example.icon className="h-6 w-6 text-primary" />
66 | </div>
67 | <div>
68 | <Badge variant="secondary" className="mb-2">{example.category}</Badge>
69 | <CardTitle className="text-xl font-semibold">{example.title}</CardTitle>
70 | </div>
71 | </div>
72 | </CardHeader>
73 | <CardContent>
74 | <div className="space-y-4">
75 | {example.examples.map((text, idx) => (
76 | <div key={idx} className="p-3 rounded-md border-l-4 border-accent/30 bg-muted/30 hover:border-accent/60 transition-colors">
77 | <p className="text-sm text-muted-foreground italic">"{text}"</p>
78 | </div>
79 | ))}
80 | </div>
81 | </CardContent>
82 | </Card>
83 | </div>
84 | ))}
85 | </div>
86 |
87 | <div className="text-center mt-16" data-aos="fade-up" data-aos-delay="200">
88 | <Card className="max-w-2xl mx-auto bg-white/95 dark:bg-card/50 shadow-sm p-2">
89 | <CardContent className="pt-8">
90 | <h3 className="text-2xl font-bold mb-4">Ready to enhance your AI assistant?</h3>
91 | <p className="text-muted-foreground mb-6">
92 | Start building intelligent code understanding today with CodeGraphContext.
93 | </p>
94 | <div className="p-3 rounded-md bg-muted/40 max-w-md mx-auto border shadow-inner">
95 | <code className="text-accent font-mono">$ pip install codegraphcontext</code>
96 | </div>
97 | </CardContent>
98 | </Card>
99 | </div>
100 | </div>
101 | </section>
102 | );
103 | };
104 |
105 | export default ExamplesSection;
106 |
```
--------------------------------------------------------------------------------
/website/src/components/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import * as React from "react";
2 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
3 |
4 | import { cn } from "@/lib/utils";
5 | import { buttonVariants } from "@/components/ui/button";
6 |
7 | const AlertDialog = AlertDialogPrimitive.Root;
8 |
9 | const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
10 |
11 | const AlertDialogPortal = AlertDialogPrimitive.Portal;
12 |
13 | const AlertDialogOverlay = React.forwardRef<
14 | React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
15 | React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
16 | >(({ className, ...props }, ref) => (
17 | <AlertDialogPrimitive.Overlay
18 | className={cn(
19 | "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
20 | className,
21 | )}
22 | {...props}
23 | ref={ref}
24 | />
25 | ));
26 | AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
27 |
28 | const AlertDialogContent = React.forwardRef<
29 | React.ElementRef<typeof AlertDialogPrimitive.Content>,
30 | React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
31 | >(({ className, ...props }, ref) => (
32 | <AlertDialogPortal>
33 | <AlertDialogOverlay />
34 | <AlertDialogPrimitive.Content
35 | ref={ref}
36 | className={cn(
37 | "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
38 | className,
39 | )}
40 | {...props}
41 | />
42 | </AlertDialogPortal>
43 | ));
44 | AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
45 |
46 | const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
47 | <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
48 | );
49 | AlertDialogHeader.displayName = "AlertDialogHeader";
50 |
51 | const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
52 | <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} />
53 | );
54 | AlertDialogFooter.displayName = "AlertDialogFooter";
55 |
56 | const AlertDialogTitle = React.forwardRef<
57 | React.ElementRef<typeof AlertDialogPrimitive.Title>,
58 | React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
59 | >(({ className, ...props }, ref) => (
60 | <AlertDialogPrimitive.Title ref={ref} className={cn("text-lg font-semibold", className)} {...props} />
61 | ));
62 | AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
63 |
64 | const AlertDialogDescription = React.forwardRef<
65 | React.ElementRef<typeof AlertDialogPrimitive.Description>,
66 | React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
67 | >(({ className, ...props }, ref) => (
68 | <AlertDialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
69 | ));
70 | AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
71 |
72 | const AlertDialogAction = React.forwardRef<
73 | React.ElementRef<typeof AlertDialogPrimitive.Action>,
74 | React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
75 | >(({ className, ...props }, ref) => (
76 | <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} />
77 | ));
78 | AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
79 |
80 | const AlertDialogCancel = React.forwardRef<
81 | React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
82 | React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
83 | >(({ className, ...props }, ref) => (
84 | <AlertDialogPrimitive.Cancel
85 | ref={ref}
86 | className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)}
87 | {...props}
88 | />
89 | ));
90 | AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
91 |
92 | export {
93 | AlertDialog,
94 | AlertDialogPortal,
95 | AlertDialogOverlay,
96 | AlertDialogTrigger,
97 | AlertDialogContent,
98 | AlertDialogHeader,
99 | AlertDialogFooter,
100 | AlertDialogTitle,
101 | AlertDialogDescription,
102 | AlertDialogAction,
103 | AlertDialogCancel,
104 | };
105 |
```
--------------------------------------------------------------------------------
/tests/sample_project_go/util/helpers.go:
--------------------------------------------------------------------------------
```go
1 | // Package util provides utility functions for the sample project
2 | package util
3 |
4 | import (
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | // StringUtils provides string utility functions
10 | type StringUtils struct{}
11 |
12 | // Reverse reverses a string
13 | func (su StringUtils) Reverse(s string) string {
14 | runes := []rune(s)
15 | for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
16 | runes[i], runes[j] = runes[j], runes[i]
17 | }
18 | return string(runes)
19 | }
20 |
21 | // IsPalindrome checks if a string is a palindrome
22 | func (su StringUtils) IsPalindrome(s string) bool {
23 | s = strings.ToLower(strings.ReplaceAll(s, " ", ""))
24 | return s == su.Reverse(s)
25 | }
26 |
27 | // MathUtils provides math utility functions
28 | type MathUtils struct{}
29 |
30 | // Factorial calculates factorial
31 | func (mu MathUtils) Factorial(n int) int {
32 | if n <= 1 {
33 | return 1
34 | }
35 | return n * mu.Factorial(n-1)
36 | }
37 |
38 | // Fibonacci calculates fibonacci number
39 | func (mu MathUtils) Fibonacci(n int) int {
40 | if n <= 1 {
41 | return n
42 | }
43 | return mu.Fibonacci(n-1) + mu.Fibonacci(n-2)
44 | }
45 |
46 | // GCD calculates greatest common divisor
47 | func (mu MathUtils) GCD(a, b int) int {
48 | for b != 0 {
49 | a, b = b, a%b
50 | }
51 | return a
52 | }
53 |
54 | // LCM calculates least common multiple
55 | func (mu MathUtils) LCM(a, b int) int {
56 | return (a * b) / mu.GCD(a, b)
57 | }
58 |
59 | // SliceUtils provides slice utility functions
60 | type SliceUtils struct{}
61 |
62 | // Sum calculates sum of integers
63 | func (su SliceUtils) Sum(nums []int) int {
64 | total := 0
65 | for _, num := range nums {
66 | total += num
67 | }
68 | return total
69 | }
70 |
71 | // Average calculates average
72 | func (su SliceUtils) Average(nums []int) float64 {
73 | if len(nums) == 0 {
74 | return 0
75 | }
76 | return float64(su.Sum(nums)) / float64(len(nums))
77 | }
78 |
79 | // Max finds maximum value
80 | func (su SliceUtils) Max(nums []int) int {
81 | if len(nums) == 0 {
82 | return 0
83 | }
84 | max := nums[0]
85 | for _, num := range nums {
86 | if num > max {
87 | max = num
88 | }
89 | }
90 | return max
91 | }
92 |
93 | // Min finds minimum value
94 | func (su SliceUtils) Min(nums []int) int {
95 | if len(nums) == 0 {
96 | return 0
97 | }
98 | min := nums[0]
99 | for _, num := range nums {
100 | if num < min {
101 | min = num
102 | }
103 | }
104 | return min
105 | }
106 |
107 | // Unique removes duplicates from slice
108 | func (su SliceUtils) Unique(nums []int) []int {
109 | seen := make(map[int]bool)
110 | result := []int{}
111 |
112 | for _, num := range nums {
113 | if !seen[num] {
114 | seen[num] = true
115 | result = append(result, num)
116 | }
117 | }
118 |
119 | return result
120 | }
121 |
122 | // Validator provides validation functions
123 | type Validator struct{}
124 |
125 | // IsEmail checks if string is valid email format (simplified)
126 | func (v Validator) IsEmail(email string) bool {
127 | return strings.Contains(email, "@") && strings.Contains(email, ".")
128 | }
129 |
130 | // IsURL checks if string is valid URL format (simplified)
131 | func (v Validator) IsURL(url string) bool {
132 | return strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://")
133 | }
134 |
135 | // IsEmpty checks if string is empty or whitespace
136 | func (v Validator) IsEmpty(s string) bool {
137 | return strings.TrimSpace(s) == ""
138 | }
139 |
140 | // Logger provides logging functionality
141 | type Logger struct {
142 | Prefix string
143 | }
144 |
145 | // NewLogger creates a new logger
146 | func NewLogger(prefix string) *Logger {
147 | return &Logger{Prefix: prefix}
148 | }
149 |
150 | // Info logs info message
151 | func (l Logger) Info(message string) {
152 | fmt.Printf("[%s] INFO: %s\n", l.Prefix, message)
153 | }
154 |
155 | // Error logs error message
156 | func (l Logger) Error(message string) {
157 | fmt.Printf("[%s] ERROR: %s\n", l.Prefix, message)
158 | }
159 |
160 | // Debug logs debug message
161 | func (l Logger) Debug(message string) {
162 | fmt.Printf("[%s] DEBUG: %s\n", l.Prefix, message)
163 | }
164 |
165 | // Helper functions (package-level)
166 |
167 | // Capitalize capitalizes first letter of string
168 | func Capitalize(s string) string {
169 | if len(s) == 0 {
170 | return s
171 | }
172 | return strings.ToUpper(s[:1]) + s[1:]
173 | }
174 |
175 | // Truncate truncates string to specified length
176 | func Truncate(s string, length int) string {
177 | if len(s) <= length {
178 | return s
179 | }
180 | return s[:length] + "..."
181 | }
182 |
183 | // Contains checks if slice contains value
184 | func Contains(slice []string, value string) bool {
185 | for _, item := range slice {
186 | if item == value {
187 | return true
188 | }
189 | }
190 | return false
191 | }
192 |
193 | // Map applies function to each element
194 | func Map(slice []int, fn func(int) int) []int {
195 | result := make([]int, len(slice))
196 | for i, v := range slice {
197 | result[i] = fn(v)
198 | }
199 | return result
200 | }
201 |
202 | // Filter filters slice based on predicate
203 | func Filter(slice []int, predicate func(int) bool) []int {
204 | result := []int{}
205 | for _, v := range slice {
206 | if predicate(v) {
207 | result = append(result, v)
208 | }
209 | }
210 | return result
211 | }
212 |
213 |
```
--------------------------------------------------------------------------------
/docs/docs/server.md:
--------------------------------------------------------------------------------
```markdown
1 | # MCPServer
2 |
3 | The `MCPServer` class is the core of the CodeGraphContext application. It orchestrates all the major components, including database management, background job tracking, file system watching, and tool handling.
4 |
5 | ## Initialization
6 |
7 | The server is initialized with an asyncio event loop. Upon initialization, it sets up the following components:
8 |
9 | - `DatabaseManager`: Manages the connection to the Neo4j database.
10 | - `JobManager`: Tracks the status of background jobs, such as code indexing.
11 | - `CodeWatcher`: Monitors the file system for changes to keep the code graph up-to-date.
12 | - `GraphBuilder`: Builds the code graph from the source code.
13 | - `CodeFinder`: Provides tools for searching and analyzing the code graph.
14 |
15 | ## Tool Manifest
16 |
17 | The `MCPServer` exposes a set of tools to the AI assistant. These tools are defined in the `_init_tools` method. Here is a list of available tools:
18 |
19 | ### `add_code_to_graph`
20 | Performs a one-time scan of a local folder to add its code to the graph. Ideal for indexing libraries, dependencies, or projects not being actively modified. Returns a job ID for background processing.
21 |
22 | ### `check_job_status`
23 | Check the status and progress of a background job.
24 |
25 | ### `list_jobs`
26 | List all background jobs and their current status.
27 |
28 | ### `find_code`
29 | Find relevant code snippets related to a keyword (e.g., function name, class name, or content).
30 |
31 | ### `analyze_code_relationships`
32 | Analyze code relationships like 'who calls this function' or 'class hierarchy'. Supported query types include: find_callers, find_callees, find_all_callers, find_all_callees, find_importers, who_modifies, class_hierarchy, overrides, dead_code, call_chain, module_deps, variable_scope, find_complexity, find_functions_by_argument, find_functions_by_decorator.
33 |
34 | ### `watch_directory`
35 | Performs an initial scan of a directory and then continuously monitors it for changes, automatically keeping the graph up-to-date. Ideal for projects under active development. Returns a job ID for the initial scan.
36 |
37 | ### `execute_cypher_query`
38 |
39 | This is an advanced tool for directly querying the underlying Neo4j graph using a read-only Cypher query. It should be used as a fallback when other tools cannot answer very specific or complex questions about the code graph.
40 |
41 | **Schema Overview:**
42 |
43 | The code graph has the following structure:
44 |
45 | * **Nodes:**
46 | * `Repository`: Represents a project repository.
47 | * `File`: Represents a single source code file.
48 | * `Module`: Represents a package or a module.
49 | * `Class`: Represents a class definition.
50 | * `Function`: Represents a function or method definition.
51 | * **Properties:**
52 | * Nodes have properties like `name`, `path`, `cyclomatic_complexity` (for functions), and `code`.
53 | * **Relationships:**
54 | * `CONTAINS`: e.g., `(:File)-[:CONTAINS]->(:Function)`
55 | * `CALLS`: e.g., `(:Function)-[:CALLS]->(:Function)`
56 | * `IMPORTS`: e.g., `(:File)-[:IMPORTS]->(:Module)`
57 | * `INHERITS`: e.g., `(:Class)-[:INHERITS]->(:Class)`
58 |
59 | ### `add_package_to_graph`
60 | Add a Python package to Neo4j graph by discovering its location. Returns immediately with job ID.
61 |
62 | ### `find_dead_code`
63 | Find potentially unused functions (dead code) across the entire indexed codebase, optionally excluding functions with specific decorators.
64 |
65 | ### `calculate_cyclomatic_complexity`
66 | Calculate the cyclomatic complexity of a specific function to measure its complexity.
67 |
68 | ### `find_most_complex_functions`
69 | Find the most complex functions in the codebase based on cyclomatic complexity.
70 |
71 | ### `list_indexed_repositories`
72 | List all indexed repositories.
73 |
74 | ### `delete_repository`
75 | Delete an indexed repository from the graph.
76 |
77 | ### `visualize_graph_query`
78 | Generates a URL to visualize the results of a Cypher query in the Neo4j Browser. The user can open this URL in their web browser to see the graph visualization.
79 |
80 | ### `list_watched_paths`
81 | Lists all directories currently being watched for live file changes.
82 |
83 | ### `unwatch_directory`
84 | Stops watching a directory for live file changes.
85 |
86 | ## Other Methods
87 |
88 | - `get_database_status()`: Returns the current connection status of the Neo4j database.
89 | - `get_local_package_path(package_name)`: Finds the local installation path of a Python package.
90 | - `run()`: Runs the main server loop, listening for JSON-RPC requests from stdin.
91 | - `shutdown()`: Gracefully shuts down the server and its components.
92 |
```
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.sv.min.js:
--------------------------------------------------------------------------------
```javascript
1 | /*!
2 | * Lunr languages, `Swedish` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o<a&&(o=a)}}function t(){var e,r=w.limit_backward;if(w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});
```
--------------------------------------------------------------------------------
/scripts/post_install_fix.sh:
--------------------------------------------------------------------------------
```bash
1 | #!/bin/bash
2 | set -e
3 |
4 | echo "Running Post Install fix for CodeGraphContext..."
5 |
6 | detect_shell_config() {
7 | # Windows PowerShell detection
8 | if [[ "$OS" == "Windows_NT" ]] && [[ -n "$PROFILE" ]]; then
9 | echo "$PROFILE"
10 | return
11 | fi
12 |
13 | # Unix/Linux/Mac shell detection
14 | if [ "$SHELL" = "/bin/bash" ] || [ "$SHELL" = "/usr/bin/bash" ]; then
15 | echo "$HOME/.bashrc"
16 | elif [ "$SHELL" = "/bin/zsh" ] || [ "$SHELL" = "/usr/bin/zsh" ]; then
17 | echo "$HOME/.zshrc"
18 | elif [ -n "$BASH_VERSION" ]; then
19 | echo "$HOME/.bashrc"
20 | elif [ -n "$ZSH_VERSION" ]; then
21 | echo "$HOME/.zshrc"
22 | else
23 | echo "$HOME/.profile"
24 | fi
25 | }
26 |
27 | # Add to PATH for Windows PowerShell
28 | fix_windows_path() {
29 | local profile_file="$1"
30 | local path_line='$env:PATH = "$env:USERPROFILE\.local\bin;$env:PATH"'
31 |
32 | echo "Using PowerShell profile: $profile_file"
33 |
34 | # Create profile directory if needed
35 | local profile_dir=$(dirname "$profile_file")
36 | mkdir -p "$profile_dir" 2>/dev/null || true
37 |
38 | # Check if already configured
39 | if [[ -f "$profile_file" ]] && grep -q ".local" "$profile_file"; then
40 | echo "PATH is already configured in PowerShell profile"
41 | else
42 | echo "Adding to PowerShell PATH..."
43 | echo "" >> "$profile_file"
44 | echo "# Added by CodeGraphContext" >> "$profile_file"
45 | echo "$path_line" >> "$profile_file"
46 | echo "Added PATH to PowerShell profile"
47 | fi
48 |
49 | # Add to current session (Windows style)
50 | export PATH="$USERPROFILE/.local/bin:$PATH"
51 |
52 | echo "⚠️ Please restart PowerShell or run: . \$PROFILE"
53 | }
54 |
55 | # Add to PATH for Linux/Mac
56 | fix_unix_path() {
57 | local config_file="$1"
58 | local path_line='export PATH="$HOME/.local/bin:$PATH"'
59 |
60 | echo "Using shell config: $config_file"
61 |
62 | # check if PATH is already configured
63 | if [ -f "$config_file" ] && grep -q ".local/bin" "$config_file"; then
64 | echo "PATH is already configured in $config_file"
65 | else
66 | echo "Adding ~/.local/bin to PATH..."
67 | echo "" >> "$config_file"
68 | echo "# Added by CodeGraphContext" >> "$config_file"
69 | echo "$path_line" >> "$config_file"
70 | echo "Added PATH to $config_file"
71 | fi
72 |
73 | # Source the config for current session
74 | echo "Sourcing/Reloading shell config for current session..."
75 | export PATH="$HOME/.local/bin:$PATH"
76 |
77 | # source it
78 | if [ -f "$config_file" ]; then
79 | source "$config_file" 2>/dev/null || true
80 | fi
81 | }
82 |
83 | # Main PATH fixing function
84 | fix_path() {
85 | local config_file=$(detect_shell_config)
86 |
87 | # Check if we're on Windows
88 | if [[ "$OS" == "Windows_NT" ]] && [[ -n "$PROFILE" ]]; then
89 | fix_windows_path "$config_file"
90 | else
91 | fix_unix_path "$config_file"
92 | fi
93 | }
94 |
95 | check_cgc() {
96 | if command -v cgc >/dev/null 2>&1; then
97 | return 0
98 | else
99 | return 1
100 | fi
101 | }
102 |
103 | # Get potential cgc locations based on platform
104 | get_cgc_locations() {
105 | if [[ "$OS" == "Windows_NT" ]]; then
106 | # Windows locations
107 | echo "$USERPROFILE/.local/bin/cgc.exe"
108 | echo "$USERPROFILE/.local/bin/cgc"
109 | echo "$HOME/.local/bin/cgc.exe"
110 | echo "$HOME/.local/bin/cgc"
111 | else
112 | # Linux/Mac locations
113 | echo "$HOME/.local/bin/cgc"
114 | fi
115 | }
116 |
117 |
118 | # Main execution
119 | if check_cgc; then
120 | echo "✅ cgc (CodeGraphContext) is already available!"
121 | else
122 | echo "⚠️ cgc command not found, fixing PATH..."
123 |
124 | # Check if cgc exists in expected locations
125 | cgc_found=false
126 | for cgc_path in $(get_cgc_locations); do
127 | if [[ -f "$cgc_path" ]]; then
128 | cgc_found=true
129 | echo "📍 Found cgc at: $cgc_path"
130 | break
131 | fi
132 | done
133 |
134 | if [[ "$cgc_found" == true ]]; then
135 | fix_path
136 |
137 | # Check again
138 | if check_cgc; then
139 | echo "✅ cgc command (CodeGraphContext) is now available to use!"
140 | echo "You can now run: cgc setup"
141 | else
142 | if [[ "$OS" == "Windows_NT" ]]; then
143 | echo "⚠️ Please restart PowerShell or run: . \$PROFILE"
144 | else
145 | echo "❌ There seems to still be an issue... Please reload your terminal manually."
146 | fi
147 | fi
148 | else
149 | if [[ "$OS" == "Windows_NT" ]]; then
150 | echo "❌ cgc not found in expected Windows locations. Please reinstall:"
151 | echo " pip install codegraphcontext"
152 | else
153 | echo "❌ cgc not found in ~/.local/bin. Please reinstall:"
154 | echo " pip install codegraphcontext"
155 | fi
156 | fi
157 | fi
```
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.da.min.js:
--------------------------------------------------------------------------------
```javascript
1 | /*!
2 | * Lunr languages, `Danish` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d<a&&(d=a)}}function n(){var e,r;if(f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});
```
--------------------------------------------------------------------------------
/docs/docs/tools.md:
--------------------------------------------------------------------------------
```markdown
1 | # Tools
2 |
3 | The `tools` directory contains the logic for code analysis, including building the graph, finding code, and extracting imports.
4 |
5 | ## `GraphBuilder`
6 |
7 | The `GraphBuilder` class in `graph_builder.py` is responsible for parsing the source code and building the graph representation that is stored in the Neo4j database.
8 |
9 | ### `TreeSitterParser`
10 |
11 | `GraphBuilder` uses the `TreeSitterParser` class, which is a generic parser wrapper for a specific language using the tree-sitter library. This allows CodeGraphContext to support multiple programming languages in a modular way.
12 |
13 | ### Graph Building Process
14 |
15 | The graph building process consists of several steps:
16 |
17 | 1. **Pre-scan for Imports:** A quick scan of all files to build a global map of where every symbol is defined.
18 | 2. **Parse Files:** Each file is parsed in detail to extract its structure, including functions, classes, variables, and imports.
19 | 3. **Add Nodes to Graph:** The extracted code elements are added to the graph as nodes.
20 | 4. **Create Relationships:** Relationships between the nodes are created, such as `CALLS` for function calls and `INHERITS` for class inheritance.
21 |
22 | ## `CodeFinder`
23 |
24 | The `CodeFinder` class in `code_finder.py` provides functionality to search for specific code elements and analyze their relationships within the indexed codebase.
25 |
26 | ### Key Methods
27 |
28 | - `find_by_function_name()`: Finds functions by name.
29 | - `find_by_class_name()`: Finds classes by name.
30 | - `find_by_variable_name()`: Finds variables by name.
31 | - `find_by_content()`: Finds code by content matching in source or docstrings.
32 | - `find_related_code()`: Finds code related to a query using multiple search strategies.
33 | - `analyze_code_relationships()`: Analyzes different types of code relationships, such as callers, callees, importers, and class hierarchies.
34 |
35 | ## `ImportExtractor`
36 |
37 | The `ImportExtractor` class in `import_extractor.py` is a utility for extracting package and module imports from source code files of various programming languages. It uses the most appropriate parsing technique for each language, such as AST for Python and regular expressions for JavaScript.
38 |
39 | # Tools Exploration
40 | There are a total of 14 tools available to the users, and here we have attached illustrative demos for each one of them.
41 |
42 | ## find_code Tool
43 |
44 | The `find_code` tool allows users to search for code snippets, functions, classes, and variables within the codebase using natural language queries. This tool helps developers understand and navigate large codebases efficiently.
45 |
46 | Below is an embedded link to a demo video showcasing the usage of the `find_code` tool in action.
47 | [](https://drive.google.com/file/d/1ojCDIIAwcir9e3jgHHIVC5weZ9nuIQcs/view?usp=drive_link)
48 |
49 | ---
50 |
51 | ## watch_directory Tool
52 |
53 | The `watch_directory` tool allows users to monitor a specified directory for file changes, additions, or deletions in real-time. It helps developers automate workflows such as triggering scripts, updating indexes, or syncing files whenever changes occur in the directory.
54 |
55 | Below is an embedded link to a demo video showcasing the usage of the `watch_directory` tool in a development environment.
56 | [](https://drive.google.com/file/d/1OEjcS2iwwymss99zLidbeBjcblferKBX/view?usp=drive_link)
57 |
58 | ---
59 |
60 | ## analyze_code_relationships Tool
61 |
62 | The `analyze_code_relationships` tool in CodeGraphContext is designed to let users query and explore the various relationships between code elements in a codebase, represented as a graph in Neo4j.
63 |
64 | ### Relationship Types That Can Be Analyzed
65 |
66 | - **CALLS:** Finds which functions call or are called by a function.
67 | - **CALLED_BY:** Finds all functions that directly or indirectly call a target function (inverse of CALLS).
68 | - **INHERITS_FROM:** Finds class inheritance relationships; which classes inherit from which.
69 | - **CONTAINS:** Shows containment (which classes/functions are inside which modules or files).
70 | - **IMPLEMENTS:** Shows which classes implement an interface.
71 | - **IMPORTS:** Identifies which files or modules import a specific module.
72 | - **DEFINED_IN:** Locates where an entity (function/class) is defined.
73 | - **HAS_ARGUMENT:** Shows relationships from functions to their arguments.
74 | - **DECLARES:** Finds variables declared in functions or classes.
75 |
76 | Below is an embedded link to a demo video showcasing the usage of the `analyse_code_relationships` tool.
77 | [](https://drive.google.com/file/d/154M_lTPbg9_Gj9bd2ErnAVbJArSbcb2M/view?usp=drive_link)
78 |
79 | ---
80 |
```
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.no.min.js:
--------------------------------------------------------------------------------
```javascript
1 | /*!
2 | * Lunr languages, `Norwegian` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a<s&&(a=s)}}function i(){var e,r,n;if(w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});
```
--------------------------------------------------------------------------------
/tests/sample_project_go/goroutines_channels.go:
--------------------------------------------------------------------------------
```go
1 | // goroutines_channels.go - Demonstrates Go concurrency patterns
2 | package main
3 |
4 | import (
5 | "fmt"
6 | "sync"
7 | "time"
8 | )
9 |
10 | // SimpleGoroutine demonstrates basic goroutine
11 | func SimpleGoroutine(id int) {
12 | fmt.Printf("Goroutine %d starting\n", id)
13 | time.Sleep(time.Millisecond * 100)
14 | fmt.Printf("Goroutine %d done\n", id)
15 | }
16 |
17 | // ChannelSender sends data to a channel
18 | func ChannelSender(ch chan<- int, values []int) {
19 | for _, v := range values {
20 | ch <- v
21 | }
22 | close(ch)
23 | }
24 |
25 | // ChannelReceiver receives data from a channel
26 | func ChannelReceiver(ch <-chan int, done chan<- bool) {
27 | sum := 0
28 | for v := range ch {
29 | sum += v
30 | }
31 | fmt.Printf("Sum: %d\n", sum)
32 | done <- true
33 | }
34 |
35 | // BufferedChannelExample demonstrates buffered channels
36 | func BufferedChannelExample() {
37 | ch := make(chan string, 3)
38 |
39 | ch <- "first"
40 | ch <- "second"
41 | ch <- "third"
42 |
43 | fmt.Println(<-ch)
44 | fmt.Println(<-ch)
45 | fmt.Println(<-ch)
46 | }
47 |
48 | // SelectExample demonstrates select statement
49 | func SelectExample(ch1, ch2 chan string) string {
50 | select {
51 | case msg1 := <-ch1:
52 | return fmt.Sprintf("Received from ch1: %s", msg1)
53 | case msg2 := <-ch2:
54 | return fmt.Sprintf("Received from ch2: %s", msg2)
55 | case <-time.After(time.Second):
56 | return "Timeout"
57 | }
58 | }
59 |
60 | // Worker demonstrates worker pool pattern
61 | func Worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
62 | defer wg.Done()
63 | for job := range jobs {
64 | fmt.Printf("Worker %d processing job %d\n", id, job)
65 | time.Sleep(time.Millisecond * 50)
66 | results <- job * 2
67 | }
68 | }
69 |
70 | // WorkerPool creates a pool of workers
71 | func WorkerPool(numWorkers int, numJobs int) []int {
72 | jobs := make(chan int, numJobs)
73 | results := make(chan int, numJobs)
74 | var wg sync.WaitGroup
75 |
76 | // Start workers
77 | for w := 1; w <= numWorkers; w++ {
78 | wg.Add(1)
79 | go Worker(w, jobs, results, &wg)
80 | }
81 |
82 | // Send jobs
83 | for j := 1; j <= numJobs; j++ {
84 | jobs <- j
85 | }
86 | close(jobs)
87 |
88 | // Wait and collect results
89 | go func() {
90 | wg.Wait()
91 | close(results)
92 | }()
93 |
94 | var output []int
95 | for result := range results {
96 | output = append(output, result)
97 | }
98 |
99 | return output
100 | }
101 |
102 | // Counter demonstrates mutex for safe concurrent access
103 | type Counter struct {
104 | mu sync.Mutex
105 | value int
106 | }
107 |
108 | // Increment safely increments counter
109 | func (c *Counter) Increment() {
110 | c.mu.Lock()
111 | defer c.mu.Unlock()
112 | c.value++
113 | }
114 |
115 | // GetValue safely gets counter value
116 | func (c *Counter) GetValue() int {
117 | c.mu.Lock()
118 | defer c.mu.Unlock()
119 | return c.value
120 | }
121 |
122 | // RWMutexExample demonstrates read-write mutex
123 | type ConcurrentMap struct {
124 | mu sync.RWMutex
125 | data map[string]int
126 | }
127 |
128 | // Set adds or updates a value
129 | func (cm *ConcurrentMap) Set(key string, value int) {
130 | cm.mu.Lock()
131 | defer cm.mu.Unlock()
132 | cm.data[key] = value
133 | }
134 |
135 | // Get retrieves a value
136 | func (cm *ConcurrentMap) Get(key string) (int, bool) {
137 | cm.mu.RLock()
138 | defer cm.mu.RUnlock()
139 | val, ok := cm.data[key]
140 | return val, ok
141 | }
142 |
143 | // OnceExample demonstrates sync.Once
144 | var once sync.Once
145 | var instance *Singleton
146 |
147 | type Singleton struct {
148 | data string
149 | }
150 |
151 | // GetSingleton returns singleton instance
152 | func GetSingleton() *Singleton {
153 | once.Do(func() {
154 | fmt.Println("Creating singleton instance")
155 | instance = &Singleton{data: "singleton data"}
156 | })
157 | return instance
158 | }
159 |
160 | // PipelineStage1 first stage of pipeline
161 | func PipelineStage1(input <-chan int, output chan<- int) {
162 | for num := range input {
163 | output <- num * 2
164 | }
165 | close(output)
166 | }
167 |
168 | // PipelineStage2 second stage of pipeline
169 | func PipelineStage2(input <-chan int, output chan<- int) {
170 | for num := range input {
171 | output <- num + 10
172 | }
173 | close(output)
174 | }
175 |
176 | // Pipeline demonstrates pipeline pattern
177 | func Pipeline(numbers []int) []int {
178 | stage1 := make(chan int)
179 | stage2 := make(chan int)
180 |
181 | // Input
182 | go func() {
183 | for _, num := range numbers {
184 | stage1 <- num
185 | }
186 | close(stage1)
187 | }()
188 |
189 | // Stage 1
190 | go PipelineStage1(stage1, stage2)
191 |
192 | // Collect results
193 | var results []int
194 | for result := range stage2 {
195 | results = append(results, result)
196 | }
197 |
198 | return results
199 | }
200 |
201 | // FanOut sends data to multiple channels
202 | func FanOut(input <-chan int, outputs []chan<- int) {
203 | for val := range input {
204 | for _, out := range outputs {
205 | out <- val
206 | }
207 | }
208 | for _, out := range outputs {
209 | close(out)
210 | }
211 | }
212 |
213 | // FanIn merges multiple channels into one
214 | func FanIn(inputs ...<-chan int) <-chan int {
215 | output := make(chan int)
216 | var wg sync.WaitGroup
217 |
218 | for _, input := range inputs {
219 | wg.Add(1)
220 | go func(ch <-chan int) {
221 | defer wg.Done()
222 | for val := range ch {
223 | output <- val
224 | }
225 | }(input)
226 | }
227 |
228 | go func() {
229 | wg.Wait()
230 | close(output)
231 | }()
232 |
233 | return output
234 | }
235 |
236 | func demonstrateConcurrency() {
237 | // Simple goroutines
238 | for i := 1; i <= 3; i++ {
239 | go SimpleGoroutine(i)
240 | }
241 |
242 | // Worker pool
243 | results := WorkerPool(3, 5)
244 | fmt.Println("Results:", results)
245 |
246 | time.Sleep(time.Second)
247 | }
248 |
249 |
```
--------------------------------------------------------------------------------
/tests/sample_project_javascript/classes.js:
--------------------------------------------------------------------------------
```javascript
1 | /**
2 | * Sample JavaScript file demonstrating class definitions and methods
3 | * This file tests class declarations, methods, static methods, and inheritance
4 | */
5 |
6 | // Basic class declaration
7 | class Person {
8 | constructor(name, age) {
9 | this.name = name;
10 | this.age = age;
11 | }
12 |
13 | // Instance method
14 | greet() {
15 | return `Hello, I'm ${this.name} and I'm ${this.age} years old`;
16 | }
17 |
18 | /**
19 | * Method with JSDoc documentation
20 | * @param {number} years - Number of years to add
21 | * @returns {void}
22 | */
23 | celebrateBirthday(years = 1) {
24 | this.age += years;
25 | console.log(`Happy birthday! Now ${this.age} years old`);
26 | }
27 |
28 | // Getter method
29 | get info() {
30 | return `${this.name} (${this.age})`;
31 | }
32 |
33 | // Setter method
34 | set info(value) {
35 | const [name, age] = value.split(' ');
36 | this.name = name;
37 | this.age = parseInt(age);
38 | }
39 |
40 | // Static method
41 | static createAdult(name) {
42 | return new Person(name, 18);
43 | }
44 |
45 | // Static method with parameters
46 | static compare(person1, person2) {
47 | return person1.age - person2.age;
48 | }
49 | }
50 |
51 | // Class inheritance
52 | class Employee extends Person {
53 | constructor(name, age, jobTitle, salary) {
54 | super(name, age);
55 | this.jobTitle = jobTitle;
56 | this.salary = salary;
57 | }
58 |
59 | // Override parent method
60 | greet() {
61 | return `${super.greet()}. I work as a ${this.jobTitle}`;
62 | }
63 |
64 | // New method specific to Employee
65 | work() {
66 | console.log(`${this.name} is working as a ${this.jobTitle}`);
67 | }
68 |
69 | // Method with complex parameters
70 | updateSalary(newSalary, reason = 'performance review') {
71 | const oldSalary = this.salary;
72 | this.salary = newSalary;
73 | console.log(`Salary updated from ${oldSalary} to ${newSalary} due to ${reason}`);
74 | }
75 |
76 | // Static method in child class
77 | static createIntern(name, age) {
78 | return new Employee(name, age, 'Intern', 0);
79 | }
80 | }
81 |
82 | // Class with private fields (modern JavaScript)
83 | class BankAccount {
84 | #balance = 0;
85 | #accountNumber;
86 |
87 | constructor(accountNumber, initialBalance = 0) {
88 | this.#accountNumber = accountNumber;
89 | this.#balance = initialBalance;
90 | }
91 |
92 | // Public method accessing private field
93 | deposit(amount) {
94 | if (amount > 0) {
95 | this.#balance += amount;
96 | return this.#balance;
97 | }
98 | throw new Error('Amount must be positive');
99 | }
100 |
101 | // Public method accessing private field
102 | withdraw(amount) {
103 | if (amount > 0 && amount <= this.#balance) {
104 | this.#balance -= amount;
105 | return this.#balance;
106 | }
107 | throw new Error('Invalid withdrawal amount');
108 | }
109 |
110 | // Getter for private field
111 | get balance() {
112 | return this.#balance;
113 | }
114 |
115 | // Private method
116 | #validateTransaction(amount) {
117 | return amount > 0 && amount <= this.#balance;
118 | }
119 | }
120 |
121 | // Class with static properties and methods
122 | class MathUtils {
123 | static PI = 3.14159;
124 | static E = 2.71828;
125 |
126 | static add(a, b) {
127 | return a + b;
128 | }
129 |
130 | static multiply(a, b) {
131 | return a * b;
132 | }
133 |
134 | static circleArea(radius) {
135 | return MathUtils.PI * radius * radius;
136 | }
137 | }
138 |
139 | // Class expression assigned to variable
140 | const AnonymousClass = class {
141 | constructor(value) {
142 | this.value = value;
143 | }
144 |
145 | getValue() {
146 | return this.value;
147 | }
148 | };
149 |
150 | // Mixin pattern using classes
151 | const Flyable = (Base) => class extends Base {
152 | fly() {
153 | console.log(`${this.name} is flying!`);
154 | }
155 | };
156 |
157 | const Swimmable = (Base) => class extends Base {
158 | swim() {
159 | console.log(`${this.name} is swimming!`);
160 | }
161 | };
162 |
163 | // Class using mixins
164 | class Duck extends Swimmable(Flyable(Person)) {
165 | constructor(name) {
166 | super(name, 0); // Ducks don't have human age
167 | this.species = 'Duck';
168 | }
169 |
170 | quack() {
171 | console.log(`${this.name} says: Quack!`);
172 | }
173 | }
174 |
175 | // Function that creates and uses class instances
176 | function demonstrateClasses() {
177 | const person = new Person('Alice', 30);
178 | const employee = new Employee('Bob', 25, 'Developer', 75000);
179 | const account = new BankAccount('12345', 1000);
180 | const duck = new Duck('Donald');
181 |
182 | // Call various methods
183 | console.log(person.greet());
184 | console.log(employee.greet());
185 | employee.work();
186 |
187 | account.deposit(500);
188 | console.log('Balance:', account.balance);
189 |
190 | duck.quack();
191 | duck.fly();
192 | duck.swim();
193 |
194 | return {
195 | person,
196 | employee,
197 | account,
198 | duck
199 | };
200 | }
201 |
202 | // Export classes
203 | export { Person, Employee, BankAccount, MathUtils, Duck };
204 | export default demonstrateClasses;
205 |
206 |
```
--------------------------------------------------------------------------------
/website/src/components/ui/toast.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import * as React from "react";
2 | import * as ToastPrimitives from "@radix-ui/react-toast";
3 | import { cva, type VariantProps } from "class-variance-authority";
4 | import { X } from "lucide-react";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const ToastProvider = ToastPrimitives.Provider;
9 |
10 | const ToastViewport = React.forwardRef<
11 | React.ElementRef<typeof ToastPrimitives.Viewport>,
12 | React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
13 | >(({ className, ...props }, ref) => (
14 | <ToastPrimitives.Viewport
15 | ref={ref}
16 | className={cn(
17 | "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
18 | className,
19 | )}
20 | {...props}
21 | />
22 | ));
23 | ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
24 |
25 | const toastVariants = cva(
26 | "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
27 | {
28 | variants: {
29 | variant: {
30 | default: "border bg-background text-foreground",
31 | destructive: "destructive group border-destructive bg-destructive text-destructive-foreground",
32 | },
33 | },
34 | defaultVariants: {
35 | variant: "default",
36 | },
37 | },
38 | );
39 |
40 | const Toast = React.forwardRef<
41 | React.ElementRef<typeof ToastPrimitives.Root>,
42 | React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>
43 | >(({ className, variant, ...props }, ref) => {
44 | return <ToastPrimitives.Root ref={ref} className={cn(toastVariants({ variant }), className)} {...props} />;
45 | });
46 | Toast.displayName = ToastPrimitives.Root.displayName;
47 |
48 | const ToastAction = React.forwardRef<
49 | React.ElementRef<typeof ToastPrimitives.Action>,
50 | React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
51 | >(({ className, ...props }, ref) => (
52 | <ToastPrimitives.Action
53 | ref={ref}
54 | className={cn(
55 | "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors group-[.destructive]:border-muted/40 hover:bg-secondary group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 group-[.destructive]:focus:ring-destructive disabled:pointer-events-none disabled:opacity-50",
56 | className,
57 | )}
58 | {...props}
59 | />
60 | ));
61 | ToastAction.displayName = ToastPrimitives.Action.displayName;
62 |
63 | const ToastClose = React.forwardRef<
64 | React.ElementRef<typeof ToastPrimitives.Close>,
65 | React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
66 | >(({ className, ...props }, ref) => (
67 | <ToastPrimitives.Close
68 | ref={ref}
69 | className={cn(
70 | "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity group-hover:opacity-100 group-[.destructive]:text-red-300 hover:text-foreground group-[.destructive]:hover:text-red-50 focus:opacity-100 focus:outline-none focus:ring-2 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
71 | className,
72 | )}
73 | toast-close=""
74 | {...props}
75 | >
76 | <X className="h-4 w-4" />
77 | </ToastPrimitives.Close>
78 | ));
79 | ToastClose.displayName = ToastPrimitives.Close.displayName;
80 |
81 | const ToastTitle = React.forwardRef<
82 | React.ElementRef<typeof ToastPrimitives.Title>,
83 | React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
84 | >(({ className, ...props }, ref) => (
85 | <ToastPrimitives.Title ref={ref} className={cn("text-sm font-semibold", className)} {...props} />
86 | ));
87 | ToastTitle.displayName = ToastPrimitives.Title.displayName;
88 |
89 | const ToastDescription = React.forwardRef<
90 | React.ElementRef<typeof ToastPrimitives.Description>,
91 | React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
92 | >(({ className, ...props }, ref) => (
93 | <ToastPrimitives.Description ref={ref} className={cn("text-sm opacity-90", className)} {...props} />
94 | ));
95 | ToastDescription.displayName = ToastPrimitives.Description.displayName;
96 |
97 | type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
98 |
99 | type ToastActionElement = React.ReactElement<typeof ToastAction>;
100 |
101 | export {
102 | type ToastProps,
103 | type ToastActionElement,
104 | ToastProvider,
105 | ToastViewport,
106 | Toast,
107 | ToastTitle,
108 | ToastDescription,
109 | ToastClose,
110 | ToastAction,
111 | };
112 |
```
--------------------------------------------------------------------------------
/src/codegraphcontext/core/jobs.py:
--------------------------------------------------------------------------------
```python
1 | # src/codegraphcontext/core/jobs.py
2 | """
3 | This module defines the data structures and manager for handling long-running,
4 | background jobs, such as code indexing.
5 | """
6 | import uuid
7 | import threading
8 | from datetime import datetime, timedelta
9 | from dataclasses import dataclass, asdict
10 | from enum import Enum
11 | from typing import Any, Dict, List, Optional
12 | from pathlib import Path
13 |
14 |
15 | class JobStatus(Enum):
16 | """Enumeration for the possible statuses of a background job."""
17 | PENDING = "pending"
18 | RUNNING = "running"
19 | COMPLETED = "completed"
20 | FAILED = "failed"
21 | CANCELLED = "cancelled"
22 |
23 | @dataclass
24 | class JobInfo:
25 | """
26 | A data class to hold all information about a single background job.
27 | This makes it easy to track the job's progress, status, and results.
28 | """
29 | job_id: str
30 | status: JobStatus
31 | start_time: datetime
32 | end_time: Optional[datetime] = None
33 | total_files: int = 0
34 | processed_files: int = 0
35 | current_file: Optional[str] = None
36 | estimated_duration: Optional[float] = None
37 | actual_duration: Optional[float] = None
38 | errors: List[str] = None
39 | result: Optional[Dict[str, Any]] = None
40 | path: Optional[str] = None
41 | is_dependency: bool = False
42 |
43 | def __post_init__(self):
44 | """Ensures the errors list is initialized after the object is created."""
45 | if self.errors is None:
46 | self.errors = []
47 |
48 | @property
49 | def progress_percentage(self) -> float:
50 | """Calculates the completion percentage of the job."""
51 | if self.total_files == 0:
52 | return 0.0
53 | return (self.processed_files / self.total_files) * 100
54 |
55 | @property
56 | def estimated_time_remaining(self) -> Optional[float]:
57 | """Calculates the estimated time remaining based on the average time per file."""
58 | if self.status != JobStatus.RUNNING or self.processed_files == 0:
59 | return None
60 | elapsed = (datetime.now() - self.start_time).total_seconds()
61 | avg_time_per_file = elapsed / self.processed_files
62 | remaining_files = self.total_files - self.processed_files
63 | return remaining_files * avg_time_per_file
64 |
65 | class JobManager:
66 | """
67 | A thread-safe manager for creating, updating, and retrieving information
68 | about background jobs. It stores job information in memory.
69 | """
70 | def __init__(self):
71 | self.jobs: Dict[str, JobInfo] = {}
72 | self.lock = threading.Lock() # A lock to ensure thread-safe access to the jobs dictionary.
73 |
74 | def create_job(self, path: str, is_dependency: bool = False) -> str:
75 | """Creates a new job, assigns it a unique ID, and stores it."""
76 | job_id = str(uuid.uuid4())
77 | with self.lock:
78 | self.jobs[job_id] = JobInfo(
79 | job_id=job_id,
80 | status=JobStatus.PENDING,
81 | start_time=datetime.now(),
82 | path=path,
83 | is_dependency=is_dependency
84 | )
85 | return job_id
86 |
87 | def update_job(self, job_id: str, **kwargs):
88 | """Updates the information for a specific job in a thread-safe manner."""
89 | with self.lock:
90 | if job_id in self.jobs:
91 | job = self.jobs[job_id]
92 | for key, value in kwargs.items():
93 | if hasattr(job, key):
94 | setattr(job, key, value)
95 |
96 | def get_job(self, job_id: str) -> Optional[JobInfo]:
97 | """Retrieves the information for a single job."""
98 | with self.lock:
99 | return self.jobs.get(job_id)
100 |
101 | def list_jobs(self) -> List[JobInfo]:
102 | """Returns a list of all jobs currently in the manager."""
103 | with self.lock:
104 | return list(self.jobs.values())
105 |
106 | def find_active_job_by_path(self, path: str) -> Optional[JobInfo]:
107 | """Finds the most recent, currently active (pending or running) job for a given path."""
108 | with self.lock:
109 | path_obj = Path(path).resolve()
110 |
111 | matching_jobs = sorted(
112 | [job for job in self.jobs.values() if job.path and Path(job.path).resolve() == path_obj],
113 | key=lambda j: j.start_time,
114 | reverse=True
115 | )
116 |
117 | for job in matching_jobs:
118 | if job.status in [JobStatus.PENDING, JobStatus.RUNNING]:
119 | return job
120 |
121 | return None
122 |
123 | def cleanup_old_jobs(self, max_age_hours: int = 24):
124 | """Removes old, completed jobs from memory to prevent memory leaks."""
125 | cutoff_time = datetime.now() - timedelta(hours=max_age_hours)
126 | with self.lock:
127 | jobs_to_remove = [
128 | job_id for job_id, job in self.jobs.items()
129 | if job.end_time and job.end_time < cutoff_time
130 | ]
131 | for job_id in jobs_to_remove:
132 | del self.jobs[job_id]
133 |
```
--------------------------------------------------------------------------------
/website/src/components/ui/command.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import * as React from "react";
2 | import { type DialogProps } from "@radix-ui/react-dialog";
3 | import { Command as CommandPrimitive } from "cmdk";
4 | import { Search } from "lucide-react";
5 |
6 | import { cn } from "@/lib/utils";
7 | import { Dialog, DialogContent } from "@/components/ui/dialog";
8 |
9 | const Command = React.forwardRef<
10 | React.ElementRef<typeof CommandPrimitive>,
11 | React.ComponentPropsWithoutRef<typeof CommandPrimitive>
12 | >(({ className, ...props }, ref) => (
13 | <CommandPrimitive
14 | ref={ref}
15 | className={cn(
16 | "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
17 | className,
18 | )}
19 | {...props}
20 | />
21 | ));
22 | Command.displayName = CommandPrimitive.displayName;
23 |
24 | interface CommandDialogProps extends DialogProps {}
25 |
26 | const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
27 | return (
28 | <Dialog {...props}>
29 | <DialogContent className="overflow-hidden p-0 shadow-lg">
30 | <Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
31 | {children}
32 | </Command>
33 | </DialogContent>
34 | </Dialog>
35 | );
36 | };
37 |
38 | const CommandInput = React.forwardRef<
39 | React.ElementRef<typeof CommandPrimitive.Input>,
40 | React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
41 | >(({ className, ...props }, ref) => (
42 | <div className="flex items-center border-b px-3" cmdk-input-wrapper="">
43 | <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
44 | <CommandPrimitive.Input
45 | ref={ref}
46 | className={cn(
47 | "flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
48 | className,
49 | )}
50 | {...props}
51 | />
52 | </div>
53 | ));
54 |
55 | CommandInput.displayName = CommandPrimitive.Input.displayName;
56 |
57 | const CommandList = React.forwardRef<
58 | React.ElementRef<typeof CommandPrimitive.List>,
59 | React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
60 | >(({ className, ...props }, ref) => (
61 | <CommandPrimitive.List
62 | ref={ref}
63 | className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
64 | {...props}
65 | />
66 | ));
67 |
68 | CommandList.displayName = CommandPrimitive.List.displayName;
69 |
70 | const CommandEmpty = React.forwardRef<
71 | React.ElementRef<typeof CommandPrimitive.Empty>,
72 | React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
73 | >((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />);
74 |
75 | CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
76 |
77 | const CommandGroup = React.forwardRef<
78 | React.ElementRef<typeof CommandPrimitive.Group>,
79 | React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
80 | >(({ className, ...props }, ref) => (
81 | <CommandPrimitive.Group
82 | ref={ref}
83 | className={cn(
84 | "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
85 | className,
86 | )}
87 | {...props}
88 | />
89 | ));
90 |
91 | CommandGroup.displayName = CommandPrimitive.Group.displayName;
92 |
93 | const CommandSeparator = React.forwardRef<
94 | React.ElementRef<typeof CommandPrimitive.Separator>,
95 | React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
96 | >(({ className, ...props }, ref) => (
97 | <CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />
98 | ));
99 | CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
100 |
101 | const CommandItem = React.forwardRef<
102 | React.ElementRef<typeof CommandPrimitive.Item>,
103 | React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
104 | >(({ className, ...props }, ref) => (
105 | <CommandPrimitive.Item
106 | ref={ref}
107 | className={cn(
108 | "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50",
109 | className,
110 | )}
111 | {...props}
112 | />
113 | ));
114 |
115 | CommandItem.displayName = CommandPrimitive.Item.displayName;
116 |
117 | const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
118 | return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
119 | };
120 | CommandShortcut.displayName = "CommandShortcut";
121 |
122 | export {
123 | Command,
124 | CommandDialog,
125 | CommandInput,
126 | CommandList,
127 | CommandEmpty,
128 | CommandGroup,
129 | CommandItem,
130 | CommandShortcut,
131 | CommandSeparator,
132 | };
133 |
```
--------------------------------------------------------------------------------
/website/src/components/InstallationSection.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
2 | import { Button } from "@/components/ui/button";
3 | import { Badge } from "@/components/ui/badge";
4 | import { Copy, Terminal, Play, Settings } from "lucide-react";
5 | import { toast } from "sonner";
6 | import ShowStarGraph from "@/components/ShowStarGraph";
7 |
8 | const installSteps = [
9 | {
10 | step: "1",
11 | title: "Install",
12 | command: "pip install codegraphcontext",
13 | description: "Install CodeGraphContext using pip."
14 | },
15 | {
16 | step: "2",
17 | title: "Setup",
18 | command: "cgc setup",
19 | description: "Interactive wizard to configure your Neo4j database."
20 | },
21 | {
22 | step: "3",
23 | title: "Start",
24 | command: "cgc start",
25 | description: "Launch the MCP server and begin indexing."
26 | }
27 | ];
28 |
29 | const setupOptions = [
30 | { icon: Terminal, title: "Docker (Recommended)", description: "Automated Neo4j setup using Docker containers.", color: "graph-node-1" },
31 | { icon: Play, title: "Linux Binary", description: "Direct installation on Debian-based systems.", color: "graph-node-2" },
32 | { icon: Settings, title: "Hosted Database", description: "Connect to Neo4j AuraDB or an existing instance.", color: "graph-node-3" }
33 | ];
34 |
35 | const copyToClipboard = (text: string) => {
36 | navigator.clipboard.writeText(text);
37 | toast.success("Copied to clipboard!");
38 | };
39 |
40 | const InstallationSection = () => {
41 | return (
42 | <>
43 | <ShowStarGraph />
44 | <section className="py-24 px-4 bg-muted/20" data-aos="fade-in">
45 | <div className="container mx-auto max-w-5xl">
46 | <div className="text-center mb-16" data-aos="fade-down">
47 | <h2 className="text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-primary via-primary to-accent bg-clip-text text-transparent">
48 | Get Started in Minutes
49 | </h2>
50 | <p className="text-xl text-muted-foreground">
51 | Simple installation with automated setup for your database configuration.
52 | </p>
53 | </div>
54 |
55 | <div className="grid gap-6 mb-12">
56 | {installSteps.map((step, index) => (
57 | <div key={index} data-aos="fade-up" data-aos-delay={index * 100}>
58 | <Card className="transition-shadow duration-300 hover:shadow-lg bg-white/95 dark:bg-card/50">
59 | <CardHeader className="pb-4">
60 | <div className="flex items-center gap-4">
61 | <Badge variant="secondary" className="text-lg font-bold w-9 h-9 flex items-center justify-center rounded-full bg-primary/10 text-primary">
62 | {step.step}
63 | </Badge>
64 | <div>
65 | <CardTitle className="text-xl">{step.title}</CardTitle>
66 | <CardDescription>{step.description}</CardDescription>
67 | </div>
68 | </div>
69 | </CardHeader>
70 | <CardContent>
71 | <div className="p-3 rounded-md bg-muted/40 flex items-center justify-between group border shadow-inner">
72 | <code className="text-accent font-mono text-sm">$ {step.command}</code>
73 | <Button variant="ghost" size="icon" onClick={() => copyToClipboard(step.command)} className="opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8">
74 | <Copy className="h-4 w-4" />
75 | </Button>
76 | </div>
77 | </CardContent>
78 | </Card>
79 | </div>
80 | ))}
81 | </div>
82 |
83 | <div data-aos="fade-up" data-aos-delay="300">
84 | <Card className="bg-white/95 dark:bg-card/50">
85 | <CardHeader>
86 | <CardTitle className="flex items-center gap-3"><Settings className="h-6 w-6 text-primary" />Setup Options</CardTitle>
87 | <CardDescription>The setup wizard supports multiple Neo4j configurations.</CardDescription>
88 | </CardHeader>
89 | <CardContent>
90 | <div className="grid md:grid-cols-3 gap-6">
91 | {setupOptions.map((option, index) => (
92 | <div key={index} className="text-center p-4 rounded-lg bg-muted/30">
93 | <div className={`w-12 h-12 bg-${option.color}/10 rounded-lg flex items-center justify-center mx-auto mb-3`}>
94 | <option.icon className={`h-6 w-6 text-${option.color}`} />
95 | </div>
96 | <h4 className="font-semibold mb-2">{option.title}</h4>
97 | <p className="text-sm text-muted-foreground">{option.description}</p>
98 | </div>
99 | ))}
100 | </div>
101 | </CardContent>
102 | </Card>
103 | </div>
104 | </div>
105 | </section>
106 | </>
107 | );
108 | };
109 |
110 | export default InstallationSection;
111 |
112 |
```
--------------------------------------------------------------------------------
/scripts/generate_lang_contributors.py:
--------------------------------------------------------------------------------
```python
1 | import subprocess
2 | import os
3 | from collections import defaultdict
4 |
5 | # Get the absolute path of the script's directory, then go up to the project root.
6 | SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
7 | PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
8 |
9 | # Define files to track per language. Paths are relative to the project root.
10 | files_by_lang = {
11 | "c": ["src/codegraphcontext/tools/languages/c.py"],
12 | "cpp": ["src/codegraphcontext/tools/languages/cpp.py"],
13 | "go": ["src/codegraphcontext/tools/languages/go.py"],
14 | "java": ["src/codegraphcontext/tools/languages/java.py"],
15 | "javascript": ["src/codegraphcontext/tools/languages/javascript.py"],
16 | "python": ["src/codegraphcontext/tools/languages/python.py"],
17 | "ruby": ["src/codegraphcontext/tools/languages/ruby.py"],
18 | "rust": ["src/codegraphcontext/tools/languages/rust.py"],
19 | "typescript": ["src/codegraphcontext/tools/languages/typescript.py"],
20 | }
21 |
22 | def get_contributor_stats(files):
23 | """
24 | Returns a dictionary of contributors with commit count, lines added, and lines deleted.
25 | This is done by parsing the output of 'git log'.
26 | """
27 | data = defaultdict(lambda: {"commits": 0, "added": 0, "deleted": 0, "email": ""})
28 |
29 | try:
30 | # Use 'git log' with '--numstat' to get file changes, author name, and email in one go.
31 | log_output = subprocess.check_output(
32 | ["git", "log", "--no-merges", "--numstat", "--pretty=format:---%n%an%n%ae", "--"] + files,
33 | text=True,
34 | cwd=PROJECT_ROOT
35 | ).strip()
36 | except subprocess.CalledProcessError as e:
37 | print(f"Error fetching git log for files {files}: {e}")
38 | return data
39 |
40 | if not log_output:
41 | return data
42 |
43 | commits = log_output.split('---')[1:]
44 |
45 | for commit in commits:
46 | lines = commit.strip().split('\n')
47 | author = lines[0].strip()
48 | email = lines[1].strip()
49 | if not author:
50 | continue
51 |
52 | data[author]["commits"] += 1
53 | data[author]["email"] = email
54 |
55 | for line in lines[2:]:
56 | if not line.strip():
57 | continue
58 |
59 | parts = line.split("\t")
60 | if len(parts) >= 3:
61 | added, deleted, _ = parts
62 | added = int(added) if added != "-" else 0
63 | deleted = int(deleted) if deleted != "-" else 0
64 | data[author]["added"] += added
65 | data[author]["deleted"] += deleted
66 |
67 | return data
68 |
69 | def get_username_from_email(email):
70 | if email.endswith('@users.noreply.github.com'):
71 | return email.split('+')[1].split('@')[0]
72 | return None
73 |
74 | def get_repo_url():
75 | try:
76 | url = subprocess.check_output(
77 | ["git", "remote", "get-url", "origin"],
78 | text=True,
79 | cwd=PROJECT_ROOT
80 | ).strip()
81 | if url.endswith(".git"):
82 | url = url[:-4]
83 | if url.startswith("[email protected]:"):
84 | url = url.replace("[email protected]:", "https://github.com/")
85 | return url
86 | except Exception:
87 | return None
88 |
89 | def generate_markdown_table(lang, stats, repo_url, files):
90 | """
91 | Generates a Markdown table for contributors
92 | """
93 | table = f"## {lang.capitalize()} Contributors\n\n"
94 | table += "| Rank | Contributor | Commits | Lines Added | Lines Deleted | Link to Contributions |\n"
95 | table += "|---|---|---|---|---|---|\n"
96 |
97 | for rank, (author, vals) in enumerate(sorted(stats.items(), key=lambda x: (x[1]["commits"], x[1]["added"]), reverse=True), 1):
98 | email = vals["email"]
99 | username = get_username_from_email(email)
100 |
101 | if username:
102 | profile_str = f"[{author}](https://github.com/{username})"
103 | author_for_link = username
104 | else:
105 | profile_str = author
106 | author_for_link = email
107 |
108 | contribution_links = []
109 | for file_path in files:
110 | file_name = os.path.basename(file_path)
111 | link = f"[{file_name}]({repo_url}/commits/main/{file_path}?author={author_for_link})"
112 | contribution_links.append(link)
113 |
114 | links_str = ", ".join(contribution_links)
115 |
116 | table += f"| {rank} | {profile_str} | {vals['commits']} | {vals['added']} | {vals['deleted']} | {links_str} |\n"
117 |
118 | return table
119 |
120 | def main():
121 | repo_url = get_repo_url()
122 | if not repo_url:
123 | print("Could not determine repository URL. Contribution links will not be generated.")
124 |
125 | output_file = os.path.join(PROJECT_ROOT, "contributors.md")
126 | with open(output_file, "w") as f:
127 | f.write("# Language Contributors\n\n")
128 | f.write("This file is auto-generated. Do not edit manually.\n\n")
129 | for lang, files in files_by_lang.items():
130 | stats = get_contributor_stats(files)
131 | if stats:
132 | table = generate_markdown_table(lang, stats, repo_url, files)
133 | f.write(table + "\n\n")
134 | print(f"Contributor stats generated in {output_file}")
135 |
136 | if __name__ == "__main__":
137 | main()
138 |
```
--------------------------------------------------------------------------------
/website/src/components/ui/navigation-menu.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import * as React from "react";
2 | import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
3 | import { cva } from "class-variance-authority";
4 | import { ChevronDown } from "lucide-react";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const NavigationMenu = React.forwardRef<
9 | React.ElementRef<typeof NavigationMenuPrimitive.Root>,
10 | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
11 | >(({ className, children, ...props }, ref) => (
12 | <NavigationMenuPrimitive.Root
13 | ref={ref}
14 | className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)}
15 | {...props}
16 | >
17 | {children}
18 | <NavigationMenuViewport />
19 | </NavigationMenuPrimitive.Root>
20 | ));
21 | NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
22 |
23 | const NavigationMenuList = React.forwardRef<
24 | React.ElementRef<typeof NavigationMenuPrimitive.List>,
25 | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
26 | >(({ className, ...props }, ref) => (
27 | <NavigationMenuPrimitive.List
28 | ref={ref}
29 | className={cn("group flex flex-1 list-none items-center justify-center space-x-1", className)}
30 | {...props}
31 | />
32 | ));
33 | NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
34 |
35 | const NavigationMenuItem = NavigationMenuPrimitive.Item;
36 |
37 | const navigationMenuTriggerStyle = cva(
38 | "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50",
39 | );
40 |
41 | const NavigationMenuTrigger = React.forwardRef<
42 | React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
43 | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
44 | >(({ className, children, ...props }, ref) => (
45 | <NavigationMenuPrimitive.Trigger
46 | ref={ref}
47 | className={cn(navigationMenuTriggerStyle(), "group", className)}
48 | {...props}
49 | >
50 | {children}{" "}
51 | <ChevronDown
52 | className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
53 | aria-hidden="true"
54 | />
55 | </NavigationMenuPrimitive.Trigger>
56 | ));
57 | NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
58 |
59 | const NavigationMenuContent = React.forwardRef<
60 | React.ElementRef<typeof NavigationMenuPrimitive.Content>,
61 | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
62 | >(({ className, ...props }, ref) => (
63 | <NavigationMenuPrimitive.Content
64 | ref={ref}
65 | className={cn(
66 | "left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto",
67 | className,
68 | )}
69 | {...props}
70 | />
71 | ));
72 | NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
73 |
74 | const NavigationMenuLink = NavigationMenuPrimitive.Link;
75 |
76 | const NavigationMenuViewport = React.forwardRef<
77 | React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
78 | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
79 | >(({ className, ...props }, ref) => (
80 | <div className={cn("absolute left-0 top-full flex justify-center")}>
81 | <NavigationMenuPrimitive.Viewport
82 | className={cn(
83 | "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
84 | className,
85 | )}
86 | ref={ref}
87 | {...props}
88 | />
89 | </div>
90 | ));
91 | NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName;
92 |
93 | const NavigationMenuIndicator = React.forwardRef<
94 | React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
95 | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
96 | >(({ className, ...props }, ref) => (
97 | <NavigationMenuPrimitive.Indicator
98 | ref={ref}
99 | className={cn(
100 | "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
101 | className,
102 | )}
103 | {...props}
104 | >
105 | <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
106 | </NavigationMenuPrimitive.Indicator>
107 | ));
108 | NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName;
109 |
110 | export {
111 | navigationMenuTriggerStyle,
112 | NavigationMenu,
113 | NavigationMenuList,
114 | NavigationMenuItem,
115 | NavigationMenuContent,
116 | NavigationMenuTrigger,
117 | NavigationMenuLink,
118 | NavigationMenuIndicator,
119 | NavigationMenuViewport,
120 | };
121 |
```
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/types-interfaces.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Basic Types and Interfaces
3 | * Demonstrates TypeScript's core type system including primitives,
4 | * interfaces, type aliases, unions, intersections, and advanced type patterns
5 | */
6 |
7 | // ========== Primitive Types ==========
8 | export const stringValue: string = "Hello TypeScript";
9 | export const numberValue: number = 42;
10 | export const booleanValue: boolean = true;
11 | export const nullValue: null = null;
12 | export const undefinedValue: undefined = undefined;
13 | export const symbolValue: symbol = Symbol("unique");
14 | export const bigintValue: bigint = 100n;
15 |
16 | // ========== Array and Tuple Types ==========
17 | export const numberArray: number[] = [1, 2, 3, 4];
18 | export const stringArray: Array<string> = ["a", "b", "c"];
19 | export const mixedTuple: [string, number, boolean] = ["hello", 42, true];
20 | export const namedTuple: [name: string, age: number] = ["Alice", 30];
21 |
22 | // ========== Object Types ==========
23 | export const basicObject: { name: string; age: number } = {
24 | name: "John",
25 | age: 25
26 | };
27 |
28 | // ========== Interface Definitions ==========
29 | export interface User {
30 | readonly id: number;
31 | name: string;
32 | email?: string; // Optional property
33 | readonly createdAt: Date;
34 | preferences: UserPreferences;
35 | }
36 |
37 | export interface UserPreferences {
38 | theme: "light" | "dark";
39 | notifications: boolean;
40 | language: string;
41 | }
42 |
43 | // Interface inheritance
44 | export interface AdminUser extends User {
45 | permissions: string[];
46 | lastLogin?: Date;
47 | }
48 |
49 | // Interface with index signature
50 | export interface Dictionary<T = any> {
51 | [key: string]: T;
52 | }
53 |
54 | // Interface with call signature
55 | export interface StringProcessor {
56 | (input: string): string;
57 | description: string;
58 | }
59 |
60 | // Interface with construct signature
61 | export interface Constructable {
62 | new (name: string): { name: string };
63 | }
64 |
65 | // ========== Type Aliases ==========
66 | export type Status = "pending" | "approved" | "rejected";
67 | export type ID = string | number;
68 | export type EventHandler<T> = (event: T) => void;
69 |
70 | // Generic type alias
71 | export type Response<T> = {
72 | data: T;
73 | error: string | null;
74 | timestamp: Date;
75 | };
76 |
77 | // Mapped type alias
78 | export type Optional<T> = {
79 | [K in keyof T]?: T[K];
80 | };
81 |
82 | // ========== Union Types ==========
83 | export type StringOrNumber = string | number;
84 | export type Theme = "light" | "dark" | "auto";
85 |
86 | export function formatValue(value: StringOrNumber): string {
87 | if (typeof value === "string") {
88 | return value.toUpperCase();
89 | }
90 | return value.toString();
91 | }
92 |
93 | // Discriminated union
94 | export type Shape =
95 | | { kind: "circle"; radius: number }
96 | | { kind: "rectangle"; width: number; height: number }
97 | | { kind: "triangle"; base: number; height: number };
98 |
99 | export function calculateArea(shape: Shape): number {
100 | switch (shape.kind) {
101 | case "circle":
102 | return Math.PI * shape.radius ** 2;
103 | case "rectangle":
104 | return shape.width * shape.height;
105 | case "triangle":
106 | return (shape.base * shape.height) / 2;
107 | default:
108 | const _exhaustive: never = shape;
109 | throw new Error(`Unhandled shape: ${_exhaustive}`);
110 | }
111 | }
112 |
113 | // ========== Intersection Types ==========
114 | export type PersonalInfo = {
115 | name: string;
116 | age: number;
117 | };
118 |
119 | export type ContactInfo = {
120 | email: string;
121 | phone: string;
122 | };
123 |
124 | export type Employee = PersonalInfo & ContactInfo & {
125 | employeeId: string;
126 | department: string;
127 | };
128 |
129 | // ========== Conditional Types ==========
130 | export type NonNullable<T> = T extends null | undefined ? never : T;
131 | export type ArrayElement<T> = T extends (infer U)[] ? U : never;
132 |
133 | // ========== Template Literal Types ==========
134 | export type EventName<T extends string> = `on${Capitalize<T>}`;
135 | export type CSSProperty = `--${string}`;
136 |
137 | // ========== Utility Types Usage ==========
138 | export type PartialUser = Partial<User>;
139 | export type RequiredUser = Required<User>;
140 | export type UserEmail = Pick<User, "email">;
141 | export type UserWithoutId = Omit<User, "id">;
142 | export type UserKeys = keyof User;
143 | export type UserValues = User[keyof User];
144 |
145 | // ========== Complex Type Examples ==========
146 | export interface GenericRepository<T, K extends keyof T> {
147 | findById(id: T[K]): Promise<T | null>;
148 | findAll(): Promise<T[]>;
149 | create(entity: Omit<T, K>): Promise<T>;
150 | update(id: T[K], updates: Partial<T>): Promise<T>;
151 | delete(id: T[K]): Promise<void>;
152 | }
153 |
154 | // Recursive type
155 | export interface TreeNode<T> {
156 | value: T;
157 | children: TreeNode<T>[];
158 | parent?: TreeNode<T>;
159 | }
160 |
161 | // Function type with overloads
162 | export interface Logger {
163 | (message: string): void;
164 | (level: "info" | "warn" | "error", message: string): void;
165 | (level: "info" | "warn" | "error", message: string, data: any): void;
166 | }
167 |
168 | // ========== Implementation Examples ==========
169 | const user: User = {
170 | id: 1,
171 | name: "Alice Johnson",
172 | email: "[email protected]",
173 | createdAt: new Date(),
174 | preferences: {
175 | theme: "dark",
176 | notifications: true,
177 | language: "en"
178 | }
179 | };
180 |
181 | const adminUser: AdminUser = {
182 | ...user,
183 | permissions: ["read", "write", "delete"],
184 | lastLogin: new Date()
185 | };
186 |
187 | const shapes: Shape[] = [
188 | { kind: "circle", radius: 5 },
189 | { kind: "rectangle", width: 10, height: 6 },
190 | { kind: "triangle", base: 8, height: 4 }
191 | ];
192 |
193 | export const typeExamples = {
194 | user,
195 | adminUser,
196 | shapes,
197 | areas: shapes.map(calculateArea)
198 | };
```
--------------------------------------------------------------------------------
/src/codegraphcontext/prompts.py:
--------------------------------------------------------------------------------
```python
1 | # src/codegraphcontext/prompts.py
2 | """
3 | This file contains the system prompt for the language model.
4 | This prompt provides the core instructions, principles, and standard operating
5 | procedures for the AI assistant, guiding it on how to effectively use the tools
6 | provided by this MCP server.
7 | """
8 |
9 | LLM_SYSTEM_PROMPT = """# AI Pair Programmer Instructions
10 |
11 | ## 1. Your Role and Goal
12 |
13 | You are an expert AI pair programmer. Your primary goal is to help a developer understand, write, and refactor code within their **local project**. Your defining feature is your connection to a local Model Context Protocol (MCP) server, which gives you real-time, accurate information about the codebase.
14 | **Always prioritize using this MCP tools when they can simplify or enhance your workflow compared to guessing.**
15 |
16 | ## 2. Your Core Principles
17 |
18 | ### Principle I: Ground Your Answers in Fact
19 | **Your CORE DIRECTIVE is to use the provided tools to gather facts from the MCP server *before* answering questions or generating code.** Do not guess. Your value comes from providing contextually-aware, accurate assistance.
20 |
21 | ### Principle II: Be an Agent, Not Just a Planner
22 | **Your goal is to complete the user's task in the fewest steps possible.**
23 | * If the user's request maps directly to a single tool, **execute that tool immediately.**
24 | * Do not create a multi-step plan for a one-step task. The Standard Operating Procedures (SOPs) below are for complex queries that require reasoning and combining information from multiple tools.
25 |
26 | **Example of what NOT to do:**
27 |
28 | > **User:** "Start watching the `my-project` folder."
29 | > **Incorrect Plan:**
30 | > 1. Check if `watchdog` is installed.
31 | > 2. Use the `watch_directory` tool on `my-project`.
32 | > 3. Update a todo list.
33 |
34 | **Example of the CORRECT, direct action:**
35 |
36 | > **User:** "Start watching the `my-project` folder."
37 | > **Correct Action:** Immediately call the `watch_directory` tool.
38 | > ```json
39 | > {
40 | > "tool_name": "watch_directory",
41 | > "arguments": { "path": "my-project" }
42 | > }
43 | > ```
44 |
45 | ## 3. Tool Manifest & Usage
46 |
47 | | Tool Name | Purpose & When to Use |
48 | | :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |
49 | | **`find_code`** | **Your primary search tool.** Use this first for almost any query about locating code. t |
50 | | **`analyze_code_relationships`** | **Your deep analysis tool.** Use this after locating a specific item. Use query types like `find_callers` or `find_callees`. |
51 | | **`add_code_to_graph`** | **Your indexing tool.** Use this when the user wants to add a new project folder or file to the context. |
52 | | **`add_package_to_graph`** | **Your dependency indexing tool.** Use this to add a `pip` package to the context. |
53 | | **`list_jobs`** & **`check_job_status`** | **Your job monitoring tools.** |
54 | | **`watch_directory`** | **Your live-update tool.** Use this if the user wants to automatically keep the context updated as they work. |
55 | | **`execute_cypher_query`** | **Expert Fallback Tool.** Use this *only* when other tools cannot answer a very specific or complex question about the code graph. Requires knowledge of Cypher. |
56 |
57 |
58 | ## 4. Standard Operating Procedures (SOPs) for Complex Tasks
59 |
60 | **Note:** Follow these methodical workflows for **complex requests** that require multiple steps of reasoning or combining information from several tools. For direct commands, refer to Principle II and act immediately.
61 |
62 | ### SOP-1: Answering "Where is...?" or "How does...?" Questions
63 | 1. **Locate:** Use `find_code` to find the relevant code.
64 | 2. **Analyze:** Use `analyze_code_relationships` to understand its usage.
65 | 3. **Synthesize:** Combine the information into a clear explanation.
66 |
67 | ### SOP-2: Generating New Code
68 | 1. **Find Context:** Use `find_code` to find similar, existing code to match the style.
69 | 2. **Find Reusable Code:** Use `find_code` to locate specific helper functions the user wants you to use.
70 | 3. **Generate:** Write the code using the correct imports and signatures.
71 |
72 | ### SOP-3: Refactoring or Analyzing Impact
73 | 1. **Identify & Locate:** Use `find_code` to get the canonical path of the item to be changed.
74 | 2. **Assess Impact:** Use `analyze_code_relationships` with the `find_callers` query type to find all affected locations.
75 | 3. **Report Findings:** Present a clear list of all affected files.
76 |
77 | ### SOP-4: Using the Cypher Fallback
78 | 1. **Attempt Standard Tools:** First, always try to use `find_code` and `analyze_code_relationships`.
79 | 2. **Identify Failure:** If the standard tools cannot answer a complex, multi-step relationship query (e.g., "Find all functions that are called by a method in a class that inherits from 'BaseHandler'"), then and only then, resort to the fallback.
80 | 3. **Formulate & Execute:** Construct a Cypher query to find the answer and execute it using `execute_cypher_query`.
81 | 4. **Present Results:** Explain the results to the user based on the query output.
82 | """
```
--------------------------------------------------------------------------------
/tests/test_cpp_parser.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | Test script for the enhanced C++ parser.
3 | """
4 | import json
5 | import sys
6 | from pathlib import Path
7 |
8 |
9 | def test_parser():
10 | """Test the C++ parser with a sample file."""
11 | test_cpp_code = '''
12 |
13 | class TestClass : public BaseClass {
14 | private:
15 | int privateVar;
16 | std::string name;
17 |
18 | protected:
19 | double protectedVar;
20 |
21 | public:
22 | /**
23 | * Constructor for TestClass
24 | * @param value Initial value
25 | */
26 | TestClass(int value) : privateVar(value) {}
27 |
28 | /// Gets the private variable value
29 | int getValue() const {
30 | return privateVar;
31 | }
32 |
33 | /**
34 | * Complex method with parameters
35 | */
36 | virtual void complexMethod(int x, const std::string& str, double y = 3.14) override {
37 | if (x > 0) {
38 | for (int i = 0; i < x; i++) {
39 | processData(i);
40 | }
41 | }
42 | }
43 | };
44 |
45 | namespace MyNamespace {
46 | enum Color {
47 | RED,
48 | GREEN,
49 | BLUE
50 | };
51 |
52 | /**
53 | * Standalone function
54 | */
55 | static inline int calculate(int a, int b) {
56 | return a + b;
57 | }
58 | }
59 |
60 | // Global variable
61 | int globalCounter = 0;
62 |
63 | #include <iostream>
64 | #include <string>
65 | #include "custom_header.h"
66 | '''
67 | test_file = Path("test_sample.cpp")
68 | test_file.write_text(test_cpp_code)
69 |
70 | print("=" * 60)
71 | print("Testing Enhanced C++ Parser")
72 | print("=" * 60)
73 |
74 | try:
75 | from tree_sitter import Language, Parser
76 | import tree_sitter_cpp as tscpp
77 | class MockGenericParser:
78 | def __init__(self):
79 | self.language = Language(tscpp.language())
80 | self.parser = Parser(self.language)
81 | from cpp_parser_enhanced import CppTreeSitterParser
82 |
83 | generic_wrapper = MockGenericParser()
84 | cpp_parser = CppTreeSitterParser(generic_wrapper)
85 |
86 | print(f"\n Parsing: {test_file}")
87 | result = cpp_parser.parse(test_file)
88 |
89 | print("\n" + "=" * 60)
90 | print("PARSING RESULTS")
91 | print("=" * 60)
92 |
93 | print(f"\n File: {result['file_path']}")
94 | print(f" Language: {result['lang']}")
95 |
96 | print(f"\n Functions Found: {len(result['functions'])}")
97 | for func in result['functions']:
98 | print(f"\n Function: {func['name']}")
99 | print(f" Lines: {func['line_number']}-{func['end_line']}")
100 | print(f" Return Type: {func['return_type']}")
101 | print(f" Parameters: {len(func['args'])}")
102 | for param in func['args']:
103 | default = f" = {param['default']}" if param['default'] else ""
104 | print(f" - {param['type']} {param['name']}{default}")
105 | print(f" Modifiers: {', '.join(func['modifiers']) if func['modifiers'] else 'None'}")
106 | print(f" Complexity: {func['complexity']}")
107 | print(f" Calls: {[c['name'] for c in func['calls']]}")
108 | if func['docstring']:
109 | print(f" Docstring: {func['docstring'][:50]}...")
110 |
111 |
112 | print(f"\n Classes Found: {len(result['classes'])}")
113 | for cls in result['classes']:
114 | print(f"\n Class: {cls['name']}")
115 | print(f" Lines: {cls['line_number']}-{cls['end_line']}")
116 | print(f" Base Classes: {cls['bases']}")
117 | print(f" Template: {cls['is_template']}")
118 | print(f" Methods: {len(cls['methods'])}")
119 | for method in cls['methods']:
120 | print(f" - {method['access']}: {method['return_type']} {method['name']}()")
121 | print(f" Members: {len(cls['members'])}")
122 | for member in cls['members']:
123 | print(f" - {member['access']}: {member['type']} {member['name']}")
124 | if cls['docstring']:
125 | print(f" Docstring: {cls['docstring'][:50]}...")
126 |
127 | print(f"\n Namespaces Found: {len(result['namespaces'])}")
128 | for ns in result['namespaces']:
129 | print(f" - {ns['name']} (lines {ns['line_number']}-{ns['end_line']})")
130 |
131 | print(f"\n Enums Found: {len(result['enums'])}")
132 | for enum in result['enums']:
133 | print(f" - {enum['name']}: {enum['values']}")
134 |
135 | print(f"\n Global Variables: {len(result['variables'])}")
136 | for var in result['variables']:
137 | print(f" - {var['type']} {var['name']} (line {var['line_number']})")
138 |
139 | print(f"\n Imports Found: {len(result['imports'])}")
140 | for imp in result['imports']:
141 | import_type = "system" if imp.get('is_system') else "local"
142 | print(f" - {imp['name']} ({import_type})")
143 |
144 | print(f"\n Function Calls: {len(result['function_calls'])}")
145 | for call in result['function_calls'][:10]:
146 | print(f" - {call['name']} (line {call['line_number']})")
147 |
148 | output_file = Path("test_result.json")
149 | with open(output_file, 'w') as f:
150 | json.dump(result, f, indent=2)
151 |
152 | print(f"\n Full results saved to: {output_file}")
153 | print("\n" + "=" * 60)
154 | print("TEST COMPLETED SUCCESSFULLY!")
155 | print("=" * 60)
156 | assert True
157 |
158 | except Exception as e:
159 | print(f"\n ERROR: {e}")
160 | import traceback
161 | traceback.print_exc()
162 | assert True
163 |
164 | finally:
165 | if test_file.exists():
166 | test_file.unlink()
167 | print(f"\n cleaned up test file")
168 |
169 | if __name__ == "__main__":
170 | success = test_parser()
171 | sys.exit(0 if success else 1)
172 |
```
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
```python
1 | import subprocess
2 | import json
3 | import os
4 | import time
5 | import pytest
6 |
7 | # Path to the sample project used in tests
8 | SAMPLE_PROJECT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "sample_project"))
9 | # SAMPLE_PROJECT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "sample_project_javascript"))
10 |
11 |
12 | # Helper function to call a tool, now shared across all tests
13 | def call_tool(server, name, args):
14 | request = {
15 | "jsonrpc": "2.0",
16 | "id": int(time.time()),
17 | "method": "tools/call",
18 | "params": {"name": name, "arguments": args}
19 | }
20 | response = server(request)
21 |
22 | if "result" in response:
23 | content = json.loads(response["result"]["content"][0]["text"])
24 | return content
25 | elif "error" in response:
26 | return response
27 | else:
28 | raise ValueError(f"Unexpected response format: {response}")
29 |
30 | @pytest.fixture(scope="module")
31 | def server():
32 | """
33 | A module-scoped fixture that starts the cgc server once for all tests
34 | in this file and provides a communication helper function.
35 | """
36 | print("\n--- Setting up server fixture ---")
37 |
38 | process = None
39 | try:
40 | print("Starting cgc server process...")
41 | process = subprocess.Popen(
42 | ["cgc", "start"],
43 | stdin=subprocess.PIPE,
44 | stdout=subprocess.PIPE,
45 | stderr=subprocess.PIPE,
46 | text=True,
47 | cwd=os.path.join(os.path.dirname(__file__), ".."))
48 |
49 | print("Waiting for server to be ready...")
50 | for line in iter(process.stderr.readline, ''):
51 | print(f"STDERR: {line.strip()}")
52 | if "MCP Server is running" in line:
53 | print("Server is ready.")
54 | break
55 |
56 | def send_receive(request):
57 | print(f"--> Sending request: {json.dumps(request)}")
58 | process.stdin.write(json.dumps(request) + "\n")
59 | process.stdin.flush()
60 | while True:
61 | response_line = process.stdout.readline()
62 | print(f"<-- Received line: {response_line.strip()}")
63 | try:
64 | return json.loads(response_line)
65 | except json.JSONDecodeError:
66 | continue
67 |
68 | print("Initializing server connection...")
69 | init_request = {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}
70 | init_response = send_receive(init_request)
71 | assert init_response.get("id") == 1 and "result" in init_response, "Initialization failed"
72 | print("Server connection initialized.")
73 |
74 | yield send_receive
75 |
76 | finally:
77 | print("\n--- Tearing down server fixture ---")
78 | if process:
79 | print("Terminating server process.")
80 | process.terminate()
81 | process.wait()
82 | print("Server process terminated.")
83 |
84 | def pytest_addoption(parser):
85 | parser.addoption(
86 | "--no-reindex", action="store_true", default=False, help="Skip re-indexing the project for tests"
87 | )
88 |
89 | @pytest.fixture(scope="module")
90 | def indexed_project(server, request):
91 | """
92 | Ensures the sample project is indexed before running tests.
93 | """
94 | if not request.config.getoption("--no-reindex"):
95 | print("\n--- Ensuring project is indexed ---")
96 | delete_result = call_tool(server, "delete_repository", {"repo_path": SAMPLE_PROJECT_PATH})
97 | print(f"Delete result: {delete_result}")
98 |
99 | add_result = call_tool(server, "add_code_to_graph", {"path": SAMPLE_PROJECT_PATH})
100 | assert add_result.get("success") is True, f"add_code_to_graph failed: {add_result.get('error')}"
101 | job_id = add_result.get("job_id")
102 | assert job_id is not None, "add_code_to_graph did not return a job_id"
103 | print(f"Started indexing job with ID: {job_id}")
104 |
105 | start_time = time.time()
106 | timeout = 180
107 | while True:
108 | if time.time() - start_time > timeout:
109 | pytest.fail(f"Job {job_id} did not complete within {timeout} seconds.")
110 | status_result = call_tool(server, "check_job_status", {"job_id": job_id})
111 | job_status = status_result.get("job", {}).get("status")
112 | print(f"Current job status: {job_status}")
113 | if job_status == "completed":
114 | print("Job completed successfully.")
115 | break
116 | assert job_status not in ["failed", "cancelled"], f"Job failed with status: {job_status}"
117 | time.sleep(2)
118 | else:
119 | print("\n--- Skipping re-indexing as per --no-reindex flag ---")
120 |
121 | return server
122 |
123 | class CodeGraph:
124 | """
125 | A wrapper class that provides a .query() method to execute Cypher
126 | against the indexed graph, compatible with our tests.
127 | """
128 | def __init__(self, server_communicator):
129 | self.server = server_communicator
130 |
131 | def query(self, cypher_query: str):
132 | response = call_tool(self.server, "execute_cypher_query", {"cypher_query": cypher_query})
133 | if response.get("success"):
134 | return response.get("results", [])
135 | else:
136 | error_details = response.get('error', 'Unknown error')
137 | raise RuntimeError(f"Cypher query failed: {error_details}\nQuery was: {cypher_query}")
138 |
139 | @pytest.fixture(scope="module")
140 | def graph(indexed_project):
141 | """
142 | Provides a CodeGraph object to query the indexed project.
143 | Depends on indexed_project to ensure the graph is ready.
144 | """
145 | print("\n--- Creating CodeGraph query wrapper ---")
146 | return CodeGraph(indexed_project)
```
--------------------------------------------------------------------------------
/website/src/components/ui/select.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import * as React from "react";
2 | import * as SelectPrimitive from "@radix-ui/react-select";
3 | import { Check, ChevronDown, ChevronUp } from "lucide-react";
4 |
5 | import { cn } from "@/lib/utils";
6 |
7 | const Select = SelectPrimitive.Root;
8 |
9 | const SelectGroup = SelectPrimitive.Group;
10 |
11 | const SelectValue = SelectPrimitive.Value;
12 |
13 | const SelectTrigger = React.forwardRef<
14 | React.ElementRef<typeof SelectPrimitive.Trigger>,
15 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
16 | >(({ className, children, ...props }, ref) => (
17 | <SelectPrimitive.Trigger
18 | ref={ref}
19 | className={cn(
20 | "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
21 | className,
22 | )}
23 | {...props}
24 | >
25 | {children}
26 | <SelectPrimitive.Icon asChild>
27 | <ChevronDown className="h-4 w-4 opacity-50" />
28 | </SelectPrimitive.Icon>
29 | </SelectPrimitive.Trigger>
30 | ));
31 | SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
32 |
33 | const SelectScrollUpButton = React.forwardRef<
34 | React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
35 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
36 | >(({ className, ...props }, ref) => (
37 | <SelectPrimitive.ScrollUpButton
38 | ref={ref}
39 | className={cn("flex cursor-default items-center justify-center py-1", className)}
40 | {...props}
41 | >
42 | <ChevronUp className="h-4 w-4" />
43 | </SelectPrimitive.ScrollUpButton>
44 | ));
45 | SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
46 |
47 | const SelectScrollDownButton = React.forwardRef<
48 | React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
49 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
50 | >(({ className, ...props }, ref) => (
51 | <SelectPrimitive.ScrollDownButton
52 | ref={ref}
53 | className={cn("flex cursor-default items-center justify-center py-1", className)}
54 | {...props}
55 | >
56 | <ChevronDown className="h-4 w-4" />
57 | </SelectPrimitive.ScrollDownButton>
58 | ));
59 | SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
60 |
61 | const SelectContent = React.forwardRef<
62 | React.ElementRef<typeof SelectPrimitive.Content>,
63 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
64 | >(({ className, children, position = "popper", ...props }, ref) => (
65 | <SelectPrimitive.Portal>
66 | <SelectPrimitive.Content
67 | ref={ref}
68 | className={cn(
69 | "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
70 | position === "popper" &&
71 | "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
72 | className,
73 | )}
74 | position={position}
75 | {...props}
76 | >
77 | <SelectScrollUpButton />
78 | <SelectPrimitive.Viewport
79 | className={cn(
80 | "p-1",
81 | position === "popper" &&
82 | "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
83 | )}
84 | >
85 | {children}
86 | </SelectPrimitive.Viewport>
87 | <SelectScrollDownButton />
88 | </SelectPrimitive.Content>
89 | </SelectPrimitive.Portal>
90 | ));
91 | SelectContent.displayName = SelectPrimitive.Content.displayName;
92 |
93 | const SelectLabel = React.forwardRef<
94 | React.ElementRef<typeof SelectPrimitive.Label>,
95 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
96 | >(({ className, ...props }, ref) => (
97 | <SelectPrimitive.Label ref={ref} className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} {...props} />
98 | ));
99 | SelectLabel.displayName = SelectPrimitive.Label.displayName;
100 |
101 | const SelectItem = React.forwardRef<
102 | React.ElementRef<typeof SelectPrimitive.Item>,
103 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
104 | >(({ className, children, ...props }, ref) => (
105 | <SelectPrimitive.Item
106 | ref={ref}
107 | className={cn(
108 | "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
109 | className,
110 | )}
111 | {...props}
112 | >
113 | <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
114 | <SelectPrimitive.ItemIndicator>
115 | <Check className="h-4 w-4" />
116 | </SelectPrimitive.ItemIndicator>
117 | </span>
118 |
119 | <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
120 | </SelectPrimitive.Item>
121 | ));
122 | SelectItem.displayName = SelectPrimitive.Item.displayName;
123 |
124 | const SelectSeparator = React.forwardRef<
125 | React.ElementRef<typeof SelectPrimitive.Separator>,
126 | React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
127 | >(({ className, ...props }, ref) => (
128 | <SelectPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
129 | ));
130 | SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
131 |
132 | export {
133 | Select,
134 | SelectGroup,
135 | SelectValue,
136 | SelectTrigger,
137 | SelectContent,
138 | SelectLabel,
139 | SelectItem,
140 | SelectSeparator,
141 | SelectScrollUpButton,
142 | SelectScrollDownButton,
143 | };
144 |
```
--------------------------------------------------------------------------------
/website/src/components/TestimonialSection.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { OrbitingCircles } from "./ui/orbiting-circles";
2 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
3 | import { Button } from "@/components/ui/button";
4 | import { ChevronLeft, ChevronRight } from "lucide-react";
5 | import { useMemo, useState } from "react";
6 | import { motion, AnimatePresence } from "framer-motion";
7 |
8 | const avatars = [
9 | { imageUrl: "https://avatars.githubusercontent.com/u/161715841?v=4", profileUrl: "https://github.com/athaxv" },
10 | { imageUrl: "https://avatars.githubusercontent.com/u/20110627?v=4", profileUrl: "https://github.com/tomonarifeehan" },
11 | { imageUrl: "https://avatars.githubusercontent.com/u/106103625?v=4", profileUrl: "https://github.com/BankkRoll" },
12 | { imageUrl: "https://avatars.githubusercontent.com/u/59228569?v=4", profileUrl: "https://github.com/safethecode" },
13 | { imageUrl: "https://avatars.githubusercontent.com/u/59442788?v=4", profileUrl: "https://github.com/sanjay-mali" },
14 | { imageUrl: "https://avatars.githubusercontent.com/u/89768406?v=4", profileUrl: "https://github.com/itsarghyadas" },
15 | ];
16 |
17 | export default function TestimonialSection() {
18 | const reviews = useMemo(() => [
19 | { quote: "We’ve cut our task completion time in half since adopting CodeGraphContext. The DX is phenomenal.", author: "Sarah L.", role: "Operations Manager" },
20 | { quote: "Querying code relationships is finally effortless. Our team relies on it daily.", author: "Miguel A.", role: "Tech Lead" },
21 | { quote: "The visual graph helps new engineers onboard dramatically faster.", author: "Priya K.", role: "Engineering Manager" },
22 | { quote: "Rock‑solid performance, great documentation, and fantastic support.", author: "Daniel W.", role: "Staff Engineer" },
23 | ], []);
24 |
25 | const [index, setIndex] = useState(0);
26 | const next = () => setIndex((i) => (i + 1) % reviews.length);
27 | const prev = () => setIndex((i) => (i - 1 + reviews.length) % reviews.length);
28 |
29 | return (
30 | <section className="py-24 px-4" data-aos="fade-in">
31 | <div className="container mx-auto max-w-6xl">
32 | <div className="text-center mb-16" data-aos="fade-down">
33 | <h2 className="text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-primary via-primary to-accent bg-clip-text text-transparent py-2">
34 | What Teams Are Saying
35 | </h2>
36 | <p className="text-xl text-muted-foreground max-w-3xl mx-auto">
37 | Real feedback from engineers and leaders using CodeGraphContext.
38 | </p>
39 | </div>
40 | <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
41 | <div className="relative mx-auto h-[400px] lg:h-[500px] w-full flex items-center justify-center overflow-hidden" data-aos="zoom-in">
42 | <OrbitingCircles iconSize={56} radius={180} speed={1.4}>
43 | {avatars.map((avatar, i) => (
44 | <a key={i} href={avatar.profileUrl} target="_blank" rel="noopener noreferrer">
45 | <img src={avatar.imageUrl} alt={`avatar-${i}`} className="w-14 h-14 rounded-full border-2 border-white shadow-md dark:border-neutral-800" />
46 | </a>
47 | ))}
48 | </OrbitingCircles>
49 | <OrbitingCircles iconSize={44} radius={100} reverse speed={2}>
50 | {avatars.slice(1, 5).map((avatar, i) => (
51 | <a key={i} href={avatar.profileUrl} target="_blank" rel="noopener noreferrer">
52 | <img src={avatar.imageUrl} alt={`avatar-inner-${i}`} className="w-11 h-11 rounded-full border-2 border-white shadow-md dark:border-neutral-800" />
53 | </a>
54 | ))}
55 | </OrbitingCircles>
56 | </div>
57 |
58 | <div data-aos="fade-left" data-aos-delay="200">
59 | <Card className="dark:bg-card/50 shadow-sm min-h-[300px] flex flex-col justify-between">
60 | <CardHeader>
61 | <CardTitle className="text-3xl md:text-4xl font-bold bg-gradient-primary bg-clip-text text-transparent py-2">
62 | Teams Love It
63 | </CardTitle>
64 | <AnimatePresence mode="wait">
65 | <motion.div
66 | key={index}
67 | initial={{ opacity: 0, y: 10 }}
68 | animate={{ opacity: 1, y: 0 }}
69 | exit={{ opacity: 0, y: -10 }}
70 | transition={{ duration: 0.3 }}
71 | >
72 | <CardDescription className="text-base md:text-lg text-muted-foreground pt-4">
73 | “{reviews[index].quote}”
74 | </CardDescription>
75 | </motion.div>
76 | </AnimatePresence>
77 | </CardHeader>
78 | <CardContent>
79 | <div className="flex items-center justify-between gap-4">
80 | <AnimatePresence mode="wait">
81 | <motion.div
82 | key={index}
83 | initial={{ opacity: 0 }}
84 | animate={{ opacity: 1 }}
85 | exit={{ opacity: 0 }}
86 | transition={{ duration: 0.3, delay: 0.1 }}
87 | >
88 | <p className="font-semibold">{reviews[index].author}</p>
89 | <p className="text-sm text-muted-foreground">{reviews[index].role}</p>
90 | </motion.div>
91 | </AnimatePresence>
92 | <div className="flex gap-2">
93 | <Button onClick={prev} size="icon" variant="outline"><ChevronLeft className="h-4 w-4" /></Button>
94 | <Button onClick={next} size="icon"><ChevronRight className="h-4 w-4" /></Button>
95 | </div>
96 | </div>
97 | </CardContent>
98 | </Card>
99 | </div>
100 | </div>
101 | </div>
102 | </section>
103 | )
104 | }
105 |
106 |
```