fix: normalize agnet runtime callbacks

This commit is contained in:
gongzhiyong
2026-05-28 20:33:38 +08:00
parent 61e060909d
commit 704579f03e
4 changed files with 83 additions and 10 deletions
+1 -1
View File
@@ -1 +1 @@
1.4.17 1.4.18
+11 -5
View File
@@ -164,13 +164,14 @@ func agnetCallbackDeploymentContext(deploymentID string, swarmID string) (agnetD
return record, true return record, true
} }
} }
if swarmID == "" { runtimeID := firstNonEmpty(swarmID, deploymentID)
if runtimeID == "" {
return agnetDeploymentRecord{}, false return agnetDeploymentRecord{}, false
} }
agnetMu.RLock() agnetMu.RLock()
for _, record := range agnetDeployments { for _, record := range agnetDeployments {
if strings.TrimSpace(record.RuntimeSwarmID) == swarmID { if strings.TrimSpace(record.RuntimeSwarmID) == runtimeID || strings.TrimSpace(record.RuntimeDeploymentID) == runtimeID {
agnetMu.RUnlock() agnetMu.RUnlock()
return record, true return record, true
} }
@@ -181,7 +182,7 @@ func agnetCallbackDeploymentContext(deploymentID string, swarmID string) (agnetD
return agnetDeploymentRecord{}, false return agnetDeploymentRecord{}, false
} }
var row model.AgnetDeployment var row model.AgnetDeployment
if err := model.DB.Where("runtime_swarm_id = ?", swarmID).First(&row).Error; err != nil { if err := model.DB.Where("runtime_swarm_id = ? OR runtime_deployment_id = ?", runtimeID, runtimeID).First(&row).Error; err != nil {
return agnetDeploymentRecord{}, false return agnetDeploymentRecord{}, false
} }
record, err := agnetDeploymentModelToRecord(row) record, err := agnetDeploymentModelToRecord(row)
@@ -553,9 +554,14 @@ func AgnetReceiveSwarmEventCallback(c *gin.Context) {
return return
} }
record, _ := agnetCallbackDeploymentContext(strings.TrimSpace(payload.DeploymentID), strings.TrimSpace(payload.SwarmID)) incomingDeploymentID := strings.TrimSpace(payload.DeploymentID)
if strings.TrimSpace(payload.DeploymentID) == "" && strings.TrimSpace(record.DeploymentID) != "" { incomingSwarmID := strings.TrimSpace(payload.SwarmID)
record, _ := agnetCallbackDeploymentContext(incomingDeploymentID, incomingSwarmID)
if strings.TrimSpace(record.DeploymentID) != "" {
payload.DeploymentID = record.DeploymentID payload.DeploymentID = record.DeploymentID
if strings.TrimSpace(payload.SwarmID) == "" {
payload.SwarmID = firstNonEmpty(record.RuntimeSwarmID, record.RuntimeDeploymentID, incomingDeploymentID)
}
} }
if payload.CorrelationID == "" { if payload.CorrelationID == "" {
payload.CorrelationID = record.Plan.Metadata.CorrelationID payload.CorrelationID = record.Plan.Metadata.CorrelationID
+7 -4
View File
@@ -48,10 +48,13 @@ type agnetUserContext struct {
} }
type agnetBillingContext struct { type agnetBillingContext struct {
Provider string `json:"provider"` Provider string `json:"provider"`
NewAPIUserRef string `json:"newapi_user_ref"` NewAPIUserRef string `json:"newapi_user_ref"`
NewAPIGroup string `json:"newapi_group"` NewAPIGroup string `json:"newapi_group"`
QuotaRef string `json:"quota_ref"` QuotaRef string `json:"quota_ref"`
DefaultModelID string `json:"default_model_id"`
AllowedModelIDs []string `json:"allowed_model_ids"`
SecretRef string `json:"secret_ref"`
} }
type agnetAgileContext struct { type agnetAgileContext struct {
@@ -1154,6 +1154,70 @@ func TestAgnetCallbackUsesSwarmIDFallbackAndCreatesApproval(t *testing.T) {
require.Equal(t, "azkv://heicode-kv.vault.azure.net/secrets/repo-main", approval.SecretRef) require.Equal(t, "azkv://heicode-kv.vault.azure.net/secrets/repo-main", approval.SecretRef)
} }
func TestAgnetCallbackUsesRuntimeDeploymentIDFallback(t *testing.T) {
db := setupAgnetControlPlaneTestDB(t)
resetAgnetControlPlaneState(t)
t.Setenv("AGNET_CALLBACK_TOKEN", "callback-token")
plan := baseAgnetResourceGrantPlan()
plan.UserContext.UserID = "7"
plan.BillingContext.DefaultModelID = "model-runtime-smoke"
plan.BillingContext.AllowedModelIDs = []string{"model-runtime-smoke", "model-runtime-fallback"}
plan.BillingContext.SecretRef = "azkv://heicode-kv.vault.azure.net/secrets/model-gateway-key"
for idx := range plan.Agents[0].ResourceGrants {
plan.Agents[0].ResourceGrants[idx].UserID = "7"
}
createRecorder, createEnvelope := postAgnetCreateUserDeployment(t, 7, plan)
require.True(t, createEnvelope.Success)
var createBody map[string]any
require.NoError(t, common.Unmarshal(createRecorder.Body.Bytes(), &createBody))
deploymentID := createBody["data"].(map[string]any)["deployment_id"].(string)
runtimeID := "swm-runtime-deployment-only-1"
require.NoError(t, db.Model(&model.AgnetDeployment{}).
Where("deployment_id = ?", deploymentID).
Updates(map[string]any{
"runtime_deployment_id": runtimeID,
"runtime_swarm_id": runtimeID,
}).Error)
resetAgnetControlPlaneState(t)
body := `{
"event_id":"evt-runtime-deployment-fallback",
"event_type":"timeline.updated",
"deployment_id":"swm-runtime-deployment-only-1",
"agent_instance_id":"agi-backend-runtime",
"occurred_at":"2026-05-28T12:30:00Z",
"payload":{
"title":"Runtime accepted",
"summary":"Agent Manager returned a runtime deployment id only",
"stage":"testing",
"checkpoint":"runtime_accepted"
}
}`
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.Request = httptest.NewRequest(http.MethodPost, "/api/agnet/callbacks/swarm-events", strings.NewReader(body))
ctx.Request.Header.Set("Content-Type", "application/json")
ctx.Request.Header.Set("X-Agnet-Service-Token", "callback-token")
AgnetReceiveSwarmEventCallback(ctx)
require.Equal(t, http.StatusOK, recorder.Code)
require.Contains(t, recorder.Body.String(), `"success":true`)
require.Contains(t, recorder.Body.String(), `"deployment_id":"`+deploymentID+`"`)
var callback model.AgnetCallbackEvent
require.NoError(t, db.Where("event_id = ?", "evt-runtime-deployment-fallback").First(&callback).Error)
require.Equal(t, deploymentID, callback.DeploymentID)
require.Equal(t, runtimeID, callback.SwarmID)
require.Equal(t, "7", callback.UserID)
var stored model.AgnetDeployment
require.NoError(t, db.Where("deployment_id = ?", deploymentID).First(&stored).Error)
require.Contains(t, stored.PlanJSON, `"default_model_id":"model-runtime-smoke"`)
require.Contains(t, stored.PlanJSON, `"allowed_model_ids":["model-runtime-smoke","model-runtime-fallback"]`)
require.Contains(t, stored.PlanJSON, `"secret_ref":"azkv://heicode-kv.vault.azure.net/secrets/model-gateway-key"`)
}
func TestAgnetCallbackRejectsPlaintextSecretsAndMissingToken(t *testing.T) { func TestAgnetCallbackRejectsPlaintextSecretsAndMissingToken(t *testing.T) {
setupAgnetControlPlaneTestDB(t) setupAgnetControlPlaneTestDB(t)
resetAgnetControlPlaneState(t) resetAgnetControlPlaneState(t)