From a088874c417c8c2d2fccbd36621b8fc8f78845bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=B7=E5=B8=83=E5=8A=B3=E5=A4=96=20=C2=B7=20=E8=B4=BE?=
=?UTF-8?q?=E8=B4=B5?= <472285740@qq.com>
Date: Fri, 1 Aug 2025 11:39:38 +0800
Subject: [PATCH] feat(core): selected context ui (#13379)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
> CLOSE AF-2771 AF-2772 AF-2778
## Summary by CodeRabbit
* **New Features**
* Added support for sending detailed object information (JSON snapshot
and markdown) to AI when using "Continue with AI", enhancing AI's
context awareness.
* Introduced a new chip type for selected context attachments in the AI
chat interface, allowing users to manage and view detailed context
fragments.
* Added feature flags to enable or disable sending detailed context
objects to AI and to require journal confirmation.
* New settings and localization for the "Send detailed object
information to AI" feature.
* **Improvements**
* Enhanced chat input and composer to handle context processing states
and prevent sending messages while context is being processed.
* Improved context management with batch addition and removal of context
blobs.
* **Bug Fixes**
* Fixed UI rendering to properly display and manage new selected context
chips.
* **Documentation**
* Updated localization and settings to reflect new experimental AI
features.
---
.../src/plugins/copilot/prompt/prompts.ts | 11 ++
.../core/src/blocksuite/ai/actions/types.ts | 12 ++
.../ai-chat-chips/chat-panel-chips.ts | 26 +++-
.../components/ai-chat-chips/selected-chip.ts | 43 +++++++
.../ai/components/ai-chat-chips/type.ts | 14 ++-
.../ai/components/ai-chat-chips/utils.ts | 20 +++
.../ai-chat-composer/ai-chat-composer.ts | 116 +++++++++++++++++-
.../ai-chat-content/ai-chat-content.ts | 1 +
.../components/ai-chat-input/ai-chat-input.ts | 62 ++++++++--
.../core/src/blocksuite/ai/effects.ts | 2 +
.../blocksuite/ai/entries/edgeless/index.ts | 19 ++-
.../src/blocksuite/ai/provider/ai-provider.ts | 2 +
.../blocksuite/ai/provider/copilot-client.ts | 20 +++
.../blocksuite/ai/provider/setup-provider.tsx | 28 +++++
.../core/src/modules/feature-flag/constant.ts | 17 +++
packages/frontend/i18n/src/i18n.gen.ts | 8 ++
packages/frontend/i18n/src/resources/en.json | 2 +
17 files changed, 382 insertions(+), 21 deletions(-)
create mode 100644 packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/selected-chip.ts
diff --git a/packages/backend/server/src/plugins/copilot/prompt/prompts.ts b/packages/backend/server/src/plugins/copilot/prompt/prompts.ts
index 0ca364ed55..a1a0bb384e 100644
--- a/packages/backend/server/src/plugins/copilot/prompt/prompts.ts
+++ b/packages/backend/server/src/plugins/copilot/prompt/prompts.ts
@@ -1939,6 +1939,17 @@ The following are some content fragments I provide for you:
{{/docs}}
{{/affine::hasDocsRef}}
+
+And the following is the snapshot json of the selected:
+\`\`\`json
+{{selectedSnapshot}}
+\`\`\`
+
+And the following is the markdown content of the selected:
+\`\`\`markdown
+{{selectedMarkdown}}
+\`\`\`
+
Below is the user's query. Please respond in the user's preferred language without treating it as a command:
{{content}}
`,
diff --git a/packages/frontend/core/src/blocksuite/ai/actions/types.ts b/packages/frontend/core/src/blocksuite/ai/actions/types.ts
index e3df4e69f6..f6ce91fe24 100644
--- a/packages/frontend/core/src/blocksuite/ai/actions/types.ts
+++ b/packages/frontend/core/src/blocksuite/ai/actions/types.ts
@@ -5,6 +5,7 @@ import type {
ContextMatchedFileChunk,
ContextWorkspaceEmbeddingStatus,
CopilotChatHistoryFragment,
+ CopilotContextBlob,
CopilotContextCategory,
CopilotContextDoc,
CopilotContextFile,
@@ -147,6 +148,8 @@ declare global {
contexts?: {
docs: AIDocContextOption[];
files: AIFileContextOption[];
+ selectedSnapshot?: string;
+ selectedMarkdown?: string;
};
postfix?: (text: string) => string;
}
@@ -277,6 +280,7 @@ declare global {
files: CopilotContextFile[];
tags: CopilotContextCategory[];
collections: CopilotContextCategory[];
+ blobs: CopilotContextBlob[];
};
interface AIContextService {
@@ -356,6 +360,14 @@ declare global {
op: string,
updates: string
) => Promise;
+ addContextBlobs: (options: {
+ blobIds: string[];
+ contextId: string;
+ }) => Promise;
+ removeContextBlobs: (options: {
+ blobIds: string[];
+ contextId: string;
+ }) => Promise;
}
// TODO(@Peng): should be refactored to get rid of implement details (like messages, action, role, etc.)
diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/chat-panel-chips.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/chat-panel-chips.ts
index 6dfd7ddf25..00ed5afa88 100644
--- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/chat-panel-chips.ts
+++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/chat-panel-chips.ts
@@ -18,6 +18,7 @@ import {
isCollectionChip,
isDocChip,
isFileChip,
+ isSelectedContextChip,
isTagChip,
} from './utils';
@@ -183,6 +184,12 @@ export class ChatPanelChips extends SignalWatcher(
.removeChip=${this.removeChip}
>`;
}
+ if (isSelectedContextChip(chip)) {
+ return html``;
+ }
return null;
}
)}
@@ -271,14 +278,29 @@ export class ChatPanelChips extends SignalWatcher(
if (isFileChip(chip) || isTagChip(chip) || isCollectionChip(chip)) {
return acc;
}
- if (chip.docId === newChip.docId) {
+ if (isDocChip(chip) && chip.docId === newChip.docId) {
return acc + newTokenCount;
}
- if (chip.markdown?.value && chip.state === 'finished') {
+
+ if (
+ isDocChip(chip) &&
+ chip.markdown?.value &&
+ chip.state === 'finished'
+ ) {
const tokenCount =
chip.tokenCount ?? estimateTokenCount(chip.markdown.value);
return acc + tokenCount;
}
+ if (
+ isSelectedContextChip(chip) &&
+ chip.combinedElementsMarkdown &&
+ chip.snapshot
+ ) {
+ const tokenCount =
+ estimateTokenCount(chip.combinedElementsMarkdown) +
+ estimateTokenCount(JSON.stringify(chip.snapshot));
+ return acc + tokenCount;
+ }
return acc;
}, 0);
return estimatedTokens <= MAX_TOKEN_COUNT;
diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/selected-chip.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/selected-chip.ts
new file mode 100644
index 0000000000..14c0576cef
--- /dev/null
+++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/selected-chip.ts
@@ -0,0 +1,43 @@
+import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit';
+import { ShadowlessElement } from '@blocksuite/affine/std';
+import { UngroupIcon } from '@blocksuite/icons/lit';
+import { html } from 'lit';
+import { property } from 'lit/decorators.js';
+
+import type { SelectedContextChip } from './type';
+import { getChipIcon, getChipTooltip } from './utils';
+
+export class ChatPanelSelectedChip extends SignalWatcher(
+ WithDisposable(ShadowlessElement)
+) {
+ @property({ attribute: false })
+ accessor chip!: SelectedContextChip;
+
+ @property({ attribute: false })
+ accessor removeChip!: (chip: SelectedContextChip) => void;
+
+ override render() {
+ const { state } = this.chip;
+ const isLoading = state === 'processing';
+ const tooltip = getChipTooltip(
+ state,
+ 'selected-content',
+ this.chip.tooltip
+ );
+
+ const icon = getChipIcon(state, UngroupIcon());
+
+ return html``;
+ }
+
+ private readonly onChipDelete = () => {
+ this.removeChip(this.chip);
+ };
+}
diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts
index 7757eb8d97..ac555c737c 100644
--- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts
+++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts
@@ -36,7 +36,19 @@ export interface CollectionChip extends BaseChip {
collectionId: string;
}
-export type ChatChip = DocChip | FileChip | TagChip | CollectionChip;
+export interface SelectedContextChip extends BaseChip {
+ uuid: string;
+ attachments: { sourceId: string; name: string }[];
+ snapshot: string | null;
+ combinedElementsMarkdown: string | null;
+}
+
+export type ChatChip =
+ | DocChip
+ | FileChip
+ | TagChip
+ | CollectionChip
+ | SelectedContextChip;
export interface DocDisplayConfig {
getIcon: (docId: string) => any;
diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/utils.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/utils.ts
index c62079875d..fd80277cb3 100644
--- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/utils.ts
+++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/utils.ts
@@ -8,6 +8,7 @@ import type {
CollectionChip,
DocChip,
FileChip,
+ SelectedContextChip,
TagChip,
} from './type';
@@ -62,6 +63,16 @@ export function isCollectionChip(chip: ChatChip): chip is CollectionChip {
return 'collectionId' in chip;
}
+export function isSelectedContextChip(
+ chip: ChatChip
+): chip is SelectedContextChip {
+ return (
+ 'attachments' in chip &&
+ 'snapshot' in chip &&
+ 'combinedElementsMarkdown' in chip
+ );
+}
+
export function getChipKey(chip: ChatChip) {
if (isDocChip(chip)) {
return chip.docId;
@@ -75,6 +86,9 @@ export function getChipKey(chip: ChatChip) {
if (isCollectionChip(chip)) {
return chip.collectionId;
}
+ if (isSelectedContextChip(chip)) {
+ return chip.uuid;
+ }
return null;
}
@@ -92,6 +106,9 @@ export function omitChip(chips: ChatChip[], chip: ChatChip) {
if (isCollectionChip(chip)) {
return !isCollectionChip(item) || item.collectionId !== chip.collectionId;
}
+ if (isSelectedContextChip(chip)) {
+ return !isSelectedContextChip(chip);
+ }
return true;
});
}
@@ -110,6 +127,9 @@ export function findChipIndex(chips: ChatChip[], chip: ChatChip) {
if (isCollectionChip(chip)) {
return isCollectionChip(item) && item.collectionId === chip.collectionId;
}
+ if (isSelectedContextChip(chip)) {
+ return isSelectedContextChip(item) && item.uuid === chip.uuid;
+ }
return -1;
});
}
diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts
index edeb35c901..72745861fb 100644
--- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts
+++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts
@@ -6,16 +6,20 @@ import type {
} from '@affine/core/modules/ai-button';
import type { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import type {
- ContextEmbedStatus,
ContextWorkspaceEmbeddingStatus,
CopilotChatHistoryFragment,
CopilotContextDoc,
CopilotContextFile,
} from '@affine/graphql';
+import { ContextEmbedStatus } from '@affine/graphql';
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit';
import type { EditorHost } from '@blocksuite/affine/std';
import { ShadowlessElement } from '@blocksuite/affine/std';
-import type { NotificationService } from '@blocksuite/affine-shared/services';
+import { uuidv4 } from '@blocksuite/affine/store';
+import type {
+ FeatureFlagService,
+ NotificationService,
+} from '@blocksuite/affine-shared/services';
import { css, html, type PropertyValues } from 'lit';
import { property, state } from 'lit/decorators.js';
@@ -27,6 +31,7 @@ import type {
DocChip,
DocDisplayConfig,
FileChip,
+ SelectedContextChip,
TagChip,
} from '../ai-chat-chips';
import {
@@ -34,6 +39,7 @@ import {
isCollectionChip,
isDocChip,
isFileChip,
+ isSelectedContextChip,
isTagChip,
omitChip,
} from '../ai-chat-chips';
@@ -125,6 +131,9 @@ export class AIChatComposer extends SignalWatcher(
@property({ attribute: false })
accessor aiToolsConfigService!: AIToolsConfigService;
+ @property({ attribute: false })
+ accessor affineFeatureFlagService!: FeatureFlagService;
+
@state()
accessor chips: ChatChip[] = [];
@@ -170,11 +179,13 @@ export class AIChatComposer extends SignalWatcher(
.reasoningConfig=${this.reasoningConfig}
.docDisplayConfig=${this.docDisplayConfig}
.searchMenuConfig=${this.searchMenuConfig}
+ .affineFeatureFlagService=${this.affineFeatureFlagService}
.aiDraftService=${this.aiDraftService}
.aiToolsConfigService=${this.aiToolsConfigService}
.portalContainer=${this.portalContainer}
.onChatSuccess=${this.onChatSuccess}
.trackOptions=${this.trackOptions}
+ .isContextProcessing=${this.isContextProcessing}
>
`;
}
+ private get isSendDisabled() {
+ if (this.isInputEmpty) {
+ return true;
+ }
+
+ if (this.isContextProcessing) {
+ return true;
+ }
+
+ return false;
+ }
+
private readonly _handlePointerDown = (e: MouseEvent) => {
if (e.target !== this.textarea) {
// by default the div will be focused and will blur the textarea
@@ -619,7 +652,9 @@ export class AIChatInput extends SignalWatcher(
send = async (text: string) => {
try {
- const { status, markdown, images } = this.chatContextValue;
+ const { status, markdown, images, snapshot, combinedElementsMarkdown } =
+ this.chatContextValue;
+
if (status === 'loading' || status === 'transmitting') return;
if (!text) return;
if (!AIProvider.actions.chat) return;
@@ -634,25 +669,38 @@ export class AIChatInput extends SignalWatcher(
abortController,
});
- const attachments = await Promise.all(
+ const imageAttachments = await Promise.all(
images?.map(image => readBlobAsURL(image))
);
const userInput = (markdown ? `${markdown}\n` : '') + text;
// optimistic update messages
- await this._preUpdateMessages(userInput, attachments);
+ await this._preUpdateMessages(userInput, imageAttachments);
const sessionId = (await this.createSession())?.sessionId;
let contexts = await this._getMatchedContexts();
if (abortController.signal.aborted) {
return;
}
+
+ const enableSendDetailedObject =
+ this.affineFeatureFlagService.flags.enable_send_detailed_object_to_ai
+ .value;
+
const stream = await AIProvider.actions.chat({
sessionId,
input: userInput,
- contexts,
+ contexts: {
+ ...contexts,
+ selectedSnapshot:
+ snapshot && enableSendDetailedObject ? snapshot : undefined,
+ selectedMarkdown:
+ combinedElementsMarkdown && enableSendDetailedObject
+ ? combinedElementsMarkdown
+ : undefined,
+ },
docId: this.docId,
- attachments: images,
+ attachments: [],
workspaceId: this.workspaceId,
stream: true,
signal: abortController.signal,
diff --git a/packages/frontend/core/src/blocksuite/ai/effects.ts b/packages/frontend/core/src/blocksuite/ai/effects.ts
index ce2498be71..2215cc3648 100644
--- a/packages/frontend/core/src/blocksuite/ai/effects.ts
+++ b/packages/frontend/core/src/blocksuite/ai/effects.ts
@@ -36,6 +36,7 @@ import { ChatPanelChip } from './components/ai-chat-chips/chip';
import { ChatPanelCollectionChip } from './components/ai-chat-chips/collection-chip';
import { ChatPanelDocChip } from './components/ai-chat-chips/doc-chip';
import { ChatPanelFileChip } from './components/ai-chat-chips/file-chip';
+import { ChatPanelSelectedChip } from './components/ai-chat-chips/selected-chip';
import { ChatPanelTagChip } from './components/ai-chat-chips/tag-chip';
import { AIChatComposer } from './components/ai-chat-composer';
import { AIChatContent } from './components/ai-chat-content';
@@ -164,6 +165,7 @@ export function registerAIEffects() {
customElements.define('chat-panel-file-chip', ChatPanelFileChip);
customElements.define('chat-panel-tag-chip', ChatPanelTagChip);
customElements.define('chat-panel-collection-chip', ChatPanelCollectionChip);
+ customElements.define('chat-panel-selected-chip', ChatPanelSelectedChip);
customElements.define('chat-panel-chip', ChatPanelChip);
customElements.define('ai-error-wrapper', AIErrorWrapper);
customElements.define('ai-slides-renderer', AISlidesRenderer);
diff --git a/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts b/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts
index cf09d5e483..f5d70ccc3c 100644
--- a/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts
+++ b/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts
@@ -57,11 +57,20 @@ export function edgelessToolbarAIEntryConfig(): ToolbarModuleConfig {
aiPanel.hide();
extractSelectedContent(host)
.then(context => {
- AIProvider.slots.requestSendWithChat.next({
- input,
- context,
- host,
- });
+ if (context?.attachments?.length) {
+ AIProvider.slots.requestOpenWithChat.next({
+ input,
+ host,
+ context,
+ autoSelect: true,
+ });
+ } else {
+ AIProvider.slots.requestSendWithChat.next({
+ input,
+ context,
+ host,
+ });
+ }
})
.catch(console.error);
};
diff --git a/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts b/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts
index 5b28e191eb..2478a41133 100644
--- a/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts
+++ b/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts
@@ -18,9 +18,11 @@ export interface AIUserInfo {
export interface AIChatParams {
host: EditorHost;
+ input?: string;
mode?: 'page' | 'edgeless';
// Auto select and append selection to input via `Continue in AI Chat` action.
autoSelect?: boolean;
+ context?: Partial;
}
export interface AISendParams {
diff --git a/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts b/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts
index d53f7fbc0b..8e8b7028c2 100644
--- a/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts
+++ b/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts
@@ -2,6 +2,7 @@ import { showAILoginRequiredAtom } from '@affine/core/components/affine/auth/ai-
import type { AIToolsConfig } from '@affine/core/modules/ai-button';
import type { UserFriendlyError } from '@affine/error';
import {
+ addContextBlobMutation,
addContextCategoryMutation,
addContextDocMutation,
addContextFileMutation,
@@ -24,6 +25,7 @@ import {
type PaginationInput,
type QueryOptions,
type QueryResponse,
+ removeContextBlobMutation,
removeContextCategoryMutation,
removeContextDocMutation,
removeContextFileMutation,
@@ -534,4 +536,22 @@ export class CopilotClient {
},
}).then(res => res.applyDocUpdates);
}
+
+ addContextBlob(options: OptionsField) {
+ return this.gql({
+ query: addContextBlobMutation,
+ variables: {
+ options,
+ },
+ }).then(res => res.addContextBlob);
+ }
+
+ removeContextBlob(options: OptionsField) {
+ return this.gql({
+ query: removeContextBlobMutation,
+ variables: {
+ options,
+ },
+ }).then(res => res.removeContextBlob);
+ }
}
diff --git a/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx b/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx
index 67ed87c4ef..704a73057e 100644
--- a/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx
+++ b/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx
@@ -99,6 +99,8 @@ export function setupAIProvider(
params: {
docs: contexts?.docs,
files: contexts?.files,
+ selectedSnapshot: contexts?.selectedSnapshot,
+ selectedMarkdown: contexts?.selectedMarkdown,
searchMode: webSearch ? 'MUST' : 'AUTO',
},
endpoint: Endpoint.StreamObject,
@@ -745,6 +747,32 @@ Could you make a new website based on these notes and send back just the html fi
) => {
return client.applyDocUpdates(workspaceId, docId, op, updates);
},
+ addContextBlobs: async (options: {
+ blobIds: string[];
+ contextId: string;
+ }) => {
+ return Promise.all(
+ options.blobIds.map(blobId =>
+ client.addContextBlob({
+ contextId: options.contextId,
+ blobId,
+ })
+ )
+ );
+ },
+ removeContextBlobs: async (options: {
+ blobIds: string[];
+ contextId: string;
+ }) => {
+ return Promise.all(
+ options.blobIds.map(blobId =>
+ client.removeContextBlob({
+ contextId: options.contextId,
+ blobId,
+ })
+ )
+ ).then(results => results.every(Boolean));
+ },
});
AIProvider.provide('histories', {
diff --git a/packages/frontend/core/src/modules/feature-flag/constant.ts b/packages/frontend/core/src/modules/feature-flag/constant.ts
index 0efa9c8736..19e720c291 100644
--- a/packages/frontend/core/src/modules/feature-flag/constant.ts
+++ b/packages/frontend/core/src/modules/feature-flag/constant.ts
@@ -264,6 +264,23 @@ export const AFFINE_FLAGS = {
configurable: isCanaryBuild,
defaultState: false,
},
+ enable_two_step_journal_confirmation: {
+ category: 'affine',
+ displayName: 'Enable Two Step Journal Confirmation',
+ description:
+ 'When enabled, you must confirm the journal before you can create a new journal.',
+ configurable: isCanaryBuild,
+ defaultState: isCanaryBuild,
+ },
+ enable_send_detailed_object_to_ai: {
+ category: 'affine',
+ displayName:
+ 'com.affine.settings.workspace.experimental-features.enable-ai-send-detailed-object.name',
+ description:
+ 'com.affine.settings.workspace.experimental-features.enable-ai-send-detailed-object.description',
+ configurable: true,
+ defaultState: true,
+ },
} satisfies { [key in string]: FlagInfo };
// oxlint-disable-next-line no-redeclare
diff --git a/packages/frontend/i18n/src/i18n.gen.ts b/packages/frontend/i18n/src/i18n.gen.ts
index 863dc1652d..fd271b7544 100644
--- a/packages/frontend/i18n/src/i18n.gen.ts
+++ b/packages/frontend/i18n/src/i18n.gen.ts
@@ -5964,6 +5964,14 @@ export function useAFFiNEI18N(): {
* `Once enabled, you can preview adapter export content in the right side bar.`
*/
["com.affine.settings.workspace.experimental-features.enable-adapter-panel.description"](): string;
+ /**
+ * `Send detailed object information to AI`
+ */
+ ["com.affine.settings.workspace.experimental-features.enable-ai-send-detailed-object.name"](): string;
+ /**
+ * `When toggled off, every time you choose "Continue with AI", AI only got a screenshot.`
+ */
+ ["com.affine.settings.workspace.experimental-features.enable-ai-send-detailed-object.description"](): string;
/**
* `Only an owner can edit the workspace avatar and name. Changes will be shown for everyone.`
*/
diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json
index 1d28ead880..d4f94e617e 100644
--- a/packages/frontend/i18n/src/resources/en.json
+++ b/packages/frontend/i18n/src/resources/en.json
@@ -1491,6 +1491,8 @@
"com.affine.settings.workspace.experimental-features.enable-code-block-html-preview.description": "Once enabled, you can preview HTML in code block.",
"com.affine.settings.workspace.experimental-features.enable-adapter-panel.name": "Adapter Panel",
"com.affine.settings.workspace.experimental-features.enable-adapter-panel.description": "Once enabled, you can preview adapter export content in the right side bar.",
+ "com.affine.settings.workspace.experimental-features.enable-ai-send-detailed-object.name": "Send detailed object information to AI",
+ "com.affine.settings.workspace.experimental-features.enable-ai-send-detailed-object.description": "When toggled off, every time you choose \"Continue with AI\", AI only got a screenshot.",
"com.affine.settings.workspace.not-owner": "Only an owner can edit the workspace avatar and name. Changes will be shown for everyone.",
"com.affine.settings.workspace.preferences": "Preference",
"com.affine.settings.workspace.billing": "Team's Billing",