Skip to content

Feat/fix: AI titles/Quotes for webhooks#133

Merged
XeIris merged 3 commits intomasterfrom
ei-will-kill-me
Apr 7, 2026
Merged

Feat/fix: AI titles/Quotes for webhooks#133
XeIris merged 3 commits intomasterfrom
ei-will-kill-me

Conversation

@XeIris
Copy link
Copy Markdown
Collaborator

@XeIris XeIris commented Apr 7, 2026

also new poop log message

Summary by CodeRabbit

  • New Features

    • AI chat sessions now auto-generate concise conversation titles and persist them.
  • Improvements

    • Better handling of quoted/referenced messages originating from webhooks.
    • More reliable avatar fallback logic for quoted messages.
  • UI Updates

    • Session labels prefer auto-generated titles over persona names.
    • Updated success message wording in the logging interface.

also new poop log message
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4fe16d2a-d4e1-43e4-a7a8-3eb51b1db589

📥 Commits

Reviewing files that changed from the base of the PR and between 8900dfe and 4dc199c.

📒 Files selected for processing (5)
  • classes/handlers/keywordsBehaviorHandler.ts
  • classes/silverwolf.ts
  • database/queries/aiChatQueries.ts
  • utils/ai.ts
  • utils/quote.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • database/queries/aiChatQueries.ts
  • classes/silverwolf.ts

📝 Walkthrough

Walkthrough

Adds automatic AI session title generation: when a new conversation has empty history, the grok handler requests a concise title from a TitleGen persona, then persists it to the DB. Also adds title storage to the schema, a helper to generate titles, minor UI text and avatar/webhook handling tweaks.

Changes

