import { IObservable } from "../../../../base/common/observable.js"; import { IDisposable } from "../../../../base/common/lifecycle.js"; import { Event } from "../../../../base/common/event.js"; import { ThemeIcon } from "../../../../base/common/themables.js"; import { URI } from "../../../../base/common/uri.js"; import { IStorageSourceFilter } from "./aiCustomizationWorkspaceService.js"; import { PromptsType } from "./promptSyntax/promptTypes.js"; import { CancellationToken } from "../../../../base/common/cancellation.js"; import { ICustomizationHarnessService } from "./customizationHarnessService.service.js"; /** * Override for a management section's create-button behavior. */ export interface ISectionOverride { /** * Label for the primary button. Required when `commandId` or `rootFile` * is set. Ignored otherwise (the widget uses its default label). */ readonly label?: string; /** When set, the primary button invokes this command (e.g. hooks quick pick). */ readonly commandId?: string; /** When set, the primary button creates this file at the workspace root. */ readonly rootFile?: string; /** * Custom type label for the dropdown workspace/user create actions * (e.g. "Rule" instead of "Instruction"). When undefined, the * section's default type label is used. */ readonly typeLabel?: string; /** * Root-level file shortcuts added to the dropdown (e.g. `['AGENTS.md']`). * Each entry creates a "New {filename}" action that creates the file at * the workspace root. Harnesses that don't support a file simply omit it. */ readonly rootFileShortcuts?: readonly string[]; /** * File extension override for new files created under this section. * When set, files are created with this extension (e.g. `.md` for * Claude rules) instead of the default for the prompt type * (e.g. `.instructions.md`). */ readonly fileExtension?: string; } /** * Identifies the AI harness (execution environment) that customizations * are filtered for. Storage answers "where did this come from?"; harness * answers "who consumes it?". */ export declare enum CustomizationHarness { VSCode = "vscode", CLI = "cli", Claude = "claude" } /** * Describes a single harness option for the UI toggle. */ export interface IHarnessDescriptor { readonly id: string; readonly label: string; readonly icon: ThemeIcon; /** * Management sections that should be hidden when this harness is active. * For example, Claude does not support prompt files so the Prompts * section is hidden. */ readonly hiddenSections?: readonly string[]; /** * Workspace sub-paths that this harness recognizes for file creation. * When set, the directory picker for new customization files only offers * workspace directories under these sub-paths (e.g. `.claude` for Claude). * When `undefined`, all workspace directories are shown (Local harness). */ readonly workspaceSubpaths?: readonly string[]; /** * When `true`, the "Generate with AI" sparkle button is hidden and replaced * with a plain "New X" manual-creation button (like sessions). */ readonly hideGenerateButton?: boolean; /** * Per-section overrides for the create button behavior. * * A `commandId` entry replaces the button entirely with a command * invocation (e.g. Claude hooks → `copilot.claude.hooks`). * * A `rootFile` entry makes the primary button create a specific file * at the workspace root (e.g. Claude instructions → `CLAUDE.md`). * When combined with `typeLabel`, the dropdown create actions use * that label instead of the section's default (e.g. "Rule" instead * of "Instruction"). */ readonly sectionOverrides?: ReadonlyMap; /** * The chat agent ID that must be registered for this harness to appear. * When `undefined`, the harness is always available (e.g. Local). */ readonly requiredAgentId?: string; /** * Instruction file patterns that this harness recognizes. * Each entry is either an exact filename (e.g. `'CLAUDE.md'`) or a * path prefix ending with `/` (e.g. `'.claude/rules/'`). * When set, instruction items that don't match any pattern are filtered out. * When `undefined`, all instruction files are shown. */ readonly instructionFileFilter?: readonly string[]; /** * Returns the storage source filter that should be applied to customization * items of the given type when this harness is active. */ getStorageSourceFilter(type: PromptsType): IStorageSourceFilter; /** * When set, this harness is backed by an extension-contributed provider * that can supply customization items directly (bypassing promptsService * discovery and filtering). */ readonly itemProvider?: IExternalCustomizationItemProvider; } /** * Represents a customization item provided by an external extension. */ export interface IExternalCustomizationItem { readonly uri: URI; readonly type: string; readonly name: string; readonly description?: string; /** When set, items with the same groupKey are displayed under a shared collapsible header. */ readonly groupKey?: string; /** When set, shows a small inline badge next to the item name (e.g. an applyTo glob pattern). */ readonly badge?: string; /** Tooltip shown when hovering the badge. */ readonly badgeTooltip?: string; } /** * Provider interface for extension-contributed harnesses that supply * customization items directly from their SDK. */ export interface IExternalCustomizationItemProvider { /** * Event that fires when the provider's customizations change. */ readonly onDidChange: Event; /** * Provide the customization items this harness supports. */ provideChatSessionCustomizations(token: CancellationToken): Promise; } /** * Returns the user-home directories accessible to the Copilot CLI harness. */ export declare function getCliUserRoots(userHome: URI): readonly URI[]; /** * Returns the user-home directories accessible to the Claude harness. */ export declare function getClaudeUserRoots(userHome: URI): readonly URI[]; /** * Creates a "VS Code" harness descriptor that shows all storage sources * with no user-root restrictions. */ export declare function createVSCodeHarnessDescriptor(extras: readonly string[]): IHarnessDescriptor; /** * Creates a "Copilot CLI" harness descriptor. */ export declare function createCliHarnessDescriptor(cliUserRoots: readonly URI[], extras: readonly string[]): IHarnessDescriptor; /** * Creates a "Claude" harness descriptor. * Claude does not support prompt files (.prompt.md), AGENTS.md, or extension-contributed plugins. * It supports agents (.claude/agents/), instructions (CLAUDE.md, .claude/rules/), * skills (.claude/skills/), and hooks (.claude/settings.json). */ export declare function createClaudeHarnessDescriptor(claudeRoots: readonly URI[], extras: readonly string[]): IHarnessDescriptor; /** * Tests whether a file path belongs to one of the given workspace sub-paths. * Matches on path segment boundaries to avoid false positives * (e.g. `.claude` must appear as `/.claude/` in the path, not as part of * a longer segment like `not.claude`). */ export declare function matchesWorkspaceSubpath(filePath: string, subpaths: readonly string[]): boolean; /** * Tests whether an instruction file matches one of the harness's recognized * instruction file patterns. Patterns can be exact filenames (e.g. `CLAUDE.md`) * or path prefixes ending with `/` (e.g. `.claude/rules/`). */ export declare function matchesInstructionFileFilter(filePath: string, filters: readonly string[]): boolean; /** * Reusable base implementation of {@link ICustomizationHarnessService}. * Concrete registrations only need to supply the list of harness * descriptors and a default harness id. */ export declare class CustomizationHarnessServiceBase implements ICustomizationHarnessService { readonly _serviceBrand: undefined; private readonly _activeHarness; readonly activeHarness: IObservable; private readonly _staticHarnesses; private readonly _externalHarnesses; private readonly _availableHarnesses; readonly availableHarnesses: IObservable; constructor(staticHarnesses: readonly IHarnessDescriptor[], defaultHarness: string); private _getAllHarnesses; private _refreshAvailableHarnesses; registerExternalHarness(descriptor: IHarnessDescriptor): IDisposable; setActiveHarness(id: string): void; getStorageSourceFilter(type: PromptsType): IStorageSourceFilter; getActiveDescriptor(): IHarnessDescriptor; }