Skip to content

feat(metadata-instance-editor): support for cascade extraction#4613

Open
alexkirillovtech wants to merge 5 commits into
masterfrom
MDX-2041-cascade-extract-support-metadata-instance
Open

feat(metadata-instance-editor): support for cascade extraction#4613
alexkirillovtech wants to merge 5 commits into
masterfrom
MDX-2041-cascade-extract-support-metadata-instance

Conversation

@alexkirillovtech
Copy link
Copy Markdown

@alexkirillovtech alexkirillovtech commented Jun 8, 2026

Description

Product scope

When a metadata instance on a folder is managed by a Box AI extract agent (i.e. its cascadePolicy.cascadePolicyType === ai_extract), the values for that instance are populated and kept in sync by the agent. Editing those values inline in the metadata sidebar would put the form's local state out of sync with what the agent will produce on the next cascade run, so this PR removes the inline-edit affordance for those instances and points users to the right place to make changes — the agent itself.

Resulting UX for an extract-managed instance:

  • Collapsed / view mode — the fields are rendered read-only (no remove icons, no inputs), with a short informational notice at the top: "Metadata cascade policy is enabled for this instance".
  • Edit mode — instead of the form, we render a Blueprint ActionableInlineNotice (lock icon) titled "Managed by a Box AI extract agent" with body copy explaining that the instance can't be edited here, plus a primary "Manage agent" button. Clicking it invokes a new onManageExtractAgent(agentId) callback, where the numeric agent id is extracted from the cascade policy's agent configuration value. The host app (EUA) wires this up to navigate to the agent management surface.

For all non-extract-managed instances the existing behavior is preserved exactly — same form, same cascade-policy controls, same save/remove footer, same confirm-remove dialog.

Selected approach

Instance.js had grown into a ~700-line class component that owned both the editor state machine and the entire view tree (collapsible chrome, cascade policy, form, footer, confirm dialog). Rather than add a third rendering branch into that file, this PR splits the presentational layer into three focused components and keeps Instance as the stateful orchestrator:

New file Responsibility
InstanceCard.js Collapsible card chrome only — icon, title, error mark, header action slot. No knowledge of editing or agents.
EditableInstanceBody.js The existing editable form: CascadePolicy + TemplatedInstance/CustomInstance + Footer + confirm-remove dialog. Pure presentational — every handler and flag is passed in as a prop.
ExtractManagedInstanceBody.js New body used when cascadePolicyType === ai_extract. Renders the read-only view when collapsed and the ActionableInlineNotice + "Manage agent" button when editing.

Instance.js now:

  • keeps all the state (isEditing, isCascadingEnabled, cascadePolicyConfiguration, etc.) and all the change handlers (onSave, onFieldChange, onCascadeToggle, onAIAgentSelect, …) — unchanged behavior;
  • decides which body to render via a single check (isExtractManaged = cascadePolicy?.cascadePolicyType === CASCADE_POLICY_TYPE_AI_EXTRACT);
  • delegates the chrome to InstanceCard and the body to one of the two new components.

The new onManageExtractAgent callback is added as an optional prop and threaded MetadataInstanceEditor → Instances → Instance → ExtractManagedInstanceBody. When it's not provided (or no agentId is on the cascade policy), the "Manage agent" button is simply not rendered, so existing consumers are unaffected.

Why this split rather than inlining the new branch in Instance:

  • Instance no longer mixes "what to show when" with "how to lay out a card / form / notice"; each new file is small, props-only, and unit-testable in isolation (see the new test files).
  • The notice-vs-form choice for extract-managed instances lives in one place (ExtractManagedInstanceBody), which makes future tweaks to that UX — copy, additional CTAs, telemetry tags — a single-file change.
  • The new components are pure (no connect, no lifecycle), so they avoid the snapshot churn that touching Instance itself causes; the bulk of the snapshot diff in this PR comes from Instance.test.js re-rendering through the new component tree rather than from semantic changes.

What's included

