Josh Spicer
23246594+joshspicer@users.noreply.github.com
90d · built 2026-05-28
90-day totals
- Commits
- 149
- Grow
- 19.3
- Maintenance
- 8.8
- Fixes
- 7.2
- Total ETV
- 35.3
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 38 %
- By Growth share
- Top 8 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 42%
- Bugs you introduced
- 11.4
- Bugs you fixed
- 15.4
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 1.5ETVsessions: implement chatSessionCustomizationProvider for Claude and Copilot CLI (#4772) * Add customization providers for Claude and Copilot CLI chat sessions * Add unit tests for chat session customization providers Add tests for ClaudeCustomizationProvider and CopilotCLICustomizationProvider covering metadata, item discovery, and change event forwarding. Refactor metadata from static readonly to static getter for testability (avoids class initializer accessing vscode.ChatSessionCustomizationType before shim setup). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix customization provider accuracy: add hook discovery, mark unsupported types - Claude provider now discovers hooks from .claude/settings.json and .claude/settings.local.json (workspace + user home), reporting them as ChatSessionCustomizationType.Hook items with event/matcher names - Copilot CLI provider marks both Hook and Prompt as unsupported since it doesn't support hooks and prompt files aren't enumerable via the API - Claude provider now takes IWorkspaceService, IFileSystemService, and INativeEnvService to read settings files for hook discovery - Added 6 new hook discovery tests covering workspace/user settings, multiple matchers, invalid JSON, and missing files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Mark Agent as unsupported for Claude customization provider Claude doesn't use .agent.md files — it has its own agent system via CLAUDE.md memory files and the Claude Agent SDK. Remove Agent items from Claude's provideChatSessionCustomizations output and add Agent to its unsupportedTypes metadata. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove workspaceSubpaths from API, add internal path filtering Remove the workspaceSubpaths property from ChatSessionCustomizationProviderMetadata since the extension should filter internally. Each provider now only returns items under its relevant paths: - Claude: instructions/skills under .claude/ (workspace folders + user home) - Copilot CLI: instructions/skills under .github/ or .copilot/ (agents are always included since they're Copilot-specific) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add TODO comments for work in progress on chatSessionCustomizationProvider API * Sync chatSessionCustomizationProvider d.ts with VS Code origin/main Add groupKey, badge, and badgeTooltip fields to ChatSessionCustomizationItem to match upstream changes from #305810 and #305813. The providers don't set these fields explicitly — the VS Code UI auto-enriches instruction items by parsing frontmatter when groupKey is not provided. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: Claude customization provider uses SDK runtime data - Add IClaudeRuntimeDataService to cache agents from Query.supportedAgents() - ClaudeCodeSession calls runtimeDataService.update() after query creation - Rewrite ClaudeCustomizationProvider: - Agents: reported from SDK via IClaudeRuntimeDataService (built-in groupKey) - Instructions: hard-coded CLAUDE.md paths with existence checks - Skills: filtered from IChatPromptFileService under .claude/ - Hooks: unchanged (from .claude/settings.json) - unsupportedTypes changed from [Agent, Prompt] to [Prompt] only - 28 tests (22 provider + 6 service) * sessions: Copilot CLI customization provider uses runtime agent data - Inject ICopilotCLIAgents to enrich agents with displayName/description - Expand path filter: add .agents/ to CLI_SUBPATHS - Add home directory support: ~/.copilot/, ~/.agents/ - Listen to ICopilotCLIAgents.onDidChangeAgents for change events - 21 tests covering new paths, agent enrichment, and events * fix: register IClaudeRuntimeDataService in test services The existing claudeCodeAgent tests were failing because ClaudeCodeSession now depends on IClaudeRuntimeDataService, but it was not registered in createExtensionUnitTestingServices(). * sessions: implement correct chatSessionCustomizationProvider for Claude and Copilot CLI Claude provider: - New IClaudeRuntimeDataService to cache SDK Query agents - Hybrid agent approach: file-based .claude/ agents pre-session, SDK agents post-session - Instructions from hard-coded CLAUDE.md paths (stat-checked) - Skills from .claude/skills/ via IChatPromptFileService - Hooks from .claude/settings.json (unchanged) - Per-category debug logging with names Copilot CLI provider: - ICopilotCLIAgents as primary agent source (SDK + prompt files) - Path filter expanded to .github/, .copilot/, .agents/ - Home directory support (~/.copilot/, ~/.agents/) - Agent enrichment with displayName/description from SDK Menu contributions: - chat/customizations/create for Claude agents, hooks, instructions sections Code review fixes: - Use stat() instead of readFile() for existence checks - Fire-and-forget runtimeDataService.update() to avoid blocking session startup - Restore vscode.ChatSessionCustomizationType in test afterEach - Type-safe makeSweAgent helper (no as any) * claude: mark plugins as unsupported type --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 0201d5fd · 2026-03-31
- 1.3ETVChat Session Customizations initial Sketch (#304532) * Add ChatSessionCustomizationsProvider proposed API New types in chatSessionCustomizations.d.ts: - ChatSessionCustomizationType enum (well-known group IDs) - ChatSessionCustomizationStorageLocation enum - ChatSessionCustomizationItem, ChatSessionCustomizationItemGroup - ChatSessionCustomizationsProvider (provideCustomizations + resolveCustomizationDeletion) New registration function in chatSessionsProvider.d.ts: - chat.registerChatSessionCustomizationsProvider(chatSessionType, provider) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Implement ChatSessionCustomizationsProvider e2e plumbing Protocol: DTOs and 5 new methods on MainThread/ExtHost shapes. Ext host: registerChatSessionCustomizationsProvider, provideCustomizations, resolveCustomizationDeletion proxy methods. Type converters: ChatSessionCustomizations.fromItem/fromGroup. Main thread: bridge with per-handle emitters, harness descriptor registration. Service: IChatSessionCustomizationsProvider + registerCustomizationsProvider, getCustomizations, resolveCustomizationDeletion on IChatSessionsService. Harness: registerContributedHarness() on ICustomizationHarnessService, derived observable merges built-in + contributed harnesses. UI: AICustomizationListWidget reads from provider when extension harness is active, falls back to IPromptsService for built-in harnesses. Setting: chat.customizations.providedByExtensions.enabled (experimental). Command registration: openNewChatSessionInPlace for all contributions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Unhardcode AgentSessionProviders to support extension-contributed session types Widen type annotations from AgentSessionProviders enum to AgentSessionTarget across session target picker, delegation picker, welcome view, and utility functions. Add default cases to exhaustive switch statements. Fix chatInputPart getActiveSessionType to fall back to getChatSessionType for extension-contributed URIs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add joshbot extensionDevelopmentPath to Run and Compile Code - OSS task Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Wire provider group commands to create buttons in customization UI When an extension-contributed harness is active, buildCreateActions() reads commands from the provider's group data instead of the harness descriptor. Commands flow through the full plumbing: extension → protocol DTO → main thread → service → list widget Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add error handling to ext host customizations provider methods Wrap provideCustomizations and resolveCustomizationDeletion in try-catch to prevent extension errors from crashing the ext host. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Subscribe to onDidChangeCustomizations in list widget for live updates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix group commands race condition, remove resolveCustomizationDeletion Commands bug: _fetchItemsFromProvider no longer sets _currentGroupCommands as a side effect. Commands are now extracted in loadItems() after the section-guard check, eliminating races from computeItemCountForSection. Deletion: removed resolveCustomizationDeletion from the full stack (proposed API, protocol, ext host, main thread, service, mocks). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add NOTES.md with open design items for cross-harness customizations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update NOTES.md with pattern analysis and concrete context proposal Analyzed TreeDataProvider, StorageSourceFilter, CompletionItemProvider, and CodeActionProvider patterns. Proposed ChatSessionCustomizationsContext parameter with discoveredItems for provider-as-curator model. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify cross-harness approach: pull via chatPromptFiles API No new API needed. Extensions use existing chat.customAgents, chat.skills, chat.instructions arrays to discover global items and merge them in provideCustomizations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add swap file for VIM 9.1 configuration * Remove swap file for VIM configuration * Fix JoshBot task: inline arg into command string Shell tasks with && in command don't work with separate args array. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix create buttons: call updateAddButton after loadItems buildCreateActions reads _currentGroupCommands which is populated in loadItems. Calling updateAddButton before loadItems meant commands were always undefined for extension harnesses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Guard extension customizations behind setting as a full feature gate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix missing Hooks section, remove redundant config check - Add 'hooks' case to sectionToCustomizationGroupIds - Remove dead UseCustomizationsProvider check from widget (already enforced at registration in mainThreadChatSessions) - Remove unused IConfigurationService and ChatConfiguration imports Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Wire itemCommands to context menu for extension harness items Extension-provided itemCommands now appear in the right-click context menu on customization items when a non-built-in harness is active. Commands receive the item id and uri as arguments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add inSessions flag to Launch Component Explorer task Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix component fixtures: add IChatSessionsService mock AICustomizationListWidget now depends on IChatSessionsService. Add mock to both list widget and management editor fixtures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor ChatSessionCustomizationItem: remove id property and update related code * Remove JoshBot task from tasks.json Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename setting to chat.customizations.providerApi.enabled Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace hardcoded harness checks with hasCustomizationsProvider Remove all CustomizationHarness.VSCode/CLI/Claude comparisons from the list widget. Instead check chatSessionsService.hasCustomizationsProvider() which works for any harness — built-in or extension-contributed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add TODO comments to proposed API for open design questions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove NOTES.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add TODO: Remove hardcoded providers from core Mark all knownProvider/knownType if-else patterns that branch on whether a session type is in the AgentSessionProviders enum. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Raymond Zhao <7199958+rzhao271@users.noreply.github.com>github.com-microsoft-vscode · 2ce238e7 · 2026-03-26
- 1.2ETVAHP/Customizations: BrowserPluginGitCommandService for adding plugins in web (#313575) * chat: add real BrowserPluginGitCommandService for adding plugins in web Replaces the throwing stub at src/vs/workbench/contrib/chat/browser/pluginGitCommandService.ts with a real implementation that lets browser/web clients install agent plugins from public (and authenticated) GitHub repositories without a local git binary or AHP server. How it works - Resolve the requested ref to a commit SHA via GitHub's /repos/{owner}/{repo}/commits/{ref} endpoint. - Download the tarball at that SHA, decompress with the platform DecompressionStream, and stream-extract the USTAR archive directly into the workbench virtual file system at the caller's targetDir. The standard GitHub-archive wrapper directory ({repo}-{shortSha}/) is stripped so consumers see a clean tree, and any prior contents are wiped first so files removed upstream don't linger. - Persist {owner, repo, ref, sha, fetchedAt} per-target via IStorageService (chat.plugins.browserCache.v1). This lets revParse() answer locally and lets pull()/checkout() short-circuit when the upstream SHA matches the cached one -- which also feeds CustomizationRef.nonce so the AHP server's plugin manager dedupes. - Best-effort silent IAuthenticationService lookup attaches a GitHub token when one is already available, enabling private-repo installs; public repos still work with no session. 401/403 surfaces a typed GitHubAuthRequiredError so future UI can drive sign-in. - checkout() handles SHA-pinned plugin sources (the AbstractGitPluginSource path): no-op when the SHA matches, otherwise fetches the tarball at the requested SHA. Branches/tags/short SHAs resolve through the commits API. - Non-GitHub clone URLs throw an actionable localized error directing users to the desktop client or a remote agent host. - TAR extraction validates entry paths (rejects '.', '..', empty, NUL, leading-slash segments and double-checks isEqualOrParent) so a malicious archive cannot escape targetDir. The DI singleton registration in chat.contribution.ts already wires IPluginGitService -> BrowserPluginGitCommandService; the new constructor parameters are injected automatically. Tests - New src/vs/workbench/contrib/chat/test/browser/pluginGitCommandService.test.ts covers URL parsing (canonical / trailing-slash / extra-segment / malformed), tarball fetch+extract, no-op pull on SHA match, re-download on SHA change, stale-file cleanup, path-traversal entry rejection, checkout no-op / re-extract / no-metadata, and the auth-required error path. Test fixtures build a minimal valid USTAR + gzip via CompressionStream so bytes round-trip through the production DecompressionStream. Reuse notes - Uses isSuccess / isClientError / asJson from platform/request rather than rolling status-code checks. - Uses dirname / isEqualOrParent / joinPath from base/common/resources for path arithmetic and traversal defence. - GitHubApiClient (sessions/contrib/github) was considered but is layering-isolated, JSON-only, and forces sign-in -- wrong semantics for best-effort silent auth and binary tarball download. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: address council review on browser plugin git service Council review surfaced ~12 follow-ups across correctness, security, and parser robustness. This commit addresses the actionable ones. Correctness - Stage extraction in a sibling `.staging-{uuid}` directory and swap into place via `IFileService.move(..., overwrite=true)` only on success. If anything throws (network, gunzip, malformed tar, cancellation, FS write error), the staging dir is cleaned up and the existing `targetDir` is left untouched. Previously the target was wiped *before* extraction began, so a mid-flight failure left the persisted SHA cache pointing at an empty directory. (consensus C1) - `pull()` now wraps its catch block with `_maybeLogTransientError` for parity with `cloneRepository` / `checkout`. (S6) - `revParse(repoDir, ref)` no longer silently ignores `ref`: when asked for a 40-hex SHA that does not match the cached one, it throws instead of lying. (S3) Rate-limit detection - New `GitHubRateLimitError`, distinct from `GitHubAuthRequiredError`, thrown when GitHub returns 403 with `X-RateLimit-Remaining: 0` or a `Retry-After` header. Higher-layer UI can present "wait" rather than "sign in". `_maybeLogTransientError` logs the retry-after window. (C2) Auth + redirects - Drop the dead `followRedirects: 5` option (browser fetch ignores it per IRequestService impl). Add a comment on `fetchAndExtractGitHubTarball` explaining the codeload signed-URL flow: GitHub's tarball endpoint 302s to a URL whose authorization is encoded in the URL itself, so private-repo downloads survive the cross-origin Authorization-header strip. (C3 cleanup) - Document the multi-account auth-session selection limitation in `_lookupGitHubToken` rather than try to solve it here -- account selection is the auth provider's responsibility. (C6) Parser robustness - `readOctal` -> `readNumericField`. Now handles: - leading whitespace (legal POSIX padding) -- previously truncated to 0 - GNU base-256 binary encoding (high bit of byte 0 set) -- previously silently mis-aligned subsequent block offsets - Invalid fields throw rather than silently returning 0, so corrupt tarballs surface as errors instead of producing empty entries. - USTAR `prefix` field now joined unconditionally per spec (`${prefix}/${name}`); previous heuristic skipped the prefix when `name.startsWith(prefix)` which is non-standard. The GNU LongLink path correctly bypasses prefix join via a `fromLongLink` flag. (C5) - `stripArchiveRoot` rejects absolute paths instead of silently rebasing them under `targetDir`. (S4) - `safeJoinUnderTarget` also rejects backslash-bearing segments to defend against Windows-style separators on tar entries that would escape `targetDir` when materialised through a Windows AHP server's `agent-client:` provider. (S1) URL parsing - Reorder normalisation in `parseGitHubCloneUrl` so trailing slashes are stripped before the `.git` suffix; URLs like `https://github.com/o/r.git/` now parse correctly. (S2) Cache hygiene - Cache-key on `getComparisonKey(targetDir, ignoreFragment=true)` instead of `URI.toString()`, so callers passing equivalent URIs with different trailing-slash / percent-encoding don't silently miss the cache. (S5) - On first cache load, kick off a fire-and-forget sweep that drops entries whose `targetDir` no longer exists on disk. Bounds the storage map size when external code (e.g. `cleanupPluginSource`) deletes a plugin directory without notifying us. (C4) Tests - Rate-limit (`GitHubRateLimitError`) on `403 + X-RateLimit-Remaining: 0`. - Failed extraction leaves the previous `targetDir` intact and the cache reporting the previous SHA. - Backslash-traversal entry rejected. - USTAR prefix split + GNU LongLink paths via a new `makeGzippedTarWithSpecial` test fixture. - `parseGitHubCloneUrl` accepts `https://github.com/o/r.git/`. - `revParse` throws on unrelated full SHA, accepts cached one. Council items not addressed in this commit - Multi-account session selection (C6): documented as a VS Code-wide auth UX concern, not a plugin-git issue. - Cross-origin redirect end-to-end test (C3): the unit-test stub doesn't simulate redirects; the fix is a real-world smoke test against vscode.dev which is out of scope for this commit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: keep default plugin toolbar actions * chat: refine plugin add actions * chat: reuse signed in github session for plugin clone * chat: fallback to anonymous plugin clone * chat: fetch plugin repos via tree+raw to bypass CORS GitHub's /tarball/ endpoint 302-redirects to codeload.github.com, which returns no CORS headers. Browser fetch() therefore fails the preflight check with TypeError: Failed to fetch before any of the existing auth-retry logic in BrowserPluginGitCommandService can run, so even public repos with a signed-in session cannot be installed. Replace the tarball flow with two CORS-friendly endpoints: - GET /repos/{owner}/{repo}/git/trees/{sha}?recursive=1 returns the full file listing. - GET https://raw.githubusercontent.com/{owner}/{repo}/{sha}/{path} returns each blob's bytes (and accepts the same Authorization header for private repos). Drop the now-unused gunzip + tar parser. Update tests to stub the new tree + raw responses instead of building synthetic gzipped tar archives. * chat: fetch plugin blobs via api.github.com to bypass CORS raw.githubusercontent.com refuses the OPTIONS preflight that an Authorization: Bearer header forces, so the previous tree+raw flow still failed the CORS check (TypeError: Failed to fetch). Switch the per-blob download to api.github.com's /git/blobs/{sha} endpoint, which is properly CORS-enabled and accepts auth headers. The blob SHA already comes back from the tree response, so no extra round-trips are needed; content is base64-encoded JSON which we decode via decodeBase64. Also add a loggedRequest wrapper that re-throws transport-level errors with the URL we were trying to reach. Without it, browser fetch CORS / DNS failures bubble up as a bare 'TypeError: Failed to fetch' that hides which request actually failed. Surface the same context through _maybeLogTransientError in the install path. * chat: drop unused bytesResponse test helper * chat: rename githubTarballFetcher to githubRepoFetcher The file no longer contains tarball logic — it fetches the repo tree and individual blobs via api.github.com. Rename to match. * chat: trim verbose comments in plugin git service * chat: tidy plugin git service auth ladder and comments - Flatten the nested try/catch in cloneRepository into a linear loop over the auth-ladder rungs (signed-in token → anonymous → fresh repo session). - Trim further verbose comments in the fetcher and cache helpers. * chat: surface locally-installed plugin items in remote-harness view When the active harness has both an itemProvider and a syncProvider (remote agent host), fetchItems blends remote items with local items. The local pass only included PromptsStorage.local / .user files, so files contributed by locally-installed agent plugins (e.g. one just cloned into vscode-userdata:/User/agent-plugins/...) never reached the customizations UI. Widen the local pass to also include PromptsStorage.plugin files. Plugin files are not individually syncable — the plugin is the unit of sync — so they're returned without the syncable marker. They still get the right grouping via the normalizer's plugin-URI check. * chat: refresh customizations debug output - Stage 6: render fromMarketplace as name@version (marketplace, type) instead of [object Object]. - Stage 3: surface syncable count and per-item syncable / pluginUri flags so the local syncable vs locally-installed plugin split (added in fetchLocalSyncableItems) is visible. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · e6b9ae7f · 2026-05-01
- 1.2ETVRedesign chat customizations welcome page (#308622) * Redesign chat customizations welcome page - Extract welcome page into dedicated AICustomizationWelcomePage class and aiCustomizationWelcome.css for better code organization - Replace old banner + card grid with: - 'Analyze Your Project and Configure AI' input box that opens /agent-customization in chat with user's description - 2x3 category card grid (Agents, Skills, Instructions, Hooks, MCP Servers, Plugins) with actionable chip buttons - Chips prepopulate chat with specific prompts (e.g. 'Create a code review agent', 'Enforce coding style') - Remove redundant 'Chat Customizations' heading (already in tab) - Remove redundant 'browse by type' pills (cards serve same purpose) - Improve chip contrast with visible borders and link-colored text - Tighten card padding and description sizing for cleaner layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Polish welcome page: bigger input, separator, more copy - Make input box taller with rounded corners and inner submit button styled like a chat input (pill-shaped submit that fills on hover) - Add section divider line between input area and card grid - Add 'Or configure individual customizations:' label above grid - Expand description copy to mention codebase analysis - Bump card label font-weight to 600 and restore 12px desc size - Restore card padding to 14px for better breathing room Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rework welcome page: stacked list, better input, centered divider - Replace 2x3 card grid with full-width stacked category list where each row shows icon, label, description, and chip buttons inline on a single line - Input box uses cornerRadius-large, proper padding matching chat input style, submit button inside with pill shape - Separator now shows centered text: 'or configure individually' with lines extending on both sides - Reduce max-width to 680px and remove all excess whitespace - Remove card/grid CSS entirely Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve welcome page hierarchy and command styling - Restore strong page intro with 'Chat Customizations' heading and descriptive copy from the original welcome page - Increase overall scale: wider content, larger workflow heading, larger description text, and roomier input box - Break each section into title row, description row, and command row instead of compressing everything into a single line - Restyle example actions as monospace command-like entries such as '/create-skill ...' to better communicate they prepopulate chat - Make category rows roomier with card-like boundaries and better visual hierarchy Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify welcome page into launcher-style sections - Replace boxed customization cards with lightweight stacked sections separated by subtle rules - Keep the centered 'or configure individually' separator - Increase overall scale for the intro, workflow heading, copy, and input - Make command examples look like real slash commands with plain command-link styling instead of pill buttons - Separate each section into title, description, and command rows for clearer hierarchy Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert welcome page to original design (keep file separation) Restore the original welcome page layout from main exactly as it was: - 'Chat Customizations' heading + subtitle - 'Configure Your AI' getting-started banner - Responsive card grid with Browse and Generate with AI buttons The only structural change kept is the file separation: welcome page logic lives in aiCustomizationWelcomePage.ts and welcome CSS lives in media/aiCustomizationWelcome.css. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add centered 'or configure individually' divider between banner and cards Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace Configure Your AI banner with chat-style input box Swap the old getting-started banner for a clean input box styled like the chat input part: cornerRadius-large, input-background, submit arrow inside. No highlight borders or extra UI chrome. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix input box focus outlines to match chat input part Remove the double-outline: the inner monaco-inputbox and the native input element both had their own focus borders showing through. Force border/outline to none on both inner elements and let only the outer container show the single focus border. Use transparent as default border (matching chat input) and add overflow: hidden to clip inner outlines at the rounded corners. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix inner input box border by passing transparent inputBoxStyles The InputBox sets an inline style border via applyStyles() which cannot be overridden by CSS. Pass inputBorder: transparent and inputBackground: transparent so the inner box is invisible and only the outer container provides the border. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor agent customizations welcome page Split the Agent Customizations welcome page into classic and prompt-launcher variants, add a configuration switch for selecting the implementation, and add component fixtures for the welcome page variants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Polish customization welcome page variants Refine the classic and prompt-launcher welcome pages so the workflow entry point is more prominent and the category actions are simpler and better aligned. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Swap welcome variants and fix sessions chat prefill Move the polished workflow-box layout into promptLaunchers (now the default) and restore classic to the origin/main baseline. Add prefillChat callback so the Generate Workflow input works in both the sessions app (via NewChatViewPane.sendQuery) and core VS Code (via workbench.action.chat.open). Enable the getting-started banner in sessions. Fix double-box input styling and card footer alignment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix input focus outline and polish welcome page layout Replace InputBox widget with plain <input> element to eliminate the focus border that the global .monaco-workbench input[type=text]:focus rule was applying. Move helper text above the input, match input-row rounding to the outer card, and add strong specificity overrides for all focus states. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · c00fafef · 2026-04-09
- 1.0ETVchat: replace chatSessionCustomizations with chatSessionCustomizationProvider API (#303017) * feat: add chat.registerCustomizationProvider extension API Introduces a new proposed extension API (chatCustomizationProvider) that enables extensions to register as customization providers for the AI Customization UI. This replaces core-based harness filtering with extension-driven discovery. Key changes: - New proposed API: vscode.proposed.chatCustomizationProvider.d.ts - ChatCustomizationProvider, ChatCustomizationItem, ChatCustomizationType - chat.registerCustomizationProvider(id, metadata, provider) - ExtHost/MainThread RPC bridge for provider registration - ICustomizationHarnessService extended with registerExternalHarness() for dynamic harness registration from extensions - IHarnessDescriptor.itemProvider for extension-driven item discovery - AICustomizationListWidget falls through to provider when active harness has an itemProvider - Unit tests for dynamic harness registration and lifecycle The static CLI/Claude harness descriptors remain as fallback until extensions adopt the new API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address code review issues - Register chatCustomizationProvider in extensionsApiProposals.ts - Fix duplicate 'descriptor' variable in fetchItemsForSection - Add missing IExternalCustomizationItemProvider import Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: make management editor reactive to dynamic harness registration - Track availableHarnesses in autorun (not just activeHarness) - Add ensureHarnessDropdown() to lazily create/remove the dropdown when harnesses are dynamically registered/unregistered - Store sidebarContent and harnessDropdownContainer refs for dynamic dropdown management Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: address API review feedback for ChatCustomizationProvider - Replace ChatCustomizationType enum with TaskGroup-style class pattern (static instances with string-backed ids, extensible via constructor) - Rename provideCustomizations → provideChatCustomizations to match VS Code provider naming conventions - Add comprehensive JSDoc explaining customization lifecycle and caching semantics (cached until onDidChange fires) - Simplify type converter to use class id directly - Bump proposal version to 2 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: quality improvements for ChatCustomizationProvider plumbing - Skip storage-based grouping for provider-backed items in the customization list widget. External providers manage their own items, so Workspace/User/Extension categories don't apply — render a flat sorted list instead. - Use AICustomizationManagementSection constants instead of hardcoded string literals in hiddenSections mapping. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: make storage optional on IAICustomizationListItem External provider items don't have a storage origin — the provider manages discovery, so Workspace/User/Extension categories don't apply. Make the storage field optional: - Provider items omit storage entirely (no fake PromptsStorage.local) - Context key overlay only sets storage key when present - Management editor falls back gracefully for provider items - Debug panel accepts optional storage - Built-in path (promptsService) is unchanged — items always have storage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: include external provider data in customization debug report When the active harness has an external provider, the debug report now shows the provider's raw items grouped by type, with name, URI, and description for each item, plus a count of items matching the current section. The promptsService stages are skipped since they don't apply to provider-backed harnesses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: rename ChatCustomization → ChatSessionCustomization per API review Renames all types, methods, events, DTOs, and the proposal file to use the ChatSession prefix as requested in API review feedback. - ChatCustomizationType → ChatSessionCustomizationType - ChatCustomizationItem → ChatSessionCustomizationItem - ChatCustomizationProvider → ChatSessionCustomizationProvider - provideChatCustomizations → provideChatSessionCustomizations - onDidChangeChatCustomizations → onDidChangeChatSessionCustomizations - registerCustomizationProvider → registerChatSessionCustomizationProvider - Proposal: chatCustomizationProvider → chatSessionCustomizationProvider Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: resolve rebase conflicts and remove old ChatSessionCustomizations API Remove the old group-based ChatSessionCustomizations API from the merged PR #304532, which is superseded by our new ChatSessionCustomizationProvider API. The old API used groups, storageLocation, and commands on the chatSessionsService path; the new API uses a flat item model on the customizationHarnessService path. Removed: - IChatSessionCustomizationItem/Group DTOs from extHost.protocol.ts - registerChatSessionCustomizationsProvider from extHostChatSessions.ts, mainThreadChatSessions.ts, extHost.api.impl.ts, chatSessionsProvider.d.ts - ChatSessionCustomizations converter namespace from extHostTypeConverters.ts - mapProviderItemToListItem and old group command fields from list widget Fixed: - registerContributedHarness → registerExternalHarness in fixtures and mainThreadChatSessions.ts - Missing AGENT_MD_FILENAME import in customizationHarnessService.ts - Constructor arg mismatch in browser customizationHarnessService.ts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove version number from new chatSessionCustomizationProvider proposal Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: rename id → chatSessionType in registerChatSessionCustomizationProvider Aligns the parameter name with the chatSessions API convention. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add AICustomizationManagementCreateMenuId for extension create actions Extensions can now contribute create/add button actions to the customizations management editor via contributes.menus targeting 'AICustomizationManagementCreate'. Use the aiCustomizationManagementSection context key to scope commands to specific sections (agents, skills, etc.). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: register chat/customizations/create as extension menu contribution point Extensions contribute to 'chat/customizations/create' in package.json contributes.menus, gated by chatSessionCustomizationProvider proposal. Uses MenuId.for() to avoid cross-layer import. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: scope create menu to active harness, replace built-in actions Add aiCustomizationManagementHarness context key set to the active harness ID. Extensions scope create menu contributions using 'when: aiCustomizationManagementHarness == myHarness'. When a harness has menu-contributed create actions, they fully replace the built-in create buttons for that section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address code review feedback - Provider items without storage are now read-only (not editable/deletable) - Wrap provideChatSessionCustomizations in try/catch to handle extension errors - Use menuItem.run() instead of commandService.executeCommand for menu actions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: gate customization provider registration on kill-switch setting Registration is now blocked when chat.customizations.providerApi.enabled is false (default), preventing providers from affecting the UI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · d7c19c5a · 2026-03-27
- 1.0ETVAccount policy access restrictions: gate AI features behind approved-org sign-in (#311487) * Implement account policy gate for AI features - Introduced AccountPolicyGateContribution to manage account policy state and notifications. - Added support for "Require Approved Account" policy, restricting AI features based on account approval. - Enhanced AccountPolicyService to handle gate state and reasons for unsatisfaction. - Updated configuration for chat features to include policy definitions. - Added tests to validate gate behavior under various account scenarios. * Refactor account policy gate logic to focus on approved organizations and update related descriptions * Add Account Policy Gate service and integrate with existing policy services * Add account policy gate information to PolicyDiagnosticsAction * Fix CI: layer violation, ESLint, i18n entry, policyData export - Move ChatAccountPolicyGateActiveContext to services/policies/common to avoid services-layer import from contrib (chatContextKeys re-exports). - Replace 'in' operator in test helper with explicit undefined check. - Add vs/workbench/services/policies entry to i18n.resources.json. - Append ChatDisableAIFeatures and ChatApprovedAccountOrganizations to build/lib/policies/policyData.jsonc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add account policy settings for approved organizations and AI feature control * Switch ChatApprovedAccountOrganizations to type:'array' Use the platform's array-typed policy contract instead of a custom comma-separated string format. Mirrors PolicyConfiguration's existing normalisation: PolicyValue is always string|number|boolean, so array policies arrive at the policy service as JSON-stringified arrays. - chat.contribution.ts: type:'string' -> type:'array', items:string - accountPolicyService: simpler parser (JSON.parse + Array.isArray) - tests: pass arrays via JSON.stringify in setupGate helper Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Don't restrict policies during policyNotResolved boot window When the user IS signed into an approved org but account-side policy data hasn't loaded yet (policyNotResolved), skip applying restricted values. Policies with `value` callbacks naturally return undefined when policyData is null, so no account-level overrides slip through. This eliminates: - Transient 'Unable to write chat.disableAIFeatures' error on boot - Flash of the gate notification that auto-dismisses seconds later - Brief UI hide/show cycle as ChatDisableAIFeatures toggles For stable restricted reasons (noAccount, wrongProvider, orgNotApproved) restrictions still apply immediately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Contact Administrator and Learn More links to gate notification Replace the 'Don't Show Again' button with: - 'Contact Your informational guidanceAdministrator' - 'Learn opens enterprise docs overview pageMore' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Show approved organizations in gate notification Add approved org list to IAccountPolicyGateInfo so the notification can display which organizations the admin requires. Shown as a suffix like 'Approved organizations: github, microsoft.' when the list is concrete (not the wildcard '*'). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move 'contact your administrator' from button to message text Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix: check org membership before policyData resolution Move the org-membership check before the policyData null check in computeGateInfo. This ensures users NOT in an approved org are restricted immediately (orgNotApproved), even while policy data is loading. The policyNotResolved reason now only applies to users who ARE in an approved making it safe to skip restrictions for thatorg transient state without leaving a security gap. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Directly set chatSetupHidden context key when gate is restricted entitlement pipeline to force chat.disableAIFeatures=true (which has timing issues in the multiplex policy service), directly toggle the chatSetupHidden context key from the gate contribution. This is the same key that drives sentiment.hidden across the entire chat UI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use IChatEntitlementService.setForceHidden to hide chat when gate restricted Add setForceHidden(hidden) API to IChatEntitlementService so the gate contribution can cleanly force the hidden state without fighting with the entitlement context's own update cycle. The gate contribution calls setForceHidden(true) when restricted and setForceHidden(false) when satisfied/inactive. Inside ChatEntitlementContext, _forceHidden is checked in withConfiguration alongside the existing chat.disableAIFeatures either one forces hidden: true on the state.setting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix setForceHidden fallback when no ChatEntitlementContext In Code OSS Dev (and any build without productService.defaultChatAgent), ChatEntitlementContext is never created, so setForceHidden was a no-op. Fall back to directly setting the chatSetupHidden context key when the context is unavailable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add trace logging to AccountPolicyGateContribution Logs state, reason, and isRestricted on every gate apply so we can diagnose why setForceHidden might not be taking effect. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Gate chat view on accountPolicyGateActive context key The chat view's `when` clause had an OR with panelParticipantRegistered that bypassed the hidden state once the Copilot extension registered. Wrap the entire condition with accountPolicyGateActive.negate() so the chat view is hidden whenever the gate is restricted, regardless of extension registration state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Re-show notification on account swap, include account name and org list - Track dismissal by reason+account combo so swapping to a different account (while still blocked) triggers a fresh notification. - Show the current account name in the orgNotApproved message so the user knows which account is being evaluated. - Format approved org list as bulleted lines for readability. - Vary message text by reason (noAccount vs orgNotApproved). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Generalize sessions blocked overlay for account policy gate The sessions (Agents) app now shows a full-screen blocking overlay when the account policy gate restricts access, reusing the same pattern as the existing 'agent disabled' overlay. - SessionsPolicyBlockedOverlay now accepts ISessionsBlockedOverlayOptions with a reason enum (AgentDisabled | AccountPolicyGate) and optional account name / approved organizations - AccountPolicyGate variant shows 'Sign-In Required' title, approved org list, contact admin text, and Sign In + Open VS Code buttons - SessionsPolicyBlockedContribution listens to both ChatConfiguration and IAccountPolicyGateService, prioritizing agent-disabled over gate - Added CSS for org list and footer sections - Updated component fixture with new variants for screenshot testing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix notification formatting: use inline comma-separated org list Notifications render as plain inline text, so the bullet-point and newline formatting was collapsing into a single unreadable line. Switch to a parenthesized comma-separated list instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix sessions overlay: remove workbench notification, handle gate natively The workbench-layer AccountPolicyGateContribution (which shows a notification toast) was imported in sessions.common.main.ts, causing a notification to appear instead of the full-screen blocking overlay. - Remove accountPolicyGate.contribution.js import from sessions - SessionsPolicyBlockedContribution now handles context key, setForceHidden, and telemetry directly (same as the workbench contribution, but with an overlay instead of a notification) - Overlay properly recreates on account changes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Defer notification until account service has settled On startup, computeGateInfo fires with reason=noAccount before the default account service has loaded the persisted session. This caused the notification to show 'Sign in...' even when the user was already signed in but the account just hadn't loaded yet. Fix: set context key + setForceHidden immediately (fail-closed), but defer the notification until the first onDidChangeGateInfo event, which fires after the account service has had time to resolve. A 5-second fallback timer ensures the notification still appears if the gate never transitions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix gate stuck on noAccount: re-evaluate after account init barrier DefaultAccountService.setDefaultAccountProvider sets currentDefaultAccount via provider.refresh() but does NOT fire onDidChangeDefaultAccount for the initial load. This caused computeGateInfo() to permanently stay on noAccount even though the user was signed in. Fix: await getDefaultAccount() (which waits for the init barrier) then re-evaluate the gate. This ensures the gate transitions from noAccount to the correct state once the persisted session loads. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add 'Sign into an approved GitHub account' to notification messages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Regenerate policyData.jsonc to match array type for ChatApprovedAccountOrganizations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove ChatDisableAIFeatures policy registration This policy was dead enforcement is handled by setForceHiddencode and the accountPolicyGateActive context key, not the policy pipeline. Regenerated policyData.jsonc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address code review: fix duplicate IPC, remove unused import - Remove duplicate updatePolicyDefinitions call on managed policy service. AccountPolicyService now uses a read-only reference (managedPolicyReader) for getPolicyValue/onDidChange only. MultiplexPolicyService handles pushing definitions to all child services. (Reviews #1 & #4) - Remove unused Emitter import and void workaround in test file (Review #2) - Removed the fail-closed try/catch that was guarding the now-removed updatePolicyDefinitions call (Review # the duplicate call that could3 fail-open is gone entirely) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove JSDoc from currentDefaultAccount interface addition Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert sessions overlay will revisit approachchanges Reverts all changes to the sessions (Agents) policyBlocked overlay, CSS, fixture, and contribution. Re-adds the workbench-layer accountPolicyGate.contribution import so sessions still gets the notification + context key + telemetry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore sessions overlay with loading state for transient restrictions Bring back the generalized sessions overlay with three states: - AgentDisabled: existing 'Agents Disabled' message (unchanged) - Loading: just the logo + animated progress bar for transient states (noAccount before account loads, policyNotResolved) blocks the UI without showing an incorrect message - AccountPolicyGate: 'Sign-In Required' with sign-in button, org list, and contact admin footer for stable restrictions (orgNotApproved, wrongProvider) The loading state uses the same progress bar animation as the welcome/walkthrough overlay. This avoids the flash of 'Agents Disabled' that appeared during the fail-closed transient window when the user IS actually in an approved org. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Don't show overlay for noAccount/ let welcome screen handle sign-inwrongProvider When the user hasn't signed in yet (noAccount) or is signed into the wrong provider (wrongProvider), the sessions welcome/walkthrough screen already handles the sign-in flow. Showing our 'Agents Disabled' or loading overlay on top would block the user from signing in. Only show the overlay for: - orgNotApproved: user signed in but wrong org (stable restriction) - policyNotResolved: loading bar while waiting for policy data Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove 'Open VS Code' button from account policy gate overlay Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix: don't show 'Agents Disabled' when gate is forcing restrictedValue When the account policy gate is active, it forces chat.agent.enabled to false via restrictedValue. The overlay was checking that config first and incorrectly showing 'Agents Disabled'. Now we skip the agent-disabled check when the gate is active, since the value is being artificially restricted by our own not by an admingate explicitly disabling agents. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Defer all stable gate-blocked states to welcome screen When the account policy gate is unsatisfied for any user-actionable reason (noAccount, wrongProvider, orgNotApproved), don't show the policy-blocked overlay. Instead, defer to the sessions welcome/walkthrough screen so the user can sign in or switch accounts via the standard sign-in flow. The Loading overlay is still shown during the transient PolicyNotResolved state to prevent flashing the welcome screen while data is in flight. Removes the now-dead AccountPolicyGate overlay variant and its supporting code (organizations list, footer styles, fixtures). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Show AccountPolicyGate overlay for orgNotApproved only When the user is definitively signed into a non-approved org, show the custom Sign-In Required overlay with org list and switch-account button. noAccount/wrongProvider still defer to the welcome screen. PolicyNotResolved still shows the loading bar. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix boot-race test to match managed policy reader pattern The test was relying on AccountPolicyService calling updatePolicyDefinitions on the managed service, but that no longer happens (the MultiplexPolicyService handles it). Updated the test to explicitly seed the managed service and Restricted after seeding. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback - Fix setForceHidden signature in test mocks to match interface - Include approvedOrganizations in gateInfoChanged detection - Replace raw setTimeout with disposableTimeout for proper cleanup - Fix AgentDisabled overlay: suppress only when gate forces the value, not when gate is merely active (handles Satisfied+AgentDisabled case) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Polish ChatApprovedAccountOrganizations policy description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Trim self-explanatory comments Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · f67b2976 · 2026-04-23
- 0.9ETVLift customization items into a single observable model (#312463) * Lift customization items into a single observable model Removes debt where the sidebar 'Customizations' widget computed per-section counts via a parallel discovery code path (customizationCounts.ts) that diverged from the actual Customizations editor's data (e.g. when a ChatSessionCustomizationProvider or AHP customization was active). Introduces a singleton owning the per-active-IAICustomizationItemsModel harness ProviderCustomizationItemSource cache and exposing per-section IObservable<readonly IAICustomizationListItem[]>. Both the editor list widget and sidebar surfaces (per-link badges + header total) now read from the same observables, so counts cannot diverge from what the editor shows. - New: aiCustomizationItemsModel.ts (+ unit tests) - Editor list widget + management editor: consume the model via autoruns - Sidebar CustomizationLinkViewItem: single autorun over the model / IMcpService.servers / IAgentPluginService.plugins - AICustomizationShortcutsWidget header total: derived sum - Deletes customizationCounts.ts and its test - Updates fixture and AI_CUSTOMIZATIONS.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address council review + CI feedback - Make items model lazy: sections only fetch on first read, avoiding the 5x provider enumeration on construction. Source.onDidChange / harness switch / workspace change refetch only sections that have already been observed. - Cache sources by descriptor identity (not id) and prune entries whose descriptor is no longer in availableHarnesses. Fixes stale binding when an external harness re-registers under the same id. - Cache per-section count derived in the constructor (no allocation per call). - Add IAICustomizationItemsModel.whenSectionLoaded(section) so editor's setSection (now async again) can await the first keeps thefetch screenshot fixture deterministic. - Sidebar header total now sums over CUSTOMIZATION_ITEMS (the visible links) instead of every prompts-based section, so it cannot exceed the sum of per-link badges. Excludes Prompts which the sidebar does not surface. - Wrap items-model unit tests in a sub-suite so per-test teardown disposes before the leak-check teardown runs. Add coverage for lazy fetching and descriptor re-registration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Wire IAICustomizationItemsModel into the list widget fixture The list widget now consumes IAICustomizationItemsModel; the fixture was still injecting only the underlying services and so failed to instantiate the widget. Register the real AICustomizationItemsModel (it transparently fetches through the existing prompts-service mock) and add the missing mock methods (findAgentSkills, getPromptSlashCommands, getHooks, getSkillUIIntegrations) that the model's discovery path exercises. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · fc158466 · 2026-04-25
- 0.9ETVChatSessionCustomizationProvider testing fixes (#308071) * Delete individual hooks instead of entire hooks file When deleting a hook from the Chat Customizations UI, parse the hook item ID to identify the specific entry within the JSON file. Remove only that entry and write the file back, instead of deleting the entire hooks file. If no hooks remain after removal, the file is deleted. Also passes the item ID through the action context so the delete handler can distinguish individual hook entries from whole files. Fixes microsoft/vscode-internalbacklog#7381 * Throw CancellationError when plugin trust dialog is declined When the user cancels the trust dialog during plugin installation, throw a CancellationError instead of silently returning. This allows the install button's catch handler to properly reset to 'Install' state instead of incorrectly showing 'Installed'. Fixes microsoft/vscode-internalbacklog#7378 * Check installed state when rendering marketplace plugin items When rendering marketplace plugin items in the plugin list, check whether the plugin is already installed by comparing install URIs with the agent plugin service's plugin list. Show 'Installed' with the button disabled instead of offering a redundant install option. Fixes microsoft/vscode-internalbacklog#7379 * Replace floppy disk icon with newFile icon for create plugin button The save/floppy disk icon is misleading for a create action. Use the newFile codicon instead, which better communicates the intent and is consistent with other create actions in the UI. Fixes microsoft/vscode-internalbacklog#7373 * Fix plugin page CSS: padding, back button, and focus outlines - Add padding-bottom to marketplace plugin footer for proper Install button alignment (fixes #7377) - Restyle back-to-installed link as a button with muted foreground color and rounded hover background instead of link styling (fixes #7384) - Add outline-offset: -1px to button group buttons to prevent focus outline clipping by parent container (fixes #7385) Fixes microsoft/vscode-internalbacklog#7377 Fixes microsoft/vscode-internalbacklog#7384 Fixes microsoft/vscode-internalbacklog#7385 * Show workspace folder name in provider path for multi-root workspaces When rendering items from external customization providers (e.g. Copilot CLI), use the label service to produce workspace-relative paths for file: URIs instead of bare filenames. This shows the folder name (e.g. 'tankgame • AGENTS.md') in multi-root workspaces, matching the core (Local) path behavior. Fixes microsoft/vscode-internalbacklog#7330github.com-microsoft-vscode · dc5a5460 · 2026-04-06
- 0.8ETVFix AI customization grouping for provider-supplied built-in items (#313568) * sessions: count remote plugin customizations Remote agent-host customization providers can contribute plugin rows and plugin-sourced items without a local plugin URI. Preserve provider-declared storage while normalizing items and include remote provider plugin rows in sidebar plugin counts, excluding locally synced remote-client rows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: dedupe locally installed plugins from harness rows When the AHP harness reports plugins that are already known to IAgentPluginService (e.g. the local Copilot CLI surfaces its installed plugins as remote-host customizations), do not double-count or double-display them. Match by display name and fold harness-provided rows into the locally installed plugin. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: add data-source mirror tests for customizations counts Adds a new 'data sources' suite to AICustomizationItemsModel tests that: - Validates getCount() for each prompts-based section (Agents, Skills, Instructions, Prompts, Hooks) reflects provider items filtered by the section's prompt type. - Validates getCount() refetches and updates when the provider fires onDidChange. - Validates getPluginCount() in three scenarios: only local plugins, only harness plugin rows (with type='plugin' / 'plugins' and remote-client filtered out), and a mix that exercises name-based dedup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Preserve groupKey/isBuiltin in URI-inference fallback The Agents app customization provider declares its built-in items only via groupKey: BUILTIN_STORAGE — without an explicit storage, extensionId, pluginUri, or workspace-anchored URI. The final fallback in inferStorageAndGroup dropped groupKey/isBuiltin and returned PromptsStorage.user, so those items rendered under 'User' instead of 'Built-in'. Carry groupKey and isBuiltin through the fallback so the list widget preserves the provider's intent. Adds a regression test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align getPluginCount dedup with PluginListWidget basename fallback When a locally installed plugin has a falsy IAgentPlugin.label, the editor PluginListWidget renders it under basename(plugin.uri) (see installedPluginToItem), but the items-model getPluginCount derived its dedup key from (label ?? '').toLowerCase(). Result: a remote provider row whose name matched the URI basename was hidden by the editor list but still added to the sidebar plugin count, recreating the very count drift this PR is trying to eliminate. Use the same (label || basename(uri)) fallback as the widget. Adds a regression test that fails without the fix. Council-review: addresses 3/3 consensus finding. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address council review: align dedup, widen storage type Two fixes from a multi-model code review of this PR: 1. PluginListWidget.installedPluginToItem used `plugin.label ?? basename`, but the items model's getPluginCount uses `plugin.label || basename`. For plugins with an empty-string label, the dedup keys diverged, so a remote provider row matching the URI basename was hidden by the editor list yet still added to the sidebar plugin count — recreating the very count drift earlier commits in this PR aim to eliminate. Switch the widget to `||` so empty labels also fall back to the URI basename. 2. ICustomizationItem.storage was typed as PromptsStorage, but inferStorageAndGroup compared `item.storage === (BUILTIN_STORAGE as unknown as PromptsStorage)`, which is type-laundering. Widen the field to AICustomizationPromptsStorage so providers can declare `storage: BUILTIN_STORAGE` without a cast, and drop the cast in inferStorageAndGroup. Coerce back to PromptsStorage at the IChatPromptSlashCommand boundary in getPromptSlashCommands. * Recognize User/globalStorage extension paths as extension-owned Extensions like Copilot Chat materialize prompt files under their own `globalStorageUri` and register them via the prompt-file provider API (e.g. ~/<userdata>/User/globalStorage/github.copilot-chat/ask-agent/Ask.agent.md). When such items reach inferStorageAndGroup with no extensionId/pluginUri/storage and the URI doesn't fall under a workspace or plugin folder, they would previously land in "User" instead of the chat extension's "Built-in" group. Extend extractExtensionIdFromPath to also recognize User/globalStorage/<extensionId>/... paths. Use a strict publisher.name regex to avoid matching unrelated entries like state.vscdb. Add three regression tests. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Ubuntu <josh@ahp.4mywozgnka0etnlo23z031udwc.xx.internal.cloudapp.net>github.com-microsoft-vscode · 1eb3e7e8 · 2026-05-02
- 0.8ETVchat customizations: improve agentic engineering dev loop (#304305) * fix #304030: show custom agent names as-is without title-casing formatDisplayName was converting dashes/underscores to spaces and applying title case (e.g. nls-code-helper → Nls Code Helper). This made names inconsistent between the customization view and the agent dropdown. Now only strips .md extension, showing names exactly as defined in frontmatter headers. * fix #304131: show workspace-relative paths in customization tooltips Workspace items now show paths relative to the project root (e.g. .github/instructions/coding-standards.instructions.md) instead of absolute paths (/Users/.../workspace/.github/...). * fix #304133: show extension name instead of full path in tooltips Extension items now show 'Extension: github.copilot-chat' in the tooltip instead of the full filesystem path into the extension directory. The extensionLabel is populated from the extensionIdByUri map during item post-processing. * fix #304178: use save icon instead of ambiguous checkmark The editor save indicator now uses Codicon.save (floppy disk) instead of Codicon.check (bare checkmark), making it clear that the indicator is about save status rather than an enable/disable toggle. * fix #304183: show user-scoped hooks in sessions window HOOKS_FILTER excluded PromptsStorage.user, so hooks in ~/.copilot/hooks/ were filtered out in the sessions window (and any harness using the restricted filter). User hooks are now supported in CLI, so add user storage to the allowed sources. * fix: improve list layout footer fallback and remove extension tooltip - Use 80px footer height fallback instead of 0 when sectionHeader has not rendered yet, preventing list from overlapping the footer on first paint - Wait for async section load in fixture before final layout - Remove extensionLabel tooltip (implementation detail, not relevant to users) * fix #304178: show loading spinner before saved icon, remove green color The save indicator now shows a spinning loading animation while the file is being saved (onDidChangeDirty dirty→clean transition), then switches to the save icon when the save completes (onDidSave). The special green color was removed to use the default description foreground color instead. * fix: simplify list layout to use CSS flex instead of manual height calculation All three list widgets (AICustomizationListWidget, McpListWidget, PluginListWidget) now rely on CSS flex layout to distribute space between search bar, list container, and footer. The layout() method sets the widget height, clears any manual list container height, and reads clientHeight (forcing a synchronous reflow) to get the flex-computed height for the WorkbenchList. This eliminates hardcoded fallback values, requestAnimationFrame correction loops, and manual offsetHeight arithmetic that caused the list to overlap the footer on first render. * revert: drop save indicator icon changes (#304178) Reverts the checkmark→save icon change, the loading spinner, and the green color removal. The save indicator is back to the original Codicon.check with green color — this will be addressed separately. * fix: show Built-in/Extension name in tooltips, fix MCP scroll, hide copy path for built-in - Built-in items show 'Built-in' in tooltip instead of file path - Non-built-in extension items show 'Extension: {displayName}' - Copy path context menu hidden for built-in items - Fix MCP/Plugin scroll: fall back to passed height when container is hidden (display:none → clientHeight=0), and re-layout when section becomes visible via selectSectionById - Remove unused resolveExtensionGroupKey method * fix: use explicit height calculation for list layout instead of flex clientHeight The flex-based clientHeight approach was unreliable — reflow timing varied between the component explorer and the real product, causing the list to clip behind the footer at certain window sizes. Reverts to explicit height calculation by measuring sibling elements (search bar, footer, back link) via offsetHeight and subtracting from total height. For hidden widgets (MCP/Plugin when not the active tab), layout is skipped since offsetHeight returns 0; the selectSectionById re-layout handles showing them later. Removes the rAF wait from the fixture since explicit measurement doesn't depend on paint timing. * Stabilize AI customizations editor fixtures * Add narrow viewport fixture variants and fix widget overflow clipping * fix: defer layout when offsetHeight returns 0 during display:none → visible transition When switching sections in the Chat Customizations editor, the container transitions from display:none to visible. The layout method fires synchronously before the browser has reflowed, causing offsetHeight to return 0 for sibling elements. Previously, layout bailed out entirely, leaving the virtual list with no viewport height — resulting in missing rows and empty space. Now defers layout to the next animation frame so measurements are accurate after the reflow completes. * skill: add live debugging workflow to chat-customizations-editor skill * skill: reference launch skill instead of duplicating agent-browser docs * skill: add fixture gotchas — built-in grouping, editor contribution mocks, screenshot stability * ci: add blocksCi labels to key customization fixtures for automated regression gating * refactor: replace type assertion mutations with immutable map in applyBuiltinGroupKeys * fix: show extension display name instead of ID for agent extension source labelsgithub.com-microsoft-vscode · b4e7793b · 2026-03-25
- 0.8ETVfeat: add harness filtering layer to Chat Customizations (#302606) * feat: implement customization harness service and UI toggle for AI customizations * refactor: extract shared harness service base class and factories - Move CustomizationHarnessServiceBase, harness descriptor factories, and user root helpers to common/customizationHarnessService.ts - Core and sessions implementations now extend the base class with just configuration (~130 lines each reduced to ~40) - Centralize ~/.copilot, ~/.claude, ~/.agents path knowledge - Parameterize storage source extras (extension vs builtin) - Add tablist accessibility: role=tablist, aria-label, roving tabIndex, arrow-key keyboard navigation, focus-visible outline - Use scoped DisposableStore for harness toggle pill listeners * fix: initialize _activeHarness in constructor to avoid define-class-fields error * feat: move harness selector to sidebar dropdown, add per-harness section filtering - Move harness toggle from content area pills to sidebar dropdown - Use VS Code quick pick for harness selection (native UX pattern) - Add hiddenSections to IHarnessDescriptor for per-harness section visibility - Claude harness hides Agents and Hooks sections (not supported) - Rename VS Code harness to 'Local' with Codicon.vm icon - Use Codicon.worktree for CLI and Codicon.claude for Claude - Sessions window registers only CLI harness (dropdown hidden) - Reactively rebuild sidebar sections on harness change - Remove old pill toggle from list widget - Style dropdown with VS Code dropdown theme variables * fix: filter create targets by active harness - Hide 'New X (User)' dropdown option in core when a restricted harness (CLI/Claude) is active, since the file would be created in the VS Code profile directory which isn't visible under those filters - Sessions always shows User option (AgenticPromptsService routes to CLI-accessible paths like ~/.copilot/) - Update add button when harness changes so dropdown reflects new state * fix: filter workspace directory picker by active harness subpaths - Add workspaceSubpaths to IHarnessDescriptor for per-harness workspace directory filtering in the creation picker - Claude harness restricts to .claude/ directories only - CLI harness allows .github/, .copilot/, .agents/, .claude/ directories - Local harness has no restriction (undefined = show all) - Add getActiveDescriptor() to ICustomizationHarnessService for callers that need the full descriptor - CustomizationCreatorService now filters the directory picker based on the active harness's workspaceSubpathsgithub.com-microsoft-vscode · 6f526369 · 2026-03-18
- 0.8ETVAdd welcome page to Chat Customizations editor (#308307) When no section is selected (the default), shows a welcome page with: - Heading and subtitle explaining the editor - Getting Started banner that pre-fills /agent-customizations in chat - Card grid for categories (Agents, Skills, Instructions, Hooks, MCP Servers, Plugins) - Each card has Browse and Generate with AI buttons Design details: - All interactive elements are proper buttons for keyboard accessibility - Cards rebuild when visible sections change (harness switch) - Welcome container has tabindex for programmatic focus - selectedSection is now nullable (undefined = welcome page)github.com-microsoft-vscode · f414e325 · 2026-04-07
- 0.8ETVchat: route AI customization list through item sources (#309666) * chat: extract AI customization item sources * chat: clean up AI customization item source extraction Addresses code quality issues from council review: - Extract shared isChatExtensionItem() to aiCustomizationItemSourceUtils - Move storageToIcon() to aiCustomizationIcons (pure function, no class dep) - Extract shared expandHookFileItems() utility, deduplicating hook file parsing from PromptsServiceCustomizationItemProvider and ProviderCustomizationItemSource - Replace fragile backward-index splice loops in applyLocalFilters with idiomatic .filter() chains - Cache ProviderCustomizationItemSource per active harness descriptor to avoid redundant event composition on every call Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: consolidate item source files into single module Merge aiCustomizationListItem, aiCustomizationItemSourceUtils, aiCustomizationItemNormalizer, and providerCustomizationItemSource into a single aiCustomizationItemSource.ts (~414 lines). These four files form a tight linear dependency chain with one external consumer (the list widget). Consolidating matches the codebase convention (cf. testing explorerProjections/index.ts) and reduces the aiCustomization directory from 22 to 19 files. The promptsServiceCustomizationItemProvider remains separate as a distinct adapter that bridges the core promptsService into the provider-shaped pipeline for harnesses without an external provider. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 32f144f2 · 2026-04-14
- 0.7ETVcustomizations: harness filtering for Claude, agent gating, general harness extensibility in core (#303036) customizations: harness filtering for Claude, agent gating, extensible section overridesgithub.com-microsoft-vscode · f5a3b7a2 · 2026-03-19
- 0.7ETVchat: replace embedded MCP/plugin editors with compact detail widgets (#312465) * Replace embedded MCP/plugin editors with compact detail widgets The Chat Customizations management editor previously embedded the full-page McpServerEditor and AgentPluginEditor inside its split-pane detail host. Those editors are designed for a wide standalone editor area and rendered visually broken in the narrow split pane regardless of CSS overrides. This change introduces two small dedicated detail components, EmbeddedMcpServerDetail and EmbeddedAgentPluginDetail, which render compactly in the split pane (icon, name, scope/source, description) and offer an 'Open in editor' link to launch the full standalone editor for advanced flows. The previous '.extension-editor' host overrides are removed in favor of focused '.ai-customization-embedded-detail' styles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add standalone fixtures for embedded MCP/plugin detail widgets Adds six new component-explorer fixtures that render EmbeddedMcpServerDetail and EmbeddedAgentPluginDetail in isolation (workspace/user/empty for MCP, installed/marketplace/empty for plugin). These complement the existing host- editor fixtures and catch regressions in the widgets themselves without requiring the full management editor stack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove 'Open in editor' link from embedded MCP/plugin detail widgets The full-page McpServerEditor and AgentPluginEditor are visually broken in several flows, so linking out to them from the compact detail widget did more harm than and the link looked out of place in an otherwise minimalgood header. Drop the link, its handlers, and the now-unused services (IHoverService, IEditorService, IInstantiationService) along with the related CSS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback: fix codicon class & doc inaccuracy - EmbeddedMcpServerDetail: server.codicon already contains the full codicon class name (e.g. "codicon-foo"), matching the pattern in mcpServerWidgets.ts. The previous code prefixed it again and validated against the Codicon registry, so custom server icons never rendered. Mirror the existing pattern: `codicon ${server.codicon}` when set, otherwise the themed mcpServerIcon. - AI_CUSTOMIZATIONS.md: drop stale mention of the "Open in editor" link, which was removed earlier in this branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fixtures: add findHarnessById to mock ICustomizationHarnessService The AICustomizationManagementEditor constructor calls harnessService.findHarnessById, which the fixture mock did not implement. This caused all renderEditor-based fixtures (including McpServerDetailNarrow and PluginDetailNarrow) to crash during construction and produce blank screenshots in CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 37eaefac · 2026-04-25
- 0.7ETVAdd disable/enable toggle for built-in skills in AI Customization editor (#303039) * Add disable/enable context menu for AI customization items Add the ability to disable and enable customization items (agents, skills, instructions, prompts) from the sessions tree view context menu. This leverages the existing IPromptsService disabled prompt files infrastructure. Changes: - Add Disable/Enable context menu actions that toggle items in the disabled prompt files set via IPromptsService - Track disabled state on tree file items by checking getDisabledPromptFiles - Apply 'disabled' CSS class (opacity: 0.5) to greyed-out disabled items - Add aiCustomizationItemDisabled context key for when-clause filtering - Update ARIA labels to announce disabled state for accessibility - Show 'Disable' when item is enabled, 'Enable' when item is disabled Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add disable/enable to management editor and fix cache refresh Wire up the disable/enable feature in the AI Customization management editor (the full-page list view), not just the sessions sidebar tree view. Changes: - Add AI_CUSTOMIZATION_ITEM_DISABLED_KEY context key for when-clause filtering - Add 'disabled' field to IAICustomizationListItem interface - Track disabled state in fetchItemsForSection via getDisabledPromptFiles - Apply 'disabled' CSS class (opacity: 0.5) on greyed-out items in renderer - Include disabled key in context overlay for both inline and context menus - Register Disable/Enable actions on AICustomizationManagementItemMenuId - Update setDisabledPromptFiles to refresh caches for all types (skills, prompts, instructions), not just agents - Subscribe list widget to onDidChangeSkills and onDidChangeInstructions so the list refreshes after toggling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add disable/enable to inline hover actions Show eye/eye-closed icon buttons on hover for toggling disabled state, in both the management editor and the sessions tree view. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix inline menu registration ordering Move inline hover menu registrations for disable/enable after the action const declarations to avoid 'Cannot access before initialization' ReferenceError at runtime. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Filter disabled skills and instructions from LLM consumption Disabled items remain visible in the UI (greyed out) but are now excluded from the LLM/extension host pipeline: - Skills: filter in _pushSkills() before sending to extension host - Instructions: filter in getInstructionFiles() which is only used by computeAutomaticInstructions and extension host push - Prompts slash commands and findAgentSkills() remain unfiltered since the management editor uses them for display Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Filter disabled builtins at registration, scope UI to builtin only Fix skill unregistration by filtering at the thesource AgenticPromptsService overrides where built-in items are registered: - findAgentSkills(): skip disabled built-in skills - listPromptFiles(): skip disabled built-in items (removes from slash commands since computePromptSlashCommands uses this) Revert filtering from promptsServiceImpl (computeAgentSkills, getInstructionFiles) and mainThreadChatAgents2 (_pushSkills) since the correct place is the registration override, not the consumer. Scope disable/enable UI to built-in items only: - Add storage context key to both tree view and management editor - All menu items now require storage === 'builtin' in when-clause Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix missing ResourceSet import in aiCustomizationListWidget Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix: keep listPromptFiles unfiltered, filter in slash commands listPromptFiles() is the raw listing used by the UI to show all items (including disabled ones greyed out). It must not filter disabled items. Instead, filter disabled items in computePromptSlashCommands() which is the consumption path for slash command completions (typing /). - Revert disabled filter from AgenticPromptsService.listPromptFiles() - Add disabled filter in computePromptSlashCommands() for both prompts and skills Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Scope disable/enable to built-in skills only Add promptType === skill constraint to all disable/enable menu items so the toggle only appears for built-in skills, not prompts or other types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix slash command cache refresh and stop filtering prompts Two fixes: - Refresh cachedSlashCommands when disabling a skill, so the /skill completion disappears immediately without a reload - Only filter disabled skills from slash commands, not prompts prompts have no re-enable UI so filtering them makes them permanently hidden Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove unnecessary cache refresh branches Only the skill branch is needed in setDisabledPromptFiles since we only disable built-in skills. Remove prompt/instructions branches. Remove onDidChangeInstructions not needed for this feature.subscription Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: enrich disabled skill paths, accessibility labels, tree view disabled skills - Include name/description from built-in skills cache in getBuiltinSkillPaths() - Add 'disabled' announcement to accessibility labels in list widget - Merge disabled skills into tree view so they can be re-enabled from sidebar Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix duplicate import of aiCustomizationTreeView Merge two separate imports from './aiCustomizationTreeView.js' into a single import statement to fix ESLint no-duplicate-imports rule violation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · eeb4486f · 2026-03-19
- 0.6ETVcloud: patches for GHE (#4235) * feat: add GHE (GitHub Enterprise) support for cloud agent - Add host field to GithubRepoId (defaults to github.com) - Add rawHost to parseRemoteUrl for SSH alias resolution - Add toGithubWebUrl helper for constructing host-aware URLs - Use ICAPIClientService.dotcomAPIURL in GithubRepositoryService instead of hardcoded https://api.github.com - Update cloud session error messages and UI links to use repo host - Support GHE URLs in _normalizeGitUri, remote agent icons, and github repo search tool - Add comprehensive tests for GHE URL parsing and host propagation * fix: make PR fetch resilient in provideChatSessionItems Wrap individual getPullRequestFromGlobalId calls in try-catch so a single failure (e.g. PermissiveAuthRequiredError on GHE) doesn't prevent all other sessions from loading. Log warnings for failures. * fix: refresh cloud sessions when CAPI URL changes for GHE Listen to IDomainService.onDidChangeDomains so that when the GHE Copilot token arrives and updates the CAPI base URL, the sessions provider clears caches and re-fetches against the correct endpoint. Previously, the initial session fetch raced with token minting and hit the default api.githubcopilot.com with a GHE token, getting 401. Also cleaned up diagnostic retry logic in getAllSessions and kept useful debug logging for session fetch diagnostics. * fix: clear chatSessionItemsPromise on refresh to prevent stale results refresh() was clearing cachedSessionItems but not chatSessionItemsPromise, so when the CAPI URL changed and triggered a refresh, the old in-flight promise (which hit the wrong URL) was still returned by subsequent provideChatSessionItems calls, preventing the re-fetch. * tidygithub.com-microsoft-vscode · e852bd8a · 2026-03-11
- 0.6ETVMcpGateway extensive logging (#299043) * McpGateway extensive logging * update * updategithub.com-microsoft-vscode · 6acf4df9 · 2026-03-03
- 0.5ETVchat: improve ChatSessionCustomizationProvider API (#307278) * chat: add Plugins to ChatSessionCustomizationType Adds a static Plugins instance so extensions can use ChatSessionCustomizationType.Plugins instead of constructing new ChatSessionCustomizationType('plugins') manually. Also adds explicit mapping in mainThread section conversion. * chat: rename unsupportedTypes to supportedTypes in customization provider metadata Inverts the semantics from a blacklist (types to hide) to a whitelist (types to show). More natural API: providers declare what they support rather than what they don't. When omitted, all sections are shown. * fix: pass through groupKey from provider items and infer storage for auto-grouping - fetchItemsFromProvider now passes through groupKey, badge, badgeTooltip - When no groupKey, infers storage from URI (workspace folder = local, else = user) - Include BUILTIN_STORAGE in external provider's visible sources so items with groupKey 'builtin' get a Built-in group header * fix: enhance debug panel to dump full harness descriptor and item details - Report now shows active harness metadata: id, label, hiddenSections, workspaceSubpaths, hideGenerateButton, requiredAgentId, instructionFileFilter - External provider items now dump groupKey, badge, status, scheme - Accepts full IHarnessDescriptor instead of just itemProvider * feat: add 'Generate Customization Debug Report' command Registers a command palette action that generates a debug report for the current customization section. Available when the Chat Customizations editor is focused. Dumps harness metadata, provider items with all fields, and widget state into a new editor tab. * fix: proper auto-grouping for provider items by URI scheme and path - file: under workspace folder → Workspace group (storage: local) - file: elsewhere → User group (storage: user) - vscode-userdata: → Extensions group (storage: extension, read-only) - non-file schemes (copilotcli:, claude-code:) → Built-in group - Also catch and log errors in loadItems to surface silent failures * cleanup: improve type safety in group filter logic * refactor: split filterItems into provider vs core paths with shared helpers Extracts shared logic into reusable helpers: - applySearchFilter(): search query matching with highlights - buildGroupedEntries(): assigns items to groups, builds display entries - commitDisplayEntries(): splices into list and updates empty state Splits grouping logic into two clear paths: - filterItemsForProvider(): sync layout OR simple storage grouping (Workspace, User, Extensions, Built-in) - filterItemsForCore(): instruction categories OR full storage grouping with visibleSources filtering * refactor: extract fetchCoreItemsForSection for clean provider/core separation Splits fetchItemsForSection into three methods: - fetchItemsForSection(): dispatcher that routes to provider or core path - fetchProviderItemsForSection(): clean provider path (provider + optional sync) - fetchCoreItemsForSection(): legacy core path with full promptsService pipeline The core path is now fully isolated with a TODO marker for future removal. When provider API becomes the sole path, delete fetchCoreItemsForSection() and all its helpers (applyBuiltinGroupKeys, applyStorageSourceFilter filters, workspaceSubpath/instructionFileFilter logic). * fix: treat vscode-userdata: items as built-in in provider path Extension-contributed items (Ask, Explore, Plan) use vscode-userdata: URIs. Previously _inferStorageAndGroup mapped these to storage=extension which showed them in an 'Extensions' group, while the core path treated them as 'Built-in'. Now all non-file schemes map to the Built-in group for consistency. * fix: enrich provider items with skill descriptions from promptsService When the provider doesn't supply a description (e.g. skills from chatPromptFileService which only have URIs), fall back to descriptions from promptsService.findAgentSkills(). This ensures skill descriptions show in the provider path just like in the core path. * fix: address Copilot review feedback - Add precondition to Generate Debug Report command so it only appears when chat features are enabled - Log errors via onUnexpectedError in loadItems instead of silently swallowing them - Handle unknown type IDs in supportedTypes→hiddenSections mapping by explicitly filtering with a guard instead of relying on filter(Boolean)github.com-microsoft-vscode · 11bc1e6d · 2026-04-02
- 0.5ETVchat customizations: fix clipping (#304281) * fix: re-layout list when toggling browse mode in MCP/plugin widgets When toggling browse mode, the back link appears/disappears but layout() was never re-called, causing the list height to not account for the changed chrome. This clipped the last entry. Cache the last layout dimensions and re-call layout() after toggling browse mode. Fixes https://github.com/microsoft/vscode/issues/304139 * fix: register IProductService in AI customization component fixtures The AICustomizationListWidget recently added a dependency on IProductService but the component fixtures were not updated, causing all AI customization fixtures to fail with 'depends on UNKNOWN service productService'. * fix: address PR review — remove manual layout() in fixtures, fix null! in ParsedPromptFilegithub.com-microsoft-vscode · c3231e5f · 2026-03-23