facebook / facebook/lexical

Feature: Official guidance/support for persistent external node IDs in AI-driven diff editing workflows

Open
#8,251 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
23.9k
Forks
2.2k
Avg merge
1d 16h
Merged PRs (30d)
61

Description

## TL;DR

- LobeHub exports document XML where each serialized tag carries a stable identifier, so an AI agent can produce document diff updates against those identifiers.
- Today this workflow depends on a local Lexical patch to preserve imported ids, access the in-progress imported `EditorState`, and reseed key generation after import.
- We would like an upstream-supported pattern or API for this kind of AI-driven diff editing workflow, instead of patching Lexical internals.

## Description

We have a concrete AI-assisted editing use case in LobeHub that currently requires a local patch on top of Lexical, and we would like to ask for an upstream-supported solution.

Our workflow is:

```mermaid
flowchart TD
A[Lexical document] --> B[Export XML with a stable id on each serialized tag]
B --> C[Send XML to AI agent]
C --> D[AI returns document diff operations referencing those ids]
D --> E[Apply document diff back onto editor by id]
```

This is useful because the AI does not need to understand Lexical internals deeply. It can work against serialized document XML and return diff operations keyed by stable serialized identifiers, and we can translate those operations back into editor updates safely.

## Current workaround

Today we are doing this with a patch over Lexical in our app:

- preserve imported node ids during deserialization
- build a new `EditorState` while keeping those imported ids
- reseed the next generated key after import to avoid collisions

More concretely, our current patch relies on two runtime behaviors:

1. `parseEditorState(serializedState, updateFn)` passes the newly created `EditorState` into `updateFn`
2. `resetRandomKey(targetId)` can reseed the next generated node key after we import content with pre-existing ids

That lets us do something like:

```mermaid
flowchart TD
A[Empty root] --> B[Parse imported JSON or XML carrying stable serialized ids]
B --> C[Populate the new EditorState directly]
C --> D[Scan imported node ids]
D --> E[Reseed next generated key to maxImportedId + 1]
```

We currently use this for both:

- JSON import with a `keepId`-style path
- XML import where every serialized tag already carries a stable id used by our AI diff pipeline

Without the first behavior, we cannot populate the fresh `EditorState` during import in the way we need.
Without the second behavior, imported ids and newly created ids can collide.

This works for our editor, but we would strongly prefer an upstream-supported solution instead of maintaining a patch.

## Related closed issues

- #6313
- #7326

I understand from those discussions that stable internal `__key` values are not planned in Lexical core, and that application-level ids / NodeState are the preferred direction.

However, our request is not only "please make `__key` stable". The request is:

- an official pattern for persistent external ids in import/export workflows
- guidance for AI-driven document diff editing workflows
- a way to reconstruct editor state from serialized content while preserving externally meaningful ids
- ideally an upstream-supported API or example that avoids patching Lexical internals

## What would help

Any of the following would already be very helpful:

1. Official docs/example for persistent external ids using NodeState or node subclasses
2. A recommended import/export workflow for preserving application-level ids safely
3. An officially supported hook/API for building a new imported `EditorState` with access to that in-progress state
4. An officially supported hook/API for reseeding or reconciling ids after importing serialized content
5. Guidance for conflict handling in copy/paste / duplicate / merge scenarios when persistent ids are used

## Why this matters

AI-assisted editing is becoming a common editor workflow:

- export structured content
- let an agent propose document diff updates
- map those diff updates back to editor nodes deterministically through stable serialized ids

Without a stable application-level addressing mechanism, this becomes much harder than it needs to be. Right now, patching Lexical internals is the only practical path for our use case.

To be clear: we are not asking Lexical to change its philosophy around ephemeral internal keys if that is still the intended design.

We are asking for a supported technical path for this class of workflow, because today our implementation depends on patching Lexical internals to:

- preserve imported ids
- access the in-progress imported `EditorState`
- continue key generation after the imported max id

We would appreciate any upstream guidance or support here, even if the answer is "this should live outside core, and here is the recommended pattern".

Contributor guide

Open the contributing guide

Research direction

Start with the documented behaviors named in the issue: parseEditorState(serializedState, updateFn) and resetRandomKey(targetId), then review related issues #6313 and #7326. The requested outcome is upstream guidance, an example, or supported APIs for preserving application-level ids during import/export and applying AI-driven diffs without patching Lexical internals.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
developer-experience, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.