Skip to content

[chore] Split PlaygroundConfigSection - #5572

Merged
mmabrouk merged 3 commits into
release/v0.106.2from
fe-chore/playground-config-section-split
Jul 31, 2026
Merged

[chore] Split PlaygroundConfigSection#5572
mmabrouk merged 3 commits into
release/v0.106.2from
fe-chore/playground-config-section-split

Conversation

@ardaerzin

Copy link
Copy Markdown
Contributor

Context

PlaygroundConfigSection.tsx had reached 2003 lines: 8 inline components and 26 module-level helpers in one file.

Changes

The file keeps its path so the barrel import is unchanged. Its parts move into the co-located PlaygroundConfigSection/ directory, which already held four components.

Helpers and types split along a one-directional import chain, which matters here because an earlier attempt at this hit a circular dependency:

types <- constants <- {metadata, llmConfig, schemaData} <- atoms <- adapters

The component body's two contiguous blocks become hooks, called at their original positions so hook order, hook count and dependency arrays are unchanged:

  • useModelConfigurePopover for the configure popover. This stayed a hook rather than becoming a component, because the popover content is a useMemo with a 26-entry dependency array. Turning it into a component would change the memoization semantics.
  • useFieldSlots for the per-field slot renderers.

PlaygroundConfigSection.tsx is 478 lines.

The four public types moved to types.ts and are re-exported from PlaygroundConfigSection.tsx, so none of the six call sites in oss, ee and playground-ui changed, and no compatibility shim was left behind.

Tests

  • pnpm --filter @agenta/entity-ui exec tsc --noEmit passes, as do @agenta/oss and @agenta/ee.
  • pnpm lint-fix across the repo makes no changes. Prettier clean.
  • Every module-level helper, constant and internal type was grepped across oss, ee and packages first. All were file-private, so only the barrel surface needed preserving.
  • Effect bodies, dependency arrays and lazy initializers moved verbatim, comments included. The only comment content removed is five section-divider banners, which the new per-module doc comments replace.

Not runtime verified. The gates above are static.

One piece of the original plan is not done here: useRawEditor (the JSON and YAML serialize-sync effect, roughly 110 lines) stays in the main file. Pulling it out needs about eight parameters, which is not worth it at a 478-line root.

What to QA

  • Open the agent config panel. Every section renders, and the section headers show the same summaries as before.
  • Open the model configure popover and change a model. The change applies and the popover state behaves as before.
  • Switch revisions with the panel open. The config re-reads and does not strand stale values.
  • Regression: the raw JSON and YAML editor still round-trips edits, since its sync effect stayed in the root.

Follows the parked Phase-1 plan: the file keeps its path (barrel import
unchanged) and its parts move into the co-located PlaygroundConfigSection/
dir, in a one-directional import DAG to avoid the circular-dep trap:

  types <- constants <- {metadata, llmConfig, schemaData} <- atoms <- adapters

The component body's two contiguous blocks become hooks called at their
original positions, so hook order, count and dep arrays are unchanged:

  useModelConfigurePopover   the configure popover (26-entry useMemo dep
                             array kept as a memo, not made a component)
  useFieldSlots              the per-field slot renderers

The four public types moved to types.ts and are re-exported from
PlaygroundConfigSection.tsx, so no importer changed and no shim was left.

PlaygroundConfigSection.tsx: 2003 -> 478 lines.
@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jul 30, 2026
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview Jul 30, 2026 8:31pm

Request Review

@dosubot dosubot Bot added the refactoring A code change that neither fixes a bug nor adds a feature label Jul 30, 2026
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c0c70fb4-0271-4216-a4de-7372cec4aba1

📥 Commits

Reviewing files that changed from the base of the PR and between bad129d and 6420e31.

📒 Files selected for processing (5)
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/adapters.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/atoms.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useFieldSlots.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useModelConfigurePopover.tsx
💤 Files with no reviewable changes (1)
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useModelConfigurePopover.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/atoms.ts

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Enhanced model configuration UI with clearer model, fallback, and retry controls.
    • Improved reset behavior for configurable LLM fields, including parameter extensions.
  • Bug Fixes
    • Improved schema detection and routing for grouped/nested configuration fields to avoid mis-editing.
    • Preserve and restore internal metadata during view/edit cycles so changes remain consistent.
    • Reduce unnecessary rerenders/updates when configuration values haven’t changed.

Walkthrough

PlaygroundConfigSection is reorganized around dedicated type, constant, metadata, schema, adapter, and configuration-helper modules. The composition root delegates model popover state and field-slot wiring to hooks, while adapter schema resolution and configuration update routing are centralized.

Changes

Playground configuration flow

Layer / File(s) Summary
Configuration contracts and helpers
web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/{types,constants,llmConfig,metadata}.ts
Public types, policy constants, LLM configuration utilities, and metadata strip/collect/reattach functions are defined in dedicated modules.
Adapter and schema data plumbing
web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/{adapters,atoms,schemaData}.ts
The default adapter directly resolves molecule schemas; atom memoization, stable selection, update routing, active-data selection, sibling-field merging, and schema resolution are implemented separately.
Model configuration popover
web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useModelConfigurePopover.tsx
The hook retains model, fallback, and retry popover state and now returns popover content, open-change handling, open state, and model information without updatePromptRootField.
Drill-in rendering composition
web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useFieldSlots.tsx, web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection.tsx
Field-slot parameters and callback dependencies no longer include revisionId or updatePromptRootField; the composition root imports extracted modules and re-exports public types.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ConfigSection as PlaygroundConfigSection
  participant Popover as useModelConfigurePopover
  participant Slots as useFieldSlots
  participant Router as configUpdateRouterAtom
  participant Molecule as workflowMolecule
  ConfigSection->>Popover: initialize model configuration state
  ConfigSection->>Slots: provide popover state and field dependencies
  Slots->>Popover: render configuration popover content
  Popover->>Router: dispatch configuration changes
  Router->>Molecule: update configuration or sibling data
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 60.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: splitting PlaygroundConfigSection into smaller modules.
Description check ✅ Passed The description is directly about the refactor and matches the files and objectives in the changeset.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fe-chore/playground-config-section-split

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.

@ardaerzin
ardaerzin changed the base branch from release/v0.106.1 to release/v0.106.2 July 30, 2026 18:13
@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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.

🧹 Nitpick comments (5)
web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/adapters.ts (1)

161-179: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop the dead placeholder schemaAtPath.

buildWorkflowMoleculeAdapter builds a schemaAtPath that always returns atom(() => null) (with a double cast and a comment referring to a wrapper), only for buildDefaultAdapter to overwrite it. Assign moleculeSchemaAtPath directly and drop the extra layer.

♻️ Proposed simplification
         selectors: {
-            schemaAtPath: memoAtom((key: string) => {
-                // key is serialized "{id}:{path}" — parse it
-                // But the interface takes {id, path}, so we use a wrapper below
-                return atom(() => null)
-            }) as unknown as ConfigSectionMoleculeAdapter["selectors"]["schemaAtPath"],
+            schemaAtPath: moleculeSchemaAtPath,
         },
     }
 }
 
-function buildDefaultAdapter(): ConfigSectionMoleculeAdapter {
-    const base = buildWorkflowMoleculeAdapter()
-    return {
-        ...base,
-        selectors: {
-            schemaAtPath: moleculeSchemaAtPath,
-        },
-    }
-}
-
-export const defaultAdapter = buildDefaultAdapter()
+export const defaultAdapter = buildWorkflowMoleculeAdapter()
web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/atoms.ts (2)

71-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the console.debug debug artifact from the atom read.

This runs on every recompute of the root-path schema atom in production and logs schema internals.

