WordPress 和 WooCommerce
内容同步
一旦插件连接到您的工作区,您需要将 WordPress 内容推送到互客鱼, 以便智能体可以从中检索。插件以两种互补模式同步: 您从设置页面触发的手动批量同步,以及为您选择的帖子/产品类型 在每个 WP 钩子上触发的自动增量。
两种模式在 external_id 上都是幂等的 — 重新运行它们是免费的。
内容源
| WP 实体 | 互客鱼 Source 类型 | External ID 格式 |
|---|---|---|
| 帖子、页面、自定义帖子类型 | wordpress | wp:{post_id} |
| WooCommerce 产品 | woocommerce_products | wc:{product_id} |
| WC 优惠券 | 嵌入在 woocommerce_products source config['coupons'] 中 | — |
每个(智能体、站点主机)一对应一个 Source 行。两种类型共存于同一智能体上 — 帖子回答 FAQ 风格的问题,产品回答 "你有 X 吗" 风格的购物意图。 互客鱼在第一次同步时自动创建每个 Source。
批量同步(手动)
打开 Settings → hukeyu。配置插件后会出现两个按钮:
- Sync posts now — 始终可见。分页遍历您启用的帖子类型的每个
publish状态帖子,每批 HTTP 50 个。 - Sync products now — 仅在 WooCommerce 活动时可见。分页遍历
simple、variable、grouped和external产品,每批 50 个。
点击任一按钮。状态行显示进度和最终计数: "Sync complete. (124 posts, 87 queued, 37 skipped)"。 Skipped 表示内容哈希与之前的同步匹配 — 无需重新嵌入,无 LLM 成本。
可恢复同步(大型站点)
共享主机通常强制执行 30 秒 PHP 执行上限。互客鱼的同步器尊重这一点:
每次传递强制执行 TIME_BUDGET_SECONDS = 20 挂钟保护。
当预算耗尽且还有更多页面要处理时,同步器:
- 将恢复标记持久化为 WP transient:帖子的
hukeyu_post_sync_resume,产品的hukeyu_product_sync_resume。形状:{ "page": 7, "at": 1715472000 }。 - 在同一钩子上调度 30 秒后的 WP-Cron 延续(
hukeyu_run_full_sync_event/hukeyu_run_product_sync_event)。 - 立即返回,响应中包含
more: true、next_page: 7,以便管理员 UI 知道显示 "检测到大型站点,其余部分在后台继续。"
当存在恢复标记时重新运行 "Sync now" 会从上次传递停止的地方继续。 成功完成(没有更多页面)会清除恢复标记。
当块状同步正在进行时,每个 WP 管理员页面都会显示一个柔和通知: "hukeyu is finishing a large-site sync in the background (posts). The widget already works; new content shows up once this completes."
增量同步(自动)
在每个 save_post、wp_trash_post 或
before_delete_post 对于具有 publish 状态的
已选择加入的帖子类型,插件会向互客鱼触发单个增量调用:
| 端点 | 触发器 | Body 形状 |
|---|---|---|
POST /api/v1/wp/posts/changed |
save_post / wp_trash_post / before_delete_post 在已选择加入的帖子类型上。 |
一个帖子负载 + action: "upsert" 或 "delete"。 |
POST /api/v1/wp/products/changed |
woocommerce_new_product、woocommerce_update_product、woocommerce_delete_product、woocommerce_trash_product。 |
一个产品负载 + action: "upsert" 或 "delete"。 |
批量同步使用并行的 /posts/sync 和 /products/sync
端点,每批最多 50 个实体。两个端点的身份验证方式完全相同
(bearer + HMAC)。
内容规范化
插件的 PostContentExtractor 在发送到互客鱼之前为每个帖子解析可见 HTML:
- 页面构建器检测 — 如果帖子由 Elementor、Beaver Builder、Oxygen 或 Bricks 拥有,则调用构建器的原生渲染器而不是
post_content。详见 页面构建器。 - Postdata 准备 — 设置
$GLOBALS['post']+ 调用setup_postdata(),以便第三方the_content过滤器(Yoast、Jetpack、Divi、嵌入)看到有效的$post全局变量。 - 块扩展 —
do_blocks()解析每个 Gutenberg 块。 - 过滤器链 —
apply_filters('the_content', …)运行每个主题/插件钩子(懒加载、图像替换、相关帖子等)。 - 短代码解析 —
do_shortcode()解析任何剩余的短代码。 - 过滤器覆盖 — 最终 HTML 通过您自己的
hukeyu_post_content_html过滤器运行,这使您可以剥离导航 chrome、强制自定义模板或完全短路。见下面的“覆盖同步的 HTML”。 - 清理 —
$GLOBALS['post']在finally块中恢复并调用wp_reset_postdata(),因此抛出过滤器回调不会泄露循环状态。
内容哈希和不变跳过
每次同步(批量或增量)都发送一个 content_hash 字段。
互客鱼将其与现有 Document 的存储哈希进行比较;匹配时服务器立即返回,
无需重新分块或重新嵌入。针对稳定站点重新运行 "Sync now" 实际上是免费的 —
只有差异有成本。
哈希是规范化连接的 SHA-256:
sha256( title + "\n" + content_html + "\n" + excerpt + "\n" + taxonomy_term_names )
在哈希之前,空格通过 preg_replace('/\s+/u', ' ', …)
折叠为单个空格,因此琐碎的重排不会触发重新索引。
每个帖子索引的内容
- 帖子标题(纯文本、实体解码、标签剥离)
- 摘要 — 如果设置了显式帖子摘要,否则为剥离内容的前 40 个单词
- 分类术语名称 — 帖子类型注册的每个分类中的每个术语(类别、标签、自定义分类)
- 主体 HTML — 如上所述完全扩展,服务器剥离标签成块
- 永久链接、帖子类型、修改时间戳、检测到的语言(来自 WP 语言环境)
每个 WooCommerce 产品索引的内容
- 名称、SKU、永久链接、主图像 URL(中等大小)
- 简短描述 + 长描述(Gutenberg 块扩展、短代码解析、应用 the_content 过滤器)
- 价格、regular_price、sale_price、货币、on_sale 标志、stock_status
- 类别名称(通过
product_cat分类) - 属性名称 + 值对展平为
"color: blue, red"字符串,以便嵌入捕获两者 - SHA-256 content_hash + ISO 8601 modified_at
优惠券同步
优惠券随产品同步一起进行。在每次成功的产品同步完成后
(恢复到完成,而不是中途),插件的 CouponSyncer 运行快照:
- 通过
get_posts()枚举最多 50 个shop_coupon自定义帖子类型的发布状态条目 — 这适用于自 WC 2.0 中优惠券发货以来的每个 WooCommerce 版本。(之前插件使用wc_get_coupons(),这不是每个版本的公共 WC API。) - 通过
new WC_Coupon($id)(稳定的 WC 类)水化每个匹配项。 - 过滤掉已过期的优惠券(
get_date_expires()< now)或已超过其使用限制的优惠券。 - 将结果 POST 到
POST /api/v1/wp/coupons/sync。互客鱼将它们持久化在 source 的config['coupons']数组上。
对于每个优惠券,插件发送:code(大写)、
label(人性化:"10% off"、"5 off your order" 等)、
discount、expires_at。
详见 WooCommerce 深度链接
了解 LLM 如何使用这些。
自动切换到电商垂直领域
在针对 site_type 为 generic 的智能体的第一次成功产品 upsert 时,
互客鱼自动将智能体切换到 site_type = "ecommerce"。
这启用了 EcommercePreset 系统提示词片段和
<product/> 内联块发射规则,以便
LLM can recommend products as rich cards instead of plain text.
The switch fires only when site_type is
generic。已经在 saas、documentation 或显式 ecommerce 的智能体永远不会被覆盖。
删除语义
before_delete_post / woocommerce_delete_product
触发单个 delete 增量。互客鱼拆除 Document、其块以及与之关联的向量点。
删除互客鱼从未见过的实体是静默无操作
(HTTP 200,带有 deleted: false),因此重复清理是安全的。
覆盖同步的 HTML
应用您自己的过滤器来修改插件发送到互客鱼的 HTML — 剥离站点标题、强制 Elementor 模板、编辑某一部分等。
add_filter('hukeyu_post_content_html', function ($html, $post, $builder) {
// $builder 是检测到的页面构建器 slug,或者对于普通 Gutenberg 帖子为 null。
// 例如 'elementor'、'divi'、'bricks'。
if ($post->post_type === 'product') {
return $html;
}
// 剥离我们的主题通过 the_content 注入的任何剩余导航 chrome。
// 互客鱼已经进行自己的标签剥离,但在这里做可以减少块开销。
$html = preg_replace('#<nav[^>]*>.*?</nav>#is', '', $html);
return $html;
}, 10, 3);
过滤器在哈希和 POST 之前接收完全渲染的 HTML。
返回 '' 实际上禁用该帖子的同步
(互客鱼将看到空内容并拒绝嵌入任何内容)。
程序化同步(从 PHP)
您可以从自己的代码触发同步 — 对迁移或测试很有用:
// 帖子
$result = (new \hukeyu\Sync\PostSyncer)->runFullSync();
// $result['ok'], $result['posts'], $result['more'], $result['next_page']
// 产品(需要 WooCommerce)
$result = (new \hukeyu\Sync\ProductSyncer)->runFullSync();
// 优惠券
$result = (new \hukeyu\Sync\CouponSyncer)->run();
这些都不会抛出异常 — 它们返回带有 ok 键、
errors 数组的结果数组,以及(对于块状同步器)
用于恢复跟踪的 more + next_page 字段。