Skip to content

Commit 2420b10

Browse files
committed
feat: basic ability and agent mode
1 parent 7f3d235 commit 2420b10

File tree

23 files changed

+685
-246
lines changed

23 files changed

+685
-246
lines changed

designer-demo/src/composable/http/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const procession = {
1616
let loginVM = null
1717

1818
const showError = (url, message) => {
19+
if (message === 'canceled') return // 取消请求场景不报错
1920
globalNotify({
2021
type: 'error',
2122
title: '接口报错',

packages/configurator/src/select-icon-configurator/SelectIconConfigurator.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ export default {
5454
iconSearchValue: '',
5555
icon: {
5656
name: props.modelValue,
57-
component: props.modelValue && SvgICons[props.modelValue]()
57+
component: props.modelValue && SvgICons[props.modelValue]?.()
5858
},
5959
defaultIcon: {
6060
name: props.modelValue,
61-
component: props.modelValue && SvgICons[props.modelValue]()
61+
component: props.modelValue && SvgICons[props.modelValue]?.()
6262
}
6363
})
6464
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading

packages/plugins/robot/assets/test.png

Whitespace-only changes.

packages/plugins/robot/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,19 @@
2525
"license": "MIT",
2626
"homepage": "https://opentiny.design/tiny-engine",
2727
"dependencies": {
28-
"@opentiny/tiny-engine-meta-register": "workspace:*",
2928
"@opentiny/tiny-engine-common": "workspace:*",
29+
"@opentiny/tiny-engine-meta-register": "workspace:*",
3030
"@opentiny/tiny-engine-utils": "workspace:*",
3131
"@opentiny/tiny-robot": "0.3.0-rc.5",
3232
"@opentiny/tiny-robot-kit": "0.3.0-rc.5",
3333
"@opentiny/tiny-robot-svgs": "0.3.0-rc.5",
3434
"@opentiny/tiny-schema-renderer": "1.0.0-beta.6",
35-
"fast-json-patch": "~3.1.1",
35+
"@vueuse/core": "^9.13.0",
3636
"dompurify": "^3.0.1",
37+
"fast-json-patch": "~3.1.1",
3738
"highlight.js": "^11.11.1",
38-
"markdown-it": "^14.1.0",
39-
"jsonrepair": "3.13.0"
39+
"jsonrepair": "3.13.0",
40+
"markdown-it": "^14.1.0"
4041
},
4142
"devDependencies": {
4243
"@opentiny/tiny-engine-vite-plugin-meta-comments": "workspace:*",

packages/plugins/robot/src/BuildLoadingRenderer.vue

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<template>
22
<div class="build-loading-renderer">
3-
<img src="../assets/loading.webp" alt="loading" />
3+
<img :src="getIconUrl(statusData.icon)" :alt="status" />
44
<div class="build-loading-renderer-content">
5-
<div class="build-loading-renderer-content-header">页面生成中,请稍等片刻</div>
6-
<div class="build-loading-renderer-content-body">{{ renderContent }}</div>
5+
<div class="build-loading-renderer-content-header">{{ statusData.title }}</div>
6+
<div class="build-loading-renderer-content-body">{{ statusData.content }}</div>
77
</div>
88
</div>
99
</template>
@@ -16,15 +16,46 @@ export default {
1616
content: {
1717
type: String,
1818
required: true
19+
},
20+
status: {
21+
type: String,
22+
default: 'loading'
1923
}
2024
},
2125
setup(props) {
22-
const renderContent = computed(() => {
23-
return props.content.slice(-30)
26+
const getIconUrl = (icon: string) => {
27+
return new URL(`../assets/${icon}`, import.meta.url).href
28+
}
29+
30+
const statusDataMap = {
31+
loading: {
32+
title: '页面生成中,请稍等片刻',
33+
icon: 'loading.webp',
34+
content: () => props.content?.slice(-30)
35+
},
36+
success: {
37+
title: '已生成新页面效果',
38+
content: '您可以继续问答更新页面效果',
39+
icon: 'success.svg'
40+
},
41+
failed: {
42+
title: '页面生成失败',
43+
content: '页面生成失败',
44+
icon: 'failed.svg'
45+
}
46+
}
47+
48+
const statusData = computed(() => {
49+
const data = statusDataMap[props.status as keyof typeof statusDataMap] || statusDataMap.loading
50+
return {
51+
...data,
52+
content: typeof data.content === 'function' ? data.content() : data.content
53+
}
2454
})
2555
2656
return {
27-
renderContent
57+
statusData,
58+
getIconUrl
2859
}
2960
}
3061
}

packages/plugins/robot/src/Home.vue

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
<Teleport v-if="showTeleport" defer :to="fullscreen ? 'body' : '.tiny-engine-right-robot'">
1111
<div class="robot-chat-container" :class="{ 'robot-chat-container-fullscreen': fullscreen }">
1212
<robot-chat
13-
:ref="robotChatRef"
13+
ref="robotChatRef"
1414
:prompt-items="promptItems"
15-
:allowFiles="isVisualModel() && aiType === AI_MODES.Agent"
15+
:bubbleRenderers="
16+
aiMode === CHAT_MODE.Agent ? { markdown: BuildLoadingRenderer, loading: BuildLoadingRenderer } : {}
17+
"
18+
:allowFiles="isVisualModel() && aiMode === CHAT_MODE.Agent"
1619
@fileSelected="handleFileSelected"
1720
>
1821
<template #operations>
@@ -25,24 +28,21 @@
2528
>
2629
<robot-setting-popover
2730
v-if="showSettingPopover"
28-
@changeType="changeModel"
31+
@changeType="handleChatModeChange"
2932
@close="closePanel"
3033
></robot-setting-popover>
3134
<template #reference>
32-
<span class="chat-title-dropdown" @click.stop="showSettingPopover = true">
35+
<span class="setting-icon" @click.stop="showSettingPopover = !showSettingPopover">
3336
<svg-icon name="setting" class="operations-setting ml8"> </svg-icon>
3437
</span>
3538
</template>
3639
</tiny-popover>
3740
</template>
3841
<template #footer-left>
39-
<robot-type-select :aiType="aiType" @typeChange="typeChange"></robot-type-select>
40-
<mcp-server :position="mcpDrawerPosition" v-if="aiType === AI_MODES.Chat"></mcp-server>
42+
<robot-type-select :aiMode="aiMode" @typeChange="typeChange"></robot-type-select>
43+
<mcp-server :position="mcpDrawerPosition" v-if="aiMode === CHAT_MODE.Chat"></mcp-server>
4144
</template>
4245
</robot-chat>
43-
<tiny-dialog-box v-model:visible="showPreview" title="当前AI渲染效果" width="80%">
44-
<schema-renderer v-if="showPreview" :schema="currentSchema"></schema-renderer>
45-
</tiny-dialog-box>
4646
</div>
4747
</Teleport>
4848
</div>
@@ -53,16 +53,17 @@ import { computed, h, onMounted, ref } from 'vue'
5353
import { ToolbarBase } from '@opentiny/tiny-engine-common'
5454
import RobotChat from './components/RobotChat.vue'
5555
import RobotSettingPopover from './components/RobotSettingPopover.vue'
56-
import { TinyPopover, TinyDialogBox } from '@opentiny/vue'
56+
import { TinyPopover } from '@opentiny/vue'
5757
import { useRobot, getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register'
5858
import McpIconComponent from './icons/mcp-icon.vue'
5959
import PageIconComponent from './icons/page-icon.vue'
6060
import StudyIconComponent from './icons/study-icon.vue'
6161
import type { PromptProps } from '@opentiny/tiny-robot'
62-
import SchemaRenderer from '@opentiny/tiny-schema-renderer'
6362
import RobotTypeSelect from './components/RobotTypeSelect.vue'
6463
import McpServer from './mcp/McpServer.vue'
64+
import BuildLoadingRenderer from './BuildLoadingRenderer.vue'
6565
import { updateLLMConfig } from './client'
66+
import useChat from './composables/useChat'
6667
6768
const { options } = defineProps({
6869
options: {
@@ -71,7 +72,7 @@ const { options } = defineProps({
7172
}
7273
})
7374
74-
const robotChatRef = ref('robotChatRef')
75+
const robotChatRef = ref(null)
7576
7677
const fullscreen = computed(() => {
7778
return robotChatRef.value?.fullscreen
@@ -107,54 +108,30 @@ const promptItems: PromptProps[] = [
107108
}
108109
]
109110
110-
const showPreview = ref(false)
111-
const currentSchema = ref(null)
112111
const showTeleport = ref(false)
113112
const showSettingPopover = ref(false)
114113
115-
const { robotSettingState, AI_MODES, AIModelOptions } = useRobot()
114+
const { robotSettingState, CHAT_MODE, AIModelOptions, aiMode } = useRobot()
115+
const { inputMessage } = useChat()
116116
117117
const isVisualModel = () => {
118118
const platform = AIModelOptions.find((option) => option.value === robotSettingState.selectedModel.baseUrl)
119-
const modelAbility = platform.model.find((item) => item.value === robotSettingState.selectedModel.model)
119+
const modelAbility = platform?.model.find((item) => item.value === robotSettingState.selectedModel.model)
120120
return modelAbility?.ability?.includes('visual') || false
121121
}
122122
123-
const aiType = ref(AI_MODES.Agent)
124-
125123
const typeChange = (type: string) => {
126-
aiType.value = type
124+
aiMode.value = type
127125
robotChatRef.value?.createConversation()
128126
updateLLMConfig({
129-
apiUrl: type === AI_MODES.Agent ? '/app-center/api/ai/chat' : '/app-center/api/chat/completions'
127+
apiUrl: type === CHAT_MODE.Agent ? '/app-center/api/ai/chat' : '/app-center/api/chat/completions'
130128
})
131129
}
132130
133-
const changeApiKey = () => {
134-
localStorage.removeItem('aiChat')
135-
}
136-
137-
const changeModel = (model) => {
138-
robotSettingState.selectedModel = {
139-
label: model.label || model.model,
140-
activeName: model.activeName,
141-
baseUrl: model.baseUrl,
142-
model: model.model,
143-
completeModel: model.completeModel,
144-
apiKey: model.apiKey
145-
}
131+
const handleChatModeChange = () => {
146132
// singleAttachmentItems.value = []
147133
// imageUrl.value = ''
148134
// endContent()
149-
150-
if (
151-
robotSettingState.selectedModel.apiKey !== model.apiKey &&
152-
robotSettingState.selectedModel.baseUrl === model.baseUrl &&
153-
robotSettingState.selectedModel.model === model.model
154-
) {
155-
robotSettingState.selectedModel.apiKey = model.apiKey
156-
changeApiKey()
157-
}
158135
}
159136
160137
const closePanel = () => {
@@ -175,6 +152,9 @@ const handleFileSelected = (formData: unknown, updateAttachment: (resourceUrl: s
175152
})
176153
.then((res: any) => {
177154
updateAttachment(res?.resourceUrl)
155+
if (!inputMessage.value) {
156+
inputMessage.value = '生成图片中UI效果'
157+
}
178158
})
179159
} catch (error) {
180160
// eslint-disable-next-line no-console
@@ -203,6 +183,10 @@ onMounted(async () => {
203183
}
204184
}
205185
186+
.setting-icon {
187+
cursor: pointer;
188+
}
189+
206190
.operations-setting {
207191
font-size: 28px;
208192
padding: 4px;

0 commit comments

Comments
 (0)