mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
fix(core): in edgeless mode, an error occurs when asking AI questions without selecting any content (#12437)
### TL;DR fix: in edgeless mode, an error occurs when asking AI questions without selecting any content > CLOSE AI-133 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added support for asking AI input in edgeless mode when no content is selected. - Enhanced AI panel behavior with improved input handling and chat message sending in edgeless mode. - **Bug Fixes** - Improved handling of AI chat input visibility and context extraction in edgeless mode. - **Tests** - Introduced new end-to-end tests to verify chat interactions with AI in edgeless mode. - Centralized editor content removal logic in test utilities for better maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -6,14 +6,9 @@ import {
|
||||
type ShapeElementModel,
|
||||
} from '@blocksuite/affine/model';
|
||||
import { matchModels } from '@blocksuite/affine/shared/utils';
|
||||
import type { BlockComponent, EditorHost } from '@blocksuite/affine/std';
|
||||
import type { BlockComponent } from '@blocksuite/affine/std';
|
||||
import type { GfxModel } from '@blocksuite/affine/std/gfx';
|
||||
|
||||
import {
|
||||
AFFINE_EDGELESS_COPILOT_WIDGET,
|
||||
type EdgelessCopilotWidget,
|
||||
} from '../widgets/edgeless-copilot';
|
||||
|
||||
export function mindMapToMarkdown(mindmap: MindmapElementModel) {
|
||||
let markdownStr = '';
|
||||
|
||||
@@ -45,17 +40,7 @@ export function isMindmapChild(ele: GfxModel) {
|
||||
return ele?.group instanceof MindmapElementModel && !isMindMapRoot(ele);
|
||||
}
|
||||
|
||||
export function getEdgelessCopilotWidget(
|
||||
host: EditorHost
|
||||
): EdgelessCopilotWidget {
|
||||
const rootBlockId = host.store.root?.id as string;
|
||||
const copilotWidget = host.view.getWidget(
|
||||
AFFINE_EDGELESS_COPILOT_WIDGET,
|
||||
rootBlockId
|
||||
) as EdgelessCopilotWidget;
|
||||
|
||||
return copilotWidget;
|
||||
}
|
||||
export { getEdgelessCopilotWidget } from './get-edgeless-copilot-widget';
|
||||
|
||||
export function findNoteBlockModel(blockElement: BlockComponent) {
|
||||
let curBlock = blockElement;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/std';
|
||||
|
||||
import type { EdgelessCopilotWidget } from '../widgets/edgeless-copilot';
|
||||
import { AFFINE_EDGELESS_COPILOT_WIDGET } from '../widgets/edgeless-copilot/constant';
|
||||
|
||||
export function getEdgelessCopilotWidget(
|
||||
host: EditorHost
|
||||
): EdgelessCopilotWidget {
|
||||
const rootBlockId = host.store.root?.id as string;
|
||||
const copilotWidget = host.view.getWidget(
|
||||
AFFINE_EDGELESS_COPILOT_WIDGET,
|
||||
rootBlockId
|
||||
) as EdgelessCopilotWidget;
|
||||
|
||||
return copilotWidget;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
|
||||
import { getContentFromSlice } from '../../utils';
|
||||
import type { CopilotTool } from '../tool/copilot-tool';
|
||||
import { getEdgelessCopilotWidget } from './edgeless';
|
||||
import { getEdgelessCopilotWidget } from './get-edgeless-copilot-widget';
|
||||
|
||||
export async function selectedToCanvas(host: EditorHost) {
|
||||
const gfx = host.std.get(GfxControllerIdentifier);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const AFFINE_EDGELESS_COPILOT_WIDGET = 'affine-edgeless-copilot-widget';
|
||||
@@ -27,13 +27,14 @@ import { styleMap } from 'lit/directives/style-map.js';
|
||||
import { literal, unsafeStatic } from 'lit/static-html.js';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../components/ai-item/types.js';
|
||||
import { AIProvider } from '../../provider/index.js';
|
||||
import { extractSelectedContent } from '../../utils/extract.js';
|
||||
import {
|
||||
AFFINE_AI_PANEL_WIDGET,
|
||||
AffineAIPanelWidget,
|
||||
} from '../ai-panel/ai-panel.js';
|
||||
import { EdgelessCopilotPanel } from '../edgeless-copilot-panel/index.js';
|
||||
|
||||
export const AFFINE_EDGELESS_COPILOT_WIDGET = 'affine-edgeless-copilot-widget';
|
||||
import { AFFINE_EDGELESS_COPILOT_WIDGET } from './constant.js';
|
||||
|
||||
export class EdgelessCopilotWidget extends WidgetComponent<RootBlockModel> {
|
||||
static override styles = css`
|
||||
@@ -95,6 +96,31 @@ export class EdgelessCopilotWidget extends WidgetComponent<RootBlockModel> {
|
||||
|
||||
if (input instanceof AffineAIPanelWidget) {
|
||||
input.setState('input', referenceElement);
|
||||
const aiPanel = input;
|
||||
// TODO: @xiaojun refactor these scattered config overrides
|
||||
if (aiPanel.config && !aiPanel.config.generateAnswer) {
|
||||
aiPanel.config.generateAnswer = ({ finish, input }) => {
|
||||
finish('success');
|
||||
aiPanel.hide();
|
||||
extractSelectedContent(this.host)
|
||||
.then(context => {
|
||||
AIProvider.slots.requestSendWithChat.next({
|
||||
input,
|
||||
context,
|
||||
host: this.host,
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
};
|
||||
aiPanel.config.inputCallback = text => {
|
||||
const panel = this.shadowRoot?.querySelector(
|
||||
'edgeless-copilot-panel'
|
||||
);
|
||||
if (panel instanceof HTMLElement) {
|
||||
panel.style.visibility = text ? 'hidden' : 'visible';
|
||||
}
|
||||
};
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
this._createCopilotPanel();
|
||||
this._updateCopilotPanel(input);
|
||||
@@ -314,3 +340,5 @@ declare global {
|
||||
[AFFINE_EDGELESS_COPILOT_WIDGET]: EdgelessCopilotWidget;
|
||||
}
|
||||
}
|
||||
|
||||
export * from './constant';
|
||||
|
||||
Reference in New Issue
Block a user