Skip to content

Conversation

@OhYee
Copy link
Member

@OhYee OhYee commented Feb 2, 2026

… error logging

This commit introduces a new AIOToolSet class that provides comprehensive browser automation capabilities through Playwright integration. The new toolset supports various browser operations including navigation, interaction, page info, advanced JavaScript evaluation, tab management, and file/code execution. It also includes enhanced error logging for Playwright installation issues and improved type safety across the sandbox integration.

The changes also remove the templateType parameter from the sandbox function in mastra integration, update the version check warning to reflect Python SDK, adjust test cases accordingly, and add playwright to the build externals.

build: add playwright to externals in tsup config

feat(builtin): 添加具有 Playwright 集成的 AIOToolSet 并增强错误日志记录

此提交引入了一个新的 AIOToolSet 类,通过 Playwright 集成为浏览器自动化提供全面的功能。新工具集支持各种浏览器操作,包括导航、交互、页面信息、高级 JavaScript 评估、标签页管理和文件/代码执行。它还包括对 Playwright 安装问题的增强错误日志记录,以及在整个沙箱集成中改进的类型安全性。

更改还从 mastra 集成中的 sandbox 函数中移除了 templateType 参数,更新版本检查警告以反映 Python SDK,相应调整测试用例,并在构建外部依赖中添加 playwright。

build: 在 tsup 配置中将 playwright 添加到外部依赖
Signed-off-by: OhYee oyohyee@oyohyee.com

Change-Id: I9485e0df19ea33f96792644eb38e2c16af9a31b4

Thank you for creating a pull request to contribute to Serverless Devs agentrun-sdk-python code! Before you open the request please answer the following questions to help it be more easily integrated. Please check the boxes "[ ]" with "[x]" when done too.
Please select one of the PR types below to complete


Fix bugs

Bug detail

The specific manifestation of the bug or the associated issue.

Pull request tasks

  • Add test cases for the changes
  • Passed the CI test

Update docs

Reason for update

Why do you need to update your documentation?

Pull request tasks

  • Update Chinese documentation
  • Update English documentation

Add contributor

Contributed content

  • Code
  • Document

Content detail

if content_type == 'code' || content_type == 'document':
    please tell us `PR url`,like: https://github.com/Serverless-Devs/agentrun-sdk-python/pull/1
else:
    please describe your contribution in detail

Others

Reason for update

Why do you need to update your documentation?

… error logging

This commit introduces a new AIOToolSet class that provides comprehensive browser automation capabilities through Playwright integration. The new toolset supports various browser operations including navigation, interaction, page info, advanced JavaScript evaluation, tab management, and file/code execution. It also includes enhanced error logging for Playwright installation issues and improved type safety across the sandbox integration.

The changes also remove the templateType parameter from the sandbox function in mastra integration, update the version check warning to reflect Python SDK, adjust test cases accordingly, and add playwright to the build externals.

build: add playwright to externals in tsup config

feat(builtin): 添加具有 Playwright 集成的 AIOToolSet 并增强错误日志记录

此提交引入了一个新的 AIOToolSet 类,通过 Playwright 集成为浏览器自动化提供全面的功能。新工具集支持各种浏览器操作,包括导航、交互、页面信息、高级 JavaScript 评估、标签页管理和文件/代码执行。它还包括对 Playwright 安装问题的增强错误日志记录,以及在整个沙箱集成中改进的类型安全性。

更改还从 mastra 集成中的 sandbox 函数中移除了 templateType 参数,更新版本检查警告以反映 Python SDK,相应调整测试用例,并在构建外部依赖中添加 playwright。

build: 在 tsup 配置中将 playwright 添加到外部依赖
Signed-off-by: OhYee <oyohyee@oyohyee.com>

Change-Id: I9485e0df19ea33f96792644eb38e2c16af9a31b4
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an AIO (all‑in‑one) sandbox toolset with Playwright-based browser automation, extends sandbox template handling to support AIO templates, updates Mastra integration APIs accordingly, and tweaks the version-check warning and build config.

Changes:

  • Add AIOToolSet that combines browser automation (via Playwright) with code execution, filesystem, and process operations, and route TemplateType.AIO templates through it in sandboxToolset.
  • Simplify Mastra sandbox() integration to infer templateType via sandboxToolset, comment out the codeInterpreter() and browser() convenience wrappers, and adjust tests to stop passing templateType explicitly.
  • Update the version warning string to reference the Python SDK and add Playwright to the tsup externals for correct bundling of the dynamic import.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tsup.config.ts Adds playwright to the bundler externals so dynamic imports of Playwright in the sandbox toolsets don’t get bundled.
tests/unittests/integration/mastra.test.ts Updates Mastra integration tests for the new sandbox() behavior and continues to exercise the (now-removed) codeInterpreter()/browser() helpers.
src/utils/version-check.ts Changes the global version warning string to reference the Python SDK, pip install advice, and Python SDK release URL, and adds ANSI styling.
src/integration/mastra/index.ts Adjusts Mastra sandbox() to no longer take a templateType parameter, delegates to sandboxToolset, and comments out the codeInterpreter() and browser() API helpers.
src/integration/builtin/sandbox.ts Enhances Playwright error logging in BrowserToolSet, introduces AIOToolSet with combined browser/code/file/process tools, and updates sandboxToolset to dispatch to BrowserToolSet, CodeInterpreterToolSet, or AIOToolSet based on template type.
Comments suppressed due to low confidence (4)

tests/unittests/integration/mastra.test.ts:288

  • This test still expects sandbox() to pass templateType: TemplateType.BROWSER into builtin.sandboxToolset, but the implementation no longer sends a templateType field at all. Update the expectation to reflect the new behavior where sandboxToolset determines the template type based on the template metadata.
      expect(builtin.sandboxToolset).toHaveBeenCalledWith('browser-template', {
        templateType: TemplateType.BROWSER,
        sandboxIdleTimeoutSeconds: undefined,
        config: undefined,
      });

tests/unittests/integration/mastra.test.ts:270

  • This expectation still asserts that sandbox() forwards templateType: TemplateType.CODE_INTERPRETER to builtin.sandboxToolset, but sandbox() no longer accepts or passes a templateType parameter and now relies on sandboxToolset to infer it. Please update the expected call shape here to match the new sandbox() implementation (likely only sandboxIdleTimeoutSeconds and config).
      expect(builtin.sandboxToolset).toHaveBeenCalledWith('my-template', {
        templateType: TemplateType.CODE_INTERPRETER,
        sandboxIdleTimeoutSeconds: undefined,
        config: undefined,
      });

