indent 0.1.10__py3-none-any.whl → 0.1.12__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.

Files changed (34) hide show
  1. exponent/__init__.py +16 -3
  2. exponent/commands/cloud_commands.py +582 -0
  3. exponent/commands/common.py +4 -9
  4. exponent/commands/config_commands.py +1 -161
  5. exponent/commands/run_commands.py +20 -9
  6. exponent/commands/utils.py +3 -3
  7. exponent/commands/workflow_commands.py +2 -2
  8. exponent/core/config.py +0 -1
  9. exponent/core/graphql/mutations.py +114 -0
  10. exponent/core/graphql/queries.py +23 -0
  11. exponent/core/graphql/subscriptions.py +0 -449
  12. exponent/core/remote_execution/cli_rpc_types.py +48 -1
  13. exponent/core/remote_execution/client.py +114 -26
  14. exponent/core/remote_execution/file_write.py +1 -376
  15. exponent/core/remote_execution/files.py +1 -102
  16. exponent/core/remote_execution/git.py +1 -1
  17. exponent/core/remote_execution/http_fetch.py +3 -4
  18. exponent/core/remote_execution/languages/python_execution.py +1 -1
  19. exponent/core/remote_execution/languages/shell_streaming.py +1 -1
  20. exponent/core/remote_execution/session.py +1 -1
  21. exponent/core/remote_execution/system_context.py +0 -3
  22. exponent/core/remote_execution/tool_execution.py +24 -4
  23. exponent/core/remote_execution/truncation.py +51 -47
  24. exponent/core/remote_execution/types.py +25 -79
  25. exponent/core/remote_execution/utils.py +23 -51
  26. exponent/core/types/event_types.py +2 -2
  27. exponent/core/types/generated/strategy_info.py +0 -12
  28. exponent/utils/version.py +1 -1
  29. {indent-0.1.10.dist-info → indent-0.1.12.dist-info}/METADATA +3 -3
  30. indent-0.1.12.dist-info/RECORD +52 -0
  31. exponent/core/graphql/cloud_config_queries.py +0 -77
  32. indent-0.1.10.dist-info/RECORD +0 -53
  33. {indent-0.1.10.dist-info → indent-0.1.12.dist-info}/WHEEL +0 -0
  34. {indent-0.1.10.dist-info → indent-0.1.12.dist-info}/entry_points.txt +0 -0
@@ -13,11 +13,6 @@ from exponent.commands.settings import use_settings
13
13
  from exponent.commands.types import exponent_cli_group
14
14
  from exponent.core.config import Settings
15
15
  from exponent.core.graphql.client import GraphQLClient
16
- from exponent.core.graphql.cloud_config_queries import (
17
- CREATE_CLOUD_CONFIG_MUTATION,
18
- GET_CLOUD_CONFIGS_QUERY,
19
- UPDATE_CLOUD_CONFIG_MUTATION,
20
- )
21
16
  from exponent.core.graphql.get_chats_query import GET_CHATS_QUERY
22
17
  from exponent.core.graphql.github_config_queries import (
23
18
  CHECK_GITHUB_CONFIG_VALIDITY_QUERY,
@@ -185,7 +180,7 @@ async def repos_for_github_config_task(
185
180
  help="Clear use default colors",
186
181
  )
187
182
  @use_settings
188
- def config(
183
+ def config( # noqa: PLR0913
189
184
  settings: Settings,
190
185
  set_git_warning_disabled: bool,
191
186
  set_git_warning_enabled: bool,
@@ -394,34 +389,6 @@ async def get_authenticated_user_task(
394
389
  click.echo(it)
395
390
 
396
391
 
397
- @config_cli.command(hidden=True)
398
- @use_settings
399
- def get_cloud_configs(
400
- settings: Settings,
401
- ) -> None:
402
- if not settings.api_key:
403
- redirect_to_login(settings)
404
- return
405
-
406
- run_until_complete(
407
- get_cloud_configs_task(
408
- api_key=settings.api_key,
409
- base_api_url=settings.get_base_api_url(),
410
- base_ws_url=settings.get_base_ws_url(),
411
- )
412
- )
413
-
414
-
415
- async def get_cloud_configs_task(
416
- api_key: str,
417
- base_api_url: str,
418
- base_ws_url: str,
419
- ) -> None:
420
- graphql_client = GraphQLClient(api_key, base_api_url, base_ws_url)
421
- result = await graphql_client.execute(GET_CLOUD_CONFIGS_QUERY)
422
- click.echo(result)
423
-
424
-
425
392
  async def create_github_config_task(
426
393
  api_key: str,
427
394
  base_api_url: str,
@@ -436,133 +403,6 @@ async def create_github_config_task(
436
403
  click.echo(result)
437
404
 
438
405
 
439
- @config_cli.command(hidden=True)
440
- @click.option("--github-pat", required=True, help="Github personal access token")
441
- @use_settings
442
- def create_github_config(
443
- settings: Settings,
444
- github_pat: str,
445
- ) -> None:
446
- if not settings.api_key:
447
- redirect_to_login(settings)
448
- return
449
-
450
- run_until_complete(
451
- create_github_config_task(
452
- api_key=settings.api_key,
453
- base_api_url=settings.get_base_api_url(),
454
- base_ws_url=settings.get_base_ws_url(),
455
- github_pat=github_pat,
456
- )
457
- )
458
-
459
-
460
- @config_cli.command(hidden=True)
461
- @click.option("--github-org-name", required=True, help="GitHub organization name")
462
- @click.option("--github-repo-name", required=True, help="GitHub repository name")
463
- @click.option(
464
- "--setup_commands",
465
- required=False,
466
- help="List of commands to set up and build your repo",
467
- multiple=True,
468
- )
469
- @use_settings
470
- def create_cloud_config(
471
- settings: Settings,
472
- github_org_name: str,
473
- github_repo_name: str,
474
- setup_commands: list[str] | None = None,
475
- ) -> None:
476
- if not settings.api_key:
477
- redirect_to_login(settings)
478
- return
479
-
480
- run_until_complete(
481
- create_cloud_config_task(
482
- api_key=settings.api_key,
483
- base_api_url=settings.get_base_api_url(),
484
- base_ws_url=settings.get_base_ws_url(),
485
- github_org_name=github_org_name,
486
- github_repo_name=github_repo_name,
487
- setup_commands=setup_commands,
488
- )
489
- )
490
-
491
-
492
- async def create_cloud_config_task(
493
- api_key: str,
494
- base_api_url: str,
495
- base_ws_url: str,
496
- github_org_name: str,
497
- github_repo_name: str,
498
- setup_commands: list[str] | None,
499
- ) -> None:
500
- graphql_client = GraphQLClient(api_key, base_api_url, base_ws_url)
501
- variables = {
502
- "githubOrgName": github_org_name,
503
- "githubRepoName": github_repo_name,
504
- "setupCommands": setup_commands,
505
- }
506
- result = await graphql_client.execute(CREATE_CLOUD_CONFIG_MUTATION, variables)
507
- click.echo(result)
508
-
509
-
510
- @config_cli.command(hidden=True)
511
- @click.option("--cloud-config-uuid", required=True, help="Cloud config UUID")
512
- @click.option("--github-org-name", required=True, help="GitHub organization name")
513
- @click.option("--github-repo-name", required=True, help="GitHub repository name")
514
- @click.option(
515
- "--setup_commands",
516
- required=False,
517
- help="List of commands to set up and build your repo",
518
- multiple=True,
519
- )
520
- @use_settings
521
- def update_cloud_config(
522
- settings: Settings,
523
- cloud_config_uuid: str,
524
- github_org_name: str,
525
- github_repo_name: str,
526
- setup_commands: list[str] | None = None,
527
- ) -> None:
528
- if not settings.api_key:
529
- redirect_to_login(settings)
530
- return
531
-
532
- run_until_complete(
533
- update_cloud_config_task(
534
- api_key=settings.api_key,
535
- base_api_url=settings.get_base_api_url(),
536
- base_ws_url=settings.get_base_ws_url(),
537
- cloud_config_uuid=cloud_config_uuid,
538
- github_org_name=github_org_name,
539
- github_repo_name=github_repo_name,
540
- setup_commands=setup_commands,
541
- )
542
- )
543
-
544
-
545
- async def update_cloud_config_task(
546
- api_key: str,
547
- base_api_url: str,
548
- base_ws_url: str,
549
- cloud_config_uuid: str,
550
- github_org_name: str,
551
- github_repo_name: str,
552
- setup_commands: list[str] | None,
553
- ) -> None:
554
- graphql_client = GraphQLClient(api_key, base_api_url, base_ws_url)
555
- variables = {
556
- "cloudConfigUuid": cloud_config_uuid,
557
- "githubOrgName": github_org_name,
558
- "githubRepoName": github_repo_name,
559
- "setupCommands": setup_commands,
560
- }
561
-
562
- result = await graphql_client.execute(UPDATE_CLOUD_CONFIG_MUTATION, variables)
563
- click.echo(result)
564
-
565
-
566
406
  @config_cli.command(hidden=True)
567
407
  @use_settings
568
408
  def refresh_key(settings: Settings) -> None:
@@ -61,12 +61,19 @@ def run_cli() -> None:
61
61
  hidden=True,
62
62
  required=False,
63
63
  )
64
+ @click.option(
65
+ "--timeout-seconds",
66
+ type=int,
67
+ help="Number of seconds without receiving a request before shutting down",
68
+ envvar="INDENT_TIMEOUT_SECONDS",
69
+ )
64
70
  @use_settings
65
71
  def run(
66
72
  settings: Settings,
67
73
  chat_id: str | None = None,
68
74
  prompt: str | None = None,
69
75
  workflow_id: str | None = None,
76
+ timeout_seconds: int | None = None,
70
77
  ) -> None:
71
78
  """[default] Start or reconnect to an Indent session."""
72
79
  check_exponent_version_and_upgrade(settings)
@@ -104,7 +111,9 @@ def run(
104
111
  launch_exponent_browser(settings.environment, base_url, chat_uuid)
105
112
 
106
113
  while True:
107
- result = run_chat(loop, api_key, chat_uuid, settings, prompt, workflow_id)
114
+ result = run_chat(
115
+ loop, api_key, chat_uuid, settings, prompt, workflow_id, timeout_seconds
116
+ )
108
117
  if result is None or isinstance(result, WSDisconnected):
109
118
  # NOTE: None here means that handle_connection_changes exited
110
119
  # first. We should likely have a different message for this.
@@ -112,11 +121,11 @@ def run(
112
121
  click.secho(f"Error: {result.error_message}", fg="red")
113
122
  sys.exit(10)
114
123
  else:
115
- print("Disconnected upon user request, shutting down...")
124
+ click.echo("Disconnected upon user request, shutting down...")
116
125
  break
117
126
  elif isinstance(result, SwitchCLIChat):
118
127
  chat_uuid = result.new_chat_uuid
119
- print("\nSwitching chats...")
128
+ click.echo("\nSwitching chats...")
120
129
  else:
121
130
  assert_unreachable(result)
122
131
 
@@ -128,6 +137,7 @@ def run_chat(
128
137
  settings: Settings,
129
138
  prompt: str | None,
130
139
  workflow_id: str | None,
140
+ timeout_seconds: int | None,
131
141
  ) -> REMOTE_EXECUTION_CLIENT_EXIT_INFO | None:
132
142
  start_ts = time.time()
133
143
  base_url = settings.base_url
@@ -135,7 +145,7 @@ def run_chat(
135
145
  base_ws_url = settings.get_base_ws_url()
136
146
 
137
147
  print_exponent_message(base_url, chat_uuid)
138
- print()
148
+ click.echo()
139
149
 
140
150
  connection_tracker = ConnectionTracker()
141
151
 
@@ -149,6 +159,7 @@ def run_chat(
149
159
  prompt=prompt,
150
160
  workflow_id=workflow_id,
151
161
  connection_tracker=connection_tracker,
162
+ timeout_seconds=timeout_seconds,
152
163
  )
153
164
  )
154
165
 
@@ -179,27 +190,27 @@ async def handle_connection_changes(
179
190
  try:
180
191
  async with timeout(5):
181
192
  assert await connection_tracker.next_change()
182
- print(ready_message(start_ts))
193
+ click.echo(ready_message(start_ts))
183
194
  except TimeoutError:
184
195
  spinner = Spinner("Connecting...")
185
196
  spinner.show()
186
197
  assert await connection_tracker.next_change()
187
198
  spinner.hide()
188
- print(ready_message(start_ts))
199
+ click.echo(ready_message(start_ts))
189
200
 
190
201
  while True:
191
202
  assert not await connection_tracker.next_change()
192
203
 
193
- print("Disconnected...", end="")
204
+ click.echo("Disconnected...", nl=False)
194
205
  await asyncio.sleep(1)
195
206
  spinner = Spinner("Reconnecting...")
196
207
  spinner.show()
197
208
  assert await connection_tracker.next_change()
198
209
  spinner.hide()
199
- print("\x1b[1;32m✓ Reconnected", end="")
210
+ click.echo("\x1b[1;32m✓ Reconnected", nl=False)
200
211
  sys.stdout.flush()
201
212
  await asyncio.sleep(1)
202
- print("\r\x1b[0m\x1b[2K", end="")
213
+ click.echo("\r\x1b[0m\x1b[2K", nl=False)
203
214
  sys.stdout.flush()
204
215
 
205
216
 
@@ -98,9 +98,9 @@ class Spinner:
98
98
  while True:
99
99
  t = time.time() - base_time
100
100
  i = round(t * self.animation_speed) % len(self.animation_chars)
101
- print(
101
+ click.echo(
102
102
  f"\r{style_start}{self.animation_chars[i]} {self.text}{style_end}",
103
- end="",
103
+ nl=False,
104
104
  )
105
105
  await asyncio.sleep(0.1)
106
106
 
@@ -112,7 +112,7 @@ class Spinner:
112
112
 
113
113
  self.task.cancel()
114
114
  self.task = None
115
- print("\r\x1b[0m\x1b[2K", end="")
115
+ click.echo("\r\x1b[0m\x1b[2K", nl=False)
116
116
  sys.stdout.flush()
117
117
 
118
118
 
@@ -47,7 +47,7 @@ def trigger(settings: Settings, workflow_type: str) -> None:
47
47
 
48
48
  while True:
49
49
  result = run_chat(
50
- loop, settings.api_key, response.chat_uuid, settings, None, None
50
+ loop, settings.api_key, response.chat_uuid, settings, None, None, None
51
51
  )
52
52
  if result is None or isinstance(result, WSDisconnected):
53
53
  # NOTE: None here means that handle_connection_changes exited
@@ -56,7 +56,7 @@ def trigger(settings: Settings, workflow_type: str) -> None:
56
56
  click.secho(f"Error: {result.error_message}", fg="red")
57
57
  sys.exit(10)
58
58
  else:
59
- print("Disconnected upon user request, shutting down...")
59
+ click.echo("Disconnected upon user request, shutting down...")
60
60
  break
61
61
  else:
62
62
  raise click.ClickException("Workflow run exited unexpectedly")
exponent/core/config.py CHANGED
@@ -24,7 +24,6 @@ logger = logging.getLogger(__name__)
24
24
 
25
25
 
26
26
  def is_editable_install() -> bool:
27
-
28
27
  if os.getenv("ENVIRONMENT") == "test" or os.getenv("EXPONENT_TEST_AUTO_UPGRADE"):
29
28
  # We should explicitly set these variables
30
29
  # in test when needed
@@ -73,3 +73,117 @@ mutation CreateCloudChat($configId: String!) {
73
73
  }
74
74
  }
75
75
  """
76
+
77
+
78
+ CREATE_CLOUD_CHAT_FROM_REPOSITORY_MUTATION = """
79
+ mutation CreateCloudChatFromRepository($repositoryId: String!) {
80
+ createCloudChat(repositoryId: $repositoryId) {
81
+ __typename
82
+ ...on Chat {
83
+ chatUuid
84
+ }
85
+ ...on UnauthenticatedError {
86
+ message
87
+ }
88
+ ...on ChatNotFoundError {
89
+ message
90
+ }
91
+ ...on CloudConfigNotFoundError {
92
+ message
93
+ }
94
+ ...on GithubConfigNotFoundError {
95
+ message
96
+ }
97
+ ...on CloudSessionError {
98
+ message
99
+ }
100
+ }
101
+ }
102
+ """
103
+
104
+
105
+ ENABLE_CLOUD_REPOSITORY_MUTATION = """
106
+ mutation EnableCloudRepository($orgName: String!, $repoName: String!) {
107
+ enableCloudRepository(orgName: $orgName, repoName: $repoName) {
108
+ __typename
109
+ ...on ContainerImage {
110
+ buildRef
111
+ createdAt
112
+ updatedAt
113
+ }
114
+ ...on UnauthenticatedError {
115
+ message
116
+ }
117
+ ...on CloudConfigNotFoundError {
118
+ message
119
+ }
120
+ ...on GithubConfigNotFoundError {
121
+ message
122
+ }
123
+ ...on CloudSessionError {
124
+ message
125
+ }
126
+ ...on Error {
127
+ message
128
+ }
129
+ }
130
+ }
131
+ """
132
+
133
+
134
+ INCREMENTAL_BUILD_CLOUD_REPOSITORY_MUTATION = """
135
+ mutation IncrementalBuildCloudRepository($orgName: String!, $repoName: String!) {
136
+ incrementalBuildCloudRepository(orgName: $orgName, repoName: $repoName) {
137
+ __typename
138
+ ...on ContainerImage {
139
+ buildRef
140
+ createdAt
141
+ updatedAt
142
+ }
143
+ ...on UnauthenticatedError {
144
+ message
145
+ }
146
+ ...on CloudConfigNotFoundError {
147
+ message
148
+ }
149
+ ...on GithubConfigNotFoundError {
150
+ message
151
+ }
152
+ ...on CloudSessionError {
153
+ message
154
+ }
155
+ ...on Error {
156
+ message
157
+ }
158
+ }
159
+ }
160
+ """
161
+
162
+
163
+ REBUILD_CLOUD_REPOSITORY_MUTATION = """
164
+ mutation RebuildCloudRepository($orgName: String!, $repoName: String!) {
165
+ rebuildCloudRepository(orgName: $orgName, repoName: $repoName) {
166
+ __typename
167
+ ...on ContainerImage {
168
+ buildRef
169
+ createdAt
170
+ updatedAt
171
+ }
172
+ ...on UnauthenticatedError {
173
+ message
174
+ }
175
+ ...on CloudConfigNotFoundError {
176
+ message
177
+ }
178
+ ...on GithubConfigNotFoundError {
179
+ message
180
+ }
181
+ ...on CloudSessionError {
182
+ message
183
+ }
184
+ ...on Error {
185
+ message
186
+ }
187
+ }
188
+ }
189
+ """
@@ -1,3 +1,26 @@
1
+ GITHUB_REPOSITORIES_QUERY: str = """
2
+ query GithubRepositories {
3
+ githubRepositories {
4
+ __typename
5
+ ... on GithubRepositories {
6
+ repositories {
7
+ id
8
+ githubOrgName
9
+ githubRepoName
10
+ baseHost
11
+ containerImageId
12
+ createdAt
13
+ updatedAt
14
+ }
15
+ }
16
+ ... on Error {
17
+ message
18
+ }
19
+ }
20
+ }
21
+ """
22
+
23
+
1
24
  EVENTS_FOR_CHAT_QUERY: str = """query EventsForChat($chatUuid: UUID!) {
2
25
  eventsForChat(chatUuid: $chatUuid) {
3
26
  ... on EventHistory {