@dudko.dev/agent-web

中文文档
0.0.33发布于 2026/11/09MITTypeScriptESM + CJS构建来源已验证近 30 天下载 2790

Vercel AI SDK上的无头,可配置的浏览器 LLM代理:多提供者带入自有密钥(OpenAI, Anthropic, Google, xAI, DeepSeek, 网关, openai- 兼容)和本地WebGPU/WebLLM, 本地 + 提示工具调用, 有结构的输出, encry

中文使用文档
文档目录13 节
  1. 安装
  2. CDN / 独立捆绑( 无构建步骤)
  3. 快速启动——云型,带上自有钥匙
  4. 快速启动——本地WebGPU模型(无密钥,下行)
  5. 简单生成工具调用( 无代理循环) (T)
  6. 可选: HTTP 上的 MCP 工具
  7. OAuth 2.1 + 动态客户注册
  8. CORS: 服务器必须发送的内容
  9. 可选:WebMCP——一个页面的工具,双向
  10. 思考、限制、同意、技能、潜质
  11. 配置( 亮点)
  12. 文档
  13. 许可证

@dudko.dev/代理网络

无头, 普遍可配置 浏览器 LLM 代理基于 维塞尔 AI SDK一个软件包驱动器 任意 模型从 浏览器 :

  • ☁️ 云提供商,带上你的钥匙 — OpenAI, Anthropic, Google, xAI, (英语), DeepSeek,任何OpenAI相容的服务器,以及Vercel AI Gateway.
  • 🖥️ 本地 WebGPU 模型 通过 网络LLM (单位:千美元)@browser-ai/web-llm;没有服务器,没有密钥,数据从不离开设备.
  • 🔌 任何AI SDK LanguageModel 例如:Chrome/Edge内置AI.

它给你 简单的文本生成、流出、本地工具调用以及 结构化产出,加上一个高级 规划 执行 重新规划 综合 代理 - 有主机定义 工具选项 MCP 磁共振, (中文(简体) ), 系统提示, (中文(简体) ), 索引数据库 存储,和 a 加密令牌金库. UI 不可知:它流出 键入事件; 随你喜欢.

代理循环也有 思维 (便携式推理水平或精确度) 预算, 符号限制 (投入/产出/思考/每跑总), 上下文收缩 (自动和 agent.compact(), (中文(简体) ), 快速缓存, (中文(简体) ), 技能 (SKILLL.MD捆绑), 带有自动驾驶开关的工具同意模式, (中文(简体) ), 工具搜索 数百种多氯乙烯工具目录, 子剂 内 网络工人, 图像 / PDF / 文件 / URL 输入 (模型有明显错误) 无法带走他们, (单位:千美元) 虚拟文件系统 在索引数据库中 fs_* 工具, 使用量 数活 整个届会agent.usage, (中文(简体) ), 引导 跑去的时候RunControl, (中文(简体) ), 恢复 运行中断, 环球 打开并绑定(模型的) web_fetch),以及 学习 ——经纪人将自己的课写成技能 看到了吗 文件/能力。 。 。 .

npm npm NpmLicense GitHub last commit GitHub release

节点包的浏览器比对 @dudko.dev/agent。 。 。 .

使用反应? @dudko.dev/agent-web-react 将此核心包成一个 useAgent 钩子,一个 <AgentProvider> 上下文和下进 UI 组件——尝试 现场演示 (单位:千美元)来源) (中文(简体) ).

安装

npm install @dudko.dev/agent-web ai zod

然后添加 只有您使用的提供者 (所有可选的同伴,动态) 进口:

# cloud, pick what you need
npm install @ai-sdk/openai        # or @ai-sdk/anthropic, @ai-sdk/google, @ai-sdk/xai, @ai-sdk/deepseek, @ai-sdk/openai-compatible
# local WebGPU models
npm install @browser-ai/web-llm @mlc-ai/web-llm
# optional: HTTP MCP
npm install @modelcontextprotocol/sdk

CDN / 独立捆绑( 无构建步骤)

dist/agent-web.js 是一个 自成一体的无害环境管理捆绑 (b) 核心资源 ai, (中文(简体) ), zod 财务报告和审定财务报表 idb 被烤进。 它在npm的包装(所以它在每个 CDN),并附着于各条 GitHub 发布 作为 agent-web-<version>.min.js数字 :

<script type="module">
  import { createAgent, defineTool } from 'https://cdn.jsdelivr.net/npm/@dudko.dev/agent-web/dist/agent-web.js'
  // or: https://unpkg.com/@dudko.dev/agent-web/dist/agent-web.js
</script>

Bundler 用户也可以通过 @dudko.dev/agent-web/bundle 子路径。 可选提供者同伴即使在捆绑中也保持外部; 在 a 无捆绑页, 用导入地图映射您使用的页面( 运行时间) import() 尊重)——直接 LanguageModels 和 gateway 规格不需要 导入映射 :

<script type="importmap">
  {
    "imports": {
      "@ai-sdk/openai": "https://cdn.jsdelivr.net/npm/@ai-sdk/openai/+esm"
    }
  }
</script>

快速启动——云型,带上自有钥匙

密钥已存储 休息时加密 (WebCrypto,索引DB)和引用者为: id——从未被内入到配置中. 见 警卫。 。 。 .

import {
  createAgent,
  defineTool,
  VaultCredentialStore,
} from '@dudko.dev/agent-web'
import { z } from 'zod'

// 1. Store the user's key once (e.g. from a settings form). Encrypted at rest.
const credentials = new VaultCredentialStore()
await credentials.setApiKey('openai', userProvidedKey)

// 2. Tools = your app's actions.
const tools = {
  add_text: defineTool({
    description: 'Add a text block to the page.',
    inputSchema: z.object({ text: z.string(), x: z.number().optional() }),
    execute: async ({ text, x }) => addTextBlock(text, x), // your code
  }),
}

// 3. Create the agent. The key is fetched from the vault at build time.
const agent = await createAgent({
  model: { providerType: 'openai', model: 'gpt-4o-mini', credentialRef: 'openai' },
  credentials,
  tools,
  describeState: () => serializeMyCanvas(), // optional grounding
})

// 4. Run. Every step is a typed event.
const result = await agent.run('Add a centered title and a totals line', {
  onEvent: (e) => {
    if (e.type === 'plan.created') console.log('plan:', e.plan.steps)
    if (e.type === 'step.tool-call') console.log('tool:', e.name, e.input)
    if (e.type === 'final') console.log('done:', e.text)
  },
})
console.log(result.final, `— ${result.applied} changes`)

直接浏览器调用 & CORS : 截至2026年10月,谷歌、OpenAI、xAI和 DeepSeek发送 CORS 头,所以用户自己的密钥从页面直接工作; Athropic 作品也 (为您注入所需的头条) 。 基米 格罗克, Mistral 和 OpenRouter 也这样做(自己建造他们的 AI SDK 模型并通过) 他们作为 model) (中文(简体) ). 见 文件/提供者.md。 。 。 .

快速启动——本地WebGPU模型(无密钥,下行)

import { createAgent, createWebLLMModel, isWebGPUAvailable } from '@dudko.dev/agent-web'

if (!isWebGPUAvailable()) throw new Error('WebGPU required for local models')

const model = await createWebLLMModel('Llama-3.2-3B-Instruct-q4f16_1-MLC', {
  initProgressCallback: (r) => console.log('loading', Math.round(r.progress * 100), '%'),
  contextWindowTokens: 8192, // WebLLM loads with 4096 unless told otherwise
})

// Local models default to the robust "prompted" tool-mode automatically, and
// the agent sizes compaction and tool lists from the model's own window.
const agent = await createAgent({ model, tools /* ...same as above */ })
await agent.run('Summarize the current page and add a heading')

当地人 愿景 型号(Phi-3.5-vision-instruct-q4f16_1-MLC) 获取图像 如来一一云. 见 文件/能力 对于窗口:WebLLM的默认值为4096个令牌,每个模型在负载时提高.

您也可以通过 spec: { providerType: 'web-llm', model: '…' }。 。 。 .

简单生成工具调用( 无代理循环) (T)

import { generate, stream, generateStructured, runToolLoop } from '@dudko.dev/agent-web'
import { z } from 'zod'

const { text } = await generate(model, { prompt: 'Write a haiku about WebGPU' })

const { textStream } = stream(model, { prompt: 'Explain IndexedDB' })
for await (const chunk of textStream) process.stdout.write(chunk)

const { object } = await generateStructured(
  model,
  z.object({ title: z.string(), tags: z.array(z.string()) }),
  { prompt: 'Suggest a title and tags for this article: …' },
)

// Tool-calling with feedback (native or prompted), normalized result. In both
// modes the model sees its tool results and can keep going, up to `maxSteps`
// rounds (default 4; prompted models get the results as a TOOL RESULTS turn):
const { text: reply, toolCalls } = await runToolLoop(model, {
  mode: 'native',
  prompt: 'Add a title',
  tools,
})

可选: HTTP 上的 MCP 工具

import { connectMcpHttp } from '@dudko.dev/agent-web/mcp'

const mcp = await connectMcpHttp({
  docs: { url: 'https://my-mcp-server.example/mcp', headers: { Authorization: `Bearer ${t}` } },
})
const agent = await createAgent({ model, tools: { ...tools, ...mcp.tools } })
// ... later: await mcp.close()

浏览器只能说 HTTP (Streamable HTTP) (缩写为"硬") 运输——Stdio MCP是 唯节. 连接者住在 ./mcp 子路径让 MCP SDK 永远不要 进入你的核心捆绑.

一次通过数个服务器——它们同时连接,每个服务器都有自己的 截止日期(connectTimeoutMs,默认为 30 s),每页 tools/list 读取,工具为服务器标记 readOnlyHint 被视为 仅由同意门读取。 一个失败的服务器在 results; 数据 其他人还在上山 用数百个工具 代理交换工具搜索 自动( 见 文件/能力) (中文(简体) ).

connectMcpHttp 返回时 { tools, catalog, results, refreshServer, close }。 。 。 . tools 财务报告和审定财务报表 catalog 已变异 到位 以 refreshServer(name),所以一个 由它们构建的代理取取取服务器的新工具列表(通过 onToolsChanged 选项)而不重建。 过滤是普通对象的工作 : 合并前删除您不想要的密钥.

OAuth 2.1 + 动态客户注册

OAuth 背后的服务器需要的不止一个信头:访问符已到期中跑. 通过一个 authProvider mCP SDK 发现了授权服务器 (RFC 9728),动态注册此应用程序(RFC 7591-没有客户端 id to 运行PKCE 刷新任何 401 上的访问令牌 重复请求。 。 。 .

import { BrowserOAuthProvider, connectMcpHttp, finishMcpOAuth, readOAuthCallback }
  from '@dudko.dev/agent-web/mcp'

const provider = new BrowserOAuthProvider({
  serverUrl: 'https://my-mcp-server.example/mcp',
  redirectUrl: `${location.origin}/callback`, // must match on the way back
})

// 1. On the callback page: finish the flow before anything else.
const callback = readOAuthCallback()
if (callback) await finishMcpOAuth(provider, callback)

// 2. Connect. `needsAuthorization` means "send the user to authorize".
const mcp = await connectMcpHttp({ docs: { url: provider.serverUrl, authProvider: provider } })
if (mcp.results[0]?.needsAuthorization) {
  location.href = String(provider.authorizationUrl) // a button, a popup — your call
}

托肯斯,动态注册和PCE验证器被存储在同一处 加密索引化DB金库 作为提供者 API 密钥( E)VaultOAuthStorage; 互换为 MemoryOAuthStorage 或者你自己通过 storage) (中文(简体) ). redirectToAuthorization 永远 自行导航——SDK可以要求运行内部的授权 工具调用,然后驱逐用户就会丢弃运行。 URL 被记录 打开 provider.authorizationUrl 而应用程序决定何时使用.

CORS: 服务器必须发送的内容

一个浏览器不告诉 JavaScript 为何会屏蔽一个请求—— 一个 CORS 拒绝和下方的服务器均以 TypeError: Failed to fetch, (中文(简体) ), 真实原因只打印到devtools控制台. 所以这些是值得的 先检查而不是最后检查 :

Access-Control-Allow-Origin:   <your origin>
Access-Control-Allow-Methods:  GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers:  Content-Type, Authorization, mcp-session-id,
                               MCP-Protocol-Version, Last-Event-ID
Access-Control-Expose-Headers: mcp-session-id, WWW-Authenticate

每一行都得到它的位置:

  • MCP-Protocol-Version 在允许页眉中 是最难受的 这个 spec 要求每个请求都使用该页眉 之后 initialize 自此以来 2025-06-18,CORS在该日期前所写的列表省略. 第一项请求 不携带,所以发现, 整个OAuth舞蹈 initialize 全部 成功——然后一切就被封锁。 读起来就像 同意步骤失败,并派您去调试客户端 .
  • WWW-Authenticate 在 Expose 标题中,或浏览器隐藏 401 jS和OAuth的质疑从未开始.
  • Last-Event-ID 用于恢复已丢弃的SSE流.
  • 授权服务器的 /register,元数据和符号端点需要CORS 我也一样, OPTIONS 包含 —— 一个浏览器客户端直接调用它们.
  • 如果服务器使用 MCP SDK 的 DNS 绑定保护,则其 allowedOrigins 必须包含您的来源。 空的,它回答 403 (韩语) Origin not allowed 对载有下列内容的任何请求: Origin 标题——每个请求 a 浏览器制造.

当连接失败时, connectMcpHttp 不再只是重复 浏览器的沉默:它用一个简单的请求重新检测端点,如果是的话 说哪个标题被拒绝了. diagnoseMcpCors(url) 实值 导出一个 UI 可以显示相同的句子 .

可选:WebMCP——一个页面的工具,双向

网络MCP 允许一个已命名、已输入工具的页面寄存器 (单位:千美元)document.modelContext.registerTool(tool, { signal })),浏览器的代理——克罗姆的出处 审判,Edge,一个扩展,一个页面内代理——可以发现和调用. 这个 ./webmcp 亚道桥 和经纪人的 ToolSet,没有额外的依赖性,并作为浏览器没有WebMCP的禁用:

import { connectWebMcp, registerWebMcpTools } from '@dudko.dev/agent-web/webmcp'

// 1. Publish the tools your in-page agent uses, so any agent of the browser can drive them too.
//    One definition, two consumers; withdrawn when the signal aborts or unregister() is called.
const reg = await registerWebMcpTools(tools, {
  prefix: 'myapp_', // WebMCP tool names are shared with everything else on the page
  except: ['debug_dump'],
  consequential: ['clear_page'], // annotated consequentialHint: true
  signal: controller.signal,
})
// readOnly: true tools (defineTool) are annotated readOnlyHint: true

// 2. Use the tools a page has registered as the agent's own.
const web = await connectWebMcp({ onToolsChanged: () => rebuildAgent() })
const agent = await createAgent({ model, tools: { ...tools, ...web?.tools } })

两代的浏览器 API 都被处理: 当前的一个打开 document.modelContext 联合国 工具通过中止其信号而被撤回)和 Chrome 的早期预览 navigator.modelContext (单位:千美元)unregisterTool(name)) (中文(简体) ). 结果作为文本内容返回(结构化结果为JSON),作为 WebMCP客户端阅读. 严格在您体内验证 execute,松散在计划: a 拒绝调用应该是调用代理能够读取的结果,而不是一个被停顿的工具.

import { createAgent, createSubagentTool, defineSkill } from '@dudko.dev/agent-web'

const agent = await createAgent({
  model,
  tools: { ...tools, ...mcp.tools },
  thinking: 'high', // or { level, budgetTokens }; per stage via stageThinking
  limits: { maxTotalTokens: 200_000, maxReasoningTokens: 20_000 },
  maxToolCalls: 40,
  compaction: { contextWindowTokens: 128_000 }, // auto-compacts history and long runs
  skills: [defineSkill({ name: 'triage', description: 'Triage a bug report', content: '…' })],
  toolApproval: {
    mode: 'ask-writes', // autopilot | ask-writes | ask-all | read-only
    onRequest: async (req) => window.confirm(`Allow ${req.toolName}?`),
  },
})
agent.setToolApprovalMode('autopilot') // flip the switch at any time
await agent.compact() // summarise the stored transcript now

使用超过40个工具(多个MCP服务器)的执行器切换到 工具 搜索: 它从每个小步骤开始并呼叫 find_tools 来激活它 需要帮助。 副剂也是工具—— createSubagentTool({ config }) 运行一个孩子 正在处理的代理, createSubagentTool({ worker, workerConfig }) 把它隔开 网络工作者 serveSubagentWorker()添加 profiles 和父模式 每个调用时,在同一副剂的命名变体之间进行选择——另一种型号, 思维级别、限制或系统提示。 给 persistence 仓库 (单位:千美元)new IndexedDBRunStore())和被重新装入或崩溃恢复中断的运行 最后一个检查点为 run('', { resumeFromRunId }) 计划员不会再跑了 没有重复已完成步骤. createRunControl() 引导运行中: send() 在下一个边界的模型前放置一条信息( 重新规划者重新检查计划) 反对, stopSubagent(id) 停止一个副剂. egress (默认关闭)给模型一个安全 web_fetch 带有允许/拒绝列表的工具. learning (默认关闭)让代理记下自己发现的技巧——在记忆中,或在整个会话中的文件系统中. 细节、 默认和事件 : 文件/能力。 。 。 .

配置( 亮点)

选项默认目的
model—— 说(单位:千美元) LanguageModel 或者说 ProviderModelSpec (执行者/ 默认)
planner 编号 : synthesizer=: model每个阶段的模型都超过(如果是部分,则继承基供应商/红外线)
credentials—— 说(单位:千美元) CredentialStore 页:1 credentialRef 密钥
tools{}主机工具( r)defineTool(中文(简体) )
availableTools 编号 : excludedTools—— 说挂起的工具名称的白名单/黑名单 tools
toolMode'auto'native | prompted | auto (云) 本地、当地(即时)
toolSelectionStrategy'auto'all | plan-narrowed | search | auto (上文查询) toolSearchThreshold,40,或者一旦定义需要1⁄4的窗口)
toolApproval自动驾驶同意政策: { mode, rules, onRequest, timeoutMs }· ; agent.setToolApprovalMode()
skills—— 说SKILL.MD 捆绑defineSkill 编号 : parseSkillMarkdown 编号 : loadSkillFromUrl(中文(简体) )
egress关这是什么 模式 可能获取( e)web_fetch: true = https上的任何公共主机,或 { allow, deny, protocols, allowPrivateNetwork, fetch, ... };浏览器无法对 DNS 进行编码,所以倾向于 allow 列表 - 见 侵略
learning关代理人将课程写作技能(save_skill 编号 : forget_skill: true = 本届会议, { store: new VfsSkillStore(vfs) } = 各届会议——见 学习
thinking 编号 : stageThinking提供者默认true,一个级别('low'.'xhigh', (中文(简体) ), 'none'),或 { level, budgetTokens, includeThoughts }
limits—— 说运行盖 maxInputTokens 编号 : maxOutputTokens 编号 : maxReasoningTokens 编号 : maxTotalTokens + 键 perCall 输出封顶
maxToolCalls 编号 : maxPlanSteps页:1每个运行/每个计划的步骤
compaction自动, 占 128k 窗口的 85% (本地型号: 自己的){ auto, contextWindowTokens, thresholdRatio, thresholdTokens, keepRecentTurns, keepRecentSteps, maxToolOutputChars } ——根据整个上下文(固定的快取+笔录+步骤日志)判断,从未超过模型的窗口
promptCachingtrue稳定的系统前缀、 Anthropic 断点、 OpenAI 缓存密钥
vision 编号 : inputs推断模型将什么作为附件(run(goal, { images, files }); 见 agent.capabilities
systemPrompt 编号 : prompts—— 说准备到每个阶段 / 覆盖任何阶段的快速构建器
describeState—— 说将世界状态序列化为快速上下文
memory—— 说ContextStore (单位:千美元)IndexedDBStore 编号 : MemoryStore); 最近的转折被读回规划器提示
sessionId—— 说名称 memory还有水桶 agent.sessionUsage() 计数为
persistence—— 说检查站运行IndexedDBRunStore 编号 : MemoryRunStore这样 run(goal, { resumeFromRunId }) 重新装入后继续——见 续会
maxIterations 编号 : maxStepsPerTask 编号 : maxRevisions8,4,2 (中文(简体) )循环盖
chatTimeoutMs120 000 个每个呼叫监视器
temperature提供者默认每个阶段的取样温度
budgets—— 说遗留的每个阶段产出上限; limits.perCall 胜出,默认为模型窗口的股份
clientName—— 说以 Openai 兼容提供者名称和 MCP 客户端名称发送
logLevel 编号 : logger'warn' 编号 : console动词( r)'silent' | 'error' | 'warn' | 'info' | 'debug'和控制台一样沉入木头
replan 编号 : synthesizetrue切换相机
replanAfter'failure'重新规划触发器 : 'failure' | 'always' | (stepResult) => boolean | Promise<boolean>
compressAfterChars12000 (韩语)遗留: 总结过去的历史( 当 compaction 未设置)

文档

  • 文件/设计 ——建筑与原理.
  • 文件/能力 思维、限制、收缩, 缓存、技能、工具同意/自动驾驶、大型MCP目录、副剂、, 引导运行的代理,学习,进取,使用,恢复,自主,事件引用.
  • 文件/提供者.md ——每个供应商,CORS & direct-vs-proxy.
  • 文档/安保 ——道具地库,出行地和学习:威胁模型.
  • 文件/任务 ——状态和行进图.
  • @dudko.dev/agent-web-react —— 说 反应绑定( R)useAgent, (中文(简体) ), <AgentProvider>,预型组件)- 现场演示 • 妇女 来源。 。 。 .
  • @dudko.dev/agent - 那个 节点/服务器兄弟会(stdio MCP,持久性/再生,OpenTeleometry, CLI).

许可证

麻省理工学院

版本与发布记录

@dudko.dev/agent-web 共发布 30 个版本,首次发布于 2026/07/03;过去 12 个月发布了 30 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.0.33latest2026/11/094 天前
0.0.322026/11/094 天前
0.0.312026/11/094 天前
0.0.302026/11/094 天前
0.0.292026/11/094 天前
0.0.282026/11/094 天前

关于 @dudko.dev/agent-web 的常见问题

@dudko.dev/agent-web 是什么?

Vercel AI SDK上的无头,可配置的浏览器 LLM代理:多提供者带入自有密钥(OpenAI, Anthropic, Google, xAI, DeepSeek, 网关, openai- 兼容)和本地WebGPU/WebLLM, 本地 + 提示工具调用, 有结构的输出, encry

如何安装 @dudko.dev/agent-web?

在项目目录运行 npm install @dudko.dev/agent-web,或使用 pnpm add / yarn add / bun add。

@dudko.dev/agent-web 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dudko.dev/agent-web 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@dudko.dev/agent-web 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dudko.dev/agent-web 可以商用吗?

@dudko.dev/agent-web 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dudko.dev/agent-web 的下载量有多少?

根据 npm 官方下载统计,@dudko.dev/agent-web 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,790 次,日均约 93 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dudko.dev/agent-web 还在维护吗?

最新版本 0.0.33 发布于 2026/11/09(4 天前);至今共发布 30 个版本,其中过去 12 个月发布了 30 个;首次发布于 2026/07/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。