Skip to content

feat: add ai hint that content contains ai generated text#13022

Open
GretaD wants to merge 1 commit into
mainfrom
feat/ai-hint-for-ai-content
Open

feat: add ai hint that content contains ai generated text#13022
GretaD wants to merge 1 commit into
mainfrom
feat/ai-hint-for-ai-content

Conversation

@GretaD

@GretaD GretaD commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

fixes #12689
Screenshot from 2026-06-25 17-36-56

@GretaD GretaD self-assigned this Jun 3, 2026
@GretaD GretaD force-pushed the feat/ai-hint-for-ai-content branch 2 times, most recently from 21163d0 to 2f099a7 Compare June 16, 2026 11:54
@GretaD GretaD force-pushed the feat/ai-hint-for-ai-content branch from 17eabe8 to f884e5c Compare June 25, 2026 13:30
@GretaD GretaD marked this pull request as ready for review June 25, 2026 15:37
@GretaD GretaD force-pushed the feat/ai-hint-for-ai-content branch from 26ca113 to 59506e7 Compare June 25, 2026 15:42
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change introduces an AI-generated content flag across the mail stack. The IMAP fetcher reads an x-ai-generated header and passes it into IMAPMessage, which propagates it into the Message DB entity via a new flagAiGenerated field, exposed via accessors and included in JSON serialization. A migration adjusts the corresponding database schema. LocalMessage also registers a type for its existing requestMdn field. In the frontend, ThreadEnvelope.vue displays an "Contains AI content" label with an icon when the envelope's aiGenerated flag is true, with supporting layout and styling updates.

Changes

Cohort / File(s) Summary
DB schema & migrationlib/Db/Message.php, lib/Db/LocalMessage.php, lib/Migration/Version5201Date20260604000000.php Adds flagAiGenerated property, accessors, type registration, JSON serialization for Message; registers requestMdn type in LocalMessage; migration drops ai_generated from mail_local_messages and adds flag_ai_generated to mail_messages.
IMAP fetch & propagationlib/IMAP/ImapMessageFetcher.php, lib/Model/IMAPMessage.php Reads x-ai-generated header, stores flag, passes it to IMAPMessage constructor, and sets flagAiGenerated on the DB message during conversion.
UI labelsrc/components/ThreadEnvelope.vue Adds AiIcon, hasAiGeneratedContent computed property, conditional label rendering, and layout/styling updates.

Sequence Diagram(s)

sequenceDiagram
  participant ImapMessageFetcher
  participant IMAPMessage
  participant Message
  participant ThreadEnvelope

  ImapMessageFetcher->>ImapMessageFetcher: parseHeaders reads x-ai-generated
  ImapMessageFetcher->>IMAPMessage: construct with isAiGenerated
  IMAPMessage->>Message: toDbMessage sets flagAiGenerated
  Message-->>ThreadEnvelope: jsonSerialize exposes flags.aiGenerated
  ThreadEnvelope->>ThreadEnvelope: hasAiGeneratedContent computed
  ThreadEnvelope->>ThreadEnvelope: render AI content label
Loading

Related issues: #12990, #12689

Suggested labels: enhancement, feature

Suggested reviewers: GretaD, st3iny


🐰 A whisper of AI now tags each mail,
A flag in the schema, a header in the trail,
From IMAP it travels, through message and view,
A small icon glowing, "AI wrote this too!"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: adding an AI-generated content hint in the UI.
Linked Issues check ✅ Passed [#12990] The PR implements the requested AI-generated message hint by persisting the flag and surfacing it in the thread UI.
Out of Scope Changes check ✅ Passed All changes support detecting, storing, and displaying the AI-generated content hint; no unrelated additions are evident.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 feat/ai-hint-for-ai-content

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eed45071-7465-42a0-93d9-22edd4613038

📥 Commits

Reviewing files that changed from the base of the PR and between 7fb0a1c and b8d17c6.

📒 Files selected for processing (6)
  • lib/Db/LocalMessage.php
  • lib/Db/Message.php
  • lib/IMAP/ImapMessageFetcher.php
  • lib/Migration/Version5201Date20260604000000.php
  • lib/Model/IMAPMessage.php
  • src/components/ThreadEnvelope.vue
💤 Files with no reviewable changes (1)
  • lib/Db/LocalMessage.php

Comment on lines +1202 to +1205
display: flex;
align-items: center;
gap: 6px;
min-width: 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Replace hardcoded pixel gaps with Nextcloud CSS variables.

gap: 6px and gap: 4px are magic numbers. Per coding guidelines, spacing should use Nextcloud CSS variables (with calc() for finer control) rather than literal pixel values.

As per coding guidelines: "Use Nextcloud CSS variables for all CSS colors, spacing, and dimensions; do not use magic numbers. Use calc(x*var) when needing more specific control over dimensions with CSS variables."

♻️ Proposed fix
 	.sender {
 		margin-inline-start: calc(var(--default-grid-baseline) * 3);
 		display: flex;
 		align-items: center;
-		gap: 6px;
+		gap: calc(var(--default-grid-baseline) * 1.5);
 		min-width: 0;
 	.ai-generated-label {
 		display: flex;
 		align-items: center;
-		gap: 4px;
+		gap: var(--default-grid-baseline);
 		opacity: 0.8;
 	}

Also applies to: 1502-1508

Source: Coding guidelines

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds end-to-end support for flagging messages as AI-generated: the composer can mark outgoing messages, the backend transmits/detects the flag via an email header and persists it on messages, and the UI surfaces a “Contains AI content” hint in the thread view.

Changes:

  • Add a composer toggle (and auto-mark on smart reply) to mark outgoing mail as AI-generated and send it via X-AI-Generated.
  • Detect X-AI-Generated on IMAP fetch and persist/expose the flag via message JSON flags.aiGenerated.
  • Show an AI label in the thread envelope when flags.aiGenerated is set.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/components/ThreadEnvelope.vue Displays an AI-content label in the sender line based on envelope.flags.aiGenerated.
src/components/Composer.vue Adds “Mark as AI generated” toggle and includes isAiGenerated in send payload; auto-sets it for smart replies.
lib/Service/MailTransmission.php Adds X-AI-Generated: 1 header when sending AI-generated local messages.
lib/Model/IMAPMessage.php Carries IMAP-detected AI flag into DB Message entity flags.
lib/Migration/Version5201Date20260604000000.php Schema change related to AI-generated flag storage.
lib/IMAP/ImapMessageFetcher.php Detects X-AI-Generated header during IMAP fetch.
lib/Db/Message.php Persists/serializes flagAiGenerated into JSON flags.aiGenerated.
lib/Db/LocalMessage.php Adds non-persisted aiGenerated flag on local messages (used for sending header).
lib/Controller/OutboxController.php Accepts isAiGenerated in outbox create/update requests and sets it on the LocalMessage.

Comment thread lib/Migration/Version5201Date20260604000000.php Outdated
Comment thread lib/Db/LocalMessage.php Outdated
Comment thread lib/IMAP/ImapMessageFetcher.php Outdated
@GretaD GretaD marked this pull request as draft July 2, 2026 07:29
@GretaD GretaD force-pushed the feat/ai-hint-for-ai-content branch 3 times, most recently from 5371779 to b5bcfc2 Compare July 7, 2026 15:05
@GretaD GretaD marked this pull request as ready for review July 7, 2026 15:06
Assisted-by: ClaudeCode:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-5

Signed-off-by: greta <gretadoci@gmail.com>
@kesselb kesselb force-pushed the feat/ai-hint-for-ai-content branch from b5bcfc2 to 4ee4979 Compare July 7, 2026 17:46

editorMode: (this.body?.format !== 'html') ? EDITOR_MODE_TEXT : EDITOR_MODE_HTML,
requestMdnVal: this.requestMdn,
isAiGeneratedVal: this.isAiGenerated,

@kesselb kesselb Jul 7, 2026

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.

Claude: Please also reset isAiGeneratedVal in reset method

}
if (this.smartReply) {
this.bus.emit('append-to-body-at-cursor', this.smartReply)
this.isAiGeneratedVal = true

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.

Claude flagged this block, because a onEditorReady event (e.g the user is changing the alias) would insert the smart reply again, reset isAiGeneratedVal to true, and overwrite the user's choice. I think it's okay for now to ignore it, but we should look into a better way as follow up.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a tag/header on the sent email. It will signal to the recipient that they are receiving (partly) generated content.

3 participants