From 03f60ce0128d5539c70d937ce9c52979e18988e6 Mon Sep 17 00:00:00 2001 From: A Vertex SDK engineer Date: Thu, 6 Aug 2026 13:07:39 -0700 Subject: [PATCH] feat: Add public Agent Engines and sandbox methods to the Vertex AI GenAI SDK for JavaScript. PiperOrigin-RevId: 960460415 --- src/agentengines.ts | 49 +++++ src/client.ts | 8 + src/sandboxes.ts | 42 ++++ src/sandboxsnapshots.ts | 28 +++ src/sandboxtemplates.ts | 28 +++ .../sandbox_templates_snapshots_e2e_test.ts | 199 +++++++++--------- 6 files changed, 255 insertions(+), 99 deletions(-) diff --git a/src/agentengines.ts b/src/agentengines.ts index d23f57f6..2d326e8b 100644 --- a/src/agentengines.ts +++ b/src/agentengines.ts @@ -23,6 +23,55 @@ export class AgentEngines extends BaseModule { this.sandboxes = new Sandboxes(apiClient); } + /** Creates an agent engine and returns the operation. */ + async create( + params: types.CreateAgentEngineRequestParameters, + ): Promise { + return this.createInternal(params); + } + + /** Deletes the agent engine and returns the operation. */ + async delete( + params: types.DeleteAgentEngineRequestParameters, + ): Promise { + return this.deleteInternal(params); + } + + /** Returns the agent engine with the specified name. */ + async get( + params: types.GetAgentEngineRequestParameters, + ): Promise { + return this.getInternal(params); + } + + /** Lists the agent engines for the given config. */ + async list( + params: types.ListAgentEngineRequestParameters, + ): Promise { + return this.listInternal(params); + } + + /** Returns the agent engine operation with the specified name. */ + async getAgentOperation( + params: types.GetAgentEngineOperationParameters, + ): Promise { + return this.getAgentOperationInternal(params); + } + + /** Queries the agent engine. */ + async query( + params: types.QueryAgentEngineRequestParameters, + ): Promise { + return this.queryInternal(params); + } + + /** Updates the agent engine and returns the operation. */ + async update( + params: types.UpdateAgentEngineRequestParameters, + ): Promise { + return this.updateInternal(params); + } + async createInternal( params: types.CreateAgentEngineRequestParameters, ): Promise { diff --git a/src/client.ts b/src/client.ts index f530da00..70940032 100644 --- a/src/client.ts +++ b/src/client.ts @@ -78,4 +78,12 @@ export class Client { } return this._agentEnginesInternal; } + + /** + * Provides access to the Agent Engines API, including its sandboxes, + * sandbox templates, and sandbox snapshots submodules. + */ + public get agentEngines(): AgentEngines { + return this._agentEnginesInternal; + } } diff --git a/src/sandboxes.ts b/src/sandboxes.ts index 9114124e..ecb186a6 100644 --- a/src/sandboxes.ts +++ b/src/sandboxes.ts @@ -23,6 +23,48 @@ export class Sandboxes extends BaseModule { this.snapshots = new SandboxSnapshots(apiClient); } + /** Creates a sandbox environment and returns the operation. */ + async create( + params: types.CreateAgentEngineSandboxRequestParameters, + ): Promise { + return this.createInternal(params); + } + + /** Deletes the sandbox environment and returns the operation. */ + async delete( + params: types.DeleteAgentEngineSandboxRequestParameters, + ): Promise { + return this.deleteInternal(params); + } + + /** Executes code in the sandbox environment. */ + async executeCode( + params: types.ExecuteCodeAgentEngineSandboxRequestParameters, + ): Promise { + return this.executeCodeInternal(params); + } + + /** Returns the sandbox environment with the specified name. */ + async get( + params: types.GetAgentEngineSandboxRequestParameters, + ): Promise { + return this.getInternal(params); + } + + /** Lists the sandbox environments for the given name. */ + async list( + params: types.ListAgentEngineSandboxesRequestParameters, + ): Promise { + return this.listInternal(params); + } + + /** Returns the sandbox operation with the specified name. */ + async getSandboxOperation( + params: types.GetAgentEngineSandboxOperationParameters, + ): Promise { + return this.getSandboxOperationInternal(params); + } + async createInternal( params: types.CreateAgentEngineSandboxRequestParameters, ): Promise { diff --git a/src/sandboxsnapshots.ts b/src/sandboxsnapshots.ts index bfc069eb..8a3c183c 100644 --- a/src/sandboxsnapshots.ts +++ b/src/sandboxsnapshots.ts @@ -16,6 +16,34 @@ export class SandboxSnapshots extends BaseModule { super(); } + /** Creates a snapshot of a running sandbox and returns the operation. */ + async create( + params: types.CreateSandboxEnvironmentSnapshotRequestParameters, + ): Promise { + return this.createInternal(params); + } + + /** Returns the sandbox environment snapshot with the specified name. */ + async get( + params: types.GetSandboxEnvironmentSnapshotRequestParameters, + ): Promise { + return this.getInternal(params); + } + + /** Lists the sandbox environment snapshots for the given name. */ + async list( + params: types.ListSandboxEnvironmentSnapshotsRequestParameters, + ): Promise { + return this.listInternal(params); + } + + /** Deletes the sandbox environment snapshot and returns the operation. */ + async delete( + params: types.DeleteSandboxEnvironmentSnapshotRequestParameters, + ): Promise { + return this.deleteInternal(params); + } + async createInternal( params: types.CreateSandboxEnvironmentSnapshotRequestParameters, ): Promise { diff --git a/src/sandboxtemplates.ts b/src/sandboxtemplates.ts index 0a1c275f..e18ae8db 100644 --- a/src/sandboxtemplates.ts +++ b/src/sandboxtemplates.ts @@ -16,6 +16,34 @@ export class SandboxTemplates extends BaseModule { super(); } + /** Creates a sandbox environment template and returns the operation. */ + async create( + params: types.CreateSandboxEnvironmentTemplateRequestParameters, + ): Promise { + return this.createInternal(params); + } + + /** Returns the sandbox environment template with the specified name. */ + async get( + params: types.GetSandboxEnvironmentTemplateRequestParameters, + ): Promise { + return this.getInternal(params); + } + + /** Lists the sandbox environment templates for the given name. */ + async list( + params: types.ListSandboxEnvironmentTemplatesRequestParameters, + ): Promise { + return this.listInternal(params); + } + + /** Deletes the sandbox environment template and returns the operation. */ + async delete( + params: types.DeleteSandboxEnvironmentTemplateRequestParameters, + ): Promise { + return this.deleteInternal(params); + } + async createInternal( params: types.CreateSandboxEnvironmentTemplateRequestParameters, ): Promise { diff --git a/system_test/sandbox_templates_snapshots_e2e_test.ts b/system_test/sandbox_templates_snapshots_e2e_test.ts index 852cb2d9..7421940b 100644 --- a/system_test/sandbox_templates_snapshots_e2e_test.ts +++ b/system_test/sandbox_templates_snapshots_e2e_test.ts @@ -22,9 +22,8 @@ const sandboxE2eDescribe = /** Polls an Agent Engine operation until it completes. */ async function pollAgentOperation(client: Client, operationName: string) { for (let pollCount = 0; pollCount < 120; pollCount++) { - const status = await client.agentEnginesInternal.getAgentOperationInternal({ - operationName, - }); + const status = + await client.agentEngines.getAgentOperation({operationName}); if (status.done) { return status; } @@ -37,9 +36,7 @@ async function pollAgentOperation(client: Client, operationName: string) { async function pollSandboxOperation(client: Client, operationName: string) { for (let pollCount = 0; pollCount < 120; pollCount++) { const status = - await client.agentEnginesInternal.sandboxes.getSandboxOperationInternal({ - operationName, - }); + await client.agentEngines.sandboxes.getSandboxOperation({operationName}); if (status.done) { return status; } @@ -52,7 +49,7 @@ async function pollSandboxOperation(client: Client, operationName: string) { async function pollTemplateOperation(client: Client, operationName: string) { for (let pollCount = 0; pollCount < 120; pollCount++) { const status = - await client.agentEnginesInternal.sandboxes.templates + await client.agentEngines.sandboxes.templates .getSandboxEnvironmentTemplateOperation({operationName}); if (status.done) { return status; @@ -66,7 +63,7 @@ async function pollTemplateOperation(client: Client, operationName: string) { async function pollSnapshotOperation(client: Client, operationName: string) { for (let pollCount = 0; pollCount < 120; pollCount++) { const status = - await client.agentEnginesInternal.sandboxes.snapshots + await client.agentEngines.sandboxes.snapshots .getSandboxSnapshotOperation({operationName}); if (status.done) { return status; @@ -76,6 +73,17 @@ async function pollSnapshotOperation(client: Client, operationName: string) { throw new Error(`Operation ${operationName} did not complete within the timeout.`); } +/** Returns the config for a computer-use sandbox template with internet access. */ +function computerUseTemplateConfig(): types.CreateSandboxEnvironmentTemplateConfig { + return { + defaultContainerEnvironment: { + defaultContainerCategory: + types.DefaultContainerCategory.DEFAULT_CONTAINER_CATEGORY_COMPUTER_USE, + }, + egressControlConfig: {internetAccess: true}, + }; +} + sandboxE2eDescribe('agentEngineSandboxTemplatesAndSnapshots', () => { let client: Client; let agentEngineName: string|undefined; @@ -88,7 +96,7 @@ sandboxE2eDescribe('agentEngineSandboxTemplatesAndSnapshots', () => { }); // Create a temporary Agent Engine to own the sandboxes. - const createOp = await client.agentEnginesInternal.createInternal({ + const createOp = await client.agentEngines.create({ config: { displayName: 'sandbox-templates-snapshots-sample', labels: {'test-label': 'test-value'}, @@ -101,7 +109,7 @@ sandboxE2eDescribe('agentEngineSandboxTemplatesAndSnapshots', () => { afterAll(async () => { if (agentEngineName) { try { - await client.agentEnginesInternal.deleteInternal({name: agentEngineName}); + await client.agentEngines.delete({name: agentEngineName}); } catch (e) { console.error('Failed to delete Agent Engine during cleanup:', e); } @@ -110,122 +118,115 @@ sandboxE2eDescribe('agentEngineSandboxTemplatesAndSnapshots', () => { it('should create, get, list, and delete a sandbox template', async () => { // 1. Create a sandbox environment template. - const createOp = - await client.agentEnginesInternal.sandboxes.templates.createInternal({ - name: agentEngineName!, - displayName: 'Example Sandbox Template', - config: { - defaultContainerEnvironment: { - defaultContainerCategory: types.DefaultContainerCategory - .DEFAULT_CONTAINER_CATEGORY_COMPUTER_USE, - }, - egressControlConfig: {internetAccess: true}, - }, - }); + const createOp = await client.agentEngines.sandboxes.templates.create({ + name: agentEngineName!, + displayName: 'Example Sandbox Template', + config: computerUseTemplateConfig(), + }); const status = await pollTemplateOperation(client, createOp.name!); const templateName = status.response?.name; expect(templateName).toBeDefined(); // 2. Get the template. - const template = - await client.agentEnginesInternal.sandboxes.templates.getInternal({ - name: templateName!, - }); + const template = await client.agentEngines.sandboxes.templates.get({ + name: templateName!, + }); expect(template.name).toEqual(templateName); // 3. List templates. - const listResponse = - await client.agentEnginesInternal.sandboxes.templates.listInternal({ - name: agentEngineName!, - }); + const listResponse = await client.agentEngines.sandboxes.templates.list({ + name: agentEngineName!, + }); expect(listResponse.sandboxEnvironmentTemplates).toBeDefined(); // 4. Delete the template. - const deleteOp = - await client.agentEnginesInternal.sandboxes.templates.deleteInternal({ - name: templateName!, - }); + const deleteOp = await client.agentEngines.sandboxes.templates.delete({ + name: templateName!, + }); expect(deleteOp.name).toBeDefined(); }); - it('should create, get, list, and delete a sandbox snapshot', async () => { - // Snapshots capture the state of a running sandbox, and only - // template-based (e.g. computer-use) sandboxes are snapshottable. Create a - // computer-use template, then a sandbox from it, before snapshotting. - const templateCreateOp = - await client.agentEnginesInternal.sandboxes.templates.createInternal({ - name: agentEngineName!, - displayName: 'Snapshot Source Template', - config: { - defaultContainerEnvironment: { - defaultContainerCategory: types.DefaultContainerCategory - .DEFAULT_CONTAINER_CATEGORY_COMPUTER_USE, - }, - egressControlConfig: {internetAccess: true}, - }, - }); + it('should create, snapshot, restore, and delete a template-based sandbox', async () => { + // Snapshots capture the state of a running sandbox, and only template-based + // (e.g. computer-use) sandboxes are snapshottable. Create a computer-use + // template, then a sandbox from it, before snapshotting. + const templateCreateOp = await client.agentEngines.sandboxes.templates.create({ + name: agentEngineName!, + displayName: 'Snapshot Source Template', + config: computerUseTemplateConfig(), + }); const templateStatus = await pollTemplateOperation(client, templateCreateOp.name!); const templateName = templateStatus.response?.name; expect(templateName).toBeDefined(); + let sandboxName: string|undefined; + let restoredSandboxName: string|undefined; try { // Create a sandbox from the template so it has a snapshottable state. - const sandboxCreateOp = - await client.agentEnginesInternal.sandboxes.createInternal({ - name: agentEngineName!, - config: {sandboxEnvironmentTemplate: templateName!}, - }); + const sandboxCreateOp = await client.agentEngines.sandboxes.create({ + name: agentEngineName!, + config: { + displayName: 'Snapshot Source Sandbox', + sandboxEnvironmentTemplate: templateName!, + }, + }); const sandboxStatus = await pollSandboxOperation(client, sandboxCreateOp.name!); - const sandboxName = sandboxStatus.response?.name; + sandboxName = sandboxStatus.response?.name; expect(sandboxName).toBeDefined(); - try { - // 1. Create a snapshot of the sandbox. - const createOp = - await client.agentEnginesInternal.sandboxes.snapshots.createInternal( - { - sourceSandboxEnvironmentName: sandboxName!, - config: { - displayName: 'Example Sandbox Snapshot', - ttl: '3600s', - }, - }); - const status = await pollSnapshotOperation(client, createOp.name!); - const snapshotName = status.response?.name; - expect(snapshotName).toBeDefined(); - - // 2. Get the snapshot. - const snapshot = - await client.agentEnginesInternal.sandboxes.snapshots.getInternal({ - name: snapshotName!, - }); - expect(snapshot.name).toEqual(snapshotName); - - // 3. List snapshots. - const listResponse = - await client.agentEnginesInternal.sandboxes.snapshots.listInternal({ - name: agentEngineName!, - }); - expect(listResponse.sandboxEnvironmentSnapshots).toBeDefined(); - - // 4. Delete the snapshot. - const deleteOp = - await client.agentEnginesInternal.sandboxes.snapshots.deleteInternal( - { - name: snapshotName!, - }); - expect(deleteOp.name).toBeDefined(); - } finally { - // Clean up the source sandbox. - await client.agentEnginesInternal.sandboxes.deleteInternal({ - name: sandboxName!, - }); - } + // 1. Create a snapshot of the sandbox. + const createOp = await client.agentEngines.sandboxes.snapshots.create({ + sourceSandboxEnvironmentName: sandboxName!, + config: { + displayName: 'Example Sandbox Snapshot', + ttl: '3600s', + }, + }); + const status = await pollSnapshotOperation(client, createOp.name!); + const snapshotName = status.response?.name; + expect(snapshotName).toBeDefined(); + + // 2. Get the snapshot. + const snapshot = await client.agentEngines.sandboxes.snapshots.get({ + name: snapshotName!, + }); + expect(snapshot.name).toEqual(snapshotName); + + // 3. List snapshots. + const listResponse = await client.agentEngines.sandboxes.snapshots.list({ + name: agentEngineName!, + }); + expect(listResponse.sandboxEnvironmentSnapshots).toBeDefined(); + + // 4. Restore a new sandbox from the snapshot. + const restoreOp = await client.agentEngines.sandboxes.create({ + name: agentEngineName!, + config: { + displayName: 'Restored Sandbox', + sandboxEnvironmentSnapshot: snapshotName!, + }, + }); + const restoreStatus = await pollSandboxOperation(client, restoreOp.name!); + restoredSandboxName = restoreStatus.response?.name; + expect(restoredSandboxName).toBeDefined(); + + // 5. Delete the snapshot. + const deleteOp = await client.agentEngines.sandboxes.snapshots.delete({ + name: snapshotName!, + }); + expect(deleteOp.name).toBeDefined(); } finally { + // Clean up the restored sandbox and the source sandbox. + if (restoredSandboxName) { + await client.agentEngines.sandboxes.delete({name: restoredSandboxName}); + } + if (sandboxName) { + await client.agentEngines.sandboxes.delete({name: sandboxName}); + } // Clean up the source template. - await client.agentEnginesInternal.sandboxes.templates.deleteInternal({ + await client.agentEngines.sandboxes.templates.delete({ name: templateName!, }); }