Cohort / File(s) Summary
Session Title Generation
classes/handlers/keywordsBehaviorHandler.ts, utils/ai.ts, data/aiPersonas.json
Invoke generateSessionTitle for newly-created sessions (history length === 0) and persist non-empty titles; added TitleGen persona and generateSessionTitle() helper. Title-generation errors are isolated to their own try/catch.
Database Layer
database/tables/aiChatSessionTable.ts, database/queries/aiChatQueries.ts, database/models/AiChatModel.ts
Added nullable title column to session schema, UPDATE_SESSION_TITLE query (only updates when title IS NULL), and AiChatModel.updateTitle(sessionId, title).
Display & Messages
commands/ai_view.ts, commands/poop_log.ts
UI now prefers s.title over s.personaName for session labels; changed poop-log success text to start with flushed🚽!.
Message & Avatar Handling
classes/silverwolf.ts, utils/quote.ts
Skip guild-member fetch when referenced message is from a webhook; added resolveAvatarUrl(person) and broadened quote() to accept `User

Sequence Diagram

sequenceDiagram
    participant Handler as Grok Handler
    participant AI as OpenRouter (TitleGen)
    participant DB as Database

    Handler->>Handler: Receive user message / determine session
    Handler->>DB: attempt db.aiChat.getHistory(sessionId)
    Handler->>Handler: Append user + assistant messages to history
    alt historyLoaded && history.length === 0
        Handler->>AI: generateSessionTitle(userMessage, aiResponse)
        AI-->>Handler: Return title (or null)
        alt title returned
            Handler->>DB: updateTitle(sessionId, title)
            DB-->>Handler: Acknowledgement
        end
    end
    Handler-->>Handler: Continue normal flow
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

ai

Poem

🐰 I sniffed the chat and gave a name,
Five to ten words, neat and tame.
TitleGen hummed, the DB took note,
Now sessions wear a tiny coat.
Hoppity hop — a tidy chat, hooray!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feat/fix: AI titles/Quotes for webhooks' directly reflects the main changes: AI session title generation and webhook-aware quote handling.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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 ei-will-kill-me

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.

Copy link
Copy Markdown

@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

🧹 Nitpick comments (2)
database/queries/aiChatQueries.ts (1)

17-17: Make the title update idempotent.

Because the “first message” decision is made before this write, two concurrent first turns can both reach Line 17 and last-writer-wins the title. Guarding the update with AND title IS NULL keeps the first generated title stable.

Possible SQL tweak
-  UPDATE_SESSION_TITLE: 'UPDATE AiChatSession SET title = ? WHERE session_id = ?',
+  UPDATE_SESSION_TITLE: 'UPDATE AiChatSession SET title = ? WHERE session_id = ? AND title IS NULL',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@database/queries/aiChatQueries.ts` at line 17, The UPDATE_SESSION_TITLE SQL
should be made idempotent so concurrent “first message” writes don't race;
update the string constant UPDATE_SESSION_TITLE in aiChatQueries.ts to include a
guard like "AND title IS NULL" (i.e., only set title when it's currently NULL)
so only the first writer wins and subsequent concurrent updates are no-ops.
classes/silverwolf.ts (1)

290-296: Fallback when the referenced member can't be fetched.

Line 294 can still reject for quoted users who left the guild or can't be fetched, which means the temporary Generating... reply never gets replaced. Falling back to person.username keeps the quote path resilient for that case too.

Possible hardening
         if (referencedMessage.webhookId) {
           nickname = referencedMessage.author.username;
         } else {
-          const guildMember = await message.guild.members.fetch(referencedMessage.author.id);
-          nickname = guildMember.nickname || person.username;
+          try {
+            const guildMember = await message.guild.members.fetch(referencedMessage.author.id);
+            nickname = guildMember.nickname || person.username;
+          } catch {
+            nickname = person.username;
+          }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@classes/silverwolf.ts` around lines 290 - 296, The fetch of the referenced
guild member (used to set nickname) can throw if the quoted user left or can't
be fetched; update the logic around
message.guild.members.fetch(referencedMessage.author.id) so it is wrapped in a
try/catch (or use .catch) and on any failure fall back to person.username;
ensure the variable nickname still gets assigned either guildMember.nickname ||
person.username when fetch succeeds or person.username when it fails so the
temporary "Generating..." reply is always replaced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@classes/handlers/keywordsBehaviorHandler.ts`:
- Around line 230-241: The code wrongly treats an empty history array as a
signal of a new session even when getHistory() may have failed; add a boolean
flag (e.g., historyLoaded) that is set true only when getHistory() completes
successfully and only run the title-generation block when historyLoaded is true
and history.length === 0; update the logic around getHistory(), the history
variable, and the async title-generation block (references: getHistory(),
history, generateSessionTitle(), aiChat.updateTitle(), aiSession.sessionId) so
transient read failures do not cause a new title to be generated or persisted.

In `@utils/ai.ts`:
- Around line 241-259: The model output from generateSessionTitle must be
normalized and size-limited before returning: after getting
completion.choices?.[0]?.message?.content, collapse all whitespace/newlines into
single spaces, trim ends, then truncate to a safe length (e.g., limit to 10
words or ~80 characters) and ensure it is a single-line string; return null if
the normalized result is empty. Update generateSessionTitle to perform this
normalization/clamping (use the persona variable and the completion result from
openrouter.chat.completions.create to locate where to apply the change).

---

Nitpick comments:
In `@classes/silverwolf.ts`:
- Around line 290-296: The fetch of the referenced guild member (used to set
nickname) can throw if the quoted user left or can't be fetched; update the
logic around message.guild.members.fetch(referencedMessage.author.id) so it is
wrapped in a try/catch (or use .catch) and on any failure fall back to
person.username; ensure the variable nickname still gets assigned either
guildMember.nickname || person.username when fetch succeeds or person.username
when it fails so the temporary "Generating..." reply is always replaced.

In `@database/queries/aiChatQueries.ts`:
- Line 17: The UPDATE_SESSION_TITLE SQL should be made idempotent so concurrent
“first message” writes don't race; update the string constant
UPDATE_SESSION_TITLE in aiChatQueries.ts to include a guard like "AND title IS
NULL" (i.e., only set title when it's currently NULL) so only the first writer
wins and subsequent concurrent updates are no-ops.
🪄 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: 0ce19195-3037-4d29-8593-177fe963dcd0

📥 Commits

Reviewing files that changed from the base of the PR and between b3b1dca and 8900dfe.

📒 Files selected for processing (10)
  • classes/handlers/keywordsBehaviorHandler.ts
  • classes/silverwolf.ts
  • commands/ai_view.ts
  • commands/poop_log.ts
  • data/aiPersonas.json
  • database/models/AiChatModel.ts
  • database/queries/aiChatQueries.ts
  • database/tables/aiChatSessionTable.ts
  • utils/ai.ts
  • utils/quote.ts

Comment thread classes/handlers/keywordsBehaviorHandler.ts Outdated
Comment thread utils/ai.ts
Comment thread utils/quote.ts Outdated
@XeIris
Copy link
Copy Markdown
Collaborator Author

XeIris commented Apr 7, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 7, 2026

✅ Actions performed

Review triggered.

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.

@XeIris XeIris merged commit 3f96f4d into master Apr 7, 2026
1 check passed
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.

Rename /poop log success message to flushed🚽! Auto generate titles for Ai sessions (broken) Quote feature via mention breaks for webhook

1 participant