diff --git a/examples/sites/demos/pc/app/grid/ai-agent/basic-usage.vue b/examples/sites/demos/pc/app/grid/ai-agent/basic-usage.vue index d2ae337dd9..38306f2491 100644 --- a/examples/sites/demos/pc/app/grid/ai-agent/basic-usage.vue +++ b/examples/sites/demos/pc/app/grid/ai-agent/basic-usage.vue @@ -87,7 +87,7 @@ export default { await client.connect(clientTransport) const { sessionId } = await createSseProxy({ client, - url: 'http://39.108.160.245/sse' + url: 'https://39.108.160.245/sse' }) this.sessionID = sessionId diff --git a/examples/sites/package.json b/examples/sites/package.json index aea9628b96..9c6b8f1c79 100644 --- a/examples/sites/package.json +++ b/examples/sites/package.json @@ -29,9 +29,9 @@ "@docsearch/react": "npm:@docsearch/css", "@modelcontextprotocol/sdk": "1.12.1", "@opentiny/next": "0.1.2", - "@opentiny/tiny-robot": "0.2.0-alpha.8", - "@opentiny/tiny-robot-kit": "0.2.0-alpha.8", - "@opentiny/tiny-robot-svgs": "0.2.0-alpha.8", + "@opentiny/tiny-robot": "0.2.1", + "@opentiny/tiny-robot-kit": "0.2.1", + "@opentiny/tiny-robot-svgs": "0.2.1", "@opentiny/tiny-schema-renderer": "1.0.0-beta.5", "@opentiny/tiny-vue-mcp": "0.0.1-beta.1", "@opentiny/utils": "workspace:~", diff --git a/examples/sites/src/tools/appData.js b/examples/sites/src/tools/appData.js index dfb49b60ff..3163236e9b 100644 --- a/examples/sites/src/tools/appData.js +++ b/examples/sites/src/tools/appData.js @@ -1,4 +1,4 @@ -import { reactive, computed } from 'vue' +import { reactive, computed, watch } from 'vue' import { useAutoStore } from './storage' import { useMediaQuery } from './useMediaQuery' import { ZH_CN_LANG, EN_US_LANG, LANG_KEY, LANG_PATH_MAP } from '../const' @@ -8,7 +8,8 @@ const enPath = LANG_PATH_MAP[EN_US_LANG] const appData = reactive({ lang: useAutoStore('local', LANG_KEY, ZH_CN_LANG), theme: useAutoStore('local', '_theme', 'light'), - bpState: useMediaQuery([640, 1024, 1280]).matches // 3点4区间, bp0,bp1,bp2,bp3 + bpState: useMediaQuery([640, 1024, 1280]).matches, // 3点4区间, bp0,bp1,bp2,bp3 + showTinyRobot: false }) const isZhCn = computed(() => appData.lang === ZH_CN_LANG) const appFn = { @@ -27,4 +28,12 @@ const appFn = { } // 为了和tiny-vue共享同一个响应变量 window.appData = appData + +watch( + () => appData.showTinyRobot, + (value) => { + document.body.classList.toggle('docs-on-robot-show', value) + } +) + export { appData, appFn, isZhCn } diff --git a/examples/sites/src/views/components-doc/common.vue b/examples/sites/src/views/components-doc/common.vue index 207f41d9d1..b85ef176f3 100644 --- a/examples/sites/src/views/components-doc/common.vue +++ b/examples/sites/src/views/components-doc/common.vue @@ -90,7 +90,7 @@ - + diff --git a/examples/sites/src/views/components-doc/composition/DifyModelProvider.ts b/examples/sites/src/views/components-doc/composition/DifyModelProvider.ts index e7309964f0..93ac9fdae3 100644 --- a/examples/sites/src/views/components-doc/composition/DifyModelProvider.ts +++ b/examples/sites/src/views/components-doc/composition/DifyModelProvider.ts @@ -3,7 +3,8 @@ import type { AIModelConfig } from '@opentiny/tiny-robot-kit' import type { ChatCompletionResponse } from '@opentiny/tiny-robot-kit' import type { StreamHandler } from '@opentiny/tiny-robot-kit' import { BaseModelProvider } from '@opentiny/tiny-robot-kit' -import { handleSSEStream } from './utils.js' +import { globalConversation, handleSSEStream } from './utils.js' +import type { Ref } from 'vue' /** * 对接AIClient的自定义 Dify 大模型服务 @@ -14,6 +15,8 @@ import { handleSSEStream } from './utils.js' * }); */ export class DifyModelProvider extends BaseModelProvider { + _messages: Ref = [] + constructor(config: AIModelConfig) { super(config) } @@ -45,11 +48,12 @@ export class DifyModelProvider extends BaseModelProvider { response_mode: 'streaming', inputs: { sessionId: window.$sessionId - } + }, + conversation_id: globalConversation.id }) }) - await handleSSEStream(response, handler, signal) + await handleSSEStream(response, handler, this._messages, signal) } catch (error) { if (signal && signal.aborted) { console.warn('Request was aborted:', error) diff --git a/examples/sites/src/views/components-doc/composition/useTinyRobot.ts b/examples/sites/src/views/components-doc/composition/useTinyRobot.ts index 1f2777e61a..c3167d3dd8 100644 --- a/examples/sites/src/views/components-doc/composition/useTinyRobot.ts +++ b/examples/sites/src/views/components-doc/composition/useTinyRobot.ts @@ -1,7 +1,7 @@ import type { AIModelConfig } from '@opentiny/tiny-robot-kit' import { AIClient, useConversation } from '@opentiny/tiny-robot-kit' import { IconAi, IconUser } from '@opentiny/tiny-robot-svgs' -import { h, nextTick, onMounted, reactive, ref, toRaw, watch } from 'vue' +import { h, nextTick, onMounted, ref, watch } from 'vue' import { DifyModelProvider } from './DifyModelProvider.js' import type { SuggestionItem } from '@opentiny/tiny-robot' @@ -11,8 +11,9 @@ const difyConfig: AIModelConfig = { apiKey: 'app-H0VJI4LqZ4KskdcA5a07pjXf' } export function useTinyRobot() { + const difyModelProvider = new DifyModelProvider(difyConfig) const client = new AIClient({ - providerImplementation: new DifyModelProvider(difyConfig), + providerImplementation: difyModelProvider, ...difyConfig }) @@ -27,25 +28,21 @@ export function useTinyRobot() { { label: '识别网页的内容', description: '公司人员表有多少列,有多少行数据,帮我统计一下!', - icon: h('span', { style: { fontSize: '18px' } }, '🧠') + icon: h('span', { style: { fontSize: '18px' } }, '💡') }, { label: '智能操作网页', - description: '请勾选公司人员表最后一行”!', - icon: h('span', { style: { fontSize: '18px' } }, '🤔') + description: '请勾选公司人员表最后一行', + icon: h('span', { style: { fontSize: '18px' } }, '🕹') } ] const handlePromptItemClick = (ev, item) => { sendMessage(item.description) } - const { messageManager, createConversation } = useConversation({ client }) - - const randomId = () => Math.random().toString(36).substring(2, 15) - - const currentMessageId = ref('') - + const { messageManager } = useConversation({ client }) const { messages, messageState, inputMessage, sendMessage, abortRequest } = messageManager + difyModelProvider._messages = messages const roles = { assistant: { @@ -61,20 +58,17 @@ export function useTinyRobot() { } } - const showHistory = ref(false) - const historyData = reactive([]) - // 建议按钮组,设置对话的模板 const suggestionPillItems = [ { id: '1', text: '公司人员表', - icon: h('span', { style: { fontSize: '18px' } }, '🔍') + icon: h('span', { style: { fontSize: '18px' } }, '🏢') }, { id: '2', text: '城市下拉框', - icon: h('span', { style: { fontSize: '18px' } }, '🛠️') + icon: h('span', { style: { fontSize: '18px' } }, '🌐') } ] @@ -86,60 +80,11 @@ export function useTinyRobot() { senderRef.value.setTemplate(templateText, currentInitialValue) } } - watch( - () => messages.value[messages.value.length - 1]?.content, - () => { - if (!messages.value.length) { - return - } - - if (messages.value.length === 1) { - currentMessageId.value = randomId() - } - - const allSessions = historyData.flatMap((item) => item.items) - const currentSession = allSessions.find((item) => item.id === currentMessageId.value) - - const data = toRaw(messages.value) - if (!currentSession) { - const today = historyData.find((item) => item.group === '今天') - if (today) { - today.items.unshift({ title: messages.value[0].content, id: currentMessageId.value, data }) - } else { - historyData.unshift({ - group: '今天', - items: [{ title: messages.value[0].content, id: currentMessageId.value, data }] - }) - } - } else { - currentSession.data = data - } - } - ) - - const handleHistorySelect = (item) => { - currentMessageId.value = item.id - messages.value = item.data - showHistory.value = false - } const senderRef = ref(null) const currentTemplate = ref('') const suggestionOpen = ref(false) - // 设置指令 - const handleFillTemplate = (templateText) => { - setTimeout(() => { - currentTemplate.value = templateText - inputMessage.value = '' - - // 等待DOM更新后激活第一个字段 - setTimeout(() => { - senderRef.value?.activateTemplateFirstField() - }, 100) - }, 300) - } - // 清除当前指令 const clearTemplate = () => { // 清空指令相关状态 @@ -207,23 +152,17 @@ export function useTinyRobot() { promptItems, messageManager, - createConversation, messages, messageState, inputMessage, sendMessage, abortRequest, roles, - showHistory, - historyData, - currentMessageId, handlePromptItemClick, - handleHistorySelect, senderRef, currentTemplate, suggestionOpen, - handleFillTemplate, clearTemplate, handleSendMessage, handleMessageKeydown, diff --git a/examples/sites/src/views/components-doc/composition/utils.ts b/examples/sites/src/views/components-doc/composition/utils.ts index 879f1ad9bf..0844caf87c 100644 --- a/examples/sites/src/views/components-doc/composition/utils.ts +++ b/examples/sites/src/views/components-doc/composition/utils.ts @@ -4,13 +4,23 @@ */ import type { ChatMessage, ChatCompletionResponse, StreamHandler } from '@opentiny/tiny-robot-kit' +import type { ChatCompletionRequest } from '@opentiny/tiny-robot-kit' +import type { Ref } from 'vue' +export const globalConversation = { + id: '' +} /** * 处理SSE流式响应 * @param response fetch响应对象 * @param handler 流处理器 */ -export async function handleSSEStream(response: Response, handler: StreamHandler, signal?: AbortSignal): Promise { +export async function handleSSEStream( + response: Response, + handler: StreamHandler, + message: Ref, + signal?: AbortSignal +): Promise { // 获取ReadableStream const reader = response.body?.getReader() if (!reader) { @@ -64,6 +74,7 @@ export async function handleSSEStream(response: Response, handler: StreamHandler if (!dataMatch) continue const data = JSON.parse(dataMatch[1]) + // console.log('SSE data:', data) if (data?.event === 'workflow_started') { handler.onData({ id: data.workflow_run_id, @@ -73,7 +84,7 @@ export async function handleSSEStream(response: Response, handler: StreamHandler index: messageIndex++, delta: { role: 'assistant', - content: '**Workflow started** \r\n' + content: ' ' }, finish_reason: null } @@ -81,6 +92,10 @@ export async function handleSSEStream(response: Response, handler: StreamHandler object: '', model: '' }) + message.value.slice(-1)[0].loading = true + if (!globalConversation.id) { + globalConversation.id = data.conversation_id + } } if (data?.event === 'message' && data?.answer) { @@ -100,6 +115,7 @@ export async function handleSSEStream(response: Response, handler: StreamHandler object: '', model: '' }) + message.value.slice(-1)[0].loading = false } if (data?.event === 'message_end') { handler.onData({ @@ -118,6 +134,7 @@ export async function handleSSEStream(response: Response, handler: StreamHandler object: '', model: '' }) + message.value.slice(-1)[0].loading = false } // handler.onData(data) } catch (error) { diff --git a/examples/sites/src/views/components-doc/tiny-robot-chat.vue b/examples/sites/src/views/components-doc/tiny-robot-chat.vue index de07c9e0d9..5d0749003e 100644 --- a/examples/sites/src/views/components-doc/tiny-robot-chat.vue +++ b/examples/sites/src/views/components-doc/tiny-robot-chat.vue @@ -1,22 +1,6 @@