{
)
}
+// Wrapper component to safely display potentially large data in CodeViewer
+const TruncatedCodeViewer: React.FC<{
+ value: string
+ label: string
+ language?: string
+}> = ({ value, label, language = 'json' }) => {
+ const { t } = useTranslation()
+ const { content, truncated, isLikelyBase64 } = truncateLargeData(value, t)
+
+ return (
+
+
+ {label}:{truncated && {t('error.truncatedBadge')}}
+
+ {isLikelyBase64 ? (
+ {content}
+ ) : (
+
+ )}
+
+ )
+}
+
const AiSdkError = ({ error }: { error: SerializedAiSdkErrorUnion }) => {
const { t } = useTranslation()
@@ -358,14 +446,7 @@ const AiSdkError = ({ error }: { error: SerializedAiSdkErrorUnion }) => {
)}
{isSerializedAiSdkAPICallError(error) && (
- <>
- {error.responseBody && (
-
- {t('error.responseBody')}:
-
-
- )}
- >
+ <>{error.responseBody && }>
)}
{(isSerializedAiSdkAPICallError(error) || isSerializedAiSdkDownloadError(error)) && (
@@ -394,23 +475,10 @@ const AiSdkError = ({ error }: { error: SerializedAiSdkErrorUnion }) => {
)}
{error.requestBodyValues && (
-
- {t('error.requestBodyValues')}:
-
-
+
)}
- {error.data && (
-
- {t('error.data')}:
-
-
- )}
+ {error.data && }
>
)}
diff --git a/src/renderer/src/utils/__tests__/image.test.ts b/src/renderer/src/utils/__tests__/image.test.ts
index 3f35e7c737..0e02957395 100644
--- a/src/renderer/src/utils/__tests__/image.test.ts
+++ b/src/renderer/src/utils/__tests__/image.test.ts
@@ -7,8 +7,7 @@ import {
captureScrollableAsDataURL,
compressImage,
convertToBase64,
- makeSvgSizeAdaptive,
- parseDataUrlMediaType
+ makeSvgSizeAdaptive
} from '../image'
// mock 依赖
@@ -202,36 +201,4 @@ describe('utils/image', () => {
expect(result.outerHTML).toBe(originalOuterHTML)
})
})
-
- describe('parseDataUrlMediaType', () => {
- it('extracts media type and base64 flag from standard data url', () => {
- const r = parseDataUrlMediaType('data:image/png;base64,AAA')
- expect(r.mediaType).toBe('image/png')
- expect(r.isBase64).toBe(true)
- })
-
- it('handles additional parameters in header', () => {
- const r = parseDataUrlMediaType('data:image/jpeg;name=foo;base64,AAA')
- expect(r.mediaType).toBe('image/jpeg')
- expect(r.isBase64).toBe(true)
- })
-
- it('returns undefined media type when missing and detects non-base64', () => {
- const r = parseDataUrlMediaType('data:text/plain,hello')
- expect(r.mediaType).toBe('text/plain')
- expect(r.isBase64).toBe(false)
- })
-
- it('handles empty mediatype header', () => {
- const r = parseDataUrlMediaType('data:;base64,AAA')
- expect(r.mediaType).toBeUndefined()
- expect(r.isBase64).toBe(true)
- })
-
- it('gracefully handles non data urls', () => {
- const r = parseDataUrlMediaType('https://example.com/x.png')
- expect(r.mediaType).toBeUndefined()
- expect(r.isBase64).toBe(false)
- })
- })
})
diff --git a/src/renderer/src/utils/file.ts b/src/renderer/src/utils/file.ts
index 1d4bf4577c..c1a68ee2eb 100644
--- a/src/renderer/src/utils/file.ts
+++ b/src/renderer/src/utils/file.ts
@@ -1,6 +1,6 @@
import type { FileMetadata } from '@renderer/types'
import { FileTypes } from '@renderer/types'
-import { audioExts, documentExts, imageExts, KB, MB, textExts, videoExts } from '@shared/config/constant'
+import { audioExts, documentExts, GB, imageExts, KB, MB, textExts, videoExts } from '@shared/config/constant'
import mime from 'mime-types'
/**
@@ -46,6 +46,10 @@ export function removeFileExtension(filePath: string): string {
* @returns {string} 格式化后的文件大小字符串
*/
export function formatFileSize(size: number): string {
+ if (size >= GB) {
+ return (size / GB).toFixed(1) + ' GB'
+ }
+
if (size >= MB) {
return (size / MB).toFixed(1) + ' MB'
}
diff --git a/src/renderer/src/utils/image.ts b/src/renderer/src/utils/image.ts
index 6f8d8c3d18..3d4824549a 100644
--- a/src/renderer/src/utils/image.ts
+++ b/src/renderer/src/utils/image.ts
@@ -617,23 +617,3 @@ export const convertImageToPng = async (blob: Blob): Promise => {
img.src = url
})
}
-
-/**
- * Parse media type from a data URL without using heavy regular expressions.
- *
- * data:[][;base64],
- * - mediatype may be empty (defaults to text/plain;charset=US-ASCII per spec)
- * - we only care about extracting media type and whether it's base64
- */
-export function parseDataUrlMediaType(url: string): { mediaType?: string; isBase64: boolean } {
- if (!url.startsWith('data:')) return { isBase64: false }
- const comma = url.indexOf(',')
- if (comma === -1) return { isBase64: false }
- // strip leading 'data:' and take header portion only
- const header = url.slice(5, comma)
- const semi = header.indexOf(';')
- const mediaType = (semi === -1 ? header : header.slice(0, semi)).trim() || undefined
- // base64 flag may appear anywhere after mediatype in the header
- const isBase64 = header.indexOf(';base64') !== -1
- return { mediaType, isBase64 }
-}
diff --git a/vitest.config.ts b/vitest.config.ts
index a245f7a416..e91d014b6b 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -56,6 +56,18 @@ export default defineConfig({
'packages/aiCore/**/__tests__/**/*.{test,spec}.{ts,tsx}'
]
}
+ },
+ // shared 包单元测试配置
+ {
+ extends: true,
+ test: {
+ name: 'shared',
+ environment: 'node',
+ include: [
+ 'packages/shared/**/*.{test,spec}.{ts,tsx}',
+ 'packages/shared/**/__tests__/**/*.{test,spec}.{ts,tsx}'
+ ]
+ }
}
],
// 全局共享配置