indent 0.1.3__tar.gz → 0.1.5__tar.gz

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 (56) hide show
  1. {indent-0.1.3 → indent-0.1.5}/PKG-INFO +1 -1
  2. indent-0.1.5/exponent/__init__.py +1 -0
  3. {indent-0.1.3 → indent-0.1.5}/exponent/cli.py +2 -0
  4. indent-0.1.5/exponent/commands/workflow_commands.py +111 -0
  5. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/cli_rpc_types.py +0 -14
  6. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/client.py +16 -0
  7. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/types.py +17 -0
  8. {indent-0.1.3 → indent-0.1.5}/pyproject.toml +1 -1
  9. indent-0.1.3/exponent/__init__.py +0 -1
  10. {indent-0.1.3 → indent-0.1.5}/.gitignore +0 -0
  11. {indent-0.1.3 → indent-0.1.5}/exponent/commands/cloud_commands.py +0 -0
  12. {indent-0.1.3 → indent-0.1.5}/exponent/commands/common.py +0 -0
  13. {indent-0.1.3 → indent-0.1.5}/exponent/commands/config_commands.py +0 -0
  14. {indent-0.1.3 → indent-0.1.5}/exponent/commands/github_app_commands.py +0 -0
  15. {indent-0.1.3 → indent-0.1.5}/exponent/commands/listen_commands.py +0 -0
  16. {indent-0.1.3 → indent-0.1.5}/exponent/commands/run_commands.py +0 -0
  17. {indent-0.1.3 → indent-0.1.5}/exponent/commands/settings.py +0 -0
  18. {indent-0.1.3 → indent-0.1.5}/exponent/commands/shell_commands.py +0 -0
  19. {indent-0.1.3 → indent-0.1.5}/exponent/commands/theme.py +0 -0
  20. {indent-0.1.3 → indent-0.1.5}/exponent/commands/types.py +0 -0
  21. {indent-0.1.3 → indent-0.1.5}/exponent/commands/upgrade.py +0 -0
  22. {indent-0.1.3 → indent-0.1.5}/exponent/commands/utils.py +0 -0
  23. {indent-0.1.3 → indent-0.1.5}/exponent/core/config.py +0 -0
  24. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/__init__.py +0 -0
  25. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/client.py +0 -0
  26. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/cloud_config_queries.py +0 -0
  27. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/get_chats_query.py +0 -0
  28. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/github_config_queries.py +0 -0
  29. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/mutations.py +0 -0
  30. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/queries.py +0 -0
  31. {indent-0.1.3 → indent-0.1.5}/exponent/core/graphql/subscriptions.py +0 -0
  32. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/checkpoints.py +0 -0
  33. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/code_execution.py +0 -0
  34. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/error_info.py +0 -0
  35. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/exceptions.py +0 -0
  36. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/file_write.py +0 -0
  37. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/files.py +0 -0
  38. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/git.py +0 -0
  39. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/languages/python_execution.py +0 -0
  40. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/languages/shell_streaming.py +0 -0
  41. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/languages/types.py +0 -0
  42. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/session.py +0 -0
  43. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/system_context.py +0 -0
  44. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/tool_execution.py +0 -0
  45. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/truncation.py +0 -0
  46. {indent-0.1.3 → indent-0.1.5}/exponent/core/remote_execution/utils.py +0 -0
  47. {indent-0.1.3 → indent-0.1.5}/exponent/core/types/__init__.py +0 -0
  48. {indent-0.1.3 → indent-0.1.5}/exponent/core/types/command_data.py +0 -0
  49. {indent-0.1.3 → indent-0.1.5}/exponent/core/types/event_types.py +0 -0
  50. {indent-0.1.3 → indent-0.1.5}/exponent/core/types/generated/__init__.py +0 -0
  51. {indent-0.1.3 → indent-0.1.5}/exponent/core/types/generated/strategy_info.py +0 -0
  52. {indent-0.1.3 → indent-0.1.5}/exponent/migration-docs/login.md +0 -0
  53. {indent-0.1.3 → indent-0.1.5}/exponent/py.typed +0 -0
  54. {indent-0.1.3 → indent-0.1.5}/exponent/utils/__init__.py +0 -0
  55. {indent-0.1.3 → indent-0.1.5}/exponent/utils/colors.py +0 -0
  56. {indent-0.1.3 → indent-0.1.5}/exponent/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indent
3
- Version: 0.1.3
3
+ Version: 0.1.5
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
@@ -0,0 +1 @@
1
+ __version__ = "0.1.5" # Keep in sync with pyproject.toml
@@ -10,6 +10,7 @@ from exponent.commands.run_commands import run_cli
10
10
  from exponent.commands.shell_commands import shell_cli
11
11
  from exponent.commands.types import ExponentGroup, exponent_cli_group
12
12
  from exponent.commands.upgrade import upgrade_cli
13
+ from exponent.commands.workflow_commands import workflow_cli
13
14
  from exponent.utils.version import (
14
15
  get_installed_version,
15
16
  )
@@ -35,6 +36,7 @@ sources: list[ExponentGroup] = [
35
36
  cloud_cli, # Cloud commands
36
37
  listen_cli, # Listen to chat events
37
38
  github_app_cli, # Setup github app installation
39
+ workflow_cli, # Workflow commands
38
40
  ]
39
41
 
40
42
  for source in sources:
@@ -0,0 +1,111 @@
1
+ import asyncio
2
+ import os
3
+ import sys
4
+ from typing import cast
5
+
6
+ import click
7
+
8
+ from exponent.commands.run_commands import run_chat
9
+ from exponent.commands.settings import use_settings
10
+ from exponent.commands.types import exponent_cli_group
11
+ from exponent.core.config import Settings
12
+ from exponent.core.remote_execution.client import RemoteExecutionClient, WSDisconnected
13
+ from exponent.core.remote_execution.types import (
14
+ PrReviewWorkflowInput,
15
+ WorkflowTriggerResponse,
16
+ )
17
+
18
+
19
+ @exponent_cli_group(name="workflow")
20
+ def workflow_cli() -> None:
21
+ """Workflow commands."""
22
+ pass
23
+
24
+
25
+ @workflow_cli.group()
26
+ def workflow() -> None:
27
+ """Workflow management commands."""
28
+ pass
29
+
30
+
31
+ @workflow.command()
32
+ @use_settings
33
+ @click.argument("workflow_type", type=click.STRING)
34
+ def trigger(settings: Settings, workflow_type: str) -> None:
35
+ """Trigger a workflow."""
36
+
37
+ if not settings.api_key:
38
+ raise click.ClickException(
39
+ "No API key found. Use `indent login` to set your API key."
40
+ )
41
+
42
+ if workflow_type != "pr_review":
43
+ raise click.UsageError("Invalid workflow name. Only 'pr_review' is supported.")
44
+
45
+ loop = asyncio.get_event_loop()
46
+ response = loop.run_until_complete(trigger_pr_review_workflow(settings))
47
+
48
+ while True:
49
+ result = run_chat(
50
+ loop, settings.api_key, response.chat_uuid, settings, None, None
51
+ )
52
+ if result is None or isinstance(result, WSDisconnected):
53
+ # NOTE: None here means that handle_connection_changes exited
54
+ # first. We should likely have a different message for this.
55
+ if result and result.error_message:
56
+ click.secho(f"Error: {result.error_message}", fg="red")
57
+ sys.exit(10)
58
+ else:
59
+ print("Disconnected upon user request, shutting down...")
60
+ break
61
+ else:
62
+ raise click.ClickException("Workflow run exited unexpectedly")
63
+
64
+
65
+ async def _subprocess_check_output(command: str) -> str:
66
+ process = await asyncio.create_subprocess_shell(
67
+ command,
68
+ stdout=asyncio.subprocess.PIPE,
69
+ stderr=asyncio.subprocess.STDOUT,
70
+ )
71
+ stdout, _ = await process.communicate()
72
+
73
+ if process.returncode != 0:
74
+ output = stdout.decode().strip()
75
+ raise click.ClickException(
76
+ f"Command '{command}' failed with exit code {process.returncode}:\n{output}"
77
+ )
78
+
79
+ return stdout.decode().strip()
80
+
81
+
82
+ async def trigger_pr_review_workflow(settings: Settings) -> WorkflowTriggerResponse:
83
+ origin_url = await _subprocess_check_output("git ls-remote --get-url origin")
84
+ url = origin_url.strip().removesuffix(".git")
85
+ remote = url.split(":")[-1]
86
+ owner, repo = remote.split("/")[-2:]
87
+
88
+ pr_number_str = os.environ.get("PR_NUMBER")
89
+ if not pr_number_str:
90
+ raise click.ClickException("PR_NUMBER environment variable is not set")
91
+ try:
92
+ pr_number = int(pr_number_str)
93
+ except ValueError:
94
+ raise click.ClickException(
95
+ "PR_NUMBER environment variable is not a valid integer"
96
+ )
97
+
98
+ async with RemoteExecutionClient.session(
99
+ api_key=cast(str, settings.api_key),
100
+ base_url=settings.get_base_api_url(),
101
+ base_ws_url=settings.get_base_ws_url(),
102
+ working_directory=os.getcwd(),
103
+ ) as client:
104
+ return await client.trigger_workflow(
105
+ workflow_name="pr_review",
106
+ workflow_input=PrReviewWorkflowInput(
107
+ repo_owner=owner,
108
+ repo_name=repo,
109
+ pr_number=pr_number,
110
+ ),
111
+ )
@@ -104,20 +104,6 @@ class GrepToolResult(ToolResult, tag=GREP_TOOL_NAME):
104
104
  truncated: bool = False
105
105
 
106
106
 
107
- WEB_FETCH_TOOL_NAME = "web_fetch"
108
-
109
-
110
- class WebFetchToolInput(ToolInput, tag=WEB_FETCH_TOOL_NAME):
111
- query: str
112
-
113
-
114
- class WebFetchToolResult(ToolResult, tag=WEB_FETCH_TOOL_NAME):
115
- url: str
116
- title: bool = False
117
- encrypted_content: str | None = None
118
- page_age: str | None = None
119
-
120
-
121
107
  BASH_TOOL_NAME = "bash"
122
108
 
123
109
 
@@ -54,9 +54,12 @@ from exponent.core.remote_execution.types import (
54
54
  CreateChatResponse,
55
55
  GitInfo,
56
56
  HeartbeatInfo,
57
+ PrReviewWorkflowInput,
57
58
  RemoteExecutionResponseType,
58
59
  RunWorkflowRequest,
59
60
  StreamingCodeExecutionRequest,
61
+ WorkflowTriggerRequest,
62
+ WorkflowTriggerResponse,
60
63
  )
61
64
  from exponent.core.remote_execution.utils import (
62
65
  deserialize_api_response,
@@ -378,6 +381,7 @@ class RemoteExecutionClient:
378
381
  )
379
382
  return cast(dict[str, Any], response.json())
380
383
 
384
+ # deprecated
381
385
  async def run_workflow(self, chat_uuid: str, workflow_id: str) -> dict[str, Any]:
382
386
  response = await self.api_client.post(
383
387
  "/api/remote_execution/run_workflow",
@@ -393,6 +397,18 @@ class RemoteExecutionClient:
393
397
  )
394
398
  return cast(dict[str, Any], response.json())
395
399
 
400
+ async def trigger_workflow(
401
+ self, workflow_name: str, workflow_input: PrReviewWorkflowInput
402
+ ) -> WorkflowTriggerResponse:
403
+ response = await self.api_client.post(
404
+ "/api/remote_execution/trigger_workflow",
405
+ json=WorkflowTriggerRequest(
406
+ workflow_name=workflow_name,
407
+ workflow_input=workflow_input,
408
+ ).model_dump(),
409
+ )
410
+ return await deserialize_api_response(response, WorkflowTriggerResponse)
411
+
396
412
  async def get_heartbeat_info(self) -> HeartbeatInfo:
397
413
  return HeartbeatInfo(
398
414
  system_info=await system_context.get_system_info(self.working_directory),
@@ -42,6 +42,23 @@ class RunWorkflowRequest(BaseModel):
42
42
  workflow_id: str
43
43
 
44
44
 
45
+ # note: before adding fields here, probably update
46
+ # get_workflow_run_by_trigger db query
47
+ class PrReviewWorkflowInput(BaseModel):
48
+ repo_owner: str
49
+ repo_name: str
50
+ pr_number: int
51
+
52
+
53
+ class WorkflowTriggerRequest(BaseModel):
54
+ workflow_name: str
55
+ workflow_input: PrReviewWorkflowInput
56
+
57
+
58
+ class WorkflowTriggerResponse(BaseModel):
59
+ chat_uuid: str
60
+
61
+
45
62
  class ExecutionEndResponse(BaseModel):
46
63
  execution_ended: bool
47
64
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "indent"
7
- version = "0.1.3"
7
+ version = "0.1.5"
8
8
  description = "Indent is an AI Pair Programmer"
9
9
  authors = [{ name = "Sashank Thupukari", email = "sashank@exponent.run" }]
10
10
  requires-python = ">=3.10,<3.13"
@@ -1 +0,0 @@
1
- __version__ = "0.1.3" # Keep in sync with pyproject.toml
File without changes
File without changes
File without changes
File without changes
File without changes