mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
BlockPartHostedResource: enable always-embed
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import TimeAgo from 'react-timeago';
|
||||
|
||||
import { Box, CircularProgress, Dropdown, IconButton, ListDivider, ListItemDecorator, Menu, MenuButton, MenuItem, Sheet, Typography } from '@mui/joy';
|
||||
import { Box, Checkbox, CircularProgress, Dropdown, IconButton, ListDivider, ListItemDecorator, Menu, MenuButton, MenuItem, Sheet, Typography } from '@mui/joy';
|
||||
import AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||
@@ -21,6 +21,7 @@ import { copyBlobPromiseToClipboard, copyToClipboard } from '~/common/util/clipb
|
||||
import { downloadBlob } from '~/common/util/downloadUtils';
|
||||
import { humanReadableBytes } from '~/common/util/textUtils';
|
||||
import { mimeTypeIsPlainText, mimeTypeIsSupportedImage } from '~/common/attachment-drafts/attachment.mimetypes';
|
||||
import { useAIPreferencesStore } from '~/common/stores/store-ai';
|
||||
import { useLlmServiceAccess } from '~/common/stores/llms/hooks/useLlmServiceAccess';
|
||||
import { useOverlayComponents } from '~/common/layout/overlays/useOverlayComponents';
|
||||
|
||||
@@ -63,6 +64,7 @@ function AnthropicFileChip(props: {
|
||||
const { access, fileId, onFragmentDelete, onFragmentReplace } = props;
|
||||
|
||||
// external state
|
||||
const autoEmbedEnabled = useAIPreferencesStore(state => state.vndAntInlineFiles !== 'off');
|
||||
const { data: metadata, isLoading: metaLoading, error: metaError } = apiQuery.llmAnthropic.fileApiGetMetadata.useQuery({ access, fileId }, {
|
||||
staleTime: Infinity,
|
||||
select: _enrichMetadataWithMimeFlags,
|
||||
@@ -152,29 +154,29 @@ function AnthropicFileChip(props: {
|
||||
fence += '`';
|
||||
onFragmentReplace(createTextContentFragment(`${fence}${fileName}\n${text}\n${fence}\n`));
|
||||
}
|
||||
// image: get dimensions, store in DBlob, and create a Zync asset reference
|
||||
// else if (data.httpMimeIsImage) {
|
||||
//
|
||||
// const { width, height } = await imageBlobGetDimensions(data.blob).catch(() => ({ width: 0, height: 0 }));
|
||||
//
|
||||
// const dblobAssetId = await addDBImageAsset('app-chat', data.blob, {
|
||||
// label: fileName,
|
||||
// origin: { ot: 'generated', source: 'ai-text-to-image', generatorName: 'anthropic-code-execution', prompt: '', parameters: {}, generatedAt: new Date().toISOString() },
|
||||
// metadata: { width, height },
|
||||
// });
|
||||
//
|
||||
// onFragmentReplace(createZyncAssetReferenceContentFragment(
|
||||
// nanoidToUuidV4(dblobAssetId, 'convert-dblob-to-dasset'),
|
||||
// fileName,
|
||||
// 'image',
|
||||
// {
|
||||
// pt: 'image_ref',
|
||||
// dataRef: createDMessageDataRefDBlob(dblobAssetId, data.httpMimeType, data.blob.size),
|
||||
// ...(fileName ? { altText: fileName } : {}),
|
||||
// ...(width ? { width } : {}),
|
||||
// ...(height ? { height } : {}),
|
||||
// },
|
||||
// ));
|
||||
// image: get dimensions, store in DBlob, and create a Zync asset reference
|
||||
// else if (data.httpMimeIsImage) {
|
||||
//
|
||||
// const { width, height } = await imageBlobGetDimensions(data.blob).catch(() => ({ width: 0, height: 0 }));
|
||||
//
|
||||
// const dblobAssetId = await addDBImageAsset('app-chat', data.blob, {
|
||||
// label: fileName,
|
||||
// origin: { ot: 'generated', source: 'ai-text-to-image', generatorName: 'anthropic-code-execution', prompt: '', parameters: {}, generatedAt: new Date().toISOString() },
|
||||
// metadata: { width, height },
|
||||
// });
|
||||
//
|
||||
// onFragmentReplace(createZyncAssetReferenceContentFragment(
|
||||
// nanoidToUuidV4(dblobAssetId, 'convert-dblob-to-dasset'),
|
||||
// fileName,
|
||||
// 'image',
|
||||
// {
|
||||
// pt: 'image_ref',
|
||||
// dataRef: createDMessageDataRefDBlob(dblobAssetId, data.httpMimeType, data.blob.size),
|
||||
// ...(fileName ? { altText: fileName } : {}),
|
||||
// ...(width ? { width } : {}),
|
||||
// ...(height ? { height } : {}),
|
||||
// },
|
||||
// ));
|
||||
// }
|
||||
else
|
||||
return setActionError('Cannot inline this file type');
|
||||
@@ -189,6 +191,29 @@ function AnthropicFileChip(props: {
|
||||
}, [fileContent, refetchFileContent, access, fileId, fileName, onFragmentReplace]);
|
||||
|
||||
|
||||
const handleToggleAutoEmbed = React.useCallback(async () => {
|
||||
if (autoEmbedEnabled)
|
||||
return useAIPreferencesStore.getState().setVndAntInlineFiles('off');
|
||||
if (await showPromisedOverlay('chat-message-auto-embed-notice', { rejectWithValue: false }, ({ onResolve, onUserReject }) =>
|
||||
<ConfirmationModal
|
||||
open onClose={onUserReject} onPositive={() => onResolve(true)}
|
||||
noTitleBar
|
||||
lowStakes
|
||||
confirmationText={<>
|
||||
From now on, files generated by Claude tools (code execution, etc.) will be automatically downloaded and embedded into messages, then removed from Anthropic's File API.
|
||||
<br /><br />
|
||||
You can change this anytime in <b>Settings > Chat AI > Anthropic File Inlining</b>.
|
||||
</>}
|
||||
positiveActionText='Enable & Embed'
|
||||
negativeActionText='Cancel'
|
||||
/>,
|
||||
)) {
|
||||
useAIPreferencesStore.getState().setVndAntInlineFiles('inline-file-and-delete');
|
||||
await handleInline();
|
||||
}
|
||||
}, [autoEmbedEnabled, handleInline, showPromisedOverlay]);
|
||||
|
||||
|
||||
const canCopy = !!metadata?.mimeIsText || !!metadata?.mimeIsImage;
|
||||
const canInline = !!onFragmentReplace && !!metadata?.mimeIsText; // for images, replace with ... && canCopy
|
||||
|
||||
@@ -236,6 +261,13 @@ function AnthropicFileChip(props: {
|
||||
</IconButton>
|
||||
</GoodTooltip>
|
||||
)}
|
||||
{/*{canInline && (*/}
|
||||
{/* <GoodTooltip title='Embed in chat'>*/}
|
||||
{/* <IconButton variant='soft' color='primary' disabled={isBusy} onClick={handleInline} size='sm'>*/}
|
||||
{/* {busy === 'inline' ? <CircularProgress size='sm' /> : <VerticalAlignBottomIcon sx={{ fontSize: 'lg' }} />}*/}
|
||||
{/* </IconButton>*/}
|
||||
{/* </GoodTooltip>*/}
|
||||
{/*)}*/}
|
||||
<GoodTooltip title='Download file'>
|
||||
<IconButton variant='soft' color='primary' disabled={isBusy || isFileGone} onClick={handleDownload} size='sm'>
|
||||
{busy === 'download' ? <CircularProgress size='sm' /> : <DownloadIcon sx={{ fontSize: 'lg' }} />}
|
||||
@@ -246,12 +278,29 @@ function AnthropicFileChip(props: {
|
||||
<MenuButton slots={{ root: IconButton }} slotProps={{ root: { variant: 'soft', color: 'primary', size: 'sm', disabled: isBusy && busy !== 'inline' } }}>
|
||||
{(busy === 'delete' || busy === 'inline') ? <CircularProgress size='sm' /> : <MoreVertIcon sx={{ fontSize: 'lg' }} />}
|
||||
</MenuButton>
|
||||
<Menu placement='bottom-end' sx={{ minWidth: 180 }}>
|
||||
<Menu placement='bottom-end' sx={{ minWidth: 220 }}>
|
||||
{/* Inline as doc attachment */}
|
||||
<MenuItem disabled={!canInline || isBusy} onClick={handleInline}>
|
||||
<ListItemDecorator><VerticalAlignBottomIcon /></ListItemDecorator>
|
||||
Inline
|
||||
<div>
|
||||
Embed
|
||||
{!canInline && <Typography level='body-xs' sx={{ opacity: 0.6 }}>
|
||||
File type not supported
|
||||
</Typography>}
|
||||
</div>
|
||||
</MenuItem>
|
||||
{/* Auto-embed toggle - shared global preference */}
|
||||
{!autoEmbedEnabled && <>
|
||||
<MenuItem disabled={!canInline || isBusy} onClick={handleToggleAutoEmbed}>
|
||||
<ListItemDecorator><Checkbox checked={autoEmbedEnabled} readOnly color='neutral' /></ListItemDecorator>
|
||||
<div>
|
||||
Always embed
|
||||
<Typography level='body-xs' sx={{ opacity: 0.6 }}>
|
||||
Change anytime in Settings
|
||||
</Typography>
|
||||
</div>
|
||||
</MenuItem>
|
||||
</>}
|
||||
{!!onFragmentDelete && <ListDivider />}
|
||||
{/* Delete from provider */}
|
||||
{!!onFragmentDelete && (
|
||||
|
||||
@@ -25,6 +25,7 @@ export type GlobalOverlayId = // string - disabled so we keep an orderliness
|
||||
| 'chat-message-delete-confirmation'
|
||||
| 'chat-message-delete-aux'
|
||||
| 'chat-message-delete-hosted-resource'
|
||||
| 'chat-message-auto-embed-notice'
|
||||
| 'chat-message-inline-aux'
|
||||
| 'livefile-overwrite'
|
||||
| 'shortcuts-confirm-close'
|
||||
|
||||
Reference in New Issue
Block a user