Source

  • Instance.js — refactor: extract chrome + body, add isExtractManaged branch, accept new onManageExtractAgent prop.
  • InstanceCard.js — new presentational card.
  • EditableInstanceBody.js — new presentational editable body.
  • ExtractManagedInstanceBody.js + .scss — new presentational managed body.
  • Instances.js, MetadataInstanceEditor.js — forward the new optional onManageExtractAgent prop.
  • messages.js — 4 new i18n strings (extractManagedTitle, extractManagedDescription, extractManagedManageAgent, extractManagedNoticeIconAriaLabel).
  • i18n/en-US.properties — generated.

Tests

  • New: EditableInstanceBody.test.js, ExtractManagedInstanceBody.test.js, InstanceCard.test.js, plus a shared __fixtures__/metadataInstances.js.
  • Updated: Instance.test.js, Instances.test.js, MetadataInstanceEditor.test.js to cover the new prop pass-through and the extract-managed branching (view + edit).
  • Updated: Instance.test.js.snap — large diff, but purely structural (rendering goes through InstanceCard / EditableInstanceBody wrappers now).

All 650 tests pass; coverage on the touched module is 100% statements / ~85% branches for the new files.

How to test

  • Setup: you need box-ui-elements and enduserapp
  • Run box-ui-elements with yarn start:npm and enduserapp with yarn start:local:linked / or yarn start:linked, whatever you prefer more
  • You need a test account with Extract enabled (contact @akirylau if you need help in setup), metadata template created in Admin Console and one test folder
  • Go to Automate -> Extract -> Create custom agent -> Select template -> Click select source folder -> select a test folder
  • Now go to files -> However over test folder and the end of row click "..." button -> metadata
  • In metadata instance modal confirm that template instance exist
  • Expand it and click pencil icon
  • Confirm that there are no more fields or cascade setup, but the new banner exists and navigate to custom agent works
  • Also confirm that navigation is protected with unsaved changes banner, by adding new template to folder or editing existing instance of non agent template and click navigate -> modal should appear protecting for unsaved changes

Screenshots

Semantic release type

PR title: feat(metadata-instance-editor): support cascade extraction

  • feat — New feature (extract-agent-managed metadata instances)

Summary by CodeRabbit

  • New Features

    • Add AI extract agent management UI: informational managed-by notice and "Manage agent" action; enhanced editable instance body with cascade, AI extraction, and field edit controls.
  • Refactor

    • Move instance UI to a card-based layout and split editable vs extract-managed render paths for clearer composition.
  • Tests

    • Add extensive tests and fixtures covering editable, extract-managed, agent-management, and interaction flows.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 8, 2026

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Refactors the metadata instance editor to split extract-managed and editable flows. Adds CustomExtractAgentInstanceBody (managed view), EditableInstanceBody (editable form), and InstanceCard (collapsible container). Instance now routes between managed and editable bodies and threads an optional onManageExtractAgent callback through the editor tree.

Changes

Metadata instance editor — extract-managed and delegated bodies

Layer / File(s) Summary
Custom extract agent utilities and tests
src/features/metadata-instance-editor/constants.js, src/features/metadata-instance-editor/metadataUtil.js, src/features/metadata-instance-editor/__tests__/metadataUtil.test.js
Adds CUSTOM_EXTRACT_AGENT_CONFIGURATION_PREFIX, getCustomExtractAgentId() to parse numeric agent id from configuration strings, and isCustomExtractAgentPolicy() to detect ai_extract policies using the custom prefix. Includes parameterized tests for parsing and policy detection.
CustomExtractAgentInstanceBody component, styles, messages, and tests
src/features/metadata-instance-editor/CustomExtractAgentInstanceBody.js, src/features/metadata-instance-editor/CustomExtractAgentInstanceBody.scss, src/features/metadata-instance-editor/messages.js, src/features/metadata-instance-editor/__tests__/CustomExtractAgentInstanceBody.test.js
Adds a presentational component for instances managed by custom Box AI extract agents: shows a locked actionable notice in edit mode with an optional "Manage agent" action (resolves numeric id), and renders read-only CustomInstance/TemplatedInstance in collapsed mode. Includes SCSS and i18n messages plus unit tests covering modes and manage-button visibility/wiring.
EditableInstanceBody component and tests
src/features/metadata-instance-editor/EditableInstanceBody.js, src/features/metadata-instance-editor/__tests__/EditableInstanceBody.test.js
New delegated editable body accepting cascade/extraction/edit flags and callbacks (27 props). Renders optional remove-confirm dialog, CascadePolicy control when applicable, CustomInstance or TemplatedInstance based on template type, and Footer when editing. Tests verify conditional rendering, disabled-state propagation, footer interactions, and submit behavior tied to isDirty.
InstanceCard container and tests
src/features/metadata-instance-editor/InstanceCard.js, src/features/metadata-instance-editor/__tests__/InstanceCard.test.js
Introduces a Collapsible wrapper (InstanceCard) that computes icon/type from cascade applicability and policy id, determines template type, optionally shows error indicator, computes animation duration from field count, and forwards children/header action items. Tests cover icons, error state, title, and forwarded content.
Instance routing logic and tests
src/features/metadata-instance-editor/Instance.js, src/features/metadata-instance-editor/__tests__/Instance.test.js
Refactors Instance.render() to wrap content in InstanceCard and route to CustomExtractAgentInstanceBody when a custom ai_extract policy is detected (passes agentConfiguration and onManageExtractAgent), otherwise to EditableInstanceBody. Adds onManageExtractAgent prop and imports isCustomExtractAgentPolicy. Tests updated to assert managed-notice rendering, absence of editable fields when managed, conditional Manage button, and callback invocation with numeric agent id.
Prop threading, fixtures, and integration tests
src/features/metadata-instance-editor/MetadataInstanceEditor.js, src/features/metadata-instance-editor/Instances.js, src/features/metadata-instance-editor/__tests__/__fixtures__/metadataInstances.js, src/features/metadata-instance-editor/__tests__/Instances.test.js, src/features/metadata-instance-editor/__tests__/MetadataInstanceEditor.test.js
Threads onManageExtractAgent through MetadataInstanceEditor → Instances → Instance. Adds comprehensive test fixtures (builders for fields, templates, cascade policies, instances, and editors) and updates integration tests to verify extract-managed routing, managed notice presence, Manage button behavior, agent-id parsing, and agent-selector flows.

Sequence Diagram(s)

sequenceDiagram
  participant Parent as Parent Component
  participant MetadataInstanceEditor
  participant Instances
  participant Instance
  participant InstanceCard
  participant CustomExtractAgentInstanceBody
  participant EditableInstanceBody

  Parent->>MetadataInstanceEditor: provide onManageExtractAgent callback
  MetadataInstanceEditor->>Instances: pass onManageExtractAgent
  Instances->>Instance: pass onManageExtractAgent

  Instance->>Instance: evaluate cascadePolicy
  alt ai_extract with custom agent
    Instance->>InstanceCard: render card
    InstanceCard->>CustomExtractAgentInstanceBody: render managed body
    CustomExtractAgentInstanceBody->>CustomExtractAgentInstanceBody: isEditing?
    alt isEditing and hasResolvedAgentId and onManageExtractAgent
      CustomExtractAgentInstanceBody->>Parent: onManageExtractAgent(numericAgentId)
    else collapsed
      CustomExtractAgentInstanceBody->>InstanceCard: render read-only child instances
    end
  else standard or enhanced policy
    Instance->>InstanceCard: render card
    InstanceCard->>EditableInstanceBody: render editable form
    EditableInstanceBody->>EditableInstanceBody: render CascadePolicy, fields, Footer
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

ready-to-merge

Suggested reviewers

  • tjuanitas
  • jmcbgaston
  • patlm

Poem

🐰 I hopped through cards and tidied views,

