@carrot-foundation/ai-发现
人工智能发现原始人为胡萝卜网络: Schema.org JSON-LD 建设者,
llms.txt 人工智能发电机 robots.txt 帮手,马克倒镜路线,
只读 MCP 脚手架、 关键字搜索、 IndexNow 提交助手和 a
公开的docs词汇客户端.
当公共胡萝卜网站或兼容的生态系统工具需要时使用此软件包 向搜索引擎、AI爬行器、LLM客户披露相同内容, 和人类开发者.
状态
释放- 触发合并到 main cI 成功后自动发布, 所以
只有在克里斯蒂亚诺审查过包裹PR和柏油丸后,它们才合并.
安装
pnpm add @carrot-foundation/ai-discovery
# or
npm install @carrot-foundation/ai-discovery
需要节点.js >=22. 一揽子措施为无害环境管理优先,船舶为共同JS双向
仍在使用的消费者的产出 require()。 。 。 .
它提供什么
| 模块 | 导入路径 | 目的 |
|---|---|---|
| JSON-LD( 日语) | @carrot-foundation/ai-discovery/jsonld | 为公共页面构建已验证的 Schema.org 图表节点 . |
| 机器人 | @carrot-foundation/ai-discovery/robots | 生成 robots.txt 对已知的AI bots 的政策. |
| 页:1 | @carrot-foundation/ai-discovery/llms-txt | 生成 /llms.txt 财务报告和审定财务报表 /llms-full.txt 样式 Markdown 文件. |
| 标记下镜像 | @carrot-foundation/ai-discovery/md-mirror | 创建一个 Request -> Response Markdown路由处理器. |
| MCP 服务器 | @carrot-foundation/ai-discovery/mcp-server | 注册只读工具并处理可流式HTTP生命周期. |
| 奥拉马搜索 | @carrot-foundation/ai-discovery/orama | 构建、搜索、序列化并恢复仅关键词索引. |
| 现在索引 | @carrot-foundation/ai-discovery/index-now | 将 URL 批次规范化、 块化、 提交和汇总 . |
| 词汇客户端 | @carrot-foundation/ai-discovery/glossary | 用缓存查询公共胡萝卜 Docs MCP词汇工具. |
| 身份 | @carrot-foundation/ai-discovery/identity | 峡谷胡萝卜 Organization 创建者 Person。 。 。 . |
| 根命名空间 | @carrot-foundation/ai-discovery | 所有模块的命名导出 . |
快速启动
在页面上添加 JSON- LD
import { carrotOrganization } from "@carrot-foundation/ai-discovery/identity";
import {
article,
compose,
website,
} from "@carrot-foundation/ai-discovery/jsonld";
const graph = compose([
carrotOrganization(),
website({
name: "Carrot Documentation",
url: "https://docs.carrot.eco",
inLanguage: ["en", "pt-BR"],
searchUrlTemplate: "https://docs.carrot.eco/search?q={query}",
}),
article({
url: "https://docs.carrot.eco/docs/concepts/dmrv",
headline: "Digital Measurement, Reporting and Verification",
description:
"How Carrot structures source data, evidence, and verification.",
datePublished: "2026-04-15",
dateModified: "2026-05-01",
author: {
name: "Jane Doe",
url: "https://example.com/jane",
},
inLanguage: "en",
image: "https://docs.carrot.eco/og/docs/concepts/dmrv.png",
}),
]);
const jsonLd = JSON.stringify(graph);
渲染器 jsonLd 在一个 application/ld+json 脚本标记. 构建者验证输入
在返回平原对象之前使用 Zod, 所以无效的 URL, 日期, 语言标记,
或缺少所需的字段 .
生成 AI 意识机器人.txt
import { buildRobots } from "@carrot-foundation/ai-discovery/robots";
export function GET() {
return new Response(
buildRobots({
allow: "fetchers-only",
sitemap: "https://docs.carrot.eco/sitemap.xml",
disallowPaths: ["/api/", "/internal/"],
}),
{
headers: {
"content-type": "text/plain; charset=utf-8",
},
},
);
}
allow 支持四种模式:
| 模式 | 行为 |
|---|---|
all-ai-bots | 允许每个已知的AI机器人,每个被明确命名. 内容站点政策. |
fetchers-only | 屏蔽训练爬行者并允许搜索索引和用户获取器. |
block-all-ai | 封锁每个机器人 AI_BOTS;其他爬行者可以留下来. |
disallow-all | 关闭整个网站 每一个爬行者, 对于认证的应用程序. |
输出每瓶有一组,每组以注释为首,在
User-agent: * 组合。 一个爬行者只服从最具体的群体命名它,
这样 disallowPaths 重复每个允许的组. sitemap 可选; 省略
无索引的站点 :
buildRobots({ allow: "disallow-all" });
// User-agent: *
// Disallow: /
// ...one `Disallow: /` group per AI bot intent
无模式名称 Applebot苹果在Spotlight后面的普通爬行者 Siri和
Safari搜索,所以它跟随 User-agent: * 组:仅 disallow-all
从苹果搜索中删除一个站点. 苹果也可能训练其基础模型
在Applebot爬行并用它来解答AI生成的答案。 开除
页:1 Applebot-Extended 符号,作为每个模式,但 all-ai-bots 选择退出
该培训;a nosnippet 元标记保存这些答案的一页
(单位:千美元)苹果公司) (中文(简体) ).
机器人.txt只绑住那些尊重它的爬行者. 抓取者和代理人
用户的请求可能不会, 代理在 AI_AGENTS (谷歌代理公司)
ChatGPT代理)没有机器人代号,因此没有模式命名. disallow-all
无法与 omitWildcard,则未知 allow 数值抛出.
分类人工智能机器人流量
AI_BOTS 列出 AI bots 机器人.txt 可以地址,以及 AI_AGENTS 大赦国际
特工不能这样 两者的条目:
| 外地 | 含义 |
|---|---|
name, (中文(简体) ), operator | 机器人是它的运营商命名它. |
intent | training, (中文(简体) ), search-index, (中文(简体) ), user-fetch, (中文(简体) ), agent,或 ai-browser (单位:千美元)AI_BOT_INTENTS) (中文(简体) ). |
robotsToken | 机器人们.txt User-agent 符号 . AI_BOTS 只有条目. |
userAgentPatterns | 在请求中识别机器人的大小写不敏感子字符串 User-Agent 头曰. |
vercelBotName | Vercel 的价值 bot_name 维度,当Vercel的被验证的机器人目录列出时. |
source | 操作员的文件被核对了. |
仅限机器人控制符号,例如 Google-Extended 财务报告和审定财务报表 Applebot-Extended
有个 robotsToken 但是没有 userAgentPatterns:它们从未出现在请求中.
发送一个股票浏览器用户代理, 如 ChatGPT 代理的代理, 已知
只有通过 vercelBotName. AI 浏览器,如 ChatGPT Atlas 和 迷惑彗星
发送 stock Chromium 用户代理, 因此没有条目可以识别它们 .
import {
classifyUserAgent,
findByVercelBotName,
} from "@carrot-foundation/ai-discovery/robots";
classifyUserAgent(request.headers.get("user-agent"))?.intent;
// "user-fetch" for ChatGPT-User, undefined for a browser
findByVercelBotName("chatgpt-operator")?.intent; // "agent"
两个搜索 AI_BOTS 财务报告和审定财务报表 AI_AGENTS 返回一个 AIRegistryEntry页:1
AIBotEntry 何时 robotsToken 设定, a AIAgentEntry 否则。 缩小它
与 entry.robotsToken !== undefined; 一个 in 检查不缩小。 一个用户
特工是自报的 校验( 已公布的 IP 范围, 逆向 DNS, Web Bot)
在信任它之前,我先说.
1.2起的球场仍保留在每起 AI_BOTS 条目并作折旧:
userAgent 等于 robotsToken,以及 kind 折叠 agent 财务报告和审定财务报表 ai-browser
输入 user-fetch。 。 。 . AI_AGENTS 条目中既没有.
从 1.x 移动
第2版修改了机器人模块:
-
buildRobots()每瓶发出一组 而不是每瓶发出一组. 每个组以一个#注释行和列表数User-agent线条 在其规则之前,如RFC 9309允许:# AI training crawlers User-agent: GPTBot User-agent: ClaudeBot ... Disallow: /在空白行上分割输出并读取一个的代码
User-agent百分比 块断。 测试每个区块的第一行 现在第二行是# AI training crawlers作为用户代理User-agent: GPTBot作为它的规则。 分析组代替: 每组User-agent线条在块中共享遵循的规则。 一个被封锁的团体携带 仅限Disallow: /· ;disallowPaths在允许的组合中重复, 其中 留下每个机器人的有效政策. -
AI_BOTS以意向命令,所以按索引读取条目的代码得到一个 不同的机器人。 查找条目robotsToken换句话说. -
AI_BOTS, (中文(简体) ),AI_AGENTS他们的进入被冻结。 类型脚本已键入 他们readonly在 Java 脚本中,push和其他变异数组方法 丢出一个TypeError; 指定一个字段以严格模式投掷(ES模块,"use strict"),被默默地忽略在草率的剧本中. -
AIBotEntry拥有需要的新字段 :name, (中文(简体) ),intent, (中文(简体) ),robotsToken, (中文(简体) ),userAgentPatterns财务报告和审定财务报表source。构建自己的条目的代码必须设置 他们. -
登记册增加了Amazonbot和Meta-ExternalAgent(培训), Amzn-SearchBot、Meta-WebIndexer和DuckAssistBot(搜索索引),以及 Meta-ExternalFatcher和Amzn-User(用户获取).
fetchers-only现在的块 两个新的训练爬行者,和block-all-ai7个街区. -
buildRobots()丢入未知的allow值,并持续disallow-all结合omitWildcard。 。 。 .RobotsAllowMode收益disallow-all,所以一个 详尽无遗switch因为它需要新的案子. -
没有机器人.txt 令牌(Google-Agent, ChatGPT 代理)的代理被列出于 新建
AI_AGENTS中,没有AI_BOTS。 。 。 . -
userAgent财务报告和审定财务报表kind继续AIBotEntry,以有利于robotsToken财务报告和审定财务报表intent。 。 。 .
构建 llms.txt 文件
import {
buildFull,
buildIndex,
} from "@carrot-foundation/ai-discovery/llms-txt";
const index = buildIndex({
site: {
name: "Carrot Documentation",
url: "https://docs.carrot.eco",
tagline: "The public reference for the Carrot Network.",
},
sections: [
{
title: "Concepts",
urls: [
{
title: "dMRV",
url: "https://docs.carrot.eco/docs/concepts/dmrv",
description:
"Digital Measurement, Reporting and Verification in Carrot.",
},
],
},
],
});
const full = buildFull({
pages: [
{
title: "dMRV",
url: "https://docs.carrot.eco/docs/concepts/dmrv",
markdown: "# dMRV\n\nDigital Measurement, Reporting and Verification.",
},
],
});
buildIndex() 用于压缩的 Markdown 文本和格式
索引文件. buildFull() 以源 URL 注释连接页面
所以LLM客户端可以追踪到每个街区回它的Cononical页面.
显示 Markdown 镜像路由
import { createMdMirrorRoute } from "@carrot-foundation/ai-discovery/md-mirror";
export const GET = createMdMirrorRoute<{ slug?: string[] }>({
async load({ params }) {
const slug = params.slug?.join("/") ?? "index";
const page = await loadPageAsMarkdown(slug);
if (page === null) return null;
return {
markdown: page.markdown,
sourceUrl: `https://docs.carrot.eco/docs/${slug}`,
};
},
});
路径帮助返回 404 何时 load() 返回时 null,否则服务
text/markdown; charset=utf-8组合 x-source-url,并应用缓存控制
头曰. 默认缓存策略是 public, max-age=300, s-maxage=86400。 。 。 .
在犬科URL上为Markdown服务
prefersMarkdown(accept) 阅读请求 Accept 标题并决定是否
cononial URL 使用页面的 Markdown 而不是它的 HTML 回答 :
import { prefersMarkdown } from "@carrot-foundation/ai-discovery/md-mirror";
prefersMarkdown("text/markdown"); // true
prefersMarkdown("text/markdown, text/html;q=0.9"); // true
prefersMarkdown("text/markdown, */*"); // true: named beats a wildcard
prefersMarkdown("text/html, text/markdown"); // false: a named tie keeps HTML
prefersMarkdown("*/*"); // false
prefersMarkdown(null); // false
它尊重q值,让最具体的媒体范围取胜. 马克倒数取胜
何时 text/markdown 重过重 text/html同等重量
0以上,名称范围 text/markdown 击出 text/html 仅匹配
结束 text/* 或者说 */*这样 text/markdown, */* 得到马克德。 相同重量
当两者均被命名时,或当两者单独通过通配符匹配时,保留 HTML。 A 类
标出 0 的下方重, 带有任何畸形区域或缺少标题的页眉
保留 HTML 。 仅在类型和子类型上匹配的范围:参数
q 被忽略,所以 text/markdown;profile=x 计数为 text/markdown他们必须
仍然身材不错 name=value 双对,所以 text/markdown;foo 错误
并保留 HTML。 信头读取为发送: 类型和子类型取 ASCII 令牌
只匹配 A- Z 上的不区分大小写, 只匹配空格和标签
计为白空格,所以一个未破解的空格或开尔文符号是错的
保留 HTML。 发送 Vary: Accept 取决于它的反应.
胡萝卜在各地都一样
这个 identity 每个胡萝卜网站都声称:
import {
CARROT_ORGANIZATION,
carrotOrganization,
} from "@carrot-foundation/ai-discovery/identity";
import { compose, website } from "@carrot-foundation/ai-discovery/jsonld";
import { buildIndex } from "@carrot-foundation/ai-discovery/llms-txt";
const graph = compose([
carrotOrganization(),
website({
name: "Carrot Documentation",
url: "https://docs.carrot.eco",
inLanguage: ["en", "pt-BR"],
}),
]);
const index = buildIndex({
site: {
name: CARROT_ORGANIZATION.name,
url: "https://docs.carrot.eco",
tagline: CARROT_ORGANIZATION.description,
},
sections: [],
});
carrotOrganization() 返回时 Organization 节点: 名称 Carrot备注
名称 Carrot Foundation一个标志,胡萝卜自己的简介 sameAs,则
@id 胡萝卜网站已经出版。 其创始人伊恩·麦基被嵌入了
Person (单位:千美元)carrotFounder()上面有他的个人资料.
注册只读 MCP 工具
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { registerReadOnlyTool } from "@carrot-foundation/ai-discovery/mcp-server";
const server = new McpServer({ name: "carrot-docs", version: "1.0.0" });
registerReadOnlyTool(server, {
name: "search_docs",
title: "Search docs",
description: "Search public Carrot documentation.",
inputSchema: {
query: z.string(),
},
handler: (input) => ({
results: searchPublicDocs(input.query),
}),
});
registerReadOnlyTool() 对每个工具应用相同的安全说明:
readOnlyHint: true, (中文(简体) ), destructiveHint: false, (中文(简体) ), idempotentHint: true,以及
openWorldHint: false。 。 。 . createMcpHttpHandler() 提供通用流程
HTTP 请求使用应用提供的速率键的生命周期,主机的遥测,以及
工具名允许列表如此原始的正文, 原始的 IP 密钥, 信头, 以及快速文本
文库不释放.
构建关键词搜索索引
import {
buildSearchIndex,
searchIndex,
serializeSearchIndex,
} from "@carrot-foundation/ai-discovery/orama";
const index = await buildSearchIndex([
{
id: "en/blog/massid",
title: "MassID launch",
url: "https://www.carrot.eco/en/blog/massid",
text: "MassID traceability for circular economy data.",
locale: "en",
kind: "post",
},
]);
const results = await searchIndex(index, { query: "massid", limit: 5 });
const serialized = serializeSearchIndex(index);
Orama 包装器只在 1.1.0嵌入和交叉财产
联邦有意留待以后阶段.
提交索引现在 URL 批次
import {
chunkIndexNowUrls,
formatGitHubActionsSummary,
submitIndexNowUrls,
} from "@carrot-foundation/ai-discovery/index-now";
const urls = [
"https://www.carrot.eco/en",
"https://www.carrot.eco/en/blog/massid",
];
const indexNowKey = process.env.INDEXNOW_KEY;
if (!indexNowKey) {
throw new Error("INDEXNOW_KEY is required");
}
for (const batch of chunkIndexNowUrls(urls)) {
const result = await submitIndexNowUrls({
host: "www.carrot.eco",
key: indexNowKey,
keyLocation: "https://www.carrot.eco/indexnow-key.txt",
urls: batch,
fetch,
});
console.log(formatGitHubActionsSummary(result));
}
normalizeIndexNowUrls() 在所配置的主机下只保留唯一 HTTPS URL .
非-2xx响应返回打入的失败,但不包括原始响应机构.
设定 INDEXNOW_KEY 打电话前 submitIndexNowUrls()。 。 。 .
查询公共文件词汇表 MCP
import {
createDocsGlossaryClient,
createMemoryGlossaryCache,
getGlossaryTerm,
} from "@carrot-foundation/ai-discovery/glossary";
const glossary = createDocsGlossaryClient({
endpoint: "https://docs.carrot.eco/mcp",
fetch,
cache: createMemoryGlossaryCache({ ttlMs: 60_000 }),
});
const trc = await getGlossaryTerm(glossary, { term: "TRC", locale: "en" });
术语表客户端是针对公众的 get_glossary_term 工具。 没有
Authorization 默认标题和缓存
提供了缓存.
JSON-LD 构建器
JSON-LD模块输出用于公共页面类型胡萝卜站点的构建器 最常见的情况是:
| 构建器 | Schema.org 节点 |
|---|---|
apiReference() | APIReference 带有 WebAPI 目标. |
article() | BlogPosting, (中文(简体) ), Article, (中文(简体) ), TechArticle,或 HowTo。 。 。 . |
breadcrumbList() | BreadcrumbList。 。 。 . |
definedTerm() | DefinedTerm。 。 。 . |
definedTermSet() | DefinedTermSet。 。 。 . |
faqPage() | FAQPage。 。 。 . |
organization() | Organization,可选 alternateName 财务报告和审定财务报表 founder。 。 。 . |
person() | Person,带有可选稳定 id。 。 。 . |
podcastEpisode() | PodcastEpisode,带有可选媒体和平台链接. |
podcastSeries() | PodcastSeries,有可选的网络反馈和平台链接. |
speakable() | SpeakableSpecification。 。 。 . |
website() | WebSite,可选 SearchAction。 。 。 . |
使用 compose(nodes) 用于条形输出形状:
{
"@context": "https://schema.org",
"@graph": []
}
使用 schemaId(siteOrigin, kind, payload?) 当你需要决定 @id
自定义节点的值.
设计原则
- 建设者是纯. 它们返回字符串或平庸对象而不执行 我/欧.
- 验证通过Zod schemas在边界上发生.
- 缺席时省略可选字段,而不是设置为
undefined。 。 。 . - AI bot政策是明确的,并产生于一个经过审查的清单.
- Markdown 输出保留了可追溯性源 URL.
- 每个顶级模块可作为小消费者的子路径输出 捆绑.
项目结构
src/
index.ts # Root namespaced exports
jsonld/ # Schema.org JSON-LD builders and validation helpers
robots/ # AI bot registry and robots.txt builder
llms-txt/ # llms.txt index and full-content builders
md-mirror/ # Request -> Response Markdown route helper
mcp-server/ # Read-only MCP registration and HTTP lifecycle helpers
orama/ # Keyword search index helpers
index-now/ # IndexNow URL normalization and submission helpers
glossary/ # Carrot Docs glossary MCP client
identity/ # Canonical Carrot Organization and founder
test/
jsonld/
robots/
llms-txt/
md-mirror/
mcp-server/
orama/
index-now/
glossary/
identity/
新增顶级模块时, 保持公用表面同步 :
- 添加导入并需要成对到
package.jsonexports。 。 。 . - 将模块条目添加到
tsup.config.ts。 。 。 . - 添加名称空格再导出到
src/index.ts。 。 。 . - 镜像测试
test/<module>/。 。 。 .
发展
pnpm install --frozen-lockfile
pnpm test
pnpm build
pnpm type-check
pnpm lint
pnpm format:check
pnpm spell-check
pnpm check
pnpm check 是完整的本地门和镜像 CI:格式、线条、类型检查,
拼写检查、测试、构建、出口类型检查、干洗包装和生产
审计.
有用的焦点命令 :
pnpm vitest run test/jsonld/article.test.ts
pnpm vitest -t "robots"
pnpm check-types-exports
pnpm pack --dry-run
释放
释放是自动的,语义上从 main 之后 Check Code
工作流程成功推动. 手动 workflow_dispatch 保存为回收
路径.
不要颠倒 version 手动. 留下来 0.0.0-development; 语义释放
确定从常规委员会发布的版本.
相关胡萝卜项目
@carrot-foundation/schemas为胡萝卜提供Zod验证计划并生成 JSON Schemas 元数据.carrot-foundation/methodology-rules为Carrot dMRV管道提供开源规则处理器.- 胡萝卜文档 用于公开引用 胡萝卜概念、方法和综合指南.
许可证
Apache 许可证 2.0。见 通知 为归属, 商标和保函.