refactor: move chat block to affine (#8368)

[BS-898](https://linear.app/affine-design/issue/BS-898/move-ai-chat-block-to-affine)

Should be merged after https://github.com/toeverything/blocksuite/pull/8420 merged and bumped.
This commit is contained in:
donteatfriedrice
2024-10-16 12:40:30 +00:00
parent 6f541ecf80
commit 11aa6f63b2
58 changed files with 1213 additions and 360 deletions

View File

@@ -3,7 +3,7 @@
"private": true,
"type": "module",
"devDependencies": {
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"vitest": "2.1.1"
},
"exports": {

View File

@@ -14,7 +14,7 @@
"@affine/debug": "workspace:*",
"@affine/env": "workspace:*",
"@affine/templates": "workspace:*",
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"@datastructures-js/binary-search-tree": "^5.3.2",
"foxact": "^0.2.33",
"fractional-indexing": "^3.2.0",

View File

@@ -0,0 +1,48 @@
import { GfxCompatible } from '@blocksuite/affine/block-std/gfx';
import type { SerializedXYWH } from '@blocksuite/affine/global/utils';
import { BlockModel, defineBlockSchema } from '@blocksuite/affine/store';
type AIChatProps = {
xywh: SerializedXYWH;
index: string;
scale: number;
messages: string; // JSON string of ChatMessage[]
sessionId: string; // forked session id
rootWorkspaceId: string; // workspace id of root chat session
rootDocId: string; // doc id of root chat session
};
export const AIChatBlockSchema = defineBlockSchema({
flavour: 'affine:embed-ai-chat',
props: (): AIChatProps => ({
xywh: '[0,0,0,0]',
index: 'a0',
scale: 1,
messages: '',
sessionId: '',
rootWorkspaceId: '',
rootDocId: '',
}),
metadata: {
version: 1,
role: 'content',
children: [],
},
toModel: () => {
return new AIChatBlockModel();
},
});
export class AIChatBlockModel extends GfxCompatible<AIChatProps>(BlockModel) {}
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace BlockSuite {
interface EdgelessBlockModelMap {
'affine:embed-ai-chat': AIChatBlockModel;
}
interface BlockModels {
'affine:embed-ai-chat': AIChatBlockModel;
}
}
}

View File

@@ -0,0 +1,2 @@
export const CHAT_BLOCK_WIDTH = 300;
export const CHAT_BLOCK_HEIGHT = 320;

View File

@@ -0,0 +1,3 @@
export * from './ai-chat-model';
export * from './consts';
export * from './types';

View File

@@ -0,0 +1,25 @@
import { z } from 'zod';
// Define the Zod schema
const ChatMessageSchema = z.object({
id: z.string(),
content: z.string(),
role: z.union([z.literal('user'), z.literal('assistant')]),
createdAt: z.string(),
attachments: z.array(z.string()).optional(),
userId: z.string().optional(),
userName: z.string().optional(),
avatarUrl: z.string().optional(),
});
export const ChatMessagesSchema = z.array(ChatMessageSchema);
// Derive the TypeScript type from the Zod schema
export type ChatMessage = z.infer<typeof ChatMessageSchema>;
export type MessageRole = 'user' | 'assistant';
export type MessageUserInfo = {
userId?: string;
userName?: string;
avatarUrl?: string;
};

View File

@@ -0,0 +1 @@
export * from './ai-chat-block';

View File

@@ -1,3 +1,4 @@
export * from './blocks';
export {
migratePages as forceUpgradePages,
migrateGuidCompatibility,

View File

@@ -30,7 +30,7 @@ export function initDocFromProps(doc: Doc, props?: DocProps) {
'affine:page',
props?.page || { title: new Text('') }
);
doc.addBlock('affine:surface', props?.surface || {}, pageBlockId);
doc.addBlock('affine:surface' as never, props?.surface || {}, pageBlockId);
const noteBlockId = doc.addBlock(
'affine:note',
{

View File

@@ -1,5 +1,9 @@
import { Unreachable } from '@affine/env/constant';
import { type DocMode } from '@blocksuite/affine/blocks';
import {
type AffineTextAttributes,
type DocMode,
} from '@blocksuite/affine/blocks';
import type { DeltaInsert } from '@blocksuite/affine/inline';
import { Service } from '../../../framework';
import { type DocProps, initDocFromProps } from '../../../initialization';
@@ -77,7 +81,7 @@ export class DocsService extends Service {
const { doc, release } = this.open(targetDocId);
doc.setPriorityLoad(10);
await doc.waitForSyncReady();
const text = doc.blockSuiteDoc.Text.fromDelta([
const text = new doc.blockSuiteDoc.Text([
{
insert: ' ',
attributes: {
@@ -87,7 +91,7 @@ export class DocsService extends Service {
},
},
},
]);
] as DeltaInsert<AffineTextAttributes>[]);
const [frame] = doc.blockSuiteDoc.getBlocksByFlavour('affine:note');
frame &&
doc.blockSuiteDoc.addBlock(

View File

@@ -1,7 +1,8 @@
import { AffineSchemas } from '@blocksuite/affine/blocks/schemas';
import { AIChatBlockSchema } from '@blocksuite/affine/presets';
import { Schema } from '@blocksuite/affine/store';
import { AIChatBlockSchema } from '../../blocksuite/blocks/ai-chat-block/ai-chat-model';
let _schema: Schema | null = null;
export function getAFFiNEWorkspaceSchema() {
if (!_schema) {

View File

@@ -28,7 +28,7 @@
"@affine/core": "workspace:*",
"@affine/i18n": "workspace:*",
"@affine/native": "workspace:*",
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"@electron-forge/cli": "^7.3.0",
"@electron-forge/core": "^7.3.0",
"@electron-forge/core-utils": "^7.3.0",

View File

@@ -13,7 +13,7 @@
"@affine/component": "workspace:*",
"@affine/core": "workspace:*",
"@affine/i18n": "workspace:*",
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"@blocksuite/icons": "^2.1.67",
"@sentry/react": "^8.0.0",
"react": "^18.2.0",

View File

@@ -60,7 +60,7 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"@blocksuite/icons": "2.1.68",
"@chromatic-com/storybook": "^2.0.0",
"@storybook/addon-essentials": "^8.2.9",

View File

@@ -16,7 +16,7 @@
"@affine/i18n": "workspace:*",
"@affine/templates": "workspace:*",
"@affine/track": "workspace:*",
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"@blocksuite/icons": "2.1.68",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
@@ -27,6 +27,7 @@
"@floating-ui/dom": "^1.6.5",
"@juggle/resize-observer": "^3.4.0",
"@marsidev/react-turnstile": "^1.0.0",
"@preact/signals-core": "^1.8.0",
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-popover": "^1.0.7",

View File

@@ -1,22 +1,22 @@
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/block-std';
import {
type AffineAIPanelState,
type AffineAIPanelWidgetConfig,
import type {
AffineAIPanelState,
AffineAIPanelWidgetConfig,
} from '@blocksuite/affine/blocks';
import {
CodeBlockComponent,
DividerBlockComponent,
ListBlockComponent,
ParagraphBlockComponent,
SpecProvider,
} from '@blocksuite/affine/blocks';
import { WithDisposable } from '@blocksuite/affine/global/utils';
import { BlockViewType, type Doc, type Query } from '@blocksuite/affine/store';
import { css, html, LitElement, type PropertyValues } from 'lit';
import { css, html, LitElement, nothing, type PropertyValues } from 'lit';
import { property, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { keyed } from 'lit/directives/keyed.js';
import { CustomPageEditorBlockSpecs } from '../utils/custom-specs';
import { markDownToDoc } from '../utils/markdown-utils';
const textBlockStyles = css`
@@ -67,12 +67,12 @@ const customHeadingStyles = css`
}
`;
type TextRendererOptions = {
export type TextRendererOptions = {
maxHeight?: number;
customHeading?: boolean;
};
export class AIAnswerText extends WithDisposable(LitElement) {
export class TextRenderer extends WithDisposable(LitElement) {
static override styles = css`
.ai-answer-text-editor.affine-page-viewport {
background: transparent;
@@ -138,43 +138,14 @@ export class AIAnswerText extends WithDisposable(LitElement) {
editor-host * {
box-sizing: border-box;
}
editor-host {
isolation: isolate;
}
}
${textBlockStyles}
${customHeadingStyles}
`;
@query('.ai-answer-text-container')
private accessor _container!: HTMLDivElement;
private _doc!: Doc;
private _answers: string[] = [];
private _timer?: ReturnType<typeof setInterval> | null = null;
@property({ attribute: false })
accessor host!: EditorHost;
@property({ attribute: false })
accessor answer!: string;
@property({ attribute: false })
accessor options!: TextRendererOptions;
@property({ attribute: false })
accessor state: AffineAIPanelState | undefined = undefined;
private _onWheel(e: MouseEvent) {
e.stopPropagation();
if (this.state === 'generating') {
e.preventDefault();
}
}
private readonly _clearTimer = () => {
if (this._timer) {
clearInterval(this._timer);
@@ -182,6 +153,8 @@ export class AIAnswerText extends WithDisposable(LitElement) {
}
};
private _doc: Doc | null = null;
private readonly _query: Query = {
mode: 'strict',
match: [
@@ -195,6 +168,8 @@ export class AIAnswerText extends WithDisposable(LitElement) {
].map(flavour => ({ flavour, viewType: BlockViewType.Display })),
};
private _timer?: ReturnType<typeof setInterval> | null = null;
private readonly _updateDoc = () => {
if (this._answers.length > 0) {
const latestAnswer = this._answers.pop();
@@ -222,13 +197,11 @@ export class AIAnswerText extends WithDisposable(LitElement) {
}
};
override shouldUpdate(changedProperties: PropertyValues) {
if (changedProperties.has('answer')) {
this._answers.push(this.answer);
return false;
private _onWheel(e: MouseEvent) {
e.stopPropagation();
if (this.state === 'generating') {
e.preventDefault();
}
return true;
}
override connectedCallback() {
@@ -246,16 +219,13 @@ export class AIAnswerText extends WithDisposable(LitElement) {
this._clearTimer();
}
override updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
requestAnimationFrame(() => {
if (!this._container) return;
this._container.scrollTop = this._container.scrollHeight;
});
}
override render() {
if (!this._doc) {
return nothing;
}
const { maxHeight, customHeading } = this.options;
const previewSpec = SpecProvider.getInstance().getSpec('page:preview');
const classes = classMap({
'ai-answer-text-container': true,
'show-scrollbar': !!maxHeight,
@@ -273,18 +243,50 @@ export class AIAnswerText extends WithDisposable(LitElement) {
html`<div class="ai-answer-text-editor affine-page-viewport">
${new BlockStdScope({
doc: this._doc,
extensions: CustomPageEditorBlockSpecs,
extensions: previewSpec.value,
}).render()}
</div>`
)}
</div>
`;
}
override shouldUpdate(changedProperties: PropertyValues) {
if (changedProperties.has('answer')) {
this._answers.push(this.answer);
return false;
}
return true;
}
override updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
requestAnimationFrame(() => {
if (!this._container) return;
this._container.scrollTop = this._container.scrollHeight;
});
}
@query('.ai-answer-text-container')
private accessor _container!: HTMLDivElement;
@property({ attribute: false })
accessor answer!: string;
@property({ attribute: false })
accessor host!: EditorHost;
@property({ attribute: false })
accessor options!: TextRendererOptions;
@property({ attribute: false })
accessor state: AffineAIPanelState | undefined = undefined;
}
declare global {
interface HTMLElementTagNameMap {
'ai-answer-text': AIAnswerText;
'text-renderer': TextRenderer;
}
}
@@ -293,11 +295,11 @@ export const createTextRenderer: (
options: TextRendererOptions
) => AffineAIPanelWidgetConfig['answerRenderer'] = (host, options) => {
return (answer, state) => {
return html`<ai-answer-text
return html`<text-renderer
.host=${host}
.answer=${answer}
.state=${state}
.options=${options}
></ai-answer-text>`;
></text-renderer>`;
};
};

View File

@@ -0,0 +1,2 @@
export * from './components/text-renderer';
export * from './utils/markdown-utils';

View File

@@ -12,7 +12,8 @@ import {
PlainTextAdapter,
titleMiddleware,
} from '@blocksuite/affine/blocks';
import { assertExists } from '@blocksuite/affine/global/utils';
import { DocCollection, Job } from '@blocksuite/affine/store';
import { assertExists } from '@blocksuite/global/utils';
import type {
BlockModel,
BlockSnapshot,
@@ -20,8 +21,7 @@ import type {
DraftModel,
Slice,
SliceSnapshot,
} from '@blocksuite/affine/store';
import { DocCollection, Job } from '@blocksuite/affine/store';
} from '@blocksuite/store';
const updateSnapshotText = (
point: TextRangePoint,

View File

@@ -24,14 +24,14 @@ import {
getElementsBound,
type SerializedXYWH,
} from '@blocksuite/affine/global/utils';
import { type ChatMessage } from '@blocksuite/affine/presets';
import type { Doc } from '@blocksuite/affine/store';
import type { ChatMessage } from '@toeverything/infra/blocksuite';
import type { TemplateResult } from 'lit';
import { insertFromMarkdown } from '../../_common';
import { AIProvider, type AIUserInfo } from '../provider';
import { reportResponse } from '../utils/action-reporter';
import { insertBelow, replace } from '../utils/editor-actions';
import { insertFromMarkdown } from '../utils/markdown-utils';
import { BlockIcon, CreateIcon, InsertBelowIcon, ReplaceIcon } from './icons';
const { matchFlavours } = BlocksUtils;

View File

@@ -7,6 +7,7 @@ import type {
import { assertExists } from '@blocksuite/affine/global/utils';
import type { TemplateResult } from 'lit';
import { createTextRenderer } from '../../_common';
import {
buildCopyConfig,
buildErrorConfig,
@@ -14,7 +15,6 @@ import {
buildGeneratingConfig,
getAIPanel,
} from '../ai-panel';
import { createTextRenderer } from '../messages/text';
import { AIProvider } from '../provider';
import { reportResponse } from '../utils/action-reporter';
import {

View File

@@ -15,17 +15,17 @@ import {
TextElementModel,
} from '@blocksuite/affine/blocks';
import { assertExists } from '@blocksuite/affine/global/utils';
import { AIChatBlockModel } from '@blocksuite/affine/presets';
import { Slice } from '@blocksuite/affine/store';
import { AIChatBlockModel } from '@toeverything/infra';
import type { TemplateResult } from 'lit';
import { createTextRenderer, getContentFromSlice } from '../../_common';
import { getAIPanel } from '../ai-panel';
import {
createMindmapExecuteRenderer,
createMindmapRenderer,
} from '../messages/mindmap';
import { createSlidesRenderer } from '../messages/slides-renderer';
import { createTextRenderer } from '../messages/text';
import { createIframeRenderer, createImageRenderer } from '../messages/wrapper';
import { AIProvider } from '../provider';
import { reportResponse } from '../utils/action-reporter';
@@ -35,7 +35,6 @@ import {
isMindMapRoot,
} from '../utils/edgeless';
import { copyTextAnswer } from '../utils/editor-actions';
import { getContentFromSlice } from '../utils/markdown-utils';
import {
getCopilotSelectedElems,
getSelectedNoteAnchor,

View File

@@ -28,6 +28,7 @@ import { assertExists, Bound } from '@blocksuite/affine/global/utils';
import { html, type TemplateResult } from 'lit';
import { styleMap } from 'lit/directives/style-map.js';
import { insertFromMarkdown } from '../../_common';
import { AIPenIcon, ChatWithAIIcon } from '../_common/icons';
import { getAIPanel } from '../ai-panel';
import { AIProvider } from '../provider';
@@ -39,7 +40,6 @@ import {
} from '../utils/edgeless';
import { preprocessHtml } from '../utils/html';
import { fetchImageToFile } from '../utils/image';
import { insertFromMarkdown } from '../utils/markdown-utils';
import {
getCopilotSelectedElems,
getEdgelessRootFromEditor,
@@ -313,7 +313,7 @@ const imageHandler = (host: EditorHost) => {
host.doc.transact(() => {
edgelessRoot
.addImages([img], [x, y], true)
.addImages([img], [x, y])
.then(blockIds => {
const imageBlockId = blockIds[0];
const imageBlock = host.doc.getBlock(imageBlockId);

View File

@@ -12,6 +12,7 @@ import {
import { assertExists, Bound } from '@blocksuite/affine/global/utils';
import type { TemplateResult } from 'lit';
import { createTextRenderer, insertFromMarkdown } from '../_common';
import {
AIPenIcon,
AIStarIconWithAnimation,
@@ -24,7 +25,6 @@ import {
RetryIcon,
} from './_common/icons';
import { INSERT_ABOVE_ACTIONS } from './actions/consts';
import { createTextRenderer } from './messages/text';
import { AIProvider } from './provider';
import { reportResponse } from './utils/action-reporter';
import { findNoteBlockModel, getService } from './utils/edgeless';
@@ -34,7 +34,6 @@ import {
insertBelow,
replace,
} from './utils/editor-actions';
import { insertFromMarkdown } from './utils/markdown-utils';
import { getSelections } from './utils/selection-utils';
function getSelection(host: EditorHost) {

View File

@@ -3,6 +3,7 @@ import { WithDisposable } from '@blocksuite/affine/global/utils';
import { css, html, LitElement, nothing, type TemplateResult } from 'lit';
import { property, state } from 'lit/decorators.js';
import { createTextRenderer } from '../../../_common';
import {
ActionIcon,
AIChangeToneIcon,
@@ -22,7 +23,6 @@ import {
ArrowDownIcon,
ArrowUpIcon,
} from '../../_common/icons';
import { createTextRenderer } from '../../messages/text';
import type { ChatAction } from '../chat-context';
import { renderImages } from '../components/images';
import { HISTORY_IMAGE_ACTIONS } from '../const';

View File

@@ -6,7 +6,7 @@ import { WithDisposable } from '@blocksuite/affine/global/utils';
import { html, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import { createTextRenderer } from '../../messages/text';
import { createTextRenderer } from '../../../_common';
import { renderImages } from '../components/images';
export class ChatText extends WithDisposable(ShadowlessElement) {
@property({ attribute: false })

View File

@@ -6,7 +6,7 @@ import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { createTextRenderer } from '../../messages/text';
import { createTextRenderer } from '../../../_common';
import type { ChatAction } from '../chat-context';
export class ActionText extends WithDisposable(LitElement) {

View File

@@ -1,18 +1,3 @@
import '../messages/slides-renderer';
import './ai-loading';
import '../messages/text';
import './actions/text';
import './actions/action-wrapper';
import './actions/make-real';
import './actions/slides';
import './actions/mindmap';
import './actions/chat-text';
import './actions/image-to-text';
import './actions/image';
import './chat-cards';
import '../_common/components/chat-action-list';
import '../_common/components/copy-more';
import type { BaseSelection, EditorHost } from '@blocksuite/affine/block-std';
import { ShadowlessElement } from '@blocksuite/affine/block-std';
import {

View File

@@ -6,4 +6,3 @@ export * from './entries/index';
export * from './messages/index';
export { AIChatBlockPeekViewTemplate } from './peek-view/chat-block-peek-view';
export * from './provider';
export * from './setup';

View File

@@ -1,2 +1 @@
export * from './text';
export * from './wrapper';

View File

@@ -1,6 +1,6 @@
import type { EditorHost } from '@blocksuite/affine/block-std';
import { type AIError, openFileOrFiles } from '@blocksuite/affine/blocks';
import { type ChatMessage } from '@blocksuite/affine/presets';
import type { ChatMessage } from '@toeverything/infra';
import { css, html, LitElement, nothing } from 'lit';
import { property, query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';

View File

@@ -1,8 +1,3 @@
import './chat-block-input';
import './date-time';
import '../_common/components/chat-action-list';
import '../_common/components/copy-more';
import { type EditorHost } from '@blocksuite/affine/block-std';
import {
type AIError,
@@ -17,7 +12,7 @@ import {
type AIChatBlockModel,
type ChatMessage,
ChatMessagesSchema,
} from '@blocksuite/affine/presets';
} from '@toeverything/infra/blocksuite';
import { html, LitElement, nothing } from 'lit';
import { property, query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';

View File

@@ -1,5 +1,5 @@
import type { AIError } from '@blocksuite/affine/blocks';
import { type ChatMessage } from '@blocksuite/affine/presets';
import type { ChatMessage } from '@toeverything/infra/blocksuite';
export type ChatStatus =
| 'success'

View File

@@ -4,7 +4,7 @@ import {
type AIChatBlockModel,
CHAT_BLOCK_HEIGHT,
CHAT_BLOCK_WIDTH,
} from '@blocksuite/affine/presets';
} from '@toeverything/infra';
/**
* Calculates the bounding box for a child block

View File

@@ -1,50 +0,0 @@
import { AskAIButton } from './_common/components/ask-ai-button';
import { AskAIPanel } from './_common/components/ask-ai-panel';
import { ChatActionList } from './_common/components/chat-action-list';
import { ChatCopyMore } from './_common/components/copy-more';
import { ChatPanel } from './chat-panel';
import { ActionWrapper } from './chat-panel/actions/action-wrapper';
import { ChatText } from './chat-panel/actions/chat-text';
import { ActionImage } from './chat-panel/actions/image';
import { ActionImageToText } from './chat-panel/actions/image-to-text';
import { ActionMakeReal } from './chat-panel/actions/make-real';
import { ActionMindmap } from './chat-panel/actions/mindmap';
import { ActionSlides } from './chat-panel/actions/slides';
import { ActionText } from './chat-panel/actions/text';
import { AILoading } from './chat-panel/ai-loading';
import { ChatCards } from './chat-panel/chat-cards';
import { ChatPanelInput } from './chat-panel/chat-panel-input';
import { ChatPanelMessages } from './chat-panel/chat-panel-messages';
import { AIAnswerText, AIAnswerWrapper } from './messages';
import { AIErrorWrapper } from './messages/error';
import { AISlidesRenderer } from './messages/slides-renderer';
import { ChatBlockInput } from './peek-view/chat-block-input';
import { AIChatBlockPeekView } from './peek-view/chat-block-peek-view';
import { DateTime } from './peek-view/date-time';
export function registerAICustomComponents() {
customElements.define('ask-ai-button', AskAIButton);
customElements.define('ask-ai-panel', AskAIPanel);
customElements.define('chat-action-list', ChatActionList);
customElements.define('chat-copy-more', ChatCopyMore);
customElements.define('action-wrapper', ActionWrapper);
customElements.define('chat-text', ChatText);
customElements.define('action-image-to-text', ActionImageToText);
customElements.define('action-image', ActionImage);
customElements.define('action-make-real', ActionMakeReal);
customElements.define('action-mindmap', ActionMindmap);
customElements.define('action-slides', ActionSlides);
customElements.define('action-text', ActionText);
customElements.define('ai-loading', AILoading);
customElements.define('chat-cards', ChatCards);
customElements.define('chat-panel-input', ChatPanelInput);
customElements.define('chat-panel-messages', ChatPanelMessages);
customElements.define('chat-panel', ChatPanel);
customElements.define('ai-error-wrapper', AIErrorWrapper);
customElements.define('ai-slides-renderer', AISlidesRenderer);
customElements.define('ai-answer-wrapper', AIAnswerWrapper);
customElements.define('ai-answer-text', AIAnswerText);
customElements.define('chat-block-input', ChatBlockInput);
customElements.define('ai-chat-block-peek-view', AIChatBlockPeekView);
customElements.define('date-time', DateTime);
}

View File

@@ -2,7 +2,7 @@ import type { EditorHost } from '@blocksuite/affine/block-std';
import type { EdgelessRootService } from '@blocksuite/affine/blocks';
import type { BlockSnapshot } from '@blocksuite/affine/store';
import { markdownToSnapshot } from '../utils/markdown-utils';
import { markdownToSnapshot } from '../../_common';
import { getSurfaceElementFromEditor } from '../utils/selection-utils';
import {
basicTheme,

View File

@@ -11,7 +11,7 @@ import {
insertFromMarkdown,
markDownToDoc,
markdownToSnapshot,
} from './markdown-utils';
} from '../../_common';
const getNoteId = (blockElement: BlockComponent) => {
let element = blockElement;

View File

@@ -14,8 +14,8 @@ import {
toDraftModel,
} from '@blocksuite/affine/store';
import { getContentFromSlice } from '../../_common';
import { getEdgelessCopilotWidget, getService } from './edgeless';
import { getContentFromSlice } from './markdown-utils';
export const getRootService = (host: EditorHost) => {
return host.std.getService('affine:page');

View File

@@ -0,0 +1,102 @@
import { html } from 'lit';
export const ChatWithAIIcon = html`<svg
width="21"
height="21"
viewBox="0 0 21 21"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.59593 7.38585C2.75058 6.62196 3.25841 5.16699 4.43763 5.16699H16.3017C17.2852 5.16699 17.8664 6.23248 17.3995 7.06491L11.5806 17.4378C11.0097 18.4556 9.51091 18.2189 9.25406 17.098L7.9249 11.2976L3.59593 7.38585ZM9.20223 11.2755L10.4725 16.8188C10.4742 16.8262 10.4759 16.8301 10.4767 16.8316C10.4777 16.8321 10.4796 16.8329 10.4827 16.8334C10.4839 16.8336 10.4849 16.8337 10.4857 16.8337C10.4869 16.8321 10.4885 16.8297 10.4904 16.8263L15.7266 7.492L9.20223 11.2755ZM15.0887 6.41699H4.43763C4.4362 6.41699 4.43499 6.41703 4.434 6.41709C4.43249 6.41912 4.43033 6.42258 4.42836 6.42784C4.42439 6.43845 4.42506 6.44624 4.42551 6.44838C4.42564 6.44898 4.42571 6.4491 4.42586 6.44937L4.42588 6.44939C4.42593 6.44949 4.42768 6.4527 4.434 6.45841L8.57091 10.1967L15.0887 6.41699Z"
/>
</svg>`;
export const AffineAIIcon = html`<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.2812 5.49104C11.2403 5.13024 10.9353 4.85751 10.5722 4.85714C10.2091 4.85677 9.90345 5.12887 9.86185 5.48959C9.59131 7.83515 8.89003 9.48448 7.75868 10.6158C6.62734 11.7472 4.97801 12.4485 2.63244 12.719C2.27173 12.7606 1.99963 13.0662 2 13.4293C2.00037 13.7924 2.2731 14.0975 2.63389 14.1383C4.94069 14.3996 6.62508 15.1006 7.78328 16.2379C8.93713 17.3709 9.65305 19.0198 9.85994 21.3489C9.89271 21.7178 10.2019 22.0004 10.5722 22C10.9425 21.9996 11.2511 21.7162 11.2831 21.3473C11.4813 19.0565 12.1966 17.3729 13.3562 16.2133C14.5157 15.0537 16.1994 14.3385 18.4902 14.1402C18.8591 14.1083 19.1424 13.7997 19.1429 13.4294C19.1433 13.0591 18.8606 12.7499 18.4918 12.7171C16.1627 12.5102 14.5137 11.7943 13.3807 10.6404C12.2435 9.48222 11.5425 7.79783 11.2812 5.49104Z"
/>
<path
d="M18.9427 2.24651C18.9268 2.1062 18.8082 2.00014 18.667 2C18.5257 1.99986 18.4069 2.10567 18.3907 2.24595C18.2855 3.15811 18.0128 3.79952 17.5728 4.23949C17.1329 4.67946 16.4914 4.95218 15.5793 5.05739C15.439 5.07356 15.3332 5.19241 15.3333 5.33362C15.3335 5.47482 15.4395 5.59345 15.5798 5.60935C16.4769 5.71096 17.132 5.98357 17.5824 6.42584C18.0311 6.86644 18.3095 7.50771 18.39 8.41347C18.4027 8.55691 18.523 8.66683 18.667 8.66667C18.811 8.6665 18.931 8.55632 18.9434 8.41284C19.0205 7.52199 19.2987 6.86723 19.7496 6.41629C20.2006 5.96534 20.8553 5.68719 21.7462 5.61008C21.8896 5.59766 21.9998 5.47765 22 5.33365C22.0002 5.18964 21.8902 5.06939 21.7468 5.05664C20.841 4.97619 20.1998 4.69777 19.7592 4.24905C19.3169 3.79864 19.0443 3.1436 18.9427 2.24651Z"
/>
</svg> `;
export const ImageLoadingFailedIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M2.1665 3.99984C2.1665 2.98732 2.98732 2.1665 3.99984 2.1665H11.9998C13.0124 2.1665 13.8332 2.98732 13.8332 3.99984V7.33317C13.8332 7.60931 13.6093 7.83317 13.3332 7.83317C13.057 7.83317 12.8332 7.60931 12.8332 7.33317V3.99984C12.8332 3.5396 12.4601 3.1665 11.9998 3.1665H3.99984C3.5396 3.1665 3.1665 3.5396 3.1665 3.99984V9.4594L5.37014 7.25576C6.0861 6.5398 7.2469 6.5398 7.96287 7.25576L8.35339 7.64628C8.54865 7.84155 8.54865 8.15813 8.35339 8.35339C8.15813 8.54865 7.84155 8.54865 7.64628 8.35339L7.25576 7.96287C6.93032 7.63743 6.40268 7.63743 6.07725 7.96287L3.1665 10.8736V11.9998C3.1665 12.4601 3.5396 12.8332 3.99984 12.8332H7.33317C7.60931 12.8332 7.83317 13.057 7.83317 13.3332C7.83317 13.6093 7.60931 13.8332 7.33317 13.8332H3.99984C2.98732 13.8332 2.1665 13.0124 2.1665 11.9998V3.99984Z"
fill="currentColor"
fill-opacity="0.6"
/>
<path
d="M9.99984 5.33317C9.99984 5.70136 9.70136 5.99984 9.33317 5.99984C8.96498 5.99984 8.6665 5.70136 8.6665 5.33317C8.6665 4.96498 8.96498 4.6665 9.33317 4.6665C9.70136 4.6665 9.99984 4.96498 9.99984 5.33317Z"
fill="currentColor"
fill-opacity="0.6"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.97962 8.97962C9.17488 8.78435 9.49146 8.78435 9.68672 8.97962L11.3332 10.6261L12.9796 8.97962C13.1749 8.78435 13.4915 8.78435 13.6867 8.97962C13.882 9.17488 13.882 9.49146 13.6867 9.68672L12.0403 11.3332L13.6867 12.9796C13.882 13.1749 13.882 13.4915 13.6867 13.6867C13.4915 13.882 13.1749 13.882 12.9796 13.6867L11.3332 12.0403L9.68672 13.6867C9.49146 13.882 9.17488 13.882 8.97962 13.6867C8.78435 13.4915 8.78435 13.1749 8.97962 12.9796L10.6261 11.3332L8.97962 9.68672C8.78435 9.49146 8.78435 9.17488 8.97962 8.97962Z"
fill="currentColor"
fill-opacity="0.6"
/>
</svg>`;
export const LoadingIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<style xmlns="http://www.w3.org/2000/svg">
.spinner {
transform-origin: center;
animation: spinner_animate 0.75s infinite linear;
}
@keyframes spinner_animate {
100% {
transform: rotate(360deg);
}
}
</style>
<path
d="M14.6666 8.00004C14.6666 11.6819 11.6818 14.6667 7.99992 14.6667C4.31802 14.6667 1.33325 11.6819 1.33325 8.00004C1.33325 4.31814 4.31802 1.33337 7.99992 1.33337C11.6818 1.33337 14.6666 4.31814 14.6666 8.00004ZM3.30003 8.00004C3.30003 10.5957 5.40424 12.6999 7.99992 12.6999C10.5956 12.6999 12.6998 10.5957 12.6998 8.00004C12.6998 5.40436 10.5956 3.30015 7.99992 3.30015C5.40424 3.30015 3.30003 5.40436 3.30003 8.00004Z"
fill="black"
fill-opacity="0.1"
/>
<path
d="M13.6833 8.00004C14.2263 8.00004 14.674 7.55745 14.5942 7.02026C14.5142 6.48183 14.3684 5.954 14.1591 5.44882C13.8241 4.63998 13.333 3.90505 12.714 3.286C12.0949 2.66694 11.36 2.17588 10.5511 1.84084C10.046 1.63159 9.51812 1.48576 8.9797 1.40576C8.44251 1.32595 7.99992 1.77363 7.99992 2.31671C7.99992 2.85979 8.44486 3.28974 8.9761 3.40253C9.25681 3.46214 9.53214 3.54746 9.79853 3.65781C10.3688 3.894 10.8869 4.2402 11.3233 4.67664C11.7598 5.11307 12.106 5.6312 12.3422 6.20143C12.4525 6.46782 12.5378 6.74315 12.5974 7.02386C12.7102 7.5551 13.1402 8.00004 13.6833 8.00004Z"
fill="#1C9EE4"
class="spinner"
/>
</svg>`;
export const SmallHintIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.00008 3.16699C5.33071 3.16699 3.16675 5.33095 3.16675 8.00033C3.16675 10.6697 5.33071 12.8337 8.00008 12.8337C10.6695 12.8337 12.8334 10.6697 12.8334 8.00033C12.8334 5.33095 10.6695 3.16699 8.00008 3.16699ZM2.16675 8.00033C2.16675 4.77866 4.77842 2.16699 8.00008 2.16699C11.2217 2.16699 13.8334 4.77866 13.8334 8.00033C13.8334 11.222 11.2217 13.8337 8.00008 13.8337C4.77842 13.8337 2.16675 11.222 2.16675 8.00033ZM8.00008 5.12996C8.27622 5.12996 8.50008 5.35381 8.50008 5.62996V8.00033C8.50008 8.27647 8.27622 8.50033 8.00008 8.50033C7.72394 8.50033 7.50008 8.27647 7.50008 8.00033V5.62996C7.50008 5.35381 7.72394 5.12996 8.00008 5.12996ZM7.50008 10.3707C7.50008 10.0946 7.72394 9.8707 8.00008 9.8707H8.00601C8.28215 9.8707 8.50601 10.0946 8.50601 10.3707C8.50601 10.6468 8.28215 10.8707 8.00601 10.8707H8.00008C7.72394 10.8707 7.50008 10.6468 7.50008 10.3707Z"
fill-opacity="0.6"
/>
</svg> `;

View File

@@ -0,0 +1,60 @@
import { BlockComponent } from '@blocksuite/affine/block-std';
import { Peekable } from '@blocksuite/affine/blocks';
import { computed } from '@preact/signals-core';
import {
type AIChatBlockModel,
ChatMessagesSchema,
} from '@toeverything/infra/blocksuite';
import { html } from 'lit';
import { ChatWithAIIcon } from '../_common/icon';
import { AIChatBlockStyles } from './styles';
@Peekable({
enableOn: ({ doc }: AIChatBlockComponent) => !doc.readonly,
})
export class AIChatBlockComponent extends BlockComponent<AIChatBlockModel> {
static override styles = AIChatBlockStyles;
// Deserialize messages from JSON string and verify the type using zod
private readonly _deserializeChatMessages = computed(() => {
const messages = this.model.messages$.value;
try {
const result = ChatMessagesSchema.safeParse(JSON.parse(messages));
if (result.success) {
return result.data;
} else {
return [];
}
} catch {
return [];
}
});
override renderBlock() {
const messages = this._deserializeChatMessages.value.slice(-2);
const textRendererOptions = {
customHeading: true,
};
return html`<div class="affine-ai-chat-block-container">
<div class="ai-chat-messages-container">
<ai-chat-messages
.host=${this.host}
.messages=${messages}
.textRendererOptions=${textRendererOptions}
.withMask=${true}
></ai-chat-messages>
</div>
<div class="ai-chat-block-button">
${ChatWithAIIcon} <span>AI chat block</span>
</div>
</div> `;
}
}
declare global {
interface HTMLElementTagNameMap {
'affine-ai-chat': AIChatBlockComponent;
}
}

View File

@@ -0,0 +1,38 @@
import { toGfxBlockComponent } from '@blocksuite/affine/block-std';
import { Bound } from '@blocksuite/global/utils';
import { html } from 'lit';
import { styleMap } from 'lit/directives/style-map.js';
import { AIChatBlockComponent } from './ai-chat-block';
export class EdgelessAIChatBlockComponent extends toGfxBlockComponent(
AIChatBlockComponent
) {
override renderGfxBlock() {
const bound = Bound.deserialize(this.model.xywh$.value);
const scale = this.model.scale$.value;
const width = bound.w / scale;
const height = bound.h / scale;
const style = {
width: `${width}px`,
height: `${height}px`,
borderRadius: '8px',
transformOrigin: '0 0',
boxShadow: 'var(--affine-shadow-1)',
border: '1px solid var(--affine-border-color)',
transform: `scale(${scale})`,
};
return html`
<div class="edgeless-ai-chat" style=${styleMap(style)}>
${this.renderPageContent()}
</div>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
'affine-edgeless-ai-chat': EdgelessAIChatBlockComponent;
}
}

View File

@@ -0,0 +1,17 @@
import {
BlockViewExtension,
type ExtensionType,
} from '@blocksuite/affine/block-std';
import { literal } from 'lit/static-html.js';
export const AIChatBlockSpec: ExtensionType[] = [
BlockViewExtension('affine:embed-ai-chat', model => {
const parent = model.doc.getParent(model.id);
if (parent?.flavour === 'affine:surface') {
return literal`affine-edgeless-ai-chat`;
}
return literal`affine-ai-chat`;
}),
];

View File

@@ -0,0 +1,153 @@
import type { EditorHost } from '@blocksuite/block-std';
import type { AffineAIPanelState } from '@blocksuite/blocks';
import type {
ChatMessage,
MessageRole,
MessageUserInfo,
} from '@toeverything/infra/blocksuite';
import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { repeat } from 'lit/directives/repeat.js';
import type { TextRendererOptions } from '../../../_common/components/text-renderer';
import { UserInfoTemplate } from './user-info';
export class AIChatMessage extends LitElement {
static override styles = css`
.ai-chat-message {
display: flex;
width: 100%;
flex-direction: column;
gap: 4px;
box-sizing: border-box;
}
.ai-chat-content {
display: block;
width: calc(100% - 34px);
padding-left: 34px;
font-weight: 400;
}
.with-attachments {
margin-top: 8px;
}
`;
override render() {
const {
host,
textRendererOptions,
state,
content,
attachments,
messageRole,
userInfo,
} = this;
const withAttachments = !!attachments && attachments.length > 0;
const messageClasses = classMap({
'with-attachments': withAttachments,
});
return html`
<div class="ai-chat-message">
${UserInfoTemplate(userInfo, messageRole)}
<div class="ai-chat-content">
<chat-images .attachments=${attachments}></chat-images>
<div class=${messageClasses}>
<text-renderer
.host=${host}
.answer=${content}
.options=${textRendererOptions}
.state=${state}
></text-renderer>
</div>
</div>
</div>
`;
}
@property({ attribute: false })
accessor attachments: string[] | undefined = undefined;
@property({ attribute: false })
accessor content: string = '';
@property({ attribute: false })
accessor host!: EditorHost;
@property({ attribute: false })
accessor messageRole: MessageRole | undefined = undefined;
@property({ attribute: false })
accessor state: AffineAIPanelState = 'finished';
@property({ attribute: false })
accessor textRendererOptions: TextRendererOptions = {};
@property({ attribute: false })
accessor userInfo: MessageUserInfo = {};
}
export class AIChatMessages extends LitElement {
static override styles = css`
:host {
width: 100%;
box-sizing: border-box;
}
.ai-chat-messages {
display: flex;
box-sizing: border-box;
width: 100%;
height: 100%;
flex-direction: column;
gap: 24px;
}
`;
override render() {
return html`<div class="ai-chat-messages">
${repeat(
this.messages,
message => message.id,
message => {
const { attachments, role, content } = message;
const userInfo = {
userId: message.userId,
userName: message.userName,
avatarUrl: message.avatarUrl,
};
return html`
<ai-chat-message
.host=${this.host}
.textRendererOptions=${this.textRendererOptions}
.content=${content}
.attachments=${attachments}
.messageRole=${role}
.userInfo=${userInfo}
></ai-chat-message>
`;
}
)}
</div>`;
}
@property({ attribute: false })
accessor host!: EditorHost;
@property({ attribute: false })
accessor messages: ChatMessage[] = [];
@property({ attribute: false })
accessor textRendererOptions: TextRendererOptions = {};
}
declare global {
interface HTMLElementTagNameMap {
'ai-chat-message': AIChatMessage;
'ai-chat-messages': AIChatMessages;
}
}

View File

@@ -0,0 +1,102 @@
import { css, html, LitElement, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import { choose } from 'lit/directives/choose.js';
import { repeat } from 'lit/directives/repeat.js';
import { ImageLoadingFailedIcon, LoadingIcon } from '../../_common/icon';
export class ChatImage extends LitElement {
static override styles = css`
.image-container {
border-radius: 4px;
overflow: hidden;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 70%;
max-width: 200px;
max-height: 122px;
img {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
}
}
`;
override render() {
return choose(this.status, [
[
'loading',
() =>
html`<image-placeholder
.text=${'Loading image'}
.icon=${LoadingIcon}
></image-placeholder>`,
],
[
'error',
() =>
html`<image-placeholder
.text=${'Image Loading Failed'}
.icon=${ImageLoadingFailedIcon}
></image-placeholder>`,
],
[
'success',
() =>
html`<div class="image-container">
<img src=${this.imageUrl} />
</div>`,
],
]);
}
@property({ attribute: false })
accessor imageUrl!: string;
@property({ attribute: false })
accessor status!: 'loading' | 'error' | 'success';
}
export class ChatImages extends LitElement {
static override styles = css`
.images-container {
display: flex;
width: 100%;
gap: 8px;
flex-wrap: wrap;
}
`;
override render() {
if (!this.attachments || this.attachments.length === 0) {
return nothing;
}
return html`<div class="images-container">
${repeat(
this.attachments,
attachment => attachment,
attachment =>
html`<chat-image
.imageUrl=${attachment}
.status=${'success'}
></chat-image>`
)}
</div>`;
}
@property({ attribute: false })
accessor attachments: string[] | undefined;
}
declare global {
interface HTMLElementTagNameMap {
'chat-image': ChatImage;
'chat-images': ChatImages;
}
}

View File

@@ -0,0 +1,62 @@
import { baseTheme } from '@toeverything/theme';
import { css, html, LitElement, type TemplateResult, unsafeCSS } from 'lit';
import { property } from 'lit/decorators.js';
export class ImagePlaceholder extends LitElement {
static override styles = css`
.placeholder-container {
display: flex;
width: 100%;
height: 122px;
padding: 12px;
align-items: flex-start;
border-radius: 8px;
border: 1px solid var(--affine-background-tertiary-color);
background: var(--affine-background-secondary-color);
box-sizing: border-box;
}
.placeholder-title {
display: flex;
gap: 8px;
align-items: center;
color: var(--affine-placeholder-color, #c0bfc1);
text-align: justify;
/* light/smBold */
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
font-size: var(--affine-font-sm);
font-style: normal;
font-weight: 600;
line-height: 22px; /* 157.143% */
height: 22px;
}
.placeholder-icon {
display: flex;
align-items: center;
justify-content: center;
color: var(--affine-icon-color);
}
`;
override render() {
return html`<div class="placeholder-container">
<div class="placeholder-title">
<span class="placeholder-icon">${this.icon}</span>
<span>${this.text}</span>
</div>
</div>`;
}
@property({ attribute: false })
accessor icon!: TemplateResult<1>;
@property({ attribute: false })
accessor text!: string;
}
declare global {
interface HTMLElementTagNameMap {
'image-placeholder': ImagePlaceholder;
}
}

View File

@@ -0,0 +1,114 @@
import type { MessageRole, MessageUserInfo } from '@toeverything/infra';
import { baseTheme } from '@toeverything/theme';
import { css, html, LitElement, type TemplateResult, unsafeCSS } from 'lit';
import { property } from 'lit/decorators.js';
import { AffineAIIcon } from '../../_common/icon';
export class UserInfo extends LitElement {
static override styles = css`
.user-info-container {
display: flex;
width: 100%;
height: 24px;
flex-direction: row;
gap: 10px;
font-weight: 500;
.user-avatar-container {
width: 24px;
height: 24px;
color: var(--affine-brand-color);
display: flex;
justify-content: center;
align-items: center;
}
.default-avatar,
.user-avatar-container img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.user-avatar-container img {
object-fit: cover;
}
.default-avatar,
.avatar-image {
background-color: var(--affine-primary-color);
}
.user-name {
color: var(--affine-text-primary-color);
text-align: justify;
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
font-size: var(--affine-font-sm);
font-style: normal;
font-weight: 500;
line-height: 22px;
text-overflow: ellipsis;
}
}
`;
private _handleAvatarLoadError(e: Event) {
const target = e.target as HTMLImageElement;
target.onerror = null;
this.avatarLoadedFailed = true;
}
override render() {
return html`<div class="user-info-container">
<div class="user-avatar-container">
${this.avatarIcon
? this.avatarIcon
: this.avatarUrl && !this.avatarLoadedFailed
? html`<img
.src=${this.avatarUrl}
@error=${this._handleAvatarLoadError}
/>`
: html`<span class="default-avatar"></span>`}
</div>
<span class="user-name">${this.userName}</span>
</div>`;
}
@property({ attribute: false })
accessor avatarIcon: TemplateResult<1> | undefined = undefined;
@property({ attribute: false })
accessor avatarLoadedFailed = false;
@property({ attribute: false })
accessor avatarUrl: string | undefined = undefined;
@property({ attribute: false })
accessor userName!: string;
}
declare global {
interface HTMLElementTagNameMap {
'user-info': UserInfo;
}
}
export function UserInfoTemplate(
userInfo: MessageUserInfo,
messageRole?: MessageRole
) {
const isUser = !!messageRole && messageRole === 'user';
const userInfoTemplate = isUser
? html`<user-info
.userName=${userInfo.userName ?? 'You'}
.avatarUrl=${userInfo.avatarUrl}
></user-info>`
: html`<user-info
.userName=${'AFFiNE AI'}
.avatarIcon=${AffineAIIcon}
></user-info>`;
return userInfoTemplate;
}

View File

@@ -0,0 +1,3 @@
export * from './ai-chat-block.js';
export * from './ai-chat-edgeless-block.js';
export * from './ai-chat-spec.js';

View File

@@ -0,0 +1,54 @@
import { baseTheme } from '@toeverything/theme';
import { css, unsafeCSS } from 'lit';
export const AIChatBlockStyles = css`
.affine-ai-chat-block-container {
display: flex;
flex-direction: column;
align-items: flex-end;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 16px;
background: var(--affine-white);
color: var(--affine-text-primary-color);
line-height: 22px;
font-size: var(--affine-font-sm);
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
border-radius: 8px;
user-select: none;
pointer-events: none;
.ai-chat-messages-container {
display: block;
flex: 1 0 0;
width: 100%;
box-sizing: border-box;
background: linear-gradient(to top, transparent, var(--affine-white));
-webkit-mask-image: linear-gradient(
to bottom,
var(--affine-white) 25%,
transparent
);
mask-image: linear-gradient(
to bottom,
var(--affine-white) 25%,
transparent
);
overflow: hidden;
}
.ai-chat-block-button {
display: flex;
width: 100%;
height: 22px;
flex-direction: row;
align-items: center;
gap: 8px;
font-weight: 600;
svg {
color: var(--affine-icon-color);
}
}
}
`;

View File

@@ -0,0 +1,2 @@
export { AIChatMessages } from './ai-chat-block/components/ai-chat-messages.js';
export * from './ai-chat-block/index.js';

View File

@@ -0,0 +1,74 @@
import { TextRenderer } from './_common/components/text-renderer';
import { AskAIButton } from './ai/_common/components/ask-ai-button';
import { AskAIPanel } from './ai/_common/components/ask-ai-panel';
import { ChatActionList } from './ai/_common/components/chat-action-list';
import { ChatCopyMore } from './ai/_common/components/copy-more';
import { ChatPanel } from './ai/chat-panel';
import { ActionWrapper } from './ai/chat-panel/actions/action-wrapper';
import { ChatText } from './ai/chat-panel/actions/chat-text';
import { ActionImage } from './ai/chat-panel/actions/image';
import { ActionImageToText } from './ai/chat-panel/actions/image-to-text';
import { ActionMakeReal } from './ai/chat-panel/actions/make-real';
import { ActionMindmap } from './ai/chat-panel/actions/mindmap';
import { ActionSlides } from './ai/chat-panel/actions/slides';
import { ActionText } from './ai/chat-panel/actions/text';
import { AILoading } from './ai/chat-panel/ai-loading';
import { ChatCards } from './ai/chat-panel/chat-cards';
import { ChatPanelInput } from './ai/chat-panel/chat-panel-input';
import { ChatPanelMessages } from './ai/chat-panel/chat-panel-messages';
import { AIErrorWrapper } from './ai/messages/error';
import { AISlidesRenderer } from './ai/messages/slides-renderer';
import { AIAnswerWrapper } from './ai/messages/wrapper';
import { ChatBlockInput } from './ai/peek-view/chat-block-input';
import { AIChatBlockPeekView } from './ai/peek-view/chat-block-peek-view';
import { DateTime } from './ai/peek-view/date-time';
import { AIChatBlockComponent } from './blocks/ai-chat-block/ai-chat-block';
import { EdgelessAIChatBlockComponent } from './blocks/ai-chat-block/ai-chat-edgeless-block';
import {
AIChatMessage,
AIChatMessages,
} from './blocks/ai-chat-block/components/ai-chat-messages';
import {
ChatImage,
ChatImages,
} from './blocks/ai-chat-block/components/chat-images';
import { ImagePlaceholder } from './blocks/ai-chat-block/components/image-placeholder';
import { UserInfo } from './blocks/ai-chat-block/components/user-info';
export function registerBlocksuitePresetsCustomComponents() {
customElements.define('ask-ai-button', AskAIButton);
customElements.define('ask-ai-panel', AskAIPanel);
customElements.define('chat-action-list', ChatActionList);
customElements.define('chat-copy-more', ChatCopyMore);
customElements.define('action-wrapper', ActionWrapper);
customElements.define('chat-text', ChatText);
customElements.define('action-image-to-text', ActionImageToText);
customElements.define('action-image', ActionImage);
customElements.define('action-make-real', ActionMakeReal);
customElements.define('action-mindmap', ActionMindmap);
customElements.define('action-slides', ActionSlides);
customElements.define('action-text', ActionText);
customElements.define('ai-loading', AILoading);
customElements.define('chat-cards', ChatCards);
customElements.define('chat-panel-input', ChatPanelInput);
customElements.define('chat-panel-messages', ChatPanelMessages);
customElements.define('chat-panel', ChatPanel);
customElements.define('ai-error-wrapper', AIErrorWrapper);
customElements.define('ai-slides-renderer', AISlidesRenderer);
customElements.define('ai-answer-wrapper', AIAnswerWrapper);
customElements.define('chat-block-input', ChatBlockInput);
customElements.define('ai-chat-block-peek-view', AIChatBlockPeekView);
customElements.define('date-time', DateTime);
customElements.define(
'affine-edgeless-ai-chat',
EdgelessAIChatBlockComponent
);
customElements.define('affine-ai-chat', AIChatBlockComponent);
customElements.define('ai-chat-message', AIChatMessage);
customElements.define('ai-chat-messages', AIChatMessages);
customElements.define('image-placeholder', ImagePlaceholder);
customElements.define('chat-image', ChatImage);
customElements.define('chat-images', ChatImages);
customElements.define('user-info', UserInfo);
customElements.define('text-renderer', TextRenderer);
}

View File

@@ -1,4 +1,4 @@
import { registerAICustomComponents } from '@affine/core/blocksuite/presets/ai';
import { registerBlocksuitePresetsCustomComponents } from '@affine/core/blocksuite/presets/effects';
import { effects as bsEffects } from '@blocksuite/affine/effects';
import { setupAIProvider } from './ai/setup-provider';
@@ -9,6 +9,6 @@ bsEffects();
patchEffects();
setupAIProvider();
edgelessEffects();
registerAICustomComponents();
registerBlocksuitePresetsCustomComponents();
export * from './blocksuite-editor';

View File

@@ -3,6 +3,7 @@ import {
AIImageBlockSpec,
AIParagraphBlockSpec,
} from '@affine/core/blocksuite/presets/ai';
import { AIChatBlockSpec } from '@affine/core/blocksuite/presets/blocks/ai-chat-block';
import type { ExtensionType } from '@blocksuite/affine/block-std';
import {
BookmarkBlockSpec,
@@ -25,7 +26,6 @@ import {
RefNodeSlotsExtension,
RichTextExtensions,
} from '@blocksuite/affine/blocks';
import { AIChatBlockSpec } from '@blocksuite/affine/presets';
import { CustomAttachmentBlockSpec } from './custom/attachment-block';

View File

@@ -11,24 +11,16 @@ import type {
DatabaseBlockModel,
MenuOptions,
} from '@blocksuite/affine/blocks';
import { menu } from '@blocksuite/affine-components/context-menu';
import { LinkIcon } from '@blocksuite/icons/lit';
import type { FrameworkProvider } from '@toeverything/infra';
import type { TemplateResult } from 'lit';
export function createDatabaseOptionsConfig(framework: FrameworkProvider) {
return {
configure: (model: DatabaseBlockModel, options: MenuOptions) => {
const items = options.items;
const copyIndex = items.findIndex(
item => item.type === 'action' && item.name === 'Copy'
);
items.splice(
copyIndex + 1,
0,
createCopyLinkToBlockMenuItem(framework, model)
);
items.splice(2, 0, createCopyLinkToBlockMenuItem(framework, model));
return options;
},
@@ -38,17 +30,10 @@ export function createDatabaseOptionsConfig(framework: FrameworkProvider) {
function createCopyLinkToBlockMenuItem(
framework: FrameworkProvider,
model: DatabaseBlockModel
): {
type: 'action';
name: string;
icon?: TemplateResult<1>;
hide?: () => boolean;
select: () => void;
} {
return {
type: 'action',
) {
return menu.action({
name: 'Copy link to block',
icon: LinkIcon({ width: '20', height: '20' }),
prefix: LinkIcon({ width: '20', height: '20' }),
hide: () => {
const { editor } = framework.get(EditorService);
const mode = editor.mode$.value;
@@ -91,5 +76,5 @@ function createCopyLinkToBlockMenuItem(
})
.catch(console.error);
},
};
});
}

View File

@@ -50,9 +50,9 @@ import {
QuickSearchExtension,
ReferenceNodeConfigExtension,
} from '@blocksuite/affine/blocks';
import { AIChatBlockSchema } from '@blocksuite/affine/presets';
import { type BlockSnapshot, Text } from '@blocksuite/affine/store';
import {
AIChatBlockSchema,
type DocProps,
type DocService,
DocsService,

View File

@@ -1,6 +1,6 @@
import { AIChatBlockSpec } from '@affine/core/blocksuite/presets/blocks/ai-chat-block';
import type { ExtensionType } from '@blocksuite/affine/block-std';
import { SpecProvider } from '@blocksuite/affine/blocks';
import { AIChatBlockSpec } from '@blocksuite/affine/presets';
import { getFontConfigExtension } from './font-extension';

View File

@@ -1,3 +1,5 @@
import type { AffineTextAttributes } from '@blocksuite/affine/blocks';
import type { DeltaInsert } from '@blocksuite/affine/inline';
import type { DocCollection } from '@blocksuite/affine/store';
import { useCallback } from 'react';
@@ -8,7 +10,7 @@ export function useReferenceLinkHelper(docCollection: DocCollection) {
if (!page) {
return;
}
const text = page.Text.fromDelta([
const text = new page.Text([
{
insert: ' ',
attributes: {
@@ -18,7 +20,7 @@ export function useReferenceLinkHelper(docCollection: DocCollection) {
},
},
},
]);
] as DeltaInsert<AffineTextAttributes>[]);
const [frame] = page.getBlockByFlavour('affine:note');
frame && page.addBlock('affine:paragraph', { text }, frame.id);

View File

@@ -8,8 +8,8 @@ import type {
SurfaceRefBlockModel,
} from '@blocksuite/affine/blocks';
import { AffineReference } from '@blocksuite/affine/blocks';
import type { AIChatBlockModel } from '@blocksuite/affine/presets';
import type { BlockModel } from '@blocksuite/affine/store';
import type { AIChatBlockModel } from '@toeverything/infra';
import { Entity, LiveData } from '@toeverything/infra';
import type { TemplateResult } from 'lit';
import { firstValueFrom, map, race } from 'rxjs';

View File

@@ -6,7 +6,7 @@
"@affine/env": "workspace:*",
"@affine/templates": "workspace:*",
"@aws-sdk/client-s3": "^3.620.0",
"@blocksuite/affine": "0.17.18",
"@blocksuite/affine": "0.17.19",
"@clack/core": "^0.3.4",
"@clack/prompts": "^0.7.0",
"@magic-works/i18n-codegen": "^0.6.0",

409
yarn.lock
View File

@@ -237,7 +237,7 @@ __metadata:
"@affine/env": "workspace:*"
"@affine/templates": "workspace:*"
"@aws-sdk/client-s3": "npm:^3.620.0"
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
"@clack/core": "npm:^0.3.4"
"@clack/prompts": "npm:^0.7.0"
"@magic-works/i18n-codegen": "npm:^0.6.0"
@@ -294,7 +294,7 @@ __metadata:
"@affine/i18n": "workspace:*"
"@atlaskit/pragmatic-drag-and-drop": "npm:^1.2.1"
"@atlaskit/pragmatic-drag-and-drop-hitbox": "npm:^1.0.3"
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
"@blocksuite/icons": "npm:2.1.68"
"@chromatic-com/storybook": "npm:^2.0.0"
"@emotion/react": "npm:^11.11.4"
@@ -364,7 +364,7 @@ __metadata:
"@affine/i18n": "workspace:*"
"@affine/templates": "workspace:*"
"@affine/track": "workspace:*"
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
"@blocksuite/icons": "npm:2.1.68"
"@dnd-kit/core": "npm:^6.1.0"
"@dnd-kit/modifiers": "npm:^7.0.0"
@@ -375,6 +375,7 @@ __metadata:
"@floating-ui/dom": "npm:^1.6.5"
"@juggle/resize-observer": "npm:^3.4.0"
"@marsidev/react-turnstile": "npm:^1.0.0"
"@preact/signals-core": "npm:^1.8.0"
"@radix-ui/react-collapsible": "npm:^1.0.3"
"@radix-ui/react-dialog": "npm:^1.0.5"
"@radix-ui/react-popover": "npm:^1.0.7"
@@ -469,7 +470,7 @@ __metadata:
"@affine/core": "workspace:*"
"@affine/i18n": "workspace:*"
"@affine/native": "workspace:*"
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
"@electron-forge/cli": "npm:^7.3.0"
"@electron-forge/core": "npm:^7.3.0"
"@electron-forge/core-utils": "npm:^7.3.0"
@@ -522,7 +523,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@affine/env@workspace:packages/common/env"
dependencies:
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
vitest: "npm:2.1.1"
zod: "npm:^3.22.4"
peerDependencies:
@@ -571,7 +572,7 @@ __metadata:
"@affine/component": "workspace:*"
"@affine/core": "workspace:*"
"@affine/i18n": "workspace:*"
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
"@blocksuite/icons": "npm:^2.1.67"
"@sentry/react": "npm:^8.0.0"
"@types/react": "npm:^18.2.75"
@@ -2434,19 +2435,19 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/affine-block-embed@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-block-embed@npm:0.17.18"
"@blocksuite/affine-block-embed@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-block-embed@npm:0.17.19"
dependencies:
"@blocksuite/affine-block-surface": "npm:0.17.18"
"@blocksuite/affine-components": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/icons": "npm:^2.1.67"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-block-surface": "npm:0.17.19"
"@blocksuite/affine-components": "npm:0.17.19"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/icons": "npm:^2.1.68"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
@@ -2454,21 +2455,21 @@ __metadata:
lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8"
checksum: 10/d5ecbfe26c3858622e1468c3005bd70dcedf5ad093ddec127fecf62506204a98d266964c1d4a297de71ef029a8dbce0d9d72a1525d97feb04291c6d3300b56ba
checksum: 10/33586d045e67766ab2f2ef6f2df1776fb1a43e036e4bf10b99d523c4844d781ef9037afbd5203665cf5e30566d934e33a292593afb4e15261efe8268ff051290
languageName: node
linkType: hard
"@blocksuite/affine-block-list@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-block-list@npm:0.17.18"
"@blocksuite/affine-block-list@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-block-list@npm:0.17.19"
dependencies:
"@blocksuite/affine-components": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-components": "npm:0.17.19"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
@@ -2476,21 +2477,21 @@ __metadata:
lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8"
checksum: 10/3d0429f4c460a9d6a586695f5d3283ae336779b8d2044caa411856135a36bfd4c524367705f731bebbc3e546030cfa86b077db04e040befe476ec6089991fa2d
checksum: 10/e804d4ea2bef41efe7ee323aecde1339b3c8a499f16854c4a67877a39bae2d100e590dc758f004ec90fb8b7ebe1a61f003d045389557838230a905f2a187446d
languageName: node
linkType: hard
"@blocksuite/affine-block-paragraph@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-block-paragraph@npm:0.17.18"
"@blocksuite/affine-block-paragraph@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-block-paragraph@npm:0.17.19"
dependencies:
"@blocksuite/affine-components": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-components": "npm:0.17.19"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
@@ -2498,43 +2499,44 @@ __metadata:
lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8"
checksum: 10/4fd2e9bc6fa546a73ccc5b99954db1b5a74cf7a8fee3aca725a59740656da74c034c351541bf54b8f866786cd1c3b58c4e65382c1dedb4c70d94b25284d8b7b1
checksum: 10/a8caa526260b16ded0dae7bd4caae0d38f4fa7bcbdf96e36acf5cdb7e0fc14c330b2d0727b08c84384e19e3115ea1eec6a4061d29ccbc638bd68f7bcadb6fb98
languageName: node
linkType: hard
"@blocksuite/affine-block-surface@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-block-surface@npm:0.17.18"
"@blocksuite/affine-block-surface@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-block-surface@npm:0.17.19"
dependencies:
"@blocksuite/affine-components": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-components": "npm:0.17.19"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
"@toeverything/theme": "npm:^1.0.8"
fractional-indexing: "npm:^3.2.0"
lit: "npm:^3.2.0"
lodash.chunk: "npm:^4.2.0"
nanoid: "npm:^5.0.7"
zod: "npm:^3.23.8"
checksum: 10/a9aaf7d3cf5a6b890b4f1e7161367a2e84f284f7f4b0c9382188bebccf2905fdc1c4f2e126215129b90ac4049f073d579eda5926906295aee3cf4cce01fabc4c
checksum: 10/037831fca259761d23972958eff52d93068cf564efc4a149195a1979e754bad225232c20adb4eff0dbdfad37d1c07850042dde50efdeba1f9446bf5075cd9183
languageName: node
linkType: hard
"@blocksuite/affine-components@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-components@npm:0.17.18"
"@blocksuite/affine-components@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-components@npm:0.17.19"
dependencies:
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/icons": "npm:^2.1.67"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/icons": "npm:^2.1.68"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@lottiefiles/dotlottie-wc": "npm:^0.2.16"
@@ -2545,33 +2547,33 @@ __metadata:
lit: "npm:^3.2.0"
shiki: "npm:^1.12.0"
zod: "npm:^3.23.8"
checksum: 10/3c2433fa3529b9d271fcd8ad7fc480e83b18ee631423c24a57d8fb349ff2f0e713befbdcc8d5a84615126a7eef16a12d974108de39a3494d8b177c8aed536f66
checksum: 10/d77ec6a908851b06c3efb97ce6e8d3e944ce383f1804763a20b1956bb4fac9feb5d61e8bdd1abb968102989716a64246908017c93002d2d7996b4271ebdae324
languageName: node
linkType: hard
"@blocksuite/affine-model@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-model@npm:0.17.18"
"@blocksuite/affine-model@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-model@npm:0.17.19"
dependencies:
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
fractional-indexing: "npm:^3.2.0"
zod: "npm:^3.23.8"
checksum: 10/638e604b0b8c06f52f3b739eea223985550fc6a389a326bdec0cf1723878e5eff166585b86babcfd6ef63b430f5219baebe1e5243cd35971fbfda1483734dd41
checksum: 10/a47c149ed8dfde0bd56cc81be38d12884eb52e94df0484870fe6bb44ad5ea0ad82abe7a1a33e71d2ea9d6a1ffdf48d7bbb543318c4a97dbf0f09b39278700eaa
languageName: node
linkType: hard
"@blocksuite/affine-shared@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-shared@npm:0.17.18"
"@blocksuite/affine-shared@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-shared@npm:0.17.19"
dependencies:
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
@@ -2581,46 +2583,46 @@ __metadata:
lodash.mergewith: "npm:^4.6.2"
minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8"
checksum: 10/fcfb402cd25a8e43f3d4552b94b86d3d5257f9bcc838862930821221c3b9dca7da497849f1bddda34857e8e761e19be927e3b9c23e8af92df64f1a540ee31464
checksum: 10/2771454709f2a6f595b386464707c51a8e952cc36424ca1efe2fbb89444401f725a24bd66bddd1afa1f9668f005d4a6462306e70c672936f50e0d37092495a66
languageName: node
linkType: hard
"@blocksuite/affine-widget-scroll-anchoring@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine-widget-scroll-anchoring@npm:0.17.18"
"@blocksuite/affine-widget-scroll-anchoring@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine-widget-scroll-anchoring@npm:0.17.19"
dependencies:
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@preact/signals-core": "npm:^1.8.0"
"@toeverything/theme": "npm:^1.0.8"
lit: "npm:^3.2.0"
checksum: 10/f1206c07d2e5317ac1bde5f92f53f478ad13cbb3cb0668da0d6456bce9e80482c1d75af67587061c21bfa1b375cdb308faa12695cc478439f9772d4939ba6ab2
checksum: 10/ef2bbfe1b024404356ad4ceee00c0373bcd3627d32dc5ea4a241cf3539a6de2f5feb02e09f14b54721add9a30e7616c6f56234d3cf481f0625ea81ddbb555fab
languageName: node
linkType: hard
"@blocksuite/affine@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/affine@npm:0.17.18"
"@blocksuite/affine@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/affine@npm:0.17.19"
dependencies:
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/blocks": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/presets": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
checksum: 10/26efaae8cdf6279c5abb98a8e3603c28f474fdb0227bfee74f0f65113a29485cd62da6a06a1749e69b82cd7520fcf927fcf140bea1ad09be42d5bdbfc98b81da
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/blocks": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/presets": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
checksum: 10/58ec92eaa00624fbe9a6a180315afe7bbebafa5465cb86b01b38c378fa18a1a8cf5f9ff9325bf356fbd96448cdf5a6fcc4c002d08db3d34fc84b0b0b2b28f23a
languageName: node
linkType: hard
"@blocksuite/block-std@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/block-std@npm:0.17.18"
"@blocksuite/block-std@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/block-std@npm:0.17.19"
dependencies:
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
"@types/hast": "npm:^3.0.4"
@@ -2632,28 +2634,28 @@ __metadata:
unified: "npm:^11.0.5"
w3c-keyname: "npm:^2.2.8"
zod: "npm:^3.23.8"
checksum: 10/0e466bf95abe2294bec775b3e49c03ddbcc1b5a3aab4688b67292dc7d9c7dda82fcb7a26ed96194d633840b30d0af8f75f6c08b599507537e3377fb83804a89a
checksum: 10/b6011fc979f9711811b9ed8357df6c943fe4769db7fe4911a211964dbfd1fa38ba006df0a9d3c859c827a7f9f785d1865084b68d64c558a240139817b16c919f
languageName: node
linkType: hard
"@blocksuite/blocks@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/blocks@npm:0.17.18"
"@blocksuite/blocks@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/blocks@npm:0.17.19"
dependencies:
"@blocksuite/affine-block-embed": "npm:0.17.18"
"@blocksuite/affine-block-list": "npm:0.17.18"
"@blocksuite/affine-block-paragraph": "npm:0.17.18"
"@blocksuite/affine-block-surface": "npm:0.17.18"
"@blocksuite/affine-components": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/affine-widget-scroll-anchoring": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/data-view": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/icons": "npm:^2.1.67"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-block-embed": "npm:0.17.19"
"@blocksuite/affine-block-list": "npm:0.17.19"
"@blocksuite/affine-block-paragraph": "npm:0.17.19"
"@blocksuite/affine-block-surface": "npm:0.17.19"
"@blocksuite/affine-components": "npm:0.17.19"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/affine-widget-scroll-anchoring": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/data-view": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/icons": "npm:^2.1.68"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
@@ -2684,6 +2686,7 @@ __metadata:
pdf-lib: "npm:^1.17.1"
rehype-parse: "npm:^9.0.0"
rehype-stringify: "npm:^10.0.0"
remark-math: "npm:^6.0.0"
remark-parse: "npm:^11.0.0"
remark-stringify: "npm:^11.0.0"
shiki: "npm:^1.14.1"
@@ -2691,20 +2694,20 @@ __metadata:
sortablejs: "npm:^1.15.2"
unified: "npm:^11.0.5"
zod: "npm:^3.23.8"
checksum: 10/3703d4e40c99f82961c5afd27877306f40c62641f9312a2d519af1871c1ed50009f1d56b33b5889af385990e7532922d141593fcf1cd6fe5c4a571ad5a641955
checksum: 10/b3ab015d3d622638056bc831a2a21ba4877e8beb303895e0e8ca1dbe722172714f248c26fec52dab065db3976c47b76fb57a897bee5f2cd4fe70792eb6d3a92c
languageName: node
linkType: hard
"@blocksuite/data-view@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/data-view@npm:0.17.18"
"@blocksuite/data-view@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/data-view@npm:0.17.19"
dependencies:
"@blocksuite/affine-components": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/icons": "npm:^2.1.67"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-components": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/icons": "npm:^2.1.68"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
@@ -2713,23 +2716,23 @@ __metadata:
lit: "npm:^3.2.0"
sortablejs: "npm:^1.15.2"
zod: "npm:^3.23.8"
checksum: 10/0b95516ea82cb3c597cbc0230a04e51087dbe777f3bf862f9cdf881e52480208cac70ca7c632a89587c69c13a0f2c32f0456385b4a5700fe08392a11f8867411
checksum: 10/8e874f7038f1ca35f0f01db8b03d2ba8f84b83ae268ca92d7ebd6e3341e3fff9897bcb281e6321fe42e00aae9f8d9025d2ee7770ee0741783acedb15f0181dfe
languageName: node
linkType: hard
"@blocksuite/global@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/global@npm:0.17.18"
"@blocksuite/global@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/global@npm:0.17.19"
dependencies:
"@preact/signals-core": "npm:^1.8.0"
lib0: "npm:^0.2.97"
lit: "npm:^3.2.0"
zod: "npm:^3.23.8"
checksum: 10/9e3251d1100d83fc22468562e84093e3ab66bb12b6673c48173eb7780829092a7d9aaf94c8c91471ff78ede37958d6573eeec002442d6bec84920f3ffd391d67
checksum: 10/eac517fb270f7680f465af3874d64492fcf41d4313336dee2ba778b696b8019fb64cbe0e982da2bc1d4cc4c6b21726e5d81ad06a90017517ffaa579274f87b73
languageName: node
linkType: hard
"@blocksuite/icons@npm:2.1.68, @blocksuite/icons@npm:^2.1.67":
"@blocksuite/icons@npm:2.1.68, @blocksuite/icons@npm:^2.1.67, @blocksuite/icons@npm:^2.1.68":
version: 2.1.68
resolution: "@blocksuite/icons@npm:2.1.68"
peerDependencies:
@@ -2745,49 +2748,49 @@ __metadata:
languageName: node
linkType: hard
"@blocksuite/inline@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/inline@npm:0.17.18"
"@blocksuite/inline@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/inline@npm:0.17.19"
dependencies:
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.19"
"@preact/signals-core": "npm:^1.8.0"
zod: "npm:^3.23.8"
peerDependencies:
lit: ^3.2.0
yjs: ^13.6.18
checksum: 10/644fb3ae1a51bb6c0a7e6bbe54646726db8a6cdc4305bbf44d07d13c6c58cf311a8bd653b97f8885bce4db4dfb25f09343f8fab020369914dbfde6f5bbf8dba9
checksum: 10/fa03765e69847b2677548b2f491cd53e9028ca7d48e2ec102147d43d155fb1084bbc7c72cde51070a700e9b511cb462c9406e5f6f68cf8872a5a4f7ae0770b70
languageName: node
linkType: hard
"@blocksuite/presets@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/presets@npm:0.17.18"
"@blocksuite/presets@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/presets@npm:0.17.19"
dependencies:
"@blocksuite/affine-block-surface": "npm:0.17.18"
"@blocksuite/affine-model": "npm:0.17.18"
"@blocksuite/affine-shared": "npm:0.17.18"
"@blocksuite/block-std": "npm:0.17.18"
"@blocksuite/blocks": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/store": "npm:0.17.18"
"@blocksuite/affine-block-surface": "npm:0.17.19"
"@blocksuite/affine-model": "npm:0.17.19"
"@blocksuite/affine-shared": "npm:0.17.19"
"@blocksuite/block-std": "npm:0.17.19"
"@blocksuite/blocks": "npm:0.17.19"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/store": "npm:0.17.19"
"@floating-ui/dom": "npm:^1.6.10"
"@lottiefiles/dotlottie-wc": "npm:^0.2.16"
"@preact/signals-core": "npm:^1.8.0"
"@toeverything/theme": "npm:^1.0.8"
lit: "npm:^3.2.0"
zod: "npm:^3.23.8"
checksum: 10/83d23b5d53fb5149a3331534679d933c62aa7728e517775bc4333e0ef28f49233471af705e4e7bb988d9ad80cf07b3321e3d8130e26d3264a3b2cca6fd150406
checksum: 10/9f7c34223df50f23f872241e7fd05d163f6731710af01ba8a37fe91eb88596dd565f5e86a71717ba6e07ba888e22e72c75b0298959aebefc1583819a61629384
languageName: node
linkType: hard
"@blocksuite/store@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/store@npm:0.17.18"
"@blocksuite/store@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/store@npm:0.17.19"
dependencies:
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/inline": "npm:0.17.18"
"@blocksuite/sync": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.19"
"@blocksuite/inline": "npm:0.17.19"
"@blocksuite/sync": "npm:0.17.19"
"@preact/signals-core": "npm:^1.8.0"
"@types/flexsearch": "npm:^0.7.6"
"@types/lodash.ismatch": "npm:^4.4.9"
@@ -2803,21 +2806,21 @@ __metadata:
zod: "npm:^3.23.8"
peerDependencies:
yjs: ^13.6.18
checksum: 10/65add43cd868e4055e44347d0823127bb59ee56a2a29b30b3deacb631036dc90da7caa179794a3a75571dc5f6187dd02f98be40eb3c6b258d3006a10ee19b670
checksum: 10/64418424c466af8fec004f338fe1931c872af0cc2ec75c669a85ea52bd44c02b359e4f9def5ef1d99518397aae75e0931fe52be080d35410039b46d00243b404
languageName: node
linkType: hard
"@blocksuite/sync@npm:0.17.18":
version: 0.17.18
resolution: "@blocksuite/sync@npm:0.17.18"
"@blocksuite/sync@npm:0.17.19":
version: 0.17.19
resolution: "@blocksuite/sync@npm:0.17.19"
dependencies:
"@blocksuite/global": "npm:0.17.18"
"@blocksuite/global": "npm:0.17.19"
idb: "npm:^8.0.0"
idb-keyval: "npm:^6.2.1"
y-protocols: "npm:^1.0.6"
peerDependencies:
yjs: ^13.6.15
checksum: 10/2c5b67524a309577b1765c42684471d90173756e36bb33f8ee118739c83d6e12cee6738860de8101dc84badb49d641b4ab416ce43e3fbf6415ab5db22e3e60ee
checksum: 10/e3893e09122559df5d373e8f693683aa971e5c241b032ab2e5236bd91a544d1487ac00e1413805f1c657cf9475842073eeadfbaa6f307998830e40f0591ac921
languageName: node
linkType: hard
@@ -12841,7 +12844,7 @@ __metadata:
"@affine/debug": "workspace:*"
"@affine/env": "workspace:*"
"@affine/templates": "workspace:*"
"@blocksuite/affine": "npm:0.17.18"
"@blocksuite/affine": "npm:0.17.19"
"@datastructures-js/binary-search-tree": "npm:^5.3.2"
"@testing-library/react": "npm:^16.0.0"
fake-indexeddb: "npm:^6.0.0"
@@ -13426,6 +13429,13 @@ __metadata:
languageName: node
linkType: hard
"@types/katex@npm:^0.16.0":
version: 0.16.7
resolution: "@types/katex@npm:0.16.7"
checksum: 10/4fd15d93553be97c02c064e16be18d7ccbabf66ec72a9dc7fd5bfa47f0c7581da2f942f693c7cb59499de4c843c2189796e49c9647d336cbd52b777b6722a95a
languageName: node
linkType: hard
"@types/keygrip@npm:*":
version: 1.0.6
resolution: "@types/keygrip@npm:1.0.6"
@@ -23643,7 +23653,7 @@ __metadata:
languageName: node
linkType: hard
"katex@npm:^0.16.11":
"katex@npm:^0.16.0, katex@npm:^0.16.11":
version: 0.16.11
resolution: "katex@npm:0.16.11"
dependencies:
@@ -24031,6 +24041,13 @@ __metadata:
languageName: node
linkType: hard
"lodash.chunk@npm:^4.2.0":
version: 4.2.0
resolution: "lodash.chunk@npm:4.2.0"
checksum: 10/3b6639fda107a0d8c3996090eeb7ad0f05063e6a1f4692a01335e7c1990030d3274c3164d78159f24928d86eb0943ad326b0a4a2da706c250c4d3166ddd8ed0e
languageName: node
linkType: hard
"lodash.clonedeep@npm:^4.5.0":
version: 4.5.0
resolution: "lodash.clonedeep@npm:4.5.0"
@@ -24739,6 +24756,21 @@ __metadata:
languageName: node
linkType: hard
"mdast-util-math@npm:^3.0.0":
version: 3.0.0
resolution: "mdast-util-math@npm:3.0.0"
dependencies:
"@types/hast": "npm:^3.0.0"
"@types/mdast": "npm:^4.0.0"
devlop: "npm:^1.0.0"
longest-streak: "npm:^3.0.0"
mdast-util-from-markdown: "npm:^2.0.0"
mdast-util-to-markdown: "npm:^2.1.0"
unist-util-remove-position: "npm:^5.0.0"
checksum: 10/26f44933f3ae2bfce85df23e79cd31bcc42ef328eaeef70550f38310e29fc8eece5e79fc404ed1485fd38b9113e1817258ca6c1a602be82a933e0198d812c9af
languageName: node
linkType: hard
"mdast-util-phrasing@npm:^4.0.0":
version: 4.1.0
resolution: "mdast-util-phrasing@npm:4.1.0"
@@ -24766,7 +24798,7 @@ __metadata:
languageName: node
linkType: hard
"mdast-util-to-markdown@npm:^2.0.0":
"mdast-util-to-markdown@npm:^2.0.0, mdast-util-to-markdown@npm:^2.1.0":
version: 2.1.0
resolution: "mdast-util-to-markdown@npm:2.1.0"
dependencies:
@@ -25033,6 +25065,21 @@ __metadata:
languageName: node
linkType: hard
"micromark-extension-math@npm:^3.0.0":
version: 3.1.0
resolution: "micromark-extension-math@npm:3.1.0"
dependencies:
"@types/katex": "npm:^0.16.0"
devlop: "npm:^1.0.0"
katex: "npm:^0.16.0"
micromark-factory-space: "npm:^2.0.0"
micromark-util-character: "npm:^2.0.0"
micromark-util-symbol: "npm:^2.0.0"
micromark-util-types: "npm:^2.0.0"
checksum: 10/37b2002aca15cf354ff754191379942f2b36df5ceeb69509294d80b4e158e8af83dda03c434e1497ccc597d63cf85a1ccc0d46f17770fc7692f76887404c8d1d
languageName: node
linkType: hard
"micromark-factory-destination@npm:^2.0.0":
version: 2.0.0
resolution: "micromark-factory-destination@npm:2.0.0"
@@ -29075,6 +29122,18 @@ __metadata:
languageName: node
linkType: hard
"remark-math@npm:^6.0.0":
version: 6.0.0
resolution: "remark-math@npm:6.0.0"
dependencies:
"@types/mdast": "npm:^4.0.0"
mdast-util-math: "npm:^3.0.0"
micromark-extension-math: "npm:^3.0.0"
unified: "npm:^11.0.0"
checksum: 10/8cd262eadccba1a48bb2353e5b3d0ff18ae6aa2f00adec96458bfd4d414a0763463ff15d2c71d86330bbc355272d6ae7ae2efafba6cb4ae5ba7b7c642394c022
languageName: node
linkType: hard
"remark-parse@npm:^11.0.0":
version: 11.0.0
resolution: "remark-parse@npm:11.0.0"
@@ -32322,6 +32381,16 @@ __metadata:
languageName: node
linkType: hard
"unist-util-remove-position@npm:^5.0.0":
version: 5.0.0
resolution: "unist-util-remove-position@npm:5.0.0"
dependencies:
"@types/unist": "npm:^3.0.0"
unist-util-visit: "npm:^5.0.0"
checksum: 10/4d89dc25e2091f9d47d92552145a26bf0e4a32d6b453e9cacac7742d730ada186ee1b820579fee3eeaa31e119850c2cb82f8b5898f977a636d7220e998626967
languageName: node
linkType: hard
"unist-util-stringify-position@npm:^4.0.0":
version: 4.0.0
resolution: "unist-util-stringify-position@npm:4.0.0"