adk-code-mode 1.0.0__tar.gz → 1.2.0__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.2.0/.release-please-manifest.json +3 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/CHANGELOG.md +14 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/PKG-INFO +1 -1
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/__about__.py +1 -1
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/__about__.py +1 -1
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/_artifact_tools.py +4 -1
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tool.py +14 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_artifact_tools.py +42 -8
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_tool.py +10 -0
- adk_code_mode-1.0.0/.release-please-manifest.json +0 -3
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.githooks/pre-commit +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.githooks/pre-push +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.github/workflows/ci.yml +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.github/workflows/release-please.yml +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.gitignore +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.prettierrc +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.vscode/settings.json +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/.zed/settings.json +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/AGENTS.md +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/CLAUDE.md +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/LICENSE +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/Makefile +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/README.md +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/docker/Dockerfile +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/pyproject.toml +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/release-please-config.json +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/README.md +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/pyproject.toml +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/protocol.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/scripts/install-git-hooks.sh +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/__init__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/output.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/py.typed +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/runtime/__init__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/runtime/base.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/runtime/docker.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/runtime/protocol.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/runtime/remote.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tool_result_artifacts.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tools/__init__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tools/catalog.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tools/dispatcher.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tools/namespacing.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tools/normaliser.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/tools/stubs.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/workspace/__init__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/src/adk_code_mode/workspace/files.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/__init__.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/_docker_helpers.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/_fake_runtime.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/conftest.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_agent_with_fake_llm.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_catalog.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_dispatcher.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_docker_image.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_docker_integration.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_host_loop.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_integration.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_namespacing.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_normaliser.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_output.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_protocol.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_remote_backend.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_remote_integration.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_runtime_docker.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_sandbox_rpc_client.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_stubs.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_tool_result_artifacts.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_version.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/tests/test_workspace_files.py +0 -0
- {adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/uv.lock +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.0](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v1.1.0...adk-code-mode-v1.2.0) (2026-07-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add `custom_metadata` to the `save_artifact` tool ([dfd9a59](https://github.com/a2anet/adk-code-mode/commit/dfd9a59bf1718084a1d5c02cc1ea453269223f16))
|
|
9
|
+
|
|
10
|
+
## [1.1.0](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v1.0.0...adk-code-mode-v1.1.0) (2026-07-15)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* expose `tools` and `backend` as public properties on `ExecuteCodeTool` ([acfb704](https://github.com/a2anet/adk-code-mode/commit/acfb704d388da5d66e318775e03fe055467679c2))
|
|
16
|
+
|
|
3
17
|
## [1.0.0](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v0.4.1...adk-code-mode-v1.0.0) (2026-07-15)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adk-code-mode
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
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
|
|
@@ -43,6 +43,7 @@ async def save_artifact(
|
|
|
43
43
|
filename: str,
|
|
44
44
|
content: str,
|
|
45
45
|
mime_type: str | None = None,
|
|
46
|
+
custom_metadata: dict[str, Any] | None = None,
|
|
46
47
|
tool_context: ToolContext,
|
|
47
48
|
) -> int:
|
|
48
49
|
"""Save an artifact to the session. Returns the new version number.
|
|
@@ -62,6 +63,8 @@ async def save_artifact(
|
|
|
62
63
|
content=base64.b64encode(image_bytes).decode("ascii"),
|
|
63
64
|
mime_type="image/png",
|
|
64
65
|
)
|
|
66
|
+
|
|
67
|
+
``custom_metadata`` is custom metadata to associate with the artifact.
|
|
65
68
|
"""
|
|
66
69
|
if _is_text_mime(mime_type):
|
|
67
70
|
part = genai_types.Part(
|
|
@@ -77,7 +80,7 @@ async def save_artifact(
|
|
|
77
80
|
mime_type=mime_type or "application/octet-stream",
|
|
78
81
|
)
|
|
79
82
|
)
|
|
80
|
-
return await tool_context.save_artifact(filename, part)
|
|
83
|
+
return await tool_context.save_artifact(filename, part, custom_metadata=custom_metadata)
|
|
81
84
|
|
|
82
85
|
|
|
83
86
|
async def load_artifact(
|
|
@@ -294,6 +294,20 @@ class ExecuteCodeTool(BaseTool):
|
|
|
294
294
|
if eager_resolved:
|
|
295
295
|
namespacing.build(eager_resolved)
|
|
296
296
|
|
|
297
|
+
@property
|
|
298
|
+
def tools(self) -> Sequence[BaseTool | BaseToolset]:
|
|
299
|
+
"""Tools and toolsets available inside the sandbox, including built-in artifact tools.
|
|
300
|
+
|
|
301
|
+
Host apps that own a toolset's lifecycle (e.g. an ``McpToolset`` needing
|
|
302
|
+
``close()`` on shutdown) need this to find it again after construction.
|
|
303
|
+
"""
|
|
304
|
+
return self._tools
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def backend(self) -> SandboxBackend:
|
|
308
|
+
"""The configured sandbox runtime backend."""
|
|
309
|
+
return self._backend
|
|
310
|
+
|
|
297
311
|
def _get_declaration(self) -> genai_types.FunctionDeclaration | None:
|
|
298
312
|
return genai_types.FunctionDeclaration(
|
|
299
313
|
name=self.name,
|
|
@@ -34,12 +34,17 @@ class _StubToolContext:
|
|
|
34
34
|
) -> None:
|
|
35
35
|
self._load_result = load_result
|
|
36
36
|
self._list_result = list_result or []
|
|
37
|
-
self.saved: list[tuple[str, genai_types.Part]] = []
|
|
37
|
+
self.saved: list[tuple[str, genai_types.Part, dict[str, Any] | None]] = []
|
|
38
38
|
self.loaded: list[tuple[str, int | None]] = []
|
|
39
39
|
self.listed = 0
|
|
40
40
|
|
|
41
|
-
async def save_artifact(
|
|
42
|
-
self
|
|
41
|
+
async def save_artifact(
|
|
42
|
+
self,
|
|
43
|
+
filename: str,
|
|
44
|
+
part: genai_types.Part,
|
|
45
|
+
custom_metadata: dict[str, Any] | None = None,
|
|
46
|
+
) -> int:
|
|
47
|
+
self.saved.append((filename, part, custom_metadata))
|
|
43
48
|
return len(self.saved)
|
|
44
49
|
|
|
45
50
|
async def load_artifact(
|
|
@@ -65,7 +70,7 @@ async def test_save_artifact_encodes_text_mime_as_utf8() -> None:
|
|
|
65
70
|
|
|
66
71
|
assert version == 1
|
|
67
72
|
assert len(ctx.saved) == 1
|
|
68
|
-
name, part = ctx.saved[0]
|
|
73
|
+
name, part, _ = ctx.saved[0]
|
|
69
74
|
assert name == "report.json"
|
|
70
75
|
assert part.inline_data is not None
|
|
71
76
|
assert part.inline_data.mime_type == "application/json"
|
|
@@ -82,7 +87,7 @@ async def test_save_artifact_treats_text_plus_subtype_as_text() -> None:
|
|
|
82
87
|
tool_context=ctx, # type: ignore[arg-type]
|
|
83
88
|
)
|
|
84
89
|
|
|
85
|
-
_, part = ctx.saved[0]
|
|
90
|
+
_, part, _ = ctx.saved[0]
|
|
86
91
|
assert part.inline_data is not None
|
|
87
92
|
assert part.inline_data.data == b"<svg/>"
|
|
88
93
|
|
|
@@ -98,7 +103,7 @@ async def test_save_artifact_decodes_base64_for_binary_mime() -> None:
|
|
|
98
103
|
tool_context=ctx, # type: ignore[arg-type]
|
|
99
104
|
)
|
|
100
105
|
|
|
101
|
-
_, part = ctx.saved[0]
|
|
106
|
+
_, part, _ = ctx.saved[0]
|
|
102
107
|
assert part.inline_data is not None
|
|
103
108
|
assert part.inline_data.data == raw
|
|
104
109
|
assert part.inline_data.mime_type == "application/octet-stream"
|
|
@@ -114,12 +119,41 @@ async def test_save_artifact_defaults_mime_when_none() -> None:
|
|
|
114
119
|
tool_context=ctx, # type: ignore[arg-type]
|
|
115
120
|
)
|
|
116
121
|
|
|
117
|
-
_, part = ctx.saved[0]
|
|
122
|
+
_, part, _ = ctx.saved[0]
|
|
118
123
|
assert part.inline_data is not None
|
|
119
124
|
assert part.inline_data.mime_type == "application/octet-stream"
|
|
120
125
|
assert part.inline_data.data == raw
|
|
121
126
|
|
|
122
127
|
|
|
128
|
+
@pytest.mark.asyncio
|
|
129
|
+
async def test_save_artifact_forwards_custom_metadata() -> None:
|
|
130
|
+
ctx = _StubToolContext()
|
|
131
|
+
await save_artifact(
|
|
132
|
+
filename="report.md",
|
|
133
|
+
content="# Report",
|
|
134
|
+
mime_type="text/markdown",
|
|
135
|
+
custom_metadata={"a2anet_agent_run.send_as_a2a_artifact": "true"},
|
|
136
|
+
tool_context=ctx, # type: ignore[arg-type]
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
_, _, custom_metadata = ctx.saved[0]
|
|
140
|
+
assert custom_metadata == {"a2anet_agent_run.send_as_a2a_artifact": "true"}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@pytest.mark.asyncio
|
|
144
|
+
async def test_save_artifact_defaults_custom_metadata_to_none() -> None:
|
|
145
|
+
ctx = _StubToolContext()
|
|
146
|
+
await save_artifact(
|
|
147
|
+
filename="scratch.txt",
|
|
148
|
+
content="notes",
|
|
149
|
+
mime_type="text/plain",
|
|
150
|
+
tool_context=ctx, # type: ignore[arg-type]
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
_, _, custom_metadata = ctx.saved[0]
|
|
154
|
+
assert custom_metadata is None
|
|
155
|
+
|
|
156
|
+
|
|
123
157
|
@pytest.mark.asyncio
|
|
124
158
|
async def test_load_artifact_returns_text_kind_for_text_mime() -> None:
|
|
125
159
|
part = genai_types.Part(
|
|
@@ -196,4 +230,4 @@ def test_artifact_tools_declarations_omit_tool_context_param() -> None:
|
|
|
196
230
|
assert save_decl is not None
|
|
197
231
|
properties: dict[str, Any] = save_decl.parameters.properties or {} # type: ignore[union-attr]
|
|
198
232
|
assert "tool_context" not in properties
|
|
199
|
-
assert {"filename", "content"}.issubset(properties.keys())
|
|
233
|
+
assert {"filename", "content", "custom_metadata"}.issubset(properties.keys())
|
|
@@ -69,6 +69,16 @@ def test_declaration_exposes_a_single_code_parameter() -> None:
|
|
|
69
69
|
assert decl.parameters_json_schema["required"] == ["code"]
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
def test_tools_and_backend_properties_expose_the_configured_surface() -> None:
|
|
73
|
+
schema_tool = _SchemaTool("ping", "Ping.")
|
|
74
|
+
backend = FakeRuntime()
|
|
75
|
+
|
|
76
|
+
tool = ExecuteCodeTool(tools=[schema_tool], backend=backend)
|
|
77
|
+
|
|
78
|
+
assert schema_tool in tool.tools
|
|
79
|
+
assert tool.backend is backend
|
|
80
|
+
|
|
81
|
+
|
|
72
82
|
@pytest.mark.asyncio
|
|
73
83
|
async def test_process_llm_request_declares_the_tool() -> None:
|
|
74
84
|
tool = _make_tool([])
|
|
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
|
{adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py
RENAMED
|
File without changes
|
{adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py
RENAMED
|
File without changes
|
{adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py
RENAMED
|
File without changes
|
{adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py
RENAMED
|
File without changes
|
{adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py
RENAMED
|
File without changes
|
{adk_code_mode-1.0.0 → adk_code_mode-1.2.0}/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
|