promptsServiceImpl.ts ×11

Frontier kind: Code frontier

unlabeled · c_9d94c8f30d33

22 tests · 68776 LOC · 326 files · introduces 0 tests · 93 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
13 ranges93 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
6885 ranges68776 lines · 326 files · Browse complete extent
All tests (intent)
22 testsBrowse 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.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

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

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

src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts 86 introduced LOC · 11 ranges

Open complete file

446
447 public async getPromptSlashCommands(token: CancellationToken): Promise<readonly IChatPromptSlashCommand[]> {
448 > const discoveryInfo = await this.cachedSlashCommands.get(token); promptsServiceImpl.ts
449 > const result = this.slashCommandsFromDiscoveryInfo(discoveryInfo);
450 > return result;
451 > }
452
453 /**
455 */
456 private async computeSlashCommandDiscoveryInfo(token: CancellationToken): Promise<ISlashCommandDiscoveryInfo> {
457 > const stopWatch = StopWatch.create(true); promptsServiceImpl.ts
458 > const promptFiles = await this.listPromptFiles(PromptsType.prompt, token);
459 > const useAgentSkills = this.configurationService.getValue(PromptsConfig.USE_AGENT_SKILLS);
460 > const skills = useAgentSkills ? await this.listPromptFiles(PromptsType.skill, token) : [];
461 > const disabledSkills = this.getDisabledPromptFiles(PromptsType.skill);
462 > // Order skills by precedence before parsing so that the duplicate-name
463 > // dedup below keeps a deterministic winner (e.g. workspace over personal).
464 > const enabledSkills = skills
465 > .filter(s => !disabledSkills.has(s.uri))
466 > .sort((a, b) => this.getSkillPriority(a) - this.getSkillPriority(b));
467 > const slashCommandFiles = [
468 > ...promptFiles,
469 > ...enabledSkills,
470 > ];
471 >
472 > const parseResults = await Promise.all(slashCommandFiles.map(async promptPath => {
473 > try {
474 > const parsedPromptFile = await this.parseNew(promptPath.uri, token);
475 > let rawName: string;
476 > if (promptPath.type === PromptsType.skill) {
477 // For skills, always use the folder name as the canonical name
478 // (consistent with computeSkillDiscoveryInfo)
479 rawName = getSkillFolderName(promptPath.uri);
480 > } else { promptsServiceImpl.ts
481 rawName = parsedPromptFile?.header?.name ?? promptPath.name ?? getCleanPromptName(promptPath.uri);
482 }
483 > // For plugin resources, ensure the canonical plugin prefix is always preserved even when the promptsServiceImpl.ts
484 > // file's frontmatter overrides the name.
485 > const name = promptPath.source === PromptFileSource.Plugin && promptPath.pluginUri
486 ? getCanonicalPluginCommandId({ uri: promptPath.pluginUri, label: promptPath.pluginLabel }, rawName)
487 : rawName;
488 > const description = parsedPromptFile?.header?.description ?? promptPath.description; promptsServiceImpl.ts
489 > const argumentHint = parsedPromptFile?.header?.argumentHint;
490 > const userInvocable = parsedPromptFile?.header?.userInvocable;
491 > return { status: 'loaded', promptPath: this.withPromptPathMetadata(promptPath, name, description), argumentHint, userInvocable } satisfies ISlashCommandDiscoveryResult;
492 > } catch (e) {
493 this.logger.error(`[computeSlashCommandDiscoveryInfo] Failed to parse prompt file for slash command: ${promptPath.uri}`, e instanceof Error ? e.message : String(e));
494 return { status: 'skipped', skipReason: 'parse-error', errorMessage: e instanceof Error ? e.message : String(e), promptPath } satisfies ISlashCommandDiscoveryResult;
495 }
497 >
498 > // Deduplicate skills that resolve to the same canonical name. This can
499 > // happen when two skill locations point at the same files, e.g. when
500 > // `~/.claude/skills` is a symlink to `~/.agents/skills` (created by
501 > // `npx skills`). Without this, every such skill would appear twice in
502 > // the `/` menu. `parseResults` preserves input order, so skills are
503 > // already sorted by precedence; the first occurrence of a name wins.
504 > const seenSkillNames = new Set<string>();
505 > const files: ISlashCommandDiscoveryResult[] = [];
506 > for (const result of parseResults) {
507 > if (result.status === 'loaded' && result.promptPath.type === PromptsType.skill) {
508 const name = result.promptPath.name;
509 if (name !== undefined) {
515 }
516 }
517 > files.push(result); promptsServiceImpl.ts
518 > }
519 >
520 > const promptSourceFolders = await this._collectSourceFolderDiagnostics(PromptsType.prompt);
521 > const sourceFolders = [...promptSourceFolders];
522 >
523 > if (useAgentSkills) {
524 const skillSourceFolders = await this._collectSourceFolderDiagnostics(PromptsType.skill);
525 sourceFolders.push(...skillSourceFolders);
526 }
527 > return { type: PromptsType.prompt, files, sourceFolders, durationInMillis: stopWatch.elapsed() }; promptsServiceImpl.ts
528 > }
529
530 /**
532 */
533 private slashCommandsFromDiscoveryInfo(discoveryInfo: ISlashCommandDiscoveryInfo): readonly IChatPromptSlashCommand[] {
534 > const result: IChatPromptSlashCommand[] = []; promptsServiceImpl.ts
535 > const seen = new ResourceSet();
536 >
537 > for (const file of discoveryInfo.files) {
538 > if (file.status === 'loaded') {
539 > result.push(this.asChatPromptSlashCommand(file.argumentHint, file.userInvocable, file.promptPath));
540 > seen.add(file.promptPath.uri);
541 > }
542 > }
543 >
544 > // Include untitled prompt models not covered by discovery
545 > for (const model of this.modelService.getModels()) {
546 if (model.getLanguageId() === PROMPT_LANGUAGE_ID && model.uri.scheme === Schemas.untitled && !seen.has(model.uri)) {
547 const parsedPromptFile = this.getParsedPromptFile(model);
551 }
552 }
554 > return result;
555 > }
556
557 public isValidSlashCommandName(command: string): boolean {
592
593 private asChatPromptSlashCommand(argumentHint: string | undefined, userInvocable: boolean | undefined, promptPath: IPromptPath): IChatPromptSlashCommand {
594 > let name = promptPath.name ?? getCleanPromptName(promptPath.uri); promptsServiceImpl.ts
595 > name = name.replace(/[^\p{L}\d_\-\.:]+/gu, '-'); // replace spaces with dashes
596 > return {
597 > uri: promptPath.uri,
598 > name: name,
599 > source: promptPath.source,
600 > storage: promptPath.storage,
601 > type: promptPath.type,
602 > extension: promptPath.extension,
603 > pluginUri: promptPath.pluginUri,
604 > pluginLabel: promptPath.pluginLabel,
605 > description: promptPath.description,
606 > argumentHint: argumentHint,
607 > userInvocable: userInvocable ?? true,
608 > sessionTypes: promptPath.sessionTypes,
609 > };
610 > }
611
612 public async getPromptSlashCommandName(uri: URI, token: CancellationToken): Promise<string> {
src/vs/editor/common/services/modelService.ts 7 introduced LOC · 2 ranges

Open complete file

462
463 public getModels(): ITextModel[] {
464 > const ret: ITextModel[] = []; modelService.ts
465 >
466 > const keys = Object.keys(this._models);
467 > for (let i = 0, len = keys.length; i < len; i++) {
468 const modelId = keys[i];
469 ret.push(this._models[modelId].model);
470 }
472 > return ret;
473 > }
474
475 public getModel(resource: URI): ITextModel | null {