adk-code-mode 1.6.0__tar.gz → 1.6.1__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.
- adk_code_mode-1.6.1/.release-please-manifest.json +3 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/CHANGELOG.md +7 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/PKG-INFO +1 -1
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/__about__.py +1 -1
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py +0 -1
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py +15 -5
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/__about__.py +1 -1
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_remote_integration.py +35 -0
- adk_code_mode-1.6.0/.release-please-manifest.json +0 -3
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.githooks/pre-commit +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.githooks/pre-push +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.github/workflows/ci.yml +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.github/workflows/release-please.yml +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.gitignore +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.prettierrc +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.vscode/settings.json +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/.zed/settings.json +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/LICENSE +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/Makefile +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/README.md +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/docker/Dockerfile +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/pyproject.toml +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/release-please-config.json +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/README.md +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/pyproject.toml +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/protocol.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/scripts/install-git-hooks.sh +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/__init__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/_artifact_tools.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/metadata.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/output.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/py.typed +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/runtime/__init__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/runtime/base.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/runtime/docker.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/runtime/protocol.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/runtime/remote.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tool.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tool_result_artifacts.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tools/__init__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tools/catalog.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tools/dispatcher.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tools/namespacing.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tools/normaliser.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/tools/stubs.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/workspace/__init__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/src/adk_code_mode/workspace/files.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/__init__.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/_docker_helpers.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/_fake_runtime.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/conftest.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_agent_with_fake_llm.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_artifact_tools.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_catalog.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_dispatcher.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_docker_image.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_docker_integration.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_host_loop.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_integration.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_metadata.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_namespacing.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_normaliser.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_output.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_protocol.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_remote_backend.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_runtime_docker.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_sandbox_entry.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_sandbox_rpc_client.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_stubs.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_stubs_json_schema.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_tool.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_tool_result_artifacts.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_version.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/tests/test_workspace_files.py +0 -0
- {adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/uv.lock +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.1](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v1.6.0...adk-code-mode-v1.6.1) (2026-09-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* exit the sandbox when the host disconnects mid-block ([bd3fb0f](https://github.com/a2anet/adk-code-mode/commit/bd3fb0fb0d8a0cab9370f2ad6db56dfacf566cb4))
|
|
9
|
+
|
|
3
10
|
## [1.6.0](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v1.5.0...adk-code-mode-v1.6.0) (2026-08-29)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: adk-code-mode
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.1
|
|
4
4
|
Summary: A "Code Mode" sandboxed code-execution tool for ADK agents to interact with tools, files, and custom packages with Python
|
|
5
5
|
Project-URL: Documentation, https://github.com/A2ANet/adk-code-mode#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/A2ANet/adk-code-mode/issues
|
{adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py
RENAMED
|
@@ -228,7 +228,6 @@ def main() -> int:
|
|
|
228
228
|
port = int(os.environ.get("PORT", "8080"))
|
|
229
229
|
token = os.environ.get(AUTH_TOKEN_ENV)
|
|
230
230
|
asyncio.run(serve(port, token))
|
|
231
|
-
return 0
|
|
232
231
|
|
|
233
232
|
reader, writer = _open_control_streams()
|
|
234
233
|
client = RpcClient(reader=reader, writer=writer)
|
{adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py
RENAMED
|
@@ -38,7 +38,7 @@ import shutil
|
|
|
38
38
|
import tarfile
|
|
39
39
|
import tempfile
|
|
40
40
|
from http import HTTPStatus
|
|
41
|
-
from typing import Any
|
|
41
|
+
from typing import Any, NoReturn
|
|
42
42
|
|
|
43
43
|
import websockets
|
|
44
44
|
import websockets.asyncio.server
|
|
@@ -112,10 +112,11 @@ class _WsBridgeWriter:
|
|
|
112
112
|
pass
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
async def serve(port: int, token: str | None) ->
|
|
115
|
+
async def serve(port: int, token: str | None) -> NoReturn:
|
|
116
116
|
"""Start the WebSocket server on *port* with optional bearer *token* auth.
|
|
117
117
|
|
|
118
|
-
Accepts exactly one WebSocket connection, runs user code, then
|
|
118
|
+
Accepts exactly one WebSocket connection, runs user code, then exits the
|
|
119
|
+
process.
|
|
119
120
|
"""
|
|
120
121
|
stop = asyncio.Event()
|
|
121
122
|
accepted = False
|
|
@@ -136,9 +137,15 @@ async def serve(port: int, token: str | None) -> None:
|
|
|
136
137
|
return None
|
|
137
138
|
|
|
138
139
|
async def handler(ws: Any) -> None:
|
|
140
|
+
turn = asyncio.create_task(_handle_connection(ws))
|
|
141
|
+
# End the turn when the socket closes, even mid-block: user code that
|
|
142
|
+
# ignores the disconnect would otherwise keep this single-use container
|
|
143
|
+
# alive, answering every later connection with "Busy".
|
|
144
|
+
ws_closed = asyncio.create_task(ws.wait_closed())
|
|
145
|
+
ws_closed.add_done_callback(lambda _: turn.cancel())
|
|
139
146
|
try:
|
|
140
|
-
await
|
|
141
|
-
except websockets.ConnectionClosed:
|
|
147
|
+
await turn
|
|
148
|
+
except (websockets.ConnectionClosed, asyncio.CancelledError):
|
|
142
149
|
logger.debug("client disconnected")
|
|
143
150
|
except Exception:
|
|
144
151
|
logger.exception("error handling WebSocket connection")
|
|
@@ -154,6 +161,9 @@ async def serve(port: int, token: str | None) -> None:
|
|
|
154
161
|
):
|
|
155
162
|
logger.info("sandbox HTTP server listening on port %d", port)
|
|
156
163
|
await stop.wait()
|
|
164
|
+
# Don't let interpreter shutdown join a worker thread still running user code
|
|
165
|
+
# the host has given up on.
|
|
166
|
+
os._exit(0)
|
|
157
167
|
|
|
158
168
|
|
|
159
169
|
async def _handle_connection(ws: Any) -> None:
|
|
@@ -340,3 +340,38 @@ async def test_remote_close_shuts_the_container_down(
|
|
|
340
340
|
break
|
|
341
341
|
await asyncio.sleep(0.02)
|
|
342
342
|
assert http_server.poll() is not None # container exited after ShutdownFrame
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
@pytest.mark.asyncio
|
|
346
|
+
async def test_remote_timed_out_block_shuts_the_container_down(
|
|
347
|
+
http_server: subprocess.Popen[bytes],
|
|
348
|
+
) -> None:
|
|
349
|
+
"""A block still running when the host gives up doesn't keep the server alive."""
|
|
350
|
+
artifact_service = InMemoryArtifactService()
|
|
351
|
+
session = Session(
|
|
352
|
+
id="remote-timeout",
|
|
353
|
+
app_name="test-app",
|
|
354
|
+
user_id="u1",
|
|
355
|
+
state={},
|
|
356
|
+
events=[],
|
|
357
|
+
last_update_time=0.0,
|
|
358
|
+
)
|
|
359
|
+
ctx = _make_ctx(artifact_service, session)
|
|
360
|
+
|
|
361
|
+
tool = ExecuteCodeTool(
|
|
362
|
+
tools=[],
|
|
363
|
+
backend=RemoteBackend(url=_server_url(http_server)),
|
|
364
|
+
max_output_chars=10_000,
|
|
365
|
+
timeout_seconds=1,
|
|
366
|
+
)
|
|
367
|
+
result = await tool.run_async(
|
|
368
|
+
args={"code": "import time\ntime.sleep(3600)\n"},
|
|
369
|
+
tool_context=_tool_context(ctx, call_id="remote-timeout-1"),
|
|
370
|
+
)
|
|
371
|
+
assert "exceeded timeout" in result["stderr"]
|
|
372
|
+
|
|
373
|
+
for _ in range(200):
|
|
374
|
+
if http_server.poll() is not None:
|
|
375
|
+
break
|
|
376
|
+
await asyncio.sleep(0.02)
|
|
377
|
+
assert http_server.poll() is not None # container exited despite the running block
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py
RENAMED
|
File without changes
|
{adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py
RENAMED
|
File without changes
|
{adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py
RENAMED
|
File without changes
|
{adk_code_mode-1.6.0 → adk_code_mode-1.6.1}/sandbox-wheel/src/adk_code_mode_sandbox/protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|