feat(server): notify mcp-server billing_provider=newapi after Agnet user sync
Implements Heicode's choice (b) for §7.7.1 ②: in syncLocalUserFromAgnet,
fire-and-forget PUT mcp-server's internal /api/auth/internal/billing-provider
{email, billing_provider:"newapi"} so mcp-server's User table billing_provider
column lands as 'newapi' for users that came in via Heicode Manager (vs the
default 'litellm' for native taijiagent users).
- Goroutine: never blocks login on this side-effect; mcp-server endpoint is
idempotent so retries from repeat logins are harmless.
- Token via env MCP_SERVER_INTERNAL_TOKEN (K8s/compose secret); empty env
silently skips (dev-friendly).
- Reuses agnetHTTPClient + common.Marshal + common.GetUUID per repo
conventions.
Spec: docs/Heicode-对接进度与待办.md §7.8.1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,6 +174,61 @@ func fetchAgnetRefresh(baseURL, refreshToken string) (access string, refresh str
|
|||||||
return env.Data.Token, env.Data.RefreshToken, nil
|
return env.Data.Token, env.Data.RefreshToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// markBillingProviderNewapi notifies mcp-server that this user's billing
|
||||||
|
// provider should be set to "newapi" (per Heicode 决策 7.7.1 ②).
|
||||||
|
//
|
||||||
|
// Fire-and-forget: 失败不影响登录主流程;mcp-server 那边也允许重复调用
|
||||||
|
// (内部端点对相同 email 幂等)。详见 Heicode-对接进度与待办.md §7.8.1。
|
||||||
|
//
|
||||||
|
// Token 通过 K8s secret / docker compose env `MCP_SERVER_INTERNAL_TOKEN`
|
||||||
|
// 注入;未配置时跳过(开发环境兼容)。
|
||||||
|
func markBillingProviderNewapi(email string) {
|
||||||
|
tok := strings.TrimSpace(os.Getenv("MCP_SERVER_INTERNAL_TOKEN"))
|
||||||
|
if tok == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
email = strings.TrimSpace(email)
|
||||||
|
if email == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func(email, tok string) {
|
||||||
|
body, err := common.Marshal(map[string]string{
|
||||||
|
"email": email,
|
||||||
|
"billing_provider": "newapi",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
common.SysLog("markBillingProviderNewapi: marshal failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
baseURL := defaultHeicodeAuthBaseURL()
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
http.MethodPut,
|
||||||
|
baseURL+"/api/auth/internal/billing-provider",
|
||||||
|
strings.NewReader(string(body)),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
common.SysLog("markBillingProviderNewapi: req build failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tok)
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("X-Request-Id", common.GetUUID())
|
||||||
|
res, err := agnetHTTPClient().Do(req)
|
||||||
|
if err != nil {
|
||||||
|
common.SysLog("markBillingProviderNewapi: send failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode >= 400 {
|
||||||
|
b, _ := io.ReadAll(io.LimitReader(res.Body, 1<<14))
|
||||||
|
common.SysLog(fmt.Sprintf(
|
||||||
|
"markBillingProviderNewapi: %d %s — %s",
|
||||||
|
res.StatusCode, email, strings.TrimSpace(string(b)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}(email, tok)
|
||||||
|
}
|
||||||
|
|
||||||
func syncLocalUserFromAgnet(me agnetMeEnvelope) (*model.User, error) {
|
func syncLocalUserFromAgnet(me agnetMeEnvelope) (*model.User, error) {
|
||||||
email := strings.TrimSpace(me.Data.Email)
|
email := strings.TrimSpace(me.Data.Email)
|
||||||
if email == "" {
|
if email == "" {
|
||||||
@@ -242,6 +297,9 @@ func syncLocalUserFromAgnet(me agnetMeEnvelope) (*model.User, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify mcp-server billing_provider=newapi (fire-and-forget; goroutine).
|
||||||
|
markBillingProviderNewapi(user.Email)
|
||||||
|
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user