indent 0.1.21__tar.gz → 0.1.22__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.
Files changed (52) hide show
  1. {indent-0.1.21 → indent-0.1.22}/PKG-INFO +2 -1
  2. {indent-0.1.21 → indent-0.1.22}/exponent/__init__.py +2 -2
  3. {indent-0.1.21 → indent-0.1.22}/exponent/commands/cloud_commands.py +2 -0
  4. {indent-0.1.21 → indent-0.1.22}/exponent/core/graphql/mutations.py +2 -2
  5. indent-0.1.22/exponent/core/remote_execution/port_utils.py +73 -0
  6. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/system_context.py +2 -0
  7. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/types.py +9 -0
  8. {indent-0.1.21 → indent-0.1.22}/pyproject.toml +1 -0
  9. {indent-0.1.21 → indent-0.1.22}/.gitignore +0 -0
  10. {indent-0.1.21 → indent-0.1.22}/exponent/cli.py +0 -0
  11. {indent-0.1.21 → indent-0.1.22}/exponent/commands/common.py +0 -0
  12. {indent-0.1.21 → indent-0.1.22}/exponent/commands/config_commands.py +0 -0
  13. {indent-0.1.21 → indent-0.1.22}/exponent/commands/run_commands.py +0 -0
  14. {indent-0.1.21 → indent-0.1.22}/exponent/commands/settings.py +0 -0
  15. {indent-0.1.21 → indent-0.1.22}/exponent/commands/types.py +0 -0
  16. {indent-0.1.21 → indent-0.1.22}/exponent/commands/upgrade.py +0 -0
  17. {indent-0.1.21 → indent-0.1.22}/exponent/commands/utils.py +0 -0
  18. {indent-0.1.21 → indent-0.1.22}/exponent/core/config.py +0 -0
  19. {indent-0.1.21 → indent-0.1.22}/exponent/core/graphql/__init__.py +0 -0
  20. {indent-0.1.21 → indent-0.1.22}/exponent/core/graphql/client.py +0 -0
  21. {indent-0.1.21 → indent-0.1.22}/exponent/core/graphql/get_chats_query.py +0 -0
  22. {indent-0.1.21 → indent-0.1.22}/exponent/core/graphql/queries.py +0 -0
  23. {indent-0.1.21 → indent-0.1.22}/exponent/core/graphql/subscriptions.py +0 -0
  24. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/checkpoints.py +0 -0
  25. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/cli_rpc_types.py +0 -0
  26. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/client.py +0 -0
  27. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/code_execution.py +0 -0
  28. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/default_env.py +0 -0
  29. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/error_info.py +0 -0
  30. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/exceptions.py +0 -0
  31. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/file_write.py +0 -0
  32. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/files.py +0 -0
  33. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/git.py +0 -0
  34. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/http_fetch.py +0 -0
  35. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/languages/python_execution.py +0 -0
  36. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/languages/shell_streaming.py +0 -0
  37. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/languages/types.py +0 -0
  38. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/session.py +0 -0
  39. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/tool_execution.py +0 -0
  40. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/tool_type_utils.py +0 -0
  41. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/truncation.py +0 -0
  42. {indent-0.1.21 → indent-0.1.22}/exponent/core/remote_execution/utils.py +0 -0
  43. {indent-0.1.21 → indent-0.1.22}/exponent/core/types/__init__.py +0 -0
  44. {indent-0.1.21 → indent-0.1.22}/exponent/core/types/command_data.py +0 -0
  45. {indent-0.1.21 → indent-0.1.22}/exponent/core/types/event_types.py +0 -0
  46. {indent-0.1.21 → indent-0.1.22}/exponent/core/types/generated/__init__.py +0 -0
  47. {indent-0.1.21 → indent-0.1.22}/exponent/core/types/generated/strategy_info.py +0 -0
  48. {indent-0.1.21 → indent-0.1.22}/exponent/migration-docs/login.md +0 -0
  49. {indent-0.1.21 → indent-0.1.22}/exponent/py.typed +0 -0
  50. {indent-0.1.21 → indent-0.1.22}/exponent/utils/__init__.py +0 -0
  51. {indent-0.1.21 → indent-0.1.22}/exponent/utils/colors.py +0 -0
  52. {indent-0.1.21 → indent-0.1.22}/exponent/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indent
3
- Version: 0.1.21
3
+ Version: 0.1.22
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
@@ -22,6 +22,7 @@ Requires-Dist: msgspec>=0.19.0
22
22
  Requires-Dist: packaging~=24.1
23
23
  Requires-Dist: pip<26,>=25.0.1
24
24
  Requires-Dist: prompt-toolkit<4,>=3.0.36
25
+ Requires-Dist: psutil<7,>=5.9.0
25
26
  Requires-Dist: pydantic-ai==0.0.30
26
27
  Requires-Dist: pydantic-settings<3,>=2.2.1
27
28
  Requires-Dist: pydantic[email]<3,>=2.6.4
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.1.21'
32
- __version_tuple__ = version_tuple = (0, 1, 21)
31
+ __version__ = version = '0.1.22'
32
+ __version_tuple__ = version_tuple = (0, 1, 22)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -111,6 +111,7 @@ async def create_cloud_chat_from_repository(
111
111
  base_api_url: str,
112
112
  base_ws_url: str,
113
113
  repository_id: str,
114
+ provider: str | None = None,
114
115
  ) -> dict[str, Any]:
115
116
  graphql_client = GraphQLClient(
116
117
  api_key=api_key, base_api_url=base_api_url, base_ws_url=base_ws_url
@@ -118,6 +119,7 @@ async def create_cloud_chat_from_repository(
118
119
 
119
120
  variables = {
120
121
  "repositoryId": repository_id,
122
+ "provider": provider,
121
123
  }
122
124
 
123
125
  result = await graphql_client.execute(
@@ -76,8 +76,8 @@ mutation CreateCloudChat($configId: String!) {
76
76
 
77
77
 
78
78
  CREATE_CLOUD_CHAT_FROM_REPOSITORY_MUTATION = """
79
- mutation CreateCloudChatFromRepository($repositoryId: String!) {
80
- createCloudChat(repositoryId: $repositoryId) {
79
+ mutation CreateCloudChatFromRepository($repositoryId: String!, $provider: String) {
80
+ createCloudChat(repositoryId: $repositoryId, provider: $provider) {
81
81
  __typename
82
82
  ...on Chat {
83
83
  chatUuid
@@ -0,0 +1,73 @@
1
+ import time
2
+
3
+ import psutil
4
+
5
+ from exponent.core.remote_execution.types import PortInfo
6
+
7
+
8
+ def get_port_usage() -> list[PortInfo] | None:
9
+ """
10
+ Get information about all listening ports on the system.
11
+
12
+ Returns:
13
+ List of PortInfo objects containing process name, port, protocol, pid, and uptime.
14
+ Returns None if there's a permission error.
15
+ Returns empty list if no listening ports are found.
16
+ """
17
+ try:
18
+ connections = psutil.net_connections(kind="tcp")
19
+ except (psutil.AccessDenied, PermissionError):
20
+ # If we don't have permission to see connections, return None
21
+ return None
22
+ except Exception:
23
+ # For any other unexpected errors, return None
24
+ return None
25
+
26
+ port_info_list: list[PortInfo] = []
27
+ current_time = time.time()
28
+
29
+ for conn in connections:
30
+ # Only include TCP ports in LISTEN state
31
+ if conn.status != "LISTEN":
32
+ continue
33
+
34
+ # Skip if no local address (shouldn't happen for LISTEN, but be safe)
35
+ if not conn.laddr:
36
+ continue
37
+
38
+ port = conn.laddr.port
39
+ pid = conn.pid
40
+
41
+ # Try to get process information
42
+ process_name = "unknown"
43
+ uptime_seconds = None
44
+
45
+ if pid:
46
+ try:
47
+ process = psutil.Process(pid)
48
+ process_name = process.name()
49
+
50
+ # Calculate uptime
51
+ create_time = process.create_time()
52
+ uptime_seconds = current_time - create_time
53
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
54
+ # Process disappeared or we don't have permission
55
+ pass
56
+ except Exception:
57
+ # Any other unexpected error, just skip process info
58
+ pass
59
+
60
+ port_info = PortInfo(
61
+ process_name=process_name,
62
+ port=port,
63
+ protocol="TCP",
64
+ pid=pid,
65
+ uptime_seconds=uptime_seconds,
66
+ )
67
+ port_info_list.append(port_info)
68
+
69
+ # Limit to 50 ports to avoid bloating the heartbeat payload
70
+ if len(port_info_list) >= 50:
71
+ break
72
+
73
+ return port_info_list
@@ -4,6 +4,7 @@ import platform
4
4
 
5
5
  from exponent.core.remote_execution.git import get_git_info
6
6
  from exponent.core.remote_execution.languages import python_execution
7
+ from exponent.core.remote_execution.port_utils import get_port_usage
7
8
  from exponent.core.remote_execution.types import (
8
9
  SystemInfo,
9
10
  )
@@ -17,6 +18,7 @@ async def get_system_info(working_directory: str) -> SystemInfo:
17
18
  shell=_get_user_shell(),
18
19
  git=await get_git_info(working_directory),
19
20
  python_env=python_execution.get_python_env_info(),
21
+ port_usage=get_port_usage(),
20
22
  )
21
23
 
22
24
 
@@ -120,6 +120,14 @@ class PythonEnvInfo(BaseModel):
120
120
  provider: Literal["venv", "pyenv", "pipenv", "conda"] | None = "pyenv"
121
121
 
122
122
 
123
+ class PortInfo(BaseModel):
124
+ process_name: str
125
+ port: int
126
+ protocol: str
127
+ pid: int | None
128
+ uptime_seconds: float | None
129
+
130
+
123
131
  class SystemInfo(BaseModel):
124
132
  name: str
125
133
  cwd: str
@@ -127,6 +135,7 @@ class SystemInfo(BaseModel):
127
135
  shell: str
128
136
  git: GitInfo | None
129
137
  python_env: PythonEnvInfo | None
138
+ port_usage: list[PortInfo] | None = None
130
139
 
131
140
 
132
141
  class HeartbeatInfo(BaseModel):
@@ -19,6 +19,7 @@ dependencies = [
19
19
  "jupyter-client>=8.6.1,<9",
20
20
  "packaging~=24.1",
21
21
  "prompt-toolkit>=3.0.36,<4",
22
+ "psutil>=5.9.0,<7",
22
23
  "pydantic[email]>=2.6.4,<3",
23
24
  "pydantic-settings>=2.2.1,<3",
24
25
  "pydantic-ai==0.0.30",
File without changes
File without changes
File without changes
File without changes