indent 0.0.8__py3-none-any.whl → 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of indent might be problematic. Click here for more details.
- exponent/__init__.py +1 -1
- exponent/core/remote_execution/cli_rpc_types.py +3 -0
- exponent/core/remote_execution/files.py +30 -2
- exponent/core/remote_execution/tool_execution.py +3 -8
- {indent-0.0.8.dist-info → indent-0.1.2.dist-info}/METADATA +1 -2
- {indent-0.0.8.dist-info → indent-0.1.2.dist-info}/RECORD +8 -9
- exponent/core/remote_execution/command_execution.py +0 -105
- {indent-0.0.8.dist-info → indent-0.1.2.dist-info}/WHEEL +0 -0
- {indent-0.0.8.dist-info → indent-0.1.2.dist-info}/entry_points.txt +0 -0
exponent/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.1.2" # Keep in sync with pyproject.toml
|
|
@@ -96,14 +96,17 @@ class GrepToolInput(ToolInput, tag=GREP_TOOL_NAME):
|
|
|
96
96
|
pattern: str
|
|
97
97
|
path: str | None = None
|
|
98
98
|
include: str | None = None
|
|
99
|
+
multiline: bool | None = None
|
|
99
100
|
|
|
100
101
|
|
|
101
102
|
class GrepToolResult(ToolResult, tag=GREP_TOOL_NAME):
|
|
102
103
|
matches: list[str]
|
|
103
104
|
truncated: bool = False
|
|
104
105
|
|
|
106
|
+
|
|
105
107
|
WEB_FETCH_TOOL_NAME = "web_fetch"
|
|
106
108
|
|
|
109
|
+
|
|
107
110
|
class WebFetchToolInput(ToolInput, tag=WEB_FETCH_TOOL_NAME):
|
|
108
111
|
query: str
|
|
109
112
|
|
|
@@ -6,6 +6,7 @@ from anyio import Path as AsyncPath
|
|
|
6
6
|
from python_ripgrep import PySortMode, PySortModeKind, files, search
|
|
7
7
|
from rapidfuzz import process
|
|
8
8
|
|
|
9
|
+
from exponent.core.remote_execution.cli_rpc_types import ErrorToolResult, GrepToolResult
|
|
9
10
|
from exponent.core.remote_execution.types import (
|
|
10
11
|
FileAttachment,
|
|
11
12
|
FilePath,
|
|
@@ -28,6 +29,7 @@ FILE_NOT_FOUND: Final[str] = "File {} does not exist"
|
|
|
28
29
|
MAX_FILES_TO_WALK: Final[int] = 10_000
|
|
29
30
|
|
|
30
31
|
GLOB_MAX_COUNT: Final[int] = 1000
|
|
32
|
+
GREP_MAX_RESULTS = 100
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
class FileCache:
|
|
@@ -222,12 +224,32 @@ async def search_files(
|
|
|
222
224
|
file_pattern: str | None,
|
|
223
225
|
regex: str,
|
|
224
226
|
working_directory: str,
|
|
225
|
-
|
|
227
|
+
multiline: bool | None = None,
|
|
228
|
+
) -> GrepToolResult | ErrorToolResult:
|
|
226
229
|
path = AsyncPath(working_directory) / path_str
|
|
230
|
+
|
|
231
|
+
if not await path.exists():
|
|
232
|
+
return ErrorToolResult(
|
|
233
|
+
error_message=f"Path does not exist: {path_str}",
|
|
234
|
+
)
|
|
235
|
+
|
|
227
236
|
path_resolved = await path.resolve()
|
|
228
237
|
globs = [file_pattern] if file_pattern else None
|
|
229
238
|
|
|
230
|
-
|
|
239
|
+
if globs:
|
|
240
|
+
matched_files = await to_thread(
|
|
241
|
+
files,
|
|
242
|
+
patterns=[],
|
|
243
|
+
paths=[str(path_resolved)],
|
|
244
|
+
globs=globs,
|
|
245
|
+
max_count=1,
|
|
246
|
+
)
|
|
247
|
+
if not matched_files:
|
|
248
|
+
return ErrorToolResult(
|
|
249
|
+
error_message=f"No files matched the include glob pattern: {file_pattern} at {path_str}",
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
results = await to_thread(
|
|
231
253
|
search,
|
|
232
254
|
patterns=[regex],
|
|
233
255
|
paths=[str(path_resolved)],
|
|
@@ -238,6 +260,12 @@ async def search_files(
|
|
|
238
260
|
separator_field_context="|",
|
|
239
261
|
separator_field_match="|",
|
|
240
262
|
separator_context="\n...\n",
|
|
263
|
+
multiline=multiline,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
return GrepToolResult(
|
|
267
|
+
matches=results[:GREP_MAX_RESULTS],
|
|
268
|
+
truncated=bool(len(results) > GREP_MAX_RESULTS),
|
|
241
269
|
)
|
|
242
270
|
|
|
243
271
|
|
|
@@ -37,8 +37,6 @@ from exponent.core.remote_execution.utils import (
|
|
|
37
37
|
safe_read_file,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
GREP_MAX_RESULTS = 100
|
|
41
|
-
|
|
42
40
|
|
|
43
41
|
async def execute_tool(
|
|
44
42
|
tool_input: ToolInputType, working_directory: str
|
|
@@ -247,16 +245,13 @@ async def execute_glob_files(
|
|
|
247
245
|
|
|
248
246
|
async def execute_grep_files(
|
|
249
247
|
tool_input: GrepToolInput, working_directory: str
|
|
250
|
-
) -> GrepToolResult:
|
|
251
|
-
|
|
248
|
+
) -> GrepToolResult | ErrorToolResult:
|
|
249
|
+
return await files.search_files(
|
|
252
250
|
path_str=working_directory if tool_input.path is None else tool_input.path,
|
|
253
251
|
file_pattern=tool_input.include,
|
|
254
252
|
regex=tool_input.pattern,
|
|
255
253
|
working_directory=working_directory,
|
|
256
|
-
|
|
257
|
-
return GrepToolResult(
|
|
258
|
-
matches=results[:GREP_MAX_RESULTS],
|
|
259
|
-
truncated=bool(len(results) > GREP_MAX_RESULTS),
|
|
254
|
+
multiline=tool_input.multiline,
|
|
260
255
|
)
|
|
261
256
|
|
|
262
257
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: indent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Indent is an AI Pair Programmer
|
|
5
5
|
Author-email: Sashank Thupukari <sashank@exponent.run>
|
|
6
6
|
Requires-Python: <3.13,>=3.10
|
|
@@ -12,7 +12,6 @@ Requires-Dist: click<9,>=8.1.7
|
|
|
12
12
|
Requires-Dist: colour<0.2,>=0.1.5
|
|
13
13
|
Requires-Dist: diff-match-patch<20230431,>=20230430
|
|
14
14
|
Requires-Dist: eval-type-backport<0.3,>=0.2.0
|
|
15
|
-
Requires-Dist: gevent==24.2.1
|
|
16
15
|
Requires-Dist: git-python>=1.0.3
|
|
17
16
|
Requires-Dist: gitignore-parser<0.2,>=0.1.11
|
|
18
17
|
Requires-Dist: gql[httpx,websockets]<4,>=3.5.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
exponent/__init__.py,sha256=
|
|
1
|
+
exponent/__init__.py,sha256=W4xwjAPdDCDNl1Z1bnYJwDlxi1NKhql6yqsZmX7rk_A,58
|
|
2
2
|
exponent/cli.py,sha256=9FPB5bqqGn7qVA_q2XZL6B2kRngVQoPdyvUvC5BH1_0,3496
|
|
3
3
|
exponent/py.typed,sha256=9XZl5avs8yHp89XP_1Fjtbeg_2rjYorCC9I0k_j-h2c,334
|
|
4
4
|
exponent/commands/cloud_commands.py,sha256=4DgS7PjCtCFB5uNN-szzAzOj16UU1D9b9_qS7DskoLE,2026
|
|
@@ -23,18 +23,17 @@ exponent/core/graphql/mutations.py,sha256=WRwgJzMTETvry1yc9-EBlIRWkePjHIskBAm_6t
|
|
|
23
23
|
exponent/core/graphql/queries.py,sha256=TXXHLGb7QpeICaofowVYsjyHDfqjCoQ3omLbesuw06s,2612
|
|
24
24
|
exponent/core/graphql/subscriptions.py,sha256=gg42wG5HqEuNMJU7OUHruNCAGtM6FKPLRD7KfjcKjC4,9995
|
|
25
25
|
exponent/core/remote_execution/checkpoints.py,sha256=3QGYMLa8vT7XmxMYTRcGrW8kNGHwRC0AkUfULribJWg,6354
|
|
26
|
-
exponent/core/remote_execution/cli_rpc_types.py,sha256=
|
|
26
|
+
exponent/core/remote_execution/cli_rpc_types.py,sha256=3Yj6kIkqPAf7FNNni5V4XNe8SLPoTgbcL6swesW7cw4,4593
|
|
27
27
|
exponent/core/remote_execution/client.py,sha256=3QbSAsukuVHCwmGfkoZBaBwgy4DuRZQs7LGAJtmT068,21010
|
|
28
28
|
exponent/core/remote_execution/code_execution.py,sha256=jYPB_7dJzS9BTPLX9fKQpsFPatwjbXuaFFSxT9tDTfI,2388
|
|
29
|
-
exponent/core/remote_execution/command_execution.py,sha256=HC9NXJg1R2sq1-Co1_paCrYnGn06rb_kTh5APG_B39Y,3672
|
|
30
29
|
exponent/core/remote_execution/error_info.py,sha256=Rd7OA3ps06qYejPVcOaMBB9AtftP3wqQoOfiILFASnc,1378
|
|
31
30
|
exponent/core/remote_execution/exceptions.py,sha256=eT57lBnBhvh-KJ5lsKWcfgGA5-WisAxhjZx-Z6OupZY,135
|
|
32
31
|
exponent/core/remote_execution/file_write.py,sha256=j9X4QfCBuZK6VIMfeu53WTN90G4w0AtN4U9GcoCJvJk,12531
|
|
33
|
-
exponent/core/remote_execution/files.py,sha256=
|
|
32
|
+
exponent/core/remote_execution/files.py,sha256=0EmOP2OdreGHjkKEIhtB_nNcjvLLx_UJWbbxt7cGSNg,12225
|
|
34
33
|
exponent/core/remote_execution/git.py,sha256=Yo4mhkl6LYzGhVco91j_E8WOUey5KL9437rk43VCCA8,7826
|
|
35
34
|
exponent/core/remote_execution/session.py,sha256=cSJcCG1o74mBE6lZS_9VFmhyZdW6BeIOsbq4IVWH0t4,3863
|
|
36
35
|
exponent/core/remote_execution/system_context.py,sha256=0FkbsSxEVjdjTF0tQpOkYK_VaVM126C3_K8QP0YXxOs,1510
|
|
37
|
-
exponent/core/remote_execution/tool_execution.py,sha256=
|
|
36
|
+
exponent/core/remote_execution/tool_execution.py,sha256=G7wB_DA0jANqywhm_a6lbWtwjCcpQsuQHlExGohsgeY,9233
|
|
38
37
|
exponent/core/remote_execution/truncation.py,sha256=rFQDfT7qf_u6lvhEADWSpoRe_GTPegXXqknk7OZp0uI,10093
|
|
39
38
|
exponent/core/remote_execution/types.py,sha256=G-5EU-NtIj_zZbV305YMDZEcSacGK7QfzEdCYSHAGmA,17206
|
|
40
39
|
exponent/core/remote_execution/utils.py,sha256=Hw2zGMq0NKVwkVzNOVekAvpM33rfIz2P36mEcJr43Ag,20688
|
|
@@ -50,7 +49,7 @@ exponent/migration-docs/login.md,sha256=KIeXy3m2nzSUgw-4PW1XzXfHael1D4Zu93CplLMb
|
|
|
50
49
|
exponent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
50
|
exponent/utils/colors.py,sha256=HBkqe_ZmhJ9YiL2Fpulqek4KvLS5mwBTY4LQSM5N8SM,2762
|
|
52
51
|
exponent/utils/version.py,sha256=Q4txP7Rg_KO0u0tUpx8O0DoOt32wrX7ctNeDXVKaOfA,8835
|
|
53
|
-
indent-0.
|
|
54
|
-
indent-0.
|
|
55
|
-
indent-0.
|
|
56
|
-
indent-0.
|
|
52
|
+
indent-0.1.2.dist-info/METADATA,sha256=PHb_HZsTkfwbzHsnR5fo5P-iyi7JxA-T9VRuf_D1C5g,1283
|
|
53
|
+
indent-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
54
|
+
indent-0.1.2.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
|
|
55
|
+
indent-0.1.2.dist-info/RECORD,,
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from exponent.core.remote_execution import files
|
|
5
|
-
from exponent.core.remote_execution.types import (
|
|
6
|
-
CommandRequest,
|
|
7
|
-
CommandResponse,
|
|
8
|
-
)
|
|
9
|
-
from exponent.core.types.command_data import (
|
|
10
|
-
FileReadCommandData,
|
|
11
|
-
PrototypeCommandData,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
# Intentionally split the separator into two parts
|
|
15
|
-
# to avoid matching it in the content
|
|
16
|
-
CONTEXT_BATCH_SEPARATOR = "\n<batch_sep" + "arator>\n"
|
|
17
|
-
CONTEXT_FILE_SEPARATOR = "\n<file_sep" + "arator>\n"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
async def execute_command(
|
|
21
|
-
request: CommandRequest,
|
|
22
|
-
working_directory: str,
|
|
23
|
-
) -> CommandResponse:
|
|
24
|
-
try:
|
|
25
|
-
if isinstance(request.data, FileReadCommandData):
|
|
26
|
-
correlation_id = request.correlation_id
|
|
27
|
-
file_path = request.data.file_path
|
|
28
|
-
path = Path(working_directory, file_path)
|
|
29
|
-
content, _ = await files.get_file_content(
|
|
30
|
-
path, request.data.offset, request.data.limit
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
return CommandResponse(
|
|
34
|
-
subcommand=request.data.type.value,
|
|
35
|
-
content=content,
|
|
36
|
-
correlation_id=correlation_id,
|
|
37
|
-
)
|
|
38
|
-
elif isinstance(request.data, PrototypeCommandData):
|
|
39
|
-
correlation_id = request.correlation_id
|
|
40
|
-
command_name = request.data.command_name
|
|
41
|
-
content_json = request.data.content_json
|
|
42
|
-
content_raw = request.data.content_raw
|
|
43
|
-
content_rendered = request.data.content_rendered
|
|
44
|
-
|
|
45
|
-
content = await execute_prototype_command(
|
|
46
|
-
command_name=command_name,
|
|
47
|
-
content_json=content_json,
|
|
48
|
-
content_raw=content_raw,
|
|
49
|
-
content_rendered=content_rendered,
|
|
50
|
-
working_directory=working_directory,
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
return CommandResponse(
|
|
54
|
-
subcommand=command_name,
|
|
55
|
-
content=content,
|
|
56
|
-
correlation_id=correlation_id,
|
|
57
|
-
)
|
|
58
|
-
else:
|
|
59
|
-
raise ValueError(f"Unknown command request: {request}")
|
|
60
|
-
except Exception as e: # noqa: BLE001 - TODO (Josh): Specialize errors for execution
|
|
61
|
-
return CommandResponse(
|
|
62
|
-
content="An error occurred during command execution: " + str(e),
|
|
63
|
-
correlation_id=request.correlation_id,
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
async def execute_prototype_command(
|
|
68
|
-
command_name: str,
|
|
69
|
-
content_json: dict[str, Any],
|
|
70
|
-
content_raw: str,
|
|
71
|
-
content_rendered: str,
|
|
72
|
-
working_directory: str,
|
|
73
|
-
) -> str:
|
|
74
|
-
if command_name == "file_open":
|
|
75
|
-
return f'Successfully opened file "{content_json["file_path"]}"'
|
|
76
|
-
elif command_name == "search_files":
|
|
77
|
-
results = await files.search_files(
|
|
78
|
-
path_str=content_json["path"],
|
|
79
|
-
file_pattern=content_json["file_pattern"],
|
|
80
|
-
regex=content_json["regex"],
|
|
81
|
-
working_directory=working_directory,
|
|
82
|
-
)
|
|
83
|
-
return "\n".join(results)
|
|
84
|
-
elif command_name == "codebase_context":
|
|
85
|
-
batches = await files.get_all_file_contents(
|
|
86
|
-
working_directory=working_directory,
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
return CONTEXT_BATCH_SEPARATOR.join(
|
|
90
|
-
CONTEXT_FILE_SEPARATOR.join(batch) for batch in batches
|
|
91
|
-
)
|
|
92
|
-
elif command_name == "ls":
|
|
93
|
-
results = await files.file_walk(
|
|
94
|
-
directory=content_json["path"],
|
|
95
|
-
ignore_extra=files.DEFAULT_IGNORES,
|
|
96
|
-
max_files=1000,
|
|
97
|
-
)
|
|
98
|
-
return "\n".join(results)
|
|
99
|
-
elif command_name == "glob":
|
|
100
|
-
results = await files.glob(
|
|
101
|
-
path=content_json["path"],
|
|
102
|
-
glob_pattern=content_json["glob"],
|
|
103
|
-
)
|
|
104
|
-
return "\n".join(results)
|
|
105
|
-
raise ValueError(f"Unhandled prototype command: {command_name}")
|
|
File without changes
|
|
File without changes
|