Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions docs/schemas/draft/relation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Relation API

**Core Value**: Trace the call path between two symbols — answering "how does A reach B?"

This is a high-value query for:

- **Code Flow Understanding**: How does `handle_request` eventually call `db.query`?
- **Impact Analysis**: If I modify function X, which entry points are affected?
- **Architecture Validation**: Verify that module A never directly/indirectly calls module B

## RelationRequest

| Field | Type | Default | Description |
| :---------- | :---------------------------- | :------- | :--------------------------------------- |
| `source` | [`Locate`](../locate.md) | Required | The starting symbol for the path search. |
| `target` | [`Locate`](../locate.md) | Required | The ending symbol for the path search. |
| `max_depth` | `number` | `10` | Maximum search depth. |

## RelationResponse

| Field | Type | Description |
| :---------- | :---------------- | :---------------------------------------------------- |
| `request` | `RelationRequest` | The original request. |
| `source` | `ChainNode` | The resolved source symbol. |
| `target` | `ChainNode` | The resolved target symbol. |
| `chains` | `ChainNode[][]` | All paths found. Each path is a sequence of nodes. |

The maximum depth used for the search is available as `request.max_depth`, since the response includes the original `RelationRequest`.

### ChainNode

A lightweight symbol representation for path display:

| Field | Type | Description |
| :---------- | :------- | :--------------------------------- |
| `name` | `string` | Symbol name (e.g., `get_user`) |
| `kind` | `string` | Symbol kind (e.g., `Function`) |
| `file_path` | `Path` | File containing the symbol |
| `detail` | `string` | Optional: signature or extra info |

> **Design Note**: Unlike `HierarchyItem`, `ChainNode` has no `level` or `is_cycle` fields — the array index naturally represents position in the chain.

## Example

### How does `handle_request` reach `db.query`?

#### Request

```json
{
"source": {
"file_path": "src/controllers.py",
"scope": { "symbol_path": ["handle_request"] }
},
"target": {
"file_path": "src/db.py",
"scope": { "symbol_path": ["query"] }
},
"max_depth": 5
}
```

#### Response (Markdown Rendered)

```markdown
# Relation: `handle_request` → `query`

Found 2 call chain(s):

### Chain 1
1. **handle_request** (`Function`) - `src/controllers.py`
2. **UserService.get_user** (`Method`) - `src/services/user.py`
3. **db.query** (`Function`) - `src/db.py`

### Chain 2
1. **handle_request** (`Function`) - `src/controllers.py`
2. **AuthService.validate_token** (`Method`) - `src/services/auth.py`
3. **SessionManager.get_session** (`Method`) - `src/services/session.py`
4. **db.query** (`Function`) - `src/db.py`
```

## Implementation

Orchestrates LSP `Call Hierarchy` requests:

1. **Resolve**: Use `textDocument/prepareCallHierarchy` to get `CallHierarchyItem` for both endpoints
2. **Search**: BFS via `callHierarchy/outgoingCalls` from source (optionally bidirectional with `incomingCalls` from target)
3. **Reconstruct**: Build paths when frontiers meet; filter by `max_depth`

## Design Decisions

| Decision | Rationale |
| :------- | :-------- |
| No pagination | `max_depth` bounds result size; path enumeration is typically small |
| `ChainNode` over `HierarchyItem` | Chains are linear; no tree semantics needed |
| Bidirectional search optional | Optimization for large graphs; not required for correctness |
91 changes: 91 additions & 0 deletions schema/explore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Explore API

## Overview
The Explore API provides "what's around" information for a specific code element. It builds a relationship map of the symbol's neighborhood, including its siblings, dependencies, dependents, and hierarchical position. This API is designed to help Agents build a mental map of the code structure and discover related architectural context.

## When to Use
- **Building a mental map**: When an Agent first encounters a new class or module and needs to understand its role in the system.
- **Impact analysis**: When an Agent wants to see what other components depend on a specific class before making changes.
- **Discovering related code**: When an Agent is looking for similar implementations or helper classes in the same neighborhood.
- **Architectural context**: When an Agent needs to understand the "big picture" of how a component fits into the overall project structure.

## Key Differences from Hierarchy API
| Feature | Explore API | Hierarchy API |
|---------|-------------|---------------|
| **Scope** | Neighborhood & Relationships | Deep Tree Traversal |
| **Direction** | Multi-directional (Up, Down, Sideways) | Vertical (Parent/Child) |
| **Goal** | Contextual Mapping | Structural Navigation |
| **Content** | Siblings, Callers, Callees, Types | Call/Type Hierarchy Tree |

## Relationship Types
- **Hierarchy**: The parent/child relationship (e.g., class members, module contents).
- **Calls**: Outgoing calls (dependencies) and incoming calls (dependents).
- **Types**: Type relationships (e.g., base classes, interface implementations).
- **Siblings**: Other symbols defined in the same scope or file.

## Request Schema
- `locate`: The target symbol to explore.
- `depth`: (Integer) How many levels of relationships to traverse (default: 1).
- `relationship_types`: (List of Strings) Which types of relationships to include (e.g., `["calls", "hierarchy", "siblings"]`).

## Response Schema
- `center`: The symbol at the center of the exploration.
- `relationships`: A structured map of related symbols grouped by relationship type.
- `summary`: A high-level description of the symbol's neighborhood.

## Example: Exploring a class
**Request:**
```json
{
"locate": {
"file_path": "src/models/user.py",
"scope": {
"symbol_path": ["User"]
}
},
"relationship_types": ["hierarchy", "siblings", "calls"],
"depth": 1
}
```

**Response:**
```json
{
"center": { "name": "User", "kind": "class" },
"relationships": {
"hierarchy": [
{ "name": "User.validate", "kind": "method" },
{ "name": "User.save", "kind": "method" }
],
"siblings": [
{ "name": "UserRole", "kind": "enum" },
{ "name": "AnonymousUser", "kind": "class" }
],
"dependents": [
{ "name": "AuthService", "kind": "class", "file": "src/services/auth.py" }
]
}
}
```

**Markdown Output:**
```markdown
# Explore: `User` (class)

`User` is a central model in `src/models/user.py`, primarily used by `AuthService`.

## Hierarchy (Members)
- `validate` (method)
- `save` (method)

## Siblings (In same file)
- `UserRole` (enum)
- `AnonymousUser` (class)

## Dependents (Used by)
- `AuthService` (src/services/auth.py)
```

## See Also
- [Outline API](./outline.md)
- [Reference API](./reference.md)
89 changes: 89 additions & 0 deletions schema/inspect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Inspect API

## Overview
The Inspect API provides "how to use" information for a specific symbol. While the Symbol API focuses on "what it is" (implementation details), the Inspect API is designed to help Agents understand how to correctly call or interact with a symbol by providing its signature, documentation, and real-world usage examples.

## When to Use
- **Learning to call an API**: When an Agent needs to know the parameters, types, and return values of a function.
- **Understanding usage patterns**: When an Agent wants to see how other parts of the codebase call a specific method to avoid common mistakes.
- **Contextual documentation**: When the Agent needs a high-level summary of a symbol's purpose without reading the entire implementation.

## Key Differences from Symbol API
| Feature | Inspect API | Symbol API |
|---------|-------------|------------|
| **Primary Focus** | How to use the symbol | What the symbol is/does |
| **Content** | Signature, Docstring, Usage Examples | Full Source Code, Implementation |
| **Goal** | Integration & Calling | Understanding Implementation |
| **Context** | External perspective | Internal perspective |

## Request Schema
- `locate`: The target symbol to inspect (supports `file_path`, `symbol_path`, `find`, etc.).
- `include_usage`: (Boolean) Whether to include real-world usage examples from the codebase.
- `max_usage_examples`: (Integer) Maximum number of usage examples to return.

## Response Schema
- `symbol`: Basic information about the symbol (name, kind, location).
- `signature`: The formal signature of the symbol (e.g., function parameters and return types).
- `documentation`: The docstring or comments associated with the symbol.
- `usages`: A list of code snippets showing how the symbol is used elsewhere.

## Example: Inspecting a function
**Request:**
```json
{
"locate": {
"file_path": "src/utils/auth.py",
"scope": {
"symbol_path": ["verify_token"]
}
},
"include_usage": true,
"max_usage_examples": 2
}
```

**Response:**
```json
{
"symbol": {
"name": "verify_token",
"kind": "function",
"location": { "uri": "file:///src/utils/auth.py", "range": { ... } }
},
"signature": "def verify_token(token: str, secret: str = None) -> UserPayload",
"documentation": "Verifies a JWT token and returns the decoded payload.\n\n:param token: The JWT string to verify.\n:param secret: Optional secret override.",
"usages": [
{
"file_path": "src/api/middleware.py",
"line": 42,
"code": "payload = verify_token(auth_header.split(' ')[1])"
}
]
}
```

**Markdown Output:**
```markdown
# Inspect: `verify_token`

**Signature:** `def verify_token(token: str, secret: str = None) -> UserPayload`

---

Verifies a JWT token and returns the decoded payload.

:param token: The JWT string to verify.
:param secret: Optional secret override.

## Usage Examples

### src/api/middleware.py:42
```python
41 | auth_header = request.headers.get('Authorization')
42 | payload = verify_token(auth_header.split(' ')[1])
43 | request.user = payload
```

## See Also
- [Symbol API](./symbol.md)
- [Reference API](./reference.md)
2 changes: 2 additions & 0 deletions src/lsap/capability/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .locate import LocateCapability
from .outline import OutlineCapability
from .reference import ReferenceCapability
from .relation import RelationCapability
from .rename import RenameExecuteCapability, RenamePreviewCapability
from .search import SearchCapability
from .symbol import SymbolCapability
Expand All @@ -14,6 +15,7 @@ class Capabilities(TypedDict):
locate: LocateCapability
outline: OutlineCapability
references: ReferenceCapability
relation: RelationCapability
rename_preview: RenamePreviewCapability
rename_execute: RenameExecuteCapability
search: SearchCapability
Expand Down
Loading