fix: allow addSibling to target the root message#2432
Conversation
addSibling threw when the sibling target was the root message, even though the existing logic already handles that case correctly: the new message is pushed with the same (empty) ancestors array, and the nearestAncestor lookup resolves to undefined so the children-update step is safely skipped. Removed the unnecessary guard clause.
There was a problem hiding this comment.
💡 Codex Review
chat-ui/src/lib/utils/tree/addSibling.ts
Lines 27 to 28 in a341dde
When the target is the root, sibling.ancestors is empty, so nearestAncestorId becomes undefined and no children array is updated. The branch picker is built exclusively from message.children (createMessagesAlternatives in src/routes/conversation/[id]/+page.svelte lines 116-123, then matched in ChatWindow.svelte line 620), so retrying or editing the first user message creates a second top-level message that is not present in any alternatives list; after this succeeds, users cannot navigate between the original root branch and the retried root branch. Please also represent root siblings in the branch data, or teach the UI to include messages with empty ancestors.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Removing the root-message guard also removed a TypeScript narrowing check on sibling.ancestors, causing 2 svelte-check errors -- fixed with an explicit ?? [] fallback. Also addresses the Codex review finding on this PR: root-level siblings had no parent to record them in a children array, so they were created but never appeared in any alternatives group, making them unreachable from the branch switcher UI. createMessagesAlternatives now also emits a root-level alternatives group when more than one top-level message exists.
|
Thanks @chatgpt-codex-connector for catching this — confirmed and fixed in the latest commit. Root-level siblings had no parent to record them in a While verifying this, |
|
To use Codex here, create a Codex account and connect to github. |
Closes #2386, Closes #2387
What this PR does
addSiblinginsrc/lib/utils/tree/addSibling.tsthrew an error wheneverthe sibling target was the conversation's root message:
This restriction was unnecessary. A sibling of the root message is just
another top-level message with an empty
ancestorsarray, and the rest ofthe function already handles that case correctly.
Root cause
The guard clause explicitly threw when
sibling.ancestorswas empty orundefined:
Change
Removed the guard clause. With it gone, the existing logic already handles
the root case correctly:
sibling.ancestorsis[], so the new message is pushed withancestors: [](same as the root).nearestAncestorIdresolves tosibling.ancestors[sibling.ancestors.length - 1],i.e.
[][-1], which isundefined.conv.messages.find(m => m.id === nearestAncestorId)returnsundefinedsince no message has
id === undefined.if (nearestAncestor)block is therefore skipped, which is exactlyright: there is no parent node whose
childrenarray needs updating.The non-root path is completely unaffected — the removed guard only ever
fired when
ancestorswas empty/falsy, so every other call path behavesidentically to before.
Also updated
addSibling.spec.ts: the existing test asserted the oldthrowing behavior (with a
// TODO: This behaviour should be fixedcommentalready acknowledging it needed to change). Replaced it with a test that
confirms
addSiblingnow succeeds when targeting the root message andreturns a new message with the same (empty)
ancestorsas the root.Verification
confirm no other code path re-throws or crashes once the guard is gone.
npx prettier --checkandnpx eslintboth pass clean on the changed files.addSibling.spec.tssuite: 8/8 tests pass, including theupdated root-message test and the pre-existing "should add a sibling to
a message" test (confirms non-root behavior is unchanged).