跳转至

Deep Dive | src/utils/plugins/marketplaceManager.ts 2643 行 — 插件市场管理

重要性:⭐⭐⭐(plugin 分发生态——marketplace 加载、缓存、刷新、自动更新) 真实位置src/utils/plugins/marketplaceManager.ts2643 行角色:管理所有已注册的 plugin marketplace(git / URL / seed),缓存 marketplace manifest,支持手动 / 自动刷新 关联topics/deep-dive-plugin-loader.md(plugin 加载)、topics/deep-dive-manage-plugins.md(管理 UI)


1. 文件全景

marketplaceManager.ts (2643 行)
├── 行 1-200   :imports + 2 个 type + 5 个 helper
│   ├── LoadedPluginMarketplace type (行 93)
│   ├── getKnownMarketplacesFile / getMarketplacesCacheDir (行 102, 110)
│   ├── clearMarketplacesCache (行 122)
│   ├── KnownMarketplacesConfig type (行 129)
│   ├── DeclaredMarketplace type (行 138)
│   ├── getDeclaredMarketplaces (行 161)
│   └── getMarketplaceDeclaringSource (行 200)
├── 行 220-380 :settings 持久化
│   ├── saveMarketplaceToSettings (行 226)
│   ├── loadKnownMarketplacesConfig (行 264)
│   ├── loadKnownMarketplacesConfigSafe (行 309)
│   └── saveKnownMarketplacesConfig (行 327)
├── 行 380-510 :seed marketplace
│   ├── registerSeedMarketplaces (行 380, ~55 行)
│   ├── readSeedKnownMarketplaces (行 436)
│   ├── findSeedMarketplaceLocation (行 473)
│   └── seedDirFor (行 496)
├── 行 510-800 :git 操作
│   ├── GIT_NO_PROMPT_ENV (行 510)
│   ├── DEFAULT_PLUGIN_GIT_TIMEOUT_MS (120s, 行 515)
│   ├── getPluginGitTimeoutMs (行 517)
│   ├── gitPull (行 528, ~80 行)
│   ├── gitSubmoduleUpdate (行 609, ~40 行)
│   ├── enhanceGitPullErrorMessages (行 649, ~75 行)
│   ├── isGitHubSshLikelyConfigured (行 723, ~45 行)
│   ├── isAuthenticationError (行 767, ~15 行)
│   ├── extractSshHost (行 781, ~22 行)
│   └── gitClone (行 803, ~195 行)
├── 行 998-1080:进度回调
│   ├── MarketplaceProgressCallback type (行 998)
│   ├── safeCallProgress (行 1007)
│   └── reconcileSparseCheckout (行 1034, ~50 行)
├── 行 1084-1370:cache
│   ├── cacheMarketplaceFromGit (行 1084, ~100 行)
│   ├── redactHeaders (行 1186)
│   ├── redactUrlCredentials (行 1213, ~42 行)
│   ├── cacheMarketplaceFromUrl (行 1256, ~100 行)
│   └── getCachePathForSource (行 1355)
├── 行 1372-1780:parseFileWithSchema (行 1372, ~60 行) + loadAndCacheMarketplace (行 1433, ~350 行)
├── 行 1782-2058:增删
│   ├── addMarketplaceSource (行 1782, ~155 行)
│   └── removeMarketplaceSource (行 1937, ~120 行)
├── 行 2058-2238:读
│   ├── readCachedMarketplace (行 2058)
│   ├── getMarketplaceCacheOnly (行 2081, ~40 行)
│   ├── getMarketplace (memoize, 行 2122, ~65 行)
│   ├── getPluginByIdCacheOnly (行 2188, ~50 行)
│   └── getPluginById (行 2238, ~58 行)
├── 行 2296-2640:刷新
│   ├── refreshAllMarketplaces (行 2296, ~70 行)
│   ├── refreshMarketplace (行 2365, ~220 行)
│   └── setMarketplaceAutoUpdate (行 2587, ~55 行)
└── 行 2641-2643:_test (export for testing)

2. 2 个核心 Type

type LoadedPluginMarketplace = { ... }  // 加载后的 marketplace
type DeclaredMarketplace = { ... }      // 用户声明的 marketplace

3. 5 个核心 Helper

function getKnownMarketplacesFile(): string { ... }   // 配置路径
export function getMarketplacesCacheDir(): string { ... }  // 缓存目录
export function clearMarketplacesCache(): void { ... }  // 清缓存

export function getDeclaredMarketplaces(): Record<string, DeclaredMarketplace> { ... }
export function getMarketplaceDeclaringSource(name: string): ... { ... }

5 个 helper——获取配置、缓存、来源。


4. Settings 持久化(4 个函数)

saveMarketplaceToSettings(name, marketplace)  // 写到 user/project
loadKnownMarketplacesConfig()                  // 从多源读
loadKnownMarketplacesConfigSafe()              // safe 版本(不抛)
saveKnownMarketplacesConfig()                  // 保存

4 个函数——配置增删改查。


5. Seed Marketplace(4 个函数)

registerSeedMarketplaces()           // 注册内置 seed
readSeedKnownMarketplaces()          // 读 seed 配置
findSeedMarketplaceLocation()        // 找 seed 路径
seedDirFor()                         // seed 目录

4 个函数——Anthropic 预装的 marketplace(类似 npm 的官方源)。


6. Git 操作(9 个函数)

6.1 gitPull — 80 行(行 528)

export async function gitPull(repoDir: string, ...): Promise<...> {
  // 1. 检查 git 可用
  // 2. 设置 env (no prompt)
  // 3. git pull
  // 4. 处理错误
  // 5. 增强错误信息
}

6.2 gitClone — 195 行(行 803)

export async function gitClone(url, dest, ...): Promise<...> {
  // 1. 选 transport (HTTPS/SSH)
  // 2. 处理 SSH config
  // 3. 设置 timeout
  // 4. git clone
  // 5. 处理错误
}

195 行反映 git clone 的复杂(auth/SSH/HTTPS/proxy)。

6.3 enhanceGitPullErrorMessages — 75 行(行 649)

function enhanceGitPullErrorMessages(result: { ... }): ... {
  // 把 git stderr 转成友好错误
}

错误信息美化——给用户可读的错误提示。

6.4 isGitHubSshLikelyConfigured — 45 行(行 723)

async function isGitHubSshLikelyConfigured(): Promise<boolean> {
  // 检查 ssh -T git@github.com 是否成功
}

GitHub SSH 检测——避免 ssh auth 失败时给出无意义错误。

6.5 extractSshHost + isAuthenticationError

2 个 helper——解析 SSH host、识别 auth 错误。

6.6 gitSubmoduleUpdate — 40 行

submodule 支持——marketplace 可能用 git submodule。


7. reconcileSparseCheckout — 50 行(行 1034)

export async function reconcileSparseCheckout(...): Promise<...> {
  // 同步 sparse-checkout 配置
}

Sparse checkout——只 checkout marketplace 需要的目录。


8. Cache(4 个函数)

cacheMarketplaceFromGit()  // 从 git 缓存 (~100 行)
redactHeaders()             // 移除敏感 header
redactUrlCredentials()      // URL 去凭证
cacheMarketplaceFromUrl()   // 从 URL 缓存 (~100 行)
getCachePathForSource()     // cache 路径

4 个 cache 函数——marketplace manifest 缓存到本地。

8.1 redactUrlCredentials — 42 行(行 1213)

function redactUrlCredentials(urlString: string): string {
  // https://user:pass@github.com → https://***:***@github.com
}

凭证脱敏——错误信息中不暴露用户密码。


9. loadAndCacheMarketplace — 350 行(行 1433)

async function loadAndCacheMarketplace(source: MarketplaceSource, ...): Promise<LoadedPluginMarketplace> {
  // 1. 选择 source 类型 (git/url)
  // 2. cache
  // 3. 解析 manifest
  // 4. 校验
}

350 行——加载并缓存 marketplace。


10. 增删(2 个函数)

10.1 addMarketplaceSource — 155 行(行 1782)

export async function addMarketplaceSource(name: string, source: MarketplaceSource): Promise<...> {
  // 1. 校验 name
  // 2. clone / fetch
  // 3. 解析 manifest
  // 4. 写到 settings
}

10.2 removeMarketplaceSource — 120 行(行 1937)

export async function removeMarketplaceSource(name: string): Promise<void> {
  // 1. 从 settings 删除
  // 2. 清理 cache
}

11. 读(5 个函数)

readCachedMarketplace()       // 读 cache
getMarketplaceCacheOnly()     // 只读 cache
getMarketplace (memoize)      // cache 优先,miss 时拉
getPluginByIdCacheOnly()      // 找单 plugin (cache only)
getPluginById()               // 找单 plugin

5 个读 API——cache-only 和 full 分离。


12. 刷新(2 个函数)

12.1 refreshAllMarketplaces — 70 行(行 2296)

export async function refreshAllMarketplaces(): Promise<void> {
  // 1. 遍历所有 marketplaces
  // 2. 并行 refresh
  // 3. 错误聚合
}

12.2 refreshMarketplace — 220 行(行 2365)

export async function refreshMarketplace(name: string, ...): Promise<...> {
  // 1. git pull
  // 2. 重新解析
  // 3. 写 cache
}

220 行——单 marketplace 完整刷新。


13. setMarketplaceAutoUpdate — 55 行(行 2587)

export async function setMarketplaceAutoUpdate(name: string, enabled: boolean): Promise<void> {
  // 开关自动更新
}

auto update 开关——某些 marketplace 支持 auto-refresh。


14. _test 导出

export const _test = { ... }

测试导出——单元测试可访问内部。


15. 关键设计模式

15.1 多源 Marketplace

  • Seed(内置)
  • Git(git URL)
  • HTTPS URL(任意 URL)
  • Local(本地路径)

4 种源 统一抽象。

15.2 缓存分层

  • readCachedMarketplace —— 读 cache
  • getMarketplaceCacheOnly —— 只 cache
  • getMarketplace (memoize) —— cache 优先,miss 拉

3 层

15.3 凭证脱敏

redactUrlCredentials —— 错误信息不暴露密码。

15.4 SSH 智能检测

isGitHubSshLikelyConfigured —— 提前发现 SSH 配置问题。

15.5 错误信息增强

enhanceGitPullErrorMessages —— 把"fatal: could not read"变成"check your SSH keys"。

15.6 Sparse checkout 优化

reconcileSparseCheckout —— monorepo 只 checkout 需要的部分。

15.7 安全 git 操作

GIT_NO_PROMPT_ENV —— git 不提示输入(避免挂起)。

DEFAULT_PLUGIN_GIT_TIMEOUT_MS = 120s —— 超时兜底。


16. 复杂度分析

维度 数字
总行数 2643
类型 2
公开函数 15+
Git 函数 9
Cache 函数 4
读 API 5

17. 性能特征

17.1 加载

  • 缓存命中:< 50ms
  • Git pull:~500ms-2s(取决于网络)
  • HTTPS URL:~200ms-2s
  • 全 marketplace 刷新(10 个):~3-10s(并行)

17.2 内存

每个 LoadedPluginMarketplace ~10-100KB。


18. 与其他文件的关系

marketplaceManager.ts
  ├──→ git subprocess
  ├──→ HTTP fetch
  ├──→ settings.json
  ├──→ pluginLoader.ts (消费)
  └──→ ManagePlugins.tsx (UI)

19. 关键洞察

19.1 Git 操作的复杂度

gitClone 195 行 —— 真实工程中 git 集成非常复杂(auth/SSH/HTTPS/proxy/sparse/timeout)。

19.2 凭证脱敏是"安全细节"

redactUrlCredentials —— 错误信息保护用户密码。

19.3 错误信息增强 = "UX 细节"

enhanceGitPullErrorMessages —— 把"fatal error"变成可读建议。

19.4 3 层 cache 设计

  • readCached
  • getCacheOnly
  • getMarketplace (memoize)

层层 fallback

19.5 SSH 检测避免"试错"

isGitHubSshLikelyConfigured —— 提前告诉用户"先配 SSH"。

19.6 120s git timeout

DEFAULT_PLUGIN_GIT_TIMEOUT_MS = 120s —— 防止挂死。

19.7 _test 导出

明确暴露内部 API 给测试 —— 测试友好


20. 阅读建议

  1. 看 2 个 type(行 93, 138)—— 数据模型
  2. 看 4 个 settings 函数(行 220-380)—— 持久化
  3. 看 gitPull + gitClone(行 528, 803)—— git 核心
  4. 看 cache 函数(行 1084-1370)—— 缓存
  5. 看 addMarketplaceSource(行 1782)—— 添加流程
  6. 看 refreshMarketplace(行 2365)—— 刷新流程

21. 与其他深度拆解的关系

文件 关系
pluginLoader.ts 消费 marketplace
ManagePlugins.tsx UI
settings.json 持久化

22. 阅读清单

  1. ✅ 看 2 个 type(行 93, 138)
  2. ✅ 看 4 个 settings 函数(行 220-380)
  3. ✅ 看 gitPull + gitClone(行 528, 803)
  4. ✅ 看 addMarketplaceSource(行 1782)
  5. ✅ 看 refreshMarketplace(行 2365)
  6. 📌 对照 topics/deep-dive-plugin-loader.md
  7. 📌 对照 topics/deep-dive-manage-plugins.md

23. 练习任务

  1. 数 git 函数(grep)—— 9 个
  2. 数 cache 函数(grep)—— 4 个
  3. 画 marketplace 加载流程 —— source → cache → loadAndCache → LoadedPluginMarketplace
  4. 手写迷你 git pull(~30 行)—— 用 simple-git
  5. 思考:marketplace 系统的"安全"应该在哪一层做?