indent 0.1.7__py3-none-any.whl → 0.1.9__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 +21 -1
- exponent/cli.py +8 -10
- exponent/commands/config_commands.py +10 -10
- exponent/commands/run_commands.py +1 -1
- exponent/commands/upgrade.py +3 -3
- exponent/commands/utils.py +0 -90
- exponent/commands/workflow_commands.py +1 -1
- exponent/core/config.py +2 -0
- exponent/core/graphql/queries.py +13 -0
- exponent/core/graphql/subscriptions.py +13 -0
- exponent/core/remote_execution/cli_rpc_types.py +25 -1
- exponent/core/remote_execution/client.py +79 -1
- exponent/core/remote_execution/files.py +0 -12
- exponent/core/remote_execution/http_fetch.py +23 -15
- exponent/core/remote_execution/system_context.py +0 -27
- exponent/core/remote_execution/types.py +0 -50
- exponent/core/remote_execution/utils.py +3 -98
- {indent-0.1.7.dist-info → indent-0.1.9.dist-info}/METADATA +2 -2
- {indent-0.1.7.dist-info → indent-0.1.9.dist-info}/RECORD +21 -25
- exponent/commands/github_app_commands.py +0 -211
- exponent/commands/listen_commands.py +0 -96
- exponent/commands/shell_commands.py +0 -2840
- exponent/commands/theme.py +0 -246
- {indent-0.1.7.dist-info → indent-0.1.9.dist-info}/WHEEL +0 -0
- {indent-0.1.7.dist-info → indent-0.1.9.dist-info}/entry_points.txt +0 -0
|
@@ -7,26 +7,10 @@ from anyio import Path as AsyncPath
|
|
|
7
7
|
from exponent.core.remote_execution.git import get_git_info
|
|
8
8
|
from exponent.core.remote_execution.languages import python_execution
|
|
9
9
|
from exponent.core.remote_execution.types import (
|
|
10
|
-
SystemContextRequest,
|
|
11
|
-
SystemContextResponse,
|
|
12
10
|
SystemInfo,
|
|
13
11
|
)
|
|
14
12
|
from exponent.core.remote_execution.utils import safe_read_file
|
|
15
13
|
|
|
16
|
-
EXPONENT_TXT_FILENAMES = [
|
|
17
|
-
"exponent.txt",
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
async def get_system_context(
|
|
22
|
-
request: SystemContextRequest, working_directory: str
|
|
23
|
-
) -> SystemContextResponse:
|
|
24
|
-
return SystemContextResponse(
|
|
25
|
-
correlation_id=request.correlation_id,
|
|
26
|
-
exponent_txt=await _read_exponent_txt(working_directory),
|
|
27
|
-
system_info=await get_system_info(working_directory),
|
|
28
|
-
)
|
|
29
|
-
|
|
30
14
|
|
|
31
15
|
async def get_system_info(working_directory: str) -> SystemInfo:
|
|
32
16
|
return SystemInfo(
|
|
@@ -39,16 +23,5 @@ async def get_system_info(working_directory: str) -> SystemInfo:
|
|
|
39
23
|
)
|
|
40
24
|
|
|
41
25
|
|
|
42
|
-
async def _read_exponent_txt(working_directory: str) -> str | None:
|
|
43
|
-
for filename in EXPONENT_TXT_FILENAMES:
|
|
44
|
-
file_path = AsyncPath(os.path.join(working_directory, filename.lower()))
|
|
45
|
-
exists = await file_path.exists()
|
|
46
|
-
|
|
47
|
-
if exists:
|
|
48
|
-
return await safe_read_file(file_path)
|
|
49
|
-
|
|
50
|
-
return None
|
|
51
|
-
|
|
52
|
-
|
|
53
26
|
def _get_user_shell() -> str:
|
|
54
27
|
return os.environ.get("SHELL", "bash")
|
|
@@ -229,10 +229,6 @@ Namespace = Literal[
|
|
|
229
229
|
"get_file_attachment",
|
|
230
230
|
"get_file_attachments",
|
|
231
231
|
"get_matching_files",
|
|
232
|
-
"system_context",
|
|
233
|
-
"get_all_tracked_files",
|
|
234
|
-
"halt",
|
|
235
|
-
"switch_cli_chat",
|
|
236
232
|
"error",
|
|
237
233
|
"create_checkpoint",
|
|
238
234
|
"rollback_to_checkpoint",
|
|
@@ -355,27 +351,6 @@ class GetMatchingFilesResponse(RemoteExecutionResponse):
|
|
|
355
351
|
files: list[RemoteFile]
|
|
356
352
|
|
|
357
353
|
|
|
358
|
-
class GetAllTrackedFilesResponse(RemoteExecutionResponse):
|
|
359
|
-
namespace: ClassVar[Namespace] = "get_all_tracked_files"
|
|
360
|
-
|
|
361
|
-
files: list[RemoteFile]
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
class SystemContextResponse(RemoteExecutionResponse):
|
|
365
|
-
namespace: ClassVar[Namespace] = "system_context"
|
|
366
|
-
|
|
367
|
-
exponent_txt: str | None
|
|
368
|
-
system_info: SystemInfo | None
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
class HaltResponse(RemoteExecutionResponse):
|
|
372
|
-
namespace: ClassVar[Namespace] = "halt"
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
class SwitchCLIChatResponse(RemoteExecutionResponse):
|
|
376
|
-
namespace: ClassVar[Namespace] = "switch_cli_chat"
|
|
377
|
-
|
|
378
|
-
|
|
379
354
|
class ErrorResponse(RemoteExecutionResponse):
|
|
380
355
|
namespace: ClassVar[Namespace] = "error"
|
|
381
356
|
# The namespace of the request that caused the error.
|
|
@@ -460,15 +435,6 @@ class StreamingCodeExecutionRequest(
|
|
|
460
435
|
timeout: int
|
|
461
436
|
|
|
462
437
|
|
|
463
|
-
class HaltRequest(RemoteExecutionRequest[HaltResponse]):
|
|
464
|
-
namespace: ClassVar[Namespace] = "halt"
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
class SwitchCLIChatRequest(RemoteExecutionRequest[SwitchCLIChatResponse]):
|
|
468
|
-
namespace: ClassVar[Namespace] = "switch_cli_chat"
|
|
469
|
-
new_chat_uuid: str
|
|
470
|
-
|
|
471
|
-
|
|
472
438
|
class FileWriteRequest(RemoteExecutionRequest[FileWriteResponse]):
|
|
473
439
|
namespace: ClassVar[Namespace] = "file_write"
|
|
474
440
|
|
|
@@ -504,14 +470,6 @@ class GetMatchingFilesRequest(RemoteExecutionRequest[GetMatchingFilesResponse]):
|
|
|
504
470
|
search_term: str
|
|
505
471
|
|
|
506
472
|
|
|
507
|
-
class GetAllTrackedFilesRequest(RemoteExecutionRequest[GetAllTrackedFilesResponse]):
|
|
508
|
-
namespace: ClassVar[Namespace] = "get_all_tracked_files"
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
class SystemContextRequest(RemoteExecutionRequest[SystemContextResponse]):
|
|
512
|
-
namespace: ClassVar[Namespace] = "system_context"
|
|
513
|
-
|
|
514
|
-
|
|
515
473
|
class CreateCheckpointRequest(RemoteExecutionRequest[CreateCheckpointResponse]):
|
|
516
474
|
namespace: ClassVar[Namespace] = "create_checkpoint"
|
|
517
475
|
|
|
@@ -557,12 +515,8 @@ RemoteExecutionRequestType = Union[
|
|
|
557
515
|
GetFileAttachmentRequest,
|
|
558
516
|
GetFileAttachmentsRequest,
|
|
559
517
|
GetMatchingFilesRequest,
|
|
560
|
-
SystemContextRequest,
|
|
561
|
-
GetAllTrackedFilesRequest,
|
|
562
518
|
CommandRequest,
|
|
563
|
-
HaltRequest,
|
|
564
519
|
StreamingCodeExecutionRequest,
|
|
565
|
-
SwitchCLIChatRequest,
|
|
566
520
|
CreateCheckpointRequest,
|
|
567
521
|
RollbackToCheckpointRequest,
|
|
568
522
|
]
|
|
@@ -576,11 +530,7 @@ RemoteExecutionResponseType = Union[
|
|
|
576
530
|
GetFileAttachmentResponse,
|
|
577
531
|
GetFileAttachmentsResponse,
|
|
578
532
|
GetMatchingFilesResponse,
|
|
579
|
-
GetAllTrackedFilesResponse,
|
|
580
|
-
SystemContextResponse,
|
|
581
533
|
CommandResponse,
|
|
582
|
-
HaltResponse,
|
|
583
|
-
SwitchCLIChatResponse,
|
|
584
534
|
ErrorResponse,
|
|
585
535
|
CreateCheckpointResponse,
|
|
586
536
|
RollbackToCheckpointResponse,
|
|
@@ -35,16 +35,12 @@ from exponent.core.remote_execution.types import (
|
|
|
35
35
|
FilePath,
|
|
36
36
|
FileWriteRequest,
|
|
37
37
|
FileWriteResponse,
|
|
38
|
-
GetAllTrackedFilesRequest,
|
|
39
|
-
GetAllTrackedFilesResponse,
|
|
40
38
|
GetFileAttachmentRequest,
|
|
41
39
|
GetFileAttachmentResponse,
|
|
42
40
|
GetFileAttachmentsRequest,
|
|
43
41
|
GetFileAttachmentsResponse,
|
|
44
42
|
GetMatchingFilesRequest,
|
|
45
43
|
GetMatchingFilesResponse,
|
|
46
|
-
HaltRequest,
|
|
47
|
-
HaltResponse,
|
|
48
44
|
ListFilesRequest,
|
|
49
45
|
ListFilesResponse,
|
|
50
46
|
RemoteExecutionMessage,
|
|
@@ -61,10 +57,6 @@ from exponent.core.remote_execution.types import (
|
|
|
61
57
|
StreamingCodeExecutionResponse,
|
|
62
58
|
StreamingCodeExecutionResponseChunk,
|
|
63
59
|
SupportedLanguage,
|
|
64
|
-
SwitchCLIChatRequest,
|
|
65
|
-
SwitchCLIChatResponse,
|
|
66
|
-
SystemContextRequest,
|
|
67
|
-
SystemContextResponse,
|
|
68
60
|
)
|
|
69
61
|
from exponent.core.types.command_data import NaturalEditContent
|
|
70
62
|
from exponent.core.types.event_types import (
|
|
@@ -78,82 +70,6 @@ from exponent.utils.version import get_installed_version
|
|
|
78
70
|
### Serde
|
|
79
71
|
|
|
80
72
|
|
|
81
|
-
def deserialize_message_data(
|
|
82
|
-
message_data: RemoteExecutionMessageData | str,
|
|
83
|
-
) -> RemoteExecutionMessage:
|
|
84
|
-
if isinstance(message_data, str):
|
|
85
|
-
message_data = RemoteExecutionMessageData.model_validate_json(message_data)
|
|
86
|
-
if message_data.direction == "request":
|
|
87
|
-
return deserialize_request_data(cast(RemoteExecutionRequestData, message_data))
|
|
88
|
-
elif message_data.direction == "response":
|
|
89
|
-
return deserialize_response_data(
|
|
90
|
-
cast(RemoteExecutionResponseData, message_data)
|
|
91
|
-
)
|
|
92
|
-
else:
|
|
93
|
-
# type checking trick, if you miss a namespace then
|
|
94
|
-
# this won't typecheck due to the input parameter
|
|
95
|
-
# having a potential type other than no-return
|
|
96
|
-
assert_unreachable(message_data.direction)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def deserialize_request_data(
|
|
100
|
-
request_data: RemoteExecutionRequestData | str,
|
|
101
|
-
) -> RemoteExecutionRequestType:
|
|
102
|
-
request: RemoteExecutionRequestType
|
|
103
|
-
if isinstance(request_data, str):
|
|
104
|
-
request_data = RemoteExecutionRequestData.model_validate_json(request_data)
|
|
105
|
-
if request_data.direction != "request":
|
|
106
|
-
raise ValueError(f"Expected request, but got {request_data.direction}")
|
|
107
|
-
if request_data.namespace == "code_execution":
|
|
108
|
-
request = CodeExecutionRequest.model_validate_json(request_data.message_data)
|
|
109
|
-
elif request_data.namespace == "file_write":
|
|
110
|
-
request = FileWriteRequest.model_validate_json(request_data.message_data)
|
|
111
|
-
elif request_data.namespace == "list_files":
|
|
112
|
-
request = ListFilesRequest.model_validate_json(request_data.message_data)
|
|
113
|
-
elif request_data.namespace == "get_file_attachment":
|
|
114
|
-
request = GetFileAttachmentRequest.model_validate_json(
|
|
115
|
-
request_data.message_data
|
|
116
|
-
)
|
|
117
|
-
elif request_data.namespace == "get_file_attachments":
|
|
118
|
-
request = GetFileAttachmentsRequest.model_validate_json(
|
|
119
|
-
request_data.message_data
|
|
120
|
-
)
|
|
121
|
-
elif request_data.namespace == "get_matching_files":
|
|
122
|
-
request = GetMatchingFilesRequest.model_validate_json(request_data.message_data)
|
|
123
|
-
elif request_data.namespace == "system_context":
|
|
124
|
-
request = SystemContextRequest.model_validate_json(request_data.message_data)
|
|
125
|
-
elif request_data.namespace == "get_all_tracked_files":
|
|
126
|
-
request = GetAllTrackedFilesRequest.model_validate_json(
|
|
127
|
-
request_data.message_data
|
|
128
|
-
)
|
|
129
|
-
elif request_data.namespace == "command":
|
|
130
|
-
request = CommandRequest.model_validate_json(request_data.message_data)
|
|
131
|
-
elif request_data.namespace == "halt":
|
|
132
|
-
request = HaltRequest.model_validate_json(request_data.message_data)
|
|
133
|
-
elif request_data.namespace == "streaming_code_execution":
|
|
134
|
-
request = StreamingCodeExecutionRequest.model_validate_json(
|
|
135
|
-
request_data.message_data
|
|
136
|
-
)
|
|
137
|
-
elif request_data.namespace == "switch_cli_chat":
|
|
138
|
-
request = SwitchCLIChatRequest.model_validate_json(request_data.message_data)
|
|
139
|
-
elif request_data.namespace == "streaming_code_execution_chunk":
|
|
140
|
-
assert False, "Streaming code execution chunk is a response, not a request"
|
|
141
|
-
elif request_data.namespace == "error":
|
|
142
|
-
assert False, "Error is a response, not a request"
|
|
143
|
-
elif request_data.namespace == "create_checkpoint":
|
|
144
|
-
request = CreateCheckpointRequest.model_validate_json(request_data.message_data)
|
|
145
|
-
elif request_data.namespace == "rollback_to_checkpoint":
|
|
146
|
-
request = RollbackToCheckpointRequest.model_validate_json(
|
|
147
|
-
request_data.message_data
|
|
148
|
-
)
|
|
149
|
-
else:
|
|
150
|
-
# type checking trick, if you miss a namespace then
|
|
151
|
-
# this won't typecheck due to the input parameter
|
|
152
|
-
# having a potential type other than no-return
|
|
153
|
-
request = assert_unreachable(request_data.namespace)
|
|
154
|
-
return truncate_message(request)
|
|
155
|
-
|
|
156
|
-
|
|
157
73
|
def deserialize_response_data(
|
|
158
74
|
response_data: RemoteExecutionResponseData | str,
|
|
159
75
|
) -> RemoteExecutionResponseType:
|
|
@@ -188,18 +104,9 @@ def deserialize_response_data(
|
|
|
188
104
|
response = GetFileAttachmentsResponse.model_validate_json(
|
|
189
105
|
response_data.message_data
|
|
190
106
|
)
|
|
191
|
-
|
|
192
|
-
response = SystemContextResponse.model_validate_json(response_data.message_data)
|
|
193
|
-
elif response_data.namespace == "get_all_tracked_files":
|
|
194
|
-
response = GetAllTrackedFilesResponse.model_validate_json(
|
|
195
|
-
response_data.message_data
|
|
196
|
-
)
|
|
107
|
+
|
|
197
108
|
elif response_data.namespace == "command":
|
|
198
109
|
response = CommandResponse.model_validate_json(response_data.message_data)
|
|
199
|
-
elif response_data.namespace == "halt":
|
|
200
|
-
response = HaltResponse.model_validate_json(response_data.message_data)
|
|
201
|
-
elif response_data.namespace == "switch_cli_chat":
|
|
202
|
-
response = SwitchCLIChatResponse.model_validate_json(response_data.message_data)
|
|
203
110
|
elif response_data.namespace == "error":
|
|
204
111
|
response = ErrorResponse.model_validate_json(response_data.message_data)
|
|
205
112
|
elif response_data.namespace == "create_checkpoint":
|
|
@@ -424,10 +331,8 @@ def truncate_message(response: GetMatchingFilesRequest) -> GetMatchingFilesReque
|
|
|
424
331
|
def truncate_message(
|
|
425
332
|
response: GetMatchingFilesResponse,
|
|
426
333
|
) -> GetMatchingFilesResponse: ...
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
@overload
|
|
430
|
-
def truncate_message(response: SystemContextResponse) -> SystemContextResponse: ...
|
|
334
|
+
|
|
335
|
+
|
|
431
336
|
@overload
|
|
432
337
|
def truncate_message(
|
|
433
338
|
response: RemoteExecutionRequestType,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: indent
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
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
|
|
@@ -15,7 +15,7 @@ Requires-Dist: eval-type-backport<0.3,>=0.2.0
|
|
|
15
15
|
Requires-Dist: git-python>=1.0.3
|
|
16
16
|
Requires-Dist: gitignore-parser<0.2,>=0.1.11
|
|
17
17
|
Requires-Dist: gql[httpx,websockets]<4,>=3.5.0
|
|
18
|
-
Requires-Dist: httpx
|
|
18
|
+
Requires-Dist: httpx>=0.28.1
|
|
19
19
|
Requires-Dist: ipykernel<7,>=6.29.4
|
|
20
20
|
Requires-Dist: jupyter-client<9,>=8.6.1
|
|
21
21
|
Requires-Dist: msgspec>=0.19.0
|
|
@@ -1,44 +1,40 @@
|
|
|
1
|
-
exponent/__init__.py,sha256=
|
|
2
|
-
exponent/cli.py,sha256=
|
|
1
|
+
exponent/__init__.py,sha256=bhntibG3PKk5Ai3XlSNEV8gj-ffItuKloY6vzWn6swo,511
|
|
2
|
+
exponent/cli.py,sha256=u3hhZnn5uqVXyNz6wU8j4U5vLJ--pbA-PweHhpvRzY4,3444
|
|
3
3
|
exponent/py.typed,sha256=9XZl5avs8yHp89XP_1Fjtbeg_2rjYorCC9I0k_j-h2c,334
|
|
4
4
|
exponent/commands/cloud_commands.py,sha256=4DgS7PjCtCFB5uNN-szzAzOj16UU1D9b9_qS7DskoLE,2026
|
|
5
5
|
exponent/commands/common.py,sha256=HUzc9yl5L6GZEF5DDsF3IeArwPKrghxmK43vxtkxgGs,13679
|
|
6
|
-
exponent/commands/config_commands.py,sha256=
|
|
7
|
-
exponent/commands/
|
|
8
|
-
exponent/commands/listen_commands.py,sha256=Zh_3HWZ7u0m9T6BIqocMUZzSvg-tJcMuvFYDM1yoAE4,3201
|
|
9
|
-
exponent/commands/run_commands.py,sha256=jxZp4F-RNTZbhD6-tIcyxAUDbpUSfaTX-X1Q7hyC_Q0,5857
|
|
6
|
+
exponent/commands/config_commands.py,sha256=5xIWMVMBoY2-90gEe61DzIuvpT5_r0r91jpgDLeb-AU,15959
|
|
7
|
+
exponent/commands/run_commands.py,sha256=syuC_YUFSz57eT7Rl0aFiIfogINmiAvmenLClnogWQU,5865
|
|
10
8
|
exponent/commands/settings.py,sha256=UwwwoCgCY5hzAFD9slOBbA9Gr1hNfoyJ2blsFDC6V8w,1559
|
|
11
|
-
exponent/commands/shell_commands.py,sha256=bh6Ni4Lu5KsrWBqpV_GFrPJKta6F7RrgHNqRUqvsEVk,93892
|
|
12
|
-
exponent/commands/theme.py,sha256=XoX9lYDf8YyoU1HoRdctDHjK5MrMRUcBALBLcHDVPc8,8111
|
|
13
9
|
exponent/commands/types.py,sha256=iDJL3hdwhO1PrhsJTJBioNYSKo0CWV8Nv-ONcDaWIRs,3670
|
|
14
|
-
exponent/commands/upgrade.py,sha256=
|
|
15
|
-
exponent/commands/utils.py,sha256=
|
|
16
|
-
exponent/commands/workflow_commands.py,sha256=
|
|
17
|
-
exponent/core/config.py,sha256=
|
|
10
|
+
exponent/commands/upgrade.py,sha256=JZr0sNazziuLByQHdT8GZb-lDbRG1YpHW8VB94q-r8w,803
|
|
11
|
+
exponent/commands/utils.py,sha256=c8KO1EjfwmEVXAKIvKSuJE_nl338q8fLSNKxuxQSyAY,4624
|
|
12
|
+
exponent/commands/workflow_commands.py,sha256=1IZCw_EWkpLHF3urOR5kwYyfHWQrjBbaih8FRu6hPW8,3591
|
|
13
|
+
exponent/core/config.py,sha256=faWzY3wZ8MF8BmeZ7mOZbuDDRs3ShVeSDPe2OH2nrI0,5748
|
|
18
14
|
exponent/core/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
15
|
exponent/core/graphql/client.py,sha256=KRveVt4lsrSdF9PnhhlQeqx74FQ9-iN28WQp0WKnQ30,1921
|
|
20
16
|
exponent/core/graphql/cloud_config_queries.py,sha256=Xy8SRP-sfWFcaq33hF-Ni1KwZDU4AdkkGbntsOxYytA,1968
|
|
21
17
|
exponent/core/graphql/get_chats_query.py,sha256=9-2N1VfapXUZB3IFIKw5U_gKdmfyviJp5JSUntB_Yyk,1177
|
|
22
18
|
exponent/core/graphql/github_config_queries.py,sha256=zKRDxF38q73apQcVaEAA_A20FVr3U0ADc5-8Y6Ns5Dw,1260
|
|
23
19
|
exponent/core/graphql/mutations.py,sha256=WRwgJzMTETvry1yc9-EBlIRWkePjHIskBAm_6tEiRaU,1352
|
|
24
|
-
exponent/core/graphql/queries.py,sha256=
|
|
25
|
-
exponent/core/graphql/subscriptions.py,sha256=
|
|
20
|
+
exponent/core/graphql/queries.py,sha256=AJgDM1qc2_Zo0DhLqbogVTVokrzjfqhwhUz0SCdrKNI,2943
|
|
21
|
+
exponent/core/graphql/subscriptions.py,sha256=qDlWQsaY0F4lUaHEAeAa02iuKpUfml4I6kD9HMKGe1E,10301
|
|
26
22
|
exponent/core/remote_execution/checkpoints.py,sha256=3QGYMLa8vT7XmxMYTRcGrW8kNGHwRC0AkUfULribJWg,6354
|
|
27
|
-
exponent/core/remote_execution/cli_rpc_types.py,sha256=
|
|
28
|
-
exponent/core/remote_execution/client.py,sha256=
|
|
23
|
+
exponent/core/remote_execution/cli_rpc_types.py,sha256=ZokZXSMYGqJJX9fqzzoXJx9ElZjg6wOUl8dT9QMJQ9Y,5793
|
|
24
|
+
exponent/core/remote_execution/client.py,sha256=gSnR3vJ7HCovZN1cvwFD-PNsS7syWE4WAYK3ibJ3M-U,25586
|
|
29
25
|
exponent/core/remote_execution/code_execution.py,sha256=jYPB_7dJzS9BTPLX9fKQpsFPatwjbXuaFFSxT9tDTfI,2388
|
|
30
26
|
exponent/core/remote_execution/error_info.py,sha256=Rd7OA3ps06qYejPVcOaMBB9AtftP3wqQoOfiILFASnc,1378
|
|
31
27
|
exponent/core/remote_execution/exceptions.py,sha256=eT57lBnBhvh-KJ5lsKWcfgGA5-WisAxhjZx-Z6OupZY,135
|
|
32
28
|
exponent/core/remote_execution/file_write.py,sha256=j9X4QfCBuZK6VIMfeu53WTN90G4w0AtN4U9GcoCJvJk,12531
|
|
33
|
-
exponent/core/remote_execution/files.py,sha256=
|
|
29
|
+
exponent/core/remote_execution/files.py,sha256=ypqDuXhnANWMnwiYrw033oBSDaDT9v9J0jvdHesRw24,11868
|
|
34
30
|
exponent/core/remote_execution/git.py,sha256=Yo4mhkl6LYzGhVco91j_E8WOUey5KL9437rk43VCCA8,7826
|
|
35
|
-
exponent/core/remote_execution/http_fetch.py,sha256=
|
|
31
|
+
exponent/core/remote_execution/http_fetch.py,sha256=ZoQ2EcB1vQys-QmIbt1xC0ftyWkOIohxCfYNVYv4kF0,2856
|
|
36
32
|
exponent/core/remote_execution/session.py,sha256=cSJcCG1o74mBE6lZS_9VFmhyZdW6BeIOsbq4IVWH0t4,3863
|
|
37
|
-
exponent/core/remote_execution/system_context.py,sha256=
|
|
33
|
+
exponent/core/remote_execution/system_context.py,sha256=XBvWeLLsrfzdicYBMbIneOBlnelBMb2n-VpHw5q2kcA,749
|
|
38
34
|
exponent/core/remote_execution/tool_execution.py,sha256=_UQPyOTY49RQ70kfgnf03eev7c7lTWhFBC68cuifj2M,12354
|
|
39
35
|
exponent/core/remote_execution/truncation.py,sha256=rFQDfT7qf_u6lvhEADWSpoRe_GTPegXXqknk7OZp0uI,10093
|
|
40
|
-
exponent/core/remote_execution/types.py,sha256=
|
|
41
|
-
exponent/core/remote_execution/utils.py,sha256=
|
|
36
|
+
exponent/core/remote_execution/types.py,sha256=P1hlhg_cw6A0iplODzI2irs5f7k8zBYYGX4Xvs4-YC4,16212
|
|
37
|
+
exponent/core/remote_execution/utils.py,sha256=Jwn2f753WuyanceUQSyJypcplOlUrfPchebAy7ULoz8,15927
|
|
42
38
|
exponent/core/remote_execution/languages/python_execution.py,sha256=GcQU5PiAOUD9tUZDrSObgM3L7FjXMdzr4FQg6ts2XjY,7780
|
|
43
39
|
exponent/core/remote_execution/languages/shell_streaming.py,sha256=eSeHcK_unGpVRRdfgfwhml_tSlCo0VCeUEQY4zuMbDw,7372
|
|
44
40
|
exponent/core/remote_execution/languages/types.py,sha256=f7FjSRNRSga-ZaE3LddDhxCirUVjlSYMEdoskG6Pta4,314
|
|
@@ -51,7 +47,7 @@ exponent/migration-docs/login.md,sha256=KIeXy3m2nzSUgw-4PW1XzXfHael1D4Zu93CplLMb
|
|
|
51
47
|
exponent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
48
|
exponent/utils/colors.py,sha256=HBkqe_ZmhJ9YiL2Fpulqek4KvLS5mwBTY4LQSM5N8SM,2762
|
|
53
49
|
exponent/utils/version.py,sha256=Q4txP7Rg_KO0u0tUpx8O0DoOt32wrX7ctNeDXVKaOfA,8835
|
|
54
|
-
indent-0.1.
|
|
55
|
-
indent-0.1.
|
|
56
|
-
indent-0.1.
|
|
57
|
-
indent-0.1.
|
|
50
|
+
indent-0.1.9.dist-info/METADATA,sha256=Rn7HmjV09LMsxtUQDO2X5vr7rfeWnDrIScyXtKs0ec4,1277
|
|
51
|
+
indent-0.1.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
52
|
+
indent-0.1.9.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
|
|
53
|
+
indent-0.1.9.dist-info/RECORD,,
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import json
|
|
3
|
-
import subprocess
|
|
4
|
-
import sys
|
|
5
|
-
import webbrowser
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from uuid import uuid4
|
|
8
|
-
|
|
9
|
-
import click
|
|
10
|
-
from git import GitCommandError, Repo
|
|
11
|
-
|
|
12
|
-
from exponent.commands.common import (
|
|
13
|
-
redirect_to_login,
|
|
14
|
-
verify_gh_app_installation,
|
|
15
|
-
)
|
|
16
|
-
from exponent.commands.settings import use_settings
|
|
17
|
-
from exponent.commands.types import exponent_cli_group
|
|
18
|
-
from exponent.core.config import Settings
|
|
19
|
-
from exponent.core.remote_execution.git import get_git_info
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@exponent_cli_group()
|
|
23
|
-
def github_app_cli() -> None:
|
|
24
|
-
"""Run AI-powered chat sessions."""
|
|
25
|
-
pass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@github_app_cli.command()
|
|
29
|
-
@use_settings
|
|
30
|
-
def install_github_app(
|
|
31
|
-
settings: Settings,
|
|
32
|
-
) -> None:
|
|
33
|
-
"""Start or reconnect to an Exponent session."""
|
|
34
|
-
if not settings.api_key:
|
|
35
|
-
redirect_to_login(settings)
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
loop = asyncio.get_event_loop()
|
|
39
|
-
|
|
40
|
-
api_key = settings.api_key
|
|
41
|
-
base_api_url = settings.get_base_api_url()
|
|
42
|
-
base_ws_url = settings.get_base_ws_url()
|
|
43
|
-
|
|
44
|
-
git_info = asyncio.run(get_git_info("."))
|
|
45
|
-
if not git_info:
|
|
46
|
-
raise RuntimeError("Not running inside of valid git repository")
|
|
47
|
-
|
|
48
|
-
install_url = "https://github.com/apps/indent/installations/new"
|
|
49
|
-
webbrowser.open(install_url)
|
|
50
|
-
|
|
51
|
-
click.confirm(
|
|
52
|
-
"Press enter once you've installed the github app.",
|
|
53
|
-
default=True,
|
|
54
|
-
abort=True,
|
|
55
|
-
prompt_suffix="",
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
click.secho("Verifying installation...", fg="yellow")
|
|
59
|
-
verified = loop.run_until_complete(
|
|
60
|
-
verify_gh_app_installation(api_key, base_api_url, base_ws_url, git_info)
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
if verified:
|
|
64
|
-
click.secho("Verified!", fg="green")
|
|
65
|
-
else:
|
|
66
|
-
click.secho("No verification found :(", fg="red")
|
|
67
|
-
sys.exit(1)
|
|
68
|
-
|
|
69
|
-
click.secho("Creating workflow file...", fg="yellow")
|
|
70
|
-
_create_workflow_yaml()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
WORKFLOW_YAML = """
|
|
74
|
-
name: Indent Action
|
|
75
|
-
|
|
76
|
-
on:
|
|
77
|
-
issue_comment:
|
|
78
|
-
types: [created]
|
|
79
|
-
pull_request_review_comment:
|
|
80
|
-
types: [created]
|
|
81
|
-
issues:
|
|
82
|
-
types: [opened, assigned]
|
|
83
|
-
pull_request_review:
|
|
84
|
-
types: [submitted]
|
|
85
|
-
|
|
86
|
-
jobs:
|
|
87
|
-
indent:
|
|
88
|
-
if: |
|
|
89
|
-
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@indent')) ||
|
|
90
|
-
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@indent')) ||
|
|
91
|
-
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@indent')) ||
|
|
92
|
-
(github.event_name == 'issues' && (contains(github.event.issue.body, '@indent') || contains(github.event.issue.title, '@indent')))
|
|
93
|
-
runs-on: ubuntu-latest
|
|
94
|
-
|
|
95
|
-
steps:
|
|
96
|
-
- name: Generate token for Indent app
|
|
97
|
-
id: generate_token
|
|
98
|
-
uses: actions/create-github-app-token@v1
|
|
99
|
-
with:
|
|
100
|
-
app-id: ${{ secrets.INDENT_APP_ID }}
|
|
101
|
-
private-key: ${{ secrets.INDENT_APP_PRIVATE_KEY }}
|
|
102
|
-
|
|
103
|
-
- name: Respond to mention
|
|
104
|
-
uses: actions/github-script@v7
|
|
105
|
-
with:
|
|
106
|
-
github-token: ${{ steps.generate_token.outputs.token }}
|
|
107
|
-
script: |
|
|
108
|
-
const issue_number = context.payload.issue?.number ||
|
|
109
|
-
context.payload.pull_request?.number ||
|
|
110
|
-
context.payload.review?.pull_request?.number;
|
|
111
|
-
|
|
112
|
-
await github.rest.issues.createComment({
|
|
113
|
-
owner: context.repo.owner,
|
|
114
|
-
repo: context.repo.repo,
|
|
115
|
-
issue_number: issue_number,
|
|
116
|
-
body: 'Hi it\'s me, Indent'
|
|
117
|
-
});
|
|
118
|
-
""".lstrip()
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _create_workflow_yaml() -> None:
|
|
122
|
-
git_branch = f"indent-workflow-{uuid4()}"
|
|
123
|
-
workflow_file = "indent-review.yml"
|
|
124
|
-
|
|
125
|
-
# 1. Locate the repository (searches upward until it finds .git).
|
|
126
|
-
repo = Repo(Path.cwd(), search_parent_directories=True)
|
|
127
|
-
if repo.bare or not repo.working_tree_dir:
|
|
128
|
-
sys.exit("Error: cannot operate inside a bare repository.")
|
|
129
|
-
|
|
130
|
-
original_branch = repo.active_branch.name if not repo.head.is_detached else None
|
|
131
|
-
|
|
132
|
-
# 2. Create or reuse the branch, then check it out.
|
|
133
|
-
try:
|
|
134
|
-
branch_ref = repo.create_head(git_branch)
|
|
135
|
-
except GitCommandError:
|
|
136
|
-
branch_ref = repo.heads[git_branch]
|
|
137
|
-
branch_ref.checkout()
|
|
138
|
-
|
|
139
|
-
# 3. Ensure workflow directory exists.
|
|
140
|
-
wf_dir = Path(repo.working_tree_dir) / ".github" / "workflows"
|
|
141
|
-
wf_dir.mkdir(parents=True, exist_ok=True)
|
|
142
|
-
|
|
143
|
-
yml = wf_dir / workflow_file
|
|
144
|
-
if not yml.exists():
|
|
145
|
-
yml.write_text(WORKFLOW_YAML)
|
|
146
|
-
# 5. Stage & commit.
|
|
147
|
-
repo.index.add([str(yml)])
|
|
148
|
-
repo.index.commit("Add Indent workflow template")
|
|
149
|
-
print(
|
|
150
|
-
f"Created {yml.relative_to(repo.working_tree_dir)} "
|
|
151
|
-
f"on branch '{git_branch}'."
|
|
152
|
-
)
|
|
153
|
-
else:
|
|
154
|
-
print(
|
|
155
|
-
f"{yml.relative_to(repo.working_tree_dir)} already exists; nothing to do."
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
subprocess.run(
|
|
159
|
-
["git", "push", "-u", "origin", git_branch],
|
|
160
|
-
cwd=repo.working_tree_dir,
|
|
161
|
-
check=True,
|
|
162
|
-
capture_output=False,
|
|
163
|
-
text=True,
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
pr_url: str | None = None
|
|
167
|
-
pr_title = f"Add Indent workflow ({workflow_file})"
|
|
168
|
-
pr_body = "This PR introduces an Indent github action workflow"
|
|
169
|
-
|
|
170
|
-
def run_gh(cmd: list[str]) -> subprocess.CompletedProcess[str]:
|
|
171
|
-
return subprocess.run(
|
|
172
|
-
["gh", *cmd],
|
|
173
|
-
cwd=repo.working_tree_dir,
|
|
174
|
-
check=True,
|
|
175
|
-
capture_output=True,
|
|
176
|
-
text=True,
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
try:
|
|
180
|
-
# Does a PR already exist for this head branch?
|
|
181
|
-
result = run_gh(["pr", "view", git_branch, "--json", "url"])
|
|
182
|
-
pr_url = json.loads(result.stdout)["url"]
|
|
183
|
-
except subprocess.CalledProcessError:
|
|
184
|
-
# No PR yet → create one
|
|
185
|
-
base = original_branch or repo.remotes.origin.refs[0].name.split("/")[-1]
|
|
186
|
-
run_gh(
|
|
187
|
-
[
|
|
188
|
-
"pr",
|
|
189
|
-
"create",
|
|
190
|
-
"--head",
|
|
191
|
-
git_branch,
|
|
192
|
-
"--base",
|
|
193
|
-
base,
|
|
194
|
-
"--title",
|
|
195
|
-
pr_title,
|
|
196
|
-
"--body",
|
|
197
|
-
pr_body,
|
|
198
|
-
]
|
|
199
|
-
)
|
|
200
|
-
# Fetch the newly created URL
|
|
201
|
-
result = run_gh(["pr", "view", git_branch, "--json", "url"])
|
|
202
|
-
pr_url = json.loads(result.stdout)["url"]
|
|
203
|
-
|
|
204
|
-
if pr_url:
|
|
205
|
-
click.secho(f"PR: {pr_url}", fg="green")
|
|
206
|
-
webbrowser.open(pr_url)
|
|
207
|
-
else:
|
|
208
|
-
click.secho("Failed to create PR!", fg="red")
|
|
209
|
-
|
|
210
|
-
if original_branch:
|
|
211
|
-
repo.git.checkout(original_branch)
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
from websockets.exceptions import ConnectionClosed
|
|
5
|
-
|
|
6
|
-
from exponent.commands.settings import use_settings
|
|
7
|
-
from exponent.commands.shell_commands import LiveView
|
|
8
|
-
from exponent.commands.theme import get_theme
|
|
9
|
-
from exponent.commands.types import exponent_cli_group
|
|
10
|
-
from exponent.core.config import Settings
|
|
11
|
-
from exponent.core.graphql.client import GraphQLClient
|
|
12
|
-
from exponent.core.graphql.subscriptions import INDENT_CHAT_EVENT_STREAM_SUBSCRIPTION
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@exponent_cli_group(hidden=True)
|
|
16
|
-
def listen_cli() -> None:
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@listen_cli.command()
|
|
21
|
-
@click.option("--chat-id", help="ID of the chat to listen to", required=True)
|
|
22
|
-
@click.option(
|
|
23
|
-
"--known-event-uuids",
|
|
24
|
-
help="Comma-separated list of known event UUIDs to skip",
|
|
25
|
-
default="",
|
|
26
|
-
)
|
|
27
|
-
@use_settings
|
|
28
|
-
def listen(settings: Settings, chat_id: str, known_event_uuids: str) -> None:
|
|
29
|
-
"""Listen to events from an indent chat session."""
|
|
30
|
-
api_key = settings.api_key
|
|
31
|
-
if not api_key:
|
|
32
|
-
raise click.UsageError("API key is not set")
|
|
33
|
-
|
|
34
|
-
base_api_url = settings.get_base_api_url()
|
|
35
|
-
base_ws_url = settings.get_base_ws_url()
|
|
36
|
-
|
|
37
|
-
gql_client = GraphQLClient(api_key, base_api_url, base_ws_url)
|
|
38
|
-
|
|
39
|
-
# Parse known event UUIDs
|
|
40
|
-
known_uuids = []
|
|
41
|
-
if known_event_uuids:
|
|
42
|
-
known_uuids = [
|
|
43
|
-
uuid.strip() for uuid in known_event_uuids.split(",") if uuid.strip()
|
|
44
|
-
]
|
|
45
|
-
|
|
46
|
-
# Set up the live view with theme
|
|
47
|
-
theme = get_theme(settings.options.use_default_colors)
|
|
48
|
-
live_view = LiveView(theme, render_user_messages=True)
|
|
49
|
-
|
|
50
|
-
asyncio.run(_listen(gql_client, chat_id, known_uuids, live_view))
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
async def _listen(
|
|
54
|
-
gql_client: GraphQLClient,
|
|
55
|
-
chat_id: str,
|
|
56
|
-
known_event_uuids: list[str],
|
|
57
|
-
live_view: LiveView,
|
|
58
|
-
) -> None:
|
|
59
|
-
"""Internal listen function that handles the WebSocket subscription."""
|
|
60
|
-
while True:
|
|
61
|
-
try:
|
|
62
|
-
variables = {
|
|
63
|
-
"chatUuid": chat_id,
|
|
64
|
-
"lastKnownFullEventUuid": known_event_uuids[-1]
|
|
65
|
-
if known_event_uuids
|
|
66
|
-
else None,
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async for response in gql_client.subscribe(
|
|
70
|
-
INDENT_CHAT_EVENT_STREAM_SUBSCRIPTION, variables
|
|
71
|
-
):
|
|
72
|
-
event = response["indentChatEventStream"]
|
|
73
|
-
kind = event["__typename"]
|
|
74
|
-
|
|
75
|
-
# Handle different event types
|
|
76
|
-
if kind in ["UserEvent", "AssistantEvent", "SystemEvent"]:
|
|
77
|
-
live_view.render_event(kind, event)
|
|
78
|
-
elif kind == "Error":
|
|
79
|
-
print(f"Error: {event.get('message', 'Unknown error')}")
|
|
80
|
-
elif kind == "UnauthenticatedError":
|
|
81
|
-
print(
|
|
82
|
-
f"Authentication error: {event.get('message', 'Unauthenticated')}"
|
|
83
|
-
)
|
|
84
|
-
break
|
|
85
|
-
else:
|
|
86
|
-
print(f"Unknown event type: {kind}")
|
|
87
|
-
|
|
88
|
-
except ConnectionClosed:
|
|
89
|
-
print("WebSocket disconnected, reconnecting...")
|
|
90
|
-
await asyncio.sleep(1)
|
|
91
|
-
except KeyboardInterrupt:
|
|
92
|
-
print("\nDisconnecting...")
|
|
93
|
-
break
|
|
94
|
-
except Exception as e:
|
|
95
|
-
print(f"Error: {e}")
|
|
96
|
-
await asyncio.sleep(1)
|