Skip to content

feat(site): add the tiny-robot drawer to the official website. #3467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 3, 2025
Merged
6 changes: 5 additions & 1 deletion examples/sites/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
"@docsearch/css": "^3.8.0",
"@docsearch/js": "^3.8.0",
"@docsearch/react": "npm:@docsearch/css",
"@opentiny/tiny-robot": "0.2.0-alpha.7",
"@opentiny/tiny-robot-kit": "0.2.0-alpha.7",
"@opentiny/tiny-robot-svgs": "0.2.0-alpha.7",
"@opentiny/tiny-schema-renderer": "1.0.0-beta.5",
"@opentiny/utils": "workspace:~",
"@opentiny/vue": "workspace:~",
"@opentiny/vue-common": "workspace:~",
Expand Down Expand Up @@ -100,4 +104,4 @@
"vite-svg-loader": "^3.6.0",
"vue-tsc": "^1.8.5"
}
}
}
3 changes: 3 additions & 0 deletions examples/sites/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { createHead } from '@vueuse/head'
import { createApp } from 'vue'
import '@unocss/reset/eric-meyer.css'

// tiny-robot 对话框
import '@opentiny/tiny-robot/dist/style.css'

// markdown文件内代码高亮
import 'prismjs/themes/prism.css'
import 'uno.css'
Expand Down
22 changes: 21 additions & 1 deletion examples/sites/src/views/components-doc/common.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
<slot name="header-right" />
</template>
</ComponentHeader>
<div class="docs-content" id="doc-layout-scroller" ref="scrollRef" @scroll="onDocLayoutScroll">
<div
class="docs-content"
:class="{ 'docs-on-robot-show': show }"
id="doc-layout-scroller"
ref="scrollRef"
@scroll="onDocLayoutScroll"
>
<div class="ti-rel cmp-container">
<div class="flex-horizontal docs-content-main">
<div class="docs-tabs-wrap">
Expand Down Expand Up @@ -84,6 +90,7 @@
</div>
<div id="footer"></div>
</div>
<robotChat v-if="show"></robotChat>
</template>

<script setup lang="ts">
Expand All @@ -101,6 +108,8 @@ import ComponentContributor from './components/contributor.vue'
import ApiDocs from './components/api-docs.vue'
import useTasksFinish from './composition/useTasksFinish'

import robotChat from './tiny-robot-chat.vue'

const props = defineProps({ loadData: {}, appMode: {}, demoKey: {} })

const emit = defineEmits(['single-demo-change', 'load-page'])
Expand Down Expand Up @@ -435,6 +444,13 @@ const handleAnchorClick = (e, data) => {
}

defineExpose({ loadPage })

const show = ref(false)
onMounted(() => {
// tiny-robot 通过路由参数存在 mcp-robot, 则弹出对话容器
const hasRobot = router.currentRoute.value.query['mcp-robot'] !== undefined
show.value = !!hasRobot
})
</script>

<style lang="less" scoped>
Expand All @@ -444,6 +460,10 @@ defineExpose({ loadPage })
margin-top: 16px;
transition: all ease-in-out 0.3s;

&.docs-on-robot-show {
margin-right: 480px;
}

.docs-tabs-wrap {
width: 100%;
flex: 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { ChatCompletionRequest } from '@opentiny/tiny-robot-kit'
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, handleSSEStream, handleRequestError } from '@opentiny/tiny-robot-kit'

/**
* 对接AIClient的自定义 Dify 大模型服务
*
* const client = new AIClient({
* provider: 'custom',
* providerImplementation: new CustomModelProvider( config )
* });
*/
export class DifyModelProvider extends BaseModelProvider {
constructor(config: AIModelConfig) {
super(config)
}
/** 同步请示不需要实现 */
chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse> {
throw new Error('Method not implemented.')
}

/** 异步流式请求 */
async chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void> {
const { signal } = request
this.validateRequest(request)

try {
// 验证请求的messages属性,必须是数组,且每个消息必须有role\content属性
// const { onData, onDone, onError } = handler
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

无用的代码可以删除

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已删除

const lastMessage = request.messages[request.messages.length - 1].content

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add bounds check before accessing array element.

Accessing the last message without checking if the array is empty could cause a runtime error.

 try {
   // 验证请求的messages属性,必须是数组,且每个消息必须有role\content属性
   // const { onData, onDone, onError } = handler
+  if (!request.messages || request.messages.length === 0) {
+    throw new Error('Messages array is empty')
+  }
   const lastMessage = request.messages[request.messages.length - 1].content
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
// 验证请求的messages属性,必须是数组,且每个消息必须有role\content属性
// const { onData, onDone, onError } = handler
const lastMessage = request.messages[request.messages.length - 1].content
try {
// 验证请求的messages属性,必须是数组,且每个消息必须有role\content属性
// const { onData, onDone, onError } = handler
if (!request.messages || request.messages.length === 0) {
throw new Error('Messages array is empty')
}
const lastMessage = request.messages[request.messages.length - 1].content
🤖 Prompt for AI Agents
In examples/sites/src/views/components-doc/composition/DifyModelProvider.ts
around lines 29 to 33, the code accesses the last element of the
request.messages array without verifying if the array is empty, which can cause
a runtime error. Add a check to ensure request.messages is not empty before
accessing its last element, and handle the empty case appropriately to avoid
errors.

// 模拟异步流式响应
const response = await fetch(`${this.config.apiUrl}/chat-messages`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
'Accept': 'text/event-stream'
},
body: JSON.stringify({
query: lastMessage,
user: 'user',
response_mode: 'stream'
// conversation_id:''
})
})

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}

await handleSSEStream(response, handler, signal)
} catch (error) {
if (signal && signal.aborted) {
console.warn('Request was aborted:', error)
} else {
console.error('Error in chatStream:', error)
handler.onError(handleRequestError(error))
}
}
}
}
Loading
Loading