Skip to content

Commit 302dad1

Browse files
committed
doc: add lsap-api-design skill
1 parent cfd5ce5 commit 302dad1

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
---
2+
name: lsap-api-design
3+
description: Guide for designing and implementing new LSAP APIs. Use when adding new capabilities to LSAP (definitions, references, rename, etc.) or when asking how to add new features to the LSAP protocol. Provides architectural patterns, implementation steps, and references to existing code examples.
4+
---
5+
6+
# LSAP API Design
7+
8+
Guide for adding new APIs to LSAP. Study existing code as needed.
9+
10+
## Architecture
11+
12+
Three layers:
13+
14+
1. **Schema** (`src/lsap/schema/`): Request/Response models (Pydantic), Markdown templates
15+
2. **Capability** (`src/lsap/capability/`): Business logic, LSP orchestration
16+
3. **LSP** (lsp-client library): Raw protocol operations
17+
18+
**Key Principles:** Agent-cognitive design, Markdown-first output, semantic anchoring via `Locate`, composed capabilities
19+
20+
## Reference Implementations
21+
22+
Study these before implementing:
23+
24+
- **Simple**: `src/lsap/schema/definition.py` + `src/lsap/capability/definition.py`
25+
- **Paginated**: `src/lsap/schema/reference.py` + `src/lsap/capability/reference.py`
26+
- **Multi-mode**: `src/lsap/schema/rename.py` + `src/lsap/capability/rename.py`
27+
- **Complex**: `src/lsap/schema/symbol.py` + `src/lsap/capability/symbol.py`
28+
29+
## Implementation Steps
30+
31+
### 1. Define Schema (`src/lsap/schema/<name>.py`)
32+
33+
See `src/lsap/schema/definition.py` for complete example.
34+
35+
Key components:
36+
37+
- **Request Model**: Inherit from `Request`, `LocateRequest`, or `PaginatedRequest`
38+
- **Response Model**: Inherit from `Response` or `PaginatedResponse`
39+
- **Markdown Template**: Liquid template in `model_config.json_schema_extra["markdown"]`
40+
41+
Template basics (see `docs/liquid_cheatsheet.md`):
42+
- Conditionals: `{% if items.size == 0 %}...{% endif %}`
43+
- Loops: `{% for item in items %}...{% endfor %}`
44+
- Filters: `{{ mode | capitalize }}`, `{{ path | join: "." }}`
45+
46+
### 2. Implement Capability (`src/lsap/capability/<name>.py`)
47+
48+
See `src/lsap/capability/definition.py` for complete example.
49+
50+
Pattern:
51+
52+
```python
53+
from attrs import define
54+
from .abc import Capability
55+
56+
@define
57+
class MyCapability(Capability[MyRequest, MyResponse]):
58+
async def __call__(self, req: MyRequest) -> MyResponse | None:
59+
# 1. Locate position (if needed)
60+
if not (loc_resp := await self.locate(req)):
61+
return None
62+
63+
# 2. Call LSP operations via ensure_capability()
64+
# 3. Process results (use asyncer.create_task_group for parallelism)
65+
# 4. Return response (or None on failure)
66+
```
67+
68+
**Important:** Return `None` on failure, not empty response.
69+
70+
### 3. Register Exports
71+
72+
Add to `src/lsap/capability/__init__.py` and `src/lsap/schema/__init__.py`
73+
74+
### 4. Add Tests
75+
76+
See `tests/test_definition.py` for examples. Must test: success case, not found case.
77+
78+
### 5. Add Documentation
79+
80+
Create `schema/<name>.md` with usage examples.
81+
82+
## Common Patterns
83+
84+
### Pagination
85+
86+
See `src/lsap/capability/reference.py` for complete pattern with `PaginationCache` and `paginate()`.
87+
88+
### Reading Code Context
89+
90+
```python
91+
from lsap.utils.document import DocumentReader
92+
93+
content = await self.client.read_file(file_path)
94+
reader = DocumentReader(content)
95+
snippet = reader.read(context_range, trim_empty=True)
96+
```
97+
98+
### Symbol Information
99+
100+
```python
101+
from lsap.utils.symbol import symbol_at
102+
103+
symbols = await ensure_capability(
104+
self.client, WithRequestDocumentSymbol
105+
).request_document_symbol_list(file_path)
106+
107+
if symbols and (match := symbol_at(symbols, position)):
108+
symbol_path, symbol = match
109+
```
110+
111+
### LSP Capability Check
112+
113+
```python
114+
from lsap.utils.capability import ensure_capability
115+
116+
result = await ensure_capability(
117+
self.client,
118+
WithRequestReferences,
119+
error="Fallback instructions if not supported"
120+
).request_references(file_path, position)
121+
```
122+
123+
## Common Utilities
124+
125+
See `src/lsap/utils/` for implementations.
126+
127+
**Path handling:**
128+
- `client.from_uri(uri)` - Returns relative path by default
129+
- `client.from_uri(uri, relative=False)` - Returns absolute path
130+
131+
**Position conversion:**
132+
- `Position.from_lsp(lsp_pos)` - LSP (0-based) → LSAP (1-based)
133+
- `lsap_pos.to_lsp()` - LSAP (1-based) → LSP (0-based)
134+
135+
**Hover content:**
136+
- `clean_hover_content(hover.value)` - Removes LSP formatting artifacts
137+
138+
## Checklists
139+
140+
**Files to create:**
141+
- `src/lsap/schema/<name>.py`
142+
- `src/lsap/capability/<name>.py`
143+
- `tests/test_<name>.py`
144+
- `schema/<name>.md`
145+
146+
**Files to update:**
147+
- `src/lsap/schema/__init__.py`
148+
- `src/lsap/capability/__init__.py`
149+
150+
**Must verify:**
151+
- Returns `None` on failure (not empty response)
152+
- Uses `ensure_capability()` for LSP operations
153+
- Concurrent operations use semaphores
154+
- Tests cover success and failure cases
155+
156+
## Related Documentation
157+
158+
- `docs/locate_design.md` - Position resolution patterns
159+
- `docs/liquid_cheatsheet.md` - Template syntax
160+
- `CONTRIBUTING.md` - Development workflow

.opencode/skills/lsap-api-design

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/Users/wangbowei/workspace/lsp-skill/packages/LSAP/.agents/skills/lsap-api-design

0 commit comments

Comments
 (0)