tests/unittests/integration/mastra.test.ts:380

  • The codeInterpreter() tests assume that codeInterpreter is still exported from '@/integration/mastra' and that it forces templateType: TemplateType.CODE_INTERPRETER when calling builtin.sandboxToolset, but codeInterpreter() has been commented out and sandbox() no longer accepts templateType. These tests will fail against the new implementation; consider removing them or updating them to target the new sandbox/AIO flow instead.
  describe('codeInterpreter()', () => {
    it('should create CODE_INTERPRETER sandbox tools', async () => {
      const mockSandboxToolSet = {
        tools: jest.fn().mockReturnValue([]),
      };

      (builtin.sandboxToolset as jest.Mock).mockResolvedValue(mockSandboxToolSet);

      await codeInterpreter({
        templateName: 'code-template',
      });

      expect(builtin.sandboxToolset).toHaveBeenCalledWith('code-template', {
        templateType: TemplateType.CODE_INTERPRETER,
        sandboxIdleTimeoutSeconds: undefined,
        config: undefined,
      });
    });

    it('should be shorthand for sandbox()', async () => {
      const mockSandboxToolSet = {
        tools: jest.fn().mockReturnValue([]),
      };

      (builtin.sandboxToolset as jest.Mock).mockResolvedValue(mockSandboxToolSet);

      await codeInterpreter({
        templateName: 'test-template',
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });

      await sandbox({
        templateName: 'test-template',
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });

      // Should call with same parameters
      expect(builtin.sandboxToolset).toHaveBeenCalledTimes(2);
      expect(builtin.sandboxToolset).toHaveBeenNthCalledWith(1, 'test-template', {
        templateType: TemplateType.CODE_INTERPRETER,
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });
      expect(builtin.sandboxToolset).toHaveBeenNthCalledWith(2, 'test-template', {
        templateType: TemplateType.CODE_INTERPRETER,
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });
    });

tests/unittests/integration/mastra.test.ts:433

  • The browser() tests still rely on a browser helper exported from '@/integration/mastra' and expect it to set templateType: TemplateType.BROWSER when invoking builtin.sandboxToolset, but browser() has been commented out and sandbox() no longer propagates templateType. These tests should be removed or rewritten to exercise the new sandbox/AIO entry points so they align with the current public API.
  describe('browser()', () => {
    it('should create BROWSER sandbox tools', async () => {
      const mockSandboxToolSet = {
        tools: jest.fn().mockReturnValue([]),
      };

      (builtin.sandboxToolset as jest.Mock).mockResolvedValue(mockSandboxToolSet);

      await browser({
        templateName: 'browser-template',
      });

      expect(builtin.sandboxToolset).toHaveBeenCalledWith('browser-template', {
        templateType: TemplateType.BROWSER,
        sandboxIdleTimeoutSeconds: undefined,
        config: undefined,
      });
    });

    it('should be shorthand for sandbox()', async () => {
      const mockSandboxToolSet = {
        tools: jest.fn().mockReturnValue([]),
      };

      (builtin.sandboxToolset as jest.Mock).mockResolvedValue(mockSandboxToolSet);

      await browser({
        templateName: 'test-browser',
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });

      await sandbox({
        templateName: 'test-browser',
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });

      // Should call with same parameters
      expect(builtin.sandboxToolset).toHaveBeenCalledTimes(2);
      expect(builtin.sandboxToolset).toHaveBeenNthCalledWith(1, 'test-browser', {
        templateType: TemplateType.BROWSER,
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });
      expect(builtin.sandboxToolset).toHaveBeenNthCalledWith(2, 'test-browser', {
        templateType: TemplateType.BROWSER,
        sandboxIdleTimeoutSeconds: 300,
        config: mockConfig,
      });
    });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1309 to +1312
// Ensure sandbox is running first
const sb = await this.ensureSandbox();
const browserSandbox = sb as BrowserSandbox;

Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In AIOToolSet.ensurePlaywright(), runInSandbox creates a sandbox with TemplateType.AIO, so the underlying instance is an AioSandbox but it is being cast to BrowserSandbox. This bypasses type-safety and makes the intent unclear; please import and use the AioSandbox type (or a dedicated AIO interface) for these casts, and similarly adjust other AIOToolSet methods that cast the sandbox to BrowserSandbox or CodeInterpreterSandbox so the types reflect the actual runtime object.

Copilot uses AI. Check for mistakes.
Comment on lines +2357 to +2358
const client = new SandboxClient();
const template = await client.getTemplate({ name: templateName });
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sandboxToolset() constructs SandboxClient without passing options?.config and calls getTemplate with only the name, so the template lookup ignores the caller-provided Config while the created ToolSet instances do honor it. To keep behavior consistent in multi-account/config scenarios, pass options?.config into the SandboxClient and/or into getTemplate so template resolution uses the same configuration as sandbox creation.

Suggested change
const client = new SandboxClient();
const template = await client.getTemplate({ name: templateName });
const client = new SandboxClient({ config: options?.config });
const template = await client.getTemplate({ name: templateName, config: options?.config });

Copilot uses AI. Check for mistakes.
Comment on lines +250 to +275
// * 创建 Mastra 兼容的浏览器自动化工具
// *
// * Shorthand for sandbox() with BROWSER type.
// *
// * @example
// * ```typescript
// * const tools = await browser({
// * templateName: 'my-browser-template',
// * });
// *
// * const agent = new Agent({
// * tools,
// * model: await model({ name: 'qwen-max' }),
// * });
// * ```
// */
// export async function browser(params: {
// templateName: string;
// sandboxIdleTimeoutSeconds?: number;
// config?: Config;
// }): Promise<ToolsInput> {
// return sandbox({
// ...params,
// templateType: TemplateType.BROWSER,
// });
// }
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commenting out the codeInterpreter() and browser() functions effectively removes them from the public Mastra integration API, while they are still imported and tested elsewhere in this repo. If the intent is to deprecate these helpers, consider keeping them as thin wrappers around sandbox() (or replacing them with new AIO entry points) and marking them deprecated, and in any case align tests and documentation with the updated API surface.

Suggested change
// * 创建 Mastra 兼容的浏览器自动化工具
// *
// * Shorthand for sandbox() with BROWSER type.
// *
// * @example
// * ```typescript
// * const tools = await browser({
// * templateName: 'my-browser-template',
// * });
// *
// * const agent = new Agent({
// * tools,
// * model: await model({ name: 'qwen-max' }),
// * });
// * ```
// */
// export async function browser(params: {
// templateName: string;
// sandboxIdleTimeoutSeconds?: number;
// config?: Config;
// }): Promise<ToolsInput> {
// return sandbox({
// ...params,
// templateType: TemplateType.BROWSER,
// });
// }
/**
* 创建 Mastra 兼容的浏览器自动化工具
*
* Shorthand for sandbox() with BROWSER type.
*
* @example
* ```typescript
* const tools = await browser({
* templateName: 'my-browser-template',
* });
*
* const agent = new Agent({
* tools,
* model: await model({ name: 'qwen-max' }),
* });
* ```
*
* @deprecated Use {@link sandbox} directly with {@link TemplateType.BROWSER} instead.
*/
export async function browser(params: {
templateName: string;
sandboxIdleTimeoutSeconds?: number;
config?: Config;
}): Promise<ToolsInput> {
return sandbox({
...params,
templateType: TemplateType.BROWSER,
});
}

Copilot uses AI. Check for mistakes.
Comment on lines +12 to 21
`当前您正在使用 AgentRun Python SDK 版本 ${VERSION}。早期版本通常包含许多新功能,这些功能\x1b[1;33m 可能引入不兼容的变更 \x1b[0m。为避免潜在问题,我们强烈建议\x1b[1;32m 将依赖锁定为此版本 \x1b[0m。
You are currently using AgentRun Python SDK version ${VERSION}. Early versions often include many new features, which\x1b[1;33m may introduce breaking changes\x1b[0m. To avoid potential issues, we strongly recommend \x1b[1;32mpinning the dependency to this version\x1b[0m.
\x1b[2;3m pip install 'agentrun-sdk==${VERSION}' \x1b[0m

增加\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0m到您的环境变量以关闭此警告。
Add\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0mto your environment variables to disable this warning.

Releases:\x1b[2;3m https://github.com/Serverless-Devs/agentrun-sdk-python/releases\x1b[0m`
);
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version warning string now refers to the "AgentRun Python SDK", uses a pip install command for 'agentrun-sdk', and links to the Python SDK releases, while package.json describes '@agentrun/sdk' as the Node.js SDK and points to the NodeJS repository. Unless this module is only ever embedded in the Python SDK, this mismatch will be confusing for Node users; consider keeping Node-specific installation instructions and release URL here or otherwise clarifying which SDK this message targets.

Suggested change
`当前您正在使用 AgentRun Python SDK 版本 ${VERSION}。早期版本通常包含许多新功能,这些功能\x1b[1;33m 可能引入不兼容的变更 \x1b[0m。为避免潜在问题,我们强烈建议\x1b[1;32m 将依赖锁定为此版本 \x1b[0m。
You are currently using AgentRun Python SDK version ${VERSION}. Early versions often include many new features, which\x1b[1;33m may introduce breaking changes\x1b[0m. To avoid potential issues, we strongly recommend \x1b[1;32mpinning the dependency to this version\x1b[0m.
\x1b[2;3m pip install 'agentrun-sdk==${VERSION}' \x1b[0m
增加\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0m到您的环境变量以关闭此警告。
Add\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0mto your environment variables to disable this warning.
Releases:\x1b[2;3m https://github.com/Serverless-Devs/agentrun-sdk-python/releases\x1b[0m`
);
}
`当前您正在使用 AgentRun Node.js SDK 版本 ${VERSION}。早期版本通常包含许多新功能,这些功能\x1b[1;33m 可能引入不兼容的变更 \x1b[0m。为避免潜在问题,我们强烈建议\x1b[1;32m 将依赖锁定为此版本 \x1b[0m。
You are currently using AgentRun Node.js SDK version ${VERSION}. Early versions often include many new features, which\x1b[1;33m may introduce breaking changes\x1b[0m. To avoid potential issues, we strongly recommend \x1b[1;32mpinning the dependency to this version\x1b[0m.
\x1b[2;3m npm install @agentrun/sdk@${VERSION} \x1b[0m
增加\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0m到您的环境变量以关闭此警告。
Add\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0mto your environment variables to disable this warning.`
);
}
}

