Skip to content

Commit bd8f8e0

Browse files
authored
Merge branch 'main' into ethan/tbb-plan-usage
2 parents 2bac11b + b303976 commit bd8f8e0

29 files changed

Lines changed: 778 additions & 316 deletions

.github/skills/ui-action/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,4 @@ action is usable from every probe.
296296
### Keep one probe focused
297297

298298
Each JSON script represents one test case. Split unrelated behaviours into
299-
separate probes so a single `FAILED-step…` screenshot tells you what broke.
299+
separate probes so a single `FAILED-step…` screenshot tells you what broke.

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ MCP support enables integrating external tools and services into Copilot workflo
6161
- **Custom Agents** allow users to create personalized agents with specific instructions and behaviors.
6262
- **Isolated Subagents** can be spawned by the main agent to handle specific tasks or contexts independently.
6363
- **Plan Agent** can generate multi-step plans to accomplish complex tasks, breaking them down into manageable actions.
64+
- **Skills** are reusable, specialized AI assistant templates that enrich chat context in Agent Mode. Skills are defined as `SKILL.md` files and can be scoped to a workspace or shared globally.
65+
66+
- Creating Skills
67+
68+
Place a `SKILL.md` file in any of these directories:
69+
70+
- **Project-scoped:** `.github/skills/<skill-name>/`, `.claude/skills/<skill-name>/`, `.agents/skills/<skill-name>/`
71+
- **User-scoped (global):** `~/.copilot/skills/<skill-name>/`, `~/.claude/skills/<skill-name>/`, `~/.agents/skills/<skill-name>/`
72+
73+
Each `SKILL.md` file can include YAML front matter with metadata (name, description) followed by Markdown content that provides domain knowledge, workflows, or instructions for the AI assistant.
74+
75+
Skills are automatically discovered and available in Agent Mode. You can enable or disable skills in **Window → Preferences → Copilot → Chat → Enable Skills**.
6476

6577
For other available features in Eclipse, see the [Copilot feature matrix](https://docs.github.com/en/copilot/reference/copilot-feature-matrix?tool=eclipse).
6678

com.microsoft.copilot.eclipse.core/copilot-agent/package-lock.json

Lines changed: 33 additions & 33 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.microsoft.copilot.eclipse.core/copilot-agent/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
"postinstall": "node copy-binaries.js"
1313
},
1414
"dependencies": {
15-
"@github/copilot-language-server": "1.482.0",
16-
"@github/copilot-language-server-win32-x64": "1.482.0",
17-
"@github/copilot-language-server-darwin-x64": "1.482.0",
18-
"@github/copilot-language-server-darwin-arm64": "1.482.0",
19-
"@github/copilot-language-server-linux-x64": "1.482.0",
20-
"@github/copilot-language-server-linux-arm64": "1.482.0"
15+
"@github/copilot-language-server": "1.484.0",
16+
"@github/copilot-language-server-win32-x64": "1.484.0",
17+
"@github/copilot-language-server-darwin-x64": "1.484.0",
18+
"@github/copilot-language-server-darwin-arm64": "1.484.0",
19+
"@github/copilot-language-server-linux-x64": "1.484.0",
20+
"@github/copilot-language-server-linux-arm64": "1.484.0"
2121
}
2222
}

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/Constants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ private Constants() {
2828
public static final String WORKSPACE_CONTEXT_ENABLED = "workspaceContextEnabled";
2929
public static final String SUB_AGENT_ENABLED = "subAgentEnabled";
3030
public static final String AGENT_MAX_REQUESTS = "agentMaxRequests";
31+
public static final String ENABLE_SKILLS = "enableSkills";
32+
public static final String TRANSCRIPT_SUBDIR = ".copilot/eclipse";
3133
public static final String MCP = "mcp";
3234
public static final String MCP_REGISTRY_URL = "mcpRegistryUrl";
3335
public static final String MCP_REGISTRY_VERSION = "v0.1";

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/events/CopilotEventConstants.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,10 @@ public class CopilotEventConstants {
160160
* Event when a rate limit warning is received from the language server.
161161
*/
162162
public static final String TOPIC_RATE_LIMIT_WARNING = TOPIC_CHAT + "RATE_LIMIT_WARNING";
163+
164+
/**
165+
* Event when custom prompts, skills, agents, or instructions change on the language server. Clients should re-fetch
166+
* conversation templates on receipt.
167+
*/
168+
public static final String TOPIC_CHAT_DID_CHANGE_CUSTOMIZATION_FILES = TOPIC_CHAT + "DID_CHANGE_CUSTOMIZATION_FILES";
163169
}

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/lsp/CopilotLanguageClient.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ public CompletableFuture<Object[]> getConversationContext(ConversationContextPar
140140
public CompletableFuture<Object> invokeClientTool(InvokeClientToolParams params) {
141141
return CompletableFuture.supplyAsync(() -> {
142142
try {
143-
CompletableFuture<LanguageModelToolResult[]> toolFuture =
144-
CopilotCore.getPlugin().getChatEventsManager().invokeAgentTool(params);
143+
CompletableFuture<LanguageModelToolResult[]> toolFuture = CopilotCore.getPlugin().getChatEventsManager()
144+
.invokeAgentTool(params);
145145
if (toolFuture == null) {
146-
CopilotCore.LOGGER.error(
147-
new IllegalStateException("invokeAgentTool returned null for tool: " + params.getName()));
146+
CopilotCore.LOGGER
147+
.error(new IllegalStateException("invokeAgentTool returned null for tool: " + params.getName()));
148148
LanguageModelToolResult errorResult = new LanguageModelToolResult();
149149
errorResult.addContent("Failed to invoke the tool: tool invocation returned null");
150150
errorResult.setStatus(ToolInvocationStatus.error);
@@ -182,6 +182,8 @@ public CompletableFuture<Object[]> confirmClientTool(InvokeClientToolConfirmatio
182182
});
183183
}
184184

185+
// TODO: Should remove workspace-root folder as the projects are not directly under it in Eclipse, and can cause
186+
// confusion in CLS.
185187
@Override
186188
public CompletableFuture<List<WorkspaceFolder>> workspaceFolders() {
187189
// Ideally, we should return each IProject as a workspace folder, but given that when
@@ -259,9 +261,30 @@ public void onRateLimitWarning(RateLimitWarningParams params) {
259261
}
260262

261263
/**
262-
* Handles the Dynamic OAuth request for MCP.
263-
* Shows a dialog with multiple input fields and returns the user's input values.
264-
* Returns null if the user cancels the request.
264+
* Notify when custom skills change (global or workspace). Signal-only; clients re-fetch templates.
265+
*/
266+
@JsonNotification("copilot/customSkill/didChange")
267+
public void onDidChangeCustomSkill(Object params) {
268+
notifyCustomizationFilesChanged();
269+
}
270+
271+
/**
272+
* Notify when custom prompts change (global or workspace). Signal-only; clients re-fetch templates.
273+
*/
274+
@JsonNotification("copilot/customPrompt/didChange")
275+
public void onDidChangeCustomPrompt(Object params) {
276+
notifyCustomizationFilesChanged();
277+
}
278+
279+
private void notifyCustomizationFilesChanged() {
280+
if (eventBroker != null) {
281+
eventBroker.post(CopilotEventConstants.TOPIC_CHAT_DID_CHANGE_CUSTOMIZATION_FILES, null);
282+
}
283+
}
284+
285+
/**
286+
* Handles the Dynamic OAuth request for MCP. Shows a dialog with multiple input fields and returns the user's input
287+
* values. Returns null if the user cancels the request.
265288
*/
266289
@JsonRequest("copilot/dynamicOAuth")
267290
public CompletableFuture<Map<String, String>> mcpOauth(McpOauthRequest request) {
@@ -307,13 +330,11 @@ public void onDidChangePolicy(DidChangePolicyParams params) {
307330
}
308331
if (flags.isSubAgentPolicyEnabled() != params.isSubAgentEnabled()) {
309332
flags.setSubAgentPolicyEnabled(params.isSubAgentEnabled());
310-
eventBroker.post(CopilotEventConstants.TOPIC_DID_CHANGE_SUB_AGENT_POLICY,
311-
params.isSubAgentEnabled());
333+
eventBroker.post(CopilotEventConstants.TOPIC_DID_CHANGE_SUB_AGENT_POLICY, params.isSubAgentEnabled());
312334
}
313335
if (flags.isCustomAgentPolicyEnabled() != params.isCustomAgentEnabled()) {
314336
flags.setCustomAgentPolicyEnabled(params.isCustomAgentEnabled());
315-
eventBroker.post(CopilotEventConstants.TOPIC_DID_CHANGE_CUSTOM_AGENT_POLICY,
316-
params.isCustomAgentEnabled());
337+
eventBroker.post(CopilotEventConstants.TOPIC_DID_CHANGE_CUSTOM_AGENT_POLICY, params.isCustomAgentEnabled());
317338
}
318339
}
319340
}

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/lsp/CopilotLanguageServer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationMode;
3030
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationModesParams;
3131
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationTemplate;
32+
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationTemplatesParams;
3233
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationTurnParams;
3334
import com.microsoft.copilot.eclipse.core.lsp.protocol.CopilotModel;
3435
import com.microsoft.copilot.eclipse.core.lsp.protocol.CopilotStatusResult;
@@ -140,9 +141,11 @@ public interface CopilotLanguageServer extends LanguageServer {
140141

141142
/**
142143
* List conversation templates.
144+
*
145+
* @param params includes workspace folders for discovering workspace-specific prompt files and skills
143146
*/
144147
@JsonRequest("conversation/templates")
145-
CompletableFuture<ConversationTemplate[]> listTemplates(NullParams param);
148+
CompletableFuture<ConversationTemplate[]> listTemplates(ConversationTemplatesParams params);
146149

147150
/**
148151
* List conversation modes.

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/lsp/CopilotLanguageServerConnection.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.eclipse.lsp4j.ProgressParams;
2121
import org.eclipse.lsp4j.Range;
2222
import org.eclipse.lsp4j.TextDocumentIdentifier;
23+
import org.eclipse.lsp4j.WorkspaceFolder;
2324
import org.eclipse.lsp4j.jsonrpc.Endpoint;
2425
import org.eclipse.lsp4j.jsonrpc.messages.Either;
2526
import org.eclipse.lsp4j.services.LanguageServer;
@@ -46,6 +47,7 @@
4647
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationMode;
4748
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationModesParams;
4849
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationTemplate;
50+
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationTemplatesParams;
4951
import com.microsoft.copilot.eclipse.core.lsp.protocol.ConversationTurnParams;
5052
import com.microsoft.copilot.eclipse.core.lsp.protocol.CopilotModel;
5153
import com.microsoft.copilot.eclipse.core.lsp.protocol.CopilotStatusResult;
@@ -278,6 +280,18 @@ public CompletableFuture<ChatCreateResult> createConversation(String workDoneTok
278280
List<IResource> files, IFile currentFile, Range currentSelection, List<Turn> turns, CopilotModel activeModel,
279281
String chatModeName, String customChatModeId, List<TodoItem> todos, String agentSlug,
280282
String agentJobWorkspaceFolder) {
283+
return createConversation(workDoneToken, message, files, currentFile, currentSelection, turns, activeModel,
284+
chatModeName, customChatModeId, todos, agentSlug, agentJobWorkspaceFolder, null, null);
285+
}
286+
287+
/**
288+
* Create a conversation with the given parameters, including optional conversationId and restoreToTurnId for session
289+
* restoration.
290+
*/
291+
public CompletableFuture<ChatCreateResult> createConversation(String workDoneToken, String message,
292+
List<IResource> files, IFile currentFile, Range currentSelection, List<Turn> turns, CopilotModel activeModel,
293+
String chatModeName, String customChatModeId, List<TodoItem> todos, String agentSlug,
294+
String agentJobWorkspaceFolder, String conversationId, String restoreToTurnId) {
281295
boolean supportVision = activeModel.getCapabilities().supports().vision();
282296
Either<String, List<ChatCompletionContentPart>> messageWithImages = ChatMessageUtils
283297
.createMessageWithImages(message, FileUtils.filterFilesFrom(files), supportVision);
@@ -308,6 +322,13 @@ public CompletableFuture<ChatCreateResult> createConversation(String workDoneTok
308322

309323
// TODO: remove needToolCallConfirmation when CLS fully supports it across all IDEs.
310324
param.setNeedToolCallConfirmation(true);
325+
326+
// Set conversationId and restoreToTurnId for session restoration from history
327+
if (conversationId != null) {
328+
param.setConversationId(conversationId);
329+
param.setRestoreToTurnId(restoreToTurnId);
330+
}
331+
311332
if (currentFile != null) {
312333
param.setTextDocument(new TextDocumentIdentifier(FileUtils.getResourceUri(currentFile)));
313334
if (currentSelection != null) {
@@ -372,10 +393,12 @@ public CompletableFuture<ChatTurnResult> addConversationTurn(String workDoneToke
372393

373394
/**
374395
* List the conversation templates.
396+
*
397+
* @param workspaceFolders workspace folders for discovering workspace-specific prompt files and skills
375398
*/
376-
public CompletableFuture<ConversationTemplate[]> listConversationTemplates() {
399+
public CompletableFuture<ConversationTemplate[]> listConversationTemplates(List<WorkspaceFolder> workspaceFolders) {
377400
Function<LanguageServer, CompletableFuture<ConversationTemplate[]>> fn = server -> {
378-
return ((CopilotLanguageServer) server).listTemplates(new NullParams());
401+
return ((CopilotLanguageServer) server).listTemplates(new ConversationTemplatesParams(workspaceFolders));
379402
};
380403
return this.languageServerWrapper.execute(fn);
381404
}

0 commit comments

Comments
 (0)