Skip to content

Commit 9983a93

Browse files
authored
Merge pull request #67 from agentic-labs/range-refactor
refactor: Update models and client to use new ReadSourceCodeRequest
2 parents 8702e7c + 088f630 commit 9983a93

File tree

6 files changed

+46
-28
lines changed

6 files changed

+46
-28
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ wheels/
4040
*.egg
4141
trieve
4242
.aider*
43+
44+
.DS_Store

lsproxy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
ReferencedSymbolsResponse,
1515
)
1616

17-
__version__ = "0.2.0"
17+
__version__ = "0.3.0"
1818

1919
__all__ = [
2020
"Lsproxy",

lsproxy/client.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
from .models import (
88
DefinitionResponse,
9-
FileRange,
109
ReadSourceCodeResponse,
10+
ReadSourceCodeRequest,
1111
ReferencesResponse,
1212
GetDefinitionRequest,
1313
GetReferencesRequest,
@@ -111,11 +111,18 @@ def list_files(self) -> List[str]:
111111
files = response.json()
112112
return files
113113

114-
def read_source_code(self, request: FileRange) -> ReadSourceCodeResponse:
115-
"""Read source code from a specified file range."""
116-
if not isinstance(request, FileRange):
114+
def read_source_code(self, request: ReadSourceCodeRequest) -> ReadSourceCodeResponse:
115+
"""Read source code from a specified file range.
116+
117+
Args:
118+
request: The request containing the file path and an optional range.
119+
120+
Returns:
121+
ReadSourceCodeResponse containing the source code.
122+
"""
123+
if not isinstance(request, ReadSourceCodeRequest):
117124
raise TypeError(
118-
f"Expected FileRange, got {type(request).__name__}. Please use FileRange model to construct the request."
125+
f"Expected ReadSourceCodeRequest, got {type(request).__name__}. Please use ReadSourceCodeRequest to construct the request."
119126
)
120127
response = self._request(
121128
"POST", "/workspace/read-source-code", json=request.model_dump()
@@ -129,7 +136,7 @@ def initialize_with_modal(
129136
git_token: Optional[str] = None,
130137
sha: Optional[str] = None,
131138
timeout: Optional[int] = None,
132-
version: str = "0.3.5",
139+
version: str = "0.4.0",
133140
) -> "Lsproxy":
134141
"""
135142
Initialize lsproxy by starting a Modal sandbox with the server and connecting to it.
@@ -140,6 +147,7 @@ def initialize_with_modal(
140147
git_token: Optional Git personal access token for private repositories
141148
sha: Optional commit to checkout in the repo
142149
timeout: Sandbox timeout in seconds (defaults to Modal's 5-minute timeout if None)
150+
version: lsproxy version to use (defaults to "0.4.0")
143151
144152
Returns:
145153
Configured Lsproxy client instance

lsproxy/modal.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import time
2-
import json
32
import hashlib
43
import subprocess
54

@@ -131,7 +130,7 @@ def __init__(self, repo_url: str, git_token: str, sha: str, timeout: int, versio
131130
self.tunnel_url = self.sandbox.tunnels()[4444].url
132131

133132
# Start lsproxy
134-
p = self.sandbox.exec(f"lsproxy")
133+
self.sandbox.exec("lsproxy")
135134

136135
def terminate(self):
137136
self.sandbox.terminate()

lsproxy/models.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,33 +71,40 @@ def __hash__(self) -> int:
7171
return hash((self.path, self.position.line, self.position.character))
7272

7373

74+
class Range(BaseModel):
75+
start: Position = Field(..., description="Start position of the range.")
76+
end: Position = Field(..., description="End position of the range.")
77+
78+
def __hash__(self) -> int:
79+
return hash((self.start.line, self.start.character, self.end.line, self.end.character))
80+
81+
7482
class FileRange(BaseModel):
7583
"""Range within a file, defined by start and end positions."""
7684

7785
path: str = Field(..., description="The path to the file.", example="src/main.py")
78-
start: Position = Field(..., description="Start position of the range.")
79-
end: Position = Field(..., description="End position of the range.")
86+
range: Range = Field(..., description="The range within the file.")
8087

8188
def contains(self, file_position: FilePosition) -> bool:
8289
"""Check if a position is within the range."""
8390
return (
8491
self.path == file_position.path
85-
and self.start <= file_position.position
86-
and file_position.position <= self.end
92+
and self.range.start <= file_position.position
93+
and file_position.position <= self.range.end
8794
)
8895

8996
def __lt__(self, other: "FileRange") -> bool:
9097
"""Compare ranges by path first, then start position."""
9198
if self.path != other.path:
9299
return self.path < other.path
93-
return self.start < other.start
100+
return self.range.start < other.range.start
94101

95102
def __eq__(self, other: "FileRange") -> bool:
96103
"""Check if two ranges are equal."""
97104
return (
98105
self.path == other.path
99-
and self.start == other.start
100-
and self.end == other.end
106+
and self.range.start == other.range.start
107+
and self.range.end == other.range.end
101108
)
102109

103110
def __le__(self, other: "FileRange") -> bool:
@@ -116,10 +123,10 @@ def __hash__(self) -> int:
116123
return hash(
117124
(
118125
self.path,
119-
self.start.line,
120-
self.start.character,
121-
self.end.line,
122-
self.end.character,
126+
self.range.start.line,
127+
self.range.start.character,
128+
self.range.end.line,
129+
self.range.end.character,
123130
)
124131
)
125132

@@ -145,17 +152,17 @@ class Symbol(BaseModel):
145152
identifier_position: FilePosition = Field(
146153
..., description="The start position of the symbol's identifier."
147154
)
148-
range: FileRange = Field(..., description="The full range of the symbol.")
155+
file_range: FileRange = Field(..., description="The full range of the symbol.")
149156

150157
def __hash__(self) -> int:
151-
return hash((self.kind, self.name, self.identifier_position, self.range))
158+
return hash((self.kind, self.name, self.identifier_position, self.file_range))
152159

153160

154161
class Identifier(BaseModel):
155162
"""Representation of an identifier in code."""
156163

157164
name: str = Field(..., description="The name of the identifier.")
158-
range: FileRange = Field(
165+
file_range: FileRange = Field(
159166
..., description="The range of the identifier in the file."
160167
)
161168
kind: Optional[str] = Field(
@@ -253,10 +260,6 @@ class GetReferencesRequest(BaseModel):
253260
description="Number of source code lines to include around each reference.",
254261
ge=0,
255262
)
256-
include_declaration: Optional[bool] = Field(
257-
False,
258-
description="Whether to include the declaration of the symbol in the references.",
259-
)
260263
include_raw_response: Optional[bool] = Field(
261264
False,
262265
description="Whether to include the raw response from the language server.",
@@ -308,3 +311,9 @@ class ReadSourceCodeResponse(BaseModel):
308311
source_code: str = Field(
309312
..., description="The source code for the specified range."
310313
)
314+
315+
316+
class ReadSourceCodeRequest(BaseModel):
317+
"""Request to read source code from a file with an optional range."""
318+
path: str = Field(..., description="Path to the file, relative to the workspace root")
319+
range: Optional[Range] = Field(None, description="Optional range within the file to read")

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "lsproxy-sdk"
3-
version = "0.2.5"
3+
version = "0.3.0"
44
description = "SDK for interacting with lsproxy container"
55
readme = "README.md"
66
requires-python = ">=3.10"

0 commit comments

Comments
 (0)