mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-10-05 23:31:05 +08:00
refactor(devin): deduplicate auth credentials extraction, filter sparse tool calls, and optimize model lookup
This commit is contained in:
@@ -62,7 +62,15 @@ func LookupDevinModel(modelID string) *ModelInfo {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, m := range GetDevinModels() {
|
||||
devinCatalogStore.mu.RLock()
|
||||
models := devinCatalogStore.models
|
||||
devinCatalogStore.mu.RUnlock()
|
||||
|
||||
if len(models) == 0 {
|
||||
models = GetDevinModels()
|
||||
}
|
||||
|
||||
for _, m := range models {
|
||||
mClean := strings.ToLower(strings.TrimPrefix(m.ID, "devin/"))
|
||||
if mClean == clean {
|
||||
return cloneModelInfo(m)
|
||||
|
||||
@@ -144,38 +144,15 @@ func (e *DevinExecutor) Refresh(ctx context.Context, auth *cliproxyauth.Auth) (*
|
||||
return nil, errors.New("devin executor: auth is nil")
|
||||
}
|
||||
|
||||
sessionToken := strings.TrimSpace(auth.Attributes["api_key"])
|
||||
if sessionToken == "" {
|
||||
sessionToken = strings.TrimSpace(auth.Attributes["session_token"])
|
||||
}
|
||||
if sessionToken == "" && auth.Metadata != nil {
|
||||
if v, ok := auth.Metadata["api_key"].(string); ok {
|
||||
sessionToken = strings.TrimSpace(v)
|
||||
}
|
||||
if sessionToken == "" {
|
||||
if v, ok := auth.Metadata["session_token"].(string); ok {
|
||||
sessionToken = strings.TrimSpace(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
sessionToken, baseURL, deviceSeed := devinAuthCredentials(auth)
|
||||
if sessionToken == "" {
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
httpClient := helps.NewDevinHTTPClient(ctx, e.cfg, auth, 30*time.Second)
|
||||
authService := devinauth.NewDevinAuthService(httpClient)
|
||||
if baseURL := strings.TrimSpace(auth.Attributes["base_url"]); baseURL != "" {
|
||||
if baseURL != "" {
|
||||
authService.SetServerBaseURL(baseURL)
|
||||
} else if auth.Metadata != nil {
|
||||
if v, ok := auth.Metadata["base_url"].(string); ok && strings.TrimSpace(v) != "" {
|
||||
authService.SetServerBaseURL(v)
|
||||
}
|
||||
}
|
||||
deviceSeed := strings.TrimSpace(auth.Attributes["device_seed"])
|
||||
if deviceSeed == "" && auth.Metadata != nil {
|
||||
if v, ok := auth.Metadata["device_seed"].(string); ok {
|
||||
deviceSeed = strings.TrimSpace(v)
|
||||
}
|
||||
}
|
||||
|
||||
status, err := authService.FetchUserStatus(ctx, sessionToken, deviceSeed)
|
||||
@@ -784,7 +761,9 @@ func (e *DevinExecutor) streamDevinFrames(
|
||||
completedEvent, _ = sjson.SetBytes(completedEvent, "interaction.usage.total_cached_tokens", finalUsage.CachedTokens)
|
||||
completedEvent, _ = sjson.SetBytes(completedEvent, "interaction.usage.total_tokens", totalTokens)
|
||||
if detail, ok := helps.ParseInteractionsStreamUsage(completedEvent); ok {
|
||||
reporter.Publish(ctx, detail)
|
||||
if reporter != nil {
|
||||
reporter.Publish(ctx, detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = emitInteractionsEvent(completedEvent)
|
||||
@@ -846,13 +825,20 @@ func consumeDevinFramesToInteractions(body io.Reader, model, chatModelUID string
|
||||
if len(toolBuilders) == 0 {
|
||||
return nil
|
||||
}
|
||||
res := make([]helps.DevinToolCall, len(toolBuilders))
|
||||
res := make([]helps.DevinToolCall, 0, len(toolBuilders))
|
||||
for i := range toolBuilders {
|
||||
res[i] = helps.DevinToolCall{
|
||||
if toolBuilders[i] == nil {
|
||||
continue
|
||||
}
|
||||
// Skip unpopulated sparse placeholders
|
||||
if toolBuilders[i].id == "" && toolBuilders[i].name == "" && toolBuilders[i].args.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
res = append(res, helps.DevinToolCall{
|
||||
ID: toolBuilders[i].id,
|
||||
Name: toolBuilders[i].name,
|
||||
Arguments: toolBuilders[i].args.String(),
|
||||
}
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -447,6 +447,9 @@ func BuildDevinGetChatMessageRequest(
|
||||
tBytes = protowire.AppendString(tBytes, tool.Name)
|
||||
}
|
||||
desc := tool.Description
|
||||
// Claude Code subagent tool descriptions hardcode snake_case "task_id", but Devin's
|
||||
// upstream tool execution environment strictly expects camelCase "taskId". Normalizing
|
||||
// the prompt description prevents the model from generating incompatible parameter names.
|
||||
if strings.Contains(desc, "Takes a task_id parameter identifying the task") {
|
||||
desc = strings.ReplaceAll(desc, "Takes a task_id parameter identifying the task", "Takes a taskId parameter identifying the task")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user