From 47d2cc6587dc3755d79359457908f4c27c8d5710 Mon Sep 17 00:00:00 2001 From: Lawrence Lane Date: Thu, 7 May 2026 14:28:51 -0400 Subject: [PATCH 1/3] fix(docs): shrink inline base64 images in notebook HTML outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The image notebooks (5, 6) emit `IPython.display.HTML` blocks containing inline `data:image/png;base64,...` URIs to render side-by-side image grids. Those bypassed the existing `image/png` MIME shrinker and shipped multi-MB strings through the `text/html` branch, producing 1.8 MB and 4.6 MB .ts modules. Fern's hosted SSR bundler couldn't render the version, taking every page down with a Server Components error. Add `shrink_inline_b64_in_html()` so the html branch resizes embedded base64 images through the same 800px JPEG q=82 path the standalone image branch already uses. Apply in-place to the committed bundles: notebook 5 1.8 MB → 423 KB, notebook 6 4.6 MB → 1.3 MB. Other outputs preserved. Signed-off-by: Lawrence Lane --- .../notebooks/5-generating-images.json | 2 +- .../notebooks/5-generating-images.ts | 2 +- .../6-editing-images-with-image-context.json | 4 +-- .../6-editing-images-with-image-context.ts | 4 +-- fern/scripts/ipynb-to-fern-json.py | 25 +++++++++++++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/fern/components/notebooks/5-generating-images.json b/fern/components/notebooks/5-generating-images.json index 2bee94def..328a38619 100644 --- a/fern/components/notebooks/5-generating-images.json +++ b/fern/components/notebooks/5-generating-images.json @@ -304,7 +304,7 @@ }, { "type": "text", - "data": "\n
\n
🖼️ generated_image[0]
\n \n
\n ", + "data": "\n
\n
🖼️ generated_image[0]
\n \n
\n ", "format": "html" } ] diff --git a/fern/components/notebooks/5-generating-images.ts b/fern/components/notebooks/5-generating-images.ts index 3fbeb93b9..e657d5d22 100644 --- a/fern/components/notebooks/5-generating-images.ts +++ b/fern/components/notebooks/5-generating-images.ts @@ -304,7 +304,7 @@ export default { cells: [ }, { "type": "text", - "data": "\n
\n
🖼️ generated_image[0]
\n \n
\n ", + "data": "\n
\n
🖼️ generated_image[0]
\n \n
\n ", "format": "html" } ] diff --git a/fern/components/notebooks/6-editing-images-with-image-context.json b/fern/components/notebooks/6-editing-images-with-image-context.json index 0d142636d..53687ae56 100644 --- a/fern/components/notebooks/6-editing-images-with-image-context.json +++ b/fern/components/notebooks/6-editing-images-with-image-context.json @@ -364,12 +364,12 @@ }, { "type": "text", - "data": "\n
\n
🖼️ animal_portrait[0]
\n \n
\n ", + "data": "\n
\n
🖼️ animal_portrait[0]
\n \n
\n ", "format": "html" }, { "type": "text", - "data": "\n
\n
🖼️ edited_portrait[0]
\n \n
\n ", + "data": "\n
\n
🖼️ edited_portrait[0]
\n \n
\n ", "format": "html" } ] diff --git a/fern/components/notebooks/6-editing-images-with-image-context.ts b/fern/components/notebooks/6-editing-images-with-image-context.ts index 38346490d..74841a09c 100644 --- a/fern/components/notebooks/6-editing-images-with-image-context.ts +++ b/fern/components/notebooks/6-editing-images-with-image-context.ts @@ -364,12 +364,12 @@ export default { cells: [ }, { "type": "text", - "data": "\n
\n
🖼️ animal_portrait[0]
\n \n
\n ", + "data": "\n
\n
🖼️ animal_portrait[0]
\n \n
\n ", "format": "html" }, { "type": "text", - "data": "\n
\n
🖼️ edited_portrait[0]
\n \n
\n ", + "data": "\n
\n
🖼️ edited_portrait[0]
\n \n
\n ", "format": "html" } ] diff --git a/fern/scripts/ipynb-to-fern-json.py b/fern/scripts/ipynb-to-fern-json.py index fd8f876b9..95055e542 100755 --- a/fern/scripts/ipynb-to-fern-json.py +++ b/fern/scripts/ipynb-to-fern-json.py @@ -56,6 +56,16 @@ re.IGNORECASE, ) +# Inline base64 PNG/JPEG embedded in IPython.display.HTML blobs. The image +# notebooks (5, 6) emit `` inside HTML +# outputs, which bypasses the `image/png` MIME path and so skips +# shrink_image_b64 — leaving multi-MB images in the .ts payload and breaking +# Fern's SSR bundler. Match here so the HTML branch can shrink them too. +INLINE_DATA_URI_RE = re.compile( + r"data:image/(png|jpe?g);base64,([A-Za-z0-9+/=\s]+?)(?=[\"'\s)])", + re.IGNORECASE, +) + def get_language(metadata: dict) -> str: info = metadata.get("kernelspec", {}) or {} @@ -112,6 +122,20 @@ def shrink_image_b64(b64: str, max_dim: int = MAX_IMAGE_DIMENSION) -> tuple[str, return b64, "image/png" +def shrink_inline_b64_in_html(html: str) -> str: + """Replace each inline `data:image/...;base64,...` URI inside an HTML string + with a shrunk JPEG variant. IPython.display.HTML outputs in the image + notebooks embed full-resolution PNGs this way; without resizing, a single + cell can carry 2MB+ of base64.""" + + def _sub(match: re.Match[str]) -> str: + b64 = "".join(match.group(2).split()) + shrunk, mime = shrink_image_b64(b64) + return f"data:{mime};base64,{shrunk}" + + return INLINE_DATA_URI_RE.sub(_sub, html) + + def extract_outputs(outputs: list) -> list[dict]: result: list[dict] = [] for out in outputs: @@ -133,6 +157,7 @@ def extract_outputs(outputs: list) -> list[dict]: if isinstance(html, list): html = "".join(html) if html.strip(): + html = shrink_inline_b64_in_html(html) result.append({"type": "text", "data": html, "format": "html"}) elif "text/plain" in data: text = data["text/plain"] From afadf1c52ac86015f7b00a6c5fb3ded032836212 Mon Sep 17 00:00:00 2001 From: Lawrence Lane Date: Thu, 7 May 2026 14:28:56 -0400 Subject: [PATCH 2/3] fix(docs): migrate leftover MkDocs tab syntax to Fern Tabs The agent-rollout-ingestion concept page still used PyMdown `=== "Title"` tab blocks left over from the MkDocs source. Fern's MDX runtime doesn't recognize the syntax, breaking the published page. Convert the five tab blocks to Fern's / JSX components, preserving titles, intro text, and code snippets verbatim. Signed-off-by: Lawrence Lane --- .../concepts/agent-rollout-ingestion.mdx | 94 ++++++++++--------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/fern/versions/v0.5.8/pages/concepts/agent-rollout-ingestion.mdx b/fern/versions/v0.5.8/pages/concepts/agent-rollout-ingestion.mdx index 4681b6da0..559d10ae0 100644 --- a/fern/versions/v0.5.8/pages/concepts/agent-rollout-ingestion.mdx +++ b/fern/versions/v0.5.8/pages/concepts/agent-rollout-ingestion.mdx @@ -9,68 +9,76 @@ position: 3 Use `AgentRolloutSeedSource` when you want to work from existing agent traces instead of traces captured during a Data Designer generation run. -=== "Claude Code" + + - Uses `~/.claude/projects` and `*.jsonl` by default. +Uses `~/.claude/projects` and `*.jsonl` by default. - ```python - import data_designer.config as dd +```python +import data_designer.config as dd - seed_source = dd.AgentRolloutSeedSource( - format=dd.AgentRolloutFormat.CLAUDE_CODE, - ) - ``` +seed_source = dd.AgentRolloutSeedSource( + format=dd.AgentRolloutFormat.CLAUDE_CODE, +) +``` -=== "Codex" + + - Uses `~/.codex/sessions` and `*.jsonl` by default. +Uses `~/.codex/sessions` and `*.jsonl` by default. - ```python - import data_designer.config as dd +```python +import data_designer.config as dd - seed_source = dd.AgentRolloutSeedSource( - format=dd.AgentRolloutFormat.CODEX, - ) - ``` +seed_source = dd.AgentRolloutSeedSource( + format=dd.AgentRolloutFormat.CODEX, +) +``` -=== "Hermes Agent" + + - Uses `~/.hermes/sessions` and `*.json*` by default so CLI session logs and gateway transcripts can coexist. +Uses `~/.hermes/sessions` and `*.json*` by default so CLI session logs and gateway transcripts can coexist. - ```python - import data_designer.config as dd +```python +import data_designer.config as dd - seed_source = dd.AgentRolloutSeedSource( - format=dd.AgentRolloutFormat.HERMES_AGENT, - ) - ``` +seed_source = dd.AgentRolloutSeedSource( + format=dd.AgentRolloutFormat.HERMES_AGENT, +) +``` -=== "Pi Coding Agent" + + - Uses `~/.pi/agent/sessions` and `*.jsonl` by default. Sessions are tree-structured JSONL files; the active conversation path is resolved automatically. +Uses `~/.pi/agent/sessions` and `*.jsonl` by default. Sessions are tree-structured JSONL files; the active conversation path is resolved automatically. - ```python - import data_designer.config as dd +```python +import data_designer.config as dd - seed_source = dd.AgentRolloutSeedSource( - format=dd.AgentRolloutFormat.PI_CODING_AGENT, - ) - ``` +seed_source = dd.AgentRolloutSeedSource( + format=dd.AgentRolloutFormat.PI_CODING_AGENT, +) +``` -=== "ATIF" + + - ATIF requires an explicit `path`. See Harbor's [ATIF documentation](https://harborframework.com/docs/trajectory-format) for the format specification. +ATIF requires an explicit `path`. See Harbor's [ATIF documentation](https://harborframework.com/docs/trajectory-format) for the format specification. - ```python - import data_designer.config as dd +```python +import data_designer.config as dd - seed_source = dd.AgentRolloutSeedSource( - format=dd.AgentRolloutFormat.ATIF, - path="/data/harbor/runs/swe-bench/job-042", - recursive=True, - file_pattern="trajectory*.json", - ) - ``` +seed_source = dd.AgentRolloutSeedSource( + format=dd.AgentRolloutFormat.ATIF, + path="/data/harbor/runs/swe-bench/job-042", + recursive=True, + file_pattern="trajectory*.json", +) +``` + + + You can override `path` and `file_pattern` for any format when your rollout artifacts live outside the built-in defaults. From afa7f68d25500d6a7cbdffaf92cee8fb498137f0 Mon Sep 17 00:00:00 2001 From: Lawrence Lane Date: Thu, 7 May 2026 14:39:11 -0400 Subject: [PATCH 3/3] fix(docs): convert leftover MkDocs admonition to Fern Tip Co-Authored-By: Claude Opus 4.7 Signed-off-by: Lawrence Lane --- .../v0.5.8/pages/concepts/models/default-model-settings.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fern/versions/v0.5.8/pages/concepts/models/default-model-settings.mdx b/fern/versions/v0.5.8/pages/concepts/models/default-model-settings.mdx index beadc08d1..4bfa96b7f 100644 --- a/fern/versions/v0.5.8/pages/concepts/models/default-model-settings.mdx +++ b/fern/versions/v0.5.8/pages/concepts/models/default-model-settings.mdx @@ -88,8 +88,9 @@ When the Data Designer library or the CLI is initialized, default model configur - **Model Configs**: `~/.data-designer/model_configs.yaml` - **Model Providers**: `~/.data-designer/model_providers.yaml` -!!! tip Tip - While these files provide a convenient way to specify settings for your model providers and configuration you use most often, they can always be set programmatically in your SDG workflow. + +While these files provide a convenient way to specify settings for your model providers and configuration you use most often, they can always be set programmatically in your SDG workflow. + You can customize the home directory location by setting the `DATA_DESIGNER_HOME` environment variable: