indent 0.1.20__py3-none-any.whl → 0.1.28__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.
- exponent/__init__.py +2 -2
- exponent/commands/cloud_commands.py +2 -87
- exponent/commands/common.py +3 -0
- exponent/core/config.py +1 -1
- exponent/core/container_build/__init__.py +0 -0
- exponent/core/container_build/types.py +25 -0
- exponent/core/graphql/mutations.py +2 -31
- exponent/core/graphql/queries.py +0 -3
- exponent/core/remote_execution/cli_rpc_types.py +183 -13
- exponent/core/remote_execution/client.py +265 -64
- exponent/core/remote_execution/code_execution.py +26 -7
- exponent/core/remote_execution/languages/shell_streaming.py +3 -5
- exponent/core/remote_execution/port_utils.py +73 -0
- exponent/core/remote_execution/system_context.py +2 -0
- exponent/core/remote_execution/terminal_session.py +517 -0
- exponent/core/remote_execution/terminal_types.py +29 -0
- exponent/core/remote_execution/tool_execution.py +151 -11
- exponent/core/remote_execution/truncation.py +1 -3
- exponent/core/remote_execution/types.py +32 -1
- exponent/utils/version.py +1 -0
- {indent-0.1.20.dist-info → indent-0.1.28.dist-info}/METADATA +4 -2
- {indent-0.1.20.dist-info → indent-0.1.28.dist-info}/RECORD +24 -19
- {indent-0.1.20.dist-info → indent-0.1.28.dist-info}/WHEEL +0 -0
- {indent-0.1.20.dist-info → indent-0.1.28.dist-info}/entry_points.txt +0 -0
exponent/__init__.py
CHANGED
|
@@ -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.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
31
|
+
__version__ = version = '0.1.28'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 28)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -23,7 +23,6 @@ from exponent.core.graphql.client import GraphQLClient
|
|
|
23
23
|
from exponent.core.graphql.mutations import (
|
|
24
24
|
CREATE_CLOUD_CHAT_FROM_REPOSITORY_MUTATION,
|
|
25
25
|
ENABLE_CLOUD_REPOSITORY_MUTATION,
|
|
26
|
-
INCREMENTAL_BUILD_CLOUD_REPOSITORY_MUTATION,
|
|
27
26
|
REBUILD_CLOUD_REPOSITORY_MUTATION,
|
|
28
27
|
START_CHAT_TURN_MUTATION,
|
|
29
28
|
)
|
|
@@ -62,32 +61,6 @@ async def enable_cloud_repository(
|
|
|
62
61
|
return cast(dict[str, Any], result["enableCloudRepository"])
|
|
63
62
|
|
|
64
63
|
|
|
65
|
-
async def incremental_build_cloud_repository(
|
|
66
|
-
api_key: str,
|
|
67
|
-
base_api_url: str,
|
|
68
|
-
base_ws_url: str,
|
|
69
|
-
org_name: str,
|
|
70
|
-
repo_name: str,
|
|
71
|
-
) -> dict[str, Any]:
|
|
72
|
-
graphql_client = GraphQLClient(
|
|
73
|
-
api_key=api_key, base_api_url=base_api_url, base_ws_url=base_ws_url
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
variables = {
|
|
77
|
-
"orgName": org_name,
|
|
78
|
-
"repoName": repo_name,
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
result = await graphql_client.execute(
|
|
82
|
-
INCREMENTAL_BUILD_CLOUD_REPOSITORY_MUTATION,
|
|
83
|
-
variables,
|
|
84
|
-
"IncrementalBuildCloudRepository",
|
|
85
|
-
timeout=120,
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
return cast(dict[str, Any], result["incrementalBuildCloudRepository"])
|
|
89
|
-
|
|
90
|
-
|
|
91
64
|
async def rebuild_cloud_repository(
|
|
92
65
|
api_key: str,
|
|
93
66
|
base_api_url: str,
|
|
@@ -138,6 +111,7 @@ async def create_cloud_chat_from_repository(
|
|
|
138
111
|
base_api_url: str,
|
|
139
112
|
base_ws_url: str,
|
|
140
113
|
repository_id: str,
|
|
114
|
+
provider: str | None = None,
|
|
141
115
|
) -> dict[str, Any]:
|
|
142
116
|
graphql_client = GraphQLClient(
|
|
143
117
|
api_key=api_key, base_api_url=base_api_url, base_ws_url=base_ws_url
|
|
@@ -145,6 +119,7 @@ async def create_cloud_chat_from_repository(
|
|
|
145
119
|
|
|
146
120
|
variables = {
|
|
147
121
|
"repositoryId": repository_id,
|
|
122
|
+
"provider": provider,
|
|
148
123
|
}
|
|
149
124
|
|
|
150
125
|
result = await graphql_client.execute(
|
|
@@ -243,63 +218,6 @@ def enable_repo(
|
|
|
243
218
|
sys.exit(1)
|
|
244
219
|
|
|
245
220
|
|
|
246
|
-
@cloud_cli.command(hidden=True)
|
|
247
|
-
@click.option(
|
|
248
|
-
"--org-name",
|
|
249
|
-
help="GitHub organization name",
|
|
250
|
-
required=True,
|
|
251
|
-
)
|
|
252
|
-
@click.option(
|
|
253
|
-
"--repo-name",
|
|
254
|
-
help="GitHub repository name",
|
|
255
|
-
required=True,
|
|
256
|
-
)
|
|
257
|
-
@use_settings
|
|
258
|
-
def incremental_build(
|
|
259
|
-
settings: Settings,
|
|
260
|
-
org_name: str,
|
|
261
|
-
repo_name: str,
|
|
262
|
-
) -> None:
|
|
263
|
-
"""Test utility for incremental build of cloud repository."""
|
|
264
|
-
check_exponent_version_and_upgrade(settings)
|
|
265
|
-
|
|
266
|
-
if not settings.api_key:
|
|
267
|
-
redirect_to_login(settings)
|
|
268
|
-
return
|
|
269
|
-
|
|
270
|
-
loop = asyncio.get_event_loop()
|
|
271
|
-
|
|
272
|
-
api_key = settings.api_key
|
|
273
|
-
base_api_url = settings.get_base_api_url()
|
|
274
|
-
base_ws_url = settings.get_base_ws_url()
|
|
275
|
-
|
|
276
|
-
try:
|
|
277
|
-
result = loop.run_until_complete(
|
|
278
|
-
incremental_build_cloud_repository(
|
|
279
|
-
api_key, base_api_url, base_ws_url, org_name, repo_name
|
|
280
|
-
)
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
if result["__typename"] == "ContainerImage":
|
|
284
|
-
click.secho(
|
|
285
|
-
f"✓ Successfully triggered incremental build for {org_name}/{repo_name}",
|
|
286
|
-
fg="green",
|
|
287
|
-
)
|
|
288
|
-
click.echo(f" Build ref: {result.get('buildRef', 'N/A')}")
|
|
289
|
-
click.echo(f" Created at: {result.get('createdAt', 'N/A')}")
|
|
290
|
-
click.echo(f" Updated at: {result.get('updatedAt', 'N/A')}")
|
|
291
|
-
else:
|
|
292
|
-
click.secho(
|
|
293
|
-
f"✗ Failed to trigger incremental build: {result.get('message', 'Unknown error')}",
|
|
294
|
-
fg="red",
|
|
295
|
-
)
|
|
296
|
-
click.echo(f" Error type: {result['__typename']}")
|
|
297
|
-
|
|
298
|
-
except Exception as e:
|
|
299
|
-
click.secho(f"✗ Error triggering incremental build: {e!s}", fg="red")
|
|
300
|
-
sys.exit(1)
|
|
301
|
-
|
|
302
|
-
|
|
303
221
|
@cloud_cli.command(hidden=True)
|
|
304
222
|
@click.option(
|
|
305
223
|
"--org-name",
|
|
@@ -654,9 +572,6 @@ def cloud(
|
|
|
654
572
|
create_cloud_chat(api_key, base_api_url, base_ws_url, cloud_config_id)
|
|
655
573
|
)
|
|
656
574
|
|
|
657
|
-
if chat_uuid is None:
|
|
658
|
-
sys.exit(1)
|
|
659
|
-
|
|
660
575
|
loop.run_until_complete(
|
|
661
576
|
start_chat_turn(api_key, base_api_url, base_ws_url, chat_uuid, prompt)
|
|
662
577
|
)
|
exponent/commands/common.py
CHANGED
|
@@ -207,11 +207,14 @@ def run_until_complete(coro: Coroutine[Any, Any, Any]) -> Any:
|
|
|
207
207
|
try:
|
|
208
208
|
loop.run_until_complete(task)
|
|
209
209
|
except KeyboardInterrupt:
|
|
210
|
+
click.echo("\nReceived interrupt signal, shutting down gracefully...")
|
|
210
211
|
task.cancel()
|
|
211
212
|
try:
|
|
212
213
|
loop.run_until_complete(task)
|
|
213
214
|
except asyncio.CancelledError:
|
|
214
215
|
pass
|
|
216
|
+
click.secho("Exited due to keyboard interrupt", fg="yellow")
|
|
217
|
+
sys.exit(130) # Standard exit code for SIGINT (128 + 2)
|
|
215
218
|
except ExponentError as e:
|
|
216
219
|
try:
|
|
217
220
|
settings = get_settings()
|
exponent/core/config.py
CHANGED
|
@@ -162,7 +162,7 @@ def get_settings(use_prod: bool = False, use_staging: bool = False) -> Settings:
|
|
|
162
162
|
base_ws_url = "ws://localhost:8000"
|
|
163
163
|
environment = Environment.development
|
|
164
164
|
elif use_staging:
|
|
165
|
-
base_url = "https://staging.indent.com"
|
|
165
|
+
base_url = "https://app.staging.indent.com"
|
|
166
166
|
base_api_url = "https://staging-api.indent.com"
|
|
167
167
|
base_ws_url = "wss://ws-staging-api.indent.com"
|
|
168
168
|
environment = Environment.staging
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Types for container build log streaming."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
import msgspec
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BuildLogOutput(msgspec.Struct, tag="container_build_log_output"):
|
|
9
|
+
"""A single log line from a container build."""
|
|
10
|
+
|
|
11
|
+
container_image_uuid: str
|
|
12
|
+
data: str
|
|
13
|
+
timestamp: float
|
|
14
|
+
level: Literal["info", "error", "warning"] = "info"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BuildLogStatus(msgspec.Struct, tag="container_build_log_status"):
|
|
18
|
+
"""Status update for a container build."""
|
|
19
|
+
|
|
20
|
+
container_image_uuid: str
|
|
21
|
+
status: Literal["started", "completed", "failed"]
|
|
22
|
+
message: str | None = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
BuildLogMessage = BuildLogOutput | BuildLogStatus
|
|
@@ -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: SandboxProvider) {
|
|
80
|
+
createCloudChat(repositoryId: $repositoryId, provider: $provider) {
|
|
81
81
|
__typename
|
|
82
82
|
...on Chat {
|
|
83
83
|
chatUuid
|
|
@@ -131,35 +131,6 @@ mutation EnableCloudRepository($orgName: String!, $repoName: String!) {
|
|
|
131
131
|
"""
|
|
132
132
|
|
|
133
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
134
|
REBUILD_CLOUD_REPOSITORY_MUTATION = """
|
|
164
135
|
mutation RebuildCloudRepository($orgName: String!, $repoName: String!) {
|
|
165
136
|
rebuildCloudRepository(orgName: $orgName, repoName: $repoName) {
|
exponent/core/graphql/queries.py
CHANGED
|
@@ -28,7 +28,6 @@ EVENTS_FOR_CHAT_QUERY: str = """query EventsForChat($chatUuid: UUID!) {
|
|
|
28
28
|
... on UserEvent {
|
|
29
29
|
uuid
|
|
30
30
|
parentUuid
|
|
31
|
-
chatId
|
|
32
31
|
isSidechain
|
|
33
32
|
version
|
|
34
33
|
createdAt
|
|
@@ -70,7 +69,6 @@ EVENTS_FOR_CHAT_QUERY: str = """query EventsForChat($chatUuid: UUID!) {
|
|
|
70
69
|
... on AssistantEvent {
|
|
71
70
|
uuid
|
|
72
71
|
parentUuid
|
|
73
|
-
chatId
|
|
74
72
|
isSidechain
|
|
75
73
|
version
|
|
76
74
|
createdAt
|
|
@@ -98,7 +96,6 @@ EVENTS_FOR_CHAT_QUERY: str = """query EventsForChat($chatUuid: UUID!) {
|
|
|
98
96
|
... on SystemEvent {
|
|
99
97
|
uuid
|
|
100
98
|
parentUuid
|
|
101
|
-
chatId
|
|
102
99
|
isSidechain
|
|
103
100
|
version
|
|
104
101
|
createdAt
|
|
@@ -66,14 +66,28 @@ class FileMetadata(msgspec.Struct):
|
|
|
66
66
|
file_mode: str
|
|
67
67
|
|
|
68
68
|
|
|
69
|
+
class ReadToolArtifactResult(ToolResult, tag=READ_TOOL_ARTIFACT_NAME):
|
|
70
|
+
s3_uri: str
|
|
71
|
+
file_path: str
|
|
72
|
+
media_type: str
|
|
73
|
+
|
|
74
|
+
def to_text(self) -> str:
|
|
75
|
+
return f"[Image artifact uploaded to {self.s3_uri}]"
|
|
76
|
+
|
|
77
|
+
|
|
69
78
|
class ReadToolResult(ToolResult, tag=READ_TOOL_NAME):
|
|
70
|
-
content: str
|
|
71
|
-
num_lines: int
|
|
72
|
-
start_line: int
|
|
73
|
-
total_lines: int
|
|
79
|
+
content: str | None = None
|
|
80
|
+
num_lines: int | None = None
|
|
81
|
+
start_line: int | None = None
|
|
82
|
+
total_lines: int | None = None
|
|
74
83
|
metadata: FileMetadata | None = None
|
|
84
|
+
artifact: ReadToolArtifactResult | None = None
|
|
75
85
|
|
|
76
86
|
def to_text(self) -> str:
|
|
87
|
+
if self.artifact:
|
|
88
|
+
return self.artifact.to_text()
|
|
89
|
+
assert self.content is not None
|
|
90
|
+
assert self.start_line is not None
|
|
77
91
|
lines = self.content.splitlines()
|
|
78
92
|
lines = [
|
|
79
93
|
f"{str(i).rjust(6)}→{line}"
|
|
@@ -82,15 +96,6 @@ class ReadToolResult(ToolResult, tag=READ_TOOL_NAME):
|
|
|
82
96
|
return "\n".join(lines)
|
|
83
97
|
|
|
84
98
|
|
|
85
|
-
class ReadToolArtifactResult(ToolResult, tag=READ_TOOL_ARTIFACT_NAME):
|
|
86
|
-
s3_uri: str
|
|
87
|
-
file_path: str
|
|
88
|
-
media_type: str
|
|
89
|
-
|
|
90
|
-
def to_text(self) -> str:
|
|
91
|
-
return f"[Image artifact uploaded to {self.s3_uri}]"
|
|
92
|
-
|
|
93
|
-
|
|
94
99
|
LIST_TOOL_NAME = "ls"
|
|
95
100
|
|
|
96
101
|
|
|
@@ -200,6 +205,42 @@ class BashToolResult(ToolResult, tag=BASH_TOOL_NAME):
|
|
|
200
205
|
stopped_by_user: bool
|
|
201
206
|
|
|
202
207
|
|
|
208
|
+
DOWNLOAD_ARTIFACT_TOOL_NAME = "download_artifact"
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class DownloadArtifactToolInput(ToolInput, tag=DOWNLOAD_ARTIFACT_TOOL_NAME):
|
|
212
|
+
presigned_url: str
|
|
213
|
+
file_path: str
|
|
214
|
+
artifact_id: str
|
|
215
|
+
overwrite: bool = True
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class DownloadArtifactToolResult(ToolResult, tag=DOWNLOAD_ARTIFACT_TOOL_NAME):
|
|
219
|
+
file_path: str
|
|
220
|
+
artifact_id: str
|
|
221
|
+
file_size_bytes: int
|
|
222
|
+
content_preview: str | None = None
|
|
223
|
+
num_lines: int | None = None
|
|
224
|
+
total_lines: int | None = None
|
|
225
|
+
truncated: bool = False
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
UPLOAD_ARTIFACT_TOOL_NAME = "upload_artifact"
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class UploadArtifactToolInput(ToolInput, tag=UPLOAD_ARTIFACT_TOOL_NAME):
|
|
232
|
+
presigned_url: str
|
|
233
|
+
file_path: str
|
|
234
|
+
artifact_id: str
|
|
235
|
+
content_type: str
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class UploadArtifactToolResult(ToolResult, tag=UPLOAD_ARTIFACT_TOOL_NAME):
|
|
239
|
+
artifact_id: str
|
|
240
|
+
file_size_bytes: int
|
|
241
|
+
content_type: str
|
|
242
|
+
|
|
243
|
+
|
|
203
244
|
class HttpRequest(msgspec.Struct, tag="http_fetch_cli"):
|
|
204
245
|
url: str
|
|
205
246
|
method: str = "GET"
|
|
@@ -223,6 +264,8 @@ ToolInputType = (
|
|
|
223
264
|
| GrepToolInput
|
|
224
265
|
| EditToolInput
|
|
225
266
|
| BashToolInput
|
|
267
|
+
| DownloadArtifactToolInput
|
|
268
|
+
| UploadArtifactToolInput
|
|
226
269
|
)
|
|
227
270
|
PartialToolResultType = PartialBashToolResult
|
|
228
271
|
|
|
@@ -235,6 +278,8 @@ ToolResultType = (
|
|
|
235
278
|
| GrepToolResult
|
|
236
279
|
| EditToolResult
|
|
237
280
|
| BashToolResult
|
|
281
|
+
| DownloadArtifactToolResult
|
|
282
|
+
| UploadArtifactToolResult
|
|
238
283
|
| ErrorToolResult
|
|
239
284
|
)
|
|
240
285
|
|
|
@@ -273,6 +318,10 @@ class TerminateResponse(msgspec.Struct, tag="terminate"):
|
|
|
273
318
|
pass
|
|
274
319
|
|
|
275
320
|
|
|
321
|
+
class TimeoutResponse(msgspec.Struct, tag="timeout"):
|
|
322
|
+
pass
|
|
323
|
+
|
|
324
|
+
|
|
276
325
|
class BatchToolExecutionResponse(msgspec.Struct, tag="batch_tool_execution"):
|
|
277
326
|
tool_results: list[ToolResultType]
|
|
278
327
|
|
|
@@ -295,6 +344,80 @@ class GenerateUploadUrlResponse(msgspec.Struct, tag="generate_upload_url"):
|
|
|
295
344
|
s3_uri: str
|
|
296
345
|
|
|
297
346
|
|
|
347
|
+
# Terminal session management
|
|
348
|
+
class StartTerminalRequest(msgspec.Struct, tag="start_terminal"):
|
|
349
|
+
"""Start a new terminal session with PTY"""
|
|
350
|
+
|
|
351
|
+
session_id: str
|
|
352
|
+
command: list[str] | None = None # None = default shell, or specific command
|
|
353
|
+
cols: int = 80
|
|
354
|
+
rows: int = 24
|
|
355
|
+
env: dict[str, str] | None = None # Additional environment variables
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class StartTerminalResponse(msgspec.Struct, tag="start_terminal"):
|
|
359
|
+
"""Response after starting terminal"""
|
|
360
|
+
|
|
361
|
+
session_id: str
|
|
362
|
+
success: bool
|
|
363
|
+
error_message: str | None = None
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
# Terminal input (user typing)
|
|
367
|
+
class TerminalInputRequest(msgspec.Struct, tag="terminal_input"):
|
|
368
|
+
"""Send user input to terminal"""
|
|
369
|
+
|
|
370
|
+
session_id: str
|
|
371
|
+
data: str # Raw input data from user
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class TerminalInputResponse(msgspec.Struct, tag="terminal_input"):
|
|
375
|
+
"""Acknowledge input received"""
|
|
376
|
+
|
|
377
|
+
session_id: str
|
|
378
|
+
success: bool
|
|
379
|
+
error_message: str | None = None
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
# Terminal resize
|
|
383
|
+
class TerminalResizeRequest(msgspec.Struct, tag="terminal_resize"):
|
|
384
|
+
"""Resize terminal dimensions"""
|
|
385
|
+
|
|
386
|
+
session_id: str
|
|
387
|
+
cols: int
|
|
388
|
+
rows: int
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
class TerminalResizeResponse(msgspec.Struct, tag="terminal_resize"):
|
|
392
|
+
"""Acknowledge resize"""
|
|
393
|
+
|
|
394
|
+
session_id: str
|
|
395
|
+
success: bool
|
|
396
|
+
error_message: str | None = None
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# Terminal stop
|
|
400
|
+
class StopTerminalRequest(msgspec.Struct, tag="stop_terminal"):
|
|
401
|
+
"""Stop a terminal session"""
|
|
402
|
+
|
|
403
|
+
session_id: str
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
class StopTerminalResponse(msgspec.Struct, tag="stop_terminal"):
|
|
407
|
+
"""Acknowledge terminal stopped"""
|
|
408
|
+
|
|
409
|
+
session_id: str
|
|
410
|
+
success: bool
|
|
411
|
+
error_message: str | None = None
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
class StreamingCodeExecutionRequest(msgspec.Struct, tag="streaming_code_execution"):
|
|
415
|
+
correlation_id: str
|
|
416
|
+
language: str # "python" or "shell"
|
|
417
|
+
content: str
|
|
418
|
+
timeout: int
|
|
419
|
+
|
|
420
|
+
|
|
298
421
|
class CliRpcRequest(msgspec.Struct):
|
|
299
422
|
request_id: str
|
|
300
423
|
request: (
|
|
@@ -306,6 +429,11 @@ class CliRpcRequest(msgspec.Struct):
|
|
|
306
429
|
| SwitchCLIChatRequest
|
|
307
430
|
| KeepAliveCliChatRequest
|
|
308
431
|
| GenerateUploadUrlRequest
|
|
432
|
+
| StartTerminalRequest
|
|
433
|
+
| TerminalInputRequest
|
|
434
|
+
| TerminalResizeRequest
|
|
435
|
+
| StopTerminalRequest
|
|
436
|
+
| StreamingCodeExecutionRequest
|
|
309
437
|
)
|
|
310
438
|
|
|
311
439
|
|
|
@@ -317,6 +445,40 @@ class ErrorResponse(msgspec.Struct, tag="error"):
|
|
|
317
445
|
error_message: str
|
|
318
446
|
|
|
319
447
|
|
|
448
|
+
class StreamingCodeExecutionResponseChunk(
|
|
449
|
+
msgspec.Struct, tag="streaming_code_execution_chunk"
|
|
450
|
+
):
|
|
451
|
+
correlation_id: str
|
|
452
|
+
content: str
|
|
453
|
+
truncated: bool = False
|
|
454
|
+
|
|
455
|
+
def add(
|
|
456
|
+
self, new_chunk: "StreamingCodeExecutionResponseChunk"
|
|
457
|
+
) -> "StreamingCodeExecutionResponseChunk":
|
|
458
|
+
"""Aggregates content of this and a new chunk."""
|
|
459
|
+
assert self.correlation_id == new_chunk.correlation_id
|
|
460
|
+
return StreamingCodeExecutionResponseChunk(
|
|
461
|
+
correlation_id=self.correlation_id,
|
|
462
|
+
content=self.content + new_chunk.content,
|
|
463
|
+
truncated=self.truncated or new_chunk.truncated,
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class StreamingCodeExecutionResponse(msgspec.Struct, tag="streaming_code_execution"):
|
|
468
|
+
correlation_id: str
|
|
469
|
+
content: str
|
|
470
|
+
truncated: bool = False
|
|
471
|
+
# Only present for shell code execution
|
|
472
|
+
cancelled_for_timeout: bool = False
|
|
473
|
+
exit_code: int | None = None
|
|
474
|
+
halted: bool = False
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class StreamingErrorResponse(msgspec.Struct, tag="streaming_error"):
|
|
478
|
+
correlation_id: str
|
|
479
|
+
error_message: str
|
|
480
|
+
|
|
481
|
+
|
|
320
482
|
class CliRpcResponse(msgspec.Struct):
|
|
321
483
|
request_id: str
|
|
322
484
|
response: (
|
|
@@ -324,9 +486,17 @@ class CliRpcResponse(msgspec.Struct):
|
|
|
324
486
|
| GetAllFilesResponse
|
|
325
487
|
| ErrorResponse
|
|
326
488
|
| TerminateResponse
|
|
489
|
+
| TimeoutResponse
|
|
327
490
|
| BatchToolExecutionResponse
|
|
328
491
|
| HttpResponse
|
|
329
492
|
| SwitchCLIChatResponse
|
|
330
493
|
| KeepAliveCliChatResponse
|
|
331
494
|
| GenerateUploadUrlResponse
|
|
495
|
+
| StartTerminalResponse
|
|
496
|
+
| TerminalInputResponse
|
|
497
|
+
| TerminalResizeResponse
|
|
498
|
+
| StopTerminalResponse
|
|
499
|
+
| StreamingCodeExecutionResponseChunk
|
|
500
|
+
| StreamingCodeExecutionResponse
|
|
501
|
+
| StreamingErrorResponse
|
|
332
502
|
)
|