adk-code-mode 0.2.0__tar.gz → 0.2.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-0.2.1/.release-please-manifest.json +3 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/CHANGELOG.md +12 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/PKG-INFO +64 -11
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/README.md +63 -10
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/__about__.py +1 -1
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/__about__.py +1 -1
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/callback.py +3 -3
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/executor.py +23 -3
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_agent_with_fake_llm.py +1 -1
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_callback.py +6 -6
- adk_code_mode-0.2.0/.release-please-manifest.json +0 -3
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.githooks/pre-commit +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.githooks/pre-push +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.github/workflows/ci.yml +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.github/workflows/release-please.yml +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.gitignore +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.prettierrc +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.vscode/settings.json +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/.zed/settings.json +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/AGENTS.md +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/CLAUDE.md +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/LICENSE +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/Makefile +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/docker/Dockerfile +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/pyproject.toml +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/release-please-config.json +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/README.md +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/pyproject.toml +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/protocol.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/scripts/install-git-hooks.sh +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/__init__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/_artifact_tools.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/output.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/py.typed +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/runtime/__init__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/runtime/base.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/runtime/docker.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/runtime/protocol.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/runtime/remote.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/tools/__init__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/tools/catalog.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/tools/dispatcher.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/tools/namespacing.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/tools/normaliser.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/tools/stubs.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/workspace/__init__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/src/adk_code_mode/workspace/files.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/__init__.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/_docker_helpers.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/_fake_runtime.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_artifact_tools.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_catalog.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_dispatcher.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_docker_image.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_docker_integration.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_host_loop.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_integration.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_namespacing.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_normaliser.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_output.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_protocol.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_remote_integration.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_runtime_docker.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_sandbox_rpc_client.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_stubs.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_version.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/tests/test_workspace_files.py +0 -0
- {adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/uv.lock +0 -0
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.1](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v0.2.0...adk-code-mode-v0.2.1) (2026-05-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* rename `<tools>` tag to `<code-mode>` and update `CODE_MODE_SYSTEM_INSTRUCTION` ([0a06bfb](https://github.com/a2anet/adk-code-mode/commit/0a06bfbdf22db6e0226e477d0ed074a6cc4d1515))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
* update `README.md` with deployment instructions ([1dd7a95](https://github.com/a2anet/adk-code-mode/commit/1dd7a95197fd56231ba97182526a825baf18508a))
|
|
14
|
+
|
|
3
15
|
## [0.2.0](https://github.com/a2anet/adk-code-mode/compare/adk-code-mode-v0.1.0...adk-code-mode-v0.2.0) (2026-05-03)
|
|
4
16
|
|
|
5
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adk-code-mode
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A "Code Mode" Code Executor for ADK for 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
|
|
@@ -78,12 +78,17 @@ Requires Python 3.10+. Local development requires [Docker](https://docs.docker.c
|
|
|
78
78
|
|
|
79
79
|
## 🚀 Usage
|
|
80
80
|
|
|
81
|
-
Build a `CodeModeCodeExecutor`, wire
|
|
81
|
+
Build a `CodeModeCodeExecutor`, then wire three things into the agent:
|
|
82
|
+
|
|
83
|
+
- **`CODE_MODE_SYSTEM_INSTRUCTION`** — append to the agent's `instruction`. Teaches the model how to write code blocks and use artifacts.
|
|
84
|
+
- **`code_mode_before_model_callback`** — set as `before_model_callback`. Injects the tool catalog (`<code-mode>` block) into the system prompt on every model turn.
|
|
85
|
+
- **`generate_content_config`** with `function_calling_config.mode="NONE"` — disables native function calling so the model writes Python instead of attempting tool calls that fail with `MALFORMED_FUNCTION_CALL` (since `tools=[]`).
|
|
82
86
|
|
|
83
87
|
### Production (remote sandbox)
|
|
84
88
|
|
|
85
89
|
```python
|
|
86
90
|
from google.adk.agents import LlmAgent
|
|
91
|
+
from google.genai import types as genai_types
|
|
87
92
|
from adk_code_mode import (
|
|
88
93
|
CODE_MODE_SYSTEM_INSTRUCTION,
|
|
89
94
|
CodeModeCodeExecutor,
|
|
@@ -105,6 +110,11 @@ root_agent = LlmAgent(
|
|
|
105
110
|
instruction=f"You are a helpful assistant.\n\n{CODE_MODE_SYSTEM_INSTRUCTION}",
|
|
106
111
|
tools=[], # do NOT also bind tools here; the executor owns them.
|
|
107
112
|
code_executor=executor,
|
|
113
|
+
generate_content_config=genai_types.GenerateContentConfig(
|
|
114
|
+
tool_config=genai_types.ToolConfig(
|
|
115
|
+
function_calling_config=genai_types.FunctionCallingConfig(mode="NONE"),
|
|
116
|
+
),
|
|
117
|
+
),
|
|
108
118
|
before_model_callback=code_mode_before_model_callback(executor),
|
|
109
119
|
)
|
|
110
120
|
```
|
|
@@ -153,10 +163,10 @@ Setting `ADK_CODE_MODE_CONTROL_HTTP=1` activates HTTP mode. The container:
|
|
|
153
163
|
```bash
|
|
154
164
|
# Push the sandbox image to Artifact Registry
|
|
155
165
|
gcloud auth configure-docker <region>-docker.pkg.dev
|
|
156
|
-
docker pull ghcr.io/a2anet/adk-code-mode:latest
|
|
166
|
+
docker pull --platform linux/amd64 ghcr.io/a2anet/adk-code-mode:latest
|
|
157
167
|
docker tag ghcr.io/a2anet/adk-code-mode:latest \
|
|
158
|
-
<region>-docker.pkg.dev/<project>/adk-code-mode
|
|
159
|
-
docker push <region>-docker.pkg.dev/<project>/adk-code-mode
|
|
168
|
+
<region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
169
|
+
docker push <region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
160
170
|
|
|
161
171
|
# Create a VPC connector with no egress routes (blocks outbound network from sandbox)
|
|
162
172
|
gcloud compute networks create adk-sandbox-vpc --subnet-mode=custom
|
|
@@ -176,16 +186,17 @@ gcloud compute networks vpc-access connectors create adk-sandbox-connector \
|
|
|
176
186
|
|
|
177
187
|
# Deploy — note --concurrency 1 and --vpc-egress=all-traffic
|
|
178
188
|
gcloud run deploy adk-code-mode-sandbox \
|
|
179
|
-
--image <region>-docker.pkg.dev/<project>/adk-code-mode
|
|
189
|
+
--image <region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest \
|
|
180
190
|
--region <region> \
|
|
181
191
|
--port 8080 \
|
|
182
192
|
--cpu 1 \
|
|
183
193
|
--memory 1Gi \
|
|
184
194
|
--concurrency 1 \
|
|
185
|
-
--
|
|
195
|
+
--allow-unauthenticated \
|
|
186
196
|
--vpc-connector=adk-sandbox-connector \
|
|
187
197
|
--vpc-egress=all-traffic \
|
|
188
|
-
--set-env-vars "ADK_CODE_MODE_CONTROL_HTTP=1
|
|
198
|
+
--set-env-vars "ADK_CODE_MODE_CONTROL_HTTP=1" \
|
|
199
|
+
--set-secrets "ADK_CODE_MODE_AUTH_TOKEN=<your-secret-name>:latest"
|
|
189
200
|
```
|
|
190
201
|
|
|
191
202
|
Then in your agent:
|
|
@@ -328,12 +339,41 @@ The only things crossing the boundary are: code, tool call arguments, tool retur
|
|
|
328
339
|
|
|
329
340
|
### What the model sees
|
|
330
341
|
|
|
331
|
-
Your `instruction` (containing `CODE_MODE_SYSTEM_INSTRUCTION`) followed by a `<
|
|
342
|
+
Your `instruction` (containing `CODE_MODE_SYSTEM_INSTRUCTION`) followed by a `<code-mode>` block appended by the callback:
|
|
332
343
|
|
|
333
344
|
```
|
|
334
345
|
…your instruction…
|
|
335
346
|
|
|
336
|
-
|
|
347
|
+
# How to execute code and use tools
|
|
348
|
+
Code you write in a fenced Python block (i.e. ```python) will be executed in a sandbox.
|
|
349
|
+
The Python Standard Library and a custom set of tools are available to you.
|
|
350
|
+
To see the result of your code, you need to print it.
|
|
351
|
+
|
|
352
|
+
For example, if you had the following tool:
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
from tools.slack import send_message
|
|
356
|
+
|
|
357
|
+
def send_message(*, channel: str, text: str, thread_ts: str | None = ...) -> Any:
|
|
358
|
+
"""Send a message to a Slack channel."""
|
|
359
|
+
...
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
To call the tool, you should write:
|
|
363
|
+
|
|
364
|
+
"""
|
|
365
|
+
```python
|
|
366
|
+
from tools.slack import send_message
|
|
367
|
+
|
|
368
|
+
print(send_message(channel="C123", text="hi"))
|
|
369
|
+
```
|
|
370
|
+
"""
|
|
371
|
+
|
|
372
|
+
# How to use files and variables in between executions
|
|
373
|
+
Code is executed in a new environment each time.
|
|
374
|
+
To list available Artifacts, use the `list_artifacts` tool. To save an Artifact, use the `save_artifact` tool, and to load an Artifact, use the `load_artifact` tool.
|
|
375
|
+
|
|
376
|
+
<code-mode>
|
|
337
377
|
|
|
338
378
|
# tools.slack
|
|
339
379
|
|
|
@@ -352,7 +392,20 @@ def send_message(*, channel: str, text: str, thread_ts: str | None = ...) -> Any
|
|
|
352
392
|
from tools import save_artifact, load_artifact, list_artifacts
|
|
353
393
|
…
|
|
354
394
|
|
|
355
|
-
</
|
|
395
|
+
</code-mode>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
When the rendered catalog exceeds `max_catalog_chars`, the per-tool sections are replaced with:
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
<code-mode>
|
|
402
|
+
A `tools` package is available in the sandbox. List `/tools/` with
|
|
403
|
+
`pathlib.Path('/tools').iterdir()`. Each entry is either a `.py` file
|
|
404
|
+
(a top-level tool, importable as `from tools import <name>`) or a
|
|
405
|
+
subdirectory (a namespace, with tools importable as
|
|
406
|
+
`from tools.<namespace> import <name>`). To see a tool's signature and
|
|
407
|
+
docstring, read its `.py` file with `open(...).read()`.
|
|
408
|
+
</code-mode>
|
|
356
409
|
```
|
|
357
410
|
|
|
358
411
|
Text and JSON-like MIME types travel as plain strings in artifact tools; binary content is base64-encoded. `load_artifact` returns `{"kind": "text" | "bytes", "data": str, "mime_type": str | None}`.
|
|
@@ -51,12 +51,17 @@ Requires Python 3.10+. Local development requires [Docker](https://docs.docker.c
|
|
|
51
51
|
|
|
52
52
|
## 🚀 Usage
|
|
53
53
|
|
|
54
|
-
Build a `CodeModeCodeExecutor`, wire
|
|
54
|
+
Build a `CodeModeCodeExecutor`, then wire three things into the agent:
|
|
55
|
+
|
|
56
|
+
- **`CODE_MODE_SYSTEM_INSTRUCTION`** — append to the agent's `instruction`. Teaches the model how to write code blocks and use artifacts.
|
|
57
|
+
- **`code_mode_before_model_callback`** — set as `before_model_callback`. Injects the tool catalog (`<code-mode>` block) into the system prompt on every model turn.
|
|
58
|
+
- **`generate_content_config`** with `function_calling_config.mode="NONE"` — disables native function calling so the model writes Python instead of attempting tool calls that fail with `MALFORMED_FUNCTION_CALL` (since `tools=[]`).
|
|
55
59
|
|
|
56
60
|
### Production (remote sandbox)
|
|
57
61
|
|
|
58
62
|
```python
|
|
59
63
|
from google.adk.agents import LlmAgent
|
|
64
|
+
from google.genai import types as genai_types
|
|
60
65
|
from adk_code_mode import (
|
|
61
66
|
CODE_MODE_SYSTEM_INSTRUCTION,
|
|
62
67
|
CodeModeCodeExecutor,
|
|
@@ -78,6 +83,11 @@ root_agent = LlmAgent(
|
|
|
78
83
|
instruction=f"You are a helpful assistant.\n\n{CODE_MODE_SYSTEM_INSTRUCTION}",
|
|
79
84
|
tools=[], # do NOT also bind tools here; the executor owns them.
|
|
80
85
|
code_executor=executor,
|
|
86
|
+
generate_content_config=genai_types.GenerateContentConfig(
|
|
87
|
+
tool_config=genai_types.ToolConfig(
|
|
88
|
+
function_calling_config=genai_types.FunctionCallingConfig(mode="NONE"),
|
|
89
|
+
),
|
|
90
|
+
),
|
|
81
91
|
before_model_callback=code_mode_before_model_callback(executor),
|
|
82
92
|
)
|
|
83
93
|
```
|
|
@@ -126,10 +136,10 @@ Setting `ADK_CODE_MODE_CONTROL_HTTP=1` activates HTTP mode. The container:
|
|
|
126
136
|
```bash
|
|
127
137
|
# Push the sandbox image to Artifact Registry
|
|
128
138
|
gcloud auth configure-docker <region>-docker.pkg.dev
|
|
129
|
-
docker pull ghcr.io/a2anet/adk-code-mode:latest
|
|
139
|
+
docker pull --platform linux/amd64 ghcr.io/a2anet/adk-code-mode:latest
|
|
130
140
|
docker tag ghcr.io/a2anet/adk-code-mode:latest \
|
|
131
|
-
<region>-docker.pkg.dev/<project>/adk-code-mode
|
|
132
|
-
docker push <region>-docker.pkg.dev/<project>/adk-code-mode
|
|
141
|
+
<region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
142
|
+
docker push <region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
133
143
|
|
|
134
144
|
# Create a VPC connector with no egress routes (blocks outbound network from sandbox)
|
|
135
145
|
gcloud compute networks create adk-sandbox-vpc --subnet-mode=custom
|
|
@@ -149,16 +159,17 @@ gcloud compute networks vpc-access connectors create adk-sandbox-connector \
|
|
|
149
159
|
|
|
150
160
|
# Deploy — note --concurrency 1 and --vpc-egress=all-traffic
|
|
151
161
|
gcloud run deploy adk-code-mode-sandbox \
|
|
152
|
-
--image <region>-docker.pkg.dev/<project>/adk-code-mode
|
|
162
|
+
--image <region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest \
|
|
153
163
|
--region <region> \
|
|
154
164
|
--port 8080 \
|
|
155
165
|
--cpu 1 \
|
|
156
166
|
--memory 1Gi \
|
|
157
167
|
--concurrency 1 \
|
|
158
|
-
--
|
|
168
|
+
--allow-unauthenticated \
|
|
159
169
|
--vpc-connector=adk-sandbox-connector \
|
|
160
170
|
--vpc-egress=all-traffic \
|
|
161
|
-
--set-env-vars "ADK_CODE_MODE_CONTROL_HTTP=1
|
|
171
|
+
--set-env-vars "ADK_CODE_MODE_CONTROL_HTTP=1" \
|
|
172
|
+
--set-secrets "ADK_CODE_MODE_AUTH_TOKEN=<your-secret-name>:latest"
|
|
162
173
|
```
|
|
163
174
|
|
|
164
175
|
Then in your agent:
|
|
@@ -301,12 +312,41 @@ The only things crossing the boundary are: code, tool call arguments, tool retur
|
|
|
301
312
|
|
|
302
313
|
### What the model sees
|
|
303
314
|
|
|
304
|
-
Your `instruction` (containing `CODE_MODE_SYSTEM_INSTRUCTION`) followed by a `<
|
|
315
|
+
Your `instruction` (containing `CODE_MODE_SYSTEM_INSTRUCTION`) followed by a `<code-mode>` block appended by the callback:
|
|
305
316
|
|
|
306
317
|
```
|
|
307
318
|
…your instruction…
|
|
308
319
|
|
|
309
|
-
|
|
320
|
+
# How to execute code and use tools
|
|
321
|
+
Code you write in a fenced Python block (i.e. ```python) will be executed in a sandbox.
|
|
322
|
+
The Python Standard Library and a custom set of tools are available to you.
|
|
323
|
+
To see the result of your code, you need to print it.
|
|
324
|
+
|
|
325
|
+
For example, if you had the following tool:
|
|
326
|
+
|
|
327
|
+
```
|
|
328
|
+
from tools.slack import send_message
|
|
329
|
+
|
|
330
|
+
def send_message(*, channel: str, text: str, thread_ts: str | None = ...) -> Any:
|
|
331
|
+
"""Send a message to a Slack channel."""
|
|
332
|
+
...
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
To call the tool, you should write:
|
|
336
|
+
|
|
337
|
+
"""
|
|
338
|
+
```python
|
|
339
|
+
from tools.slack import send_message
|
|
340
|
+
|
|
341
|
+
print(send_message(channel="C123", text="hi"))
|
|
342
|
+
```
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
# How to use files and variables in between executions
|
|
346
|
+
Code is executed in a new environment each time.
|
|
347
|
+
To list available Artifacts, use the `list_artifacts` tool. To save an Artifact, use the `save_artifact` tool, and to load an Artifact, use the `load_artifact` tool.
|
|
348
|
+
|
|
349
|
+
<code-mode>
|
|
310
350
|
|
|
311
351
|
# tools.slack
|
|
312
352
|
|
|
@@ -325,7 +365,20 @@ def send_message(*, channel: str, text: str, thread_ts: str | None = ...) -> Any
|
|
|
325
365
|
from tools import save_artifact, load_artifact, list_artifacts
|
|
326
366
|
…
|
|
327
367
|
|
|
328
|
-
</
|
|
368
|
+
</code-mode>
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
When the rendered catalog exceeds `max_catalog_chars`, the per-tool sections are replaced with:
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
<code-mode>
|
|
375
|
+
A `tools` package is available in the sandbox. List `/tools/` with
|
|
376
|
+
`pathlib.Path('/tools').iterdir()`. Each entry is either a `.py` file
|
|
377
|
+
(a top-level tool, importable as `from tools import <name>`) or a
|
|
378
|
+
subdirectory (a namespace, with tools importable as
|
|
379
|
+
`from tools.<namespace> import <name>`). To see a tool's signature and
|
|
380
|
+
docstring, read its `.py` file with `open(...).read()`.
|
|
381
|
+
</code-mode>
|
|
329
382
|
```
|
|
330
383
|
|
|
331
384
|
Text and JSON-like MIME types travel as plain strings in artifact tools; binary content is base64-encoded. `load_artifact` returns `{"kind": "text" | "bytes", "data": str, "mime_type": str | None}`.
|
|
@@ -12,7 +12,7 @@ callback:
|
|
|
12
12
|
2. Renders the catalog — signatures + docstrings for every tool —
|
|
13
13
|
falling back to a short overflow message when the rendered catalog
|
|
14
14
|
would exceed ``max_catalog_chars``.
|
|
15
|
-
3. Appends ``\\n\\n<
|
|
15
|
+
3. Appends ``\\n\\n<code-mode>\\n…\\n</code-mode>`` to
|
|
16
16
|
``llm_request.config.system_instruction``.
|
|
17
17
|
4. Caches the resolved tools on the executor so the follow-up
|
|
18
18
|
``execute_code`` call reuses them instead of re-resolving toolsets.
|
|
@@ -31,8 +31,8 @@ if TYPE_CHECKING:
|
|
|
31
31
|
|
|
32
32
|
logger = logging.getLogger("adk_code_mode.callback")
|
|
33
33
|
|
|
34
|
-
_TOOLS_OPEN = "<
|
|
35
|
-
_TOOLS_CLOSE = "</
|
|
34
|
+
_TOOLS_OPEN = "<code-mode>"
|
|
35
|
+
_TOOLS_CLOSE = "</code-mode>"
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def code_mode_before_model_callback(
|
|
@@ -40,7 +40,7 @@ from pydantic import ConfigDict, Field, PrivateAttr
|
|
|
40
40
|
|
|
41
41
|
from adk_code_mode._artifact_tools import ARTIFACT_TOOLS
|
|
42
42
|
from adk_code_mode.output import truncate
|
|
43
|
-
from adk_code_mode.runtime.base import
|
|
43
|
+
from adk_code_mode.runtime.base import SandboxBackend, SandboxResult, SandboxSession
|
|
44
44
|
from adk_code_mode.runtime.protocol import (
|
|
45
45
|
PROTOCOL_VERSION,
|
|
46
46
|
DoneFrame,
|
|
@@ -68,10 +68,30 @@ CODE_MODE_SYSTEM_INSTRUCTION = """\
|
|
|
68
68
|
# How to execute code and use tools
|
|
69
69
|
Code you write in a fenced Python block (i.e. ```python) will be executed in a sandbox.
|
|
70
70
|
The Python Standard Library and a custom set of tools are available to you.
|
|
71
|
-
To see the result of your code, you need to print it.
|
|
71
|
+
To see the result of your code, you need to print it.
|
|
72
|
+
|
|
73
|
+
For example, if you had the following tool:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
from tools.slack import send_message
|
|
77
|
+
|
|
78
|
+
def send_message(*, channel: str, text: str, thread_ts: str | None = ...) -> Any:
|
|
79
|
+
\"\"\"Send a message to a Slack channel.\"\"\"
|
|
80
|
+
...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
To call the tool, you should write:
|
|
84
|
+
|
|
85
|
+
\"\"\"
|
|
86
|
+
```python
|
|
87
|
+
from tools.slack import send_message
|
|
88
|
+
|
|
89
|
+
print(send_message(channel="C123", text="hi"))
|
|
90
|
+
```
|
|
91
|
+
\"\"\"
|
|
72
92
|
|
|
73
93
|
# How to use files and variables in between executions
|
|
74
|
-
Code is executed in a new environment each time.
|
|
94
|
+
Code is executed in a new environment each time.
|
|
75
95
|
To list available Artifacts, use the `list_artifacts` tool. To save an Artifact, use the `save_artifact` tool, and to load an Artifact, use the `load_artifact` tool.
|
|
76
96
|
"""
|
|
77
97
|
|
|
@@ -172,7 +172,7 @@ async def test_agent_runs_code_block_through_executor() -> None:
|
|
|
172
172
|
else:
|
|
173
173
|
rendered = "\n".join(p for p in system_instruction if isinstance(p, str))
|
|
174
174
|
assert CODE_MODE_SYSTEM_INSTRUCTION.split("\n", 1)[0] in rendered
|
|
175
|
-
assert "<
|
|
175
|
+
assert "<code-mode>" in rendered and "</code-mode>" in rendered
|
|
176
176
|
assert "def echo" in rendered
|
|
177
177
|
|
|
178
178
|
|
|
@@ -57,8 +57,8 @@ async def test_callback_appends_block_when_system_instruction_is_none() -> None:
|
|
|
57
57
|
|
|
58
58
|
instruction = request.config.system_instruction
|
|
59
59
|
assert isinstance(instruction, str)
|
|
60
|
-
assert instruction.startswith("<
|
|
61
|
-
assert instruction.rstrip().endswith("</
|
|
60
|
+
assert instruction.startswith("<code-mode>")
|
|
61
|
+
assert instruction.rstrip().endswith("</code-mode>")
|
|
62
62
|
assert "def ping" in instruction
|
|
63
63
|
|
|
64
64
|
|
|
@@ -73,8 +73,8 @@ async def test_callback_appends_block_to_string_system_instruction() -> None:
|
|
|
73
73
|
instruction = request.config.system_instruction
|
|
74
74
|
assert isinstance(instruction, str)
|
|
75
75
|
assert instruction.startswith("You are an assistant.")
|
|
76
|
-
assert "<
|
|
77
|
-
assert instruction.rstrip().endswith("</
|
|
76
|
+
assert "<code-mode>" in instruction
|
|
77
|
+
assert instruction.rstrip().endswith("</code-mode>")
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
@pytest.mark.asyncio
|
|
@@ -88,8 +88,8 @@ async def test_callback_appends_block_to_list_system_instruction() -> None:
|
|
|
88
88
|
instruction = request.config.system_instruction
|
|
89
89
|
assert isinstance(instruction, list)
|
|
90
90
|
assert instruction[:2] == ["First part.", "Second part."]
|
|
91
|
-
assert instruction[-1].startswith("<
|
|
92
|
-
assert instruction[-1].rstrip().endswith("</
|
|
91
|
+
assert instruction[-1].startswith("<code-mode>")
|
|
92
|
+
assert instruction[-1].rstrip().endswith("</code-mode>")
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
@pytest.mark.asyncio
|
|
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-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py
RENAMED
|
File without changes
|
{adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py
RENAMED
|
File without changes
|
{adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py
RENAMED
|
File without changes
|
{adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py
RENAMED
|
File without changes
|
{adk_code_mode-0.2.0 → adk_code_mode-0.2.1}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py
RENAMED
|
File without changes
|
{adk_code_mode-0.2.0 → adk_code_mode-0.2.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
|