Skip to content

feat: AI in editors list on join; suppress chat-input spellcheck#18

Merged
JohnMcLear merged 2 commits intomainfrom
feat/ux-polish-userlist-spellcheck-pageview
May 2, 2026
Merged

feat: AI in editors list on join; suppress chat-input spellcheck#18
JohnMcLear merged 2 commits intomainfrom
feat/ux-polish-userlist-spellcheck-pageview

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Background

Hands-on testing surfaced three rough edges. This PR handles two in code; the third was a deployment-config issue (see "On the third item" below).

1. AI shows up in the editors list as soon as someone joins the pad

Today the AI only appears once it's broadcast itself via announceAiAuthor after a first applied edit. New userJoin server hook calls the same broadcast for the joining client, so the AI chip is in the user list from page load. announceAiAuthor is exported from padEditor.js so index.js reuses it instead of duplicating the USER_NEWINFO emit.

2. Spell-check no longer red-underlines @ai

The browser's native spellcheck on #chatinput was treating @ai as a misspelling. postAceInit now sets spellcheck="false" on the chat input so the trigger token (and any other unfamiliar identifiers) read clean.

On the third item — "edits didn't apply, comments didn't appear"

Server-side everything was correct: comments were persisted in the DB and the comment:c-… attribute lived on the right span in the pad's atext. The UI didn't render them because ep_comments_page declares ep_page_view as a pre ("pre": ["ep_etherpad-lite/webaccess", "ep_page_view/page_view"]) — without page-view, the sidebar layout has no margin to render comment boxes into. Installing ep_page_view alongside ep_comments_page resolves it; no code change needed here. Worth a README note in ep_ai_chat's suggestion-mode docs as a follow-up.

Deferred

  • A real hover-tooltip with usage hints on the AI's user chip ("type @ai in chat, /help for commands") and a corresponding /help command — both deserve a small product call (crowd the chip, or build a help affordance in the chat panel?). Neither blocks the basic flow.

Test plan

  • Mechanical edits; the dev server is mid-test session and can't run backend tests until restart. CI on this branch will exercise both the unit and e2e suites.
  • Post-merge verify: AI chip appears in user list immediately on pad open; @ai typed into chat is not underlined.

🤖 Generated with Claude Code

User feedback after the first hands-on session highlighted three
rough edges; this PR addresses two of them in code (the third —
suggestion comments not rendering — turned out to require
ep_page_view as a documented prereq for ep_comments_page; that's
an install step on the deployment, not a code change here).

1. AI now shows up in the editors list as soon as someone joins
   the pad, not only after a first @ai edit lands. Adds a userJoin
   server hook that calls the existing announceAiAuthor broadcast
   for the joining client. announceAiAuthor is exported from
   padEditor.js so index.js can reuse it without duplicating the
   USER_NEWINFO emit.

2. The browser's native spellcheck was red-underlining "@ai" in the
   chat input as a misspelling. postAceInit now sets
   spellcheck="false" on #chatinput so the trigger token (and any
   other unfamiliar identifiers a user types) read clean.

The hover-tooltip-with-usage-hint and an actual /help command are
deliberately deferred — both deserve a small product decision (do
we crowd the user chip, or build a small help affordance in the
chat?), and neither blocks the basic flow.
@qodo-code-review
Copy link
Copy Markdown

ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one.

…le export

announceAiAuthor was reading socketio off
require('ep_etherpad-lite/node/hooks/express').socketio at module
load time. That property has never existed on the express hooks
module — Etherpad exposes the io reference to plugins through the
socketio hook (the same way adminsettings.ts and specialpages.ts
receive it). Result: the broadcast was a silent no-op for every
caller, including the new userJoin announce, so the AI chip
never appeared in the user list.

- Register a socketio hook in ep.json and capture the io reference
  in a module-level let var.
- Thread the captured reference through to applyEdit, suggestEdit
  and announceAiAuthor as an explicit parameter — no more reach-
  ing into etherpad-core for state that isn't there.
- Add diagnostic logs around userJoin and announceAiAuthor so the
  next time something silently no-ops we'll see it.
@JohnMcLear JohnMcLear merged commit c00b91d into main May 2, 2026
3 checks passed
JohnMcLear added a commit that referenced this pull request May 3, 2026
…lay name

Override the default "@<name> " chat-input prefill with the configured
AI trigger ("@ai " by default) when a user clicks the AI's row in the
user list. Without this, clicking the AI chip would prefill
"@AI_Assistant ", which doesn't match anything the server-side mention
extractor recognises.

What this PR adds:
- clientVars server hook exposing { trigger, authorName, authorId } at
  clientVars.ep_ai_chat so the client can recognise the AI's row.
- chatPrefillFromUser client hook that returns the trigger string when
  the clicked authorId matches the AI's; otherwise returns nothing so
  core's default ("@<name> ") wins.
- Mocha unit test (static/tests/backend/specs/chat_prefill.ts) covering
  AI/non-AI/missing-clientVars/custom-trigger/missing-trigger paths.

Depends on ether/etherpad#7660 which adds the chatPrefillFromUser hook
to core. On older cores the hook is never fired and this PR is a
benign no-op — graceful degradation, no install requirement bump.

Originally this PR shipped the entire user-list click handler inside
the plugin. Per review feedback, the generic "click a user → prefill
@-mention" UX belongs in core (it's a discoverability win for any
multi-user pad, AI or no AI), so the bulk moved to ether/etherpad#7660
and this PR is now ~40 lines of glue.

(Replaces the previous 3-commit history on this branch with a clean
rebase against the new main, which absorbed PRs #18 and #20 since the
branch was opened.)
JohnMcLear added a commit that referenced this pull request May 3, 2026
…lay name (#19)

Override the default "@<name> " chat-input prefill with the configured
AI trigger ("@ai " by default) when a user clicks the AI's row in the
user list. Without this, clicking the AI chip would prefill
"@AI_Assistant ", which doesn't match anything the server-side mention
extractor recognises.

What this PR adds:
- clientVars server hook exposing { trigger, authorName, authorId } at
  clientVars.ep_ai_chat so the client can recognise the AI's row.
- chatPrefillFromUser client hook that returns the trigger string when
  the clicked authorId matches the AI's; otherwise returns nothing so
  core's default ("@<name> ") wins.
- Mocha unit test (static/tests/backend/specs/chat_prefill.ts) covering
  AI/non-AI/missing-clientVars/custom-trigger/missing-trigger paths.

Depends on ether/etherpad#7660 which adds the chatPrefillFromUser hook
to core. On older cores the hook is never fired and this PR is a
benign no-op — graceful degradation, no install requirement bump.

Originally this PR shipped the entire user-list click handler inside
the plugin. Per review feedback, the generic "click a user → prefill
@-mention" UX belongs in core (it's a discoverability win for any
multi-user pad, AI or no AI), so the bulk moved to ether/etherpad#7660
and this PR is now ~40 lines of glue.

(Replaces the previous 3-commit history on this branch with a clean
rebase against the new main, which absorbed PRs #18 and #20 since the
branch was opened.)
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

🎉 This PR is included in version 1.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant