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