From 6b7d1e91e0a729b9af962b4107803e8997ff57f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=B7=E5=B8=83=E5=8A=B3=E5=A4=96=20=C2=B7=20=E8=B4=BE?= =?UTF-8?q?=E8=B4=B5?= <472285740@qq.com> Date: Thu, 10 Jul 2025 17:25:05 +0800 Subject: [PATCH] feat(core): apply model tracking (#13128) ## Summary by CodeRabbit * **New Features** * Added user interaction tracking for document editing and diff review actions, including accepting, rejecting, applying, and copying changes. * Introduced tracking for "Accept all" and "Reject all" actions in block diff views. * **Chores** * Enhanced event tracking system with new event types and payloads to support detailed analytics for editing and review actions. --- .../ai/components/ai-tools/doc-edit.ts | 17 ++++++++-- .../ai/widgets/block-diff/options.ts | 5 +-- .../blocksuite/ai/widgets/block-diff/page.ts | 15 +++++++-- packages/frontend/track/src/events.ts | 32 ++++++++++++++++++- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-edit.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-edit.ts index c49a0b14db..1552bd4c45 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-edit.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-edit.ts @@ -1,3 +1,4 @@ +import track from '@affine/track'; import { WithDisposable } from '@blocksuite/affine/global/lit'; import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine/shared/theme'; import { type EditorHost, ShadowlessElement } from '@blocksuite/affine/std'; @@ -203,24 +204,33 @@ export class DocEditTool extends WithDisposable(ShadowlessElement) { } private async _handleApply(markdown: string) { - if (!this.host) { + if (!this.host || this.data.type !== 'tool-result') { return; } + track.applyModel.chat.$.apply({ + instruction: this.data.args.instructions, + }); await this.blockDiffService?.apply(this.host.store, markdown); } private async _handleReject(changedMarkdown: string) { - if (!this.host) { + if (!this.host || this.data.type !== 'tool-result') { return; } + track.applyModel.chat.$.reject({ + instruction: this.data.args.instructions, + }); this.blockDiffService?.setChangedMarkdown(changedMarkdown); this.blockDiffService?.rejectAll(); } private async _handleAccept(changedMarkdown: string) { - if (!this.host) { + if (!this.host || this.data.type !== 'tool-result') { return; } + track.applyModel.chat.$.accept({ + instruction: this.data.args.instructions, + }); await this.blockDiffService?.apply(this.host.store, changedMarkdown); await this.blockDiffService?.acceptAll(this.host.store); } @@ -233,6 +243,7 @@ export class DocEditTool extends WithDisposable(ShadowlessElement) { if (!this.host) { return; } + track.applyModel.chat.$.copy(); const success = await copyText(removeMarkdownComments(changedMarkdown)); if (success) { this.notificationService.notify({ diff --git a/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/options.ts b/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/options.ts index 7512978cb6..e41070ebf3 100644 --- a/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/options.ts +++ b/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/options.ts @@ -1,3 +1,4 @@ +import track from '@affine/track'; import { WithDisposable } from '@blocksuite/affine/global/lit'; import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine/shared/theme'; import { CloseIcon, DoneIcon } from '@blocksuite/icons/lit'; @@ -50,12 +51,12 @@ export class BlockDiffOptions extends WithDisposable(LitElement) { accessor onReject!: (op: PatchOp) => void; private readonly _handleAcceptClick = () => { - console.log('accept', this.op); + track.applyModel.widget.block.accept(); this.onAccept(this.op); }; private readonly _handleRejectClick = () => { - console.log('reject', this.op); + track.applyModel.widget.block.reject(); this.onReject(this.op); }; diff --git a/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/page.ts b/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/page.ts index 71d9d847b6..58faa62282 100644 --- a/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/page.ts +++ b/packages/frontend/core/src/blocksuite/ai/widgets/block-diff/page.ts @@ -1,3 +1,4 @@ +import { track } from '@affine/track'; import { WidgetComponent, WidgetViewExtension } from '@blocksuite/affine/std'; import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme'; import { @@ -82,6 +83,16 @@ export class AffineBlockDiffWidgetForPage extends WidgetComponent { diffs[this.currentIndex].scrollIntoView({ behavior: 'smooth' }); } + async _handleAcceptAll() { + track.applyModel.widget.page.acceptAll(); + await this.diffService.acceptAll(this.std.store); + } + + _handleRejectAll() { + track.applyModel.widget.page.rejectAll(); + this.diffService.rejectAll(); + } + get diffService() { return this.std.get(BlockDiffProvider); } @@ -112,7 +123,7 @@ export class AffineBlockDiffWidgetForPage extends WidgetComponent {
this.diffService.rejectAll()} + @click=${() => this._handleRejectAll()} > ${CloseIcon({ style: `color: ${unsafeCSSVarV2('icon/secondary')}`, @@ -121,7 +132,7 @@ export class AffineBlockDiffWidgetForPage extends WidgetComponent {
this.diffService.acceptAll(this.std.store)} + @click=${() => this._handleAcceptAll()} > ${DoneIcon({ style: `color: ${unsafeCSSVarV2('icon/activated')}`, diff --git a/packages/frontend/track/src/events.ts b/packages/frontend/track/src/events.ts index 6dc259cfbd..70b8057210 100644 --- a/packages/frontend/track/src/events.ts +++ b/packages/frontend/track/src/events.ts @@ -207,6 +207,16 @@ type CommentEvents = | 'resolveComment'; // END SECTION +// SECTION: apply model +type ApplyModelEvents = + | 'acceptAll' + | 'rejectAll' + | 'accept' + | 'reject' + | 'apply' + | 'copy'; +// END SECTION + type UserEvents = | GeneralEvents | AppEvents @@ -231,7 +241,8 @@ type UserEvents = | IntegrationEvents | MeetingEvents | MentionEvents - | WorkspaceEmbeddingEvents; + | WorkspaceEmbeddingEvents + | ApplyModelEvents; interface PageDivision { [page: string]: { @@ -564,6 +575,15 @@ interface PageEvents extends PageDivision { $: ['createDoc']; }; }; + applyModel: { + widget: { + page: ['acceptAll', 'rejectAll']; + block: ['accept', 'reject']; + }; + chat: { + $: ['apply', 'accept', 'reject', 'copy']; + }; + }; } type OrganizeItemType = 'doc' | 'folder' | 'collection' | 'tag' | 'favorite'; @@ -635,6 +655,13 @@ type RecordingEventArgs = { option?: 'Auto transcribing' | 'handle transcribing' | 'on' | 'off'; }; +type ApplyModelArgs = { + /* ​​User's complete instruction */ + instruction?: string; + /* Split individual semantic change requests */ + operation?: string; +}; + export type EventArgs = { createWorkspace: { flavour: string }; signIn: AuthArgs; @@ -829,6 +856,9 @@ export type EventArgs = { }; editComment: { type: 'root' | 'node' }; deleteComment: { type: 'root' | 'node' }; + accept: ApplyModelArgs; + reject: ApplyModelArgs; + apply: ApplyModelArgs; }; // for type checking