The agent write-stamp idiom — `...(isAgent ? { <source>: 'agent', <chat>: aiChatId } : {})`
— was hand-reimplemented at every REST write site, so each new path risked a
wrong literal or a forgotten aiChatId. Extract a single
`agentSourceFields(provenance, sourceKey, chatKey)` next to AuthProvenanceData and
call it at the 5 uniform spread sites:
- comment.service create -> createdSource / aiChatId
- page.service create/update/orphan-move/move -> lastUpdatedSource / lastUpdatedAiChatId
Sites that must CLEAR the source on a non-agent action keep their own conditional
(comment un-resolve writes an explicit null), and the collab persistence path keeps
its sticky-window logic — both noted in the helper's doc.
Behavior-preserving (the helper returns the identical object/`{}`). Typecheck
clean; server comment/page/auth/collab suites 246 pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,10 @@ import {
|
||||
ICommentResolvedNotificationJob,
|
||||
} from '../../integrations/queue/constants/queue.interface';
|
||||
import { WsService } from '../../ws/ws.service';
|
||||
import { AuthProvenanceData } from '../../common/decorators/auth-provenance.decorator';
|
||||
import {
|
||||
AuthProvenanceData,
|
||||
agentSourceFields,
|
||||
} from '../../common/decorators/auth-provenance.decorator';
|
||||
|
||||
@Injectable()
|
||||
export class CommentService {
|
||||
@@ -60,7 +63,6 @@ export class CommentService {
|
||||
) {
|
||||
const { page, workspaceId, user } = opts;
|
||||
const commentContent = JSON.parse(createCommentDto.content);
|
||||
const isAgent = provenance?.actor === 'agent';
|
||||
|
||||
if (createCommentDto.parentCommentId) {
|
||||
const parentComment = await this.commentRepo.findById(
|
||||
@@ -87,9 +89,7 @@ export class CommentService {
|
||||
spaceId: page.spaceId,
|
||||
// Agent-edit provenance: the user stays creatorId; this only annotates the
|
||||
// source. Normal user requests leave the column default ('user').
|
||||
...(isAgent
|
||||
? { createdSource: 'agent', aiChatId: provenance.aiChatId }
|
||||
: {}),
|
||||
...agentSourceFields(provenance, 'createdSource', 'aiChatId'),
|
||||
});
|
||||
|
||||
if (createCommentDto.yjsSelection) {
|
||||
|
||||
@@ -57,7 +57,10 @@ import { WatcherService } from '../../watcher/watcher.service';
|
||||
import { sql } from 'kysely';
|
||||
import { TransclusionService } from '../transclusion/transclusion.service';
|
||||
import { remapPageEmbedSourceId } from '../transclusion/utils/transclusion-prosemirror.util';
|
||||
import { AuthProvenanceData } from '../../../common/decorators/auth-provenance.decorator';
|
||||
import {
|
||||
AuthProvenanceData,
|
||||
agentSourceFields,
|
||||
} from '../../../common/decorators/auth-provenance.decorator';
|
||||
|
||||
@Injectable()
|
||||
export class PageService {
|
||||
@@ -135,7 +138,6 @@ export class PageService {
|
||||
ydoc = createYdocFromJson(prosemirrorJson);
|
||||
}
|
||||
|
||||
const isAgent = provenance?.actor === 'agent';
|
||||
|
||||
const page = await this.pageRepo.insertPage({
|
||||
slugId: generateSlugId(),
|
||||
@@ -153,12 +155,7 @@ export class PageService {
|
||||
// Agent-edit provenance. The human stays the responsible author
|
||||
// (creatorId/lastUpdatedById); these only annotate the source. A normal
|
||||
// user request leaves the column default ('user').
|
||||
...(isAgent
|
||||
? {
|
||||
lastUpdatedSource: 'agent',
|
||||
lastUpdatedAiChatId: provenance.aiChatId,
|
||||
}
|
||||
: {}),
|
||||
...agentSourceFields(provenance, 'lastUpdatedSource', 'lastUpdatedAiChatId'),
|
||||
content,
|
||||
textContent,
|
||||
ydoc,
|
||||
@@ -231,7 +228,6 @@ export class PageService {
|
||||
contributors.add(user.id);
|
||||
const contributorIds = Array.from(contributors);
|
||||
|
||||
const isAgent = provenance?.actor === 'agent';
|
||||
|
||||
// Detect a real title/icon change so the WS tree listener can broadcast an
|
||||
// `updateOne` to the space (rename / icon swap) WITHOUT re-broadcasting on a
|
||||
@@ -251,12 +247,7 @@ export class PageService {
|
||||
lastUpdatedById: user.id,
|
||||
// Agent-edit provenance: annotate the source without changing the
|
||||
// responsible author. A normal user request leaves the column default.
|
||||
...(isAgent
|
||||
? {
|
||||
lastUpdatedSource: 'agent',
|
||||
lastUpdatedAiChatId: provenance.aiChatId,
|
||||
}
|
||||
: {}),
|
||||
...agentSourceFields(provenance, 'lastUpdatedSource', 'lastUpdatedAiChatId'),
|
||||
updatedAt: new Date(),
|
||||
contributorIds: contributorIds,
|
||||
},
|
||||
@@ -443,7 +434,6 @@ export class PageService {
|
||||
provenance?: AuthProvenanceData,
|
||||
) {
|
||||
let childPageIds: string[] = [];
|
||||
const isAgent = provenance?.actor === 'agent';
|
||||
|
||||
const allPages = await this.pageRepo.getPageAndDescendants(rootPage.id, {
|
||||
includeContent: false,
|
||||
@@ -490,12 +480,7 @@ export class PageService {
|
||||
// Agent-edit provenance on the moved root page. Child pages are bulk
|
||||
// re-parented to the new space (no content change), so the marker is
|
||||
// stamped on the root the agent acted on. Normal user: no change.
|
||||
...(isAgent
|
||||
? {
|
||||
lastUpdatedSource: 'agent',
|
||||
lastUpdatedAiChatId: provenance.aiChatId,
|
||||
}
|
||||
: {}),
|
||||
...agentSourceFields(provenance, 'lastUpdatedSource', 'lastUpdatedAiChatId'),
|
||||
},
|
||||
rootPage.id,
|
||||
trx,
|
||||
@@ -949,7 +934,6 @@ export class PageService {
|
||||
}
|
||||
}
|
||||
|
||||
const isAgent = provenance?.actor === 'agent';
|
||||
|
||||
const updateResult = await this.pageRepo.updatePage(
|
||||
{
|
||||
@@ -957,12 +941,7 @@ export class PageService {
|
||||
parentPageId: parentPageId,
|
||||
// Agent-edit provenance: annotate the source on an agent move. A normal
|
||||
// user request leaves the column default ('user').
|
||||
...(isAgent
|
||||
? {
|
||||
lastUpdatedSource: 'agent',
|
||||
lastUpdatedAiChatId: provenance.aiChatId,
|
||||
}
|
||||
: {}),
|
||||
...agentSourceFields(provenance, 'lastUpdatedSource', 'lastUpdatedAiChatId'),
|
||||
},
|
||||
dto.pageId,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user