feat: support save chat to block (#7481)

This commit is contained in:
donteatfriedrice
2024-07-24 09:46:36 +00:00
parent 98281a6394
commit 9d446469f8
18 changed files with 463 additions and 44 deletions
@@ -128,6 +128,7 @@ const blocksuiteFeatureFlags: Partial<Record<keyof BlockSuiteFlags, string>> = {
enable_database_statistics: 'Enable Database Block Statistics',
enable_block_query: 'Enable Todo Block Query',
enable_ai_onboarding: 'Enable AI Onboarding',
enable_ai_chat_block: 'Enable AI Chat Block',
};
const BlocksuiteFeatureFlagSettings = () => {
@@ -4,8 +4,10 @@ import {
createCopilotMessageMutation,
createCopilotSessionMutation,
fetcher as defaultFetcher,
forkCopilotSessionMutation,
getBaseUrl,
getCopilotHistoriesQuery,
getCopilotHistoryIdsQuery,
getCopilotSessionsQuery,
GraphQLError,
type GraphQLQuery,
@@ -76,6 +78,16 @@ export class CopilotClient {
return res.createCopilotSession;
}
async forkSession(options: OptionsField<typeof forkCopilotSessionMutation>) {
const res = await fetcher({
query: forkCopilotSessionMutation,
variables: {
options,
},
});
return res.forkCopilotSession;
}
async createMessage(
options: OptionsField<typeof createCopilotMessageMutation>
) {
@@ -117,6 +129,25 @@ export class CopilotClient {
return res.currentUser?.copilot?.histories;
}
async getHistoryIds(
workspaceId: string,
docId?: string,
options?: RequestOptions<
typeof getCopilotHistoriesQuery
>['variables']['options']
) {
const res = await fetcher({
query: getCopilotHistoryIdsQuery,
variables: {
workspaceId,
docId,
options,
},
});
return res.currentUser?.copilot?.histories;
}
async cleanupSessions(input: {
workspaceId: string;
docId: string;
@@ -1,4 +1,5 @@
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
import type { ForkChatSessionInput } from '@affine/graphql';
import { assertExists } from '@blocksuite/global/utils';
import { partition } from 'lodash-es';
@@ -44,6 +45,10 @@ export function createChatSession({
});
}
export function forkCopilotSession(forkChatSessionInput: ForkChatSessionInput) {
return client.forkSession(forkChatSessionInput);
}
async function resizeImage(blob: Blob | File): Promise<Blob | null> {
let src = '';
try {
@@ -256,6 +261,8 @@ export function textToText({
export const listHistories = client.getHistories;
export const listHistoryIds = client.getHistoryIds;
// Only one image is currently being processed
export function toImage({
docId,
@@ -3,7 +3,11 @@ import { authAtom, openSettingModalAtom } from '@affine/core/atoms';
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
import { toggleGeneralAIOnboarding } from '@affine/core/components/affine/ai-onboarding/apis';
import { mixpanel } from '@affine/core/utils';
import { getBaseUrl } from '@affine/graphql';
import {
getBaseUrl,
type getCopilotHistoriesQuery,
type RequestOptions,
} from '@affine/graphql';
import { Trans } from '@affine/i18n';
import { UnauthorizedError } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils';
@@ -14,6 +18,7 @@ import type { PromptKey } from './prompt';
import {
cleanupSessions,
createChatSession,
forkCopilotSession,
listHistories,
textToText,
toImage,
@@ -404,10 +409,13 @@ Could you make a new website based on these notes and send back just the html fi
},
chats: async (
workspaceId: string,
docId?: string
docId?: string,
options?: RequestOptions<
typeof getCopilotHistoriesQuery
>['variables']['options']
): Promise<BlockSuitePresets.AIHistory[]> => {
// @ts-expect-error - 'action' is missing in server impl
return (await listHistories(workspaceId, docId)) ?? [];
return (await listHistories(workspaceId, docId, options)) ?? [];
},
cleanup: async (
workspaceId: string,
@@ -416,6 +424,16 @@ Could you make a new website based on these notes and send back just the html fi
) => {
await cleanupSessions({ workspaceId, docId, sessionIds });
},
ids: async (
workspaceId: string,
docId?: string,
options?: RequestOptions<
typeof getCopilotHistoriesQuery
>['variables']['options']
): Promise<BlockSuitePresets.AIHistoryIds[]> => {
// @ts-expect-error - 'role' is missing type in server impl
return await listHistories(workspaceId, docId, options);
},
});
AIProvider.provide('photoEngine', {
@@ -443,6 +461,10 @@ Could you make a new website based on these notes and send back just the html fi
AIProvider.provide('onboarding', toggleGeneralAIOnboarding);
AIProvider.provide('forkChat', options => {
return forkCopilotSession(options);
});
AIProvider.slots.requestUpgradePlan.on(() => {
getCurrentStore().set(openSettingModalAtom, {
activeTab: 'billing',
@@ -19,6 +19,7 @@ import {
ListBlockSpec,
NoteBlockSpec,
} from '@blocksuite/blocks';
import { AIChatBlockSpec, EdgelessAIChatBlockSpec } from '@blocksuite/presets';
import { CustomAttachmentBlockSpec } from './custom/attachment-block';
@@ -41,4 +42,6 @@ export const CommonBlockSpecs: BlockSpec[] = [
AICodeBlockSpec,
AIImageBlockSpec,
AIParagraphBlockSpec,
AIChatBlockSpec,
EdgelessAIChatBlockSpec,
];