Copilot uses AI. Check for mistakes.
\x1b[2;3m pip install 'agentrun-sdk==${VERSION}' \x1b[0m

增加\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0m到您的环境变量以关闭此警告。
Add\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0mto your environment variables to disable this warning.
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the English warning text, there is no space between the ANSI reset sequence after 'DISABLE_BREAKING_CHANGES_WARNING=1' and the word 'to', so it renders as '...=1to your environment variables...'. Add a space after the escape sequence so the sentence reads correctly.

Suggested change
Add\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0mto your environment variables to disable this warning.
Add\x1b[2;3m DISABLE_BREAKING_CHANGES_WARNING=1 \x1b[0m to your environment variables to disable this warning.

Copilot uses AI. Check for mistakes.
…e unused imports

This change modifies the TemplateType from an import to an export in the mastra integration file, and removes unused imports and related test code for codeInterpreter and browser functions.

BREAKING CHANGE: TemplateType is now exported instead of imported, and codeInterpreter/browser functions are removed from tests

---

refactor(integration): 更改TemplateType从导入为导出并移除未使用的导入

此更改将mastra集成文件中的TemplateType从导入改为导出,并删除了codeInterpreter和browser函数的未使用导入和相关测试代码。

重大变更:TemplateType现在是导出而不是导入,且测试中移除了codeInterpreter/browser函数

Change-Id: I8987d7da888f30340d25eedc97db600d3c3496e8
Signed-off-by: OhYee <oyohyee@oyohyee.com>
@OhYee OhYee merged commit 1a6c85a into main Feb 2, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants