Logo of Lexmount
文档模板博客帮助中心
GitHub
Logo of LexmountLexmount Browser

开始使用

Lexmount 文档
控制台使用指南

Browser

概览快速开始核心能力示例

Web Fetch

概览快速开始
常见错误

Web Search

概览快速开始搜索接口

运行时

概览快速开始接口能力示例

帮助与计费

能力名词 FAQ
更新日志联系支持
Node.js SDK

Node.js 核心能力

当前 client、session、context、extension、download、CDP、Browser Agent、错误和日志 API。

Client 与区域

import { Lexmount } from "lexmount";

const client = new Lexmount({
  region: "<region-id>",
  timeout: 60_000,
});

console.log(await client.regionInfo());
console.log(await client.catalogInfo());

Client 从构造函数参数或环境变量读取凭据。区域目录发现是尽力而为:目录或探测不可用时,会回退到配置的 base URL。

Sessions

创建选项

const session = await client.sessions.create({
  browserMode: "normal",
  windowSize: "1920,1080",
  downloads: { enabled: true },
  recording: { persistent: true },
});
选项用途
browserModenormal 表示 Chromium,light 表示 Moli
context / contextDescription复用或创建持久化浏览器状态
extensionIds挂载已上传扩展
proxy / officialProxy选择本地代理、外部代理或官方代理池
downloads开启或关闭 session 存储下载
recording开启或关闭持久化回放;Moli 会强制关闭
customImageId使用获准的自定义浏览器镜像
windowSize以 width,height 设置 ACE 浏览器尺寸
enableLightmountLayout开启 LightMount layout 集成,默认 true
enableLightmountResource覆盖当前 session 的 layout-resource 集成
enableCaptcha为当前会话开启自动验证码处理,默认关闭
asyncCreate异步创建并等待 active,默认 true
pollIntervalMs / pollTimeoutMs控制激活状态轮询

officialProxy: true 与 proxy 不能同时使用。Context、扩展、代理和自定义镜像是否可用由套餐能力决定。

自动处理验证码

使用 SDK 0.6.1 或更新版本,在创建会话时显式传入 enableCaptcha:

const session = await client.sessions.create({
  browserMode: "normal",
  enableCaptcha: true,
});
try {
  console.log(session.id);
} finally {
  await session.close();
}

默认值是 false。此设置仅作用于新建的当前会话,同一项目的其他会话可以保持关闭。SDK 在同步和异步创建请求中都会发送顶层 enable_captcha 布尔字段。

服务端会为已开启且符合项目权益的会话自动检测、处理验证码。可用性和使用量受项目套餐及剩余验证码额度约束;客户端继续使用原有 SDK 或 CDP 控制浏览器。

会话生命周期介绍控制台中的对应开关。

查询、列表、targets 与关闭

const current = await client.sessions.get(session.id);
const sessions = await client.sessions.list({ status: "active" });

console.log(sessions.pagination.totalCount);
for (const item of sessions) {
  console.log(item.id, item.status, item.regionId, item.browserType);
}

for (const target of await client.sessions.listTargets(session.id)) {
  console.log(target.title, target.url, target.inspectUrl);
}

await session.close();
// 只有 ID 时等价调用:
await client.sessions.delete({ sessionId: session.id });

下载

const result = await client.sessions.downloads.list(session.id);
console.log(result.summary.count, result.summary.totalSize);

const file = await client.sessions.downloads.get(session.id, "<download-id>");
const archive = await client.sessions.downloads.archive(session.id);
const deleted = await client.sessions.downloads.delete(session.id);
console.log(file.length, archive.length, deleted.deletedCount);

存储下载默认开启。请参考 quickstart 仓库配置远端浏览器下载行为,使文件进入持久化下载目录。

本地代理隧道

SDK 0.6.0 起新增 client.tunnels.open();建议使用 0.6.1 或更高版本。隧道就绪后,以 proxy: { type: "local", tunnelId: tunnel.id } 创建 normal 会话,让云浏览器使用 SDK 电脑的网络与 DNS。需要 custom_proxy 权限,同项目/Key/区域,且与官方或外部代理互斥。先关会话,再关隧道;完整示例及选项见 本地代理指南。

Contexts

const context = await client.contexts.create({
  description: "Authenticated storefront",
  metadata: { owner: "agent-a" },
});

const session = await client.sessions.create({
  context: { id: context.id, mode: "readWrite" },
});

const contexts = await client.contexts.list({ status: "available", limit: 20 });
const details = await client.contexts.get(context.id);
const forked = await client.contexts.fork(context.id);

await client.contexts.forceRelease(context.id);
await client.contexts.delete(forked.id);

Context 被活跃的读写 session 使用时会锁定。当前 fork 只会复制离线且状态为 available 的 context;不支持热 fork、copy-on-write 或父子谱系追踪。

Extensions

const extension = await client.extensions.upload(
  "/absolute/path/to/extension.zip",
  {
    name: "demo-extension",
  },
);

const extensions = await client.extensions.list({ limit: 20, offset: 0 });
const details = await client.extensions.get(extension.id);

const session = await client.sessions.create({ extensionIds: [extension.id] });
await session.close();
await client.extensions.delete(extension.id);

服务接受 .zip 和 .crx。活跃 session 正在使用扩展时不能删除该扩展。

CDP 辅助方法与集成鉴权

import { connectOverCDP, Lexmount } from "lexmount";

const client = new Lexmount();
const session = await client.sessions.create();
const cdp = await connectOverCDP(session);

console.log(await cdp.send("Browser.getVersion"));

await cdp.close();
await session.close();
client.close();

包还导出 registerIntegratedAuthCallback 和 deregisterIntegratedAuthCallback,供应用处理集成鉴权。

错误与日志

import {
  APIError,
  AuthenticationError,
  ContextLockedError,
  NetworkError,
  TimeoutError,
  setLogLevel,
} from "lexmount";

setLogLevel("INFO");

try {
  await client.sessions.create();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Check API Key and Project ID");
  } else if (error instanceof ContextLockedError) {
    console.error(error.activeSessionId, error.retryAfter);
  } else if (error instanceof NetworkError || error instanceof TimeoutError) {
    console.error("Check whether a session was reserved before retrying");
  } else if (error instanceof APIError) {
    console.error(error.statusCode);
  } else {
    throw error;
  }
}

日志辅助方法包括 setLogLevel、enableLogging、disableLogging 和 getLogger。

Browser Agent

Browser Agent 根据自然语言指令执行浏览器任务。Run 是一次执行;保存的 Agent 包含可复用指令及可选输出结构。SDK 0.7.0 通过 client.browserAgent 提供这些能力。

配置

npm install lexmount@0.7.0
export LEXMOUNT_API_KEY='<your-api-key>'
export LEXMOUNT_PROJECT_ID='<your-project-id>'
# 可选:SDK 0.7.0 默认使用全球 COM 地址。
export LEXMOUNT_BASE_URL=https://api.lexmount.com

API Key 和 Project ID 必须属于同一项目,并在所选环境启用 Browser Agent。填写 HTTPS 源地址,不要附加 /v1/browser-agent,SDK 会添加路径。中国区请显式设置 https://api.lexmount.cn。调用这些 Agent API 无需安装 Playwright。

执行任务

运行示例前,为一次逻辑任务选择并持久保存 RUN_IDEMPOTENCY_KEY。恢复这次任务时复用同一个键和相同请求;只有明确创建新任务时才使用新键。

export RUN_IDEMPOTENCY_KEY='<persistent-unique-key-for-this-task>'

保存为 agent.mjs,运行 node agent.mjs:

import { APIError, Lexmount, RunWaitTimeout } from 'lexmount';

const key = process.env.RUN_IDEMPOTENCY_KEY;
if (!key) throw new Error('Set a persistent RUN_IDEMPOTENCY_KEY first');
const client = new Lexmount();
try {
  const receipt = await client.browserAgent.runs.create(
    {
      query: 'Read the page title and summarize the page.',
      start_url: 'https://example.com/',
    },
    { idempotencyKey: key }
  );
  console.log('Accepted:', receipt.id); // Save this Run ID before waiting.
  const run = await client.browserAgent.runs.wait(receipt.id, {
    timeoutMs: 300_000,
  });
  console.log(run.id, run.status, run.output);
  if (run.status !== 'succeeded') {
    console.error(run.stop_reason, run.error);
    process.exitCode = 1;
  }
} catch (error) {
  if (error instanceof RunWaitTimeout) {
    console.error('Resume with runs.get/wait:', error.run_id);
  } else if (error instanceof APIError) {
    console.error(error.status_code, error.code, error.request_id);
  } else {
    throw error;
  }
  process.exitCode = 1;
} finally {
  client.close();
}

创建响应只是已排队回执,不表示任务完成。保存 receipt.id,进程重启后通过 runs.get(id) 或 runs.wait(id) 恢复查询。关闭 SDK 客户端不会取消正在运行的任务。

复用已保存的 Agent

另外持久保存两个键:AGENT_IDEMPOTENCY_KEY 用于创建 Agent,SAVED_RUN_IDEMPOTENCY_KEY 用于本次 Run。保存返回的 Agent ID,后续 Run 直接使用它;创建 Agent 是一次性设置步骤。

import { Lexmount } from 'lexmount';

const agentKey = process.env.AGENT_IDEMPOTENCY_KEY;
const runKey = process.env.SAVED_RUN_IDEMPOTENCY_KEY;
if (!agentKey || !runKey)
  throw new Error('Set both persistent idempotency keys');
const client = new Lexmount();
try {
  const agent = await client.browserAgent.agents.create(
    {
      name: 'Page summary',
      instruction: 'Summarize the page in {{language}}.',
      start_url: 'https://example.com/',
      output_schema: {
        type: 'object',
        properties: { summary: { type: 'string' } },
        required: ['summary'],
        additionalProperties: false,
      },
    },
    { idempotencyKey: agentKey }
  );
  const receipt = await client.browserAgent.runs.create(
    {
      agent_id: agent.id,
      variables: { language: 'English' },
      metadata: { source: 'docs' },
    },
    { idempotencyKey: runKey }
  );
  console.log('Agent:', agent.id, 'Run:', receipt.id);
  // Recover this Run later with runs.get(receipt.id) or runs.wait(receipt.id).
} finally {
  client.close();
}

变量必须与指令模板中的变量完全匹配。Run 被接受后会冻结 Agent 版本、展开的指令和输出结构,后续编辑 Agent 不影响已接受的 Run。metadata 返回给应用,不发送给模型。使用结构定义时,成功的输出是对象;自由输出是文本。

管理资源

以下方法均位于 client.browserAgent。每次调用都使用 await。

操作调用
读取 / 列出 Agentagents.get(id) / agents.list()
编辑 Agentagents.update(id, { revision: current.revision, name: "Updated name" })
删除 Agentagents.delete(id)
读取 / 列出 Runruns.get(id) / runs.list()
请求取消runs.cancel(id)
等待终态runs.wait(id)

编辑前先读取 Agent 并传入当前 revision;版本冲突时重新读取,更新操作不会自动重试。取消与完成可能同时发生,应检查返回状态;若仍为 cancelling,继续查询直到终态。

恢复与错误处理

  • 未提供幂等键时 SDK 会自动生成。需要跨进程恢复时,请自行持久保存并传入:第二个选项参数中的 idempotencyKey。发送前持久保存键和请求体;键使用 1–128 个不含空格的可见 ASCII 字符。相同键和请求体至少七天内返回原回执,不同请求体会冲突。超过该窗口后,先核对历史记录再决定是否新建。
  • succeeded、failed、timed_out、cancelled 都是 Run 终态。HTTP 成功不代表任务成功,应检查 status、stop_reason、error 和 output。
  • RunWaitTimeout 仅停止本地轮询。用已知 Run ID 继续查询,或显式请求取消。timeoutMs、pollIntervalMs、requestTimeoutMs 单位为毫秒。
  • APIError 包含 status_code、code、request_id,排查时保留请求 ID。传入 { withResponse: true } 可读取成功响应的元信息。
  • 创建 Run 时使用的 API Key 应保持有效,直到执行和清理完成。撤销它可能让活动 Run 以 credential_unavailable 失败;更换客户端 Key 不会替换原 Run 的执行凭证。
  • 计量尚未确认时,usage.credits 可能为 null,不表示零费用。执行可能产生外部操作,结果未知时不要盲目重新提交。

可运行示例覆盖基础执行、已保存 Agent 和恢复流程。

Node.js 快速开始

创建 Chromium 和 Moli session,并使用 Playwright 连接 Chromium。

Node.js 示例

按浏览器任务选择可运行的 Node.js quickstart 脚本。

目录

Client 与区域
Sessions
创建选项
自动处理验证码
查询、列表、targets 与关闭
下载
本地代理隧道
Contexts
Extensions
CDP 辅助方法与集成鉴权
错误与日志
Browser Agent
配置
执行任务
复用已保存的 Agent
管理资源
恢复与错误处理

问题没有解决?