From f4e479ce802cad48956d46e719aa0c407ef2eb0a Mon Sep 17 00:00:00 2001 From: chenanran555 Date: Wed, 9 Sep 2026 16:45:37 +0800 Subject: [PATCH] feat(sandbox): add official image presets and template image selection --- packages/cli/src/commands.ts | 2 + .../commands/src/commands/sandbox/images.ts | 88 ++++++++++++ .../commands/src/commands/sandbox/template.ts | 31 ++++ packages/commands/src/index.ts | 1 + .../commands/tests/e2e/sandbox.e2e.test.ts | 117 +++++++++++++++ packages/commands/tests/e2e/topic-routes.ts | 1 + .../commands/tests/sandbox-images.test.ts | 134 +++++++++++++++++ skills/bailian-sandbox/SKILL.md | 21 +-- skills/bailian-sandbox/reference/index.md | 7 +- skills/bailian-sandbox/reference/sandbox.md | 135 ++++++++++++------ 10 files changed, 484 insertions(+), 53 deletions(-) create mode 100644 packages/commands/src/commands/sandbox/images.ts create mode 100644 packages/commands/tests/sandbox-images.test.ts diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index 87355ca..5551caf 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -207,6 +207,7 @@ import { managedAgentFileDownload, managedAgentFileDelete, sandboxCreate, + sandboxOfficialImages, sandboxList, sandboxGet, sandboxConnect, @@ -437,6 +438,7 @@ export const commands: Record = { "managed-agent file download": managedAgentFileDownload, "managed-agent file delete": managedAgentFileDelete, "sandbox create": sandboxCreate, + "sandbox official-images": sandboxOfficialImages, "sandbox list": sandboxList, "sandbox get": sandboxGet, "sandbox connect": sandboxConnect, diff --git a/packages/commands/src/commands/sandbox/images.ts b/packages/commands/src/commands/sandbox/images.ts new file mode 100644 index 0000000..c40239c --- /dev/null +++ b/packages/commands/src/commands/sandbox/images.ts @@ -0,0 +1,88 @@ +import { defineCommand, detectOutputFormat, UsageError } from "bailian-cli-core"; +import { emitBare, emitResult } from "bailian-cli-runtime"; + +/** Pinned CLI presets, not a live catalog or a guarantee of regional availability. */ +export const SANDBOX_IMAGES = [ + { + id: "code-interpreter", + imageName: "代码解释器", + imageUrl: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/code-interpreter-v1:v0.0.44", + icon: "https://img.alicdn.com/imgextra/i2/O1CN01iX8RH9ckFvC093x2_!!6000000000905-2-tps-72-72.png", + description: { + "en-US": "Python / Node.js runtimes with common data-processing libraries", + "zh-CN": "Python / Node.js 运行时+常用数据处理库", + }, + }, + { + id: "browser", + imageName: "浏览器", + imageUrl: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44", + icon: "https://img.alicdn.com/imgextra/i4/O1CN01ShCbPEunrRI093x2_!!6000000000155-2-tps-72-72.png", + description: { + "en-US": "Chromium and a visual desktop for clicking, filling forms, and screenshots", + "zh-CN": "Chromium +可视化桌面,支持点击/ 填表/截图", + }, + }, + { + id: "all-in-one", + imageName: "全能型", + imageUrl: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/all-in-one:v0.0.44", + icon: "https://img.alicdn.com/imgextra/i1/O1CN01smhklUahsyE093x2_!!6000000006657-2-tps-72-72.png", + description: { + "en-US": "Code execution and browser capabilities together", + "zh-CN": "代码执行+浏览器双能力", + }, + }, +] as const; + +export const SANDBOX_IMAGE_CHOICES = SANDBOX_IMAGES.flatMap((image) => [image.id, image.imageName]); + +export const SANDBOX_IMAGE_NOTES = SANDBOX_IMAGES.map((image) => ({ + "en-US": `${image.id} (${image.imageName}): ${image.description["en-US"]}. ${image.imageUrl}`, + "zh-CN": `${image.id}(${image.imageName}):${image.description["zh-CN"]}。${image.imageUrl}`, +})); + +export function resolveSandboxImage(selector: string) { + const image = SANDBOX_IMAGES.find( + (candidate) => candidate.id === selector || candidate.imageName === selector, + ); + if (!image) { + throw new UsageError( + `Unknown built-in image / 未知内置镜像: ${selector}. ${SANDBOX_IMAGE_CHOICES.join(", ")}`, + ); + } + return image; +} + +export const sandboxOfficialImages = defineCommand({ + description: { + "en-US": "List the built-in Sandbox base images (offline)", + "zh-CN": "列出 CLI 内置的 Sandbox 基础镜像(离线)", + }, + auth: "none", + exampleArgs: ["", "--output json", "--quiet"], + notes: [ + { + "en-US": + "Use a preset ID or Chinese name with template create/update --image. These are pinned cn-beijing images; other environments may differ. Use --from-image for a custom image.", + "zh-CN": + "在 template create/update 中通过 --image 传入预设 ID 或中文名。这些是固定版本的 cn-beijing 镜像,其他环境可能不同;自定义镜像使用 --from-image。", + }, + ...SANDBOX_IMAGE_NOTES, + ], + async run(ctx) { + if (ctx.settings.quiet) { + for (const image of SANDBOX_IMAGES) emitBare(image.id); + return; + } + if (detectOutputFormat(ctx.settings.output) === "json") { + emitResult(SANDBOX_IMAGES, "json"); + return; + } + for (const image of SANDBOX_IMAGES) { + emitBare(`${image.id} (${image.imageName})`); + emitBare(` ${image.imageUrl}`); + emitBare(` ${image.description["en-US"]} / ${image.description["zh-CN"]}`); + } + }, +}); diff --git a/packages/commands/src/commands/sandbox/template.ts b/packages/commands/src/commands/sandbox/template.ts index b368f42..300cdfb 100644 --- a/packages/commands/src/commands/sandbox/template.ts +++ b/packages/commands/src/commands/sandbox/template.ts @@ -13,6 +13,7 @@ import { type Settings, } from "bailian-cli-core"; import { createSpinner, emitBare, emitResult, formatTable } from "bailian-cli-runtime"; +import { resolveSandboxImage, SANDBOX_IMAGE_CHOICES, SANDBOX_IMAGE_NOTES } from "./images.ts"; import { BODY_FLAG, displayValue, @@ -69,6 +70,15 @@ const TEMPLATE_ID_FLAG = { } satisfies FlagsDef; const TEMPLATE_MUTATION_FIELDS = { + image: { + type: "string", + valueHint: "", + choices: SANDBOX_IMAGE_CHOICES, + description: { + "en-US": "Built-in image ID or Chinese name; fills fromImage and imageName", + "zh-CN": "内置镜像 ID 或中文名;自动填写 fromImage 和 imageName", + }, + }, name: { type: "string", valueHint: "", @@ -198,6 +208,11 @@ const BUILD_STATUS_FLAGS = { } satisfies FlagsDef; function applyTemplateMutationFlags(body: JsonObject, flags: CreateFlags | UpdateFlags): void { + if (flags.image !== undefined) { + const image = resolveSandboxImage(flags.image); + body.fromImage = image.imageUrl; + body.imageName = image.imageName; + } setDefined(body, "name", flags.name); setDefined(body, "cpuCount", flags.cpuCount); setDefined(body, "memoryMB", flags.memoryMb); @@ -356,12 +371,20 @@ export const sandboxTemplateCreate = defineCommand({ usageArgs: "(--name --cpu-count --memory-mb | --body ) [flags]", flags: CREATE_FLAGS, exampleArgs: [ + "--name browser --image browser --cpu-count 1 --memory-mb 2048", "--name python --cpu-count 1 --memory-mb 2048", "--body @template.json --async --output json", "--name browser --cpu-count 4 --memory-mb 8192 --dry-run --output json", ], notes: [ ...SANDBOX_NOTES, + ...SANDBOX_IMAGE_NOTES, + { + "en-US": + "--image overrides body fromImage/imageName; explicit --from-image/--image-name override the corresponding preset fields. Without --image, image behavior is unchanged.", + "zh-CN": + "--image 覆盖 body 中的 fromImage/imageName;显式 --from-image/--image-name 再覆盖对应预设字段。不传 --image 时保持原有镜像行为。", + }, { "en-US": "File mounts and other complete nested structures can be supplied through --body.", "zh-CN": "文件挂载等完整嵌套结构可通过 --body 提供。", @@ -480,12 +503,20 @@ export const sandboxTemplateUpdate = defineCommand({ usageArgs: "--template-id (--body | [fields])", flags: UPDATE_FLAGS, exampleArgs: [ + "--template-id tpl-xxx --image all-in-one", "--template-id tpl-xxx --cpu-count 4 --memory-mb 8192", "--template-id tpl-xxx --body @template-update.json --async --output json", "--template-id tpl-xxx --description updated --dry-run --output json", ], notes: [ ...SANDBOX_NOTES, + ...SANDBOX_IMAGE_NOTES, + { + "en-US": + "--image overrides body fromImage/imageName; explicit --from-image/--image-name override the corresponding preset fields. Without --image, image behavior is unchanged.", + "zh-CN": + "--image 覆盖 body 中的 fromImage/imageName;显式 --from-image/--image-name 再覆盖对应预设字段。不传 --image 时保持原有镜像行为。", + }, { "en-US": "Supplying envConfig or --env replaces the template's complete environment map.", "zh-CN": "传入 envConfig 或 --env 会整体替换模版的环境变量 Map。", diff --git a/packages/commands/src/index.ts b/packages/commands/src/index.ts index 821dcef..bf9c1a2 100644 --- a/packages/commands/src/index.ts +++ b/packages/commands/src/index.ts @@ -223,6 +223,7 @@ export { default as skillUpdate } from "./commands/skill/update.ts"; export { default as skillRemove } from "./commands/skill/remove.ts"; export { default as skillList } from "./commands/skill/list.ts"; export { default as skillInit } from "./commands/skill/init.ts"; +export { sandboxOfficialImages } from "./commands/sandbox/images.ts"; export { sandboxConnect, sandboxCreate, diff --git a/packages/commands/tests/e2e/sandbox.e2e.test.ts b/packages/commands/tests/e2e/sandbox.e2e.test.ts index 0e3b7e3..cb6c83d 100644 --- a/packages/commands/tests/e2e/sandbox.e2e.test.ts +++ b/packages/commands/tests/e2e/sandbox.e2e.test.ts @@ -27,6 +27,18 @@ function runCommandE2e(routes: typeof SANDBOX_ROUTES, args: string[]) { } describe("e2e: Sandbox command discovery", () => { + test("built-in images are discoverable without API Key authentication", async () => { + const { stderr, exitCode } = await runCommandHelp(SANDBOX_ROUTES, [ + "sandbox", + "official-images", + "--help", + ]); + expect(exitCode, stderr).toBe(0); + expect(stderr).toContain("Usage: bl sandbox official-images"); + expect(stderr).not.toContain("Authentication: API Key"); + expect(stderr).toContain("code-interpreter"); + expect(stderr).toContain("all-in-one"); + }); test.each([ ["sandbox", "create"], ["sandbox", "list"], @@ -69,6 +81,8 @@ describe("e2e: Sandbox command discovery", () => { ]); expect(exitCode, stderr).toBe(0); expect(stderr).toMatch(/--max-running-time /); + expect(stderr).toMatch(/--image <[^>]*code-interpreter[^>]*browser[^>]*all-in-one[^>]*>/); + expect(stderr).toContain("browser:v0.0.44"); expect(stderr).toMatch(/--async/); expect(stderr).toMatch(/--poll-interval /); expect(stderr).toMatch(/waits for build status ready/i); @@ -76,6 +90,109 @@ describe("e2e: Sandbox command discovery", () => { }); describe("e2e: Sandbox offline validation and dry-run", () => { + test("image catalog is available offline in JSON, text, and quiet output", async () => { + const jsonResult = await runCommandE2e(SANDBOX_ROUTES, [ + "sandbox", + "official-images", + "--output", + "json", + ]); + expect(jsonResult.exitCode, jsonResult.stderr).toBe(0); + const images = JSON.parse(jsonResult.stdout) as { + id: string; + imageName: string; + imageUrl: string; + }[]; + expect(images.map((image) => image.id)).toEqual(["code-interpreter", "browser", "all-in-one"]); + expect(images[1]).toMatchObject({ + imageName: "浏览器", + imageUrl: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44", + }); + const textResult = await runCommandE2e(SANDBOX_ROUTES, [ + "sandbox", + "official-images", + "--output", + "text", + ]); + expect(textResult.exitCode, textResult.stderr).toBe(0); + expect(textResult.stdout).toContain("代码解释器"); + expect(textResult.stdout).toContain("browser:v0.0.44"); + const quietResult = await runCommandE2e(SANDBOX_ROUTES, [ + "sandbox", + "official-images", + "--quiet", + ]); + expect(quietResult.exitCode, quietResult.stderr).toBe(0); + expect(quietResult.stdout.trim().split("\n")).toEqual([ + "code-interpreter", + "browser", + "all-in-one", + ]); + }); + + test.each([ + { + operation: "create", + args: ["--name", "test", "--cpu-count", "1", "--memory-mb", "2048"], + selector: "browser", + method: "POST", + }, + { + operation: "update", + args: ["--template-id", "template-test"], + selector: "浏览器", + method: "PUT", + }, + ])( + "template $operation resolves --image before dry-run output", + async ({ operation, args, selector, method }) => { + const { stdout, stderr, exitCode } = await runCommandE2e(SANDBOX_ROUTES, [ + "sandbox", + "template", + operation, + ...args, + "--image", + selector, + ...AUTH_ARGS, + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + expect(parseStdoutJson(stdout)).toMatchObject({ + method, + request: { + fromImage: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44", + imageName: "浏览器", + }, + }); + }, + ); + + test("unknown image selector fails before a request", async () => { + const { stderr, exitCode } = await runCommandE2e(SANDBOX_ROUTES, [ + "sandbox", + "template", + "create", + "--name", + "test", + "--cpu-count", + "1", + "--memory-mb", + "2048", + "--image", + "unknown", + ...AUTH_ARGS, + "--dry-run", + "--output", + "json", + ]); + expect(exitCode).toBe(2); + expect(JSON.parse(stderr)).toMatchObject({ + error: { code: 2, message: expect.stringContaining("--image") }, + }); + }); + test("create requires a template in flags or body", async () => { const { stderr, exitCode } = await runCommandE2e(SANDBOX_ROUTES, [ "sandbox", diff --git a/packages/commands/tests/e2e/topic-routes.ts b/packages/commands/tests/e2e/topic-routes.ts index 525dd7c..680993c 100644 --- a/packages/commands/tests/e2e/topic-routes.ts +++ b/packages/commands/tests/e2e/topic-routes.ts @@ -184,6 +184,7 @@ export const SKILL_ROUTES: E2eRouteExports = { export const SANDBOX_ROUTES: E2eRouteExports = { "sandbox create": "sandboxCreate", + "sandbox official-images": "sandboxOfficialImages", "sandbox list": "sandboxList", "sandbox get": "sandboxGet", "sandbox connect": "sandboxConnect", diff --git a/packages/commands/tests/sandbox-images.test.ts b/packages/commands/tests/sandbox-images.test.ts new file mode 100644 index 0000000..6968aaf --- /dev/null +++ b/packages/commands/tests/sandbox-images.test.ts @@ -0,0 +1,134 @@ +import { ExitCode } from "bailian-cli-core"; +import { describe, expect, test } from "vite-plus/test"; +import { resolveSandboxImage, SANDBOX_IMAGES } from "../src/commands/sandbox/images.ts"; +import { + buildTemplateCreateBody, + buildTemplateUpdateBody, +} from "../src/commands/sandbox/template.ts"; + +const EXPECTED_IMAGES = [ + ["code-interpreter", "代码解释器", "code-interpreter-v1"], + ["browser", "浏览器", "browser"], + ["all-in-one", "全能型", "all-in-one"], +] as const; + +describe("Sandbox built-in image presets", () => { + test("contains exactly the three pinned images with icons and bilingual descriptions", () => { + expect(SANDBOX_IMAGES.map((image) => image.id)).toEqual(EXPECTED_IMAGES.map(([id]) => id)); + for (const image of SANDBOX_IMAGES) { + expect(image.icon).toMatch(/^https:\/\/img\.alicdn\.com\/.*\.png$/); + expect(image.description["en-US"]).not.toBe(""); + expect(image.description["zh-CN"]).not.toBe(""); + } + }); + + test.each(EXPECTED_IMAGES)( + "%s maps both selectors to the exact create/update payload", + async (id, imageName, repositoryName) => { + const fromImage = `fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/${repositoryName}:v0.0.44`; + for (const selector of [id, imageName]) { + expect(resolveSandboxImage(selector)).toMatchObject({ id, imageName, imageUrl: fromImage }); + expect( + await buildTemplateCreateBody({ + image: selector, + name: "test", + cpuCount: 1, + memoryMb: 2048, + async: false, + }), + ).toEqual({ name: "test", cpuCount: 1, memoryMB: 2048, fromImage, imageName }); + expect( + await buildTemplateUpdateBody({ + image: selector, + templateId: "template-test", + async: false, + }), + ).toEqual({ fromImage, imageName }); + } + }, + ); + + test("preset fields override body fields without sending catalog metadata", async () => { + expect( + await buildTemplateUpdateBody({ + image: "browser", + templateId: "template-test", + async: false, + body: JSON.stringify({ fromImage: "body:latest", imageName: "body", description: "kept" }), + }), + ).toEqual({ + fromImage: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44", + imageName: "浏览器", + description: "kept", + }); + }); + + test("explicit custom image fields override the corresponding preset fields", async () => { + expect( + await buildTemplateUpdateBody({ + image: "browser", + fromImage: "custom:v2", + imageName: "custom name", + templateId: "template-test", + async: false, + }), + ).toEqual({ fromImage: "custom:v2", imageName: "custom name" }); + expect( + await buildTemplateUpdateBody({ + image: "browser", + imageName: "renamed", + templateId: "template-test", + async: false, + }), + ).toEqual({ + fromImage: "fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44", + imageName: "renamed", + }); + }); + + test("without --image, display names and custom URLs retain their previous behavior", async () => { + expect( + await buildTemplateUpdateBody({ + imageName: "浏览器", + templateId: "template-test", + async: false, + }), + ).toEqual({ imageName: "浏览器" }); + expect( + await buildTemplateCreateBody({ + name: "test", + cpuCount: 4, + memoryMb: 8192, + async: false, + body: '{"fromImage":"custom:latest","imageName":"custom"}', + }), + ).toEqual({ + name: "test", + cpuCount: 4, + memoryMB: 8192, + fromImage: "custom:latest", + imageName: "custom", + }); + expect( + await buildTemplateCreateBody({ + name: "test", + cpuCount: 1, + memoryMb: 2048, + async: false, + }), + ).not.toHaveProperty("fromImage"); + expect( + await buildTemplateUpdateBody({ + description: "only description", + templateId: "template-test", + async: false, + }), + ).toEqual({ description: "only description" }); + }); + + test("rejects unknown presets locally", () => { + expect(() => resolveSandboxImage("unknown")).toThrowError( + expect.objectContaining({ exitCode: ExitCode.USAGE }), + ); + }); +}); diff --git a/skills/bailian-sandbox/SKILL.md b/skills/bailian-sandbox/SKILL.md index a2489e2..0db8950 100644 --- a/skills/bailian-sandbox/SKILL.md +++ b/skills/bailian-sandbox/SKILL.md @@ -6,7 +6,7 @@ metadata: bins: ["bl"] description: >- 阿里云百炼 Sandbox 沙箱实例与模版生命周期管理入口:用户要创建、查询、连接、暂停、恢复或释放百炼沙箱, - 或创建、更新、查询、删除沙箱模版、查看模版构建状态时,使用 `bl sandbox`。 + 或查看内置基础镜像、创建、更新、查询、删除沙箱模版、查看模版构建状态时,使用 `bl sandbox`。 仅覆盖百炼 Sandbox 管控面;不用于宿主执行沙箱设置、E2B 官方云资源或沙箱内命令执行与文件传输。 agents.yaml 托管 Agent / Session / Environment 管理交给 bailian-managed-agent。 官方安装:`bl skill init`(与共享协议 bailian-protocol 同装)。 @@ -25,19 +25,22 @@ Before running `bl`, read the shared [bailian-protocol](../bailian-protocol/SKIL ## Choose the operation -| User intent | Command family | -| ------------------------------------- | -------------------------------------------------------- | -| Inspect or create instances | `bl sandbox list` / `get` / `create` | -| Connect, pause, or resume an instance | `bl sandbox connect` / `pause` / `resume` | -| Release an instance | `bl sandbox delete` | -| Inspect or build templates | `bl sandbox template list` / `get` / `create` / `update` | -| Check a submitted template build | `bl sandbox template build-status` | -| Delete a template | `bl sandbox template delete` | +| User intent | Command family | +| ------------------------------------- | --------------------------------------------------------- | +| Discover built-in base image presets | `bl sandbox official-images` (offline, no authentication) | +| Inspect or create instances | `bl sandbox list` / `get` / `create` | +| Connect, pause, or resume an instance | `bl sandbox connect` / `pause` / `resume` | +| Release an instance | `bl sandbox delete` | +| Inspect or build templates | `bl sandbox template list` / `get` / `create` / `update` | +| Check a submitted template build | `bl sandbox template build-status` | +| Delete a template | `bl sandbox template delete` | Read [reference/index.md](reference/index.md) and the relevant section of [reference/sandbox.md](reference/sandbox.md) for exact flags, usage, and examples, or run the matching command with `--help`. Do not guess flags. To save the origin in an isolated Profile, use `bl auth login --config sandbox --api-key --base-url `. For a one-command override, use `bl sandbox list --base-url `. Custom gateways also apply to template build-status polling. +For built-in template images, discover the preset ID or Chinese name through `sandbox official-images`, then pass it to template create/update with `--image`. This fills both `fromImage` and `imageName`; `--image-name` alone remains a display name, not an image selector. Presets override the body's image fields; explicit `--from-image` / `--image-name` override the corresponding preset fields. Presets are pinned cn-beijing image URLs, not a live catalog or an availability guarantee for other environments. Omitting `--image` does not change existing defaults or update a template's image implicitly. See the generated reference for the catalog and exact flags. + ## Operational boundaries - Mutating commands act on remote resources. Only perform the requested operation and scope; read-only discovery does not authorize creating, pausing, resuming, or deleting resources. diff --git a/skills/bailian-sandbox/reference/index.md b/skills/bailian-sandbox/reference/index.md index 41bfaeb..7b7cd66 100644 --- a/skills/bailian-sandbox/reference/index.md +++ b/skills/bailian-sandbox/reference/index.md @@ -16,6 +16,7 @@ Use this index for the skill-scoped quick index and global flags. | `bl sandbox delete` | API Key | Release a Sandbox instance | [sandbox.md](sandbox.md) | | `bl sandbox get` | API Key | Get Sandbox instance details | [sandbox.md](sandbox.md) | | `bl sandbox list` | API Key | List Sandbox instances | [sandbox.md](sandbox.md) | +| `bl sandbox official-images` | No Auth | List the built-in Sandbox base images (offline) | [sandbox.md](sandbox.md) | | `bl sandbox pause` | API Key | Pause a Sandbox instance | [sandbox.md](sandbox.md) | | `bl sandbox resume` | API Key | Resume a Sandbox instance and return connection information | [sandbox.md](sandbox.md) | | `bl sandbox template build-status` | API Key | Get Sandbox template build status | [sandbox.md](sandbox.md) | @@ -27,9 +28,9 @@ Use this index for the skill-scoped quick index and global flags. ## By group -| Group | Commands | Reference | -| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -| `sandbox` | `connect`, `create`, `delete`, `get`, `list`, `pause`, `resume`, `template build-status`, `template create`, `template delete`, `template get`, `template list`, `template update` | [sandbox.md](sandbox.md) | +| Group | Commands | Reference | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `sandbox` | `connect`, `create`, `delete`, `get`, `list`, `official-images`, `pause`, `resume`, `template build-status`, `template create`, `template delete`, `template get`, `template list`, `template update` | [sandbox.md](sandbox.md) | ## Global flags diff --git a/skills/bailian-sandbox/reference/sandbox.md b/skills/bailian-sandbox/reference/sandbox.md index 953e500..6f5503f 100644 --- a/skills/bailian-sandbox/reference/sandbox.md +++ b/skills/bailian-sandbox/reference/sandbox.md @@ -14,6 +14,7 @@ Index: [index.md](index.md) | `bl sandbox delete` | API Key | Release a Sandbox instance | | `bl sandbox get` | API Key | Get Sandbox instance details | | `bl sandbox list` | API Key | List Sandbox instances | +| `bl sandbox official-images` | No Auth | List the built-in Sandbox base images (offline) | | `bl sandbox pause` | API Key | Pause a Sandbox instance | | `bl sandbox resume` | API Key | Resume a Sandbox instance and return connection information | | `bl sandbox template build-status` | API Key | Get Sandbox template build status | @@ -241,6 +242,40 @@ bl sandbox list --state running --limit 20 bl sandbox list --template-id tpl-xxx --output json ``` +### `bl sandbox official-images` + +| Field | Value | +| ------------------ | ----------------------------------------------- | +| **Name** | `sandbox official-images` | +| **Description** | List the built-in Sandbox base images (offline) | +| **Authentication** | No Auth | +| **Usage** | `bl sandbox official-images` | + +#### Flags + +_No command-specific flags._ + +#### Notes + +- Use a preset ID or Chinese name with template create/update --image. These are pinned cn-beijing images; other environments may differ. Use --from-image for a custom image. +- code-interpreter (代码解释器): Python / Node.js runtimes with common data-processing libraries. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/code-interpreter-v1:v0.0.44 +- browser (浏览器): Chromium and a visual desktop for clicking, filling forms, and screenshots. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44 +- all-in-one (全能型): Code execution and browser capabilities together. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/all-in-one:v0.0.44 + +#### Examples + +```bash +bl sandbox official-images +``` + +```bash +bl sandbox official-images --output json +``` + +```bash +bl sandbox official-images --quiet +``` + ### `bl sandbox pause` | Field | Value | @@ -364,27 +399,28 @@ bl sandbox template build-status --template-id tpl-xxx --build-id build-xxx --ou #### Flags -| Flag | Type | Required | Description | -| ------------------------------ | ------ | -------- | ---------------------------------------------------------------------------------- | -| `--workspace-id ` | string | no | Workspace ID for the default Sandbox endpoint; optional with a configured base URL | -| `--body ` | string | no | JSON request body, inline or loaded from an @file path; explicit flags override it | -| `--name ` | string | no | Template name | -| `--cpu-count ` | number | no | vCPU count | -| `--memory-mb ` | number | no | Memory in MB | -| `--from-image ` | string | no | Base image identifier | -| `--image-name ` | string | no | Base image display name | -| `--env ` | array | no | Template environment variable; repeat for multiple values | -| `--allow-out
` | array | no | Outbound allow-list entry; repeat for multiple values | -| `--deny-out
` | array | no | Outbound deny-list entry; repeat for multiple values | -| `--auto-pause-time ` | number | no | Automatically pause after 300-604800 seconds | -| `--max-running-time ` | number | no | Maximum running lifetime in seconds (300-604800) | -| `--description ` | string | no | Template description | -| `--tag ` | array | no | E2B tag; repeat for multiple values | -| `--alias ` | string | no | E2B template alias | -| `--async` | switch | no | Return the submitted templateID/buildID immediately without polling | -| `--poll-interval ` | number | no | Template build polling interval (default: 5 seconds) | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| ----------------------------------------------------------------------------- | ------ | -------- | ---------------------------------------------------------------------------------- | +| `--workspace-id ` | string | no | Workspace ID for the default Sandbox endpoint; optional with a configured base URL | +| `--body ` | string | no | JSON request body, inline or loaded from an @file path; explicit flags override it | +| `--image ` | string | no | Built-in image ID or Chinese name; fills fromImage and imageName | +| `--name ` | string | no | Template name | +| `--cpu-count ` | number | no | vCPU count | +| `--memory-mb ` | number | no | Memory in MB | +| `--from-image ` | string | no | Base image identifier | +| `--image-name ` | string | no | Base image display name | +| `--env ` | array | no | Template environment variable; repeat for multiple values | +| `--allow-out
` | array | no | Outbound allow-list entry; repeat for multiple values | +| `--deny-out
` | array | no | Outbound deny-list entry; repeat for multiple values | +| `--auto-pause-time ` | number | no | Automatically pause after 300-604800 seconds | +| `--max-running-time ` | number | no | Maximum running lifetime in seconds (300-604800) | +| `--description ` | string | no | Template description | +| `--tag ` | array | no | E2B tag; repeat for multiple values | +| `--alias ` | string | no | E2B template alias | +| `--async` | switch | no | Return the submitted templateID/buildID immediately without polling | +| `--poll-interval ` | number | no | Template build polling interval (default: 5 seconds) | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Notes @@ -393,11 +429,19 @@ bl sandbox template build-status --template-id tpl-xxx --build-id build-xxx --ou - Without a configured base URL, workspace is required: --workspace-id > BAILIAN_WORKSPACE_ID > config workspace_id. - Sandbox is currently available in cn-beijing only and requires prior SLR authorization. - Global --timeout limits HTTP requests and total template-build polling; --instance-timeout maps to the Sandbox API lifetime field. +- code-interpreter (代码解释器): Python / Node.js runtimes with common data-processing libraries. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/code-interpreter-v1:v0.0.44 +- browser (浏览器): Chromium and a visual desktop for clicking, filling forms, and screenshots. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44 +- all-in-one (全能型): Code execution and browser capabilities together. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/all-in-one:v0.0.44 +- --image overrides body fromImage/imageName; explicit --from-image/--image-name override the corresponding preset fields. Without --image, image behavior is unchanged. - File mounts and other complete nested structures can be supplied through --body. - By default the command waits for build status ready; --async returns the submitted build immediately. #### Examples +```bash +bl sandbox template create --name browser --image browser --cpu-count 1 --memory-mb 2048 +``` + ```bash bl sandbox template create --name python --cpu-count 1 --memory-mb 2048 ``` @@ -538,26 +582,27 @@ bl sandbox template list --limit 100 --output json #### Flags -| Flag | Type | Required | Description | -| ------------------------------ | ------ | -------- | ---------------------------------------------------------------------------------- | -| `--workspace-id ` | string | no | Workspace ID for the default Sandbox endpoint; optional with a configured base URL | -| `--template-id ` | string | yes | Sandbox template ID | -| `--body ` | string | no | JSON request body, inline or loaded from an @file path; explicit flags override it | -| `--name ` | string | no | Template name | -| `--cpu-count ` | number | no | vCPU count | -| `--memory-mb ` | number | no | Memory in MB | -| `--from-image ` | string | no | Base image identifier | -| `--image-name ` | string | no | Base image display name | -| `--env ` | array | no | Template environment variable; repeat for multiple values | -| `--allow-out
` | array | no | Outbound allow-list entry; repeat for multiple values | -| `--deny-out
` | array | no | Outbound deny-list entry; repeat for multiple values | -| `--auto-pause-time ` | number | no | Automatically pause after 300-604800 seconds | -| `--max-running-time ` | number | no | Maximum running lifetime in seconds (300-604800) | -| `--description ` | string | no | Template description | -| `--async` | switch | no | Return the submitted templateID/buildID immediately without polling | -| `--poll-interval ` | number | no | Template build polling interval (default: 5 seconds) | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| ----------------------------------------------------------------------------- | ------ | -------- | ---------------------------------------------------------------------------------- | +| `--workspace-id ` | string | no | Workspace ID for the default Sandbox endpoint; optional with a configured base URL | +| `--template-id ` | string | yes | Sandbox template ID | +| `--body ` | string | no | JSON request body, inline or loaded from an @file path; explicit flags override it | +| `--image ` | string | no | Built-in image ID or Chinese name; fills fromImage and imageName | +| `--name ` | string | no | Template name | +| `--cpu-count ` | number | no | vCPU count | +| `--memory-mb ` | number | no | Memory in MB | +| `--from-image ` | string | no | Base image identifier | +| `--image-name ` | string | no | Base image display name | +| `--env ` | array | no | Template environment variable; repeat for multiple values | +| `--allow-out
` | array | no | Outbound allow-list entry; repeat for multiple values | +| `--deny-out
` | array | no | Outbound deny-list entry; repeat for multiple values | +| `--auto-pause-time ` | number | no | Automatically pause after 300-604800 seconds | +| `--max-running-time ` | number | no | Maximum running lifetime in seconds (300-604800) | +| `--description ` | string | no | Template description | +| `--async` | switch | no | Return the submitted templateID/buildID immediately without polling | +| `--poll-interval ` | number | no | Template build polling interval (default: 5 seconds) | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Notes @@ -566,11 +611,19 @@ bl sandbox template list --limit 100 --output json - Without a configured base URL, workspace is required: --workspace-id > BAILIAN_WORKSPACE_ID > config workspace_id. - Sandbox is currently available in cn-beijing only and requires prior SLR authorization. - Global --timeout limits HTTP requests and total template-build polling; --instance-timeout maps to the Sandbox API lifetime field. +- code-interpreter (代码解释器): Python / Node.js runtimes with common data-processing libraries. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/code-interpreter-v1:v0.0.44 +- browser (浏览器): Chromium and a visual desktop for clicking, filling forms, and screenshots. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44 +- all-in-one (全能型): Code execution and browser capabilities together. fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/all-in-one:v0.0.44 +- --image overrides body fromImage/imageName; explicit --from-image/--image-name override the corresponding preset fields. Without --image, image behavior is unchanged. - Supplying envConfig or --env replaces the template's complete environment map. - By default the command waits for build status ready; --async returns the submitted build immediately. #### Examples +```bash +bl sandbox template update --template-id tpl-xxx --image all-in-one +``` + ```bash bl sandbox template update --template-id tpl-xxx --cpu-count 4 --memory-mb 8192 ```