From 58bbb017a08f840b55e663a5243f78e6b1412c7a Mon Sep 17 00:00:00 2001 From: akumatus Date: Thu, 29 May 2025 02:49:11 +0000 Subject: [PATCH] feat(core): add ai playground components (#12588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close [AI-86](https://linear.app/affine-design/issue/AI-86) ![截屏2025-05-28 11.56.18.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/bdf157ce-150c-407c-877f-24a88e7927b1.png) ## Summary by CodeRabbit - **New Features** - Introduced an AI Playground accessible from the chat panel, allowing users to experiment with AI chat sessions in a dedicated modal interface. - Added a playground icon to the chat panel for quick access to the new playground feature. - Added new interactive components for managing AI chat sessions, including chat panels, session lists, and modal dialogs. - **Improvements** - Enhanced chat panel session management for a smoother experience by simplifying session filtering. - Updated property names in chat input and composer components for improved clarity and consistency. - Made tracking options optional in chat input and composer components to improve flexibility. - **Bug Fixes** - Corrected property bindings in AI chat composer to ensure proper panel sizing. --- .../core/src/blocksuite/ai/actions/types.ts | 4 +- .../src/blocksuite/ai/chat-panel/index.ts | 58 +++- .../ai-chat-composer/ai-chat-composer.ts | 6 +- .../components/ai-chat-input/ai-chat-input.ts | 10 +- .../ai/components/playground/chat.ts | 321 ++++++++++++++++++ .../ai/components/playground/content.ts | 190 +++++++++++ .../ai/components/playground/index.ts | 9 + .../ai/components/playground/modal.ts | 139 ++++++++ .../core/src/blocksuite/ai/effects.ts | 2 + 9 files changed, 717 insertions(+), 22 deletions(-) create mode 100644 packages/frontend/core/src/blocksuite/ai/components/playground/chat.ts create mode 100644 packages/frontend/core/src/blocksuite/ai/components/playground/content.ts create mode 100644 packages/frontend/core/src/blocksuite/ai/components/playground/index.ts create mode 100644 packages/frontend/core/src/blocksuite/ai/components/playground/modal.ts diff --git a/packages/frontend/core/src/blocksuite/ai/actions/types.ts b/packages/frontend/core/src/blocksuite/ai/actions/types.ts index f690489d9d..de8ea85392 100644 --- a/packages/frontend/core/src/blocksuite/ai/actions/types.ts +++ b/packages/frontend/core/src/blocksuite/ai/actions/types.ts @@ -85,8 +85,8 @@ declare global { // internal context host: EditorHost; models?: (BlockModel | GfxModel)[]; - control: TrackerControl; - where: TrackerWhere; + control?: TrackerControl; + where?: TrackerWhere; } interface AIForkChatSessionOptions { diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts index 33df0497cd..baa72ed316 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts @@ -3,11 +3,13 @@ import './chat-panel-messages'; import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; import type { ContextEmbedStatus, CopilotSessionType } from '@affine/graphql'; import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit'; +import { unsafeCSSVarV2 } from '@blocksuite/affine/shared/theme'; import type { EditorHost } from '@blocksuite/affine/std'; import { ShadowlessElement } from '@blocksuite/affine/std'; import type { ExtensionType, Store } from '@blocksuite/affine/store'; +import { CenterPeekIcon } from '@blocksuite/icons/lit'; import { type Signal, signal } from '@preact/signals-core'; -import { css, html, type PropertyValues } from 'lit'; +import { css, html, nothing, type PropertyValues } from 'lit'; import { property, state } from 'lit/decorators.js'; import { createRef, type Ref, ref } from 'lit/directives/ref.js'; import { styleMap } from 'lit/directives/style-map.js'; @@ -23,6 +25,7 @@ import type { AIReasoningConfig, } from '../components/ai-chat-input'; import { type HistoryMessage } from '../components/ai-chat-messages'; +import { createPlaygroundModal } from '../components/playground/modal'; import { AIProvider } from '../provider'; import { extractSelectedContent } from '../utils/extract'; import { @@ -104,6 +107,20 @@ export class ChatPanel extends SignalWatcher( .chat-panel-hints :nth-child(2) { color: var(--affine-text-secondary-color); } + + .chat-panel-playground { + cursor: pointer; + padding: 2px; + margin-left: 8px; + margin-right: auto; + display: flex; + justify-content: center; + align-items: center; + } + + .chat-panel-playground:hover svg { + color: ${unsafeCSSVarV2('icon/activated')}; + } `; private readonly _chatMessagesRef: Ref = @@ -165,13 +182,7 @@ export class ChatPanel extends SignalWatcher( this.doc.id, { action: false } )) || [] - ).filter(session => { - if (this.parentSessionId) { - return session.parentSessionId === this.parentSessionId; - } else { - return !session.parentSessionId; - } - }); + ).filter(session => !session.parentSessionId); this.session = sessions.at(-1); return this.session?.id; }; @@ -224,9 +235,6 @@ export class ChatPanel extends SignalWatcher( @property({ attribute: false }) accessor affineFeatureFlagService!: FeatureFlagService; - @property({ attribute: false }) - accessor parentSessionId: string | undefined = undefined; - @state() accessor isLoading = false; @@ -277,6 +285,25 @@ export class ChatPanel extends SignalWatcher( this.embeddingProgress = [0, 0]; }; + private readonly _openPlayground = () => { + const playgroundContent = html` + + `; + + createPlaygroundModal(playgroundContent, 'AI Playground'); + }; + protected override willUpdate(_changedProperties: PropertyValues) { if (_changedProperties.has('doc')) { this._resetPanel(); @@ -404,6 +431,13 @@ export class ChatPanel extends SignalWatcher( >` : 'AFFiNE AI'} + ${this.modelSwitchConfig.visible.value + ? html` +
+ ${CenterPeekIcon()} +
+ ` + : nothing} `; } diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts index 837d8c7786..a09407aaf1 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts @@ -97,13 +97,13 @@ export class AIChatComposer extends SignalWatcher( accessor onChatSuccess: (() => void) | undefined; @property({ attribute: false }) - accessor trackOptions!: BlockSuitePresets.TrackerOptions; + accessor trackOptions: BlockSuitePresets.TrackerOptions | undefined; @property({ attribute: false }) accessor portalContainer: HTMLElement | null = null; @property({ attribute: false }) - accessor sideBarWidth: Signal = signal(undefined); + accessor panelWidth: Signal = signal(undefined); @state() accessor chips: ChatChip[] = []; @@ -144,7 +144,7 @@ export class AIChatComposer extends SignalWatcher( .docDisplayConfig=${this.docDisplayConfig} .onChatSuccess=${this.onChatSuccess} .trackOptions=${this.trackOptions} - .sideBarWidth=${this.sideBarWidth} + .panelWidth=${this.panelWidth} .addImages=${this.addImages} >