pluginMarketplaceService.ts ×16

Frontier kind: Joint frontier

unlabeled · c_fda22d80cedb

1 test · 31195 LOC · 156 files · introduces 1 test · 85 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
18 ranges85 lines · 2 files
Tests
1 test

Contains — complete concept membership

All code (extent)
3324 ranges31195 lines · 156 files · Browse complete extent
All tests (intent)
1 testBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

1 test introduced at this concept.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 85 introduced LOC across 18 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/plugins/pluginMarketplaceService.ts 76 introduced LOC · 16 ranges

Open complete file

426
427 async fetchMarketplacePlugins(token: CancellationToken): Promise<IMarketplacePlugin[]> {
428 > if (!this._configurationService.getValue<boolean>(ChatConfiguration.PluginsEnabled)) { pluginMarketplaceService.ts
429 return [];
430 }
432 > // Effective set: user-facing `chat.plugins.marketplaces` (default + user)
433 > // unioned with the enterprise policy-only `chat.plugins.extraMarketplaces`.
434 > // `parseMarketplaceReferences` dedupes by canonical id.
435 > const { effectiveValues } = readConfiguredMarketplaces(this._configurationService);
436 > const configRefs = parseMarketplaceReferences(effectiveValues);
437 >
438 > // Merge marketplace references from Claude workspace settings.
439 > // Workspace-defined refs take precedence (are primary) so that their
440 > // displayLabel overrides any matching global marketplace entry.
441 > // Only include workspace-sourced refs when the workspace is trusted.
442 > let allRefs: IMarketplaceReference[];
443 > if (this._workspaceTrustService.isWorkspaceTrusted()) {
444 > const workspaceEntries = this._workspacePluginSettingsService.extraMarketplaces.get();
445 > allRefs = deduplicateMarketplaceReferences(workspaceEntries.map(e => e.reference), configRefs);
446 > } else {
447 allRefs = configRefs;
448 }
450 > for (const value of effectiveValues) {
451 > const parsed = typeof value === 'string'
452 > ? parseMarketplaceReference(value)
453 : (value && typeof value === 'object' ? parseMarketplaceObjectEntry(value as Parameters<typeof parseMarketplaceObjectEntry>[0]) : undefined);
454 > if (!parsed) { pluginMarketplaceService.ts
455 this._logService.debug(`[PluginMarketplaceService] Ignoring invalid marketplace entry: ${String(value)}`);
456 }
458 >
459 > const results = await Promise.all(
460 > allRefs.map(ref => {
461 > if (ref.kind === MarketplaceReferenceKind.GitHubShorthand && ref.githubRepo) {
462 > return this._fetchFromGitHubRepo(ref, ref.githubRepo, token);
463 > }
464 return this._fetchFromClonedRepo(ref, token);
466 > );
467 > const plugins = results.flat();
468 > this._lastFetchedPluginsStore.set({ plugins, fetchedAt: Date.now() }, undefined);
469 > return plugins;
470 > }
471
472 private async _fetchFromGitHubRepo(reference: IMarketplaceReference, repo: string, token: CancellationToken): Promise<IMarketplacePlugin[]> {
481 }));
482 }
484 > let repoMayBePrivate = true;
485 >
486 > const plugins = await this._readPluginsFromDefinitions(reference, async (defPath) => {
487 > if (token.isCancellationRequested) {
488 return undefined;
489 }
490 > const ref = encodeURIComponent(reference.ref ?? 'main'); pluginMarketplaceService.ts
491 > const url = `https://raw.githubusercontent.com/${repo}/${ref}/${defPath}`;
492 > try {
493 > const context = await this._requestService.request({ type: 'GET', url, callSite: 'pluginMarketplaceService.fetchPluginList' }, token);
494 > const statusCode = context.res.statusCode;
495 > if (statusCode !== 200) {
496 > repoMayBePrivate &&= statusCode !== undefined && statusCode >= 400 && statusCode < 500;
497 > this._logService.debug(`[PluginMarketplaceService] ${url} returned status ${statusCode}, skipping`);
498 > return undefined;
499 > }
500 return await asJson<IMarketplaceJson>(context) ?? undefined;
501 > } catch (err) { pluginMarketplaceService.ts
502 this._logService.debug(`[PluginMarketplaceService] Failed to fetch marketplace.json from ${url}:`, err);
503 return undefined;
504 }
506 >
507 > if (plugins.length > 0) {
508 cache.set(reference.canonicalId, {
509 plugins,
514 return plugins;
515 }
517 > if (repoMayBePrivate) {
518 this._logService.debug(`[PluginMarketplaceService] ${repo} may be private, attempting clone-based marketplace discovery`);
519 return this._fetchFromClonedRepo(reference, token);
520 }
522 > this._logService.debug(`[PluginMarketplaceService] No marketplace.json found in ${repo}`);
523 > return [];
524 }
525
527 const cached = cache.get(cacheKey);
528 if (!cached) {
529 > return undefined; pluginMarketplaceService.ts
530 > }
531
532 if (cached.expiresAt <= Date.now()) {
544 const stored = this._storageService.getObject<IStoredGitHubMarketplaceCache>(GITHUB_MARKETPLACE_CACHE_STORAGE_KEY, StorageScope.APPLICATION);
545 if (!stored) {
546 > return cache; pluginMarketplaceService.ts
547 > }
548
549 const revived = revive<IStoredGitHubMarketplaceCache>(stored);
946 */
947 private async _readPluginsFromDefinitions(
948 > reference: IMarketplaceReference, pluginMarketplaceService.ts
949 > readJson: (defPath: string) => Promise<IMarketplaceJson | undefined>,
950 > repoDir?: URI,
951 > ): Promise<IMarketplacePlugin[]> {
952 > for (const def of MARKETPLACE_DEFINITIONS) {
953 > const json = await readJson(def.path);
954 > if (!json?.plugins || !Array.isArray(json.plugins)) {
955 > continue;
956 > }
957 return this._parseMarketplacePlugins(json, reference, def.type, repoDir);
958 }
960 > this._logService.debug(`[PluginMarketplaceService] No marketplace.json found in ${reference.rawValue}`);
961 > return [];
962 > }
963 }
964
src/vs/workbench/contrib/chat/common/plugins/marketplaceReference.ts 9 introduced LOC · 2 ranges

Open complete file

150 */
151 export function deduplicateMarketplaceReferences(primary: readonly IMarketplaceReference[], secondary: readonly IMarketplaceReference[]): IMarketplaceReference[] {
152 > const byCanonicalId = new Map<string, IMarketplaceReference>(); marketplaceReference.ts
153 > for (const ref of primary) {
154 byCanonicalId.set(ref.canonicalId, ref);
155 }
156 > for (const ref of secondary) { marketplaceReference.ts
157 > if (!byCanonicalId.has(ref.canonicalId)) {
158 > byCanonicalId.set(ref.canonicalId, ref);
159 > }
160 > }
161 > return [...byCanonicalId.values()];
162 > }
163
164 export function parseMarketplaceReference(value: string): IMarketplaceReference | undefined {