Managed agents now have their cues,
EditableBody tends the fields,
Locked notices keep secrets sealed,
Tests and fixtures stitched the scene — hooray for neat metadata dreams!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main feature being introduced: support for cascade extraction in the metadata-instance-editor component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description check ✅ Passed PR description is comprehensive and follows template structure with clear sections covering product scope, selected approach, implementation details, and testing instructions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch MDX-2041-cascade-extract-support-metadata-instance

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 and usage tips.

@alexkirillovtech alexkirillovtech marked this pull request as ready for review June 8, 2026 11:38
@alexkirillovtech alexkirillovtech requested review from a team as code owners June 8, 2026 11:38
@alexkirillovtech alexkirillovtech changed the title feat(metadata-instance-editor) support cascade extraction via custom agent (MDX-2041) feat(metadata-instance-editor) support cascade extraction via custom agent Jun 8, 2026
@alexkirillovtech alexkirillovtech changed the title feat(metadata-instance-editor) support cascade extraction via custom agent feat(metadata-instance-editor): support for cascade extraction Jun 8, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@src/features/metadata-instance-editor/ExtractManagedInstanceBody.js`:
- Line 27: The button still renders and calls the manage callback when
getNumericAgentId(agentId) returns an empty string; update the render and
click-path to guard on the parsed numeric id (use getNumericAgentId) instead of
the raw agentId: only render the "Manage agent" button when parsedId is
non-empty and ensure the onClick handler passes parsedId (or early-returns if
parsedId is falsy) so the callback is never invoked with ''. Locate uses of
getNumericAgentId and the Manage button/callback in ExtractManagedInstanceBody
(and the click handler around the "Manage agent" action) and replace checks to
gate on the parsed numeric id.
- Around line 44-45: Replace the hardcoded iconAriaLabel="lockicon" in the
ExtractManagedInstanceBody component with the localized message you already
added: call formatMessage(messages.extractManagedNoticeIconAriaLabel) (i.e., set
iconAriaLabel={formatMessage(messages.extractManagedNoticeIconAriaLabel)}), so
the aria label uses the localizable extractManagedNoticeIconAriaLabel string
instead of the literal "lockicon".
- Line 6: Add a Flow suppression comment above the Lock import in
ExtractManagedInstanceBody.js: place "// $FlowFixMe - blueprint-web-assets icons
not typed for Flow" immediately above the existing "import { Lock } from
'`@box/blueprint-web-assets/icons/Line`';" to match the pattern used in
Classification.js; replace the hardcoded iconAriaLabel="lockicon" with a
localized string pulled from react-intl/messages (import the message and use
intl.formatMessage or the <FormattedMessage> equivalent) so the aria label is
localized; and when rendering PrimaryAction, wrap the call to
onManageExtractAgent(...) with a guard that verifies getNumericAgentId(agentId)
returns a non-empty/truthy value before invoking it (use
getNumericAgentId(agentId) in the condition to prevent calling
onManageExtractAgent with an empty id).
🪄 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: 8d7970ad-21f6-43f9-8c83-d2e39c56b2d0

📥 Commits

Reviewing files that changed from the base of the PR and between 916a2db and 8baf71b.

⛔ Files ignored due to path filters (2)
  • i18n/en-US.properties is excluded by !i18n/**
  • src/features/metadata-instance-editor/__tests__/__snapshots__/Instance.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (15)
  • src/features/metadata-instance-editor/EditableInstanceBody.js
  • src/features/metadata-instance-editor/ExtractManagedInstanceBody.js
  • src/features/metadata-instance-editor/ExtractManagedInstanceBody.scss
  • src/features/metadata-instance-editor/Instance.js
  • src/features/metadata-instance-editor/InstanceCard.js
  • src/features/metadata-instance-editor/Instances.js
  • src/features/metadata-instance-editor/MetadataInstanceEditor.js
  • src/features/metadata-instance-editor/__tests__/EditableInstanceBody.test.js
  • src/features/metadata-instance-editor/__tests__/ExtractManagedInstanceBody.test.js
  • src/features/metadata-instance-editor/__tests__/Instance.test.js
  • src/features/metadata-instance-editor/__tests__/InstanceCard.test.js
  • src/features/metadata-instance-editor/__tests__/Instances.test.js
  • src/features/metadata-instance-editor/__tests__/MetadataInstanceEditor.test.js
  • src/features/metadata-instance-editor/__tests__/__fixtures__/metadataInstances.js
  • src/features/metadata-instance-editor/messages.js

Comment thread src/features/metadata-instance-editor/ExtractManagedInstanceBody.js Outdated
Comment thread src/features/metadata-instance-editor/ExtractManagedInstanceBody.js Outdated
Comment thread src/features/metadata-instance-editor/ExtractManagedInstanceBody.js Outdated
*/
const ExtractManagedInstanceBody = ({ agentId, data, isEditing, onManageExtractAgent, template }: Props) => {
const { formatMessage } = useIntl();
const isProperties = template.templateKey === TEMPLATE_CUSTOM_PROPERTIES;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
const isProperties = template.templateKey === TEMPLATE_CUSTOM_PROPERTIES;
const isCustomProperties = template.templateKey === TEMPLATE_CUSTOM_PROPERTIES;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

it may seem like a new code, but it's actually an old code, that is consistent across multiple files and the value of constant is actually properties. I know it's not ideal, but I would like to keep extra changes at minimum
const TEMPLATE_CUSTOM_PROPERTIES: 'properties' = 'properties';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

.metadata-instance-editor-extract-managed {
padding: 8px;

.metadata-instance-editor-extract-managed-actions {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What does this CSS selector stand for? Is this overwriting a style from the Blueprint?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

text={formatMessage(messages.extractManagedDescription)}
title={formatMessage(messages.extractManagedTitle)}
>
<>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: redundant fragment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

* Extracts the numeric agent id from a prefixed configuration value.
* e.g. "extract_agent_14637327713" -> "14637327713"
*/
const getNumericAgentId = (agentId?: string): string => (agentId ? agentId.replace(/\D/g, '') : '');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey, I noticed that the agent value doesn't always follow the extract_agent_ format. In the same module, there is a second type of agent - enhanced - defined as enhanced_extract_agent (https://github.com/box/box-ui-elements/blob/master/src/features/metadata-instance-editor/constants.js#L5).

Furthermore, Instance.js actually saves this value as agent https://github.com/box/box-ui-elements/blob/master/src/features/metadata-instance-editor/Instance.js#L364.

Note that enhanced_extract_agent does not contain any digits.
So, for an instance managed by an enhanced agent:

getNumericAgentId('enhanced_extract_agent')
// 'enhanced_extract_agent'.replace(/\D/g, '')  →  ''  (empty string)

User impact: the instance with the enhanced agent displays the note "Managed by a Box AI extract agent", but provides no way to navigate to agent management - resulting in a dead end.

Is this really how it's supposed to work?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for a great Marcin! You actually surfaced a major problem in the way how we identified a custom extract agent managed instance.

My initial understanding what that type const CASCADE_POLICY_TYPE_AI_EXTRACT = 'ai_extract'; is enough to tell that it's create by extract custom agent. What was a big mistake!

Turned out if I enable Box AI on a regular cascade policy via metadata folder it will become ai_extract type. The same as when it's created by extract custom agent it's also ai_extract. So to say that it's for sure custom extract agent we need to make sure that we check for a suffix const CUSTOM_EXTRACT_AGENT_CONFIGURATION_PREFIX = 'extract_agent_';

Unfortunately it's the only way how differentiate them. I brought my concern to a platform team https://box.slack.com/archives/C03ET4QCU7P/p1780928270883609. However, it seems that this prefix is stable enough of now (check thread I attached there)

So to address this problem I made two type of changes:

  1. Re-work of differentiator logic - feat(metadata-instance-editor): fix custom extract agent logic (MDX-2…
  2. Re-work of naming system to make sure we do not mess with "extract" (cascade policy with AI) and "custom extract agent" (automate) feat(metadata-instance-editor): work on clarity of custom agent separ…

Comment thread src/features/metadata-instance-editor/CustomExtractAgentInstanceBody.js Outdated
Comment thread src/features/metadata-instance-editor/CustomExtractAgentInstanceBody.js Outdated
Comment thread src/features/metadata-instance-editor/metadataUtil.js Outdated
Comment thread src/features/metadata-instance-editor/__tests__/__fixtures__/metadataInstances.js Outdated
Comment thread src/features/metadata-instance-editor/metadataUtil.js Outdated
Comment thread src/features/metadata-instance-editor/metadataUtil.js Outdated
Comment thread src/features/metadata-instance-editor/__tests__/__fixtures__/metadataInstances.js Outdated
Comment thread src/features/metadata-instance-editor/messages.js
Comment thread src/features/metadata-instance-editor/InstanceCard.js Outdated
data: MetadataFields,
errors: { [string]: React.Node },
isAIFolderExtractionEnabled: boolean,
isBusy: boolean,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we rename the isBusy prop to isLoading here? It's only passed to <LoadingIndicatorWrapper isLoading={...}>, so matching the name makes the intent clearer. The parent can still pass isLoading={isBusy} — no need to rename the state variable in Instance.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

this code is not new, but an old component that I moved. I would like to avoid unnecessary refactoring in this PR

Comment on lines +87 to +97
if (shouldConfirmRemove) {
return (
<LoadingIndicatorWrapper isLoading={isBusy}>
<MetadataInstanceConfirmDialog
confirmationMessage={confirmationMessage}
onCancel={onConfirmCancel}
onConfirm={onRemove}
/>
</LoadingIndicatorWrapper>
);
}
Copy link
Copy Markdown
Contributor

@reneshen0328 reneshen0328 Jun 8, 2026

Choose a reason for hiding this comment

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

  1. The shouldConfirmRemove early return on line 87 means this component has two completely unrelated render paths. A cleaner split would be having Instance.js handles the rendering logic, the same way it already chooses between <CustomExtractAgentInstanceBody> and <EditableInstanceBody>. This would also remove 4 props (shouldConfirmRemove, confirmationMessage, onConfirmCancel, onRemove) for this component.
  2. Since EditableInstanceBody is only used here and isBusy is owned by Instance, consider wrapping it with LoadingIndicatorWrapper at this level instead of inside the body. That way the body stays purely presentational and you can drop the isBusy prop from its interface.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

While you might be right on this, but I would like to avoid making any refactoring/improvements for existing code. I know it shows as a new component, but I actually just extracted it from existing one

  • remove confirmation is not related to a CustomExtractAgent, since it's not possible to remove an instance created by extract agent

I know a code is not golden example, but in scope of BUIE I believe smaller steps are the better

Comment on lines +51 to +57
<span
className={classNames('metadata-instance-editor-instance-title-text', {
'metadata-instance-editor-instance-has-error': hasError,
})}
>
{isProperties ? <FormattedMessage {...messages.customTitle} /> : template.displayName}
</span>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This can be blueprint Text component instead ex. something like:

<Text
    as="span"
    variant="bodyDefaultBold"
    color={hasError ? 'textOnLightError' : 'textOnLightDefault'}
>
    {isProperties ? <FormattedMessage {...messages.customTitle} /> : template.displayName}
</Text>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

same as prev, it's an old code, don't really want to change it

Comment thread src/features/metadata-instance-editor/CustomExtractAgentInstanceBody.scss Outdated
import Collapsible from '../../components/collapsible/Collapsible';
import IconMetadataColored from '../../icons/general/IconMetadataColored';
import IconAlertCircle from '../../icons/general/IconAlertCircle';
import { bdlWatermelonRed } from '../../styles/variables';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can this be replaced with the blueprint variable $watermelon-red-100?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

this code is not new, but an old component that I moved. I would like to avoid unnecessary refactoring in this PR

Co-authored-by: Cursor <cursoragent@cursor.com>
@alexkirillovtech alexkirillovtech force-pushed the MDX-2041-cascade-extract-support-metadata-instance branch from 377406f to afad3c7 Compare June 8, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants