# @wrenautomation/birdwatch 中文文档

规范地址：https://npmcn.com/package/%40wrenautomation/birdwatch/

版本：0\.30\.6
npm 元数据更新时间：2026-11-02T22:15:30.839Z
中文译文更新时间：2026-11-02T22:41:48.416Z
软件包许可：PolyForm-Strict-1\.0\.0

本文由上游 README 机器翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40wrenautomation/birdwatch
原文对照：https://npmcn.com/package/%40wrenautomation/birdwatch/?lang=original
项目主页：https://github.com/wrenautomation/engine#readme
源码仓库：https://github.com/wrenautomation/engine

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：756 kB，144 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=24
- 运行依赖：9 个
- 首次发布：2026-10-29T21:01:34.621Z
- 最新版本发布：2026-11-02T22:15:30.488Z
- 已发布版本数：9（近 12 个月 9 个）

## 中文简介

从开放的网络上进行研究，由代理驱动，每个命令执行一步：计划，搜索，分类，打开，在报价门后面提取，检查，审查，分类账中的每条记录。代理人决定；发动机按固定的步骤运转。请求和计划文件，文件

## 安装

```sh
npm install @wrenautomation/birdwatch
```

也可以使用：`pnpm add @wrenautomation/birdwatch`、`yarn add @wrenautomation/birdwatch`、`bun add @wrenautomation/birdwatch`

## README

# birdwatch

来自开放网络的研究，由一个代理驱动，每个命令一步。代理计划，分类， 检查和停止；观鸟者搜索，打开页面，在报价门后提取发现，检查 他们，并把每一个记录在一个分类账上。每一个发现都是一个句子，在页面上引用 运行阅读。 `skills/birdwatch/SKILL.md` （在这个回购中）是代理如何驱动它。

阅读网页和文件（获取阶梯，HTML和PDF文本，视频）是 [`@wrenautomation/read`](https://github.com/wrenautomation/engine/tree/main/packages/read)每个模特的电话都接通了 [`@wrenautomation/models`](https://github.com/wrenautomation/engine/tree/main/packages/models)。在0.29.0之前，有三个软件包：raven（一个模型规划器，在0.30.0时消失了） 代理计划)、猎鹰(`./document`)和weaver（引擎、源、分类账和CLI）。

| 进口 | 做 |
| --- | --- |
| `@wrenautomation/birdwatch/engine` | `Source` (一个名字, `search` 和/或 `open`（成本）； `registry` 计划的允许清单；座席的呼叫(`planRound`， `search`， `open`， `extract`， `check`， `add`， `accept`， `brief`)，每人一步；法官的通行证(`judgeHits`， `judgeDocuments`， `judgeFindings`， `judgeStats`); `fold` 从运行的记录中重建运行的状态，因此再次步进运行会跳过已完成的操作； `Transient`失败值得再试一次；ask和plan文件形状(`Ask`， `PlanFile`， `Query`， `QueryTree`， `Edge`， `Snapshot`)，以及每一品种的股票计划档案(`web`， `video`， `channel`， `person`， `site`来源，预算， `age`， `rules`，查询树指南) |
| `@wrenautomation/birdwatch/sources` | `searxng`， `exa` (搜索), `youtube` （搜索和读取，yt-dlp）， `fetcher` （开门，礼貌的取货者） `ladder` （打开autobrowse的取回阶梯到浏览器）， `reddit` 和 `facebook` （通过autobrowse的站点路由打开一个线程或群组帖子）， `google` （b谷歌通过桌面浏览器自己的页面：每个结果一个点击，AI概述一个点击，其文本作为片段，每个页面引用一个点击）， `arxiv` (搜索和读取：里面的API `BIRDWATCH_ARXIV_CATEGORIES`，每次点击都以OpenAlex的引用次数和评论为主导；全文从HTML中读取，否则从PDF中读取；每3秒呼叫一次； `paste` （一个人的网址）， `ledger` （命中较早的运行看到）。的查询 `site` 跳过无法保持它的搜索器(`Source.keeps`： `youtube` 只在YouTube上播放)。A跟随(`Source.follows`， `follow`)列出页面作者的帖子(`youtube`：一个频道的上传，从视频或频道，以及TikTok的个人资料； `reddit`：用户最热门的帖子和评论)或类似的页面(`exa`: findSimilar) |
| `@wrenautomation/birdwatch/ledger` | 记录(`query`， `hit`， `document`， `finding`， `verdict`， `call`， `spend`， `snapshot`， `edge`， `done`， `steer`， `gap`， `check`， `pattern`， `found`， `judge`， `person`)， `FilesLedger` (一个文件夹: `runs/<run>/<writer>.jsonl`， `plans/<kind>.json`)， `MemoryLedger`，每个来源、每个人、每个渠道和每个种类的产量行 |
| `@wrenautomation/birdwatch/document` | 文件方面： `Document`， `Finding`， `Proof`， `Verdict` （zod）、媒体读者(`html`， `pdf`， `text`)， `claimExtractor` （引用文档的发现，通过gate，以及对文档的判断：其质量和请求的差距；对发现或它们的长度没有上限，并且模型的输出上限从最后保存的引用继续） `Model` 接缝，它需要和 `Cut` 当一个模特的帽子剪断一个答案时，他就扔了 |

每条记录都承载着 `from` （人工智能，人或工具）和 `by` (代理或模型id、来源 人)。一个人的保留或删除记录与代理人的记录相同。计划文件归档 `plans/<kind>.json` 在分类帐（来源、预算、年龄、规则、树指南）旁边是一个运行的地方 学习: `birdwatch learn <kind>` 从跑步中学到的东西中写出下一个版本 协议;没有调优文件的类型运行库存文件(`birdwatch plans <kind>` 打印)。 `brief.guide` 向代理人显示种类的年龄判决和规则。

## 命令行界面

需要节点24+。 `read` 和 `watch` 需要yt-dlp和ffmpeg。

```sh
npm i @wrenautomation/birdwatch
npx birdwatch fetch https://example.com/report --contact you@example.com   # a page as text
GEMINI_API_KEY=... npx birdwatch read https://www.youtube.com/watch?v=...    # captions + screen
COHERE_API_KEY=... npx birdwatch read https://www.instagram.com/reel/...     # watched: speech, screen, cuts
npx birdwatch list 'ytsearch10:cold email' --to 10                           # hits as JSON, no downloads
npx birdwatch text report.pdf                                             # a file on disk as text
npx birdwatch page saved.html --url https://example.com/report            # title, text, links as JSON
COHERE_API_KEY=... npx birdwatch watch talk.mp4                           # speech, on-screen text, cuts
npx birdwatch plans web > ledger/plans/web.json                           # a stock plan file, to tune
```

一个代理（Claude Code，或任何带有shell的代理）每次只执行一个命令来驱动引擎：it 在它自己的头脑中计划，分类，审查和停止，引擎做固定的工作(搜索， 打开，提取报价门后，检查)并保存记录。每个命令打印JSON。

```sh
export BIRDWATCH_AGENT=claude-code                     # the agent's id on every record it writes
birdwatch plan "how do staffing firms win repeat clients" --known "referrals convert"   # a run; prints its id
birdwatch plan "who buys growth help" --premise "coaches are the buyer"   # a premise gets a tree facet that tests it
birdwatch brief 01M5YS...                              # the ask, budget, sources, what is open, hits, findings, cost
birdwatch recall staffing repeat clients --not 01M5YS... # earlier runs' findings: quote, URL, source date, run; --also <ledger> per extra folder
birdwatch search 01M5YS... "staffing repeat client rate" --why "the ask's words"       # one query, then every searcher
echo '[{"terms":"...","why":"..."},{"terms":"...","why":"..."}]' | birdwatch search 01M5YS...   # a batch
birdwatch search 01M5YS... < tree.json                 # a query tree, one tier: {facets: [{name, why, tries: [[{terms, why}], [...]]}]}
birdwatch search 01M5YS... < tree.json                 # after triage, the same file: the next try of each facet still thin in kept hits
birdwatch add call 01M5YS... 01M5YT... keep --why "a survey with numbers"               # triage: a hit kept
birdwatch add call 01M5YS... 01M5YU... drop --why "a vendor page"
birdwatch open 01M5YS... 01M5YT... --url https://a.example/report --why "numbers"      # keep these, read every kept hit
birdwatch open 01M5YS... --with ladder                                                  # an opener the run lacks joins it, to open only
birdwatch show 01M5YS... 01M5YV...                     # a document's text, for the agent to read itself
birdwatch add finding 01M5YS... 01M5YV... --text "412 firms were surveyed." --quote "A 2025 survey of 412 firms"
birdwatch add check 01M5YS... 01M5YW... --ok --why "the quote says it"   # the agent's own check; --fail also drops
birdwatch extract 01M5YS...                            # or a model behind the quote gate, every document without a verdict
birdwatch check 01M5YS... -n 3                         # or a model's sample of findings read against their documents
birdwatch check 01M5YS... --patterns                   # every unchecked finding a pattern rests on
birdwatch accept 01M5YS... keep --over 0.8 --why "serves the ask"   # the judge's hints in bulk, at the agent's bar
birdwatch accept 01M5YS... class --min 0.8 --why "head of page"   # also: drop --under 0.2
birdwatch add gap 01M5YS... "no UK numbers yet"
birdwatch add steer 01M5YS... "numbers only" --human will                                # the person's word, relayed
birdwatch add pattern 01M5YS... "Repeat clients come from referrals." --on 01M5YV... 01M5YW...   # what findings say together; sites counted
birdwatch add edge 01M5YS... again --why "thin on the UK"                                # the review: a new round
birdwatch plan --run 01M5YS...                         # round 2: known, steer and what round 1 left open, in its snapshot
birdwatch plan "coaches: who pays for setters" --parent 01M5YS... --why "the best niche of round 1"   # a child run
birdwatch add dead 01M5YT... spend --why "found consumers, not buyers"   # later tries skip the facet
birdwatch follow 01M5YS... --from 01M5YV... --as posts --why "the speaker's other talks"   # the author's own posts; --as similar: pages like it; a paper: --as refs (what it cites) or citers (what cites it)
birdwatch add person 01M5YS... "Bee Speaker" --profile https://www.youtube.com/@bee --aka Bee --why "one speaker"   # one person across sites
birdwatch learn web --sources searxng exa --rounds 4   # the plan file's next version, after a good run
birdwatch learn web --thin 2                           # the tree's guide: a try under 2 new hits falls through
birdwatch learn web --show                             # the current one
birdwatch add edge 01M5YS... stop --why "enough"
```

`plan` 打开一轮：它的快照包含了问题，已知的（到目前为止的发现），每一个 舵手，上一轮还有什么空缺，允许名单和预算。没有疑问，代理人来了 通过 `search` 或者 `add query`，从不封顶。预算是一道护栏： `brief` 显示它，并且 一条边 `again` 过去的 `budget.rounds` 打印的是警告，而不是拒绝。 `search`， `open`， `extract` 和 `check` 每个程序运行一个步骤并打印它所写的内容（文档的文本） `chars`); 一个带着音符放弃出口的步骤。 `open` 读取每一个保存命中的运行，没有 文档; `extract` 每一份没有判决的文件； `check` 的跨文档示例 保留尚未检查的发现。 `add` 手动写入一条记录：查询，查找（引用） 必须逐字逐句地在文档上，否则添加失败，并带有门的“为什么”，检查(？ 代理人自己对与其文件不符的调查结果的解读；失败也会丢弃它)，调用(keep或 投掷命中或发现)，边缘(`again`， `stop`， `back --to <step>`)、缺口或转向（总是如此） 人的: `--human [name]`）. 每一个 `add` 需要 `--why` 当决策需要时。一个 `--human` 记录是当事人通过代理人的话： `from: human`， `by` 他们的名字。

当智能体给出一个面（研究者覆盖的边）时，一轮搜索是一个树 数字，如何，谁，相反的观点，主要来源；计划文件的 `tree` 指南给它们命名)， 每个都按顺序尝试，每个都尝试一个查询列表。 `search` 每次呼叫运行一个层 Fetch：第一次调用，每个facet的第一次尝试；每次调用后，每个方面的下一次尝试 比向导留下的子弹少 `thin` （默认为3）。的一个侧面 `thin` 完成;一个方面 没有名字的呼叫等待分类；有一个面没有了，仍然很薄，这是一个缺口， 写一次。尝试失败的结果是分诊保留了什么，而不是搜索者保留了什么 返回：每个搜索者返回一个页面。 `--all` 负责所有方面的下一步尝试 保存。第二次查询返回的页面是 `found` 第一炮就录，第二炮就不录了 命中，每一击都被视为命中。 `brief.hits.uncalled` 列出每个 首先，用找到它的面来击打； `brief.tree` 用它写的东西显示每一次尝试， `kept` 和 `uncalled` 每一个方面。没有查询服务的向导facet在注释中被命名。 `learn --thin <n>` 或者 `--tree <file>` 调整指南。

代理自己读取： `show <run> <document>` 打印文档中存储的文本， `add finding` 在同一扇门后面写着它读到的东西， `add check` 它自己的支票。 `extract` 和 `check` 在同一扇门后面放一个模型，以增加体积；两个路径都写相同的记录。

代理人：通过代理人或亲自：

```sh
npx birdwatch add steer 01M5YS... "numbers only; skip vendor pages" --human       # what you say: the brief shows it first
npx birdwatch add gap 01M5YS... "no UK numbers yet" --human                       # what the run lacks: the next plan reads it
npx birdwatch add edge 01M5YS... back --to fetch --why "searxng was down" --human # the step to run again
npx birdwatch trace 01M5YS... --type finding spend                                # the run's records, JSON lines
npx birdwatch add call 01M5YS... 01M5YT... drop --why "a forecast, not a result" --human   # a call in your name
npx birdwatch yield --source exa                                                  # hits, reads, proposed, kept
npx birdwatch sources                                                             # what this machine can run
npx birdwatch serve --port 4747                                                   # the ledger over HTTP for a viewer, read only
```

模型是 `anthropic` 默认(Claude Haiku直接， `ANTHROPIC_API_KEY`； `--model anthropic:sonnet|opus|id` 另一个) `--model gateway[:alias]` Wren的LLM入门课程 （`WREN_LLM_GATEWAY_URL`， `WREN_LLM_GATEWAY_TOKEN`)，或者在stdin上读取提示符的任何命令 并打印出答案(`claude -p --output-format json` 是克劳德代码无头)。模型确实如此 仅散装（提取，检查）；代理决定。源来 来自环境： `SEARXNG_URL` (和 `SEARXNG_TOKEN`举个例子，在a后面 代理), `EXA_API_KEY` (或 `_1..n`)， `GEMINI_API_KEY` 对于没有字幕的视频， `BIRDWATCH_CONTACT` 对于取回器和 `arxiv` (无联系人，无页面打开； `OPENALEX_API_KEY`免费的；给予的 `arxiv` 它自己的引用预算，和 `SEMANTIC_SCHOLAR_API_KEY`，免费，按自己的价格收费 `--as refs`； `--sources arxiv` 命名它（因为没有股票计划文件这样做），也为梯子命名 `AUTOBROWSE_URL` 和 `AUTOBROWSE_TOKEN` （一个worker的HTTP面）或 `RESTATE_INGRESS_URL` 和 `RESTATE_AUTH_TOKEN` (Restate入口，后面坐着一名办公人员； `POST /desk/call`； `AUTOBROWSE_SERVICE` 获取另一个服务名称)。同一个工人给了 `reddit` 和 `facebook` 读者。 `BIRDWATCH_ACCOUNTS` 指定每个站点读者可以登录的帐户 （`reddit=reddit@alt`）; 没有条目的站点只能读为已注销。分类帐文件夹为 `--ledger` 或者 `BIRDWATCH_LEDGER` (默认 `./ledger`); `--writer` 或者 `BIRDWATCH_WRITER` 在其中命名您的文件。 法官是 `--judge` 或者 `BIRDWATCH_JUDGE` （`jev`， `jev:<model>`， `fake`， `off`）; 没有, `jev` 当 `TYPESAFE_API_KEY` 是，否则为空。 `--no-judge` 为一个命令关闭它。

每个开放源代码都声明它打开的url (`opens`): `youtube` 一个YouTube页面， `fetcher` 和 `ladder` 任何其他http(s)页面 `reddit` Reddit帖子或评论永久链接， `facebook` 一个 公共群组帖子。网站自己的阅读器(`first`在开幕式前轮到它了。 无论允许列表的顺序如何：它都将线程作为数据响应，其中获取的页面是一个墙。 `reddit` 阅读先签出(`reddit-public`线程的馈入)；只有当那错过和 `BIRDWATCH_ACCOUNTS` 命名一个帐户，它是否要求再次登录。 `facebook` 总是 签署。用过的帽子或拒绝阅读的信都是错过；忙配置文件（503）或无应答重试。 拒绝在其原因中携带工人的访问码： `need_login`， `platform_blocked`， `rate_limited` 或者 `upstream_broken`。最后两个从未读过登录：这两个都不能解决。 读取步骤要求在调用之前，所以一个源永远不会 打开一个hit就等于不花钱。获取的页面没有任何可用的内容（403，块） 梯子的最后一个梯级还在响，一个没有读者的媒体，一个梯子的答案不是HTML这样的 作为PDF)是一个失误：源抛出，它的 `spend` 说 `ok: false` 有了理由，下一个 揭幕战轮到你了，每场揭幕战没打到的命中都是 `gap` 上面列出了每个原因。一个页面 它的答案是200，但仍然没有任何内容（一个captcha墙，一个“未找到”的shell，低于200） 文字)同样是错过，以标题或计数为原因。运行的 快照将其源固定在 `plan`： `sources`，允许列表，搜索，打开和跟踪； `opens`，注册表的其他打开器(除非 `--sources` 是给定的)，哪个打开和跟随但是 从来没有搜索。 `open --with <source>` 写入一个新快照，该快照将一个添加到 `opens` (读 注：当命中未命中时，会命名它们)。这个 梯子花费了浏览时间和工人每天的工作时间 `fetch` 每个调用的桶。穰的搜索 要求每个结果有一个亮点（三个句子，每个结果计费）作为命中的 `snippet`.

每个模型调用都是一个 `spend` 记录模型id，输入和输出令牌，以及 `usd` 从 标价(`src/app/prices.ts`：克劳德的俳句、十四行诗和作品5.5；网关的 `free` 别名为$0；另一种模式保留代币，没有价格)。 `run` 在stderr上打印运行总数 和作为 `cost` 在JSON中，最后一次复习的边缘(`edge`（下一个和为什么）同样的方式； `brief` 将总数打印为 `cost`.

`run` 当运行在一个放弃的步骤上停止时退出2（没有模型，没有源，一个块）： `--resume` 一旦问题解决了就继续。失败值得再试一次(A 429, A 5xx， A 断开连接)尝试三次并暂停，每次尝试a `spend` 记录;一个步骤 仍然不能继续写不 `done`, `run` 等待并重新开始，最多五次， 在它退出之前。搜索、读取和摘录呈扇形分布（一次读取或摘录四次）； 每个文档的记录在其批处理结束时着陆，并且再次执行步骤会跳过其记录 显示完成。永远失败的提取（模型的答案无法解析，为400）将停止 根据目前记录的调查结果和出口2： `extract` 再次只要求 没有判决的文件。削减产出上限的一个模型答案不是失败，而是整体失败 发现之前的削减通过闸门和模型再次要求其余的 已知这些发现的文件(`./document`的 `Cut`;这个 `spend` 携带两个调用（令牌）。

轮盘之间，这个人看书 `brief` （或代理人告诉他们），保留或丢弃发现(`add call`)，并以自由文本(`add steer`）. 每一个 `steer` 记录显示首先在 简短的，在它之后的回合的摘录提示。 `budget.rounds` 是一名警卫 铁轨，不是停止规则：通过它，边缘的原因说明了为什么再打一回合是值得的。

这些步骤用英语记录。每个搜索者都回答了这个问题，没有新的命中，并且保留了一个 打无源打不开（一个403，一个挡梯子打不开），各写一个 `gap`； 那么 `add gap`。一轮的回顾读的是差距和一个人的去留与其原因；接下来的 Round的计划会读取它们，而评论就是为什么 `again`，在“最后一轮未结束”下。 `add edge back --to <step>` 写一个人的边缘：折叠把它当作代理人。一个 `pattern` （`add pattern`用代理人的话说，是几份保存下来的调查结果的总和；它的计数 不同的地点是从发现的证据中计算出来的，从未声称过，并且 `brief.patterns` 列表 他们的报告。跑步可以是一个孩子(`--parent <run> --why`)：它的快照命名父快照，它的计划读 父母和兄弟姐妹发现了什么（回想那些运行），它的预算是父母的 最多。计划文件的 `runs.depth` (2)是护栏：更深的孩子警告。两个封盖停止 每轮家长的子女数(`runs.children`， 6)，整棵树的读数为(`runs.reads`,固定 在根目录的快照上 `treeReads`； 默认情况下，根节点的读数为x，四舍五入x（子节点+ 1）。 `open` 在树冠处停止或切断它的攻击； `brief.lineage` 和 `brief.treeRoom` 显示了 先人又离开了房间。一个 停止儿童的停止，模式和死角(`add dead`)达到父母的下一个计划 已知线;一个奔跑的孩子是开放的。一个 `class` （`add class`)表示文件的来源类型(原始数据、调查、 从业者，供应商，论坛，新闻，其他)，以及为什么；它的研究结果证明了这一点，而且是一门课 发现超越了它。 `brief.patterns[].classes` 计算每个类的来源：不同的站点， 但每个论坛线程都有自己的； `echo` 标记一个分类源都是供应商的模式， 和 `unchecked` 列出未检查到的结果。只有代理人或一个人写 类。一个树面 `needs` 命名可以证明这一点的类； `tree.facets[].lacks` 说 它的读页没有（而facet没有） `enough`)，以及其每次尝试都标记一个站点的facet。一个 `draft` （`add draft`（JSON项在stdin上）是一个粗略的草案 发现和模式：该研究的草稿门中有一个项目没有提及任何保留或有数字 没有引用过。 `brief.draft` 显示最新的。这永远不是最后的决定。

检查步骤读取本轮保存结果的样本(`budget.checks`，默认为3，或a 保存结果的十分之一，以较多者为准；0为无；分散在文件中)； `check --patterns` 阅读每一个未检查的找到一个模式依赖，针对文本周围的每一个引用。提取门证明引用是 在纸上；检查询问它是否支持句子。失败的发现得到A `check` 记录和挂断电话； `add call <finding> keep` 把它放回去。一次失败伴随着一次补救 适合：一个较窄的句子，同样的引用。修复通过提取门和第二个 检查，然后作为新发现登陆 `fixes` 给旧的命名。审查看到每一个检查和发现 携带其文档的日期，因此评审将时间视为计划文件的时间 `age` 行说。

法官(杰夫，来自 `@wrenautomation/models/judge`)用概率回答输入的问题 也没有短信，所以它不会写电话或支票。 `search` 对每一个新的热门作品都要求它，然后去做 为客户服务，谁写的（客户，或者卖家），什么 类。 `open` 向每个新页面询问它的类。 `check` 问每个不停找的人一句：做什么 引用它，它是否归功于另一个来源。每个答案都是一个 `judge` 记录每一次通话 消费。他们暗示和路线： `brief.hits.uncalled` 按面排序然后法官判罚，然后 显示答案； `documents.unclassed[].guess` 显示它的等级；的一面 `needs` 不是 只要它的保留命中有等级（经纪人的，否则法官的），就足够了，不需要； `patterns[].cites` 列出信任其他来源的发现，供应商重复警告名称 他们。 `check` 阅读样本，再加上每一个法官支持的结果都在0.8以下：法官的回答是“不” 取出一个。 `accept` 在特工自己的酒吧里把提示变成记录，每个都有 法官的号码在它的为什么。 `brief.judge` 计算其呼叫，成本，以及代理和客户的频率 我同意。试验（0.22.0）： `open` 还要求每个页面的 `worth` (你会小心吗？ 研究人员引用它的问题)。 `documents.toExtract[].worth` 显示了它; `brief.judge.worth` 给出了它的AUC，以防止“对它的发现被保留”，以及半门会跳过什么。没有什么 盖茨还在研究。

从0.25.0开始，法官通读整页：正文到参考文献（附录保留） 每个部分有64000个字符，最多4个，每个部分回答最多的是“是”。杰夫的意见是 便宜（每百万代币约0.04美元），所以一张纸的成本约为十分之一美分 标准(`--criterion name="question"`,在 `plan`)是一个人自己的是或否测试 好的来源：法官在每一页每一击中都问了每一个人，并且简报显示了它的几率 在每次击球（发球和测试）中作为提示。他们卑劣的种类 `hits.uncalled` 和 `documents.toExtract`； `brief.judge.criteria` 给出了每个人的AUC “关于它的发现被保留了下来”，在点击和页面上。只是一种暗示，而不是一扇门。

从0.27.0开始，提取器也读取主体（引用列表中没有发现）。每一个评论 查看之前每一轮的新发现和保留的发现，并决定何时停止。一篇论文的 `follow --as refs` 和 `--as citers` 列出它引用了什么和引用了什么。一次检查（25篇论文，参考十四行诗）： 在整个页面上，Jev的标准赔率将十四行诗的“是”与“否”进行排序，AUC为0.94比1.00；在 摘要：0.77 ~ 1.00。

的查询记录 `follow: {url, as, document?}` 和术语 `<as> of <url>`。这个 Fetch步骤将其发送到源 `follows` 需要它, `follow` 列出多达30个，以及 点击经过分类，读取和大写就像搜索一样。每个查询都进入allow列表 就像它写的时候一样：一个来源 `follow --with` 允许加入连接 `opens`，所以它运行 跟随，从不搜索。一个 `person` 在网站上命名一个作者（个人资料url，他们在下面发布的名字）；文件是 当一个帖子从他们的个人资料中找到它时，当它的URL位于个人资料下时，或者 当它的频道（或它的热门频道）是它们的名字之一时。 `brief.people` 计算每个人的 文件、保存的调查结果和地点； `brief.unfollowed` 列表保存了没有后续内容的页面 没有人拥有。

`serve` 将分类帐放在127.0.0.1以供查看者（Wren门户的Research页面）。只读: CLI仍然是唯一的写入器。 `GET /runs` 每次运行给出一行(ask, parent, round, next step， 计数、花)。 `GET /runs/:run` 给出了一个 `RunView` （`v: 1`)：简短，每个查询都有命中 它写了又找，每一击都有它的来源，查询，呼叫和判断，每一页都有它的 阶级，判决和个人，每一个发现及其检查，决定和步骤的时间表结束 每个来源都有自己的理由和花费。 `GET /runs/:run/documents/:doc` 给出页面存储的文本。 `GET /events` 发送 `event: run` 与 `{run}` 每次运行文件更改时，每25秒ping一次； 然后，观众会再次看到这段视频。歌珥的答案 `--origin` （默认情况下是门户）和任何 localhost，并对Chrome的私有网络预飞行表示同意。这些类型生活在 `src/engine/view.ts`； 主机复制它们并进行检查 `v`美国从不进口。

## 图书馆

```ts
import { PoliteFetcher, userAgent } from "@wrenautomation/read/fetch";
import { readPage } from "@wrenautomation/read/text";

const fetcher = new PoliteFetcher(userAgent("you@example.com"));
const res = await fetcher.get(url);
const page = readPage(res.text, res.url);
```

引擎，有你自己的模型和源：

```ts
import { claimExtractor } from "@wrenautomation/birdwatch/document";
import { extract, open, planRound, registry, search } from "@wrenautomation/birdwatch/engine";
import { FilesLedger, ulids } from "@wrenautomation/birdwatch/ledger";
import { exa, fetcherSource } from "@wrenautomation/birdwatch/sources";

const ledger = new FilesLedger("./ledger", "will");
const sources = registry(exa({ keys }), fetcherSource({ fetcher }));
const deps = { sources, ledger, model, extractor: claimExtractor, clock: () => new Date(), ids: ulids(), writer: "will" };
const agent = { from: "ai" as const, by: "my-agent" };
const { run } = await planRound(deps, { ask: { text: "how do staffing firms win repeat clients", kind: "web" }, planFile, model: model.id });
await search(deps, run, [{ terms: "staffing repeat client rate", why: "the ask's words" }], agent);
await open(deps, run, { urls: ["https://a.example/report"], why: "a survey" }, agent);
await extract(deps, run); // findings, each with its proof: a quote on a page the run read
```

具有自己的分类帐、源或模型挂载的主机 相同的命令： `addEngineCommands(program, { ledger, sources, model, extractor })` 从 `@wrenautomation/birdwatch` (雷恩 `research` 命令是这些在Postgres上)。

## 开发

```sh
pnpm install
pnpm lint && pnpm typecheck && pnpm test
```

一、 `v*` 标签向NPM发布(`.github/workflows/release.yml`可信发布：不存储令牌)。

许可证：PolyForm Strict 1.0.0 (`LICENSE.md`）。

## 常见问题

### @wrenautomation/birdwatch 是什么？

从开放的网络上进行研究，由代理驱动，每个命令执行一步：计划，搜索，分类，打开，在报价门后面提取，检查，审查，分类账中的每条记录。代理人决定；发动机按固定的步骤运转。请求和计划文件，文件

### 如何安装 @wrenautomation/birdwatch？

在项目目录运行 npm install @wrenautomation/birdwatch，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 birdwatch，可以用 npx birdwatch 直接运行。

### @wrenautomation/birdwatch 支持 TypeScript 吗？

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

### @wrenautomation/birdwatch 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @wrenautomation/birdwatch 需要什么版本的 Node\.js？

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

### @wrenautomation/birdwatch 可以商用吗？

@wrenautomation/birdwatch 使用 PolyForm-Strict-1\.0\.0 许可。声明的许可为 PolyForm-Strict-1\.0\.0，请阅读许可原文确认使用条件。以上为概括，不构成法律意见，请以许可原文为准。

### @wrenautomation/birdwatch 还在维护吗？

最新版本 0\.30\.6 发布于 2026/11/03（今天）；至今共发布 9 个版本，其中过去 12 个月发布了 9 个；首次发布于 2026/10/30。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

