fix(ci): unblock the feature-docs generator (76 consecutive failures) - #80
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe feature-generation pipeline normalizes rendered content, preserves schema dates, synchronizes navigation labels, handles failed detail fetches safely, and uses explicit pull-request authentication. ChangesFeature generation pipeline
Estimated code review effort: 4 (Complex) | ~40 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/generate_features.py (1)
505-508: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDo not assign today’s publication date to an existing partially dated page.
If an existing page has
dateModifiedbut nodatePublished, Line 507 assigns today, despite the requirement that only new pages receive current dates. Resolve partial pairs before using the new-page fallback.Proposed fix
- date_published = date_published or today - date_modified = date_modified or date_published + if not date_published and not date_modified: + date_published = date_modified = today + elif not date_published: + date_published = date_modified + elif not date_modified: + date_modified = date_published🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/generate_features.py` around lines 505 - 508, Update the date initialization flow around _existing_schema_dates so an existing page with only dateModified receives a resolved publication date before applying the today fallback. Reserve today’s date for genuinely new pages, while preserving the existing datePublished/dateModified values and ensuring the final pair remains consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/generate_features.py`:
- Around line 132-140: Update _render_techarticle_schema() to pass the value
returned by feature_section_name() through _js_str() before inserting it into
the raw articleSection attribute, matching the existing title and description
escaping while preserving the shared section-name source.
---
Outside diff comments:
In `@scripts/generate_features.py`:
- Around line 505-508: Update the date initialization flow around
_existing_schema_dates so an existing page with only dateModified receives a
resolved publication date before applying the today fallback. Reserve today’s
date for genuinely new pages, while preserving the existing
datePublished/dateModified values and ensuring the final pair remains
consistent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 05427e35-cfb9-44b2-b566-164d42632a7a
📒 Files selected for processing (1)
scripts/generate_features.py
Regenerated on top of the generator fixes in #80: - image/generation: reference_images type is now escaped as `array[file_input \| object]`. The unescaped pipe was splitting the cell, so Required rendered as "object]" and the description was dropped. - web/* (7 pages): articleSection "Expert Models" -> "Web Features", about "AI API" -> "Web Data API", keywords now web scraping / web search. Nav icon cube -> globe. - video/* (2 pages): articleSection "Video Generation Features" -> "Video Features", matching the nav label; keywords gain "video analysis" so the deepfake page is not tagged as generation. Also picks up upstream API drift since the previous commit: 18 output-schema rows disappeared from four web pages (html, screenshot, structured_data, metadata on scraping / crawl-async / batch-scrape-async; six fields on search). /v3/info now advertises 13 output fields for web/scraping where it advertised 17 an hour ago, consistently across repeated calls. Worth confirming that firecrawl really dropped them rather than this being an in-flight deploy.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/generate_features.py`:
- Around line 777-792: Update the error handling around fetch_subfeature_detail
to catch only its documented transport/response exception types, allowing
programming errors and malformed-response failures to propagate instead of
reaching the stale-page continue path. Preserve the existing behavior for
handled fetch failures, and add exception chaining with from e when raising
SystemExit on the no-existing-page abort path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 781792fc-3a95-4fe0-b8f4-5602dff173ef
📒 Files selected for processing (1)
scripts/generate_features.py
7ba8aa9 to
a0dcc84
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/generate_features.py (1)
197-197: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueAlias lookup is exact-match only.
"Seconde"or" seconde"from the API bypasses normalization. A normalized key lookup is cheap insurance.♻️ Proposed tweak
- unit_type = _UNIT_ALIASES.get(unit_type, unit_type) + unit_type = _UNIT_ALIASES.get(unit_type.strip().lower(), unit_type)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/generate_features.py` at line 197, Update the alias lookup in the unit normalization flow to normalize unit_type before querying _UNIT_ALIASES, including trimming surrounding whitespace and applying the existing case-normalization convention. Preserve the current fallback behavior when no alias matches.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@scripts/generate_features.py`:
- Line 197: Update the alias lookup in the unit normalization flow to normalize
unit_type before querying _UNIT_ALIASES, including trimming surrounding
whitespace and applying the existing case-normalization convention. Preserve the
current fallback behavior when no alias matches.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f2a024cb-2db3-48bf-9a56-e42a32016bd9
📒 Files selected for processing (2)
.github/workflows/generate-features.ymlscripts/generate_features.py
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/generate-features.yml
Regenerated from current main with the generator fixes in #80. Rebuilt on top of main (which now carries the hand-committed web pages from #83) rather than rebased, so there are no conflict artifacts and the diff is exactly what the pipeline produces from today's API. Pricing (provider rows 195 -> 225): - 16 corrected prices, incl. image/generation/openai $0.08 -> $0.034, ocr/financial_parser/veryfi $0.08 -> $0.16, video bytedance $1.8/1M tokens -> $0.05/second, NER openai $40/1M chars -> $10/1M tokens - 33 new provider rows (Google Imagen, gpt-image-*, sora-2-pro, pixverse) - 3 rows dropped for retired models (dall-e-2, dall-e-3, seedance-1-0-lite) - 14 units corrected from "seconde" to "second" Pages: - new: image/face-recognition, video/deepfake-detection-async - features/index.mdx gains the Web section. #83 added the web pages and their nav by hand but did not regenerate the index, so the feature index in prod has no Web cards at all. - two broken tables repaired: the tts `voice` row and explicit_content `subcategory` row had embedded newlines that ended the table early and spilled ~30 lines of prose into the page body. - image/generation reference_images type escaped as `array[file_input \| object]` Metadata: web/* and video/* articleSection now match their nav group, with per-category about/keywords instead of the generic fallback. Nav: Web Features moves into API order, face-recognition and deepfake-detection-async added, "Video Generation Features" -> "Video Features". Quick Start examples for image ai_detection and deepfake_detection now use resemble, which the API returns first for those subfeatures. No dateModified edits — update-dates.yml owns those. Verified: 1,070 table rows across 36 pages, zero malformed.
All four from CodeRabbit on #80; the first two are regressions from the earlier commits in this PR. - Escape articleSection. Deriving it from the API replaced a hardcoded literal with attacker-adjacent data written straight into articleSection="...", so a quote in a category name would end the attribute and break the MDX. Render it through _js_str() as a template literal, like title/description/about. Verified quotes, backticks, ${ and backslashes all come out inert. - Don't stamp today's date on an existing page that has dateModified but no datePublished; that dated publication after modification. Fall back to the page's own dateModified. - Only swallow fetch failures. The keep-the-old-page path caught bare Exception, so a bug in this script or a malformed response would be reported as a successful run with a stale page. Restrict to URLError / TimeoutError / JSONDecodeError and chain the abort with `from e`. - Normalise unit_type before the alias lookup, so " Seconde " and "SECONDE" resolve like "seconde" instead of reaching the output raw. Verified: 1,070 table rows across 36 pages still well-formed, zero date churn, a simulated TypeError now propagates while a URLError still preserves the page.
The generate-features workflow has failed on every run since 2026-05-12
(76 consecutive failures). Generation itself succeeds; the create-pull-request
step is what fails, because it force-pushes as github-actions[bot] (Write role)
and the agent-block ruleset rejects create/update/force-push on every ref
outside refs/heads/edenai-assistant/**:
remote: error: GH013: Repository rule violations found
remote: - Cannot force-push to this branch
remote: - Cannot update this protected ref
Same failure and same fix as update-dates.yml (#50), which was never applied
here. Falls back to GITHUB_TOKEN so the step still runs without the secret.
The generator wrote a fixed dateModified="2026-05-06" into every page it produced, so each run reset the value that update-dates.yml had bumped. PR #13 shows the effect: 24 of its 27 files change nothing except dateModified going backwards from 2026-05-07 to 2026-05-06. Read both dates back off the existing page and reuse them; only a page that does not exist yet gets today's date. dateModified stays owned by update-dates.yml, which bumps it when content actually changes. Verified against the live API: regenerating all 36 pages now produces zero date-only diffs.
update_docs_json walked navigation → V3 → tab "V3 Documentation" → group "V3 Documentation" → pages, looking for a nested "Expert Models" dict. But "Expert Models" is a sibling top-level group of "V3 Documentation", not a child of it, so the loop matched nothing and the function silently no-opped. New feature pages were written to disk and never added to the nav. Against the live API that currently hides 10 pages: web/ (7 firecrawl subfeatures), image/face-recognition and video/deepfake-detection-async. Search the V3 tabs for the group instead of assuming a fixed depth, and exit non-zero if it is missing — quietly skipping the update is what hid this. The legacy "AI Features" removal stays scoped to the V3 Documentation group so the V3 API Reference tab keeps its own "AI Features" group.
The /v3/info API returns some price units as "seconde", which flowed verbatim
into published pricing tables ("$0.05 per seconde"). Currently affects 13 rows
across the video pages.
An unescaped pipe in a cell value ends the cell early and shifts every later column left, silently corrupting the row. The API now returns a union type for image/generation: `array[file_input | object]`, which rendered as Type=`array[file_input`, Required=`object]`, Description=`No`, with the real description pushed into a phantom fifth column that renderers drop. Escape cell values in both the schema and provider tables.
The nav group title was derived from the API while the JSON-LD articleSection was hardcoded in _FEATURE_SCHEMA_META, so the two drifted. video's nav label became "Video Features" as soon as it gained a second subfeature, while its pages still declared articleSection "Video Generation Features" and keyword "video generation" — wrong for deepfake detection. A brand-new category hit the same gap from the other side: web had no entry at all, so its 7 pages fell back to generic metadata and a "cube" icon. feature_section_name() is now the single source of truth for both the nav group and articleSection, so they cannot diverge and a new category needs no entry to be labelled correctly. _FEATURE_SCHEMA_META keeps only `about` and `keywords`, which have no counterpart in /v3/info (per category it exposes just name, fullname — a repeat of name — description, and subfeatures), plus a `web` entry and a globe icon. Verified: articleSection matches the nav group for all 7 categories.
Found by auditing every live schema plus a synthetic new-category run.
1. Collapse whitespace in table cells. A newline in a cell value terminates the
row mid-sentence and ends the table, spilling the remainder into the page as
loose prose. Two live descriptions do this today, so main is publishing two
broken tables right now: the tts `voice` field and explicit_content
`subcategory`. _cell() now collapses whitespace runs before escaping pipes.
2. Never overwrite a good page with a gutted one. A failed detail fetch left
detail={}, which renders "_No schema information available._" and drops both
schema tables — so one transient 5xx during the daily run would open a PR
that silently strips documentation. Now the existing page is kept, and if
there is no page to keep the run aborts instead of publishing an empty one.
3. Don't double the plural when the API already sends one: a unit_type of
"tokens" rendered as "per 1,000 tokenss". Latent today (every live unit is
singular), but the next new unit would hit it.
Verified: 1,070 table rows across 36 pages, zero malformed. A synthetic unknown
category generates pages, derives articleSection, lands in the nav with the
fallback icon, and escapes pipes in provider labels; simulated API failures
preserve or abort as intended; a removed subfeature is cleaned from disk and nav.
All four from CodeRabbit on #80; the first two are regressions from the earlier commits in this PR. - Escape articleSection. Deriving it from the API replaced a hardcoded literal with attacker-adjacent data written straight into articleSection="...", so a quote in a category name would end the attribute and break the MDX. Render it through _js_str() as a template literal, like title/description/about. Verified quotes, backticks, ${ and backslashes all come out inert. - Don't stamp today's date on an existing page that has dateModified but no datePublished; that dated publication after modification. Fall back to the page's own dateModified. - Only swallow fetch failures. The keep-the-old-page path caught bare Exception, so a bug in this script or a malformed response would be reported as a successful run with a stale page. Restrict to URLError / TimeoutError / JSONDecodeError and chain the abort with `from e`. - Normalise unit_type before the alias lookup, so " Seconde " and "SECONDE" resolve like "seconde" instead of reaching the output raw. Verified: 1,070 table rows across 36 pages still well-formed, zero date churn, a simulated TypeError now propagates while a URLError still preserves the page.
67c8bc6 to
a4dabfa
Compare
Regenerated from current main with the generator fixes in #80. Pricing (provider rows 195 -> 225): - 16 corrected prices, incl. image/generation/openai $0.08 -> $0.034, ocr/financial_parser/veryfi $0.08 -> $0.16, video bytedance $1.8/1M tokens -> $0.05/second, NER openai $40/1M chars -> $10/1M tokens - 33 new provider rows (Google Imagen, gpt-image-*, sora-2-pro, pixverse) - 3 rows dropped for retired models (dall-e-2, dall-e-3, seedance-1-0-lite) - 14 units corrected from "seconde" to "second" Pages: - new: image/face-recognition, video/deepfake-detection-async - features/index.mdx gains the Web section; #83 added the web pages and nav by hand without regenerating the index, so prod has no Web cards - two broken tables repaired: the tts `voice` and explicit_content `subcategory` rows had newlines that ended the table early - image/generation reference_images escaped as `array[file_input \| object]` Metadata: articleSection is now a JSX template literal on all 36 pages and matches each page's nav group; web/* and video/* get real about/keywords. Nav: Web Features moves into API order, the two new pages are added, "Video Generation Features" -> "Video Features". Verified: 1,070 table rows, zero malformed, zero date churn.
Why
generate-features.ymlhas failed on every run since 2026-05-12 — 76 consecutive failures. The feature pricing tables have not been refreshed in ~2.5 months. This PR fixes the pipeline; it deliberately contains no regenerated content, so the next scheduled run opens that as its own reviewable PR.Opened while reviewing #13, which should be closed rather than merged — see below.
What's broken
1. The PR step can't push. Generation succeeds;
create-pull-requestfails:It force-pushes as
github-actions[bot](Write role), and theagent-blockruleset blockscreation/update/non_fast_forwardon every ref outsiderefs/heads/edenai-assistant/**, bypassable only by OrganizationAdmin or Triage/Maintain/Admin. Identical to the failure #50 fixed forupdate-dates.yml— the token was just never added here.2.
dateModifiedwas hardcoded. Every generated page got a fixed2026-05-06, resetting whateverupdate-dates.ymlhad bumped. 24 of #13's 27 files change nothing else:dateModifiedmoving backwards from2026-05-07to2026-05-06.3.
update_docs_jsonsilently no-opped. It walkedV3 Documentationtab →V3 Documentationgroup →pages, looking for a nestedExpert Modelsdict.Expert Modelsis a sibling top-level group, not a child, so nothing matched. New pages were written to disk and never added to the nav — currently hiding 10 pages:web/(7 firecrawl subfeatures),image/face-recognition,video/deepfake-detection-async.4. Cosmetic: the API returns
"seconde", which reached published tables as$0.05 per seconde(13 rows).Changes
995aab6token: ${{ secrets.DOCS_BOT_PAT || secrets.GITHUB_TOKEN }}on the PR step3f094c0datePublished/dateModifiedoff the existing page; only new pages get today's date152a9c7Expert Modelsgroup by search; exit non-zero if absent instead of no-oppingf76dd83Verification
Ran the generator against live
/v3/infofrom the committed state:Web Features(7),Image Features10 → 11,Video Features1 → 2; the API Reference tab keeps its ownAI FeaturesgroupdatePublished/dateModifiedof todayper seconde→per secondWhy #13 should be closed, not merged
Its branch head is from 2026-05-08, 79 commits behind. Checking its 8 price edits against the API today: it fixes 2 (Leonardo Vision XL → $0.014, veryfi → $0.16), breaks 3 (leonardo default and AlbedoBase XL are still $0.017; Phoenix is still $0.014), and 3 are already stale again (
image/generation/openaiis $0.034, not its $0.018; bytedance video is $0.05/second, not its $0.4/request;dall-e-2no longer exists in the API). Plus the 24 backwards dates.Real drift a fresh run will close: 16 wrong prices, 3 rows for removed models, 37 models missing entirely (all Google Imagen, the
gpt-image-*family,sora-2-pro, pixverse, and the wholeweb/category).Deploy notes
DOCS_BOT_PATalready exists (added in fix(ci): push date-bump commits via a bypass-eligible PAT #50) — please confirm it's visible to this workflow.auto/update-feature-docsbranch so the next run starts clean, then trigger the workflow manually rather than waiting for 06:00 UTC.test-snippets.ymlhas never exercised; expect to fix snippets there, not here.Summary by CodeRabbit
datePublished/dateModifiedwhen regenerating TechArticle schemas; added safe UTC defaults for new pages.