Skip to content

Commit 2e97a17

Browse files
perf(studio): create sandbox tools in parallel (#724)
* perf(studio): create sandbox tools in parallel * fix(frontend): align agent selector icon
1 parent ba5871b commit 2e97a17

13 files changed

Lines changed: 782 additions & 763 deletions

File tree

‎docs/content/docs/framework/frontend.en.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ frontend-process memory, so polling and downloads continue to work when FaaS
223223
requests reach different instances.
224224

225225
On the first cloud deployment, the command creates two independent CodeEnv
226-
Tools with the deployer's AK/SK when Tool IDs are omitted. Existing Tools can be
227-
selected with `--sandbox-chat-codex-tool-id` and
226+
Tools in parallel with the deployer's AK/SK when Tool IDs are omitted. Existing
227+
Tools can be selected with `--sandbox-chat-codex-tool-id` and
228228
`--sandbox-skill-creator-tool-id`. The Ark credential is resolved with the
229229
deployer's AK/SK and written directly to both Tools as model environment
230230
variables. Sandbox sessions inherit those Tool variables. The browser and

‎docs/content/docs/framework/frontend.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ ZIP 上传到 TOS,再调用 Skills API 创建或更新 Skill;只有用户填
191191
候选 Session 的 TTL 为 30 分钟,用户重新创建或离开任务时会立即清理。任务状态保存
192192
在 Sandbox 而非 Frontend 进程内存,因此 FaaS 请求命中不同实例时仍可继续轮询和下载。
193193

194-
云上首次部署时,若没有指定 Tool ID,部署命令会使用部署 AK/SK 自动创建两个独立
194+
云上首次部署时,若没有指定 Tool ID,部署命令会使用部署 AK/SK 并行创建两个独立
195195
CodeEnv Tool。也可以分别使用 `--sandbox-chat-codex-tool-id` 和
196196
`--sandbox-skill-creator-tool-id` 指定已有 Tool。部署命令会通过 AgentKit 凭据托管
197197
将 Ark 凭据保存到 KMS,并把代理地址和可撤销票据绑定到两个 Tool;VeFaaS Function

‎frontend/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ memory, so polling and downloads continue to work when FaaS requests reach a
289289
different instance.
290290

291291
For local Studio, run the AgentKit `credential-hosting` command and bind its
292-
result to both CodeEnv Tools. A cloud deployment creates both Tools when their
293-
IDs are omitted. Alternatively, select existing Tools with
292+
result to both CodeEnv Tools. A cloud deployment creates both Tools in parallel
293+
when their IDs are omitted. Alternatively, select existing Tools with
294294
`--sandbox-chat-codex-tool-id` and `--sandbox-skill-creator-tool-id`. The deploy
295295
command obtains the Ark key with the deployer's Volcengine credentials, stores
296296
it through AgentKit credential hosting, and binds only the returned ticket and

‎frontend/src/styles.css‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ body {
247247
border-color: hsl(8 46% 70%);
248248
background: hsl(8 55% 96%);
249249
}
250-
.agent-row-lead { width: 16px; height: 16px; color: hsl(var(--muted-foreground)); flex-shrink: 0; transform: translateY(3px); }
250+
.agent-row-lead { width: 16px; height: 16px; color: hsl(var(--muted-foreground)); flex-shrink: 0; }
251251
.agent-row--connected .agent-row-lead { color: hsl(142 48% 38%); }
252252
.agent-row-name {
253253
flex: 1;

‎frontend/tests/studioAccess.test.mjs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ test("runtime authorization failures are not reported as unsupported", () => {
6060
});
6161

6262
test("selected Agent icons are optically aligned with the label", () => {
63-
assert.match(stylesSource, /\.agent-row-lead[^}]*transform: translateY\(3px\)/);
63+
assert.match(stylesSource, /\.agent-row\s*{[^}]*align-items: center/);
64+
assert.doesNotMatch(stylesSource, /\.agent-row-lead[^}]*transform:/);
6465
assert.match(stylesSource, /\.agent-row-chev\.open[^}]*translateY\(1px\) rotate\(90deg\)/);
6566
});
6667

‎tests/cli/test_studio_deploy_target.py‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import threading
1516
from pathlib import Path
1617
from types import SimpleNamespace
1718
from unittest.mock import Mock
@@ -294,8 +295,12 @@ def register_callback_for_user_pool_client(self, **kwargs: object) -> None:
294295
def test_studio_deploy_creates_distinct_sandbox_tools_when_ids_are_omitted(
295296
monkeypatch: pytest.MonkeyPatch,
296297
) -> None:
298+
monkeypatch.delenv("SANDBOX_CHAT_CODEX", raising=False)
299+
monkeypatch.delenv("SANDBOX_SKILL_CREATOR", raising=False)
297300
created_names: list[str] = []
298301
credential_tool_ids: list[str] = []
302+
creation_barrier = threading.Barrier(2)
303+
created_names_lock = threading.Lock()
299304

300305
class _FakeCloudAgentEngine:
301306
def __init__(self, **_: object) -> None:
@@ -310,8 +315,10 @@ def deploy(self, **_: object) -> SimpleNamespace:
310315

311316
def _ensure_tool(**kwargs: object) -> str:
312317
name = str(kwargs["name"])
313-
created_names.append(name)
314-
return f"tool-{len(created_names)}"
318+
creation_barrier.wait(timeout=5)
319+
with created_names_lock:
320+
created_names.append(name)
321+
return "chat-tool" if "-chat-" in name else "skill-tool"
315322

316323
monkeypatch.setattr(
317324
"veadk.cloud.cloud_agent_engine.CloudAgentEngine", _FakeCloudAgentEngine
@@ -351,12 +358,11 @@ def _ensure_tool(**kwargs: object) -> str:
351358

352359
assert result.exit_code == 0, result.output
353360
assert len(created_names) == 2
354-
assert created_names[0] != created_names[1]
355-
assert "chat" in created_names[0]
356-
assert "skill" in created_names[1]
357-
assert veadk_environments["SANDBOX_CHAT_CODEX"] == "tool-1"
358-
assert veadk_environments["SANDBOX_SKILL_CREATOR"] == "tool-2"
359-
assert credential_tool_ids == ["tool-1", "tool-2"]
361+
assert any("chat" in name for name in created_names)
362+
assert any("skill" in name for name in created_names)
363+
assert veadk_environments["SANDBOX_CHAT_CODEX"] == "chat-tool"
364+
assert veadk_environments["SANDBOX_SKILL_CREATOR"] == "skill-tool"
365+
assert credential_tool_ids == ["chat-tool", "skill-tool"]
360366

361367

362368
@pytest.mark.parametrize(

‎veadk/cli/cli_frontend.py‎

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import sys
3131

3232
from collections.abc import Iterable
33+
from concurrent.futures import ThreadPoolExecutor
3334
from pathlib import Path
3435
from typing import Any
3536
from urllib.parse import urlparse
@@ -3925,29 +3926,40 @@ def frontend_deploy(
39253926
studio_sandbox_tool_name,
39263927
)
39273928

3929+
missing_sandbox_tools: dict[str, str] = {}
39283930
for purpose, tool_id in sandbox_tool_ids.items():
39293931
if tool_id:
39303932
continue
39313933
tool_name = studio_sandbox_tool_name(vefaas_app_name, purpose)
39323934
click.echo(f"Ensuring AgentKit {purpose} CodeEnv Tool '{tool_name}'…")
3933-
try:
3934-
sandbox_tool_ids[purpose] = ensure_studio_code_env_tool(
3935-
name=tool_name,
3936-
region=region,
3937-
access_key=ak,
3938-
secret_key=sk,
3939-
session_token=session_token or "",
3940-
)
3941-
except Exception as error:
3942-
detail = _safe_exception_detail(
3943-
error,
3944-
secrets=(ak, sk, session_token),
3945-
)
3946-
raise click.ClickException(
3947-
f"Failed to provision the AgentKit {purpose} CodeEnv Tool. "
3948-
f"Underlying error:\n{detail}"
3949-
) from error
3950-
click.echo(f"AgentKit {purpose} CodeEnv Tool is ready.")
3935+
missing_sandbox_tools[purpose] = tool_name
3936+
3937+
if missing_sandbox_tools:
3938+
with ThreadPoolExecutor(max_workers=len(missing_sandbox_tools)) as executor:
3939+
tool_futures = {
3940+
purpose: executor.submit(
3941+
ensure_studio_code_env_tool,
3942+
name=tool_name,
3943+
region=region,
3944+
access_key=ak,
3945+
secret_key=sk,
3946+
session_token=session_token or "",
3947+
)
3948+
for purpose, tool_name in missing_sandbox_tools.items()
3949+
}
3950+
for purpose, future in tool_futures.items():
3951+
try:
3952+
sandbox_tool_ids[purpose] = future.result()
3953+
except Exception as error:
3954+
detail = _safe_exception_detail(
3955+
error,
3956+
secrets=(ak, sk, session_token),
3957+
)
3958+
raise click.ClickException(
3959+
f"Failed to provision the AgentKit {purpose} CodeEnv Tool. "
3960+
f"Underlying error:\n{detail}"
3961+
) from error
3962+
click.echo(f"AgentKit {purpose} CodeEnv Tool is ready.")
39513963

39523964
from veadk.cli.frontend_skill_creator import (
39533965
ensure_skill_creator_model_credential,
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)