API 参考

在以下文档中,你可能会看到带有 agent. 前缀的函数调用。如果你在 Playwright 中,这些调用是不带 agent. 前缀的,如 async ({ ai, aiQuery }) => { /* ... */}。这只是解构语法的区别。

构造器

Midscene 中每个 Agent 都有自己的构造函数。

这些 Agent 有一些相同的构造参数:

  • generateReport: boolean: 如果为 true,则生成报告文件。默认值为 true。
  • autoPrintReportMsg: boolean: 如果为 true,则打印报告消息。默认值为 true。
  • cacheId: string | undefined: 如果配置,则使用此 cacheId 保存或匹配缓存。默认值为 undefined,也就是不启用缓存。
  • actionContext: string: 调用 agent.aiAction() 时,发送给 AI 模型的背景知识,比如 '有 cookie 对话框时先关闭它',默认值为空。

在 puppeteer 中,还有一个额外的参数:

  • forceSameTabNavigation: boolean: 如果为 true,则限制页面在当前 tab 打开。默认值为 true。

交互方法

这些是 Midscene 中各类 Agent 的主要 API。

自动规划 v.s. 即时操作

在 Midscene 中,你可以选择使用自动规划(Auto Planning)或即时操作(Instant Action)。

  • agent.ai() 是自动规划(Auto Planning):Midscene 会自动规划操作步骤并执行。它更智能,更像流行的 AI Agent 风格,但可能较慢,且效果依赖于 AI 模型的质量。
  • agent.aiTap(), agent.aiHover(), agent.aiInput(), agent.aiKeyboardPress(), agent.aiScroll() 是即时操作(Instant Action):Midscene 会直接执行指定的操作,而 AI 模型只负责底层任务,如定位元素等。这种接口形式更快、更可靠。当你完全确定自己想要执行的操作时,推荐使用这种接口形式。

agent.aiAction().ai()

这个方法允许你通过自然语言描述一系列 UI 操作步骤。Midscene 会自动规划这些步骤并执行。

  • 类型
function aiAction(prompt: string): Promise<void>;
function ai(prompt: string): Promise<void>; // 简写形式
  • 参数:

    • prompt: string - 用自然语言描述的操作内容
  • 返回值:

    • 返回一个 Promise。当所有步骤执行完成时解析为 void;若执行失败,则抛出错误。
  • 示例:

// 基本用法
await agent.aiAction('在搜索框中输入 "JavaScript",然后点击搜索按钮');

// 使用 .ai 简写形式
await agent.ai('点击页面顶部的登录按钮,然后在用户名输入框中输入 "test@example.com"');

// 使用 ui-tars 模型时,可以使用更高维度的提示词
await agent.aiAction('发布一条微博,内容为 "Hello World"');
TIP

在实际运行时,Midscene 会将用户指令规划(Planning)成多个步骤,然后逐步执行。如果 Midscene 认为无法执行,将抛出一个错误。

为了获得最佳效果,请尽可能提供清晰、详细的步骤描述。具体可以参考这篇文档:编写提示词的技巧

关联文档:

agent.aiTap()

点击某个元素。

  • 类型
function aiTap(locate: string, options?: Object): Promise<void>;
  • 参数:

    • locate: string - 用自然语言描述的元素定位。
    • options?: Object - 可选,一个配置对象,包含:
      • deepThink?: boolean - 是否开启深度思考。如果为 true,Midscene 会调用 AI 模型两次以精确定位元素。
  • 返回值:

    • Promise<void>
  • 示例:

await agent.aiTap('页面顶部的登录按钮');

// 使用 deepThink 功能精确定位元素
await agent.aiTap('页面顶部的登录按钮', { deepThink: true });

agent.aiHover()

鼠标悬停某个元素上。

  • 类型
function aiHover(locate: string, options?: Object): Promise<void>;
  • 参数:

    • locate: string - 用自然语言描述的元素定位。
    • options?: Object - 可选,一个配置对象,包含:
      • deepThink?: boolean - 是否开启深度思考。如果为 true,Midscene 会调用 AI 模型两次以精确定位元素。
  • 返回值:

    • Promise<void>
  • 示例:

await agent.aiHover('页面顶部的登录按钮');

agent.aiInput()

在某个元素中输入文本。

  • 类型
function aiInput(text: string, locate: string, options?: Object): Promise<void>;
  • 参数:

    • text: string - 要输入的文本内容。使用空字符串可以清空输入框。
    • locate: string - 用自然语言描述的元素定位。
    • options?: Object - 可选,一个配置对象,包含:
      • deepThink?: boolean - 是否开启深度思考。如果为 true,Midscene 会调用 AI 模型两次以精确定位元素。
  • 返回值:

    • Promise<void>
  • 示例:

await agent.aiInput('Hello World', '搜索框');

agent.aiKeyboardPress()

按下键盘上的某个键。

  • 类型
function aiKeyboardPress(key: string, locate?: string, options?: Object): Promise<void>;
  • 参数:

    • key: string - 要按下的键,如 EnterTabEscape 等。不支持组合键。
    • locate?: string - 用自然语言描述的元素定位。
    • options?: Object - 可选,一个配置对象,包含:
      • deepThink?: boolean - 是否开启深度思考。如果为 true,Midscene 会调用 AI 模型两次以精确定位元素。
  • 返回值:

    • Promise<void>
  • 示例:

await agent.aiKeyboardPress('Enter', '搜索框');

agent.aiScroll()

滚动页面或某个元素。

  • 类型
function aiScroll(scrollParam: PlanningActionParamScroll, locate?: string, options?: Object): Promise<void>;
  • 参数:

    • scrollParam: PlanningActionParamScroll - 滚动参数
      • direction: 'up' | 'down' | 'left' | 'right' - 滚动方向
      • scrollType: 'once' | 'untilBottom' | 'untilTop' | 'untilRight' | 'untilLeft' - 滚动类型
      • distance: number - 滚动距离,单位为像素。
    • locate?: string - 用自然语言描述的元素定位。如果未传入,Midscene 会在当前鼠标位置滚动。
    • options?: Object - 可选,一个配置对象,包含:
      • deepThink?: boolean - 是否开启深度思考。如果为 true,Midscene 会调用 AI 模型两次以精确定位元素。
  • 返回值:

    • Promise<void>
  • 示例:

await agent.aiScroll({ direction: 'up', distance: 100, scrollType: 'once' }, '表单区域');
关于

deepThink (深度思考)特性

deepThink 是一个强大的特性,它允许 Midscene 调用 AI 模型两次以精确定位元素。这在目标元素面积较小、难以和周围元素区分时非常有用。

数据提取

agent.aiQuery()

使用此方法,你可以直接从 UI 提取数据,并借助多模态 AI 的推理能力,实现智能提取。只需在 dataDemand 中定义期望格式(如字符串、数字、JSON、数组等),Midscene 即返回相应结果。

  • 类型
function aiQuery<T>(dataShape: string | Object): Promise<T>;
  • 参数:

    • dataShape: T: 描述预期的返回值格式。
  • 返回值:

    • 返回值可以是任何合法的基本类型,比如字符串、数字、JSON、数组等。
    • 你只需在 dataDemand 中描述它,Midscene 就会给你满足格式的返回。
  • 示例:

const dataA = await agent.aiQuery({
  time: '左上角展示的日期和时间,string',
  userInfo: '用户信息,{name: string}',
  tableFields: '表格的字段名,string[]',
  tableDataRecord: '表格中的数据记录,{id: string, [fieldName]: string}[]',
});

// 你也可以用纯字符串描述预期的返回值格式:

// dataB 将是一个字符串数组
const dataB = await agent.aiQuery('string[],列表中的任务名称');

// dataC 将是一个包含对象的数组
const dataC = await agent.aiQuery('{name: string, age: string}[], 表格中的数据记录');

更多方法

agent.aiAssert()

使用此方法,你可以通过自然语言描述一个断言条件,让 AI 判断该条件是否为真。当条件不满足时,SDK 会抛出错误,并在错误信息中追加 AI 返回的详细原因。

  • 类型
function aiAssert(assertion: string, errorMsg?: string): Promise<void>;
  • 参数:

    • assertion: string - 用自然语言描述的断言条件。
    • errorMsg?: string - 当断言失败时附加的可选错误提示信息。
  • 返回值:

    • 返回一个 Promise。当断言成功时解析为 void;若断言失败,则抛出一个错误,错误信息包含 errorMsg 以及 AI 生成的原因。
  • 示例:

await agent.aiAssert('"Sauce Labs Onesie" 的价格是 7.99');
TIP

断言在测试脚本中非常重要。为了降低因 AI 幻觉导致错误断言的风险(例如遗漏错误),你也可以使用 .aiQuery 加上常规的 JavaScript 断言来替代 .aiAssert

例如,你可以这样替代上面的断言代码:

const items = await agent.aiQuery(
  '"{name: string, price: number}[], 返回商品名称和价格列表'
);
const onesieItem = items.find(item => item.name === 'Sauce Labs Onesie');
expect(onesieItem).toBeTruthy();
expect(onesieItem.price).toBe(7.99);

agent.aiWaitFor()

使用此方法,你可以等待某个断言条件成为真。考虑到 AI 服务的成本,检查间隔不会超过 checkIntervalMs 毫秒。

  • 类型
function aiWaitFor(
  assertion: string, 
  options?: { 
    timeoutMs?: number;
    checkIntervalMs?: number;
  }
): Promise<void>;
  • 参数:

    • assertion: string - 用自然语言描述的断言条件
    • options?: object - 可选的配置对象
      • timeoutMs?: number - 超时时间(毫秒),默认为 15000
      • checkIntervalMs?: number - 检查间隔(毫秒),默认为 3000
  • 返回值:

    • 返回一个 Promise。当断言成功时解析为 void;若超时,则抛出错误。
  • 示例:

// 基本用法
await agent.aiWaitFor("界面上至少有一个耳机的信息");

// 使用自定义配置
await agent.aiWaitFor("购物车图标显示数量为 2", {
  timeoutMs: 30000,    // 等待 30 秒
  checkIntervalMs: 5000  // 每 5 秒检查一次
});
TIP

考虑到 AI 服务的时间消耗,.aiWaitFor 并不是一个特别高效的方法。使用一个普通的 sleep 可能是替代 waitFor 的另一种方式。

agent.runYaml()

使用此方法,你可以执行一个 YAML 格式的自动化脚本。脚本中的 tasks 部分会被执行,并返回所有 .aiQuery 调用的结果。

  • 类型
function runYaml(yamlScriptContent: string): Promise<{ result: any }>;
  • 参数:

    • yamlScriptContent: string - YAML 格式的脚本内容
  • 返回值:

    • 返回一个包含 result 属性的对象,其中包含所有 aiQuery 调用的结果
  • 示例:

const { result } = await agent.runYaml(`
tasks:
  - name: search weather
    flow:
      - ai: input 'weather today' in input box, click search button
      - sleep: 3000

  - name: query weather
    flow:
      - aiQuery: "the result shows the weather info, {description: string}"
`);
console.log(result);
TIP

更多关于 YAML 脚本的信息,请参考 Automate with Scripts in YAML

agent.setAIActionContext()

这个方法允许你设置在调用 agent.aiAction() 时,发送给 AI 模型的背景知识。

  • 类型
function setAIActionContext(actionContext: string): void;
  • 参数:

    • actionContext: string - 要发送给 AI 模型的背景知识。
  • 示例:

await agent.setAIActionContext('如果 “使用cookie” 对话框存在,先关闭它');

agent.evaluateJavaScript()

这个方法允许你在 web 页面上下文中执行一段 JavaScript 代码,并返回执行结果。

  • 类型
function evaluateJavaScript(script: string): Promise<any>;
  • 参数:

    • script: string - 要执行的 JavaScript 代码。
  • 返回值:

    • 返回执行结果。
  • 示例:

const result = await agent.evaluateJavaScript('document.title');
console.log(result);

属性

.reportFile

报告文件的路径。

更多配置

在运行时设置环境变量

你可以通过 overrideAIConfig 方法在运行时设置环境变量。

import { overrideAIConfig } from '@midscene/web/puppeteer'; // 或其他的 Agent

overrideAIConfig({
  OPENAI_BASE_URL: "...",
  OPENAI_API_KEY: "...",
  MIDSCENE_MODEL_NAME: "..."
});

打印 AI 性能信息

设置 MIDSCENE_DEBUG_AI_PROFILE 变量,你可以看到每次调用 AI 的时间和 token 数量。

export MIDSCENE_DEBUG_AI_PROFILE=1

使用 LangSmith

LangSmith 是一个用于调试大语言模型的平台。想要集成 LangSmith,请按以下步骤操作:

# 设置环境变量

# 启用调试标志
export MIDSCENE_LANGSMITH_DEBUG=1 

# LangSmith 配置
export LANGSMITH_TRACING_V2=true
export LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
export LANGSMITH_API_KEY="your_key_here"
export LANGSMITH_PROJECT="your_project_name_here"

启动 Midscene 后,你应该会看到类似如下的日志:

DEBUGGING MODE: langsmith wrapper enabled