@opentiny/genui-sdk-vue 1.3.1-alpha.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -11
- package/dist/ConfigProvider-BzxW9L3f.js +95 -0
- package/dist/ConfigProvider-BzxW9L3f.js.map +1 -0
- package/dist/{GenuiChatWithMaterials.vue_vue_type_script_setup_true_lang-zsZgFWJw.js → GenuiChatWithMaterials.vue_vue_type_script_setup_true_lang-Bdu-r86w.js} +3 -3
- package/dist/{GenuiChatWithMaterials.vue_vue_type_script_setup_true_lang-zsZgFWJw.js.map → GenuiChatWithMaterials.vue_vue_type_script_setup_true_lang-Bdu-r86w.js.map} +1 -1
- package/dist/{injection-tokens-DDgspg4x.js → GenuiRenderer-C2w3WGQa.js} +3497 -3474
- package/dist/GenuiRenderer-C2w3WGQa.js.map +1 -0
- package/dist/{GenuiRendererWithMaterials.vue_vue_type_script_setup_true_lang-CMjFQe5i.js → GenuiRendererWithMaterials.vue_vue_type_script_setup_true_lang-BlhUkAxb.js} +6 -6
- package/dist/GenuiRendererWithMaterials.vue_vue_type_script_setup_true_lang-BlhUkAxb.js.map +1 -0
- package/dist/chat.d.ts +0 -6
- package/dist/chat.js +15 -17
- package/dist/chat.js.map +1 -1
- package/dist/chat.types-BqZOCKBz.js +1794 -0
- package/dist/chat.types-BqZOCKBz.js.map +1 -0
- package/dist/config-provider.d.ts +12 -24
- package/dist/config-provider.js +2 -2
- package/dist/index.d.ts +19 -169
- package/dist/index.js +31 -37
- package/dist/index.js.map +1 -1
- package/dist/injection-tokens-CuDQs1ne.js +114 -0
- package/dist/injection-tokens-CuDQs1ne.js.map +1 -0
- package/dist/legacy-chat.d.ts +1 -9
- package/dist/legacy-chat.js +3 -3
- package/dist/legacy-renderer.d.ts +3 -1
- package/dist/legacy-renderer.js +2 -2
- package/dist/renderer.d.ts +2 -2
- package/dist/renderer.js +1 -1
- package/dist/transform-jsx.d.ts +3 -2
- package/dist/transform-jsx.js +2 -5
- package/dist/transform-jsx.js.map +1 -1
- package/package.json +5 -12
- package/dist/ConfigProvider-B_1dX_dv.js +0 -131
- package/dist/ConfigProvider-B_1dX_dv.js.map +0 -1
- package/dist/GenuiRenderer-f2_6u1TA.js +0 -141
- package/dist/GenuiRenderer-f2_6u1TA.js.map +0 -1
- package/dist/GenuiRendererWithMaterials.vue_vue_type_script_setup_true_lang-CMjFQe5i.js.map +0 -1
- package/dist/chat.types-DEDNSs5o.js +0 -1817
- package/dist/chat.types-DEDNSs5o.js.map +0 -1
- package/dist/code-generator.d.ts +0 -139
- package/dist/code-generator.js +0 -6
- package/dist/code-generator.js.map +0 -1
- package/dist/injection-tokens-DDgspg4x.js.map +0 -1
- package/dist/vue-code-generator-CwPQ3GDh.js +0 -573
- package/dist/vue-code-generator-CwPQ3GDh.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat.types-DEDNSs5o.js","sources":["../src/chat/chat-api.ts","../src/chat/CustomModelProvider.ts","../src/chat/chat-utils.ts","../src/chat/file-upload/file-utils.ts","../src/chat/useFileUpload.ts","../src/chat/renderer/AttachmentsRenderer.vue","../src/chat/renderer/TemplateDataRenderer.vue","../src/chat/renderer/ReasoningRenderer.vue","../src/chat/renderer/ToolRenderer.vue","../src/chat/event-emitter.ts","../src/chat/GeneratingComponent.vue","../src/chat/continue-chat-action.ts","../src/chat/ErrorText.vue","../src/chat/composable/use-resize.ts","../src/chat/tiny-robot-patch/useMessage.ts","../src/chat/tiny-robot-patch/messageManager.ts","../src/chat/tiny-robot-patch/indexedDBStrategy.ts","../src/chat/tiny-robot-patch/useConversation.ts","../src/chat/think-tag-wrap-pattern.ts","../src/chat/response-handler.ts","../src/chat/GenuiChat.vue","../src/chat/chat.types.ts"],"sourcesContent":["import type { ICustomComponentItem, CustomFetch, ICustomActionItem } from './chat.types';\nimport type { IGenPromptComponent, IGenPromptSnippet, IGenPromptExample } from '@opentiny/genui-sdk-core';\nconst removeCustomActionsExecuteFunction = (customActions: ICustomActionItem[]) => {\n return customActions.map((action: ICustomActionItem) => {\n return {\n name: action.name,\n description: action.description,\n parameters: action.parameters,\n return: action.return,\n async: action.async,\n };\n });\n};\n\n// 从 customComponents 中移除 ref 字段,只保留 schema 信息\nconst removeRefFromCustomComponents = (customComponents: ICustomComponentItem[]): IGenPromptComponent[] => {\n return customComponents.map((item) => {\n const { ref, ...rest } = item;\n return rest;\n });\n};\n\nexport const chat = async (\n chatOptions: {\n url: string,\n messages: any,\n model: string,\n temperature: number,\n signal: any,\n customComponents: ICustomComponentItem[],\n customSnippets: IGenPromptSnippet[],\n customExamples: IGenPromptExample[],\n customActions: ICustomActionItem[],\n customFetch?: CustomFetch,\n }\n) => {\n const { url, messages, model, temperature, signal, customComponents, customSnippets, customExamples, customActions, customFetch } = chatOptions;\n const tgCustomConfig = {\n customComponents: removeRefFromCustomComponents(customComponents),\n customSnippets: customSnippets,\n customExamples: customExamples,\n customActions: removeCustomActionsExecuteFunction(customActions),\n };\n\n const requestMetadata = {\n tinygenui: JSON.stringify(tgCustomConfig),\n };\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n signal,\n body: JSON.stringify({\n messages: messages,\n model: model,\n temperature: temperature,\n metadata: requestMetadata,\n }),\n };\n\n // 如果提供了自定义请求函数,使用它;否则使用默认的 fetch\n const requestFn = customFetch || fetch;\n const response = await requestFn(url, options);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP error! status: ${response.status}, details: ${errorText}`);\n }\n return response;\n};\n","import { BaseModelProvider, type ChatCompletionRequest, type ChatCompletionResponse } from '@opentiny/tiny-robot-kit';\nimport { chat } from './chat-api';\nimport type { IChatConfig, ICustomComponentItem, CustomFetch, ICustomActionItem } from './chat.types';\nimport type { IGenPromptSnippet, IGenPromptExample } from '@opentiny/genui-sdk-core';\nimport type { IChatMessage, IStreamData } from '@opentiny/genui-sdk-core';\nimport type { IResponseHandler } from './response-handler';\n\nasync function readChunk(reader: ReadableStreamDefaultReader<Uint8Array>, handler: (data: string) => void) {\n let buffer = '';\n const decoder = new TextDecoder('utf-8');\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n while (true) {\n const lineEnd = buffer.indexOf('\\n');\n if (lineEnd === -1) break;\n const line = buffer.slice(0, lineEnd).trim();\n buffer = buffer.slice(lineEnd + 1);\n if (!line.startsWith('data:')) continue;\n const data = line.slice(5).trim();\n if (data === '[DONE]') break;\n handler(data);\n }\n }\n return true;\n}\n\n/** 与 {@link chat} 入参对齐的选项;由调用方在每次请求前给出当前值(与 props / 状态同步) */\nexport interface ICustomModelChatOptions {\n url: string;\n model: string;\n temperature: number;\n chatConfig: IChatConfig;\n customComponents: ICustomComponentItem[];\n customSnippets: IGenPromptSnippet[];\n customExamples: IGenPromptExample[];\n customActions: ICustomActionItem[];\n customFetch?: CustomFetch;\n}\n\nexport interface ICustomModelProviderOptions {\n getChatOptions: () => ICustomModelChatOptions;\n}\n\nexport class CustomModelProvider extends BaseModelProvider {\n private getChatOptions: () => ICustomModelChatOptions;\n protected responseHandlers: IResponseHandler<IStreamData>[] = [];\n constructor({ getChatOptions }: ICustomModelProviderOptions) {\n super({ provider: 'custom' });\n this.getChatOptions = getChatOptions;\n }\n validateRequest(_: ChatCompletionRequest) { }\n\n setResponseHandlers(handlers: IResponseHandler<IStreamData>[]) {\n this.responseHandlers = handlers;\n }\n\n async getData(request: ChatCompletionRequest) {\n const {\n url,\n model,\n temperature,\n customComponents,\n customSnippets,\n customExamples,\n customActions,\n customFetch,\n } = this.getChatOptions();\n return await chat({\n url,\n messages: request.messages,\n model,\n temperature,\n signal: request.options?.signal,\n customComponents,\n customSnippets,\n customExamples,\n customActions,\n customFetch,\n });\n }\n\n async chat(_: ChatCompletionRequest) {\n return {} as ChatCompletionResponse;\n }\n\n async chatStream(request: any, handler: { onData: any; onDone: any; onError: any }) {\n const { onDone, onData, onError } = handler;\n const context: any = {};\n this.setupStreamContext(context, request);\n\n let response: Response;\n try {\n\n this.handlerBeforeRequest(context);\n\n response = await this.getData(request);\n } catch (error) {\n this.handlerRequestError(context, error)\n onDone({ type: 'error', error });\n return;\n }\n\n const bodyStream = response.body!;\n // const chunkStream = createAsyncIterableStream(getChunkStringStream(bodyStream));\n const reader = bodyStream.getReader();\n\n const signal = request.options?.signal;\n signal?.addEventListener('abort',\n () => {\n reader.cancel();\n this.handlerEnd(context);\n },\n { once: true }\n )\n\n this.handlerStart(context, handler);\n\n await readChunk(reader, (data) => {\n this.handlerChunk(data, context);\n });\n this.handlerEnd(context);\n\n }\n\n protected setupStreamContext(context: Record<string, unknown>, _request: ChatCompletionRequest) {\n const { chatConfig } = this.getChatOptions();\n context.chatConfig = chatConfig;\n }\n\n handlerChunk(rawData: string, context: any) {\n try {\n const streamData = JSON.parse(rawData) as IStreamData;\n\n for (const handler of this.responseHandlers) {\n if (handler.match(streamData, context)) {\n const handled = handler.handler(streamData, context);\n if (handled) break;\n } else if (handler.notMatchHandler) {\n const handled = handler.notMatchHandler(streamData, context);\n if (handled) break;\n }\n }\n } catch (e) {\n console.error(e);\n }\n }\n\n\n handlerBeforeRequest(context: any) {\n for (const handler of this.responseHandlers) {\n if (handler.beforeRequest) {\n handler.beforeRequest(context);\n }\n }\n }\n\n handlerRequestError(context: any, error?: unknown) {\n for (const handler of this.responseHandlers) {\n if (handler.onRequestError) {\n try {\n handler.onRequestError(context, error);\n } catch (error) {\n console.error(`[onRequestError] handler \"${handler.name}\" failed:`, error);\n }\n }\n }\n }\n\n handlerStart(context: any, handlers: { onData: (data: IChatMessage) => void, onDone: () => void, onError: (error: Error) => void }) {\n for (const handler of this.responseHandlers) {\n if (handler.start) {\n handler.start(context, handlers);\n }\n }\n }\n\n handlerEnd(context: any) {\n for (const handler of this.responseHandlers) {\n if (handler.end) {\n handler.end(context);\n }\n }\n }\n\n}\n","import { nextTick, onMounted, onUnmounted, type Ref, ref, h } from 'vue';\nimport type { Component, VNode } from 'vue';\n\nfunction throttle<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let lastTime = 0;\n return function (this: any, ...args: Parameters<T>) {\n const now = Date.now();\n const elapsed = now - lastTime;\n\n // 如果距离上次执行时间超过 delay,立即执行\n if (elapsed >= delay) {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n lastTime = now;\n fn.apply(this, args);\n } else {\n // 否则,清除之前的定时器,设置新的定时器,确保最后一次调用也会执行\n if (timer) {\n clearTimeout(timer);\n }\n const remaining = delay - elapsed;\n timer = setTimeout(() => {\n lastTime = Date.now();\n timer = null;\n fn.apply(this, args);\n }, remaining);\n }\n };\n}\n\nconst scrollEnd = (container: Ref<HTMLElement | undefined>) => {\n const isLastMessageInBottom = ref(false);\n const isScrollByUser = ref(false);\n let scrollByUserTimer: ReturnType<typeof setTimeout> | null = null;\n\n const updateIsLastMessageInBottom = () => {\n if (container.value) {\n isLastMessageInBottom.value =\n container.value.scrollTop + container.value.clientHeight + 130 >= container.value.scrollHeight;\n }\n };\n const scrollToBottom = () => {\n if (container.value) {\n nextTick(() => {\n container.value?.scrollTo({\n top: container.value.scrollHeight,\n behavior: 'smooth',\n });\n });\n }\n };\n\n // 用于切换会话时的滚动,带重试机制,确保在 DOM 完全渲染后滚动到底部\n const scrollToBottomWithRetry = (maxRetries = 10, retryDelay = 150) => {\n if (!container.value) return;\n\n let retryCount = 0;\n let lastScrollHeight = 0;\n let stableCount = 0; // 用于记录 scrollHeight 稳定的次数\n\n const attemptScroll = () => {\n if (!container.value) return;\n\n const currentScrollHeight = container.value.scrollHeight;\n const scrollTop = container.value.scrollTop;\n const clientHeight = container.value.clientHeight;\n const isAtBottom = scrollTop + clientHeight + 10 >= currentScrollHeight;\n\n // 如果 scrollHeight 还在变化,说明内容还在渲染,重置稳定计数\n if (currentScrollHeight !== lastScrollHeight) {\n lastScrollHeight = currentScrollHeight;\n stableCount = 0;\n retryCount = 0; // 重置重试计数,因为内容还在变化\n } else {\n stableCount++;\n }\n\n // 如果已经在底部,不需要滚动\n if (isAtBottom) {\n return;\n }\n\n // 等待 scrollHeight 稳定(连续两次相同)后再滚动,或者已经重试了多次\n if (stableCount >= 2 || retryCount >= 2) {\n scrollToBottom();\n }\n\n // 如果还没到底部且还有重试次数,继续重试\n if (!isAtBottom && retryCount < maxRetries) {\n retryCount++;\n setTimeout(() => {\n requestAnimationFrame(() => {\n attemptScroll();\n });\n }, retryDelay);\n }\n };\n\n setTimeout(() => {\n attemptScroll();\n updateIsLastMessageInBottom();\n }, 50);\n };\n const autoScrollToBottom = () => {\n // 当内容不在底部时,或者用户手动滚动时,不会触发自动滚动\n\n if (!isLastMessageInBottom.value || isScrollByUser.value) {\n return;\n }\n scrollToBottom();\n };\n const handleUserScroll = () => {\n isScrollByUser.value = true;\n if (scrollByUserTimer) {\n clearTimeout(scrollByUserTimer);\n }\n scrollByUserTimer = setTimeout(() => {\n isScrollByUser.value = false;\n scrollByUserTimer = null;\n }, 100);\n };\n\n onMounted(() => {\n updateIsLastMessageInBottom();\n if (container.value) {\n container.value.addEventListener('scroll', updateIsLastMessageInBottom, { passive: true });\n container.value.addEventListener('wheel', handleUserScroll, { passive: true });\n container.value.addEventListener('touchmove', handleUserScroll, { passive: true });\n }\n });\n onUnmounted(() => {\n if (container.value) {\n container.value.removeEventListener('scroll', updateIsLastMessageInBottom);\n container.value.removeEventListener('wheel', handleUserScroll);\n container.value.removeEventListener('touchmove', handleUserScroll);\n }\n });\n\n return {\n scrollToBottom,\n scrollToBottomWithRetry,\n autoScrollToBottom,\n isLastMessageInBottom,\n updateIsLastMessageInBottom,\n };\n};\n\ntype ISlotProps = any;\n\n// 将组件或函数转换为插槽函数\nexport const toSlotFunction = (slot: Component<ISlotProps> | ((props: ISlotProps) => VNode | VNode[]) | undefined) => {\n if (!slot) return undefined;\n // 检查是否是函数形式的插槽(函数插槽通常没有 __name 等组件属性)\n if (typeof slot === 'function' && !('__name' in slot || 'setup' in slot || 'render' in slot)) {\n return slot as (props: ISlotProps) => VNode | VNode[];\n }\n // 如果是组件,转换为插槽函数\n return (props: ISlotProps) => h(slot as Component<ISlotProps>, props);\n};\n\nexport { scrollEnd, throttle };\n","import type { ModelCapability } from '../chat.types';\n\nexport type FileCategory = 'image' | 'document';\n\n/**\n * MIME 类型映射表\n * 将文件扩展名映射到对应的 MIME 类型\n */\nexport const MIME_TYPE_MAP: Record<string, string> = {\n // 图片格式\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n heic: 'image/heic',\n tiff: 'image/tiff',\n // 文档格式\n pdf: 'application/pdf',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n txt: 'text/plain',\n md: 'text/markdown',\n csv: 'text/csv',\n json: 'application/json',\n epub: 'application/epub+zip',\n mobi: 'application/x-mobipocket-ebook',\n} as const;\n\n/**\n * 图片 MIME 类型列表\n */\nexport const IMAGE_MIME_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/bmp',\n 'image/heic',\n 'image/tiff',\n] as const;\n\n/**\n * 验证文件大小\n * @param file 文件对象\n * @param maxSizeMB 最大文件大小(MB)\n * @throws 如果文件超过大小限制\n */\nimport { useI18n } from '../i18n';\n\nexport function validateFileSize(file: FileMeta, maxSizeMB: number): void {\n const { t } = useI18n();\n const maxBytes = maxSizeMB * 1024 * 1024;\n if (file.size > maxBytes) {\n throw new Error(t('fileUpload.error.fileSizeExceeded', {\n maxSizeMB,\n currentSizeMB: (file.size / 1024 / 1024).toFixed(2),\n }));\n }\n}\n\n/**\n * 验证文件是否符合模型要求\n * @param features 模型能力配置\n * @param file 文件对象\n * @returns 验证结果\n */\nexport function validateFileForModel(file: FileMeta, features: ModelCapability): { valid: boolean; error?: string } {\n const { t } = useI18n();\n \n if (!features) {\n return { valid: false, error: t('fileUpload.error.unsupportedModel') };\n }\n\n // 检查文件扩展名\n const extension = file.name.split('.').pop()?.toLowerCase() || '';\n if (!features.supportImage?.supportedFileTypes.includes(extension)) {\n return {\n valid: false,\n error: t('fileUpload.error.unsupportedFormat', { extension }),\n };\n }\n\n // 检查文件大小\n const maxSize = features.supportImage?.maxImageSize || 0;\n const maxBytes = maxSize * 1024 * 1024;\n\n if (file.size > maxBytes) {\n return {\n valid: false,\n error: t('fileUpload.error.sizeLimitExceeded', { maxSize }),\n };\n }\n\n return { valid: true };\n}\n/**\n * 检测文件类别(基于 MIME 类型)\n * @param file 文件对象\n * @returns 文件类别(image 或 document)\n */\nexport function detectFileCategory(type: string): FileCategory {\n return IMAGE_MIME_TYPES.includes(type as any) ? 'image' : 'document';\n}\n\nexport const processFiles = async (files: FileMeta[], features: ModelCapability): Promise<any> => {\n const { t } = useI18n();\n \n // 获取模型能力配置\n if (!features) {\n throw new Error(t('fileUpload.error.unsupportedModel'));\n }\n\n // 检查文件数量限制\n if (features.supportImage?.maxFilesPerRequest && files.length > features.supportImage.maxFilesPerRequest) {\n throw new Error(t('fileUpload.error.maxFilesExceeded', { maxFiles: features.supportImage.maxFilesPerRequest }));\n }\n\n // 统一处理(单个或多个)\n const results = await Promise.all(files.map((file) => processFile(file, features)));\n\n // 合并结果\n return results;\n};\n/**\n * 处理单个文件\n */\nconst processFile = async (file: FileMeta, features: ModelCapability): Promise<any> => {\n const { t } = useI18n();\n const fileCategory = detectFileCategory(file.type);\n\n // 验证文件格式和大小\n const validation = validateFileForModel(file, features);\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n\n const maxSize = features.supportImage?.maxImageSize || 0;\n validateFileSize(file, maxSize);\n\n if (fileCategory === 'image') {\n return {\n type: 'image_url',\n image_url: {\n url: file.base64,\n },\n filename: file.name,\n };\n }\n\n if (fileCategory === 'document') {\n return {\n type: 'file',\n mediaType: file.type,\n data: file.base64,\n filename: file.name,\n };\n }\n\n throw new Error(t('fileUpload.error.unsupportedFileType', { fileCategory }));\n};\n\nexport interface FileMeta {\n name: string;\n type: string;\n size: number;\n lastModified: number;\n base64: string;\n}\n\n/**\n * 浏览器环境:File 序列化(转为 JSON 字符串,含 Base64 数据 + 元数据)\n * @param {File} file - 要序列化的 File 对象\n * @returns {Promise<string>} 序列化后的 JSON 字符串\n */\nexport const serializeFile = (file: File): Promise<FileMeta> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n // 读取 File 为 Base64 字符串\n reader.readAsDataURL(file);\n\n reader.onload = () => {\n // 提取元数据(文件名、MIME 类型、大小、最后修改时间)\n const fileMeta = {\n name: file.name,\n type: file.type,\n size: file.size,\n lastModified: file.lastModified,\n base64: reader.result,\n };\n resolve(fileMeta as FileMeta);\n };\n\n reader.onerror = (err) => reject(err);\n });\n};\n\n/**\n * 浏览器环境:反序列化 JSON 字符串 → File 对象\n * @param {FileMeta} fileMeta - 文件元数据\n * @returns {File} 原始 File 对象\n */\nexport const deserializeFile = (fileMeta: FileMeta): File => {\n const base64WithoutPrefix = fileMeta.base64.split(',')[1];\n const uint8Array = Uint8Array.from(atob(base64WithoutPrefix), (c) => c.charCodeAt(0));\n const blob = new Blob([uint8Array], { type: fileMeta.type });\n\n // 用元数据构造 File 对象(File 构造器:Blob + 文件名 + 可选元数据)\n return new File([blob], fileMeta.name, {\n type: fileMeta.type,\n lastModified: fileMeta.lastModified,\n });\n};\n","import type { UserItem } from '@opentiny/tiny-robot';\nimport { TinyNotify } from '@opentiny/vue';\nimport { ref, type Ref } from 'vue';\nimport { type FileMeta, processFiles, serializeFile } from './file-upload/file-utils';\nimport type { ModelCapability } from './chat.types';\nimport { useI18n } from './i18n';\n\nconst useFileUpload = () => {\n const { t } = useI18n();\n const attachments = ref<FileMeta[]>([]);\n const templateData = ref<UserItem[]>([]);\n\n /**\n * 处理附件并生成消息内容\n * @returns 处理结果,如果失败返回 null\n */\n const processAttachments = async (\n attachments: FileMeta[],\n features: ModelCapability,\n ): Promise<{\n apiContent: any[];\n } | null> => {\n let apiContent: any[] = [];\n if (attachments.length === 0) {\n return { apiContent };\n }\n\n try {\n // 提取原始文件\n apiContent = await processFiles(attachments, features);\n\n return {\n apiContent,\n };\n } catch (error) {\n TinyNotify({\n type: 'error',\n title: t('fileUpload.error.processFailed'),\n message: error instanceof Error ? error.message : t('fileUpload.error.unknownError'),\n position: 'top-right',\n });\n // 不再抛出错误,返回 null 表示处理失败\n return null;\n }\n };\n const clearAttachments = () => {\n attachments.value = [];\n };\n const handleFilesSelected = async (files: File[], inputMessage: string) => {\n if (!files || files.length === 0) {\n return;\n }\n if (!templateData.value.length) {\n templateData.value.unshift({\n type: 'text',\n content: inputMessage,\n });\n }\n\n for (const file of files) {\n templateData.value.push({\n type: 'template',\n content: file.name || '',\n });\n try {\n // 如果附件列表中已经存在相同的文件,则不添加\n if (attachments.value.find((fileMeta) => fileMeta.name === file.name)) {\n continue;\n }\n const fileMeta = await serializeFile(file);\n // 添加到附件列表\n attachments.value.push(fileMeta);\n } catch (error) {\n TinyNotify({\n type: 'error',\n title: t('fileUpload.error.validationFailed'),\n message: error instanceof Error ? error.message : t('fileUpload.error.unknownError'),\n position: 'top-right',\n });\n }\n }\n };\n /**\n * 处理 template 编辑:保持 templateData 和 attachments 同步\n * 删除在 attachments 中找不到对应附件的 template,以及删除没有被任何 template 引用的 attachment\n * @param templateData 当前的 templateData\n * @returns 更新后的 templateData\n */\n const handleTemplateEdit = (templateData: Ref<UserItem[]>, inputMessage: string): UserItem[] => {\n const newValue = templateData.value;\n\n // 收集 attachments 中所有的文件名\n const attachmentFileNames = new Set<string>(\n attachments.value.map((fileMeta) => fileMeta.name).filter((name): name is string => !!name),\n );\n\n // 过滤掉那些 content 在 attachments 中找不到的 template\n const updatedTemplateData = newValue.filter((item) => {\n if (item.type === 'template') {\n // 如果 template 的 content 在 attachments 中找不到,删除这个 template\n const content = (item as any).content;\n return content && attachmentFileNames.has(content);\n }\n return true;\n });\n\n // 收集更新后 templateData 中所有的 template 文件名\n const templateFileNames = new Set<string>(\n updatedTemplateData\n .filter((item) => item.type === 'template' && (item as any).content)\n .map((item) => (item as any).content as string),\n );\n\n // 删除那些没有被任何 template 引用的 attachment\n // 从后往前删除,避免索引变化导致的问题\n for (let i = attachments.value.length - 1; i >= 0; i--) {\n const attachment = attachments.value[i];\n const fileName = attachment.name;\n if (fileName && !templateFileNames.has(fileName)) {\n attachments.value.splice(i, 1);\n }\n }\n\n return updatedTemplateData;\n };\n\n return {\n attachments,\n templateData,\n processAttachments,\n clearAttachments,\n handleFilesSelected,\n handleTemplateEdit,\n };\n};\n\nexport { useFileUpload };\n","<template>\n <div class=\"attachments-renderer\">\n <!-- 图片缩略图 -->\n <div\n v-for=\"(attachment, index) in imageAttachments\"\n :key=\"attachment.name\"\n class=\"image-thumbnail\"\n @click=\"openFullscreen(attachment)\"\n >\n <div class=\"image-wrapper\">\n <img :src=\"attachment.base64\" :alt=\"attachment.name\" />\n </div>\n <!-- 删除按钮 -->\n <button class=\"delete-btn\" @click.stop=\"handleRemove(attachment)\" type=\"button\">\n <IconFileRemove class=\"delete-btn-icon\" />\n </button>\n <!-- Hover 蒙层 -->\n <div class=\"hover-overlay\">\n <span class=\"preview-text\">预览</span>\n </div>\n </div>\n <!-- 非图片文件显示文件名 -->\n <div v-for=\"attachment in nonImageAttachments\" :key=\"attachment.name\" class=\"file-item\">\n <span class=\"file-name\">{{ attachment.name }}</span>\n </div>\n <!-- 全屏预览 -->\n <Transition name=\"fullscreen-fade\">\n <div v-if=\"fullscreenImage\" class=\"fullscreen-overlay\" @click=\"closeFullscreen\">\n <Transition name=\"image-scale\">\n <img\n v-if=\"fullscreenImage\"\n :src=\"fullscreenImage.base64\"\n :alt=\"fullscreenImage.name\"\n />\n </Transition>\n </div>\n </Transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { IconFileRemove } from '@opentiny/tiny-robot-svgs';\n\nimport type { FileMeta } from '../file-upload/file-utils';\nimport { IMAGE_MIME_TYPES } from '../file-upload/file-utils';\nimport { computed, ref } from 'vue';\n\ninterface Props {\n attachments: FileMeta[];\n}\n\ninterface Emits {\n (e: 'remove', attachment: FileMeta | undefined): void;\n}\n\nconst props = defineProps<Props>();\nconst emit = defineEmits<Emits>();\n\nconst fullscreenImage = ref<FileMeta | null>(null);\n\nconst isImage = (fileMeta: FileMeta): boolean => {\n return IMAGE_MIME_TYPES.includes(fileMeta.type as any);\n};\n\nconst imageAttachments = computed(() => {\n return props.attachments.filter((fileMeta) => isImage(fileMeta));\n});\n\nconst nonImageAttachments = computed(() => {\n return props.attachments.filter((fileMeta) => !isImage(fileMeta));\n});\n\nconst handleRemove = (attachment: FileMeta) => {\n // 找到在原数组中的实际索引\n emit('remove', attachment);\n};\n\nconst openFullscreen = (fileMeta: FileMeta) => {\n fullscreenImage.value = fileMeta;\n // 禁止 body 滚动\n document.body.style.overflow = 'hidden';\n};\n\nconst closeFullscreen = () => {\n fullscreenImage.value = null;\n // 恢复 body 滚动\n document.body.style.overflow = '';\n};\n</script>\n\n<style scoped lang=\"less\">\n.attachments-renderer {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.image-thumbnail {\n position: relative;\n width: 50px;\n height: 50px;\n cursor: pointer;\n flex-shrink: 0;\n\n .image-wrapper {\n width: 100%;\n height: 100%;\n border-radius: 6px;\n overflow: hidden;\n position: relative;\n }\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n }\n\n .delete-btn {\n position: absolute;\n top: -8px;\n right: -8px;\n border-radius: 50%;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s;\n padding: 0;\n background-color: transparent;\n .delete-btn-icon {\n width: 14px;\n height: 14px;\n }\n }\n\n .hover-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity 0.2s,\n visibility 0.2s;\n\n .preview-text {\n color: #fff;\n font-size: 12px;\n font-weight: 500;\n }\n }\n\n &:hover .hover-overlay {\n opacity: 1;\n visibility: visible;\n }\n}\n\n.file-item {\n padding: 8px 12px;\n background-color: #f5f5f5;\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n\n .file-name {\n font-size: 14px;\n color: #333;\n word-break: break-all;\n }\n}\n\n.fullscreen-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n cursor: pointer;\n padding: 20px;\n\n img {\n max-width: 90%;\n max-height: 90%;\n object-fit: contain;\n cursor: default;\n border-radius: 8px;\n }\n}\n\n// 全屏蒙层淡入淡出动画\n.fullscreen-fade-enter-active {\n transition: opacity 0.3s ease;\n}\n\n.fullscreen-fade-leave-active {\n transition: opacity 0.25s ease;\n}\n\n.fullscreen-fade-enter-from,\n.fullscreen-fade-leave-to {\n opacity: 0;\n}\n\n// 图片放大动画\n.image-scale-enter-active {\n transition:\n transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),\n opacity 0.4s ease;\n}\n\n.image-scale-leave-active {\n transition:\n transform 0.3s cubic-bezier(0.55, 0.055, 0.675, 0.19),\n opacity 0.3s ease;\n}\n\n.image-scale-enter-from {\n transform: scale(0.2);\n opacity: 0;\n}\n\n.image-scale-leave-to {\n transform: scale(0.9);\n opacity: 0;\n}\n</style>\n","<template>\n <div class=\"template-data-renderer\">\n <template v-for=\"(item, index) in templateData\" :key=\"index\">\n <!-- text 类型:直接渲染文字 -->\n <span v-if=\"item.type === 'text'\" class=\"text-item\">{{ item.content }}</span>\n\n <!-- template 类型:渲染文字,如果是图片则 hover 显示预览 -->\n <span v-else-if=\"item.type === 'template'\" class=\"template-item\">\n <tiny-popover width=\"200\" trigger=\"hover\" :content=\"item.content\" placement=\"top\">\n <template #reference>\n <span class=\"template-text\" @click=\"handleImageClick(item)\">{{ item.content }}</span>\n </template>\n <div v-if=\"isImageTemplate(item)\" class=\"image-preview\">\n <img\n class=\"image-preview-img\"\n :src=\"getImageBase64(item)\"\n :alt=\"item.content\"\n @click=\"handleImageClick(item)\"\n />\n </div>\n </tiny-popover>\n </span>\n </template>\n <!-- 全屏预览 -->\n <Transition name=\"fullscreen-fade\">\n <div v-if=\"fullscreenImage\" class=\"fullscreen-overlay\" @click=\"closeFullscreen\">\n <Transition name=\"image-scale\">\n <img v-if=\"fullscreenImage\" :src=\"fullscreenImage.base64\" :alt=\"fullscreenImage.name\" />\n </Transition>\n </div>\n </Transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { UserItem } from '@opentiny/tiny-robot';\nimport type { FileMeta } from '../file-upload/file-utils';\nimport { IMAGE_MIME_TYPES } from '../file-upload/file-utils';\nimport { ref } from 'vue';\nimport { TinyPopover } from '@opentiny/vue';\n\nexport interface Props {\n templateData?: UserItem[];\n attachments?: FileMeta[];\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n templateData: () => [],\n attachments: () => [],\n});\n\nconst fullscreenImage = ref<FileMeta | null>(null);\n\n// 判断是否为图片类型\nconst isImageTemplate = (item: UserItem): boolean => {\n if (item.type !== 'template' || !item.content) {\n return false;\n }\n\n // 从 attachments 中找到对应的文件\n const attachment = props.attachments.find((fileMeta) => fileMeta.name === item.content);\n\n if (!attachment) {\n return false;\n }\n\n // 判断文件类型是否为图片\n return IMAGE_MIME_TYPES.includes(attachment.type as any);\n};\n\n// 获取图片的 base64 数据\nconst getImageBase64 = (item: UserItem): string => {\n if (item.type !== 'template' || !item.content) {\n return '';\n }\n\n const attachment = props.attachments.find((fileMeta) => fileMeta.name === item.content);\n\n return attachment?.base64 || '';\n};\n\n// 获取对应的 attachment\nconst getAttachment = (item: UserItem): FileMeta | undefined => {\n if (item.type !== 'template' || !item.content) {\n return undefined;\n }\n\n return props.attachments.find((fileMeta) => fileMeta.name === item.content);\n};\n\n// 处理图片点击事件\nconst handleImageClick = (item: UserItem) => {\n const fileMeta = getAttachment(item);\n if (!fileMeta) {\n return;\n }\n openFullscreen(fileMeta);\n};\n\n// 打开全屏预览\nconst openFullscreen = (fileMeta: FileMeta) => {\n fullscreenImage.value = fileMeta;\n // 禁止 body 滚动\n document.body.style.overflow = 'hidden';\n};\n\n// 关闭全屏预览\nconst closeFullscreen = () => {\n fullscreenImage.value = null;\n // 恢复 body 滚动\n document.body.style.overflow = '';\n};\n</script>\n\n<style scoped lang=\"less\">\n.template-data-renderer {\n display: inline;\n word-break: break-word;\n}\n\n.text-item {\n display: inline;\n}\n\n.template-item {\n position: relative;\n display: inline;\n\n .template-text {\n display: inline;\n cursor: pointer;\n color: #1476ff;\n background-color: rgba(20, 118, 255, 0.1);\n padding: 2px 4px;\n border-radius: 4px;\n }\n}\n.image-preview {\n max-width: 200px;\n cursor: pointer;\n .image-preview-img {\n width: 100%;\n height: 100%;\n object-fit: contain;\n }\n}\n\n.fullscreen-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n cursor: pointer;\n padding: 20px;\n\n img {\n max-width: 90%;\n max-height: 90%;\n object-fit: contain;\n cursor: default;\n border-radius: 8px;\n }\n}\n\n// 全屏蒙层淡入淡出动画\n.fullscreen-fade-enter-active {\n transition: opacity 0.3s ease;\n}\n\n.fullscreen-fade-leave-active {\n transition: opacity 0.25s ease;\n}\n\n.fullscreen-fade-enter-from,\n.fullscreen-fade-leave-to {\n opacity: 0;\n}\n\n// 图片放大动画\n.image-scale-enter-active {\n transition:\n transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),\n opacity 0.4s ease;\n}\n\n.image-scale-leave-active {\n transition:\n transform 0.3s cubic-bezier(0.55, 0.055, 0.675, 0.19),\n opacity 0.3s ease;\n}\n\n.image-scale-enter-from {\n transform: scale(0.2);\n opacity: 0;\n}\n\n.image-scale-leave-to {\n transform: scale(0.9);\n opacity: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { IconArrowDown } from '@opentiny/tiny-robot-svgs';\nimport { BubbleMarkdownContentRenderer } from '@opentiny/tiny-robot';\nimport { ref } from 'vue';\nimport { useI18n } from '../i18n';\n\nconst props = defineProps<{\n content: string;\n thinking?: boolean;\n}>();\n\nconst open = ref(false);\nconst { t } = useI18n();\n\nconst handleClick = () => {\n open.value = !open.value;\n};\n\nconst markdownRenderer = new BubbleMarkdownContentRenderer({\n defaultAttrs: { class: 'markdown-content' },\n mdConfig: { html: true },\n});\n\nconst MarkdownContent = (markdownProps: { content: string }) =>\n markdownRenderer.render({ content: markdownProps.content });\n</script>\n\n<template>\n <div class=\"tr-bubble__reasoning\" data-type=\"reasoning\">\n <div class=\"header\" @click=\"handleClick\">\n <div class=\"icon-and-text\" :class=\"{ thinking: props.thinking }\">\n <svg\n class=\"thinking-icon\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <path\n d=\"M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z\"\n />\n <path\n d=\"M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z\"\n />\n </svg>\n <span class=\"title\">{{ props.thinking ? t('reasoning.thinking') : t('reasoning.thinkingEnd') }}</span>\n </div>\n <IconArrowDown class=\"expand-icon\" :class=\"{ '-rotate-90': !open }\" />\n </div>\n <div v-show=\"open\" class=\"detail\">\n <div class=\"side-border\">\n <div class=\"dot-wrapper\">\n <div class=\"dot\"></div>\n </div>\n <div class=\"border-line\"></div>\n </div>\n <MarkdownContent :content=\"props.content\" class=\"detail-content\" />\n </div>\n </div>\n</template>\n\n<style lang=\"less\" scoped>\n.tr-bubble__reasoning:not(:last-child) {\n margin-top: 8px;\n}\n\n.header {\n font-size: 16px;\n line-height: 1.5;\n color: var(--tr-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n\n &:hover {\n color: var(--tr-text-primary);\n fill: var(--tr-text-primary);\n }\n\n .icon-and-text {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .expand-icon.-rotate-90 {\n transform: rotate(-90deg);\n }\n}\n\n@keyframes thinking-pulse {\n 20% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n 80% {\n opacity: 1;\n }\n}\n\n.thinking {\n animation: thinking-pulse 1.5s infinite linear;\n}\n\n.detail {\n color: var(--tr-text-secondary);\n margin-block: 8px;\n display: flex;\n gap: 8px;\n align-items: center;\n font-size: 14px;\n\n .detail-content {\n max-height: 300px;\n overflow-y: auto;\n > *:first-child {\n margin-top: 0;\n }\n > *:last-child {\n margin-bottom: 0;\n }\n }\n\n .side-border {\n width: 16px;\n flex-shrink: 0;\n align-self: stretch;\n display: flex;\n flex-direction: column;\n align-items: center;\n\n .dot-wrapper {\n width: 4px;\n height: 16px;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .dot {\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background-color: var(--tr-text-primary);\n }\n\n .border-line {\n flex: 1;\n width: 1.5px;\n background-color: #c2c2c2;\n border-radius: 1px;\n }\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { IconArrowDown, IconCancelled, IconError, IconLoading, IconPlugin } from '@opentiny/tiny-robot-svgs';\nimport { computed, ref, useCssModule, type Component } from 'vue';\nimport { useI18n } from '../i18n';\n\nconst MAX_HIGHLIGHT_JSON_FIELD_COUNT = 100;\n\n/**\n * 判断 JSON 对象的字段总数是否超过指定阈值(含嵌套 object 的 key 与 array 内 object 的 key)。\n * 超过阈值时提前终止递归,避免对大 payload 做全量遍历。\n *\n * @param value - 待统计的值\n * @param limit - 字段数上限\n * @returns 字段总数是否超过 limit\n */\nconst exceedsFieldCountLimit = (value: unknown, limit: number): boolean => {\n let count = 0;\n\n const traverse = (val: unknown): boolean => {\n if (!val || typeof val !== 'object') {\n return false;\n }\n\n if (Array.isArray(val)) {\n for (const item of val) {\n if (traverse(item)) {\n return true;\n }\n }\n return false;\n }\n\n for (const item of Object.values(val)) {\n count += 1;\n if (count > limit) {\n return true;\n }\n if (traverse(item)) {\n return true;\n }\n }\n return false;\n };\n\n return traverse(value);\n};\n\n/**\n * 转义 HTML 特殊字符,防止 v-html 注入 XSS。\n *\n * @param text - 待转义的文本\n * @returns 转义后的安全 HTML 文本\n */\nconst escapeHtml = (text: string): string =>\n text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n\nconst props = defineProps<{\n name: string;\n status: 'running' | 'success' | 'failed' | 'cancelled';\n content?: string | { params?: object; result?: object; [x: string]: unknown };\n formatPretty?: boolean;\n defaultOpen?: boolean;\n}>();\nconst { t } = useI18n();\nconst opened = ref(props.defaultOpen ?? false);\n\nconst textAndIconMap = new Map<string, { text: string; icon: Component }>([\n ['running', { text: t('toolStatus.running'), icon: IconLoading }],\n ['success', { text: t('toolStatus.success'), icon: IconPlugin }],\n ['failed', { text: t('toolStatus.failed'), icon: IconError }],\n ['cancelled', { text: t('toolStatus.cancelled'), icon: IconCancelled }],\n]);\n\nconst textAndIcon = computed(() => {\n return textAndIconMap.get(props.status) || { text: '', icon: IconPlugin };\n});\n\nconst classes = useCssModule();\n\nconst highlightJSON = <T extends string | object>(json?: T): string => {\n if (!json) {\n return '';\n }\n\n let prettyJson = '';\n let parsedValue: unknown = json;\n const space = props.formatPretty ? 2 : 0;\n\n try {\n if (typeof json === 'string') {\n parsedValue = JSON.parse(json);\n prettyJson = JSON.stringify(parsedValue, null, space);\n } else {\n parsedValue = json;\n prettyJson = JSON.stringify(json, null, space);\n }\n } catch (error) {\n console.warn(error);\n }\n\n const shouldSkipHighlight = exceedsFieldCountLimit(parsedValue, MAX_HIGHLIGHT_JSON_FIELD_COUNT);\n\n if (shouldSkipHighlight) {\n return escapeHtml(prettyJson);\n }\n\n prettyJson = prettyJson.replace(\n /(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)/g,\n (match) => {\n let className = 'number';\n if (/^\"/.test(match)) {\n className = /:$/.test(match) ? 'key' : 'string';\n } else if (/true|false/.test(match)) {\n className = 'boolean';\n } else if (/null/.test(match)) {\n className = 'null';\n }\n return `<span class=\"${classes[className]}\">${escapeHtml(match)}</span>`;\n },\n );\n\n return prettyJson;\n};\n</script>\n\n<template>\n <div class=\"tr-bubble__step-tool\">\n <div class=\"tr-bubble__step-tool-header\">\n <div class=\"tr-bubble__step-tool-left\">\n <component :is=\"textAndIcon.icon\" class=\"tr-bubble__step-tool-icon\" :class=\"`icon-${props.status}`\" />\n <span class=\"tr-bubble__step-tool-title\">\n {{ textAndIcon.text }}\n <span class=\"tr-bubble__step-tool-name\">{{ props.name }}</span>\n </span>\n </div>\n <div class=\"tr-bubble__step-tool-expand\">\n <IconArrowDown class=\"expand-icon\" :class=\"{ '-rotate-90': !opened }\" @click=\"opened = !opened\" />\n </div>\n </div>\n <div class=\"tr-bubble__step-tool-params\" v-if=\"opened\">\n <hr class=\"tr-bubble__step-tool-hr\" />\n <div class=\"tr-bubble__step-tool-params-content\" v-html=\"highlightJSON(props.content)\"></div>\n </div>\n </div>\n</template>\n\n<style lang=\"less\" scoped>\n.tr-bubble__step-tool {\n font-size: 14px;\n line-height: 24px;\n padding: 12px;\n color: var(--tr-text-secondary);\n background-color: var(--tr-container-bg-default-2);\n border-radius: 12px;\n\n .tr-bubble__step-tool-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n\n .tr-bubble__step-tool-left {\n display: flex;\n align-items: center;\n gap: 8px;\n\n .tr-bubble__step-tool-icon {\n font-size: 20px;\n flex-shrink: 0;\n\n &.icon-running {\n color: #898989;\n animation: spin 1s linear infinite;\n }\n\n &.icon-success {\n color: #898989;\n }\n\n &.icon-failed,\n &.icon-cancelled {\n color: var(--tr-color-error);\n }\n }\n\n .tr-bubble__step-tool-title {\n word-break: break-word;\n }\n\n .tr-bubble__step-tool-name {\n color: var(--tr-text-primary);\n font-weight: 600;\n }\n }\n\n .tr-bubble__step-tool-expand {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n flex-shrink: 0;\n\n .expand-icon {\n font-size: 16px;\n\n &.-rotate-90 {\n transform: rotate(-90deg);\n }\n }\n }\n\n .tr-bubble__step-tool-hr {\n margin: 12px 0;\n color: rgb(219, 219, 219);\n }\n\n .tr-bubble__step-tool-params-content {\n white-space: pre-wrap;\n word-break: break-word;\n font-family: monospace;\n max-height: 300px;\n overflow-y: auto;\n }\n}\n</style>\n\n<style module>\n.key {\n color: var(--tr-bubble-tool-key-color);\n}\n\n.number {\n color: var(--tr-bubble-tool-number-color);\n}\n\n.string {\n color: var(--tr-bubble-tool-string-color);\n}\n\n.boolean {\n color: var(--tr-bubble-tool-boolean-color);\n}\n\n.null {\n color: var(--tr-bubble-tool-null-color);\n}\n</style>\n","export class EventEmitter {\n private events: Record<string, { callback: Function; once: boolean }[]> = {};\n constructor() {\n this.events = Object.create(null);\n }\n\n /**\n * @param {string} eventName - 事件名\n * @param {Function} callback - 回调函数\n * @param {boolean} [once=false] - 是否只触发一次\n */\n on(eventName: string, callback: Function, once = false) {\n if (typeof callback !== 'function') {\n throw new TypeError('回调必须是函数');\n }\n if (!this.events[eventName]) {\n this.events[eventName] = [];\n }\n\n this.events[eventName].push({ callback, once });\n }\n\n /**\n * @param {string} eventName - 事件名\n * @param {Function} callback - 要移除的回调(必须是注册时的同一个函数引用)\n */\n off(eventName: string, callback: Function) {\n if (!this.events[eventName]) return;\n this.events[eventName] = this.events[eventName].filter((item) => item.callback !== callback);\n if (this.events[eventName].length === 0) {\n delete this.events[eventName];\n }\n }\n\n /**\n * @param {string} eventName - 事件名\n * @param {...any} args - 传递给回调的参数\n */\n emit(eventName: string, ...args: any[]) {\n if (!this.events[eventName]) return;\n const callbacks = [...this.events[eventName]];\n\n callbacks.forEach((item, index) => {\n const { callback, once } = item;\n callback.apply(this, args);\n\n if (once) {\n this.events[eventName].splice(index, 1);\n }\n });\n\n if (this.events[eventName].length === 0) {\n delete this.events[eventName];\n }\n }\n\n /**\n * @param {string} eventName - 事件名\n * @param {Function} callback - 回调函数\n */\n once(eventName: string, callback: Function) {\n this.on(eventName, callback, true);\n }\n}\nconst emitter = new EventEmitter();\nexport { emitter };\n","<script lang=\"ts\" setup>\nimport { ref, onMounted, onBeforeUnmount } from 'vue';\nimport type { INotificationPayload } from '@opentiny/genui-sdk-core';\nimport type { IThinkComponentProps } from './chat.types';\nimport { useI18n } from './i18n'; //TODO: replace with package name\n\nconst props = defineProps<IThinkComponentProps>();\n\nconst { t } = useI18n();\n\nconst loadingText = ref(t('loading.response'));\n\nconst hasSchemaCard = ref(false);\n\nconst toolStatusTextMap = new Map<string, { textKey: string }>([\n ['running', { textKey: 'toolStatus.running' }],\n ['success', { textKey: 'toolStatus.success' }],\n ['failed', { textKey: 'toolStatus.failed' }],\n ['cancelled', { textKey: 'toolStatus.cancelled' }],\n]);\n\nconst handleNotification = (payload: INotificationPayload) => {\n if (payload.type === 'done') {\n loadingText.value = '';\n return;\n }\n\n if (payload.type === 'schema-card') {\n loadingText.value = t('loading.generatingCard');\n return;\n }\n\n if (props.showThinkingResult) {\n loadingText.value = t('loading.response');\n return;\n }\n\n if (payload.type === 'tool') {\n const { toolCallData } = payload;\n const textKey = toolStatusTextMap.get(toolCallData.status)?.textKey || 'loading.response';\n loadingText.value = `${t(textKey)} ${toolCallData.name}...`;\n return;\n }\n\n // type === 'markdown'\n const lastMessage = payload.chatMessage.messages[payload.chatMessage.messages.length - 1];\n if (lastMessage) {\n if (!hasSchemaCard.value) {\n hasSchemaCard.value = payload.chatMessage.messages?.some((item: any) => item.type.startsWith('schema-card'));\n }\n loadingText.value = hasSchemaCard.value ? `${lastMessage.content}...` : t('loading.response');\n }\n};\n\nonMounted(() => {\n props.emitter.on('notification', handleNotification);\n});\n\nonBeforeUnmount(() => {\n props.emitter.off('notification', handleNotification);\n});\n</script>\n\n<template>\n <div v-if=\"loadingText\" class=\"loading-wrapper\">\n <div class=\"loading-container\" type=\"loading-text\">{{ loadingText }}</div>\n </div>\n</template>\n<style scoped lang=\"less\">\n.loading-wrapper {\n width: fit-content;\n max-width: 100%;\n overflow: hidden;\n width: 100%;\n min-height: 45px;\n position: relative;\n}\n.loading-container[type='loading-text'] {\n position: absolute;\n right: 0;\n min-width: 100%;\n margin: 10px 0;\n color: #666;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: inline-block;\n}\n\n@supports ((background-clip: text)) {\n .loading-container[type='loading-text'] {\n background: linear-gradient(90deg, #666 0%, #666 45%, #999 50%, #999 55%, #666 60%, #666 100%);\n background-size: 200% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n animation: text-shimmer 6s linear infinite;\n }\n}\n\n@keyframes text-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n</style>\n","import { useI18n } from './i18n';\n\nexport function useChatAction({\n chat,\n saveState,\n}: {\n chat: (_: { llmFriendlyMessage: string; humanFriendlyMessage: string; context: Record<string, any> }) => void,\n saveState: (context: Record<string | symbol, any>) => void,\n}) {\n const { t } = useI18n();\n \n return {\n continueChatAction: {\n name: 'continueChat',\n description: t('continueChat.description'),\n execute: (params: { message: string }, context: Record<string, any>) => {\n chat({\n llmFriendlyMessage: `${params.message},${t('continueChat.messageParam')}${JSON.stringify(context.state || {})}`,\n humanFriendlyMessage: params.message,\n context,\n });\n },\n parameters: {\n type: 'object' as const,\n properties: {\n message: {\n type: 'string',\n description: t('continueChat.paramDescription'),\n },\n },\n },\n },\n saveStateAction: {\n name: 'saveState',\n description: t('saveState.description'),\n execute: (params: any, context: Record<string | symbol, any>) => {\n saveState(context);\n },\n parameters: { type: 'null' as const},\n },\n };\n}\n","<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { iconChevronRight, iconOperationfaild } from '@opentiny/vue-icon';\nimport { useI18n } from './i18n';\n\nconst IconRight = iconChevronRight();\nconst IconError = iconOperationfaild();\n\nconst props = defineProps<{\n content: string;\n}>();\n\nconst { t } = useI18n();\n\nconst expanded = ref(false);\n\nconst toggleExpand = () => {\n expanded.value = !expanded.value;\n};\n</script>\n\n<template>\n <div class=\"tg-playground-error-card\">\n <div class=\"card-header\" @click=\"toggleExpand\">\n <IconError class=\"icon-error\" />\n <span class=\"card-title\">{{ t('error.title') }}</span>\n <IconRight class=\"icon-right\" :class=\"{ expanded }\" />\n </div>\n\n <pre class=\"card-body\" :class=\"{ collapsed: !expanded }\">\n {{ content }}\n </pre>\n </div>\n</template>\n\n<style scoped lang=\"less\">\n.tg-playground-error-card {\n margin: 8px 0;\n padding: 16px 24px;\n border-radius: 24px;\n background-color: var(--tv-color-error-bg-light);\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n font-size: var(--tr-bubble-text-font-size);\n line-height: var(--tr-bubble-text-line-height);\n overflow: hidden;\n color: var(--tr-text-primary);\n}\n\n.card-header {\n display: flex;\n position: relative;\n align-items: center;\n // color: var(--tv-base-color-error-5);\n font-weight: 500;\n gap: 8px;\n}\n\n.icon-error {\n width: 18px;\n height: 18px;\n fill: var(--tv-color-error-icon);\n transform: translateY(-1px);\n}\n\n.icon-right {\n width: 16px;\n height: 16px;\n position: absolute;\n fill: var(--tr-text-primary);;\n right: 0;\n top: 50%;\n transform: translateY(-50%) rotate(0deg);\n cursor: pointer;\n transition: transform 0.2s ease-out;\n}\n\n.icon-right.expanded {\n transform: translateY(-50%) rotate(90deg);\n}\n\n.card-title {\n white-space: nowrap;\n}\n\n.card-body {\n margin: 0;\n margin-top: 8px;\n background-color: var(--tr-bubble-content-bg);\n padding: 8px 10px;\n border-radius: 6px;\n max-height: 60vh;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-all;\n}\n\n.card-body.collapsed {\n height: 0;\n padding: 0;\n margin-top: 0;\n overflow: hidden;\n}\n</style>\n","import { onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport type { Ref } from 'vue';\n\nexport interface IElementSize {\n width: number;\n height: number;\n}\n\nexport function useResize(targetRef: Ref<HTMLElement | undefined>) {\n const width = ref(0);\n const height = ref(0);\n\n let resizeObserver: ResizeObserver | null = null;\n let frameId: number | null = null;\n\n const updateSize = (element: HTMLElement | undefined) => {\n if (!element) {\n width.value = 0;\n height.value = 0;\n return;\n }\n const rect = element.getBoundingClientRect();\n width.value = rect.width;\n height.value = rect.height;\n };\n\n const scheduleUpdate = (element: HTMLElement) => {\n if (frameId !== null) {\n cancelAnimationFrame(frameId);\n }\n frameId = requestAnimationFrame(() => {\n updateSize(element);\n frameId = null;\n });\n };\n\n const cleanupObserver = () => {\n if (resizeObserver && targetRef.value) {\n resizeObserver.unobserve(targetRef.value);\n }\n resizeObserver = null;\n if (frameId !== null) {\n cancelAnimationFrame(frameId);\n frameId = null;\n }\n };\n\n onMounted(() => {\n if (typeof ResizeObserver === 'undefined' || !targetRef.value) {\n return;\n }\n\n resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n const target = entry.target as HTMLElement;\n\n scheduleUpdate(target);\n });\n resizeObserver.observe(targetRef.value);\n updateSize(targetRef.value);\n });\n\n\n onBeforeUnmount(() => {\n cleanupObserver();\n });\n\n return {\n width,\n height\n };\n}\n\n","/**\n * useMessage composable\n * 提供消息管理和状态控制功能\n */\n\nimport { reactive, type Reactive, ref, toRaw, type Ref } from 'vue';\nimport {\n GeneratingStatus,\n STATUS,\n type AIClient,\n type ChatCompletionResponse,\n type ChatCompletionStreamResponse,\n type ChatMessage,\n type MessageState,\n} from '@opentiny/tiny-robot-kit';\n\n/**\n * useMessage选项接口\n */\nexport interface UseMessageOptions {\n /** AI客户端实例 */\n client: AIClient;\n /** 消息ID */\n conversationId: string;\n /** 是否默认使用流式响应 */\n useStreamByDefault?: boolean;\n /** 错误消息模板 */\n errorMessage?: string;\n /** 初始消息列表 */\n initialMessages?: ChatMessage[];\n events?: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onReceiveData?: <T = any>(data: T, messages: Ref<ChatMessage[]>, preventDefault: () => void) => void;\n onFinish?: (\n finishReason: string | undefined,\n context: { messages: Ref<ChatMessage[]>; messageState: Reactive<MessageState> },\n preventDefault: () => void,\n ) => void;\n };\n}\n\n/**\n * useMessage返回值接口\n */\nexport interface UseMessageReturn {\n /** 消息ID */\n conversationId: string;\n /** 消息列表 */\n messages: Ref<ChatMessage[]>;\n /** 消息状态 */\n messageState: Reactive<MessageState>;\n /** 输入消息 */\n inputMessage: Ref<string>;\n /** 是否使用流式响应 */\n useStream: Ref<boolean>;\n /** 发送消息 */\n sendMessage: (content?: ChatMessage['content'], clearInput?: boolean) => Promise<void>;\n /** 手动执行addMessage添加消息后,可以执行send发送消息 */\n send: () => Promise<void>;\n /** 清空消息 */\n clearMessages: () => void;\n /** 添加消息 */\n addMessage: (message: ChatMessage | ChatMessage[]) => void;\n /** 中止请求 */\n abortRequest: () => void;\n /** 重试请求 */\n retryRequest: (msgIndex: number) => Promise<void>;\n}\n\n/**\n * useMessage composable\n * 提供消息管理和状态控制功能\n *\n * @param options useMessage选项\n * @returns UseMessageReturn\n */\nimport { useI18n } from '../i18n';\n\nexport function useMessage(options: UseMessageOptions): UseMessageReturn {\n const { t } = useI18n();\n const { client, useStreamByDefault = true, errorMessage = t('message.requestFailed'), initialMessages = [] } = options;\n\n // 消息列表\n const messages = ref<ChatMessage[]>([...initialMessages]);\n\n // 输入消息\n const inputMessage = ref('');\n\n // 是否使用流式响应\n const useStream = ref(useStreamByDefault);\n\n // 请求控制器\n let abortController: AbortController | null = null;\n\n // 消息状态\n const messageState = reactive<MessageState>({\n status: STATUS.INIT,\n errorMsg: null,\n });\n\n const chatOnReceiveData = (data: ChatCompletionResponse) => {\n const onReceiveData = options.events?.onReceiveData;\n let defaultPrevented = false;\n if (onReceiveData) {\n onReceiveData(data, messages, () => {\n defaultPrevented = true;\n });\n }\n\n if (!defaultPrevented) {\n const assistantMessage: ChatMessage = {\n role: 'assistant',\n content: data.choices[0].message.content,\n };\n messages.value.push(assistantMessage);\n }\n };\n\n // 普通请求\n const chat = async (abortController: AbortController) => {\n const response = await client.chat({\n messages: toRaw(messages.value),\n options: {\n stream: false,\n signal: abortController.signal,\n },\n });\n\n chatOnReceiveData(response);\n };\n\n const streamChatOnReceiveData = (data: ChatCompletionStreamResponse) => {\n const onReceiveData = options.events?.onReceiveData;\n let defaultPrevented = false;\n if (onReceiveData) {\n onReceiveData(data, messages, () => {\n defaultPrevented = true;\n });\n }\n\n if (!defaultPrevented) {\n if (messages.value[messages.value.length - 1].role === 'user') {\n messages.value.push({ role: 'assistant', content: '' });\n }\n const choice = data.choices?.[0];\n if (choice && choice.delta.content) {\n messages.value[messages.value.length - 1].content += choice.delta.content;\n }\n }\n };\n\n // 流式请求\n const streamChat = async (abortController: AbortController) => {\n await client.chatStream(\n {\n messages: toRaw(messages.value),\n options: {\n stream: true,\n signal: abortController.signal,\n },\n },\n {\n onData: (data) => {\n messageState.status = STATUS.STREAMING;\n\n streamChatOnReceiveData(data);\n },\n onError: (error) => {\n messageState.status = STATUS.ERROR;\n messageState.errorMsg = errorMessage;\n console.error('Stream request error:', error);\n },\n onDone: (finishReason) => {\n const onFinish = options.events?.onFinish;\n\n let defaultPrevented = false;\n if (onFinish) {\n onFinish(finishReason, { messages, messageState }, () => {\n defaultPrevented = true;\n });\n }\n\n if (!defaultPrevented) {\n if (finishReason === 'aborted' || messageState.status === STATUS.ABORTED) {\n return;\n }\n messageState.status = STATUS.FINISHED;\n }\n },\n },\n );\n };\n\n const chatRequest = async () => {\n // 更新状态\n messageState.status = STATUS.PROCESSING;\n messageState.errorMsg = null;\n\n // 创建中止控制器\n abortController = new AbortController();\n\n try {\n if (useStream.value) {\n await streamChat(abortController);\n } else {\n await chat(abortController);\n }\n } catch (error) {\n messageState.errorMsg = errorMessage;\n messageState.status = STATUS.ERROR;\n console.error('Send message error:', error);\n } finally {\n abortController = null;\n }\n };\n\n // 发送消息\n const sendMessage = async (content: ChatMessage['content'] = inputMessage.value, clearInput: boolean = true) => {\n if (GeneratingStatus.includes(messageState.status)) {\n return;\n }\n\n if (!content) {\n return;\n }\n\n if (typeof content === 'string' && !content.trim()) {\n return;\n }\n\n if (Array.isArray(content) && content.length === 0) {\n return;\n }\n\n const userMessage: ChatMessage = {\n role: 'user',\n content,\n };\n messages.value.push(userMessage);\n if (clearInput) {\n inputMessage.value = '';\n }\n\n await chatRequest();\n };\n\n const send = async () => {\n if (GeneratingStatus.includes(messageState.status)) {\n return;\n }\n\n await chatRequest();\n };\n\n // 中止请求\n const abortRequest = () => {\n if (abortController) {\n abortController.abort();\n abortController = null;\n messageState.status = STATUS.ABORTED;\n }\n };\n\n // 重试请求\n const retryRequest = async (msgIndex: number) => {\n if (msgIndex === 0 || !messages.value[msgIndex] || messages.value[msgIndex].role === 'user') {\n return;\n }\n messages.value.splice(msgIndex);\n await chatRequest();\n };\n\n //清空消息\n const clearMessages = () => {\n messages.value = [];\n messageState.errorMsg = null;\n };\n\n // 添加消息\n const addMessage = (message: ChatMessage | ChatMessage[]) => {\n if (Array.isArray(message)) {\n messages.value.push(...message);\n } else {\n messages.value.push(message);\n }\n };\n\n return {\n conversationId: options.conversationId,\n messages,\n messageState,\n inputMessage,\n useStream,\n sendMessage,\n send,\n clearMessages,\n addMessage,\n abortRequest,\n retryRequest,\n };\n}\n","import { type Reactive } from 'vue';\nimport type { ConversationState, Conversation } from '@opentiny/tiny-robot-kit';\nimport { useMessage, type UseMessageOptions, type UseMessageReturn } from './useMessage';\n\nexport class MessageManager {\n messageManagerMap: Map<string, UseMessageReturn> = new Map();\n conversationState: Reactive<ConversationState>;\n options: UseMessageOptions;\n constructor(conversationState: Reactive<ConversationState>, options: UseMessageOptions) {\n this.messageManagerMap = new Map();\n this.conversationState = conversationState;\n this.options = options;\n }\n\n getMessageManager(conversationId: string): UseMessageReturn {\n const messageManager = this.messageManagerMap.get(conversationId);\n if (messageManager) {\n return messageManager;\n }\n const conversation = this.conversationState.conversations.find(\n (conversation: Conversation) => conversation.id === conversationId,\n );\n if (!conversation) {\n throw new Error(`Conversation not found for id: ${conversationId}`);\n }\n\n return this.setMessageManager(conversationId);\n }\n setMessageManager(id: string, options?: UseMessageOptions): UseMessageReturn {\n if (this.messageManagerMap.has(id)) {\n return this.messageManagerMap.get(id)!;\n }\n\n const newMessageManager = useMessage(options ?? { ...this.options, conversationId: id });\n this.messageManagerMap.set(id, newMessageManager);\n return newMessageManager;\n }\n \n deleteMessageManager(id: string) {\n this.messageManagerMap.delete(id);\n }\n}\n","import { isRef, isReactive, toRaw, unref } from \"vue\";\nimport { type ConversationStorageStrategy, type Conversation } from \"@opentiny/tiny-robot-kit\";\n\n// 去除响应式\nconst deepUnwrap = (obj: any): any => {\n if (isRef(obj)) return deepUnwrap(unref(obj));\n if (isReactive(obj)) return deepUnwrap(toRaw(obj));\n if (Array.isArray(obj)) return obj.map(deepUnwrap);\n if (obj && typeof obj === 'object') {\n return Object.keys(obj).reduce((acc: any, key: string) => {\n acc[key] = deepUnwrap(obj[key]);\n return acc;\n }, {});\n }\n return obj;\n};\n\n\nexport class IndexedDBStrategy implements ConversationStorageStrategy {\n private dbName: string;\n private storeName: string;\n private dataKey: string;\n private db: IDBDatabase | null = null;\n\n constructor(\n dbName: string = 'genui-ai',\n storeName: string = 'conversations',\n dataKey: string = 'conversations-list',\n ) {\n this.dbName = dbName;\n this.storeName = storeName;\n this.dataKey = dataKey;\n }\n\n private async openDB(): Promise<IDBDatabase> {\n if (this.db) {\n return this.db;\n }\n\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => {\n reject(new Error('打开 IndexedDB 失败'));\n };\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve(this.db);\n };\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n });\n }\n\n async saveConversations(conversations: Conversation[]): Promise<void> {\n try {\n const db = await this.openDB();\n const transaction = db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const serializedData = deepUnwrap(conversations);\n return new Promise<void>((resolve, reject) => {\n const putRequest = store.put(serializedData, this.dataKey);\n putRequest.onsuccess = () => resolve();\n putRequest.onerror = () => {\n console.error('保存会话失败:', putRequest.error);\n reject(putRequest.error);\n };\n });\n } catch (error) {\n console.error('保存会话失败:', error);\n }\n }\n\n async loadConversations(): Promise<Conversation[]> {\n try {\n const db = await this.openDB();\n const transaction = db.transaction([this.storeName], 'readonly');\n const store = transaction.objectStore(this.storeName);\n\n return new Promise<Conversation[]>((resolve, reject) => {\n const request = store.get(this.dataKey);\n request.onsuccess = () => {\n const result = request.result;\n if (!result) {\n resolve([]);\n return;\n }\n let conversations: Conversation[] = [];\n // 如果存储的是字符串,需要反序列化\n if (typeof result === 'string') {\n try {\n conversations = JSON.parse(result);\n } catch (parseError) {\n console.error('解析会话数据失败:', parseError);\n resolve([]);\n return;\n }\n } else {\n // 兼容旧数据格式(如果之前直接存储了对象)\n conversations = Array.isArray(result) ? result : [];\n }\n resolve(conversations);\n };\n request.onerror = () => {\n console.error('加载会话失败:', request.error);\n reject(request.error);\n };\n });\n } catch (error) {\n console.error('加载会话失败:', error);\n return [];\n }\n }\n}\n","/**\n * useConversation composable\n * 提供会话管理和持久化功能\n */\n\nimport { computed, reactive, watch, type ComputedRef } from 'vue';\nimport type { ChatMessage, ConversationState, Conversation, UseConversationOptions } from '@opentiny/tiny-robot-kit';\nimport { MessageManager } from './messageManager';\nimport { useMessage, type UseMessageReturn } from './useMessage';\nimport { IndexedDBStrategy } from './indexedDBStrategy';\nimport { useI18n } from '../i18n';\n\n/**\n * useConversation返回值接口\n */\nexport interface UseConversationReturn {\n /** 会话状态 */\n state: ConversationState;\n /** 消息管理 */\n messageManager: ComputedRef<UseMessageReturn>;\n /** 创建新会话 */\n createConversation: (title?: string, metadata?: Record<string, unknown>) => string;\n /** 切换会话 */\n switchConversation: (id: string) => void;\n /** 删除会话 */\n deleteConversation: (id: string) => void;\n /** 更新会话标题 */\n updateTitle: (id: string, title: string) => void;\n /** 更新会话元数据 */\n updateMetadata: (id: string, metadata: Record<string, unknown>) => void;\n /** 保存会话 */\n saveConversations: () => Promise<void>;\n /** 加载会话 */\n loadConversations: () => Promise<void>;\n /** 生成会话标题 */\n generateTitle: (id: string) => Promise<string>;\n /** 获取当前会话 */\n getCurrentConversation: () => Conversation | null;\n}\n\n/**\n * 生成唯一ID\n */\nfunction generateId(): string {\n return Date.now().toString(36) + Math.random().toString(36).substring(2, 9);\n}\n\n/**\n * useConversation composable\n * 提供会话管理和持久化功能\n *\n * @param options useConversation选项\n * @returns UseConversationReturn\n */\nexport function useConversation(options: UseConversationOptions): UseConversationReturn {\n const { t } = useI18n();\n const {\n client,\n storage = new IndexedDBStrategy(),\n autoSave = true,\n allowEmpty = false,\n useStreamByDefault = true,\n errorMessage: errorMessageOption,\n events,\n } = options;\n \n const errorMessage = errorMessageOption || t('message.requestFailed');\n\n // 会话状态\n const state = reactive<ConversationState>({\n conversations: [],\n currentId: null,\n loading: false,\n });\n\n // 标记是否已经触发过 onLoaded 回调\n let hasTriggeredOnLoaded = false;\n\n const messageManager = new MessageManager(state, {\n client,\n useStreamByDefault,\n conversationId: '',\n errorMessage,\n initialMessages: [],\n events: {\n onReceiveData: events?.onReceiveData,\n onFinish: events?.onFinish,\n },\n });\n\n const currentMessageManager = computed<UseMessageReturn>(() => {\n if (state.currentId) {\n return messageManager.getMessageManager(state.currentId);\n }\n return useMessage({\n client,\n useStreamByDefault,\n conversationId: '',\n errorMessage,\n initialMessages: [],\n events: {\n onReceiveData: events?.onReceiveData,\n onFinish: events?.onFinish,\n },\n });\n });\n watch(\n () => currentMessageManager.value,\n () => {\n messageManager.messageManagerMap.forEach((messageManager) => {\n const messages = messageManager.messages.value;\n if (state.currentId && messages.length > 0) {\n const index = state.conversations.findIndex((row: Conversation) => row.id === messageManager.conversationId);\n if (index !== -1) {\n state.conversations[index].messages = [...messages];\n state.conversations[index].updatedAt = Date.now();\n if (autoSave) {\n saveConversations();\n }\n }\n }\n });\n },\n { deep: true },\n );\n\n /**\n * 创建新会话\n */\n const createConversation = (title?: string, metadata: Record<string, unknown> = {}): string => {\n const defaultTitle = title || t('conversation.newConversation');\n // 空会话则不再创建新会话\n if (!allowEmpty && currentMessageManager.value.messages.value.length === 0 && state.currentId) {\n return state.currentId;\n }\n\n const id = generateId();\n const newConversation: Conversation = {\n id,\n title: defaultTitle,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n messages: [],\n metadata,\n };\n\n state.conversations.unshift(newConversation);\n messageManager.setMessageManager(id, { ...options, conversationId: id });\n switchConversation(id);\n\n if (autoSave) {\n saveConversations();\n }\n\n return id;\n };\n\n /**\n * 切换会话\n */\n const switchConversation = (id: string): void => {\n const conversation = state.conversations.find((conv: Conversation) => conv.id === id);\n if (conversation) {\n state.currentId = id;\n messageManager.setMessageManager(id, { ...options, initialMessages: conversation.messages, conversationId: id });\n }\n };\n\n /**\n * 删除会话\n */\n const deleteConversation = (id: string): void => {\n const index = state.conversations.findIndex((conv: Conversation) => conv.id === id);\n if (index !== -1) {\n messageManager.deleteMessageManager(id);\n state.conversations.splice(index, 1);\n\n // 如果删除的是当前会话,切换到第一个会话或清空\n if (state.currentId === id) {\n if (state.conversations.length > 0) {\n switchConversation(state.conversations[0].id);\n } else {\n state.currentId = null;\n }\n }\n\n if (autoSave) {\n saveConversations();\n }\n }\n };\n\n /**\n * 更新会话标题\n */\n const updateTitle = (id: string, title: string): void => {\n const conversation = state.conversations.find((conv: Conversation) => conv.id === id);\n if (conversation) {\n conversation.title = title;\n conversation.updatedAt = Date.now();\n\n if (autoSave) {\n saveConversations();\n }\n }\n };\n\n /**\n * 更新会话元数据\n */\n const updateMetadata = (id: string, metadata: Record<string, unknown>): void => {\n const conversation = state.conversations.find((conv: Conversation) => conv.id === id);\n if (conversation) {\n conversation.metadata = { ...conversation.metadata, ...metadata };\n conversation.updatedAt = Date.now();\n\n if (autoSave) {\n saveConversations();\n }\n }\n };\n\n /**\n * 保存会话\n */\n const saveConversations = async (): Promise<void> => {\n try {\n await storage.saveConversations(state.conversations);\n } catch (error) {\n console.error('保存会话失败:', error);\n }\n };\n\n /**\n * 加载会话\n */\n const loadConversations = async (): Promise<void> => {\n state.loading = true;\n try {\n const conversations = await storage.loadConversations();\n state.conversations = conversations;\n\n // 如果有会话,默认选中第一个\n if (conversations.length > 0 && !state.currentId) {\n switchConversation(conversations[0].id);\n }\n\n // 仅在第一次加载完成后触发 onLoaded 回调\n if (!hasTriggeredOnLoaded && events?.onLoaded) {\n hasTriggeredOnLoaded = true;\n events.onLoaded(conversations);\n }\n } catch (error) {\n console.error('加载会话失败:', error);\n } finally {\n state.loading = false;\n }\n };\n\n /**\n * 生成会话标题\n * 基于会话内容自动生成标题\n */\n const generateTitle = async (id: string): Promise<string> => {\n const conversation = state.conversations.find((conv: Conversation) => conv.id === id);\n if (!conversation || conversation.messages.length < 2) {\n return conversation?.title || t('conversation.newConversation');\n }\n\n try {\n // 构建生成标题的提示\n const prompt: ChatMessage = {\n role: 'system',\n content:\n '请根据以下对话内容,生成一个简短的标题(不超过20个字符)。只需要返回标题文本,不需要任何解释或额外内容。',\n };\n\n // 获取前几条消息用于生成标题\n const contextMessages = conversation.messages.slice(0, Math.min(4, conversation.messages.length));\n\n const response = await client.chat({\n messages: [prompt, ...contextMessages],\n options: {\n stream: false,\n max_tokens: 30,\n },\n });\n\n const title = response.choices[0].message.content.trim();\n updateTitle(id, title);\n return title;\n } catch (error) {\n console.error('生成标题失败:', error);\n return conversation.title;\n }\n };\n\n /**\n * 获取当前会话\n */\n const getCurrentConversation = (): Conversation | null => {\n if (!state.currentId) return null;\n return state.conversations.find((conv: Conversation) => conv.id === state.currentId) || null;\n };\n\n // 初始加载会话\n loadConversations();\n\n return {\n state,\n messageManager: currentMessageManager,\n createConversation,\n switchConversation,\n deleteConversation,\n updateTitle,\n updateMetadata,\n saveConversations,\n loadConversations,\n generateTitle,\n getCurrentConversation,\n };\n}\n","import { getPartialStartRegString } from '@opentiny/genui-sdk-core';\n\nexport class ThinkTagWrapPattern {\n protected thinkStartFlag: string = '<think>';\n protected thinkEndFlag: string = '</think>';\n protected startRegex: RegExp = new RegExp(`${this.thinkStartFlag}`);\n protected endRegex: RegExp = new RegExp(`${this.thinkEndFlag}`);\n protected partialStartRegex: RegExp = new RegExp(`${getPartialStartRegString(this.thinkStartFlag)}$`);\n protected partialEndRegex: RegExp = new RegExp(`${getPartialStartRegString(this.thinkEndFlag)}$`);\n\n get regExpMap() {\n return {\n start: {\n full: this.startRegex,\n partial: this.partialStartRegex,\n },\n end: {\n full: this.endRegex,\n partial: this.partialEndRegex,\n },\n };\n }\n}\n","import { IChatMessage, IMessageItem, IStreamDelta, IStreamData, PatternExtractor } from '@opentiny/genui-sdk-core';\nimport { ThinkTagWrapPattern } from './think-tag-wrap-pattern';\nimport { reactive, readonly, watch } from 'vue';\nimport { v4 as uuidv4 } from 'uuid';\nimport { emitter } from './event-emitter';\nimport { useI18n } from './i18n';\n\nexport interface IResponseHandler<T> {\n name: string;\n match: (data: T, context: any) => boolean;\n handler: (data: T, context: any) => boolean;\n notMatchHandler?: (data: T, context: any) => boolean;\n beforeRequest?: (context: any) => void;\n onRequestError?: (context: any, error?: unknown) => void;\n start?: (\n context: any,\n handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },\n ) => void;\n end?: (context: any) => void;\n}\n\nconst getStreamDelta = (data: IStreamData): IStreamDelta => {\n return data.choices?.[0]?.delta ?? {};\n};\n\nfunction onToolResult(\n toolCallsResult: any[],\n delta: IStreamDelta,\n toolCallIdMap: Record<string, IMessageItem & { type: 'tool' }>,\n chatMessage: IChatMessage,\n addToolCallContext: boolean,\n) {\n const {\n id,\n function: { arguments: args, result },\n } = toolCallsResult[0];\n const toolCallItem = toolCallIdMap[id];\n if (toolCallItem) {\n toolCallItem.status = 'success';\n toolCallItem.content = JSON.stringify({ arguments: args, result }, null, 2);\n\n emitter.emit('notification', {\n type: 'tool',\n delta,\n toolCallData: readonly(toolCallItem),\n chatMessage: readonly(chatMessage),\n });\n\n if (addToolCallContext) {\n const { t } = useI18n();\n chatMessage.content +=\n t('toolCall.context', {\n toolName: toolCallItem.name,\n toolParams: JSON.stringify(args),\n toolResult: JSON.stringify(result),\n }) + '\\n\\n';\n }\n }\n}\n\nfunction onToolCall(\n toolCalls: any[],\n delta: IStreamDelta,\n toolCallIdMap: Record<string, IMessageItem & { type: 'tool' }>,\n chatMessage: IChatMessage,\n toolCallStatus: { inProcessToolCallId: string | null },\n) {\n toolCalls.forEach((toolCall) => {\n const {\n id,\n function: { name, arguments: argsDelta },\n } = toolCall;\n\n let toolCallItem: IMessageItem & { type: 'tool' };\n // 有id的就是首次工具调用返回\n if (id) {\n toolCallStatus.inProcessToolCallId = id;\n toolCallItem = reactive({\n type: 'tool',\n name: name,\n formatPretty: true,\n status: 'running',\n content: JSON.stringify({ arguments: argsDelta || '' }, null, 2),\n id,\n });\n toolCallIdMap[id] = toolCallItem;\n chatMessage.messages.push(toolCallItem);\n } else {\n toolCallItem = toolCallIdMap[toolCallStatus.inProcessToolCallId];\n const prevArgs = JSON.parse(toolCallItem.content).arguments;\n const nextArgs = prevArgs + (argsDelta || '');\n\n toolCallItem.content = JSON.stringify({ arguments: nextArgs }, null, 2);\n }\n\n emitter.emit('notification', {\n type: 'tool',\n delta,\n toolCallData: readonly(toolCallItem),\n chatMessage: readonly(chatMessage),\n });\n });\n}\n\nfunction onReasoningContent(reasoningContent: string, delta: IStreamDelta, chatMessage: IChatMessage) {\n const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];\n let reasoningMessage = lastMessage;\n if (reasoningMessage?.type === 'reasoning') {\n reasoningMessage.content += reasoningContent;\n } else {\n reasoningMessage = {\n type: 'reasoning',\n content: reasoningContent,\n thinking: true,\n };\n chatMessage.messages.push(reasoningMessage);\n }\n emitNotification(delta, chatMessage);\n return reasoningMessage;\n}\n\nfunction onReasoningEnd(reasoningMessage: IMessageItem) {\n if (reasoningMessage?.type === 'reasoning') reasoningMessage.thinking = false;\n}\n\nfunction emitNotification(delta: IStreamDelta, chatMessage: IChatMessage) {\n const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];\n if (lastMessage) {\n emitter.emit('notification', {\n type: lastMessage.type as 'markdown' | 'schema-card',\n delta,\n chatMessage: readonly(chatMessage),\n });\n }\n}\n\nfunction onMarkdown(content: string, delta: IStreamDelta, chatMessage: IChatMessage) {\n if (chatMessage.messages.length > 0 && chatMessage.messages[chatMessage.messages.length - 1].type === 'markdown') {\n chatMessage.messages[chatMessage.messages.length - 1].content += content;\n } else {\n chatMessage.messages.push({\n type: 'markdown',\n content: content,\n });\n }\n emitNotification(delta, chatMessage);\n}\n\nfunction onSchemaJSON(content: string, delta: IStreamDelta, chatMessage: IChatMessage) {\n if (chatMessage.messages.length > 0 && chatMessage.messages[chatMessage.messages.length - 1].type === 'schema-card') {\n chatMessage.messages[chatMessage.messages.length - 1].content += content;\n } else {\n chatMessage.messages.push({\n type: 'schema-card',\n content: content,\n id: uuidv4(),\n });\n }\n emitNotification(delta, chatMessage);\n}\n\nfunction watchReasoningEnd(context: any) {\n context.unWatchReasoning = watch(\n () => [...context.chatMessage.messages],\n (newVal) => {\n if (context.handleReasoning && newVal[newVal.length - 1]?.type !== 'reasoning') {\n context.handleReasoning = false;\n onReasoningEnd(context.reasoningMessage);\n context.unWatchReasoning?.();\n }\n },\n { flush: 'sync' },\n );\n}\n\nexport const defaultResponseHandlers: IResponseHandler<IStreamData>[] = [\n {\n name: 'init',\n match: (data: IStreamData, context: any) => false,\n handler: (data: IStreamData, context: any) => false,\n start: (\n context: any,\n handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },\n ) => {\n const chatMessage = reactive<IChatMessage>({\n role: 'assistant',\n content: '',\n messages: [],\n });\n context.chatMessage = chatMessage;\n context.handlers = handlers;\n handlers.onData(chatMessage);\n return false;\n },\n end: (context: any) => {\n context.handlers.onDone();\n emitter.emit('notification', {\n type: 'done',\n delta: {},\n chatMessage: readonly(context.chatMessage),\n });\n },\n },\n {\n name: 'finish-info',\n match: (data: IStreamData, context: any) => {\n const { choices, usage } = data;\n return choices?.[0]?.finish_reason && Boolean(usage);\n },\n handler: (data: IStreamData, context: any) => {\n context.chatMessage.finishInfo = data;\n return true;\n },\n },\n {\n name: 'reasoning',\n match: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n return Boolean(delta.reasoning_content);\n },\n handler: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n context.reasoningMessage = onReasoningContent(delta.reasoning_content, delta, context.chatMessage);\n if (!context.handleReasoning) {\n watchReasoningEnd(context);\n context.handleReasoning = true;\n }\n return true;\n },\n start: (\n context: any,\n handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },\n ) => {\n context.handleReasoning = false;\n },\n end: (context: any) => {\n context.unWatchReasoning?.();\n if (context.handleReasoning) {\n context.handleReasoning = false;\n onReasoningEnd(context.reasoningMessage);\n }\n },\n },\n {\n name: 'toolCall',\n match: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n return delta.tool_calls?.length > 0;\n },\n handler: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n onToolCall(delta.tool_calls, delta, context.toolCallIdMap, context.chatMessage, context.toolCallStatus);\n return true;\n },\n start: (\n context: any,\n handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },\n ) => {\n context.toolCallIdMap = {};\n context.toolCallStatus = { inProcessToolCallId: null };\n },\n },\n {\n name: 'toolResult',\n match: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n return delta.tool_calls_result?.length > 0;\n },\n handler: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n onToolResult(\n delta.tool_calls_result,\n delta,\n context.toolCallIdMap,\n context.chatMessage,\n context.chatConfig.addToolCallContext,\n );\n return true;\n },\n },\n {\n name: 'content',\n match: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n return Boolean(delta.content);\n },\n handler: (data: IStreamData, context: any) => {\n const delta = getStreamDelta(data);\n context.delta = delta;\n context.patternExtractor.handleContent(delta.content);\n context.chatMessage.content += delta.content;\n return true;\n },\n start: (\n context: any,\n handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },\n ) => {\n const thinkPatternExtractor = new PatternExtractor({\n onNormalWrite: (value) => onMarkdown(value, context.delta, context.chatMessage),\n onHandledWrite: (value) => {\n context.reasoningMessage = onReasoningContent(value, context.delta, context.chatMessage);\n if (!context.handleReasoning) {\n watchReasoningEnd(context);\n context.handleReasoning = true;\n }\n },\n regExpMap: new ThinkTagWrapPattern().regExpMap,\n });\n context.patternExtractor = new PatternExtractor({\n onNormalWrite: (value) => thinkPatternExtractor.handleContent(value),\n onHandledWrite: (value) => onSchemaJSON(value, context.delta, context.chatMessage),\n });\n },\n },\n];\n","<script setup lang=\"ts\">\nimport '@opentiny/tiny-robot/dist/style.css';\nimport { TrBubbleList, TrSender, TrBubbleProvider, BubbleMarkdownContentRenderer } from '@opentiny/tiny-robot';\nimport { AIClient, GeneratingStatus, STATUS, type ChatMessage } from '@opentiny/tiny-robot-kit';\nimport { IconAi, IconUser, IconArrowDown } from '@opentiny/tiny-robot-svgs';\nimport type {\n BubbleRoleConfig,\n BubbleCommonProps,\n BubbleContentItem,\n UserItem,\n UserTextItem,\n} from '@opentiny/tiny-robot';\nimport { ref, watch, computed, h, inject } from 'vue';\nimport type { Ref, Component } from 'vue';\nimport { CustomModelProvider } from './CustomModelProvider';\nimport { scrollEnd, throttle, toSlotFunction } from './chat-utils';\nimport { useFileUpload } from './useFileUpload';\nimport AttachmentsRenderer from './renderer/AttachmentsRenderer.vue';\nimport TemplateDataRenderer from './renderer/TemplateDataRenderer.vue'; \nimport ReasoningRenderer from './renderer/ReasoningRenderer.vue';\nimport ToolRenderer from './renderer/ToolRenderer.vue';\nimport { type FileMeta, MIME_TYPE_MAP } from './file-upload/file-utils';\nimport { cardIdSymbol } from './useChat';\nimport { emitter } from './event-emitter';\nimport type { IChatProps, ICustomActionItem, IRolesConfig } from './chat.types';\nimport GeneratingComponent from './GeneratingComponent.vue';\nimport { useChatAction } from './continue-chat-action';\nimport type { IMessageItem, IStreamData } from '@opentiny/genui-sdk-core';\nimport type { IRendererProps } from '../renderer';\nimport { GenuiRenderer } from '../renderer';\nimport ErrorText from './ErrorText.vue';\nimport { useResize } from './composable/use-resize';\nimport { useConversation } from './tiny-robot-patch/useConversation';\nimport { useI18n } from './i18n';\nimport { GENUI_CONFIG } from '../config-provider/injection-tokens';\nimport { IResponseHandler, defaultResponseHandlers } from './response-handler';\n\nconst props = defineProps<IChatProps>();\n\nconst genuiConfig = inject(GENUI_CONFIG, null);\nconst { t } = useI18n();\n\nconst isAllowFiles = computed(() => {\n const supportImage = props.features?.supportImage;\n\n if (supportImage && supportImage?.enabled !== false) {\n return true;\n }\n return false;\n});\nconst buttonGroup = computed(() => {\n const fileTypes = props.features?.supportImage?.supportedFileTypes;\n const accept = fileTypes?.map((type: string) => MIME_TYPE_MAP[type.toLowerCase()]).join(',');\n return {\n file: {\n disabled: false,\n accept,\n },\n };\n});\n\n// 定义角色图标以及样式\nconst defaultRoles: { user: BubbleRoleConfig; assistant: BubbleRoleConfig } = {\n assistant: {\n placement: 'start',\n avatar: h(IconAi, { style: { fontSize: '32px' } }),\n maxWidth: '100%',\n customContentField: 'messages',\n },\n user: {\n placement: 'end',\n maxWidth: '90%',\n avatar: h(IconUser, { style: { fontSize: '32px' } }),\n customContentField: 'messages',\n },\n};\n\nconst wrapSlots = (slots: any) => {\n if (!slots) {\n return;\n }\n const newSlots: Record<string, any> = {};\n Object.keys(slots).forEach((key) => {\n newSlots[key] = (props: any) => {\n const isFinished = computed(() => {\n if (props.bubbleProps.role !== 'assistant') {\n return true;\n }\n return props.index !== messageManager.value.messages.value.length - 1 || !generating.value;\n });\n const slotFn = toSlotFunction(slots[key]);\n if (slotFn) {\n return slotFn({\n ...props,\n isFinished: isFinished.value,\n messageManager: messageManager.value,\n chatMessage: messageManager.value.messages.value[props.index],\n });\n }\n return null;\n };\n });\n return newSlots;\n};\n\nconst roles = computed(() => {\n const mergedRoles = { ...defaultRoles };\n for (const keyAny in props.roles) {\n const key = keyAny as keyof IRolesConfig;\n mergedRoles[key] = {\n ...defaultRoles[key],\n ...props.roles[key],\n slots: wrapSlots(props.roles[key]?.slots),\n };\n }\n\n return mergedRoles;\n});\n\nconst flatAllMessages = (messages: ChatMessage[]) =>\n messages\n .filter((item) => item.role === 'assistant')\n .reduce((acc: IMessageItem[], chatItem) => {\n const itemMessages = (chatItem as { messages?: IMessageItem[] }).messages;\n if (Array.isArray(itemMessages)) {\n return acc.concat(...itemMessages);\n }\n return acc;\n }, []);\n\nconst getCardMessage = (cardId: string) => {\n const flatMessages = flatAllMessages(messages.value);\n return flatMessages.find((message: IMessageItem) => 'id' in message && message.id === cardId);\n};\n\nconst saveState = (context: Record<string | symbol, any>) => {\n const cardId = context[cardIdSymbol];\n const cardMessage = getCardMessage(cardId);\n if (cardMessage) {\n (cardMessage as any).state = JSON.parse(JSON.stringify(context.state || {}));\n }\n saveConversations();\n};\n\nconst chat = ({ llmFriendlyMessage, humanFriendlyMessage, context }: any) => {\n saveState(context);\n messageManager.value.addMessage({\n role: 'user',\n content: llmFriendlyMessage,\n messages: [{ type: 'text', content: humanFriendlyMessage }],\n });\n messageManager.value.send();\n};\n\nconst { continueChatAction, saveStateAction } = useChatAction({chat, saveState}); //TODO: Refactor\n\n\nconst generating = computed(() => GeneratingStatus.includes(messageManager.value.messageState.status));\n\nconst markdownRenderer = new BubbleMarkdownContentRenderer({\n defaultAttrs: { class: 'markdown-content' },\n mdConfig: { html: true },\n});\n\nconst lastSchemaCardId = computed(() => {\n const lastChatMessage = messages.value[messages.value.length - 1];\n if (lastChatMessage?.role !== 'assistant') {\n return null;\n }\n const items = lastChatMessage?.messages;\n if (!Array.isArray(items) || !items?.length) {\n return null;\n }\n return items[items.length - 1].id;\n});\n\nconst customComponentsMap = computed(() => {\n const map: Record<string, Component> = {};\n props.customComponents?.forEach((item) => {\n if (item.ref && item.component) {\n map[item.component] = item.ref;\n }\n });\n return map;\n});\n\nconst customActionsMap = computed(() => {\n const map: Record<string, ICustomActionItem> = {};\n props.customActions?.forEach((action) => {\n if (action.name) {\n map[action.name] = action;\n }\n });\n return map;\n});\n\nconst messageRenderers = {\n 'custom-text': (props: BubbleCommonProps & { content: string }) =>\n h('span', { class: 'tr-bubble__body-text' }, props.content),\n 'schema-card': (schemaCardProps: IRendererProps) => {\n const isGenerating = lastSchemaCardId.value === schemaCardProps.id && generating.value;\n\n return h(\n 'div',\n {},\n h(\n GenuiRenderer,\n {\n ...schemaCardProps,\n requiredCompleteFieldSelectors: props.requiredCompleteFieldSelectors || [],\n generating: isGenerating,\n customComponents: customComponentsMap.value,\n customActions: {\n ...customActionsMap.value,\n continueChat: continueChatAction,\n saveState: saveStateAction,\n },\n key: schemaCardProps.id,\n },\n {\n header: toSlotFunction(props.rendererSlots?.header),\n footer: toSlotFunction(props.rendererSlots?.footer),\n },\n ),\n );\n },\n tool: ToolRenderer,\n reasoning: ReasoningRenderer,\n markdown: markdownRenderer,\n templateData: TemplateDataRenderer,\n 'loading-text': props.thinkComponent || GeneratingComponent,\n 'error-text': ErrorText,\n};\n\nconst responseHandlers: Ref<IResponseHandler<IStreamData>[]> = ref(defaultResponseHandlers);\n\nconst customModelProvider = new CustomModelProvider({\n getChatOptions: () => ({\n url: props.url,\n model: props.model || '',\n temperature: props.temperature ?? 0.3,\n chatConfig: props.chatConfig || { addToolCallContext: false, showThinkingResult: false },\n customComponents: props.customComponents || [],\n customSnippets: props.customSnippets || [],\n customExamples: props.customExamples || [],\n customActions: [...(props.customActions || []), continueChatAction, saveStateAction],\n customFetch: props.customFetch,\n }),\n});\ncustomModelProvider.setResponseHandlers(responseHandlers.value);\n\nconst client = new AIClient({\n provider: 'custom',\n providerImplementation: customModelProvider,\n});\n\nlet conversation = useConversation({\n client,\n autoSave: false,\n events: {\n onReceiveData(data, messages, preventDefault) {\n messages.value.push(data as any);\n preventDefault();\n },\n onLoaded(conversations) {\n if (!conversations.length) {\n createConversation();\n saveConversations();\n }\n\n // 如果通过 props.messages 传入了初始消息,则在会话加载完成后覆盖当前会话的消息\n if (props.messages?.length) {\n const currentMessages = messageManager.value.messages.value;\n currentMessages.splice(0, currentMessages.length, ...(props.messages as any));\n }\n },\n onFinish(data: any, context) {\n if (data?.type === 'error') {\n context.messages.value.push({\n role: 'assistant',\n content: '',\n messages: [{ type: 'error-text', content: data.error.message }],\n });\n }\n saveConversations();\n },\n },\n});\nconst { messageManager, createConversation, updateTitle, state: conversationState, saveConversations } = conversation;\n\nconst messages = computed(() => messageManager.value.messages.value);\n\nconst inputMessage = computed({\n get: () => messageManager.value.inputMessage.value,\n set: (v: string) => {\n messageManager.value.inputMessage.value = v;\n },\n});\n\nconst setInputMessage = (message: string) => {\n inputMessage.value = message;\n};\n\nif (props.messages?.length) {\n messages.value.splice(0, messages.value.length, ...(props.messages as any));\n}\n\nconst { attachments, templateData, clearAttachments, processAttachments, handleFilesSelected, handleTemplateEdit } =\n useFileUpload();\n\nconst handleTemplateDataUpdate = (value: UserItem[]) => {\n // 使用 handleTemplateEdit 处理 template 编辑,保持 templateData 和 attachments 同步\n const updatedTemplateData = handleTemplateEdit(templateData, inputMessage.value);\n inputMessage.value = '';\n templateData.value = updatedTemplateData;\n};\nconst showMessages = computed(() => {\n let showMessages = messages.value;\n\n if (messageManager.value.messageState.status === STATUS.PROCESSING) {\n return [\n ...showMessages,\n {\n role: 'assistant',\n content: t('loading.thinking'),\n loading: true,\n },\n ];\n }\n\n const lastMessage = messages.value[messages.value.length - 1];\n\n // 在流式返回过程中,为最后一条助手消息添加 loading-text 组件\n if (generating.value && lastMessage?.role === 'assistant') {\n const existingMessages = Array.isArray((lastMessage as any)?.messages) ? (lastMessage as any).messages : [];\n // 检查是否已经存在 loading-text,避免重复添加\n const hasLoadingText = existingMessages.some((msg: any) => msg.type === 'loading-text');\n\n if (!hasLoadingText) {\n return [\n ...showMessages.slice(0, -1),\n {\n ...lastMessage,\n messages: [\n ...existingMessages,\n {\n type: 'loading-text',\n emitter: emitter,\n message: lastMessage,\n showThinkingResult: props.chatConfig?.showThinkingResult,\n },\n ],\n },\n ];\n }\n }\n return showMessages;\n});\nconst setConversationTitle = (messageContent: string) => {\n const currentTitle = conversationState.conversations.find(\n (conversation) => conversation.id === conversationState.currentId,\n )?.title;\n const DEFAULT_TITLE = t('conversation.newConversation');\n if (currentTitle === DEFAULT_TITLE && conversationState.currentId) {\n const contentStr = typeof messageContent === 'string' ? messageContent : JSON.stringify(messageContent);\n updateTitle(conversationState.currentId, contentStr.substring(0, 20));\n }\n};\nconst clearInputMessage = () => {\n inputMessage.value = '';\n templateData.value = [];\n clearAttachments();\n};\n\nconst handleRemoveAttachment = (item: FileMeta | undefined) => {\n if (!item) return;\n attachments.value = attachments.value.filter((attachment) => item.name !== attachment.name);\n templateData.value = templateData.value.filter((data) => data.type !== 'template' || data.content !== item.name);\n};\n\nconst handleSendMessage = async (ipt: string) => {\n const messageContent = ipt;\n const userMessageContent: BubbleContentItem[] = [];\n let apiContent: any[] = [];\n const attachmentsValue = attachments.value.slice();\n const templateDataValue = templateData.value.slice();\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: messageContent,\n };\n messages.value.push(userMessage);\n\n if (attachmentsValue.length > 0) {\n const result = await processAttachments(attachmentsValue, props.features || {});\n if (!result) {\n messageManager.value.send();\n scrollToBottom();\n return;\n }\n apiContent = templateDataValue.map((templateItem: UserItem) => {\n if (templateItem.type === 'template') {\n return result.apiContent.find((att: any) => att.filename === templateItem.content);\n } else {\n return {\n type: 'text',\n text: (templateItem as UserTextItem).content,\n };\n }\n });\n\n // 添加 templateData 类型的消息项,用于渲染\n if (templateDataValue.length > 0) {\n userMessageContent.push({\n type: 'templateData',\n templateData: templateDataValue,\n attachments: attachmentsValue,\n });\n }\n\n userMessage.content = apiContent;\n userMessage.messages = userMessageContent;\n }\n\n messageManager.value.send();\n clearInputMessage();\n setConversationTitle(messageContent);\n saveConversations();\n scrollToBottom();\n};\n\nconst handleNewConversation = () => {\n createConversation();\n saveConversations();\n};\n\nconst abortRequest = () => {\n messageManager.value.abortRequest();\n saveConversations();\n};\n\nconst messagesContainer: Ref<HTMLElement | undefined> = ref();\nconst { width: messagesContainerWidth } = useResize(messagesContainer);\nconst { scrollToBottom, scrollToBottomWithRetry, autoScrollToBottom, isLastMessageInBottom } =\n scrollEnd(messagesContainer);\n// 使用节流包装 scrollToBottom,延迟 400ms\nconst throttledScrollToBottom = throttle(autoScrollToBottom, 400);\n\n// 最新消息滚动到底部\nwatch(() => messages.value, throttledScrollToBottom, { deep: true });\nwatch(\n () => conversationState.currentId,\n () => {\n // 切换会话, 使用带重试机制的滚动函数,确保在 DOM 完全渲染后滚动到底部\n scrollToBottomWithRetry(10, 150);\n },\n);\n\ndefineExpose({\n setInputMessage,\n handleNewConversation,\n // @experimental\n getProps: (): IChatProps => props,\n getConversation: () => conversation,\n // experimental, not stable\n getResponseHandlers: () => responseHandlers.value,\n // experimental, not stable\n setResponseHandlers: (handlers: IResponseHandler<IStreamData>[]) => {\n responseHandlers.value = handlers;\n customModelProvider.setResponseHandlers(handlers);\n },\n getMessageRenderers: () => messageRenderers,\n setMessageRenderer: (key: string, renderer: Component<IRendererProps>) => {\n messageRenderers[key] = renderer;\n },\n generating,\n // @experimental\n lastSchemaCardId,\n continueChatAction,\n saveStateAction,\n});\n</script>\n\n<template>\n <div\n class=\"tg-chat-container\"\n :class=\"{ 'dark': genuiConfig?.colorScheme === 'dark' }\"\n :style=\"!props.chatConfig?.showThinkingResult ? { '--thinking-display': 'none' } : {}\"\n >\n <div\n class=\"messages-container\"\n ref=\"messagesContainer\"\n :style=\"{ '--messages-container-width': messagesContainerWidth + 'px' }\"\n >\n <tr-bubble-provider :content-renderers=\"messageRenderers\" v-if=\"showMessages.length\">\n <tr-bubble-list :items=\"showMessages\" :roles=\"roles\" auto-scroll> </tr-bubble-list>\n </tr-bubble-provider>\n <slot v-else name=\"empty\"></slot>\n </div>\n <div class=\"sender-container\">\n <!-- TODO: 抽离到组件 -->\n <div\n :class=\"['scroll-to-bottom-button', { 'is-generating': generating }]\"\n v-show=\"!isLastMessageInBottom\"\n @click=\"scrollToBottom\"\n >\n <IconArrowDown class=\"icon-arrow-down\" />\n </div>\n <tr-sender\n v-model=\"inputMessage\"\n :placeholder=\"\n GeneratingStatus.includes(messageManager.messageState.status)\n ? t('placeholder.thinking')\n : t('placeholder.input')\n \"\n :clearable=\"true\"\n :allow-files=\"isAllowFiles\"\n :buttonGroup=\"buttonGroup\"\n :loading=\"GeneratingStatus.includes(messageManager.messageState.status)\"\n @files-selected=\"(files) => handleFilesSelected(files, inputMessage)\"\n v-model:template-data=\"templateData\"\n @update:template-data=\"handleTemplateDataUpdate\"\n :showWordLimit=\"true\"\n :maxLength=\"20000\"\n @clear=\"clearInputMessage\"\n @submit=\"handleSendMessage\"\n @cancel=\"abortRequest\"\n >\n <template #header v-if=\"attachments.length > 0\">\n <div class=\"attachments-container\">\n <AttachmentsRenderer :attachments=\"attachments\" @remove=\"handleRemoveAttachment\" />\n </div>\n </template>\n </tr-sender>\n <div class=\"footer-text\">{{ t('footer.aiGenerated') }}</div>\n </div>\n </div>\n</template>\n\n<style scoped lang=\"less\">\n.tg-chat-container {\n --ti-gen-chat-container-bg-color: #f0f0f0;\n --thinking-display: initial;\n --sender-bg: url('./assets/sender-light.svg') no-repeat center;\n --sender-border-color: #e5e5e5;\n --generating-bg-before: linear-gradient(90deg, #fff, #a2c7f4);\n --generating-bg-after: #fff;\n box-sizing: border-box;\n height: 100%;\n color: var(--tr-text-primary);\n background-color: var(--ti-gen-chat-container-bg-color);\n position: relative;\n display: flex;\n flex-direction: column;\n overflow: auto;\n\n &.dark {\n --ti-gen-chat-container-bg-color: #191919;\n --sender-bg: url('./assets/sender-dark.svg') no-repeat center;\n --sender-border-color: #333;\n --generating-bg-before: linear-gradient(90deg, #262626, #808080);\n --generating-bg-after: #191919;\n }\n}\n\n.is-loading-in-top {\n margin-top: -48px;\n}\n\n.messages-container {\n flex: 1;\n overflow: auto;\n word-break: break-word;\n}\n\n:deep(.tr-bubble__loading) {\n margin-top: 8px;\n}\n\n:deep(.tr-bubble.placement-start) {\n .tr-bubble__content {\n padding: 0;\n background: transparent;\n border-radius: 0;\n box-shadow: none;\n }\n}\n:deep(.tr-bubble[data-role='assistant'] .tr-bubble__content-items:has([type^='schema-card'])) {\n // 匹配:type非空 + 排除 schema-card/loading-text 这两个值\n > [type]:not([type='']):not([type='schema-card']):not([type='loading-text']) {\n display: var(--thinking-display, initial);\n }\n}\n\n:deep(.tr-bubble__step-tool) {\n & + .tr-bubble__step-tool {\n margin-top: 16px;\n }\n}\n\n:deep(.tr-bubble.placement-end) {\n width: 100%;\n}\n\n:deep(.tr-bubble__content-wrapper) {\n @avatar-and-gap-width: 56px;\n // TODO: 后续规范变量名,在对外暴露\n max-width: calc(100% - var(--ti-gen-chat-avatar-and-gap-width, @avatar-and-gap-width) * 2);\n\n .tr-bubble__content {\n max-width: 100%;\n }\n\n .tr-bubble__content-items {\n overflow-x: auto;\n }\n}\n\n.sender-container {\n position: relative;\n flex-shrink: 0;\n padding: 16px 0;\n background: var(--sender-bg);\n\n .attachments-container {\n padding: 0 20px;\n }\n}\n\n.scroll-to-bottom-button {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n top: -35px;\n width: 40px;\n height: 40px;\n background-color: var(--generating-bg-after);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: 1px solid var(--sender-border-color);\n z-index: 1000;\n\n & > svg {\n width: 20px;\n height: 20px;\n }\n\n &:hover {\n box-shadow:\n 0px 10px 20px 0px #0000001a,\n 0px 0px 1px 0px #00000026;\n }\n\n &.is-generating {\n border: none;\n background-color: transparent;\n\n &::before {\n content: '';\n position: absolute;\n top: -2px;\n left: -2px;\n right: -2px;\n bottom: -2px;\n width: calc(100% + 4px);\n height: calc(100% + 4px);\n border-radius: 50%;\n background: var(--generating-bg-before);\n z-index: 0;\n animation: rotate-border 2s linear infinite;\n }\n\n &::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background-color: var(--generating-bg-after);\n z-index: 1;\n }\n\n & > svg {\n z-index: 2;\n }\n }\n}\n\n.footer-text {\n font-size: 12px;\n color: #999;\n text-align: center;\n margin-top: 16px;\n}\n\n:deep(.schema-render-container) {\n @large-screen-min-width: 400px;\n @min-width-safe-padding: 250px;\n @small-screen-min-width: calc(var(--messages-container-width) - @min-width-safe-padding);\n min-width: min(@small-screen-min-width, @large-screen-min-width);\n}\n\n@keyframes rotate-border {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n.tiny-sender {\n width: 80%;\n margin: 0 auto;\n}\n</style>\n","import type { BubbleRoleConfig, BubbleProps } from '@opentiny/tiny-robot';\nimport type { Component } from 'vue';\nimport type { IRendererSlots } from '../renderer';\nimport type { UseMessageReturn } from '@opentiny/tiny-robot-kit';\nimport type {\n INotificationPayload,\n IGenPromptComponent,\n IGenPromptSnippet,\n IGenPromptExample,\n IGenPromptAction,\n IChatMessage,\n} from '@opentiny/genui-sdk-core';\n\nexport interface ICustomActionItem extends IGenPromptAction {\n execute: (params: any, context: Record<string, any>) => any;\n}\n\nexport interface IRolesConfig {\n user: Partial<BubbleRoleConfig>;\n assistant: Partial<BubbleRoleConfig>;\n}\n\n\n// 自定义组件项,扩展 IGenPromptComponent 添加 ref(组件引用)\nexport interface ICustomComponentItem extends IGenPromptComponent {\n ref: Component; // 组件引用,用于传给 SchemaRenderer\n}\n\nexport interface IChatConfig {\n addToolCallContext?: boolean;\n showThinkingResult?: boolean;\n}\n\nexport interface IMessageItem {\n type: string;\n content: string;\n [customKey: string]: any;\n}\nexport interface IMessage {\n role: 'user' | 'assistant';\n content: string;\n messages?: IMessageItem[];\n}\n\n// 有几个插槽,参数都为这个类型\nexport interface IBubbleSlotsProps {\n index: number;\n bubbleProps: BubbleProps;\n isFinished: boolean;\n messageManager: UseMessageReturn;\n chatMessage: IChatMessage;\n}\n\n/**\n * 通知事件发射器类型,专门用于处理 'notification' 事件\n */\nexport interface INotificationEventEmitter {\n on(eventName: 'notification', callback: (payload: INotificationPayload) => void, once?: boolean): void;\n off(eventName: 'notification', callback: (payload: INotificationPayload) => void): void;\n emit(eventName: 'notification', payload: INotificationPayload): void;\n once(eventName: 'notification', callback: (payload: INotificationPayload) => void): void;\n}\n\nexport interface IThinkComponentProps {\n emitter: INotificationEventEmitter;\n message: IMessage;\n showThinkingResult: boolean;\n}\n\n/**\n * 自定义请求函数类型\n * @param url 请求地址\n * @param options 请求选项(包含 method, headers, body, signal 等)\n * @returns 返回 Response 对象或 Promise<Response>\n */\nexport type CustomFetch = (\n url: string,\n options: {\n method: string;\n headers: Record<string, string>;\n body: string;\n signal?: AbortSignal;\n },\n) => Promise<Response> | Response;\n\nexport interface IChatProps {\n url?: string;\n model?: string;\n temperature?: number;\n messages?: IMessage[];\n chatConfig?: IChatConfig;\n requiredCompleteFieldSelectors?: string[];\n customComponents?: ICustomComponentItem[];\n customSnippets?: IGenPromptSnippet[];\n customExamples?: IGenPromptExample[];\n customActions?: ICustomActionItem[];\n rendererSlots?: IRendererSlots;\n thinkComponent?: Component<BubbleProps>;\n roles?: IRolesConfig;\n features?: ModelCapability;\n customFetch?: CustomFetch;\n}\n\nexport interface ImageFeatures {\n enabled: boolean;\n maxImageSize: number;\n maxFilesPerRequest: number;\n supportedFileTypes: string[];\n}\nexport interface ModelFeatures {\n supportImage?: boolean | ImageFeatures;\n supportFunctionCalling?: boolean;\n [key: string]: any;\n}\n\nexport interface ModelCapability {\n supportImage?: ImageFeatures;\n supportFunctionCalling?: boolean;\n [key: string]: any;\n}\n\nexport interface ModelInfo {\n name: string;\n features?: ModelFeatures;\n}\n\nexport const DEFAULT_IMAGE_FEATURES: ImageFeatures = {\n enabled: true,\n maxImageSize: 10,\n maxFilesPerRequest: 3,\n supportedFileTypes: ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'heic', 'tiff'],\n};\n"],"names":["removeCustomActionsExecuteFunction","customActions","action","removeRefFromCustomComponents","customComponents","item","ref","rest","chat","chatOptions","url","messages","model","temperature","signal","customSnippets","customExamples","customFetch","tgCustomConfig","requestMetadata","options","response","errorText","readChunk","reader","handler","buffer","decoder","done","value","lineEnd","line","data","CustomModelProvider","BaseModelProvider","getChatOptions","_","handlers","request","_a","onDone","onData","onError","context","error","_request","chatConfig","rawData","streamData","e","throttle","fn","delay","timer","lastTime","args","now","elapsed","remaining","scrollEnd","container","isLastMessageInBottom","isScrollByUser","scrollByUserTimer","updateIsLastMessageInBottom","scrollToBottom","nextTick","scrollToBottomWithRetry","maxRetries","retryDelay","retryCount","lastScrollHeight","stableCount","attemptScroll","currentScrollHeight","scrollTop","clientHeight","isAtBottom","autoScrollToBottom","handleUserScroll","onMounted","onUnmounted","toSlotFunction","slot","props","h","MIME_TYPE_MAP","IMAGE_MIME_TYPES","validateFileSize","file","maxSizeMB","t","useI18n","maxBytes","validateFileForModel","features","extension","_b","maxSize","_c","detectFileCategory","type","processFiles","files","processFile","fileCategory","validation","serializeFile","resolve","reject","fileMeta","err","useFileUpload","attachments","templateData","apiContent","TinyNotify","inputMessage","newValue","attachmentFileNames","name","updatedTemplateData","content","templateFileNames","i","fileName","__props","emit","__emit","fullscreenImage","isImage","imageAttachments","computed","nonImageAttachments","handleRemove","attachment","openFullscreen","closeFullscreen","_openBlock","_createElementBlock","_hoisted_1","_Fragment","_renderList","index","$event","_createElementVNode","_hoisted_3","_withModifiers","_createVNode","_unref","IconFileRemove","_hoisted_6","_toDisplayString","_Transition","isImageTemplate","getImageBase64","getAttachment","handleImageClick","_hoisted_2","TinyPopover","_hoisted_4","_hoisted_5","open","handleClick","markdownRenderer","BubbleMarkdownContentRenderer","MarkdownContent","markdownProps","_normalizeClass","IconArrowDown","_withDirectives","MAX_HIGHLIGHT_JSON_FIELD_COUNT","exceedsFieldCountLimit","limit","count","traverse","val","escapeHtml","text","opened","textAndIconMap","IconLoading","IconPlugin","IconError","IconCancelled","textAndIcon","classes","useCssModule","highlightJSON","json","prettyJson","parsedValue","space","match","className","_createBlock","_resolveDynamicComponent","_cache","_hoisted_7","EventEmitter","eventName","callback","once","emitter","loadingText","hasSchemaCard","toolStatusTextMap","handleNotification","payload","toolCallData","textKey","lastMessage","onBeforeUnmount","useChatAction","saveState","params","IconRight","iconChevronRight","iconOperationfaild","expanded","toggleExpand","useResize","targetRef","width","height","resizeObserver","frameId","updateSize","element","rect","scheduleUpdate","cleanupObserver","entries","target","useMessage","client","useStreamByDefault","errorMessage","initialMessages","useStream","abortController","messageState","reactive","STATUS","chatOnReceiveData","onReceiveData","defaultPrevented","assistantMessage","toRaw","streamChatOnReceiveData","choice","streamChat","finishReason","onFinish","chatRequest","sendMessage","clearInput","GeneratingStatus","userMessage","send","abortRequest","retryRequest","msgIndex","clearMessages","addMessage","message","MessageManager","conversationState","conversationId","messageManager","conversation","id","newMessageManager","deepUnwrap","obj","isRef","unref","isReactive","acc","key","IndexedDBStrategy","dbName","storeName","dataKey","event","db","conversations","store","serializedData","putRequest","result","parseError","generateId","useConversation","storage","autoSave","allowEmpty","errorMessageOption","events","state","hasTriggeredOnLoaded","currentMessageManager","watch","row","saveConversations","createConversation","title","metadata","defaultTitle","newConversation","switchConversation","conv","deleteConversation","updateTitle","updateMetadata","loadConversations","generateTitle","prompt","contextMessages","getCurrentConversation","ThinkTagWrapPattern","getPartialStartRegString","getStreamDelta","onToolResult","toolCallsResult","delta","toolCallIdMap","chatMessage","addToolCallContext","toolCallItem","readonly","onToolCall","toolCalls","toolCallStatus","toolCall","argsDelta","nextArgs","onReasoningContent","reasoningContent","reasoningMessage","emitNotification","onReasoningEnd","onMarkdown","onSchemaJSON","uuidv4","watchReasoningEnd","newVal","defaultResponseHandlers","choices","usage","thinkPatternExtractor","PatternExtractor","genuiConfig","inject","GENUI_CONFIG","isAllowFiles","supportImage","buttonGroup","fileTypes","defaultRoles","IconAi","IconUser","wrapSlots","slots","newSlots","isFinished","generating","slotFn","roles","mergedRoles","keyAny","flatAllMessages","chatItem","itemMessages","getCardMessage","cardId","cardIdSymbol","cardMessage","llmFriendlyMessage","humanFriendlyMessage","continueChatAction","saveStateAction","lastSchemaCardId","lastChatMessage","items","customComponentsMap","map","customActionsMap","messageRenderers","schemaCardProps","isGenerating","GenuiRenderer","ToolRenderer","ReasoningRenderer","TemplateDataRenderer","GeneratingComponent","ErrorText","responseHandlers","customModelProvider","AIClient","preventDefault","currentMessages","v","setInputMessage","clearAttachments","processAttachments","handleFilesSelected","handleTemplateEdit","handleTemplateDataUpdate","showMessages","existingMessages","msg","setConversationTitle","messageContent","currentTitle","DEFAULT_TITLE","contentStr","clearInputMessage","handleRemoveAttachment","handleSendMessage","ipt","userMessageContent","attachmentsValue","templateDataValue","templateItem","att","handleNewConversation","messagesContainer","messagesContainerWidth","throttledScrollToBottom","__expose","renderer","_normalizeStyle","TrBubbleProvider","TrBubbleList","_renderSlot","_ctx","TrSender","AttachmentsRenderer","DEFAULT_IMAGE_FEATURES"],"mappings":"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"}
|
package/dist/code-generator.d.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { CardSchema } from '@opentiny/genui-sdk-core';
|
|
2
|
-
import { NodeSchema } from '@opentiny/genui-sdk-core';
|
|
3
|
-
|
|
4
|
-
export declare type CodegenFramework = 'vue' | 'react' | 'angular' | (string & {});
|
|
5
|
-
|
|
6
|
-
export declare const generateCode: (params: ICodeGeneratorParams) => Promise<ICodeGeneratorResult>;
|
|
7
|
-
|
|
8
|
-
export declare interface ICodegenDescription {
|
|
9
|
-
componentSet: Set<string>;
|
|
10
|
-
iconComponents: {
|
|
11
|
-
componentNames: string[];
|
|
12
|
-
exportNames: string[];
|
|
13
|
-
};
|
|
14
|
-
internalTypes: Set<string>;
|
|
15
|
-
stateAccessors: IStateAccessorDefinition[];
|
|
16
|
-
needsJsx: boolean;
|
|
17
|
-
needsComputed: boolean;
|
|
18
|
-
needsCallAction: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export declare interface ICodeGeneratorParams {
|
|
22
|
-
pageInfo: {
|
|
23
|
-
schema: CardSchema | string;
|
|
24
|
-
name?: string;
|
|
25
|
-
};
|
|
26
|
-
componentsMap?: IComponentMapItem[];
|
|
27
|
-
formatWithPrettier?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export declare type ICodeGeneratorResult = ICodePanel & {
|
|
31
|
-
errors: {
|
|
32
|
-
message: string;
|
|
33
|
-
}[];
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export declare interface ICodePanel {
|
|
37
|
-
panelName: string;
|
|
38
|
-
panelValue: string;
|
|
39
|
-
panelType: CodegenFramework;
|
|
40
|
-
prettierOpts: Record<string, unknown>;
|
|
41
|
-
type: 'page';
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export declare interface IComponentMapItem {
|
|
45
|
-
componentName: string;
|
|
46
|
-
package: string;
|
|
47
|
-
exportName?: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export declare interface IFrameworkCodeGenerator<TParams, TResult> {
|
|
51
|
-
generate(params: TParams): Promise<TResult>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export declare interface IScriptSetupBuildContext {
|
|
55
|
-
schema: CardSchema;
|
|
56
|
-
componentsMap: IComponentMapItem[];
|
|
57
|
-
description: ICodegenDescription;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export declare interface IScriptSetupSectionDefinition {
|
|
61
|
-
id: string;
|
|
62
|
-
group: string;
|
|
63
|
-
build: (ctx: IScriptSetupBuildContext) => string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export declare interface IStateAccessorDefinition {
|
|
67
|
-
name: string;
|
|
68
|
-
getterExpr: string;
|
|
69
|
-
setterExpr?: string;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export declare interface IVueCodeGeneratorOptions {
|
|
73
|
-
prettierOpts?: Record<string, unknown>;
|
|
74
|
-
enableCompileValidation?: boolean;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export declare class VueCodeGenerator implements IFrameworkCodeGenerator<ICodeGeneratorParams, ICodeGeneratorResult> {
|
|
78
|
-
private readonly generatorOptions;
|
|
79
|
-
private readonly prettierOpts;
|
|
80
|
-
private readonly enableCompileValidation;
|
|
81
|
-
constructor(generatorOptions?: IVueCodeGeneratorOptions);
|
|
82
|
-
protected replaceThis(value: string, inTemplate?: boolean): string;
|
|
83
|
-
protected buildScriptSetupStateAccessors(ctx: IScriptSetupBuildContext): string;
|
|
84
|
-
protected buildScriptSetupImports(ctx: IScriptSetupBuildContext): string;
|
|
85
|
-
protected buildScriptSetupRefs(ctx: IScriptSetupBuildContext): string;
|
|
86
|
-
protected buildScriptSetupDefineProps(ctx: IScriptSetupBuildContext): string;
|
|
87
|
-
protected buildScriptSetupDefineEmits(ctx: IScriptSetupBuildContext): string;
|
|
88
|
-
protected buildScriptSetupIconStatement(ctx: IScriptSetupBuildContext): string;
|
|
89
|
-
protected buildScriptSetupReactiveState(ctx: IScriptSetupBuildContext): string;
|
|
90
|
-
protected buildScriptSetupMethods(ctx: IScriptSetupBuildContext): string;
|
|
91
|
-
protected buildScriptSetupCallAction(ctx: IScriptSetupBuildContext): string;
|
|
92
|
-
protected buildScriptSetupBody(ctx: IScriptSetupBuildContext, sections: readonly IScriptSetupSectionDefinition[]): string;
|
|
93
|
-
protected buildSfcTemplateSection(template: string): string;
|
|
94
|
-
protected buildSfcScriptSetupSection(scriptSetup: string, needsJsx?: boolean): string;
|
|
95
|
-
protected buildSfcStyleSection(style: string): string;
|
|
96
|
-
protected getScriptSetupSections(): readonly IScriptSetupSectionDefinition[];
|
|
97
|
-
protected createCodegenMeta(): ICodegenDescription;
|
|
98
|
-
protected resolveRefAttr(value: string | undefined, asJsx: boolean): string | null;
|
|
99
|
-
protected resolvePropValueType(value: unknown): string;
|
|
100
|
-
protected buildJSFunctionExpression(value: string, inTemplate?: boolean): string;
|
|
101
|
-
protected hoistPropToState(key: string, item: unknown, attrsArr: string[], state: Record<string, unknown>, asJsx?: boolean): void;
|
|
102
|
-
protected isOnEventKey(key: string): boolean;
|
|
103
|
-
protected handleSlotBinding(item: Record<string, unknown> | string): string;
|
|
104
|
-
protected handleEventBinding(key: string, item: {
|
|
105
|
-
type?: string;
|
|
106
|
-
value?: string;
|
|
107
|
-
params?: string[];
|
|
108
|
-
}, asJsx?: boolean): string;
|
|
109
|
-
protected avoidDuplicateString(existings: string[], baseName: string): string;
|
|
110
|
-
protected handleLiteralBinding(key: string, item: unknown, attrsArr: string[], description: ICodegenDescription, state: Record<string, unknown>, asJsx?: boolean): void;
|
|
111
|
-
protected handleBinding(props: Record<string, unknown>, attrsArr: string[], description: ICodegenDescription, state: Record<string, unknown>, asJsx?: boolean): void;
|
|
112
|
-
protected recurseChildren(children: NodeSchema[] | NodeSchema | string | undefined, state: Record<string, unknown>, description: ICodegenDescription, result: string[]): void;
|
|
113
|
-
protected isEmptySlotNode(componentName: string | undefined, children: unknown): boolean;
|
|
114
|
-
protected generateTemplate(schema: CardSchema, state: Record<string, any>, description: ICodegenDescription, isRootNode?: boolean): string;
|
|
115
|
-
protected generateSlotTemplate(item: Record<string, any>, description: ICodegenDescription, state?: Record<string, unknown>): string;
|
|
116
|
-
protected getFunctionInfo(fnStr: string): {
|
|
117
|
-
type: string;
|
|
118
|
-
params: string[];
|
|
119
|
-
body: string;
|
|
120
|
-
} | null;
|
|
121
|
-
protected transformStateType(current: Record<string, any>, prop: string, description: ICodegenDescription, rootState: Record<string, any>): void;
|
|
122
|
-
protected traverseState(state: Record<string, any>, description: ICodegenDescription, rootState?: Record<string, any>): void;
|
|
123
|
-
protected buildVueSfcSource({ schema, componentsMap, }: {
|
|
124
|
-
schema: CardSchema;
|
|
125
|
-
name?: string;
|
|
126
|
-
componentsMap: IComponentMapItem[];
|
|
127
|
-
}): string;
|
|
128
|
-
protected normalizeIncomingSchema(origin: CardSchema | string | null | undefined): CardSchema;
|
|
129
|
-
protected generatePageCode({ pageInfo, componentsMap, formatWithPrettier, }: {
|
|
130
|
-
pageInfo: ICodeGeneratorParams['pageInfo'];
|
|
131
|
-
componentsMap: IComponentMapItem[];
|
|
132
|
-
formatWithPrettier?: boolean;
|
|
133
|
-
}): Promise<ICodeGeneratorResult>;
|
|
134
|
-
protected normalizeComponentsMap(componentsMap: IComponentMapItem[] | undefined): IComponentMapItem[];
|
|
135
|
-
protected formatWithPrettier(source: string, prettierOpts: Record<string, unknown>): Promise<string>;
|
|
136
|
-
generate({ pageInfo, componentsMap, formatWithPrettier, }: ICodeGeneratorParams): Promise<ICodeGeneratorResult>;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export { }
|
package/dist/code-generator.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"code-generator.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|