indent 0.1.6__py3-none-any.whl → 0.1.8__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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.6" # Keep in sync with pyproject.toml
1
+ __version__ = "0.1.8" # Keep in sync with pyproject.toml
@@ -15,6 +15,19 @@ EVENTS_FOR_CHAT_QUERY: str = """query EventsForChat($chatUuid: UUID!) {
15
15
  ... on TextMessage {
16
16
  text
17
17
  }
18
+ ... on ToolCallMessage {
19
+ messageId
20
+ toolUseId
21
+ toolName
22
+ toolInput {
23
+ ... on BashToolInput {
24
+ command
25
+ }
26
+ ... on ReadToolInput {
27
+ filePath
28
+ }
29
+ }
30
+ }
18
31
  ... on ToolResultMessage {
19
32
  messageId
20
33
  toolUseId
@@ -76,6 +76,19 @@ INDENT_EVENTS_SUBSCRIPTION = """
76
76
  content
77
77
  }
78
78
  }
79
+ }
80
+ ... on ToolCallMessage {
81
+ messageId
82
+ toolUseId
83
+ toolName
84
+ toolInput {
85
+ ... on BashToolInput {
86
+ command
87
+ }
88
+ ... on ReadToolInput {
89
+ filePath
90
+ }
91
+ }
79
92
  }
80
93
  ... on PartialToolResultMessage {
81
94
  messageId
@@ -1,5 +1,6 @@
1
1
  import msgspec
2
2
  import yaml
3
+ from typing import Any
3
4
 
4
5
 
5
6
  class PartialToolResult(msgspec.Struct, tag_field="tool_name", omit_defaults=True):
@@ -9,6 +10,17 @@ class PartialToolResult(msgspec.Struct, tag_field="tool_name", omit_defaults=Tru
9
10
  class ToolInput(msgspec.Struct, tag_field="tool_name", omit_defaults=True):
10
11
  """Concrete subclasses describe the full input schema for a tool."""
11
12
 
13
+ def to_llm(self) -> dict[str, Any]:
14
+ """Convert ToolInput to LLM-friendly typed dict format.
15
+
16
+ Returns a dictionary with the tool parameters, excluding the tool_name
17
+ which is handled separately by the LLM integration layer.
18
+
19
+ Returns:
20
+ self by default, which msgspec will serialize appropriately.
21
+ """
22
+ return msgspec.to_builtins(self) # type: ignore[no-any-return]
23
+
12
24
 
13
25
  class ToolResult(msgspec.Struct, tag_field="tool_name", omit_defaults=True):
14
26
  """Concrete subclasses return data from a tool execution."""
@@ -107,6 +119,7 @@ class GrepToolResult(ToolResult, tag=GREP_TOOL_NAME):
107
119
  EDIT_TOOL_NAME = "edit"
108
120
 
109
121
 
122
+ # This is only used in the CLI. The server side type is edit_tool.py
110
123
  class EditToolInput(ToolInput, tag=EDIT_TOOL_NAME):
111
124
  file_path: str
112
125
  old_string: str
@@ -139,6 +152,21 @@ class BashToolResult(ToolResult, tag=BASH_TOOL_NAME):
139
152
  stopped_by_user: bool
140
153
 
141
154
 
155
+ class HttpRequest(msgspec.Struct, tag="http_fetch_cli"):
156
+ url: str
157
+ method: str = "GET"
158
+ headers: dict[str, str] | None = None
159
+ timeout: int | None = None
160
+
161
+
162
+ class HttpResponse(msgspec.Struct, tag="http_fetch_cli"):
163
+ status_code: int | None = None
164
+ content: str | None = None
165
+ error_message: str | None = None
166
+ duration_ms: int | None = None
167
+ headers: dict[str, str] | None = None
168
+
169
+
142
170
  ToolInputType = (
143
171
  ReadToolInput
144
172
  | WriteToolInput
@@ -174,6 +202,10 @@ class TerminateRequest(msgspec.Struct, tag="terminate"):
174
202
  pass
175
203
 
176
204
 
205
+ class SwitchCLIChatRequest(msgspec.Struct, tag="switch_cli_chat"):
206
+ new_chat_uuid: str
207
+
208
+
177
209
  class BatchToolExecutionRequest(msgspec.Struct, tag="batch_tool_execution"):
178
210
  tool_inputs: list[ToolInputType]
179
211
 
@@ -190,13 +222,19 @@ class BatchToolExecutionResponse(msgspec.Struct, tag="batch_tool_execution"):
190
222
  tool_results: list[ToolResultType]
191
223
 
192
224
 
225
+ class SwitchCLIChatResponse(msgspec.Struct, tag="switch_cli_chat"):
226
+ pass
227
+
228
+
193
229
  class CliRpcRequest(msgspec.Struct):
194
230
  request_id: str
195
231
  request: (
196
232
  ToolExecutionRequest
197
233
  | GetAllFilesRequest
198
234
  | TerminateRequest
235
+ | HttpRequest
199
236
  | BatchToolExecutionRequest
237
+ | SwitchCLIChatRequest
200
238
  )
201
239
 
202
240
 
@@ -216,4 +254,6 @@ class CliRpcResponse(msgspec.Struct):
216
254
  | ErrorResponse
217
255
  | TerminateResponse
218
256
  | BatchToolExecutionResponse
257
+ | HttpResponse
258
+ | SwitchCLIChatResponse
219
259
  )
@@ -29,16 +29,21 @@ from exponent.core.remote_execution.cli_rpc_types import (
29
29
  ErrorResponse,
30
30
  GetAllFilesRequest,
31
31
  GetAllFilesResponse,
32
+ HttpResponse,
33
+ HttpRequest,
32
34
  TerminateRequest,
33
35
  TerminateResponse,
34
36
  ToolExecutionRequest,
35
37
  ToolExecutionResponse,
36
38
  ToolResultType,
39
+ SwitchCLIChatRequest,
40
+ SwitchCLIChatResponse,
37
41
  )
38
42
  from exponent.core.remote_execution.code_execution import (
39
43
  execute_code_streaming,
40
44
  )
41
45
  from exponent.core.remote_execution.files import file_walk
46
+ from exponent.core.remote_execution.http_fetch import fetch_http_content
42
47
  from exponent.core.remote_execution.session import (
43
48
  RemoteExecutionClientSession,
44
49
  get_session,
@@ -165,6 +170,21 @@ class RemoteExecutionClient:
165
170
  )
166
171
  )
167
172
  return None
173
+ elif isinstance(request.request, SwitchCLIChatRequest):
174
+ await websocket.send(
175
+ json.dumps(
176
+ {
177
+ "type": "result",
178
+ "data": msgspec.to_builtins(
179
+ CliRpcResponse(
180
+ request_id=request.request_id,
181
+ response=SwitchCLIChatResponse(),
182
+ )
183
+ ),
184
+ }
185
+ )
186
+ )
187
+ return SwitchCLIChat(new_chat_uuid=request.request.new_chat_uuid)
168
188
  else:
169
189
  if isinstance(request.request, ToolExecutionRequest) and isinstance(
170
190
  request.request.tool_input, BashToolInput
@@ -488,11 +508,22 @@ class RemoteExecutionClient:
488
508
  tool_results=results,
489
509
  ),
490
510
  )
511
+ elif isinstance(request.request, HttpRequest):
512
+ http_response = await fetch_http_content(request.request)
513
+ return CliRpcResponse(
514
+ request_id=request.request_id,
515
+ response=http_response,
516
+ )
491
517
  elif isinstance(request.request, TerminateRequest):
492
518
  raise ValueError(
493
519
  "TerminateRequest should not be handled by handle_request"
494
520
  )
495
521
 
522
+ elif isinstance(request.request, SwitchCLIChatRequest):
523
+ raise ValueError(
524
+ "SwitchCLIChatRequest should not be handled by handle_request"
525
+ )
526
+
496
527
  raise ValueError(f"Unhandled request type: {type(request)}")
497
528
 
498
529
  except Exception as e:
@@ -10,8 +10,6 @@ from exponent.core.remote_execution.cli_rpc_types import ErrorToolResult, GrepTo
10
10
  from exponent.core.remote_execution.types import (
11
11
  FileAttachment,
12
12
  FilePath,
13
- GetAllTrackedFilesRequest,
14
- GetAllTrackedFilesResponse,
15
13
  GetFileAttachmentRequest,
16
14
  GetFileAttachmentResponse,
17
15
  GetFileAttachmentsRequest,
@@ -209,16 +207,6 @@ async def get_matching_files(
209
207
  )
210
208
 
211
209
 
212
- async def get_all_tracked_files(
213
- request: GetAllTrackedFilesRequest,
214
- working_directory: str,
215
- ) -> GetAllTrackedFilesResponse:
216
- return GetAllTrackedFilesResponse(
217
- correlation_id=request.correlation_id,
218
- files=await get_all_non_ignored_files(working_directory),
219
- )
220
-
221
-
222
210
  async def search_files(
223
211
  path_str: str,
224
212
  file_pattern: str | None,
@@ -0,0 +1,95 @@
1
+ """HTTP fetch implementation for remote execution client."""
2
+
3
+ import logging
4
+ from typing import Any
5
+
6
+ import httpx
7
+
8
+ from exponent.core.remote_execution.cli_rpc_types import (
9
+ HttpResponse,
10
+ HttpRequest,
11
+ )
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ DEFAULT_TIMEOUT = 30.0
16
+ DEFAULT_USER_AGENT = "Indent-HTTP-Client/1.0"
17
+
18
+
19
+ async def fetch_http_content(http_request: HttpRequest) -> HttpResponse:
20
+ """
21
+ Fetch content from an HTTP URL and return the response.
22
+
23
+ Args:
24
+ http_request: HttpRequest containing URL, method, headers, and timeout
25
+
26
+ Returns:
27
+ HttpResponse with status code, content, and error message if any
28
+ """
29
+ logger.info(f"Fetching {http_request.method} {http_request.url}")
30
+
31
+ try:
32
+ # Set up timeout
33
+ timeout = (
34
+ http_request.timeout
35
+ if http_request.timeout is not None
36
+ else DEFAULT_TIMEOUT
37
+ )
38
+
39
+ # Set up headers with default User-Agent
40
+ headers = http_request.headers or {}
41
+ if "User-Agent" not in headers:
42
+ headers["User-Agent"] = DEFAULT_USER_AGENT
43
+
44
+ # Create HTTP client with timeout
45
+ async with httpx.AsyncClient(timeout=timeout) as client:
46
+ # Make the HTTP request
47
+ response = await client.request(
48
+ method=http_request.method,
49
+ url=http_request.url,
50
+ headers=headers,
51
+ )
52
+
53
+ # Get response content as text
54
+ try:
55
+ content = response.text
56
+ except UnicodeDecodeError:
57
+ # If content can't be decoded as text, provide a fallback
58
+ content = f"Binary content ({len(response.content)} bytes)"
59
+ logger.warning(
60
+ f"Could not decode response content as text for {http_request.url}"
61
+ )
62
+
63
+ logger.info(
64
+ f"HTTP {http_request.method} {http_request.url} -> {response.status_code}"
65
+ )
66
+
67
+ return HttpResponse(
68
+ status_code=response.status_code,
69
+ content=content,
70
+ error_message=None,
71
+ )
72
+
73
+ except httpx.TimeoutException:
74
+ error_msg = f"Request to {http_request.url} timed out after {timeout} seconds"
75
+ return HttpResponse(
76
+ status_code=None,
77
+ content="",
78
+ error_message=error_msg,
79
+ )
80
+
81
+ except httpx.RequestError as e:
82
+ error_msg = f"Request error for {http_request.url}: {str(e)}"
83
+ return HttpResponse(
84
+ status_code=None,
85
+ content="",
86
+ error_message=error_msg,
87
+ )
88
+
89
+ except Exception as e:
90
+ error_msg = f"Unexpected error fetching {http_request.url}: {str(e)}"
91
+ return HttpResponse(
92
+ status_code=None,
93
+ content="",
94
+ error_message=error_msg,
95
+ )
@@ -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
- elif response_data.namespace == "system_context":
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
- @overload
428
- def truncate_message(response: SystemContextRequest) -> SystemContextRequest: ...
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.6
3
+ Version: 0.1.8
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<0.28,>=0.27.0
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,4 +1,4 @@
1
- exponent/__init__.py,sha256=oVf6rpSEmuBL8TgePOpVGMK15v_0KI_2MgQ0HuIaP14,58
1
+ exponent/__init__.py,sha256=8JwU8HGcy78SqyRKGzPeP1n0ZgSgd9n3eJI5oPlzLh4,58
2
2
  exponent/cli.py,sha256=GA-Bw1nys9JNrlob0t3LcS9OZ4U5JcNYjR_r3kDD_qs,3596
3
3
  exponent/py.typed,sha256=9XZl5avs8yHp89XP_1Fjtbeg_2rjYorCC9I0k_j-h2c,334
4
4
  exponent/commands/cloud_commands.py,sha256=4DgS7PjCtCFB5uNN-szzAzOj16UU1D9b9_qS7DskoLE,2026
@@ -21,23 +21,24 @@ exponent/core/graphql/cloud_config_queries.py,sha256=Xy8SRP-sfWFcaq33hF-Ni1KwZDU
21
21
  exponent/core/graphql/get_chats_query.py,sha256=9-2N1VfapXUZB3IFIKw5U_gKdmfyviJp5JSUntB_Yyk,1177
22
22
  exponent/core/graphql/github_config_queries.py,sha256=zKRDxF38q73apQcVaEAA_A20FVr3U0ADc5-8Y6Ns5Dw,1260
23
23
  exponent/core/graphql/mutations.py,sha256=WRwgJzMTETvry1yc9-EBlIRWkePjHIskBAm_6tEiRaU,1352
24
- exponent/core/graphql/queries.py,sha256=TXXHLGb7QpeICaofowVYsjyHDfqjCoQ3omLbesuw06s,2612
25
- exponent/core/graphql/subscriptions.py,sha256=gg42wG5HqEuNMJU7OUHruNCAGtM6FKPLRD7KfjcKjC4,9995
24
+ exponent/core/graphql/queries.py,sha256=AJgDM1qc2_Zo0DhLqbogVTVokrzjfqhwhUz0SCdrKNI,2943
25
+ exponent/core/graphql/subscriptions.py,sha256=qDlWQsaY0F4lUaHEAeAa02iuKpUfml4I6kD9HMKGe1E,10301
26
26
  exponent/core/remote_execution/checkpoints.py,sha256=3QGYMLa8vT7XmxMYTRcGrW8kNGHwRC0AkUfULribJWg,6354
27
- exponent/core/remote_execution/cli_rpc_types.py,sha256=GPRK_9bKJiNHJx3Y-3elO0rOwz70kyik9Wo3xdGoLVA,4587
28
- exponent/core/remote_execution/client.py,sha256=u5JH1yhbHcWpdee340x9JnYCsFJ-rJuu0-YPgSbojRw,21603
27
+ exponent/core/remote_execution/cli_rpc_types.py,sha256=ZokZXSMYGqJJX9fqzzoXJx9ElZjg6wOUl8dT9QMJQ9Y,5793
28
+ exponent/core/remote_execution/client.py,sha256=4CAc9F2-7d0FG-qq1GDvJt3n6kGkQObYlWoGO9QbsIE,22858
29
29
  exponent/core/remote_execution/code_execution.py,sha256=jYPB_7dJzS9BTPLX9fKQpsFPatwjbXuaFFSxT9tDTfI,2388
30
30
  exponent/core/remote_execution/error_info.py,sha256=Rd7OA3ps06qYejPVcOaMBB9AtftP3wqQoOfiILFASnc,1378
31
31
  exponent/core/remote_execution/exceptions.py,sha256=eT57lBnBhvh-KJ5lsKWcfgGA5-WisAxhjZx-Z6OupZY,135
32
32
  exponent/core/remote_execution/file_write.py,sha256=j9X4QfCBuZK6VIMfeu53WTN90G4w0AtN4U9GcoCJvJk,12531
33
- exponent/core/remote_execution/files.py,sha256=0EmOP2OdreGHjkKEIhtB_nNcjvLLx_UJWbbxt7cGSNg,12225
33
+ exponent/core/remote_execution/files.py,sha256=ypqDuXhnANWMnwiYrw033oBSDaDT9v9J0jvdHesRw24,11868
34
34
  exponent/core/remote_execution/git.py,sha256=Yo4mhkl6LYzGhVco91j_E8WOUey5KL9437rk43VCCA8,7826
35
+ exponent/core/remote_execution/http_fetch.py,sha256=ZoQ2EcB1vQys-QmIbt1xC0ftyWkOIohxCfYNVYv4kF0,2856
35
36
  exponent/core/remote_execution/session.py,sha256=cSJcCG1o74mBE6lZS_9VFmhyZdW6BeIOsbq4IVWH0t4,3863
36
- exponent/core/remote_execution/system_context.py,sha256=0FkbsSxEVjdjTF0tQpOkYK_VaVM126C3_K8QP0YXxOs,1510
37
+ exponent/core/remote_execution/system_context.py,sha256=XBvWeLLsrfzdicYBMbIneOBlnelBMb2n-VpHw5q2kcA,749
37
38
  exponent/core/remote_execution/tool_execution.py,sha256=_UQPyOTY49RQ70kfgnf03eev7c7lTWhFBC68cuifj2M,12354
38
39
  exponent/core/remote_execution/truncation.py,sha256=rFQDfT7qf_u6lvhEADWSpoRe_GTPegXXqknk7OZp0uI,10093
39
- exponent/core/remote_execution/types.py,sha256=3x73SJ3jQtaIu01musXgS-VF_MYwYucG3hyA2nWHbII,17567
40
- exponent/core/remote_execution/utils.py,sha256=Hw2zGMq0NKVwkVzNOVekAvpM33rfIz2P36mEcJr43Ag,20688
40
+ exponent/core/remote_execution/types.py,sha256=P1hlhg_cw6A0iplODzI2irs5f7k8zBYYGX4Xvs4-YC4,16212
41
+ exponent/core/remote_execution/utils.py,sha256=Jwn2f753WuyanceUQSyJypcplOlUrfPchebAy7ULoz8,15927
41
42
  exponent/core/remote_execution/languages/python_execution.py,sha256=GcQU5PiAOUD9tUZDrSObgM3L7FjXMdzr4FQg6ts2XjY,7780
42
43
  exponent/core/remote_execution/languages/shell_streaming.py,sha256=eSeHcK_unGpVRRdfgfwhml_tSlCo0VCeUEQY4zuMbDw,7372
43
44
  exponent/core/remote_execution/languages/types.py,sha256=f7FjSRNRSga-ZaE3LddDhxCirUVjlSYMEdoskG6Pta4,314
@@ -50,7 +51,7 @@ exponent/migration-docs/login.md,sha256=KIeXy3m2nzSUgw-4PW1XzXfHael1D4Zu93CplLMb
50
51
  exponent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
52
  exponent/utils/colors.py,sha256=HBkqe_ZmhJ9YiL2Fpulqek4KvLS5mwBTY4LQSM5N8SM,2762
52
53
  exponent/utils/version.py,sha256=Q4txP7Rg_KO0u0tUpx8O0DoOt32wrX7ctNeDXVKaOfA,8835
53
- indent-0.1.6.dist-info/METADATA,sha256=09jZnI_VohQwM0FiOXUtvE6Q-Bf_8AA_fgkXTYu77hc,1283
54
- indent-0.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
55
- indent-0.1.6.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
56
- indent-0.1.6.dist-info/RECORD,,
54
+ indent-0.1.8.dist-info/METADATA,sha256=MDPMcnA4_Zjad-c_BBv_KRXuiIkPw2sv5mT0_DlgLEg,1277
55
+ indent-0.1.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
56
+ indent-0.1.8.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
57
+ indent-0.1.8.dist-info/RECORD,,
File without changes