MCPcopy
hub / github.com/claude-code-best/claude-code / verifyAndDemote

Function verifyAndDemote

src/utils/plugins/dependencyResolver.ts:177–234  ·  view source on GitHub ↗
(plugins: readonly LoadedPlugin[])

Source from the content-addressed store, hash-verified

175 * @returns Set of pluginIds to demote, plus errors for `/doctor`
176 */
177export function verifyAndDemote(plugins: readonly LoadedPlugin[]): {
178 demoted: Set<string>
179 errors: PluginError[]
180} {
181 const known = new Set(plugins.map(p => p.source))
182 const enabled = new Set(plugins.filter(p => p.enabled).map(p => p.source))
183 // Name-only indexes for bare deps from --plugin-dir (@inline) plugins:
184 // the real marketplace is unknown, so match "B" against any enabled "B@*".
185 // enabledByName is a multiset: if B@epic AND B@other are both enabled,
186 // demoting one mustn't make "B" disappear from the index.
187 const knownByName = new Set(
188 plugins.map(p => parsePluginIdentifier(p.source).name),
189 )
190 const enabledByName = new Map<string, number>()
191 for (const id of enabled) {
192 const n = parsePluginIdentifier(id).name
193 enabledByName.set(n, (enabledByName.get(n) ?? 0) + 1)
194 }
195 const errors: PluginError[] = []
196
197 let changed = true
198 while (changed) {
199 changed = false
200 for (const p of plugins) {
201 if (!enabled.has(p.source)) continue
202 for (const rawDep of p.manifest.dependencies ?? []) {
203 const dep = qualifyDependency(rawDep, p.source)
204 // Bare dep ← @inline plugin: match by name only (see enabledByName)
205 const isBare = !parsePluginIdentifier(dep).marketplace
206 const satisfied = isBare
207 ? (enabledByName.get(dep) ?? 0) > 0
208 : enabled.has(dep)
209 if (!satisfied) {
210 enabled.delete(p.source)
211 const count = enabledByName.get(p.name) ?? 0
212 if (count <= 1) enabledByName.delete(p.name)
213 else enabledByName.set(p.name, count - 1)
214 errors.push({
215 type: 'dependency-unsatisfied',
216 source: p.source,
217 plugin: p.name,
218 dependency: dep,
219 reason: (isBare ? knownByName.has(dep) : known.has(dep))
220 ? 'not-enabled'
221 : 'not-found',
222 })
223 changed = true
224 break
225 }
226 }
227 }
228 }
229
230 const demoted = new Set(
231 plugins.filter(p => p.enabled && !enabled.has(p.source)).map(p => p.source),
232 )
233 return { demoted, errors }
234}

Callers 1

assemblePluginLoadResultFunction · 0.85

Calls 7

parsePluginIdentifierFunction · 0.85
qualifyDependencyFunction · 0.85
setMethod · 0.80
getMethod · 0.65
deleteMethod · 0.65
hasMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected