Skip to content

ci(openwiki): fix provider config + apply openwiki#33 workaround so generation succeeds - #5536

Merged
serrrfirat merged 4 commits into
mainfrom
reborn/openwiki-anthropic-fix
Jul 2, 2026
Merged

serrrfirat merged 4 commits into
mainfrom
reborn/openwiki-anthropic-fix

Conversation

@serrrfirat

Copy link
Copy Markdown
Collaborator

What this fixes

The OpenWiki workflow merged in #5532 never actually generated — it failed on the first file read. This makes it work, and it just produced the first wiki: #5535 (+3,062 lines).

The bug (langchain-ai/openwiki#33)

openwiki's bundled deepagents read-tool maps any unmapped/extensionless file (Makefile, Dockerfile, LICENSE, *.lock, …) to application/octet-stream and sends it as a base64 document content block. The Anthropic Messages API only accepts application/pdf for base64 documents, so the agent 400s on the first such file. (NEAR AI's OpenAI-compatible endpoint rejects the same shape.)

The fix

Three additions to .github/workflows/openwiki-update.yml:

  1. Set OPENWIKI_PROVIDER: anthropic — without it openwiki defaults to OpenRouter (and demanded a key we don't have). Correct model id claude-haiku-4-5 (openwiki's own id, via src/constants.ts), overridable by a model_id dispatch input.
  2. Patch step (openwiki#33 workaround) — rewrite the installed deepagents MIME fallback from octet-stream → text/plain so extensionless text files are inlined as text, not attached as documents.
  3. Strip binary assets from the ephemeral checkout (genuine .png/.pdf/... are also sent as document blocks and only application/pdf is accepted). The real repo is untouched.

Provider stays Anthropic (it was never the problem — auth and generation both work once #33 is patched). Publishing is unchanged: a human-reviewed PR via the GH App, no auto-merge (SOC 2).

Validation

Dispatched from this branch end-to-end: patch ✓, strip ✓, Regenerate wiki ✓ (ran to completion, not the prior 5-second crash), and it opened #5535.

🤖 Generated with Claude Code

serrrfirat and others added 4 commits July 2, 2026 12:47
The first dispatched run failed: openwiki defaults to OpenRouter unless
OPENWIKI_PROVIDER is set, and its Anthropic model ids (src/constants.ts) are
claude-haiku-4-5 / claude-sonnet-5 / claude-opus-4.8 — not the raw API id
claude-sonnet-4-6. Set OPENWIKI_PROVIDER=anthropic, default model claude-haiku-4-5,
and add a model_id dispatch input so the exact id can be tuned without another PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…IBLE_API_KEY

The Anthropic path failed on openwiki's malformed document content block
(400 invalid_request_error, Anthropic-format-specific). Switch to openwiki's
OpenAI provider pointed at NEAR AI's OpenAI-compatible endpoint using the existing
LIVE_OPENAI_COMPATIBLE_API_KEY repo secret (base https://cloud-api.near.ai/v1,
model Qwen/Qwen3.5-122B-A10B) — the same key/host/model live-canary.yml uses.
No new secret needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hing

Root cause was never the Anthropic provider (it authenticated and ran) — openwiki's
read_file tool wraps binary files as media/document content blocks, and it read
tests/fixtures/hello.pdf, producing a document block Anthropic rejects (400,
media_type must be application/pdf). openwiki has no ignore config, so strip
non-text assets from the ephemeral checkout before generating. Revert provider to
Anthropic (ANTHROPIC_API_KEY, claude-haiku-4-5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The recurring Anthropic 400 (document.source.base64.media_type must be
application/pdf) is a known openwiki bug (langchain-ai/openwiki#33): the bundled
deepagents read-tool maps extensionless/unmapped text files (Makefile, Dockerfile,
LICENSE, *.lock) to application/octet-stream and sends them as base64 document
blocks. Apply the issue's confirmed workaround — patch the installed deepagents
bundle's MIME fallback to text/plain — then keep the binary strip for genuine
binaries. Stays on Anthropic (which was never the problem).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5536 July 2, 2026 10:33 Destroyed
@github-actions github-actions Bot added scope: ci CI/CD workflows size: M 50-199 changed lines risk: medium Business logic, config, or moderate-risk modules contributor: core 20+ merged PRs labels Jul 2, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added a workflow dispatch option to choose the OpenWiki model at run time, with a default model preselected.
  • Bug Fixes
    • Improved OpenWiki regeneration reliability by preventing rejected content uploads during workflow runs.
    • Updated the regeneration process to better handle binary assets and avoid failures caused by file-type handling.

Walkthrough

The OpenWiki update workflow gains a model_id workflow_dispatch input (default claude-haiku-4-5) and passes it through as OPENWIKI_MODEL_ID. The regenerate job now sets OPENWIKI_PROVIDER=anthropic, patches deepagents MIME fallback to text/plain, and strips binary assets before running openwiki --update --print.

Changes

OpenWiki Update Workflow

Layer / File(s) Summary
Dispatch input for model selection
.github/workflows/openwiki-update.yml
Adds model_id workflow_dispatch input with default claude-haiku-4-5 and updates comments on provider/model usage.
Anthropic provider wiring and payload mitigation
.github/workflows/openwiki-update.yml
Sets OPENWIKI_PROVIDER=anthropic, sources OPENWIKI_MODEL_ID from dispatch input, patches deepagents MIME fallback to text/plain, and deletes binary assets before openwiki --update --print runs.

Estimated code review effort: 2 (Simple) | ~10 minutes

No sandbox/trust/secrets/egress/migration invariant from CLAUDE.md/AGENTS.md is implicated — this is a CI-only workflow file (YAML), outside Rust review scope. Flagging one CI-specific concern: patching a third-party dependency's (deepagents) MIME fallback in-place via a pre-run step is fragile and untracked — no pinned version/hash check before patching, so upstream changes could silently break or bypass the mitigation. Consider asserting the patch target exists/matches expected content before overwriting.

Poem

A rabbit hopped through YAML fields so wide,
Found octet-stream and cast it aside,
"text/plain," it whispered, "shall be your new name,"
Then swept up the binaries, tidy the same,
Haiku the model, dispatched with pride. 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has useful detail, but it misses several required template sections and headings, including Change Type, Linked Issue, Security Impact, and Rollback Plan. Rewrite it to match the repo template, filling each required section or marking N/A where appropriate, and include Linked Issue and Security Impact.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific and accurately summarizes the workflow/provider fix and the openwiki#33 workaround.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 @.github/workflows/openwiki-update.yml:
- Around line 87-95: The “Strip binary assets openwiki must not attach” step is
filtering by filename extension only, so it misses binary blobs with other or no
extensions. Update the workflow’s find/delete logic to detect and remove
unsupported files by MIME/type content rather than relying on names, while
keeping the existing openwiki asset stripping step structure intact.
- Around line 68-82: The MIME fallback patch in the workflow currently only
emits a warning when it does not apply, but this is the same fallback that can
trigger 400s in the later openwiki run. Update the patch step to fail closed:
after the loop in the openwiki-update workflow, verify the deepagents bundle
under the openwiki node_modules path no longer contains
application/octet-stream, and if the patch count is zero or the old MIME string
still exists, stop the job before the expensive openwiki execution. Use the
existing patch block that touches deepagents bundle files as the location to
enforce this check.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9962a712-1540-4a99-b66d-bacb6451d567

📥 Commits

Reviewing files that changed from the base of the PR and between 0b26d0d and cb20f64.

📒 Files selected for processing (1)
  • .github/workflows/openwiki-update.yml

Comment on lines +68 to +82
- name: Patch deepagents MIME fallback (openwiki#33 workaround)
run: |
B="$(npm root -g)/openwiki/node_modules/deepagents/dist"
patched=0
for f in "$B"/*.js "$B"/*.cjs; do
[ -f "$f" ] || continue
if grep -q 'toLocaleLowerCase()] || "application/octet-stream"' "$f"; then
sed -i 's#toLocaleLowerCase()\] || "application/octet-stream"#toLocaleLowerCase()] || "text/plain"#g' "$f"
patched=$((patched+1))
fi
done
echo "patched ${patched} deepagents bundle file(s): octet-stream -> text/plain"
if [ "${patched}" -eq 0 ]; then
echo "::warning::openwiki#33 patch matched nothing — deepagents bundle layout may have changed; run may 400 on extensionless files"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Fail closed when the MIME patch does not apply.

Line 80 only warns, but Lines 63-67 identify this fallback as the 400 trigger. Verify the bundle no longer contains application/octet-stream, and stop before the expensive openwiki run if it does.

Proposed hardening
           echo "patched ${patched} deepagents bundle file(s): octet-stream -> text/plain"
-          if [ "${patched}" -eq 0 ]; then
-            echo "::warning::openwiki#33 patch matched nothing — deepagents bundle layout may have changed; run may 400 on extensionless files"
+          if grep -RIn 'application/octet-stream' "$B" --include='*.js' --include='*.cjs' 2>/dev/null; then
+            echo "::error::openwiki#33 patch incomplete — deepagents can still emit application/octet-stream"
+            exit 1
+          fi
+          if [ "${patched}" -eq 0 ]; then
+            echo "::notice::openwiki#33 patch matched nothing; no octet-stream fallback remains"
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Patch deepagents MIME fallback (openwiki#33 workaround)
run: |
B="$(npm root -g)/openwiki/node_modules/deepagents/dist"
patched=0
for f in "$B"/*.js "$B"/*.cjs; do
[ -f "$f" ] || continue
if grep -q 'toLocaleLowerCase()] || "application/octet-stream"' "$f"; then
sed -i 's#toLocaleLowerCase()\] || "application/octet-stream"#toLocaleLowerCase()] || "text/plain"#g' "$f"
patched=$((patched+1))
fi
done
echo "patched ${patched} deepagents bundle file(s): octet-stream -> text/plain"
if [ "${patched}" -eq 0 ]; then
echo "::warning::openwiki#33 patch matched nothing — deepagents bundle layout may have changed; run may 400 on extensionless files"
fi
- name: Patch deepagents MIME fallback (openwiki#33 workaround)
run: |
B="$(npm root -g)/openwiki/node_modules/deepagents/dist"
patched=0
for f in "$B"/*.js "$B"/*.cjs; do
[ -f "$f" ] || continue
if grep -q 'toLocaleLowerCase()] || "application/octet-stream"' "$f"; then
sed -i 's#toLocaleLowerCase()\] || "application/octet-stream"`#toLocaleLowerCase`()] || "text/plain"`#g`' "$f"
patched=$((patched+1))
fi
done
echo "patched ${patched} deepagents bundle file(s): octet-stream -> text/plain"
if grep -RIn 'application/octet-stream' "$B" --include='*.js' --include='*.cjs' 2>/dev/null; then
echo "::error::openwiki#33 patch incomplete — deepagents can still emit application/octet-stream"
exit 1
fi
if [ "${patched}" -eq 0 ]; then
echo "::notice::openwiki#33 patch matched nothing; no octet-stream fallback remains"
fi
🤖 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 @.github/workflows/openwiki-update.yml around lines 68 - 82, The MIME
fallback patch in the workflow currently only emits a warning when it does not
apply, but this is the same fallback that can trigger 400s in the later openwiki
run. Update the patch step to fail closed: after the loop in the openwiki-update
workflow, verify the deepagents bundle under the openwiki node_modules path no
longer contains application/octet-stream, and if the patch count is zero or the
old MIME string still exists, stop the job before the expensive openwiki
execution. Use the existing patch block that touches deepagents bundle files as
the location to enforce this check.

Comment on lines +87 to +95
- name: Strip binary assets openwiki must not attach
run: |
find . -type f \( \
-name '*.pdf' -o -name '*.png' -o -name '*.jpg' -o -name '*.jpeg' \
-o -name '*.gif' -o -name '*.webp' -o -name '*.ico' -o -name '*.svg' \
-o -name '*.wasm' -o -name '*.woff' -o -name '*.woff2' -o -name '*.ttf' \
-o -name '*.otf' -o -name '*.gz' -o -name '*.zip' -o -name '*.zst' \
-o -name '*.mp4' -o -name '*.mov' -o -name '*.pdf' \) \
-not -path './.git/*' -delete

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Strip by MIME, not extension.

Lines 89-95 miss binary files with other or no extensions (*.bin, *.db, generated blobs). That leaves the same unsupported-document path open.

Proposed hardening
-          find . -type f \( \
-            -name '*.pdf' -o -name '*.png' -o -name '*.jpg' -o -name '*.jpeg' \
-            -o -name '*.gif' -o -name '*.webp' -o -name '*.ico' -o -name '*.svg' \
-            -o -name '*.wasm' -o -name '*.woff' -o -name '*.woff2' -o -name '*.ttf' \
-            -o -name '*.otf' -o -name '*.gz' -o -name '*.zip' -o -name '*.zst' \
-            -o -name '*.mp4' -o -name '*.mov' -o -name '*.pdf' \) \
-            -not -path './.git/*' -delete
+          find . -type f -not -path './.git/*' -print0 |
+            while IFS= read -r -d '' f; do
+              mime="$(file --brief --mime-type "$f")"
+              case "$mime" in
+                text/*|application/json|application/xml|application/x-yaml|application/toml|application/javascript|application/typescript|application/x-sh|inode/x-empty)
+                  ;;
+                *)
+                  rm -f -- "$f"
+                  ;;
+              esac
+            done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Strip binary assets openwiki must not attach
run: |
find . -type f \( \
-name '*.pdf' -o -name '*.png' -o -name '*.jpg' -o -name '*.jpeg' \
-o -name '*.gif' -o -name '*.webp' -o -name '*.ico' -o -name '*.svg' \
-o -name '*.wasm' -o -name '*.woff' -o -name '*.woff2' -o -name '*.ttf' \
-o -name '*.otf' -o -name '*.gz' -o -name '*.zip' -o -name '*.zst' \
-o -name '*.mp4' -o -name '*.mov' -o -name '*.pdf' \) \
-not -path './.git/*' -delete
- name: Strip binary assets openwiki must not attach
run: |
find . -type f -not -path './.git/*' -print0 |
while IFS= read -r -d '' f; do
mime="$(file --brief --mime-type "$f")"
case "$mime" in
text/*|application/json|application/xml|application/x-yaml|application/toml|application/javascript|application/typescript|application/x-sh|inode/x-empty)
;;
*)
rm -f -- "$f"
;;
esac
done
🤖 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 @.github/workflows/openwiki-update.yml around lines 87 - 95, The “Strip
binary assets openwiki must not attach” step is filtering by filename extension
only, so it misses binary blobs with other or no extensions. Update the
workflow’s find/delete logic to detect and remove unsupported files by MIME/type
content rather than relying on names, while keeping the existing openwiki asset
stripping step structure intact.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ 5 Reborn crate(s) have 0 int-tier coverage (target: 0) — ironclaw_reborn_config, ironclaw_reborn_identity, ironclaw_reborn_traces, ironclaw_webui_v2, ironclaw_webui_v2_static

Reborn integration-tier coverage

Line coverage (Reborn crates): 15.11% — 9538 / 63132 lines

Per-crate breakdown (12 crates, lowest-covered first)
Crate Line % Covered / Total
ironclaw_reborn_config 0% 0 / 1142
ironclaw_reborn_identity 0% 0 / 237
ironclaw_reborn_traces 0% 0 / 6662
ironclaw_webui_v2 0% 0 / 2675
ironclaw_webui_v2_static 0% 0 / 110
ironclaw_reborn_event_store 0.73% 6 / 825
ironclaw_product_adapter_registry 5.62% 25 / 445
ironclaw_product_workflow 6.06% 562 / 9272
ironclaw_product_adapters 12.71% 283 / 2227
ironclaw_reborn_composition 21.77% 6719 / 30858
ironclaw_reborn 22.3% 1932 / 8665
ironclaw_product_context 78.57% 11 / 14

This signal is informational: coverage never gates the PR — not the percentage, not the per-crate holes, not the 0-coverage callout.

@serrrfirat
serrrfirat merged commit 06b5396 into main Jul 2, 2026
35 of 36 checks passed
@serrrfirat
serrrfirat deleted the reborn/openwiki-anthropic-fix branch July 2, 2026 10:46

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-5536 — cb20f644 Deployed Jul 2, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: medium Business logic, config, or moderate-risk modules scope: ci CI/CD workflows size: M 50-199 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant