智能体详情页工具栏增加发布到市场按钮
This commit is contained in:
parent
b22df1b48b
commit
fb2363be65
@ -76,6 +76,21 @@
|
||||
{{ t('Flow Builder') }}
|
||||
</n-button>
|
||||
|
||||
<!-- 发布到市场按钮 -->
|
||||
<n-button
|
||||
type="default"
|
||||
size="medium"
|
||||
@click="handlePublish"
|
||||
:disabled="loading || isNew || publishing"
|
||||
class="toolbar-btn publish-btn"
|
||||
v-if="!isNew"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon><Icon icon="tabler:cloud-upload" /></n-icon>
|
||||
</template>
|
||||
{{ publishing ? t('Publishing...') : t('Publish to Marketplace') }}
|
||||
</n-button>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<n-button type="default" size="medium" @click="$emit('go-back')" :disabled="loading">
|
||||
<template #icon>
|
||||
@ -105,10 +120,12 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { NButton, NSpace, NIcon, useMessage } from 'naive-ui'
|
||||
import { NButton, NSpace, NIcon, useMessage, useDialog } from 'naive-ui'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { t } from '@/shared/i18n'
|
||||
import axios from 'axios'
|
||||
import { get_session_api_headers } from '@/shared/api/auth'
|
||||
|
||||
interface Props {
|
||||
entity: string
|
||||
@ -135,8 +152,10 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
defineEmits<Emits>()
|
||||
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
const router = useRouter()
|
||||
const executing = ref(false)
|
||||
const publishing = ref(false)
|
||||
|
||||
// 计算是否为新建记录
|
||||
const isNew = computed(() => {
|
||||
@ -211,6 +230,84 @@ async function handleFlowBuilder() {
|
||||
router.push({ name: 'FlowBuilder', query: { agentId } })
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
// 发布到市场按钮处理函数
|
||||
function handlePublish() {
|
||||
if (isNew.value || !props.record?.agent_name) {
|
||||
message.warning(t('Please save the agent first'))
|
||||
return
|
||||
}
|
||||
|
||||
const agentName = props.record.agent_name
|
||||
const agentFlow = props.record.agent_flow
|
||||
|
||||
if (!agentFlow) {
|
||||
message.warning(t('Agent flow data is required for publishing'))
|
||||
return
|
||||
}
|
||||
|
||||
dialog.info({
|
||||
title: t('Publish to Agent Marketplace'),
|
||||
content: t('Are you sure you want to publish agent "{0}" to the marketplace?').replace('{0}', agentName),
|
||||
positiveText: t('Confirm'),
|
||||
negativeText: t('Cancel'),
|
||||
onPositiveClick: () => {
|
||||
performPublish()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function performPublish() {
|
||||
try {
|
||||
publishing.value = true
|
||||
|
||||
const agentName = props.record?.agent_name || ''
|
||||
const agentFlow = props.record?.agent_flow
|
||||
|
||||
if (!agentFlow) {
|
||||
throw new Error(t('Agent flow data is required'))
|
||||
}
|
||||
|
||||
// 解析 agent_flow(如果是字符串)
|
||||
let flowData = agentFlow
|
||||
if (typeof agentFlow === 'string') {
|
||||
try {
|
||||
flowData = JSON.parse(agentFlow)
|
||||
} catch (e) {
|
||||
// 如果解析失败,保持原样
|
||||
}
|
||||
}
|
||||
|
||||
// 准备发布数据
|
||||
const publishData = {
|
||||
agent_name: agentName,
|
||||
title: props.record?.title || agentName,
|
||||
subtitle: props.record?.subtitle || '',
|
||||
description: props.record?.description || '',
|
||||
agent_flow: flowData
|
||||
}
|
||||
|
||||
const response = await axios.post('/jingrow/agent/publish', publishData, {
|
||||
headers: {
|
||||
...get_session_api_headers(),
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
withCredentials: true
|
||||
})
|
||||
|
||||
if (response.data.success) {
|
||||
message.success(response.data.message || t('Agent published successfully'))
|
||||
} else {
|
||||
throw new Error(response.data.message || t('Publish failed'))
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('发布智能体失败:', error)
|
||||
const errorMsg = error?.response?.data?.detail || error?.response?.data?.message || error?.message || t('Publish failed, please check permission and server logs')
|
||||
message.error(errorMsg)
|
||||
} finally {
|
||||
publishing.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -361,6 +458,20 @@ async function handleFlowBuilder() {
|
||||
box-shadow: 0 2px 8px rgba(14, 165, 233, 0.15);
|
||||
}
|
||||
|
||||
/* 发布按钮 - 紫色系 */
|
||||
.publish-btn {
|
||||
background: #f3e8ff !important;
|
||||
color: #7c3aed !important;
|
||||
border-color: rgba(139, 92, 246, 0.2) !important;
|
||||
}
|
||||
|
||||
.publish-btn:hover:not(:disabled) {
|
||||
background: #e9d5ff !important;
|
||||
color: #6d28d9 !important;
|
||||
border-color: rgba(139, 92, 246, 0.3) !important;
|
||||
box-shadow: 0 2px 8px rgba(139, 92, 246, 0.15);
|
||||
}
|
||||
|
||||
.toolbar-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
|
||||
@ -908,3 +908,69 @@ async def get_installed_agent_names():
|
||||
except Exception as e:
|
||||
logger.error(f"获取已安装智能体列表失败: {str(e)}")
|
||||
return {"success": False, "agents": []}
|
||||
|
||||
|
||||
@router.post("/jingrow/agent/publish")
|
||||
async def publish_agent_to_marketplace(payload: Dict[str, Any]):
|
||||
"""
|
||||
发布智能体到Jingrow Cloud智能体市场
|
||||
使用 create_local_agent API
|
||||
"""
|
||||
try:
|
||||
agent_name = payload.get("agent_name")
|
||||
agent_flow = payload.get("agent_flow")
|
||||
title = payload.get("title")
|
||||
description = payload.get("description", "")
|
||||
subtitle = payload.get("subtitle")
|
||||
|
||||
if not agent_name:
|
||||
raise HTTPException(status_code=400, detail="智能体名称不能为空")
|
||||
|
||||
if not agent_flow:
|
||||
raise HTTPException(status_code=400, detail="流程数据不能为空")
|
||||
|
||||
if not title:
|
||||
title = agent_name
|
||||
|
||||
url = f"{get_jingrow_cloud_url()}/api/action/jcloud.api.jlocal.create_local_agent"
|
||||
|
||||
headers = get_jingrow_cloud_api_headers()
|
||||
headers['Content-Type'] = 'application/json'
|
||||
|
||||
# 准备 agent_data
|
||||
agent_data = {
|
||||
"agent_name": agent_name,
|
||||
"title": title,
|
||||
"agent_flow": agent_flow if isinstance(agent_flow, str) else json.dumps(agent_flow, ensure_ascii=False),
|
||||
"description": description,
|
||||
"subtitle": subtitle or ""
|
||||
}
|
||||
|
||||
response = requests.post(url, json={
|
||||
"agent_data": agent_data
|
||||
}, headers=headers, timeout=20)
|
||||
|
||||
if response.status_code != 200:
|
||||
error_detail = response.json().get('detail', f"HTTP {response.status_code}") if response.headers.get('content-type', '').startswith('application/json') else f"HTTP {response.status_code}"
|
||||
raise HTTPException(status_code=response.status_code, detail=error_detail)
|
||||
|
||||
result = response.json()
|
||||
|
||||
# 检查错误
|
||||
if isinstance(result, dict) and result.get('error'):
|
||||
raise HTTPException(status_code=400, detail=result['error'])
|
||||
|
||||
message = result.get('message', {})
|
||||
if isinstance(message, dict) and message.get('error'):
|
||||
raise HTTPException(status_code=400, detail=message['error'])
|
||||
|
||||
# 成功响应
|
||||
agent_name_result = message.get('name', 'unknown') if isinstance(message, dict) else result.get('message', 'unknown')
|
||||
return {"success": True, "message": f"智能体发布成功,智能体名称: {agent_name_result}"}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"发布智能体失败: {str(e)}")
|
||||
logger.error(f"Traceback: {traceback.format_exc()}")
|
||||
raise HTTPException(status_code=500, detail=f"发布智能体失败: {str(e)}")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user