♻️ Proposed cleanup
-            const resolved = getSchemaAtPathUtil(schema, params.path) ?? null
-            if (params.path.length === 0) {
-                console.debug("[PlaygroundConfigSection] root schema", params.id.slice(0, 8), {
-                    schemaType: schema?.type,
-                    schemaHasProperties: !!schema?.properties,
-                    schemaPropertyKeys: schema?.properties
-                        ? Object.keys(schema.properties as Record<string, unknown>)
-                        : null,
-                    resolvedType: resolved?.type,
-                    resolvedPropertyKeys: resolved?.properties
-                        ? Object.keys(resolved.properties as Record<string, unknown>)
-                        : null,
-                })
-            }
-            return resolved
+            return getSchemaAtPathUtil(schema, params.path) ?? null

54-60: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

Unbounded module-level cache keyed by (id, path).

Referential stability is the stated goal, but this map is never pruned: every revision id combined with every drilled-in path adds a permanent entry for the lifetime of the tab (the memoAtom caches in adapters.ts have the same characteristic, though those are keyed by id only). Consider an LRU bound or eviction when a revision is no longer mounted if long playground sessions traverse many paths.

web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useModelConfigurePopover.tsx (1)

533-534: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

--ag-c-* literals carried over during the move.

Since these lines are being relocated anyway, consider switching the popover chrome to Ant Design semantic tokens / Tailwind color utilities (or var(--ag-color*)), and verify light + dark. Fine to defer if the split is meant to be byte-identical.

As per coding guidelines: "Consume theme colors through Ant Design semantic tokens, Tailwind color utilities, or supported var(--ag-color*) variables; do not use raw hex colors or --ag-c-* literals."

Source: Coding guidelines

web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useFieldSlots.tsx (1)

269-288: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

revisionId and updatePromptRootField are unused inside fieldHeaderSlot.

They are only present to keep the dependency array identical to the monolith, and they force the header slot (and thus the drill-in slots object) to churn whenever parameters change via updatePromptRootField. Once you're confident the extraction is behavior-equivalent, dropping both from the deps and from UseFieldSlotsParams (and from the call site in PlaygroundConfigSection.tsx lines 359/365) would remove two dead props.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7fc7eda6-8047-4145-a5d8-2fb41560db6b

📥 Commits

Reviewing files that changed from the base of the PR and between a0ef2cc and bad129d.

📒 Files selected for processing (10)
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/adapters.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/atoms.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/constants.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/llmConfig.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/metadata.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/schemaData.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/types.ts
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useFieldSlots.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/components/PlaygroundConfigSection/useModelConfigurePopover.tsx

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Status Destroyed (PR closed)

Updated at 2026-07-31T19:19:53.085Z

Three leftovers the split moved verbatim from the 2003-line monolith:

- adapters.ts: buildWorkflowMoleculeAdapter built a schemaAtPath that always
  returned atom(() => null), only for buildDefaultAdapter to overwrite it.
  Assign moleculeSchemaAtPath directly; this also removes the `as unknown as`
  cast that was the only thing letting the wrong-typed placeholder compile.

- atoms.ts: a console.debug fired on every recompute of the root-path schema
  atom, in production, logging schema internals.

- useFieldSlots: revisionId and updatePromptRootField were never read in
  fieldHeaderSlot's body, only listed in its dep array, churning the drill-in
  slots object whenever parameters changed. Dropped from the params, the dep
  array and the call site; updatePromptRootField also leaves
  useModelConfigurePopover's return (still used inside that hook).

Also fixes a stale closure the split inherited: stickyHeaderTop is read in
fieldHeaderSlot but was missing from its deps. activeData stays out on purpose
— its only use is hasParameters(activeData), which the parameters dep tracks.

No behavior change otherwise. tsc clean for @agenta/entity-ui and @agenta/oss;
pnpm lint-fix makes no changes.
@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mmabrouk
mmabrouk merged commit 0b769f2 into release/v0.106.2 Jul 31, 2026
58 of 59 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoring A code change that neither fixes a bug nor adds a feature size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants