返回 DeepSeek-Reasonix
known_overrides.go
根目录 / internal / plugin / known_overrides.go
1 package plugin
2
3 import (
4 "maps"
5 "path/filepath"
6 "slices"
7 "strings"
8 )
9
10 const (
11 codeGraphDaemonIdleTimeoutEnv = "CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS"
12 // Keep CodeGraph's shared daemon enabled, but do not leave it holding
13 // watchers for the upstream default 300s after the last MCP client exits.
14 codeGraphDaemonIdleTimeoutDefaultMS = "5000"
15 )
16
17 // ApplyKnownOverrides fills compatibility hints for known MCP servers. These
18 // are runtime-only adjustments; they do not make a server built-in or change
19 // startup behavior.
20 func ApplyKnownOverrides(s Spec, workspaceRoot string) Spec {
21 if isCodeGraphSpecName(s.Name) {
22 if isStdioSpecType(s.Type) {
23 if s.Dir == "" {
24 s.Dir = strings.TrimSpace(workspaceRoot)
25 }
26 s.Env = mergeDefaultEnv(s.Env, codeGraphDaemonIdleTimeoutEnv, codeGraphDaemonIdleTimeoutDefaultMS)
27 }
28 // CodeGraph does full-tree indexing + file-watching; run it below normal
29 // scheduling priority so a background indexer can never starve the user's
30 // machine (#3797, #2992). The proc-level mechanism already exists but was
31 // never wired to the spec, so it stayed disabled.
32 s.LowPriority = true
33 }
34 if isCodebaseMemorySpec(s) {
35 if isStdioSpecType(s.Type) && s.Dir == "" {
36 s.Dir = strings.TrimSpace(workspaceRoot)
37 }
38 // codebase-memory-mcp detects the session root from its subprocess cwd
39 // during initialize, then optionally starts its own auto-index thread.
40 // Its initial full-tree indexing can be CPU-heavy; keep it out of the
41 // foreground scheduling lane just like CodeGraph.
42 s.LowPriority = true
43 }
44 return s
45 }
46
47 func isCodeGraphSpecName(name string) bool {
48 return strings.EqualFold(strings.TrimSpace(name), "codegraph")
49 }
50
51 func isCodebaseMemorySpec(s Spec) bool {
52 if isCodebaseMemoryID(s.Name) || isCodebaseMemoryCommand(s.Command) {
53 return true
54 }
55 return slices.ContainsFunc(s.Args, isCodebaseMemoryID)
56 }
57
58 func isCodebaseMemoryCommand(command string) bool {
59 command = strings.TrimSpace(command)
60 if command == "" {
61 return false
62 }
63 command = strings.ReplaceAll(command, `\`, `/`)
64 return isCodebaseMemoryID(filepath.Base(command))
65 }
66
67 func isCodebaseMemoryID(raw string) bool {
68 id := strings.ToLower(strings.TrimSpace(raw))
69 id = strings.TrimSuffix(id, ".exe")
70 id = strings.TrimPrefix(id, "io.github.deusdata/")
71 if strings.HasPrefix(id, "codebase-memory-mcp@") {
72 return true
73 }
74 switch id {
75 case "codebase-memory-mcp", "codebase-memory":
76 return true
77 default:
78 return false
79 }
80 }
81
82 func isStdioSpecType(typ string) bool {
83 typ = strings.ToLower(strings.TrimSpace(typ))
84 return typ == "" || typ == "stdio"
85 }
86
87 func mergeDefaultEnv(existing map[string]string, key, value string) map[string]string {
88 out := make(map[string]string, len(existing))
89 maps.Copy(out, existing)
90 if _, ok := out[key]; !ok {
91 out[key] = value
92 }
93 return out
94 }
95
95 lines GO