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) {