indent 0.1.11__py3-none-any.whl → 0.1.13__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.
@@ -1,85 +1,13 @@
1
- import logging
2
1
  import os
3
- import re
4
- import subprocess
5
- from collections.abc import Callable
6
- from textwrap import dedent, indent
7
2
 
8
3
  from anyio import Path as AsyncPath
9
- from diff_match_patch import diff_match_patch
10
- from pydantic import BaseModel
11
4
 
12
5
  from exponent.core.remote_execution.types import (
13
6
  FilePath,
14
- FileWriteRequest,
15
- FileWriteResponse,
16
7
  )
17
8
  from exponent.core.remote_execution.utils import (
18
- assert_unreachable,
19
- safe_read_file,
20
9
  safe_write_file,
21
10
  )
22
- from exponent.core.types.command_data import (
23
- WRITE_STRATEGY_FULL_FILE_REWRITE,
24
- WRITE_STRATEGY_NATURAL_EDIT,
25
- WRITE_STRATEGY_SEARCH_REPLACE,
26
- WRITE_STRATEGY_UDIFF,
27
- )
28
-
29
- logger = logging.getLogger(__name__)
30
-
31
-
32
- class FileEditResult(BaseModel):
33
- content: str | None
34
- failed_edits: list[tuple[str, str]]
35
-
36
-
37
- async def execute_file_write(
38
- event: FileWriteRequest, working_directory: str
39
- ) -> FileWriteResponse:
40
- write_strategy = event.write_strategy
41
- content = event.content
42
-
43
- if write_strategy == WRITE_STRATEGY_FULL_FILE_REWRITE:
44
- result = await execute_full_file_rewrite(
45
- event.file_path, content, working_directory
46
- )
47
- elif write_strategy == WRITE_STRATEGY_UDIFF:
48
- result = await execute_udiff_edit(event.file_path, content, working_directory)
49
- elif write_strategy == WRITE_STRATEGY_SEARCH_REPLACE:
50
- result = await execute_search_replace_edit(
51
- event.file_path, content, working_directory
52
- )
53
- elif write_strategy == WRITE_STRATEGY_NATURAL_EDIT:
54
- result = await execute_full_file_rewrite(
55
- event.file_path, content, working_directory
56
- )
57
- else:
58
- assert_unreachable(write_strategy)
59
- return FileWriteResponse(
60
- content=result,
61
- correlation_id=event.correlation_id,
62
- )
63
-
64
-
65
- def lint_file(file_path: str, working_directory: str) -> str:
66
- try:
67
- # Construct the absolute path
68
- full_file_path = os.path.join(working_directory, file_path)
69
-
70
- # Run ruff check --fix on the file
71
- result = subprocess.run(
72
- ["ruff", "check", "--fix", full_file_path],
73
- capture_output=True,
74
- text=True,
75
- check=True,
76
- )
77
-
78
- # If the subprocess ran successfully, return a success message
79
- return f"Lint results:\n\n{result.stdout}\n\n{result.stderr}"
80
- except Exception as e:
81
- # For any other errors, return a generic error message
82
- return f"An error occurred while linting: {e!s}"
83
11
 
84
12
 
85
13
  async def execute_full_file_rewrite(
@@ -105,306 +33,3 @@ async def execute_full_file_rewrite(
105
33
 
106
34
  except Exception as e:
107
35
  return f"An error occurred: {e!s}"
108
-
109
-
110
- async def execute_udiff_edit(
111
- file_path: str, content: str, working_directory: str
112
- ) -> str:
113
- return await execute_partial_edit(
114
- file_path, content, working_directory, apply_udiff
115
- )
116
-
117
-
118
- async def execute_search_replace_edit(
119
- file_path: str, content: str, working_directory: str
120
- ) -> str:
121
- return await execute_partial_edit(
122
- file_path, content, working_directory, apply_all_search_replace
123
- )
124
-
125
-
126
- async def execute_partial_edit(
127
- file_path: str,
128
- edit_content: str,
129
- working_directory: str,
130
- edit_function: Callable[[str, str], FileEditResult],
131
- ) -> str:
132
- try:
133
- # Construct the absolute path
134
- full_file_path = AsyncPath(os.path.join(working_directory, file_path))
135
-
136
- # Check if the directory exists, if not, create it
137
- await full_file_path.parent.mkdir(parents=True, exist_ok=True)
138
-
139
- # Determine if the file exists and write the new content
140
- file_content, created = await read_or_init_file(full_file_path)
141
-
142
- success = await open_file_and_apply_edit(
143
- file_path=full_file_path,
144
- file_content=file_content,
145
- edit_content=edit_content,
146
- edit_function=edit_function,
147
- )
148
-
149
- if success:
150
- verb = "Created" if created else "Modified"
151
- return f"{verb} file {file_path}"
152
- else:
153
- verb = "create" if created else "modify"
154
- return f"Failed to {verb} file {file_path}"
155
-
156
- except Exception as e:
157
- raise e
158
-
159
-
160
- async def read_or_init_file(file_path: FilePath) -> tuple[str, bool]:
161
- path = AsyncPath(file_path)
162
-
163
- if not (await path.exists()):
164
- await path.touch()
165
- return "", True
166
-
167
- content = await safe_read_file(path)
168
- return content, False
169
-
170
-
171
- async def open_file_and_apply_edit(
172
- file_path: FilePath,
173
- file_content: str,
174
- edit_content: str,
175
- edit_function: Callable[[str, str], FileEditResult],
176
- ) -> bool:
177
- result = edit_function(file_content, edit_content)
178
-
179
- if not result.content:
180
- return False
181
-
182
- await safe_write_file(file_path, result.content)
183
-
184
- return True
185
-
186
-
187
- def find_leading_whitespace(existing_content: str, search: str) -> str | None:
188
- existing_lines = existing_content.splitlines()
189
-
190
- search_line_count = len(search.splitlines())
191
- dedented_search = dedent(search)
192
-
193
- for i in range(len(existing_lines)):
194
- existing_window_content = "\n".join(existing_lines[i : i + search_line_count])
195
- dedented_existing_window = dedent(existing_window_content)
196
-
197
- leading_ws_len = len(existing_window_content) - len(
198
- existing_window_content.lstrip()
199
- )
200
- leading_ws = existing_window_content[:leading_ws_len]
201
-
202
- if dedented_existing_window == dedented_search:
203
- return leading_ws
204
-
205
- return None
206
-
207
-
208
- def try_fix_whitespace(
209
- existing_content: str, search: str, replace: str
210
- ) -> tuple[str, str] | None:
211
- # Try to fix the whitespace of the search and replace
212
- # to make the edit more likely to apply
213
- leading_ws = find_leading_whitespace(existing_content, search)
214
- if leading_ws is None:
215
- return None
216
-
217
- dedented_search = dedent(search)
218
- dedented_replace = dedent(replace)
219
-
220
- return indent(dedented_search, leading_ws), indent(dedented_replace, leading_ws)
221
-
222
-
223
- def try_search_replace(existing_content: str, search: str, replace: str) -> str | None:
224
- # Try simple search and replace first
225
- new_content = simple_search_and_replace(existing_content, search, replace)
226
- if new_content:
227
- return new_content
228
-
229
- fixed_ws = try_fix_whitespace(existing_content, search, replace)
230
- if not fixed_ws:
231
- return None
232
-
233
- search, replace = fixed_ws
234
-
235
- new_content = simple_search_and_replace(existing_content, search, replace)
236
- if new_content:
237
- return new_content
238
-
239
- return None
240
-
241
-
242
- def try_diff_patch(existing_content: str, search: str, replace: str) -> str | None:
243
- new_content = diff_patch_search_and_replace(existing_content, search, replace)
244
- if new_content:
245
- print("Applied diff patch search and replace")
246
- return new_content
247
-
248
- return None
249
-
250
-
251
- def apply_udiff(existing_content: str, diff_content: str) -> FileEditResult:
252
- hunks = get_raw_udiff_hunks(diff_content)
253
-
254
- for hunk in hunks:
255
- if not hunk:
256
- continue
257
-
258
- search, replace = split_hunk_for_search_and_replace(hunk)
259
-
260
- # Exact match
261
- new_content = try_search_replace(existing_content, search, replace)
262
- if new_content is not None:
263
- print("Applied successfully!")
264
- return FileEditResult(content=new_content, failed_edits=[])
265
-
266
- # Fuzzy match
267
- new_content = try_diff_patch(existing_content, search, replace)
268
- if new_content is not None:
269
- print("Applied successfully!")
270
- return FileEditResult(content=new_content, failed_edits=[])
271
-
272
- print("Failed to apply hunk, exiting!")
273
- return FileEditResult(content=None, failed_edits=[(search, replace)])
274
-
275
- return FileEditResult(content=existing_content, failed_edits=[])
276
-
277
-
278
- def get_raw_udiff_hunks(content: str) -> list[list[str]]:
279
- lines = content.splitlines(keepends=True)
280
- hunks: list[list[str]] = []
281
- current_hunk: list[str] = []
282
- for line in lines:
283
- if line.startswith("@@"):
284
- if current_hunk:
285
- hunks.append(current_hunk)
286
- current_hunk = []
287
- else:
288
- current_hunk.append(line)
289
- if current_hunk:
290
- hunks.append(current_hunk)
291
- return hunks
292
-
293
-
294
- def split_hunk_for_search_and_replace(hunk: list[str]) -> tuple[str, str]:
295
- search_lines = []
296
- replace_lines = []
297
-
298
- search_prefixes = ["-", " "]
299
- replace_prefixes = ["+", " "]
300
- for line in hunk:
301
- if not line:
302
- continue
303
- prefix, content = line[0], line[1:]
304
- if not content:
305
- continue
306
- if prefix in search_prefixes:
307
- search_lines.append(content)
308
- if prefix in replace_prefixes:
309
- replace_lines.append(content)
310
- return "".join(search_lines), "".join(replace_lines)
311
-
312
-
313
- def simple_search_and_replace(content: str, search: str, replace: str) -> str | None:
314
- if content.count(search) >= 1:
315
- return content.replace(search, replace)
316
- return None
317
-
318
-
319
- def diff_patch_search_and_replace(
320
- content: str, search: str, replace: str
321
- ) -> str | None:
322
- patcher = diff_match_patch()
323
- # 3 second tieout for computing diffs
324
- patcher.Diff_Timeout = 3
325
- patcher.Match_Threshold = 0.95
326
- patcher.Match_Distance = 500
327
- patcher.Match_MaxBits = 128
328
- patcher.Patch_Margin = 32
329
- search_vs_replace_diff = patcher.diff_main(search, replace, False)
330
-
331
- # Simplify the diff as much as possible
332
- patcher.diff_cleanupEfficiency(search_vs_replace_diff)
333
- patcher.diff_cleanupSemantic(search_vs_replace_diff)
334
-
335
- original_vs_search_diff = patcher.diff_main(search, content)
336
- new_diffs = patcher.patch_make(search, search_vs_replace_diff)
337
- # Offset the search vs. replace diffs with the offset
338
- # of the search diff within the original content.
339
- for new_diff in new_diffs:
340
- new_diff.start1 = patcher.diff_xIndex(original_vs_search_diff, new_diff.start1)
341
- new_diff.start2 = patcher.diff_xIndex(original_vs_search_diff, new_diff.start2)
342
-
343
- new_content, successes = patcher.patch_apply(new_diffs, content)
344
- if not all(successes):
345
- return None
346
-
347
- return str(new_content)
348
-
349
-
350
- SEARCH_REPLACE_RE = re.compile(
351
- r"[^<>]*<<<+\s*SEARCH\n((?P<search>.*?)\n)??===+\n((?P<replace>.*?)\n)??>>>+\s*?REPLACE\s*?[^<>]*",
352
- re.DOTALL,
353
- )
354
-
355
- TAGGED_SEARCH_REPLACE_RE = re.compile(
356
- r"<search>(?P<search>.*?)??</search>\s*?<replace>(?P<replace>.*?)??</replace>",
357
- re.DOTALL,
358
- )
359
-
360
-
361
- def apply_search_replace(result: str, search: str, replace: str) -> str | None:
362
- if not search and not replace:
363
- # Nonsense
364
- return None
365
-
366
- if not search and not result:
367
- # New file, just return replace
368
- return replace
369
-
370
- if not search.strip():
371
- # Search on just whitespace,
372
- # too dangerous to apply
373
- return None
374
-
375
- return try_search_replace(result, search, replace)
376
-
377
-
378
- def apply_all_search_replace(
379
- existing_content: str,
380
- sr_content: str,
381
- match_re: re.Pattern[str] = SEARCH_REPLACE_RE,
382
- ) -> FileEditResult:
383
- # Same as apply_search_replace, but applies all search and replace pairs
384
- # in the sr_content to the existing_content
385
-
386
- result = existing_content
387
- failed_edits: list[tuple[str, str]] = []
388
-
389
- for match in match_re.finditer(sr_content):
390
- match_dict = match.groupdict()
391
- search, replace = match_dict.get("search"), match_dict.get("replace")
392
- search = search or ""
393
- replace = replace or ""
394
-
395
- new_result = apply_search_replace(result, search, replace)
396
- if new_result is None:
397
- failed_edits.append((search, replace))
398
- continue
399
-
400
- result = new_result
401
-
402
- return FileEditResult(content=result, failed_edits=failed_edits)
403
-
404
-
405
- def apply_all_tagged_search_replace(
406
- existing_content: str, sr_content: str
407
- ) -> FileEditResult:
408
- return apply_all_search_replace(
409
- existing_content, sr_content, TAGGED_SEARCH_REPLACE_RE
410
- )
@@ -98,6 +98,7 @@ class HeartbeatInfo(BaseModel):
98
98
  default_factory=lambda: datetime.datetime.now(datetime.UTC)
99
99
  )
100
100
  timestamp_received: datetime.datetime | None = None
101
+ cli_uuid: str | None = None
101
102
 
102
103
 
103
104
  class RemoteFile(BaseModel):
@@ -505,17 +506,10 @@ class ChatMode(str, Enum):
505
506
  CLI = "CLI"
506
507
  CLOUD = "CLOUD" # chat with cloud devbox
507
508
  CODEBASE = "CODEBASE" # chat with codebase
508
- PYTHON_INTERPRETER = "PYTHON_INTERPRETER"
509
509
  DATABASE = "DATABASE" # chat with database connection
510
510
  WORKFLOW = "WORKFLOW"
511
511
 
512
512
 
513
- DEVBOX_CHAT_MODES = [
514
- ChatMode.CLOUD,
515
- ChatMode.CODEBASE,
516
- ]
517
-
518
-
519
513
  class ChatSource(str, Enum):
520
514
  CLI_SHELL = "CLI_SHELL"
521
515
  CLI_RUN = "CLI_RUN"
@@ -4,8 +4,6 @@ import enum
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
7
- from exponent.core.remote_execution.types import ChatMode
8
-
9
7
 
10
8
  class StrategyName(str, enum.Enum):
11
9
  NATURAL_EDIT_CLAUDE_3_7_XML = "NATURAL_EDIT_CLAUDE_3_7_XML"
@@ -39,16 +37,6 @@ class StrategyInfo(BaseModel):
39
37
  is_agentic: bool
40
38
 
41
39
 
42
- CHAT_MODE_DEFAULTS: dict[ChatMode, StrategyName] = {
43
- ChatMode.DEFAULT: StrategyName.RAW_GPT,
44
- ChatMode.CLI: StrategyName.NATURAL_EDIT_CLAUDE_3_7_XML,
45
- ChatMode.CLOUD: StrategyName.NATURAL_EDIT_CLAUDE_3_7_XML,
46
- ChatMode.DATABASE: StrategyName.DATABASE,
47
- ChatMode.PYTHON_INTERPRETER: StrategyName.NATURAL_EDIT_CLAUDE_3_7_XML,
48
- ChatMode.WORKFLOW: StrategyName.NATURAL_EDIT_CLAUDE_3_7_XML,
49
- ChatMode.CODEBASE: StrategyName.READ_ONLY,
50
- }
51
-
52
40
  STRATEGY_INFO_LIST: list[StrategyInfo] = [
53
41
  StrategyInfo(
54
42
  strategy_name=StrategyName.NATURAL_EDIT_CLAUDE_3_7_XML,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indent
3
- Version: 0.1.11
3
+ Version: 0.1.13
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
@@ -14,7 +14,7 @@ Requires-Dist: diff-match-patch<20230431,>=20230430
14
14
  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
- Requires-Dist: gql[httpx,websockets]<4,>=3.5.0
17
+ Requires-Dist: gql[httpx,websockets]~=4.0
18
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
@@ -32,4 +32,4 @@ Requires-Dist: rapidfuzz<4,>=3.9.0
32
32
  Requires-Dist: rich<14,>=13.7.1
33
33
  Requires-Dist: sentry-sdk<3,>=2.1.1
34
34
  Requires-Dist: toml<0.11,>=0.10.2
35
- Requires-Dist: websockets~=11.0
35
+ Requires-Dist: websockets~=15.0
@@ -1,30 +1,30 @@
1
- exponent/__init__.py,sha256=0-Ruc52ECccw_8Ef0d7jMkzrb8fkobUkZLqGGvcm1ik,706
1
+ exponent/__init__.py,sha256=Xz5RLbyPcCHHXte393JYfUy4Dt7uaeWyrGVw9SmJ0eg,706
2
2
  exponent/cli.py,sha256=u3hhZnn5uqVXyNz6wU8j4U5vLJ--pbA-PweHhpvRzY4,3444
3
3
  exponent/py.typed,sha256=9XZl5avs8yHp89XP_1Fjtbeg_2rjYorCC9I0k_j-h2c,334
4
- exponent/commands/cloud_commands.py,sha256=4DgS7PjCtCFB5uNN-szzAzOj16UU1D9b9_qS7DskoLE,2026
5
- exponent/commands/common.py,sha256=HUzc9yl5L6GZEF5DDsF3IeArwPKrghxmK43vxtkxgGs,13679
4
+ exponent/commands/cloud_commands.py,sha256=TNSbKnc7VBo7VALj44CqV5tdCACJejEGmtYvc5wjza4,19080
5
+ exponent/commands/common.py,sha256=6Xww3tdK2IGdlPvHZ6T_fJirO3PwZi3XCzVGSOhUWIw,13493
6
6
  exponent/commands/config_commands.py,sha256=iVIX7LuoO5QshzZNSrfvw5yPIiLlce8GQSMBEp7-nzw,11415
7
- exponent/commands/run_commands.py,sha256=syuC_YUFSz57eT7Rl0aFiIfogINmiAvmenLClnogWQU,5865
7
+ exponent/commands/run_commands.py,sha256=kowWiBtp4ZLQHBMG31fSotQ35ruGD3OfbPsMcbbnHU8,6240
8
8
  exponent/commands/settings.py,sha256=UwwwoCgCY5hzAFD9slOBbA9Gr1hNfoyJ2blsFDC6V8w,1559
9
9
  exponent/commands/types.py,sha256=iDJL3hdwhO1PrhsJTJBioNYSKo0CWV8Nv-ONcDaWIRs,3670
10
10
  exponent/commands/upgrade.py,sha256=JZr0sNazziuLByQHdT8GZb-lDbRG1YpHW8VB94q-r8w,803
11
11
  exponent/commands/utils.py,sha256=Z3eu3mvYwBh7J_hq17lyt7_MwMG8KcsP7AnsCgOnTNc,4638
12
- exponent/commands/workflow_commands.py,sha256=PAxO9yN6H82ZsXKG-1ceXzPfjFAxBbjoEIgPoQ7iTk0,3596
12
+ exponent/commands/workflow_commands.py,sha256=eQufFbKrKCZtewyDpuVe_0QcndbxuaIKHfHpHF8-XzI,3602
13
13
  exponent/core/config.py,sha256=TNFLUgLnfSocRMVSav_7E4VcaNHXZ_3Mg5Lp1smP46U,5731
14
14
  exponent/core/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- exponent/core/graphql/client.py,sha256=KRveVt4lsrSdF9PnhhlQeqx74FQ9-iN28WQp0WKnQ30,1921
15
+ exponent/core/graphql/client.py,sha256=SRagD3YPyoYZSO1RtfO-OXD7b5dm1NvgoL6CTbN380o,2009
16
16
  exponent/core/graphql/get_chats_query.py,sha256=9-2N1VfapXUZB3IFIKw5U_gKdmfyviJp5JSUntB_Yyk,1177
17
17
  exponent/core/graphql/github_config_queries.py,sha256=zKRDxF38q73apQcVaEAA_A20FVr3U0ADc5-8Y6Ns5Dw,1260
18
- exponent/core/graphql/mutations.py,sha256=WRwgJzMTETvry1yc9-EBlIRWkePjHIskBAm_6tEiRaU,1352
19
- exponent/core/graphql/queries.py,sha256=AJgDM1qc2_Zo0DhLqbogVTVokrzjfqhwhUz0SCdrKNI,2943
18
+ exponent/core/graphql/mutations.py,sha256=cAAiSefyamBgy1zJEZ7LNk0rbjwawTPxMyj8eU6yRRI,3502
19
+ exponent/core/graphql/queries.py,sha256=RYsk8bub0esspqgakilhzX07yJf2652Ey9tBZK1l_lY,3297
20
20
  exponent/core/graphql/subscriptions.py,sha256=SQngv_nYVNJjiZ_P2k0UcLIu1pzc4vi7q7lhH89NCZM,393
21
21
  exponent/core/remote_execution/checkpoints.py,sha256=3QGYMLa8vT7XmxMYTRcGrW8kNGHwRC0AkUfULribJWg,6354
22
- exponent/core/remote_execution/cli_rpc_types.py,sha256=W4zowx4kyAOqEqfavuKrdaZ4qHHYEkxmfDWLSaLzxvY,6918
23
- exponent/core/remote_execution/client.py,sha256=GS0KCK1xyvH0nBTdBo_80aQ5lV3kFAB7Eq_xL5_xt90,25523
22
+ exponent/core/remote_execution/cli_rpc_types.py,sha256=bmpfZASzzsD_NDIF2Mnym79km2fem8Oc0tSlSC-0EoY,7478
23
+ exponent/core/remote_execution/client.py,sha256=PzYG5bIHLxlGxVsIzzg2SX1X6G50hJ3XXV0Cai5tS7A,28911
24
24
  exponent/core/remote_execution/code_execution.py,sha256=jYPB_7dJzS9BTPLX9fKQpsFPatwjbXuaFFSxT9tDTfI,2388
25
25
  exponent/core/remote_execution/error_info.py,sha256=Rd7OA3ps06qYejPVcOaMBB9AtftP3wqQoOfiILFASnc,1378
26
26
  exponent/core/remote_execution/exceptions.py,sha256=eT57lBnBhvh-KJ5lsKWcfgGA5-WisAxhjZx-Z6OupZY,135
27
- exponent/core/remote_execution/file_write.py,sha256=RqeGG_OyUIPD91XWGKdTQdEG0t1TCfc5WYnNvw0D9fc,12499
27
+ exponent/core/remote_execution/file_write.py,sha256=8Sa70ANIDHGxIAq4_Uy2Qoo55K7-cSzU3282zyu7hG8,978
28
28
  exponent/core/remote_execution/files.py,sha256=mIVjhStaEKETW6y3pCVeV8eJKNaPtroWGP_kBK1x8uA,8776
29
29
  exponent/core/remote_execution/git.py,sha256=dGjBpeoKJZsYgRwctSq29GmbsNIN9tbSA3VwBnRD0IQ,7810
30
30
  exponent/core/remote_execution/http_fetch.py,sha256=aFEyXd0S-MRfisSMuIFiEyc1AEAj9nUZ9Rj_P_YRows,2827
@@ -32,7 +32,7 @@ exponent/core/remote_execution/session.py,sha256=jlQIdeUj0f7uOk3BgzlJtBJ_GyTIjCc
32
32
  exponent/core/remote_execution/system_context.py,sha256=QY1zY8_fWj3sh-fmLYtewvgxh7uTX4ITIJqlUTDkj6c,648
33
33
  exponent/core/remote_execution/tool_execution.py,sha256=ZBDC2RN_l8oCFO8Fc8dkKoLY_0rn-5h394PvWeXqTnI,12972
34
34
  exponent/core/remote_execution/truncation.py,sha256=noB6c4eaebqq5ghTlYJkXbe2XY8Bz_GBeh9DazJUrrU,9644
35
- exponent/core/remote_execution/types.py,sha256=oK0L5GK-Zp3Kez-EVWsDfwxnUvVQtH-l2OO2zQWhlzQ,14930
35
+ exponent/core/remote_execution/types.py,sha256=123sT6Uz2dE0X_Amw5nxyQd8haFblrikDC5jbDh1Pjg,14847
36
36
  exponent/core/remote_execution/utils.py,sha256=6PlBqYJ3OQwZ0dgXiIu3br04a-d-glDeDZpD0XGGPAE,14793
37
37
  exponent/core/remote_execution/languages/python_execution.py,sha256=nsX_LsXcUcHhiEHpSTjOTVNd7CxM146al0kw_iQX5OU,7724
38
38
  exponent/core/remote_execution/languages/shell_streaming.py,sha256=eEhngdLhiMiDM0KUfLUtj6BdU3ay3G1zJy6dlR2V6nw,7389
@@ -41,12 +41,12 @@ exponent/core/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
41
41
  exponent/core/types/command_data.py,sha256=_HqQsnamRZeVoVaTpeO3ecVUzNBdG62WXlFy6Q7rtUM,5294
42
42
  exponent/core/types/event_types.py,sha256=Hi9OMlLwB8f0TwPsKMThkXLFVzvOyJfMWk2urjPD1Uo,2468
43
43
  exponent/core/types/generated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- exponent/core/types/generated/strategy_info.py,sha256=T9fGuH9gS4GaChgRfIjDYAs68bk4zm9OEg2mMcT-Wyw,7155
44
+ exponent/core/types/generated/strategy_info.py,sha256=LN6_ykFMszb21Qc3yw77xEKUtd7m4e-zzhPS1HZjvzE,6641
45
45
  exponent/migration-docs/login.md,sha256=KIeXy3m2nzSUgw-4PW1XzXfHael1D4Zu93CplLMb3hI,4252
46
46
  exponent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  exponent/utils/colors.py,sha256=HBkqe_ZmhJ9YiL2Fpulqek4KvLS5mwBTY4LQSM5N8SM,2762
48
48
  exponent/utils/version.py,sha256=dmSFUzspaGjehLr9y_PkGTAQe298M0TwK9PF8fv3EKA,8819
49
- indent-0.1.11.dist-info/METADATA,sha256=WSNfqZvsBT0nrTqYDdipWCXMPeGJfGz2qmMK0KNbLvI,1278
50
- indent-0.1.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
51
- indent-0.1.11.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
52
- indent-0.1.11.dist-info/RECORD,,
49
+ indent-0.1.13.dist-info/METADATA,sha256=awgxeJ-xbpUWcdHfr-2BzxOJiCJc6iHuF_myMRQhYq0,1273
50
+ indent-0.1.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
51
+ indent-0.1.13.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
52
+ indent-0.1.13.dist-info/RECORD,,