refactor: complete backend rewrite for multi-protocol proxy

Major rewrite of the Go backend to support:
- Three API format imports: openai, anthropic, compatible
- Three protocol conversions: Chat Completions, Responses, Messages
- Hub-and-spoke architecture with Chat as intermediate format

Deleted:
- opencat.go (old entry)
- store/, team/, pkg/team/, pkg/store/ (old data layer)
- internal/model/, internal/consts/ (old types)
- internal/service/team/, internal/controller/team/ (old handlers)
- llm/ (removed LLM client library, pure proxy mode)
- dist/, assets/ (old build artifacts)

Added:
- internal/store/ — 9 GORM models + multi-DB support
- internal/pkg/ — crypto (AES-GCM), apikey, jwt, ratelimit, resp, tokenizer
- internal/channel/ — channel selection, weighted LB, health checks
- internal/proxy/convert/ — 6 protocol conversion functions + SSE streaming
- internal/proxy/ — gateway with request dispatch and upstream selection
- internal/usage/ — async usage recorder with batch writes
- internal/api/ — management API (auth, users, keys, channels, models)
- Makefile for build/test/deploy

Fixed API to match frontend expectations:
- Login response wraps token in { data: { token } }
- GET /api/profile route added
- Profile response wraps user in { code, data }
- Role returned as number (10=admin, 1=user)
This commit is contained in:
Sakurasan
2026-08-30 11:49:31 +08:00
parent aa0d87f132
commit ef3025dd80
127 changed files with 4623 additions and 10500 deletions
@@ -1,7 +1,7 @@
<template>
<!-- 组件根元素:相对定位,设置最大宽度、外边距、宽高比、背景渐变、内边距、圆角、阴影和溢出隐藏 -->
<div
class="relative w-full max-w-4xl mx-auto my-10 aspect-[4/3] backdrop-blur-0 px-4 py-0 my-0 rounded-lg overflow-hidden ">
class="relative w-full max-w-4xl mx-auto my-10 aspect-[16/10] sm:aspect-[4/3] backdrop-blur-0 rounded-lg overflow-hidden ">
<!-- bg-gradient-to-br from-slate-50 to-orange-50 -->
<!-- 中心图标容器 -->
<div ref="centerElement" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-20">
+5 -2
View File
@@ -47,7 +47,7 @@
{{ star }}
</span>
</a>
<RouterLink to="/dashboard" class="btn btn-primary btn-sm h-9 min-h-9 rounded-full px-4">
<RouterLink to="/dashboard" class="btn btn-primary btn-sm h-9 min-h-9 rounded-full px-3 sm:px-4 whitespace-nowrap">
Open Dashboard
</RouterLink>
</div>
@@ -60,7 +60,7 @@
<img src="@/assets/openteam.png" alt="OpenTeam project logo" width="160" height="160" class="h-28 w-auto select-none" fetchpriority="high" />
<h1 class="mt-4 text-4xl font-bold tracking-tight text-balance sm:text-5xl">OpenTeam</h1>
<p class="mt-4 max-w-2xl text-pretty text-lg text-base-content/70">
An open-source, team-shared service compatible with the OpenAI API — share LLM API usage across your team through a single endpoint.
One endpoint for every model. Route OpenAI-compatible clients to any LLM provider — share costs, track usage, stay in control.
</p>
<div class="tooltip mt-8 w-full max-w-xl" data-tip="Point your client at the OpenTeam base URL">
@@ -78,6 +78,9 @@
👉 Api-Keys:
<a href="https://platform.openai.com/account/api-keys" class="link link-hover link-primary">platform.openai.com/account/api-keys</a>
</p>
<p class="mt-3 text-sm text-base-content/60">
Connects to OpenAI, Claude, Gemini, DeepSeek and other OpenAI-compatible providers through a single endpoint.
</p>
</section>
<!-- How it works -->
+1 -1
View File
@@ -164,7 +164,7 @@
</button>
</div>
<div v-if="passkeys && passkeys.length" class="-mx-4 overflow-x-auto sm:-mx-6">
<div v-if="passkeys && passkeys.length" class="overflow-x-auto">
<table class="table table-sm">
<thead>
<tr class="text-xs uppercase tracking-wider text-base-content/50">
+1 -1
View File
@@ -25,7 +25,7 @@
</thead>
<tbody>
<tr v-for="token in user.tokens" :key="token.id" class="border-base-300/40 hover:bg-base-200/50">
<td class="pl-4 font-medium">{{ token.name }}</td>
<td class="pl-4 font-medium truncate max-w-[120px] sm:max-w-[180px]">{{ token.name }}</td>
<td>
<input type="checkbox" class="toggle toggle-success toggle-sm"
:class="!token.active && 'toggle-error'" v-model="token.active"
+2 -2
View File
@@ -144,8 +144,8 @@
<div class="card border border-base-300/60 bg-base-100 shadow-sm">
<div class="card-body p-4 sm:p-5">
<h3 class="card-title pb-1 text-base font-semibold">Tokens</h3>
<div v-if="user.tokens && user.tokens.length" class="-mx-4 overflow-x-auto sm:-mx-5">
<table class="table table-sm">
<div v-if="user.tokens && user.tokens.length" class="overflow-x-auto">
<table class="table table-sm min-w-[520px]">
<thead>
<tr class="text-xs uppercase tracking-wider text-base-content/50">
<th class="pl-4">Token Name</th>