1616
1717from __future__ import annotations
1818
19- import json
2019import os
2120import re
2221import time
2625
2726from agentkit .sdk .tools .client import AgentkitToolsClient
2827from agentkit .sdk .tools import types as tools_types
29- from agentkit .toolkit .cli .sandbox .session_create import (
28+ from agentkit .toolkit .cli .sandbox .model_config import (
29+ ANTHROPIC_BASE_URL_ENV_KEYS ,
30+ CODE_ENV_CODEX_HOME ,
31+ CODE_ENV_HOME ,
32+ CODEX_CONFIG_TOML_ENV ,
33+ CODEX_MODEL_CATALOG_JSON_ENV ,
34+ DEFAULT_ANTHROPIC_BASE_URL ,
35+ DEFAULT_MODEL_BASE_URL ,
36+ DEFAULT_MODEL_NAME ,
3037 MODEL_API_KEY_ENV ,
3138 MODEL_API_KEY_ENV_KEYS ,
39+ MODEL_BASE_URL_ENV_KEYS ,
3240 MODEL_NAME_ENV_KEYS ,
41+ build_codex_config_toml as _shared_build_codex_config_toml ,
42+ build_codex_model_catalog_json as _shared_build_codex_model_catalog_json ,
3343)
3444from agentkit .toolkit .cli .sandbox .tool_resolve import save_tool_result
3545from agentkit .toolkit .cli .sandbox .utils import error
4454SANDBOX_REGION_ENV = "AGENTKIT_SANDBOX_REGION"
4555SANDBOX_TOS_REGION_ENV = "AGENTKIT_SANDBOX_TOS_REGION"
4656DEFAULT_CREATE_TOOL_TYPE = "CodeEnv"
57+ DEFAULT_CPU = 4
58+ VALID_CPU_VALUES = (2 , 4 , 8 , 16 )
59+ MEMORY_MB_PER_CPU = 2048
4760DEFAULT_TOS_BUCKET_PATH = "/sandbox-session/default/default"
4861DEFAULT_TOS_LOCAL_PATH = "/home/gem"
49- CODE_ENV_HOME = "/home/gem"
50- CODE_ENV_CODEX_HOME = "/home/gem/.codex"
51- CODEX_MODEL_CATALOG_PATH = f"{ CODE_ENV_CODEX_HOME } /model-catalog.json"
52- DEFAULT_MODEL_NAME = "deepseek-v4-flash-260425"
53- DEFAULT_MODEL_NAME_LIST = (
54- DEFAULT_MODEL_NAME ,
55- "deepseek-v4-pro-260425" ,
56- "doubao-seed-2-0-pro-260215" ,
57- )
58- DEFAULT_MODEL_CONTEXT_WINDOW = 1000000
59- MODEL_CONTEXT_WINDOW_OVERRIDES = {
60- "doubao-seed-2-0-pro-260215" : 256000 ,
61- }
62- DEFAULT_MODEL_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
63- DEFAULT_ANTHROPIC_BASE_URL = "https://ark.cn-beijing.volces.com/api/compatible"
64- MODEL_BASE_URL_ENV_KEYS = (
65- "OPENCODE_BASE_URL" ,
66- "CODEX_BASE_URL" ,
67- "MODEL_BASE_URL" ,
68- )
69- ANTHROPIC_BASE_URL_ENV_KEYS = ("ANTHROPIC_BASE_URL" ,)
7062DISABLED_SERVICE_ENV_KEYS = (
7163 "DISABLE_JUPYTER" ,
7264 "DISABLE_CODE_SERVER" ,
@@ -94,9 +86,21 @@ def _generate_tool_name(tool_type: str) -> str:
9486
9587def _resolve_tos_bucket (tos_bucket : Optional [str ]) -> str :
9688 resolved_bucket = (tos_bucket or "" ).strip ()
97- if resolved_bucket :
98- return resolved_bucket
99- return TOSService .generate_bucket_name ()
89+ if not resolved_bucket :
90+ error ("--tos-bucket must not be empty" )
91+ return resolved_bucket
92+
93+
94+ def _validate_cpu (value : int ) -> int :
95+ if value not in VALID_CPU_VALUES :
96+ allowed = ", " .join (str (item ) for item in VALID_CPU_VALUES )
97+ raise typer .BadParameter (f"--cpu must be one of: { allowed } " )
98+ return value
99+
100+
101+ def _cpu_to_resource_shape (cpu : int ) -> tuple [int , int ]:
102+ resolved_cpu = _validate_cpu (cpu )
103+ return resolved_cpu * 1000 , resolved_cpu * MEMORY_MB_PER_CPU
100104
101105
102106def _append_tool_envs (
@@ -114,94 +118,12 @@ def _append_tool_envs(
114118 )
115119
116120
117- def _toml_quote (value : str ) -> str :
118- return json .dumps (value , ensure_ascii = False )
119-
120-
121121def _build_codex_config_toml (model_name : str ) -> str :
122- quoted_model = _toml_quote (model_name )
123- return "\n " .join (
124- [
125- 'model_provider = "codex"' ,
126- f"model = { quoted_model } " ,
127- f"review_model = { quoted_model } " ,
128- 'approval_policy = "never"' ,
129- 'sandbox_mode = "danger-full-access"' ,
130- 'model_reasoning_effort = "medium"' ,
131- 'personality = "pragmatic"' ,
132- "check_for_update_on_startup = false" ,
133- 'web_search = "disabled"' ,
134- f"model_catalog_json = { _toml_quote (CODEX_MODEL_CATALOG_PATH )} " ,
135- "" ,
136- "[model_providers.codex]" ,
137- 'name = "codex"' ,
138- f"base_url = { _toml_quote (DEFAULT_MODEL_BASE_URL )} " ,
139- 'wire_api = "responses"' ,
140- 'env_key = "CODEX_API_KEY"' ,
141- "" ,
142- "[tui]" ,
143- "show_tooltips = false" ,
144- "" ,
145- '[projects."/home/gem"]' ,
146- 'trust_level = "trusted"' ,
147- "" ,
148- ]
149- )
150-
151-
152- def _build_model_catalog_item (model_name : str , max_context_window : int ) -> dict :
153- return {
154- "slug" : model_name ,
155- "display_name" : model_name ,
156- "supported_reasoning_levels" : [
157- {
158- "effort" : "low" ,
159- "description" : "Fast responses with lighter reasoning" ,
160- },
161- {
162- "effort" : "medium" ,
163- "description" : "Balances speed and reasoning depth" ,
164- },
165- {
166- "effort" : "high" ,
167- "description" : "Greater reasoning depth" ,
168- },
169- ],
170- "max_context_window" : max_context_window ,
171- "shell_type" : "shell_command" ,
172- "visibility" : "list" ,
173- "supported_in_api" : True ,
174- "priority" : 100 ,
175- "base_instructions" : "" ,
176- "supports_reasoning_summaries" : True ,
177- "support_verbosity" : False ,
178- "truncation_policy" : {"mode" : "tokens" , "limit" : 10000 },
179- "supports_parallel_tool_calls" : False ,
180- "experimental_supported_tools" : [],
181- }
182-
183-
184- def _model_catalog_context_window (model_name : str ) -> int :
185- return MODEL_CONTEXT_WINDOW_OVERRIDES .get (
186- model_name ,
187- DEFAULT_MODEL_CONTEXT_WINDOW ,
188- )
122+ return _shared_build_codex_config_toml (model_name )
189123
190124
191125def _build_codex_model_catalog_json (model_name : str ) -> str :
192- deduped_model_names = list (
193- dict .fromkeys ((model_name , * DEFAULT_MODEL_NAME_LIST ))
194- )
195- payload = {
196- "models" : [
197- _build_model_catalog_item (
198- name ,
199- _model_catalog_context_window (name ),
200- )
201- for name in deduped_model_names
202- ]
203- }
204- return json .dumps (payload , ensure_ascii = False , indent = 2 )
126+ return _shared_build_codex_model_catalog_json (model_name )
205127
206128
207129def _append_code_env_tool_envs (
@@ -223,11 +145,11 @@ def _append_code_env_tool_envs(
223145 Value = CODE_ENV_CODEX_HOME ,
224146 ),
225147 tools_types .EnvsItemForCreateTool (
226- Key = "CODEX_CONFIG_TOML" ,
148+ Key = CODEX_CONFIG_TOML_ENV ,
227149 Value = _build_codex_config_toml (model_name ),
228150 ),
229151 tools_types .EnvsItemForCreateTool (
230- Key = "CODEX_MODEL_CATALOG_JSON" ,
152+ Key = CODEX_MODEL_CATALOG_JSON_ENV ,
231153 Value = _build_codex_model_catalog_json (model_name ),
232154 ),
233155 ]
@@ -267,16 +189,20 @@ def _build_create_tool_request(
267189 name : Optional [str ],
268190 tos_bucket : Optional [str ],
269191 tos_region : str ,
192+ cpu : int = DEFAULT_CPU ,
270193 model_name : Optional [str ] = None ,
271194 model_api_key : Optional [str ] = None ,
272195) -> tools_types .CreateToolRequest :
273196 resolved_tool_type = tool_type .strip () or DEFAULT_CREATE_TOOL_TYPE
274197 resolved_name = (name or "" ).strip () or _generate_tool_name (resolved_tool_type )
275198 tos_mount_config = _build_tos_mount_config (tos_bucket , tos_region )
199+ cpu_milli , memory_mb = _cpu_to_resource_shape (cpu )
276200
277201 return tools_types .CreateToolRequest (
278202 Name = resolved_name ,
279203 ToolType = resolved_tool_type ,
204+ CpuMilli = cpu_milli ,
205+ MemoryMb = memory_mb ,
280206 AuthorizerConfiguration = tools_types .AuthorizerForCreateTool (
281207 KeyAuth = tools_types .AuthorizerKeyAuthForCreateTool (
282208 ApiKeyName = generate_apikey_name (),
@@ -299,7 +225,10 @@ def _build_create_tool_request(
299225def _build_tos_mount_config (
300226 tos_bucket : Optional [str ],
301227 region : str ,
302- ) -> tools_types .TosMountForCreateTool :
228+ ) -> tools_types .TosMountForCreateTool | None :
229+ if not (tos_bucket or "" ).strip ():
230+ return None
231+
303232 resolved_bucket = _resolve_tos_bucket (tos_bucket )
304233 service = TOSService (
305234 TOSServiceConfig (
@@ -397,6 +326,7 @@ def create_tool(
397326 tool_type : str = DEFAULT_CREATE_TOOL_TYPE ,
398327 tool_name : Optional [str ] = None ,
399328 tos_bucket : Optional [str ] = None ,
329+ cpu : int = DEFAULT_CPU ,
400330 model_name : Optional [str ] = None ,
401331 model_api_key : Optional [str ] = None ,
402332) -> dict [str , object ]:
@@ -407,6 +337,7 @@ def create_tool(
407337 name = tool_name ,
408338 tos_bucket = tos_bucket ,
409339 tos_region = tos_region ,
340+ cpu = cpu ,
410341 model_name = model_name ,
411342 model_api_key = model_api_key ,
412343 )
@@ -440,7 +371,16 @@ def create_command(
440371 tos_bucket : Optional [str ] = typer .Option (
441372 None ,
442373 "--tos-bucket" ,
443- help = "TOS bucket to mount at /home/gem." ,
374+ help = (
375+ "TOS bucket to mount at /home/gem. "
376+ "Omit to create the tool without a TOS mount."
377+ ),
378+ ),
379+ cpu : int = typer .Option (
380+ DEFAULT_CPU ,
381+ "--cpu" ,
382+ help = "Sandbox vCPU count. Allowed values: 2, 4, 8, 16." ,
383+ callback = _validate_cpu ,
444384 ),
445385 model_name : Optional [str ] = typer .Option (
446386 None ,
@@ -465,6 +405,7 @@ def create_command(
465405 tool_type = tool_type ,
466406 tool_name = tool_name ,
467407 tos_bucket = tos_bucket ,
408+ cpu = cpu ,
468409 model_name = model_name ,
469410 model_api_key = model_api_key ,
470411 )
0 commit comments