Compare commits

...

16 Commits

Author SHA1 Message Date
Dot.L e010f00a19 Merge pull request #383 from APIParkLab/feature/liujian-1.9
fix bug: fail to get ai logs
2025-08-15 16:27:51 +08:00
Liujian 1a9b916bab fix bug: fail to get ai logs 2025-08-15 16:25:49 +08:00
JackLiu 3e4f4e1cff Update README.md 2025-08-15 09:33:53 +08:00
ningyv 3217ad2bba Merge pull request #380 from APIParkLab/feature/1.9-OAuth
fix: Fix department selection issue
2025-08-12 10:44:59 +08:00
lcx 1485b31226 fix: Fix department selection issue 2025-08-12 10:43:17 +08:00
ningyv 8968e1f961 Merge pull request #379 from APIParkLab/feature/1.9-OAuth
fix: Fix department selection issue.
2025-08-12 10:23:42 +08:00
lcx 4b8fa43c36 fix: Fix department selection issue. 2025-08-12 10:23:14 +08:00
ningyv c21d783c52 Merge pull request #378 from APIParkLab/feature/1.9-OAuth
fix: issue with adding user permissions
2025-08-11 19:00:31 +08:00
lcx e928cd84d7 fix: issue with adding user permissions 2025-08-11 18:59:39 +08:00
FreyLoong 412cb75bf0 Update readme-zh-cn.md 2025-08-08 18:42:46 +08:00
FreyLoong a13b2a8afe Update README.md 2025-08-08 18:40:14 +08:00
Dot.L c0472c8539 Merge pull request #375 from APIParkLab/feature/liujian-1.9
Feature/liujian 1.9
2025-08-08 12:06:44 +08:00
Liujian 5f40d5092c update qiniu rput param 2025-08-08 12:05:46 +08:00
Liujian b949939816 Fix: The issue where the upstream forwarding header is not effective 2025-08-08 12:04:40 +08:00
Dot.L 55f09f7542 Merge pull request #374 from APIParkLab/feature/liujian-1.9
fix: fail to delete model
2025-08-08 11:31:25 +08:00
Liujian ef1ccb81a9 fix: fail to delete model 2025-08-08 11:29:26 +08:00
11 changed files with 151 additions and 52 deletions
+54 -1
View File
@@ -156,6 +156,10 @@ curl -sSO https://download.apipark.com/install/quick-start.sh ; bash quick-sta
<br>
<br>
# 🚀 Use Cases
## Simplify AI Integration Costs
- Connect to 100+ major models from all mainstream AI vendors, with standardized API calls requiring no additional adaptation work.
@@ -199,11 +203,20 @@ To achieve this goal, we plan to add new features to APIPark, including:
# 📕 Documentation
Visit [APIPark Documentation](https://docs.apipark.com/docs/deploy) for detailed installation guides, API references, and usage instructions.
# 🧑‍🤝‍🧑Friendly Links
<a href="https://xroute.ai/">
<img width="1248" height="158" alt="新建 PPTX 演示文稿 (2)_03" src="https://github.com/user-attachments/assets/0ebd694c-410a-4e3f-a793-90f1140d15df" />
</a>
<br>
<br>
# 🧾 License
APIPark uses the Apache 2.0 License. For more details, please refer to the LICENSE file.
<br>
# 💌 Contact Us
@@ -212,6 +225,46 @@ For enterprise-level features and professional technical support, contact our pr
- Website: https://apipark.com
- Email: contact@apipark.com
🙏 A big thanks to everyone who helped shape APIPark. We are thrilled to hear the communitys thoughts! Lets make the world of APIs and AI stronger and more fun together. 🎉
<br>
🙏 A big thanks to everyone who helped shape APIPark. We are thrilled to hear the communitys thoughts! Lets make the world of APIs and AI stronger and more fun together. 🎉
# 🤝 Partner
- [Cursor](https://www.cursor.com/): Cursor is an AI-powered code editor that integrates artificial intelligence directly into the coding workflow, offering features like intelligent next edit suggestions, deep codebase understanding for relevant answers, and natural language editing to streamline development tasks and boost developer productivity.
- [Dify](https://dify.ai/): Dify is a leading Agentic AI Development Platform that provides a comprehensive suite of tools for building and extending AI applications, offering everything needed for agentic workflows, RAG pipelines, integrations, and observability, while allowing users to amplify their applications with various global Large Language Models (LLMs) and versatile plugins.
- [Trae](https://www.trae.ai/): Trae is an AI-native Integrated Development Environment (IDE) product that aims to embody the concept of “The Real AI Engineer” through intelligent productivity, seamlessly integrating into the development process to enhance quality and efficiency, featuring a chat-based interaction interface and supporting code generation and assistance.
- [Windsurf](https://windsurf.com/): Windsurf is an AI code editor designed to provide a seamless and limitless flow for developers, introducing a new purpose-built IDE that leverages AI to enhance coding with features like "Cascade" for deep codebase understanding, "Windsurf Tab" for intelligent autocompletion, and "Memories" for remembering important aspects of the codebase.
- [Coze](https://www.coze.com/): Coze is a next-generation AI application and chatbot development platform by ByteDance, empowering users to easily create and deploy powerful AI chatbots across various platforms with a no-code bot builder, integrated workflow logic, access to proprietary data, and simplified creation through pre-built plugins, knowledge bases, and workflows.
- [Claude Code](https://www.anthropic.com/claude-code): Claude Code is a command-line AI tool by Anthropic that embeds the Claude Opus 4 model directly into the users terminal, providing deep codebase awareness, the ability to edit files and execute commands, and making coordinated changes across multiple files, all while integrating seamlessly with popular IDEs and leveraging existing test suites.
- [Flowith](https://flowith.io/): Flowith is an AI creation workspace designed to revolutionize productivity and deep work by transforming knowledge and streamlining tasks through a multi-thread interface powered by advanced AI agents, offering an intuitive canvas-based user experience unlike traditional chat-based AI tools, and including a 24/7 operational version for complex tasks.
- [OpenManus](https://github.com/FoundationAgents/OpenManus): OpenManus is an open-source framework dedicated to building general AI agents, aiming to provide a platform where users can create and deploy their own agents without an invite code, supporting multi-agent capabilities, and requiring configuration for Large Language Model (LLM) APIs while integrating with browser automation tools.
- [Fellou](https://fellou.ai/): Fellou is an innovative Agentic Browser designed to transcend traditional web browsing by actively performing actions on behalf of the user, automating the entire process of information gathering and insight delivery, and excelling in in-depth research with seamless integrations with popular tools like Notion and LinkedIn.
- [Genspark](https://www.genspark.ai/): Genspark is an ultimate all-in-one AI companion offering a comprehensive suite of tools like AI Slides, AI Sheets, and AI Chat, designed to enhance various aspects of productivity and content creation, with personalized tools and AI Pods for generating content from diverse sources.
- [TEN](https://github.com/TEN-framework/ten-framework): TEN (The Embodied Narrator) is an open-source framework for building real-time, multimodal conversational voice AI agents, including components like TEN Framework, TEN Turn Detection, TEN Agent, TMAN Designer, and TEN Portal, offering features like Real-time Avatar, seamless MCP integration, real-time hardware communication, and vision/screenshare detection.
- [ChatGPT](https://chatgpt.com/): ChatGPT is an AI chatbot developed by OpenAI, built upon large language models like GPT-3.5 and GPT-4, designed to generate human-like conversational dialogue, understand context, answer follow-up questions, and integrate with various platforms for enhanced productivity through advanced language understanding, generation, and multilingual capabilities.
- [LangChain](https://www.langchain.com/): LangChain is a robust platform engineered for the development of reliable agents and Large Language Model (LLM) applications, offering a comprehensive product suite that seamlessly integrates various tools across the entire application development lifecycle, including LangGraph, LangSmith, and the LangGraph Platform, with functionalities for code generation, automation, and AI Search.
- [LEMON AI](https://lemonai.cc/): Lemon AI is the first Full-stack, Open-source, Agentic AI framework, offering a fully local alternative to platforms like Manus & Genspark AI. It features an integrated Code Interpreter VM sandbox for safe execution.
- [LobeChat](https://lobehub.com/): LobeHub offers LobeChat, a personal LLM productivity tool designed to elevate the user experience beyond traditional chatbots by empowering individuals to build personal AI agents and professional teams, supporting a wide array of LLMs, offering a simple chat interface, visual recognition, voice interaction, a rich plugin ecosystem, and knowledge base functionalities.
- [VS Code](https://code.visualstudio.com/): Visual Studio Code (VS Code) is a widely popular, free, and open-source code editor by Microsoft, renowned for its extensibility and customization, supporting vast programming languages, and integrating AI capabilities like intelligent next edit suggestions and an advanced “agent mode” for complex tasks, with broad compatibility with various AI models.
- [XRoute](https://xroute.ai): The Unified Interface For LLMs, provides better prices, better throughput, and no subscription.
- [XPack MCP Marketplace](https://github.com/xpack-ai/XPack-MCP-Marketplace): The world's first open-source MCP monetization platform, transform any OpenAPI into a monetizable MCP server and build your own API marketplace in just 10 minutes. Everything is open-source and ready for commercial use.
- [MemU](https://github.com/NevaMind-AI/memU): MemU is an open-source memory framework for AI companions
@@ -19,7 +19,7 @@ export type MemberTableListItem = {
enable:boolean
departmentId:string
roles:EntityItem[]
form: string
from: string
};
export type AddToDepartmentProps = {
@@ -41,7 +41,7 @@ export type MemberDropdownModalFieldType = {
export type MemberDropdownModalProps = {
type:'addDep'|'addChild'|'addMember'|'editMember'|'rename'
entity?:(MemberTableListItem & {departmentIds:string[]}) | ({id?:string, departmentIds?:string[],name?:string,form?:string})
entity?:(MemberTableListItem & {departmentIds:string[]}) | ({id?:string, departmentIds?:string[],name?:string,from?:string})
selectedMemberGroupId?:string
}
@@ -14,8 +14,7 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
const {fetchData} = useFetch()
const [departmentList, setDepartmentList] = useState<DepartmentListItem[]>([])
const { state } = useGlobalContext()
const [disableEditMemberData] = useState<boolean>(entity?.form !== 'self-build')
const [disableEditMemberData] = useState<boolean>(entity?.from === 'feishu')
const save:()=>Promise<boolean | string> = ()=>{
let url:string
let method:string
@@ -95,14 +95,15 @@ const AddToDepartment = forwardRef<AddToDepartmentHandle, AddToDepartmentProps>(
treeData?.map((x: DataNode) => ({
...x,
name: $t((x as unknown as { name: string }).name),
checkable: false,
children: x.children?.map(y => ({ ...y, checkable: false }))
checkable: false, // 根节点不可选中
children: x.children?.map(y => ({ ...y, checkable: true })) // 子节点可以选中
})),
[state.language, treeData]
)
const onCheck: TreeProps['onCheck'] = (checkedKeys: string[]) => {
setSelectedKeys(checkedKeys.checked)
const onCheck: TreeProps['onCheck'] = (checkedKeys, info) => {
const selectedIds = Array.isArray(checkedKeys) ? checkedKeys : checkedKeys.checked || []
setSelectedKeys(selectedIds)
}
useEffect(() => {
@@ -153,11 +154,12 @@ const MemberList = () => {
const [tableHttpReload, setTableHttpReload] = useState(true)
const [tableListDataSource, setTableListDataSource] = useState<MemberTableListItem[]>([])
const pageListRef = useRef<ActionType>(null)
const { topGroupId, selectedDepartmentIds, refreshGroup } = useOutletContext<{
const { topGroupId, selectedDepartmentIds, refreshGroup, refreshTableCount } = useOutletContext<{
topGroupId: string
departmentList: DepartmentListItem[]
selectedDepartmentIds: string[]
refreshGroup: () => void
refreshTableCount: number
}>()
const AddMemberRef = useRef<MemberDropdownModalHandle>(null)
const EditMemberRef = useRef<MemberDropdownModalHandle>(null)
@@ -396,7 +398,7 @@ const MemberList = () => {
width: 600,
okText: $t('确认'),
okButtonProps: {
disabled: isActionAllowed(type) || (type === 'editMember' && entity?.form !== 'self-build')
disabled: isActionAllowed(type) || (type === 'editMember' && entity?.from === 'feishu')
},
cancelText: $t('取消'),
closable: true,
@@ -415,6 +417,13 @@ const MemberList = () => {
getDepartmentList()
}, [])
// 监听外部刷新触发器
useEffect(() => {
if (refreshTableCount > 0) {
manualReloadTable()
}
}, [refreshTableCount])
const getDepartmentList = async () => {
setDepartmentValueEnum([])
const { code, data, msg } = await fetchData<BasicResponse<{ department: DepartmentListItem }>>(
@@ -36,6 +36,11 @@ const MemberPage = ()=>{
const [selectedDepartmentId, setSelectedDepartmentId] = useState<string>('-1')
const {accessData,state} = useGlobalContext()
const [refreshMemberCount, setRefreshMemberCount] = useState<number>(0)
const [refreshTableCount, setRefreshTableCount] = useState<number>(0)
const refreshMemberTable = () => {
setRefreshTableCount(prev => prev + 1)
}
const onSearchWordChange = (e:string)=>{
setSearchWord(e || '')
}
@@ -90,7 +95,7 @@ const MemberPage = ()=>{
case 'addChild':
return AddChildRef.current?.save().then((res)=>{if(res === true)getDepartmentList()})
case 'addMember':
return AddMemberRef.current?.save().then((res)=>{if(res === true){getDepartmentList();setRefreshMemberCount(pre=>pre+1)}})
return AddMemberRef.current?.save().then((res)=>{if(res === true){getDepartmentList();setRefreshMemberCount(pre=>pre+1);refreshMemberTable()}})
case 'rename':
return RenameRef.current?.save().then((res)=>{if(res === true)getDepartmentList()})
case 'delete':
@@ -262,7 +267,7 @@ const MemberPage = ()=>{
</div>
</div>
<div className="flex-1 p-btnbase pr-PAGE_INSIDE_X overflow-x-hidden">
<Outlet context={{refreshMemberCount, selectedDepartmentIds,refreshGroup:()=>getDepartmentList()}}/>
<Outlet context={{refreshMemberCount, selectedDepartmentIds,refreshGroup:()=>getDepartmentList(), refreshTableCount}}/>
</div>
</div>
</InsidePage>);
+3
View File
@@ -156,6 +156,9 @@ func SetServerByOpenapi(sid, name, version, content string) error {
toolOptions = append(toolOptions, mcp.WithDescription(a.Description))
params := make(map[string]*Param)
for _, v := range a.Params {
if v.In == "header" && v.Name == "Authorization" {
continue
}
params[v.Name] = NewParam(Position(v.In), v.Required, v.Description)
options := make([]mcp.PropertyOption, 0, 2)
if v.Required {
+15 -11
View File
@@ -128,17 +128,19 @@ func (i *imlProviderModelModule) DeleteProviderModel(ctx *gin.Context, provider
if err := i.providerModelService.Delete(ctx, id); err != nil {
return err
}
err = i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{
{
BasicItem: &gateway.BasicItem{
ID: fmt.Sprintf("%s#%s", provider, modelInfo.Name),
Resource: "ai-model",
if p.GetModelConfig().AccessConfigurationStatus {
err = i.syncGateway(ctx, cluster.DefaultClusterID, []*gateway.DynamicRelease{
{
BasicItem: &gateway.BasicItem{
ID: fmt.Sprintf("%s$%s", provider, modelInfo.Name),
Resource: "ai-model",
},
Attr: nil,
},
Attr: nil,
},
}, false)
if err != nil {
return err
}, false)
if err != nil {
return err
}
}
p.RemoveModel(id)
@@ -200,7 +202,9 @@ func (i *imlProviderModelModule) AddProviderModel(ctx *gin.Context, provider str
}
func newModel(provider string, model string, config string) *gateway.DynamicRelease {
if config == "" {
config = "{}"
}
return &gateway.DynamicRelease{
BasicItem: &gateway.BasicItem{
ID: fmt.Sprintf("%s$%s", provider, model),
+38 -26
View File
@@ -185,6 +185,41 @@ func (i *imlPublishModule) getProjectRelease(ctx context.Context, projectID stri
Id: projectID,
Version: version,
}
upstreamProxyHeaders := make([]*gateway.ProxyHeader, 0)
var upstreamRelease *gateway.UpstreamRelease
if len(upstreamCommitIds) > 0 {
upstreamCommits, err := i.upstreamService.ListCommit(ctx, upstreamCommitIds...)
if err != nil {
return nil, err
}
for _, c := range upstreamCommits {
upstreamRelease = &gateway.UpstreamRelease{
BasicItem: &gateway.BasicItem{
ID: c.Target,
Version: version,
MatchLabels: map[string]string{
"serviceId": projectID,
},
},
PassHost: c.Data.PassHost,
Scheme: c.Data.Scheme,
Balance: c.Data.Balance,
Timeout: c.Data.Timeout,
Nodes: utils.SliceToSlice(c.Data.Nodes, func(n *upstream.NodeConfig) string {
return fmt.Sprintf("%s weight=%d", n.Address, n.Weight)
}),
}
upstreamProxyHeaders = utils.SliceToSlice(c.Data.ProxyHeaders, func(n *upstream.ProxyHeader) *gateway.ProxyHeader {
return &gateway.ProxyHeader{
Key: n.Key,
Value: n.Value,
Opt: n.OptType,
}
})
}
r.Upstream = upstreamRelease
}
apis := make([]*gateway.ApiRelease, 0, len(apiInfos))
hasUpstream := len(upstreamCommitIds) > 0
for _, a := range apiInfos {
@@ -221,38 +256,15 @@ func (i *imlPublishModule) getProjectRelease(ctx context.Context, projectID stri
Opt: h.OptType,
}
})
apiInfo.ProxyHeaders = append(apiInfo.ProxyHeaders, upstreamProxyHeaders...)
apiInfo.Retry = proxy.Retry
apiInfo.Timeout = proxy.Timeout
}
apis = append(apis, apiInfo)
}
r.Apis = apis
var upstreamRelease *gateway.UpstreamRelease
if len(upstreamCommitIds) > 0 {
upstreamCommits, err := i.upstreamService.ListCommit(ctx, upstreamCommitIds...)
if err != nil {
return nil, err
}
for _, c := range upstreamCommits {
upstreamRelease = &gateway.UpstreamRelease{
BasicItem: &gateway.BasicItem{
ID: c.Target,
Version: version,
MatchLabels: map[string]string{
"serviceId": projectID,
},
},
PassHost: c.Data.PassHost,
Scheme: c.Data.Scheme,
Balance: c.Data.Balance,
Timeout: c.Data.Timeout,
Nodes: utils.SliceToSlice(c.Data.Nodes, func(n *upstream.NodeConfig) string {
return fmt.Sprintf("%s weight=%d", n.Address, n.Weight)
}),
}
}
r.Upstream = upstreamRelease
}
if len(strategyCommitIds) > 0 {
strategyCommits, err := i.strategyService.ListStrategyCommit(ctx, strategyCommitIds...)
if err != nil {
+5 -1
View File
@@ -236,6 +236,10 @@ func (i *imlServiceModule) AILogs(ctx context.Context, serviceId string, start i
return nil, 0, err
}
return utils.SliceToSlice(list, func(s *log_service.Item) *service_dto.AILogItem {
var tokenPerSecond int64 = 0
if s.ResponseTime > 0 {
tokenPerSecond = s.TotalToken * 1000 / s.ResponseTime
}
item := &service_dto.AILogItem{
Id: s.ID,
API: auto.UUID(s.API),
@@ -243,7 +247,7 @@ func (i *imlServiceModule) AILogs(ctx context.Context, serviceId string, start i
LogTime: auto.TimeLabel(s.RecordTime),
Ip: s.RemoteIP,
Token: s.TotalToken,
TokenPerSecond: s.TotalToken * 1000 / s.ResponseTime,
TokenPerSecond: tokenPerSecond,
Consumer: auto.UUID(s.Consumer),
Provider: auto.UUID(s.AIProvider),
Model: s.AIModel,
+10
View File
@@ -202,6 +202,16 @@ curl -sSO https://download.apipark.com/install/quick-start.sh; bash quick-start.
# 📕文档
访问 [APIPark文档](https://docs.apipark.com/docs/deploy) 获取详细的安装指南、API 参考和使用说明。
<br>
友情链接
<a href="https://xroute.ai/">
<img width="1248" height="158" alt="新建 PPTX 演示文稿 (2)_02(1)" src="https://github.com/user-attachments/assets/3e1cd0c1-c4c3-4f0c-8649-810d76f3166b" />
</a>
<br>
+1 -1
View File
@@ -22,7 +22,7 @@ echo "login qiniu..."
qshell account ${AccessKey} ${SecretKey} ${QINIU_NAME}
echo "qshell rput ${QINIU_BUCKET} \"${APP}/images/${Tar}\" ${Tar}"
qshell rput ${QINIU_BUCKET} "${APP}/images/${Tar}" ${Tar}
qshell rput --overwrite ${QINIU_BUCKET} "${APP}/images/${Tar}" ${Tar}
rm -f ${Tar}
docker rmi -f ${ImageName}:${Version}