feat(core): add an independent AI panel (#13004)

close AI-246, AI-285
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **New Features**
* Introduced an AI chat interface accessible from the sidebar with a
dedicated "/chat" route.
* Added "AFFiNE Intelligent" button with AI icon to the sidebar for
quick chat access.
* Enhanced chat components with an "independent mode" for improved
message display and layout.
* Improved chat input and content styling, including responsive layout
and onboarding offset support.

* **Improvements**
  * Expanded icon support to include an AI icon in the app.
* Updated utility and schema functions for greater flexibility and error
prevention.
* Added a new chat container style for consistent layout and max width.

* **Bug Fixes**
* Prevented potential errors when certain editor hosts are not provided.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Cats Juice
2025-07-04 10:10:35 +08:00
committed by GitHub
parent e6b456330c
commit 64fb3a7243
12 changed files with 298 additions and 21 deletions
@@ -18,6 +18,7 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import type { Store } from '@blocksuite/affine/store';
import {
AiIcon,
AllDocsIcon,
ImportIcon,
JournalIcon,
@@ -86,6 +87,22 @@ const AllDocsButton = () => {
);
};
const AIChatButton = () => {
const { workbenchService } = useServices({
WorkbenchService,
});
const workbench = workbenchService.workbench;
const aiChatActive = useLiveData(
workbench.location$.selector(location => location.pathname === '/chat')
);
return (
<MenuLinkItem icon={<AiIcon />} active={aiChatActive} to={'/chat'}>
<span data-testid="ai-chat">AFFiNE Intelligent</span>
</MenuLinkItem>
);
};
/**
* This is for the whole affine app sidebar.
* This component wraps the app sidebar in `@affine/component` with logic and data.
@@ -184,6 +201,7 @@ export const RootAppSidebar = memo((): ReactElement => {
<AllDocsButton />
<AppSidebarJournalButton />
{sessionStatus === 'authenticated' && <NotificationButton />}
<AIChatButton />
<MenuItem
data-testid="slider-bar-workspace-setting-button"
icon={<SettingsIcon />}