diff --git a/.agent-plugin/.acp.json b/.agent-plugin/.acp.json
new file mode 100644
index 00000000..4284e5c0
--- /dev/null
+++ b/.agent-plugin/.acp.json
@@ -0,0 +1,20 @@
+{
+ "github-copilot": {
+ "distribution": {
+ "binary": {
+ "darwin-aarch64": {
+ "archive": "https://github.com/github/copilot-cli/releases/download/v1.0.78/copilot-darwin-arm64.tar.gz",
+ "cmd": "./copilot",
+ "args": ["--acp"],
+ "env": {}
+ }
+ }
+ },
+ "extendedFeatures": {
+ "userConfigFile": {
+ "path": "~/.copilot/settings.json",
+ "description": "GitHub Copilot configuration and authentication credentials. Populated automatically by `copilot login`; set `store_token_plaintext: true` and add a token under `copilot_tokens` to supply credentials without an interactive session."
+ }
+ }
+ }
+}
diff --git a/.agent-plugin/icon.svg b/.agent-plugin/icon.svg
new file mode 100644
index 00000000..0b596674
--- /dev/null
+++ b/.agent-plugin/icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/.agent-plugin/plugin.json b/.agent-plugin/plugin.json
new file mode 100644
index 00000000..1785e69a
--- /dev/null
+++ b/.agent-plugin/plugin.json
@@ -0,0 +1,17 @@
+{
+ "name": "GitHub Copilot",
+ "slug": "github-copilot",
+ "description": "GitHub's AI pair programmer",
+ "version": "0.1.0",
+ "author": {
+ "name": "GitHub",
+ "url": "https://github.com/github"
+ },
+ "repository": "https://github.com/github/CopilotForXcode",
+ "homepage": "https://github.com/features/copilot/",
+ "license": "proprietary",
+ "icon": "https://raw.githubusercontent.com/github/CopilotForXcode/main/.agent-plugin/icon.svg",
+ "tags": ["copilot", "github", "acp", "ai-assistant"],
+ "category": "ai-agent",
+ "platforms": ["darwin-aarch64"]
+}
diff --git a/.github/workflows/auto-close-pr.yml b/.github/workflows/auto-close-pr.yml
deleted file mode 100644
index 90beda84..00000000
--- a/.github/workflows/auto-close-pr.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: Auto-close PR
-on:
- pull_request_target:
- types: [opened, reopened]
-
-jobs:
- close:
- name: Run
- runs-on: ubuntu-latest
- permissions:
- pull-requests: write
- steps:
- - run: |
- gh pr close ${{ github.event.pull_request.number }} --comment \
- "At the moment we are not accepting contributions to the repository.
-
- Feedback for GitHub Copilot for Xcode can be given in the [Copilot community discussions](https://github.com/github/CopilotForXcode/discussions)."
- if: ${{ !(startsWith(github.head_ref, 'release/') && github.event.pull_request.head.repo.full_name == github.repository) }}
- env:
- GH_REPO: ${{ github.repository }}
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/auto-create-release-pr.yml b/.github/workflows/auto-create-release-pr.yml
deleted file mode 100644
index dc6995b0..00000000
--- a/.github/workflows/auto-create-release-pr.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: Auto-create Release PR
-
-on:
- push:
- branches:
- - 'release/**'
-
-jobs:
- create-pr:
- runs-on: ubuntu-latest
- permissions:
- contents: write
- pull-requests: write
- steps:
- - uses: actions/checkout@v4
-
- - name: Create pull request
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- existing_pr_count="$(gh pr list \
- --state open \
- --base main \
- --head "${{ github.ref_name }}" \
- --json number \
- --jq 'length')"
- if [ "${existing_pr_count}" -gt 0 ]; then
- echo "Open pull request already exists for branch '${{ github.ref_name }}' into 'main'; skipping creation."
- else
- gh pr create \
- --title "$(git log -1 --pretty=%s)" \
- --body "Automated release PR." \
- --base main \
- --head "${{ github.ref_name }}"
- fi
-
- - name: Approve pull request
- env:
- # PAT stored in github/CopilotForXcode, with write permissions to pull requests
- GH_TOKEN: ${{ secrets.XCODE_AUTO_APPROVE }}
- run: |
- gh pr review --approve "${{ github.ref_name }}"
-
- - name: Wait for required checks
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- for i in $(seq 1 60); do
- other_checks=$(gh pr checks "${{ github.ref_name }}" | grep -v "create-pr" || true)
- if echo "$other_checks" | grep -wq "fail"; then
- echo "Required checks failed."
- exit 1
- fi
- if [ -z "$other_checks" ]; then
- echo "No other checks found yet, waiting..."
- elif ! echo "$other_checks" | grep -wq "pending"; then
- echo "All required checks passed."
- exit 0
- fi
- echo "Waiting for checks..."
- sleep 10
- done
- echo "Timed out waiting for required checks."
- exit 1
-
- - name: Merge pull request
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- gh pr merge "${{ github.ref_name }}" \
- --merge \
- --delete-branch
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42463f66..adf6cd23 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## 0.51.0 - August 12, 2026
+### Added
+- Support for Kimi K3 through the updated Copilot language server.
+- Agent Client Protocol (ACP) plugin metadata for GitHub Copilot.
+
+### Changed
+- Updated the Copilot language server from 1.488.0 to 1.523.3.
+- Updated the ACP plugin to use Copilot CLI 1.0.78.
+
+### Fixed
+- Fixed model pricing tooltips for the latest token pricing metadata.
+
## 0.50.0 - May 20, 2026
### Added
- Reasoning effort control for supported models: Low, Medium, or High from the model picker to balance response speed and quality.
diff --git a/Core/Sources/ChatService/ToolCalls/AutoApproval/FetchWebPageApprovalStorage.swift b/Core/Sources/ChatService/ToolCalls/AutoApproval/FetchWebPageApprovalStorage.swift
new file mode 100644
index 00000000..a8216b79
--- /dev/null
+++ b/Core/Sources/ChatService/ToolCalls/AutoApproval/FetchWebPageApprovalStorage.swift
@@ -0,0 +1,33 @@
+import Foundation
+
+struct FetchWebPageApprovalStorage {
+ private var approvals: [ConversationID: Set] = [:]
+
+ mutating func allowURLs(conversationId: ConversationID, urls: [String]) {
+ guard !conversationId.isEmpty else { return }
+ let normalizedURLs = Set(urls.compactMap(normalize))
+ guard !normalizedURLs.isEmpty else { return }
+ approvals[conversationId, default: []].formUnion(normalizedURLs)
+ }
+
+ func areAllowed(conversationId: ConversationID, urls: [String]) -> Bool {
+ guard !conversationId.isEmpty else { return false }
+ let normalizedURLs = Set(urls.compactMap(normalize))
+ guard !normalizedURLs.isEmpty,
+ let approvedURLs = approvals[conversationId]
+ else {
+ return false
+ }
+ return normalizedURLs.isSubset(of: approvedURLs)
+ }
+
+ mutating func clear(conversationId: ConversationID) {
+ guard !conversationId.isEmpty else { return }
+ approvals.removeValue(forKey: conversationId)
+ }
+
+ private func normalize(_ url: String) -> String? {
+ let normalizedURL = url.trimmingCharacters(in: .whitespacesAndNewlines)
+ return normalizedURL.isEmpty ? nil : normalizedURL
+ }
+}
diff --git a/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalManager.swift b/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalManager.swift
index 71757fa8..bc3de6f2 100644
--- a/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalManager.swift
+++ b/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalManager.swift
@@ -6,6 +6,7 @@ public actor ToolAutoApprovalManager {
public enum AutoApproval: Equatable, Sendable {
case mcpTool(scope: AutoApprovalScope, serverName: String, toolName: String)
case mcpServer(scope: AutoApprovalScope, serverName: String)
+ case fetchWebPage(conversationId: ConversationID, urls: [String])
case sensitiveFile(
scope: AutoApprovalScope,
toolName: String,
@@ -18,6 +19,7 @@ public actor ToolAutoApprovalManager {
private var mcpStorage = MCPApprovalStorage()
private var sensitiveFileStorage = SensitiveFileApprovalStorage()
private var terminalStorage = TerminalApprovalStorage()
+ private var fetchWebPageStorage = FetchWebPageApprovalStorage()
public init() {}
@@ -39,6 +41,9 @@ public actor ToolAutoApprovalManager {
allowMCPServerGlobally(serverName: serverName)
}
+ case let .fetchWebPage(conversationId, urls):
+ allowFetchWebPage(conversationId: conversationId, urls: urls)
+
case let .sensitiveFile(scope, toolName, description, pattern):
switch scope {
case .session(let conversationId):
@@ -66,6 +71,16 @@ public actor ToolAutoApprovalManager {
}
}
+ // MARK: - Fetch webpage approvals
+
+ public func allowFetchWebPage(conversationId: ConversationID, urls: [String]) {
+ fetchWebPageStorage.allowURLs(conversationId: conversationId, urls: urls)
+ }
+
+ public func isFetchWebPageAllowed(conversationId: ConversationID, urls: [String]) -> Bool {
+ fetchWebPageStorage.areAllowed(conversationId: conversationId, urls: urls)
+ }
+
// MARK: - MCP approvals
public func allowMCPTool(conversationId: String, serverName: String, toolName: String) {
@@ -168,6 +183,7 @@ public actor ToolAutoApprovalManager {
mcpStorage.clear(scope: .session(conversationId))
sensitiveFileStorage.clear(scope: .session(conversationId))
terminalStorage.clear(scope: .session(conversationId))
+ fetchWebPageStorage.clear(conversationId: conversationId)
}
public func clearGlobalData() {
@@ -176,4 +192,3 @@ public actor ToolAutoApprovalManager {
terminalStorage.clear(scope: .global)
}
}
-
diff --git a/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalParsingHelpers.swift b/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalParsingHelpers.swift
index 3b8f97f5..8d3413c1 100644
--- a/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalParsingHelpers.swift
+++ b/Core/Sources/ChatService/ToolCalls/AutoApproval/ToolAutoApprovalParsingHelpers.swift
@@ -57,6 +57,26 @@ extension ToolAutoApprovalManager {
name == ToolName.runInTerminal.rawValue
}
+ public nonisolated static func isFetchWebPageOperation(name: String) -> Bool {
+ name == ToolName.fetchWebPage.rawValue
+ }
+
+ public nonisolated static func extractFetchWebPageURLs(
+ from input: [String: AnyCodable]?
+ ) -> [String] {
+ guard let urls = input?["urls"]?.value as? [String] else { return [] }
+ return normalizeFetchWebPageURLs(urls)
+ }
+
+ public nonisolated static func normalizeFetchWebPageURLs(_ urls: [String]) -> [String] {
+ var seen = Set()
+ return urls.compactMap { url in
+ let normalizedURL = url.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard !normalizedURL.isEmpty, seen.insert(normalizedURL).inserted else { return nil }
+ return normalizedURL
+ }
+ }
+
public nonisolated static func extractSensitiveFileConfirmationInfo(from message: String) -> SensitiveFileConfirmationInfo {
let fullRange = NSRange(message.startIndex ..< message.endIndex, in: message)
diff --git a/Core/Sources/ChatService/ToolCalls/ClientToolConfirmationEventHandler.swift b/Core/Sources/ChatService/ToolCalls/ClientToolConfirmationEventHandler.swift
index 262bd3f6..d9d687d0 100644
--- a/Core/Sources/ChatService/ToolCalls/ClientToolConfirmationEventHandler.swift
+++ b/Core/Sources/ChatService/ToolCalls/ClientToolConfirmationEventHandler.swift
@@ -58,6 +58,17 @@ extension ChatService {
}
}
+ if ToolAutoApprovalManager.isFetchWebPageOperation(name: params.name) {
+ let urls = ToolAutoApprovalManager.extractFetchWebPageURLs(from: params.input)
+ let allowed = await ToolAutoApprovalManager.shared.isFetchWebPageAllowed(
+ conversationId: params.conversationId,
+ urls: urls
+ )
+ if allowed {
+ return true
+ }
+ }
+
if let mcpServerName {
let allowed = await ToolAutoApprovalManager.shared.isMCPAllowed(
conversationId: params.conversationId,
diff --git a/Core/Sources/ConversationTab/ModeAndModelPicker/ModelManagerUtils.swift b/Core/Sources/ConversationTab/ModeAndModelPicker/ModelManagerUtils.swift
index a4542c90..dda65e47 100644
--- a/Core/Sources/ConversationTab/ModeAndModelPicker/ModelManagerUtils.swift
+++ b/Core/Sources/ConversationTab/ModeAndModelPicker/ModelManagerUtils.swift
@@ -374,7 +374,7 @@ extension CopilotModel {
modelPickerCategory: modelPickerCategory,
modelPickerPriceCategory: modelPickerPriceCategory,
reasoningEfforts: capabilities.supports.reasoningEfforts,
- supportsReasoningEffortLevel: capabilities.supports.supportsReasoningEffortLevel ?? false
+ supportsReasoningEffortLevel: capabilities.supports.supportsReasoningEffortLevel
)
}
}
diff --git a/Core/Sources/ConversationTab/Views/ConversationAgentProgressView/ConversationAgentProgressView.swift b/Core/Sources/ConversationTab/Views/ConversationAgentProgressView/ConversationAgentProgressView.swift
index f002f643..c38d2f94 100644
--- a/Core/Sources/ConversationTab/Views/ConversationAgentProgressView/ConversationAgentProgressView.swift
+++ b/Core/Sources/ConversationTab/Views/ConversationAgentProgressView/ConversationAgentProgressView.swift
@@ -108,6 +108,9 @@ struct ToolConfirmationView: View {
private var mcpServerName: String? { ToolAutoApprovalManager.extractMCPServerName(from: titleText) }
private var conversationId: String { tool.invokeParams?.conversationId ?? "" }
private var invokeMessage: String { tool.invokeParams?.message ?? "" }
+ private var fetchWebPageURLs: [String] {
+ ToolAutoApprovalManager.extractFetchWebPageURLs(from: tool.invokeParams?.input)
+ }
private var isSensitiveFileOperation: Bool { ToolAutoApprovalManager.isSensitiveFileOperation(message: invokeMessage) }
private var sensitiveFileInfo: ToolAutoApprovalManager.SensitiveFileConfirmationInfo {
ToolAutoApprovalManager.extractSensitiveFileConfirmationInfo(from: invokeMessage)
@@ -117,6 +120,11 @@ struct ToolConfirmationView: View {
private var shouldShowSensitiveFileSplitButton: Bool {
mcpServerName == nil && isSensitiveFileOperation && !conversationId.isEmpty
}
+ private var shouldShowFetchWebPageSplitButton: Bool {
+ ToolAutoApprovalManager.isFetchWebPageOperation(name: toolName)
+ && !conversationId.isEmpty
+ && !fetchWebPageURLs.isEmpty
+ }
@ViewBuilder
private var confirmationActionView: some View {
@@ -124,6 +132,8 @@ struct ToolConfirmationView: View {
CopilotPolicyNotifierImpl.shared.copilotPolicy.agentModeAutoApprovalEnabled {
if tool.isToolcallingLoopContinueTool {
continueButton
+ } else if shouldShowFetchWebPageSplitButton {
+ fetchWebPageSplitButton
} else if shouldShowSensitiveFileSplitButton {
sensitiveFileSplitButton
} else if shouldShowMCPSplitButton, let serverName = mcpServerName {
@@ -166,6 +176,38 @@ struct ToolConfirmationView: View {
.buttonStyle(.borderedProminent)
}
+ private var fetchWebPageMenuItems: [SplitButtonMenuItem] {
+ [
+ SplitButtonMenuItem(
+ title: fetchWebPageURLs.count == 1
+ ? "Allow this URL in this Session"
+ : "Allow these URLs in this Session"
+ ) {
+ chat.send(
+ .toolCallAcceptedWithApproval(
+ tool.id,
+ .fetchWebPage(
+ conversationId: conversationId,
+ urls: fetchWebPageURLs
+ )
+ )
+ )
+ },
+ ]
+ }
+
+ private var fetchWebPageSplitButton: some View {
+ SplitButton(
+ title: "Allow Once",
+ isDisabled: false,
+ primaryAction: {
+ chat.send(.toolCallAccepted(tool.id))
+ },
+ menuItems: fetchWebPageMenuItems,
+ style: .prominent
+ )
+ }
+
private var sensitiveFileMenuItems: [SplitButtonMenuItem] {
var items: [SplitButtonMenuItem] = []
@@ -325,6 +367,23 @@ struct ToolConfirmationView: View {
ThemedMarkdownText(text: tool.invokeParams?.message ?? "", chat: chat)
.frame(maxWidth: .infinity, alignment: .leading)
+ if ToolAutoApprovalManager.isFetchWebPageOperation(name: toolName),
+ !fetchWebPageURLs.isEmpty {
+ VStack(alignment: .leading, spacing: 4) {
+ Text(fetchWebPageURLs.count == 1 ? "URL" : "URLs")
+ .scaledFont(size: chatFontSize - 1, weight: .semibold)
+ .foregroundStyle(.primary)
+
+ ForEach(fetchWebPageURLs, id: \.self) { url in
+ Text(url)
+ .textSelection(.enabled)
+ .scaledFont(size: chatFontSize - 1)
+ .foregroundStyle(.primary)
+ }
+ }
+ .frame(maxWidth: .infinity, alignment: .leading)
+ }
+
HStack {
Button(action: {
chat.send(.toolCallCancelled(tool.id))
diff --git a/Core/Tests/ChatServiceTests/ToolAutoApprovalParsingHelpersTests.swift b/Core/Tests/ChatServiceTests/ToolAutoApprovalParsingHelpersTests.swift
index 486b018f..1c5347c8 100644
--- a/Core/Tests/ChatServiceTests/ToolAutoApprovalParsingHelpersTests.swift
+++ b/Core/Tests/ChatServiceTests/ToolAutoApprovalParsingHelpersTests.swift
@@ -39,4 +39,71 @@ class ToolAutoApprovalParsingHelpersTests: XCTestCase {
XCTAssertEqual(ToolAutoApprovalManager.extractTerminalCommandNames(from: "ls | grep match"), ["ls", "grep"])
XCTAssertEqual(ToolAutoApprovalManager.extractTerminalCommandNames(from: "ls &> out.txt"), ["ls"])
}
+
+ func testIsFetchWebPageOperation() {
+ XCTAssertTrue(ToolAutoApprovalManager.isFetchWebPageOperation(name: "fetch_webpage"))
+ XCTAssertFalse(ToolAutoApprovalManager.isFetchWebPageOperation(name: "run_in_terminal"))
+ }
+
+ func testNormalizeFetchWebPageURLs() {
+ XCTAssertEqual(
+ ToolAutoApprovalManager.normalizeFetchWebPageURLs(
+ [
+ " https://example.com/one ",
+ "",
+ "https://example.com/two",
+ "https://example.com/one",
+ ]
+ ),
+ ["https://example.com/one", "https://example.com/two"]
+ )
+ }
+
+ func testFetchWebPageApprovalIsScopedToConversationAndURL() async {
+ let manager = ToolAutoApprovalManager()
+ let firstURL = "https://example.com/one"
+ let secondURL = "https://example.com/two"
+
+ let initiallyAllowed = await manager.isFetchWebPageAllowed(
+ conversationId: "conversation-1",
+ urls: [firstURL]
+ )
+ XCTAssertFalse(initiallyAllowed)
+
+ await manager.approve(
+ .fetchWebPage(
+ conversationId: "conversation-1",
+ urls: [" \(firstURL) "]
+ )
+ )
+
+ let allowedInApprovedConversation = await manager.isFetchWebPageAllowed(
+ conversationId: "conversation-1",
+ urls: [firstURL]
+ )
+ let allowedInOtherConversation = await manager.isFetchWebPageAllowed(
+ conversationId: "conversation-2",
+ urls: [firstURL]
+ )
+ let allowedForOtherURL = await manager.isFetchWebPageAllowed(
+ conversationId: "conversation-1",
+ urls: [secondURL]
+ )
+ let allowedForMixedURLs = await manager.isFetchWebPageAllowed(
+ conversationId: "conversation-1",
+ urls: [firstURL, secondURL]
+ )
+ XCTAssertTrue(allowedInApprovedConversation)
+ XCTAssertFalse(allowedInOtherConversation)
+ XCTAssertFalse(allowedForOtherURL)
+ XCTAssertFalse(allowedForMixedURLs)
+
+ await manager.clearConversationData(conversationId: "conversation-1")
+
+ let allowedAfterClearing = await manager.isFetchWebPageAllowed(
+ conversationId: "conversation-1",
+ urls: [firstURL]
+ )
+ XCTAssertFalse(allowedAfterClearing)
+ }
}
diff --git a/ReleaseNotes.md b/ReleaseNotes.md
index 3c922d4a..74afcc7a 100644
--- a/ReleaseNotes.md
+++ b/ReleaseNotes.md
@@ -1,13 +1,10 @@
-### GitHub Copilot for Xcode 0.50.0
+### GitHub Copilot for Xcode 0.51.0
**🚀 Highlights**
-- **Reasoning Effort**: Control how deeply reasoning-capable models think before responding. You can now select reasoning efforts directly from the model picker for supported models, letting you balance response speed against answer quality.
-
-- **Bring Your Own Key (BYOK) is now Generally Available**: Bring Your Own Key support has graduated from preview and is now available to all users. Configure your own API keys for third-party models directly in Copilot for Xcode settings.
+- **Kimi K3 Support**: Added compatibility with Kimi K3 through an updated Copilot language server.
**💪 Changes**
-- Added internal support for upcoming [usage-based billing](https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/), including billing updates for the usage panel, usage notifications, and model picker. This will be visible once usage-based billing rolls out.
-
- We **strongly recommend** upgrading to this version as soon as possible.
+- Added Agent Client Protocol (ACP) plugin metadata for GitHub Copilot, including marketplace discovery and installation configuration.
+- Fixed model pricing tooltips so they correctly display token pricing from the latest model metadata.
diff --git a/Server/package-lock.json b/Server/package-lock.json
index 27f0877c..c9eb0479 100644
--- a/Server/package-lock.json
+++ b/Server/package-lock.json
@@ -8,9 +8,9 @@
"name": "@github/copilot-xcode",
"version": "0.0.1",
"dependencies": {
- "@github/copilot-language-server": "1.488.0",
- "@github/copilot-language-server-darwin-arm64": "1.488.0",
- "@github/copilot-language-server-darwin-x64": "1.488.0",
+ "@github/copilot-language-server": "1.537.0",
+ "@github/copilot-language-server-darwin-arm64": "1.537.0",
+ "@github/copilot-language-server-darwin-x64": "1.537.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"monaco-editor": "0.52.2"
@@ -37,10 +37,42 @@
"node": ">=14.17.0"
}
},
+ "node_modules/@github/copilot-darwin-arm64": {
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79.tgz",
+ "integrity": "sha512-rsw7JoMvlcxXb0yx08oIeEc0x2hUEwKSfhX9ESKfdMVt0Ckrzm4OEvNUyzOpOnLJ9+l3h/aI+u1w5g2ZU2K7UA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "bin": {
+ "copilot-darwin-arm64": "copilot"
+ }
+ },
+ "node_modules/@github/copilot-darwin-x64": {
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79.tgz",
+ "integrity": "sha512-D983e2lXYnq+KhjA8mTZXonY1+LGfJN9BM195J73shUvx49nRJmibDHWLvVtGeYc+43evGUOAQrOqOspAhhWPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "bin": {
+ "copilot-darwin-x64": "copilot"
+ }
+ },
"node_modules/@github/copilot-language-server": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server/-/copilot-language-server-1.488.0.tgz",
- "integrity": "sha512-zCyItvYtqrtQzpdAv6nTjph4Nfws5xTMNAw7cn2gIvBEBHT5NbnaceSwxJm2I96Ll2Jrq4uQG+wifYVMHjQDwg==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server/-/copilot-language-server-1.537.0.tgz",
+ "integrity": "sha512-CEu2bAl6kCLZfX2XZIGiTt54aoyGby30jAB2eB7+4e/K/Lgz78a/mXPyGW55yvA8nbrbf36we5NVxeZm6wkq8Q==",
"license": "MIT",
"dependencies": {
"vscode-languageserver-protocol": "^3.17.5"
@@ -49,18 +81,24 @@
"copilot-language-server": "dist/language-server.js"
},
"optionalDependencies": {
- "@github/copilot-language-server-darwin-arm64": "1.488.0",
- "@github/copilot-language-server-darwin-x64": "1.488.0",
- "@github/copilot-language-server-linux-arm64": "1.488.0",
- "@github/copilot-language-server-linux-x64": "1.488.0",
- "@github/copilot-language-server-win32-arm64": "1.488.0",
- "@github/copilot-language-server-win32-x64": "1.488.0"
+ "@github/copilot-darwin-arm64": "1.0.79",
+ "@github/copilot-darwin-x64": "1.0.79",
+ "@github/copilot-language-server-darwin-arm64": "1.537.0",
+ "@github/copilot-language-server-darwin-x64": "1.537.0",
+ "@github/copilot-language-server-linux-arm64": "1.537.0",
+ "@github/copilot-language-server-linux-x64": "1.537.0",
+ "@github/copilot-language-server-win32-arm64": "1.537.0",
+ "@github/copilot-language-server-win32-x64": "1.537.0",
+ "@github/copilot-linux-arm64": "1.0.79",
+ "@github/copilot-linux-x64": "1.0.79",
+ "@github/copilot-win32-arm64": "1.0.79",
+ "@github/copilot-win32-x64": "1.0.79"
}
},
"node_modules/@github/copilot-language-server-darwin-arm64": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-arm64/-/copilot-language-server-darwin-arm64-1.488.0.tgz",
- "integrity": "sha512-X4jqAKJwNJIM2Ua22UZvPM6/3x7ZiX4lgedvqWadoFA9SJmxF6OlQoe2L6coeC1U8RWj5WEyTqIDkyJkhsF24Q==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-arm64/-/copilot-language-server-darwin-arm64-1.537.0.tgz",
+ "integrity": "sha512-KYiD6G2cqOctCfWv6bkBWP43fI0YmvBW1VikXUudrVOdIUekSxV1EWk2elz1SYNOT+p9i4DJfIvJ8larnny4EQ==",
"cpu": [
"arm64"
],
@@ -70,9 +108,9 @@
]
},
"node_modules/@github/copilot-language-server-darwin-x64": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-x64/-/copilot-language-server-darwin-x64-1.488.0.tgz",
- "integrity": "sha512-JHmdBwxwfZfxWkJLNp4M2bydrkD/TsxPoPeojcIOscrHhTj2riWSe7zqUn61IAdtwG0z2HwK1tGS35KOJhW8+A==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server-darwin-x64/-/copilot-language-server-darwin-x64-1.537.0.tgz",
+ "integrity": "sha512-CXlg3sIqm3Jo2U+CQDLOWvGHiWgaJrxRF1r0bRGIC+bh+lLUeq4idgBjeckroFszaurKbkt9+FwLpQ7tqsQFpA==",
"cpu": [
"x64"
],
@@ -82,9 +120,9 @@
]
},
"node_modules/@github/copilot-language-server-linux-arm64": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-arm64/-/copilot-language-server-linux-arm64-1.488.0.tgz",
- "integrity": "sha512-t+MZuQl76nMAs0qzAZDb9hr3SC53cW87CmDI+lgfLfXay8cdunNirjI/IloRnXybYYKFCkjvqDl9cYcLdCA1/g==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-arm64/-/copilot-language-server-linux-arm64-1.537.0.tgz",
+ "integrity": "sha512-48gkdSSR2CQoYIb+pDzXbpc5eIC0Ac9IkyEZJ8JJFUZV/gfYH3NICaUauqOgXRkfJV7MeyZcmNUovmUzx75W2Q==",
"cpu": [
"arm64"
],
@@ -95,9 +133,9 @@
]
},
"node_modules/@github/copilot-language-server-linux-x64": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-x64/-/copilot-language-server-linux-x64-1.488.0.tgz",
- "integrity": "sha512-hhJ2ZVweqLCk0lptMXyHlXPrkSiHypcpza5gVUwMGMuw7Z87o3SkK8fD5jDpBvKJ0gJTGjPZ2yXzGtErpY20Sw==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server-linux-x64/-/copilot-language-server-linux-x64-1.537.0.tgz",
+ "integrity": "sha512-9514CfEr7joC5makmx+GDhNeFXG5cTafVs+/5KjhL9v2i/l+oSI1DAcy7SKtijB9AuPCw3sZd4hTYLnDzUH8Mg==",
"cpu": [
"x64"
],
@@ -108,9 +146,9 @@
]
},
"node_modules/@github/copilot-language-server-win32-arm64": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-arm64/-/copilot-language-server-win32-arm64-1.488.0.tgz",
- "integrity": "sha512-ke8czQwJcOtZpD9CnyBE7nVrFU9oa8nrLMp8xWoxKybs77Rpt36v2CGw535QHrih9f3Hp4dQtFlaRdvjnL1vZg==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-arm64/-/copilot-language-server-win32-arm64-1.537.0.tgz",
+ "integrity": "sha512-EOm3uHfN/T4t/TRVz3Z+8HVwe+0yiqA2qOumJfFVGBsEdjfRxY6YcnKzFJrmK6JMf+1E+LImKYPJtPLNY77C2A==",
"cpu": [
"arm64"
],
@@ -121,9 +159,9 @@
]
},
"node_modules/@github/copilot-language-server-win32-x64": {
- "version": "1.488.0",
- "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-x64/-/copilot-language-server-win32-x64-1.488.0.tgz",
- "integrity": "sha512-TOxA86DcpO7VYfsePj5PmbzqKaTwGXse6OBdMAPKPBBBCiusEI1kmYO3O/ywi8n5cCF1X9LvrqbunNRzokxRug==",
+ "version": "1.537.0",
+ "resolved": "https://registry.npmjs.org/@github/copilot-language-server-win32-x64/-/copilot-language-server-win32-x64-1.537.0.tgz",
+ "integrity": "sha512-PKWXk1fuAhGmg+t7sn/7YfTQPufIBSUjgFY7Ft/ZGxR0GIergGaaKdV4rqjeQQ2B2yYakLjHVbRk2OkiQtCbNA==",
"cpu": [
"x64"
],
@@ -133,6 +171,76 @@
"win32"
]
},
+ "node_modules/@github/copilot-linux-arm64": {
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79.tgz",
+ "integrity": "sha512-qqaNkvi92Wg+4OZk/kTWC2nUG72G0vV6eRAo5+PnKaPmjdX1GsI0a+lPxXPEbzX0zYLi/8yrUyANwyyNEsGgXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "bin": {
+ "copilot-linux-arm64": "copilot"
+ }
+ },
+ "node_modules/@github/copilot-linux-x64": {
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79.tgz",
+ "integrity": "sha512-wzotZfvHkItutciLFMXZT2k9Qiii4Ta8tsVDCMQ7CP8hPxV91FyJ1yf3+FFSSfPvWrfYM6BOAiqIuX+LjgRuiw==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "bin": {
+ "copilot-linux-x64": "copilot"
+ }
+ },
+ "node_modules/@github/copilot-win32-arm64": {
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79.tgz",
+ "integrity": "sha512-5wg/ayCBTVy4g4FdO/9BJZRVARY0sgjAn9rBkw5BSJMv4u7Mvxg5Sftlift+V5UWxTyCSHAELZ5IHKvox4Yi8w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "bin": {
+ "copilot-win32-arm64": "copilot.exe"
+ }
+ },
+ "node_modules/@github/copilot-win32-x64": {
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79.tgz",
+ "integrity": "sha512-FTpThWwwCDYnLdE0pfdo5zpAQLLVg36kmC2IKyVMuCYv9iPe7rE1mz7ng/UITN9M3TAMBrwHSvCV3pITvw4W8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "bin": {
+ "copilot-win32-x64": "copilot.exe"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
@@ -924,9 +1032,9 @@
"license": "MIT"
},
"node_modules/fast-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
- "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
+ "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
"dev": true,
"funding": [
{
@@ -1310,9 +1418,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
@@ -1452,9 +1560,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
- "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+ "version": "8.5.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
+ "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
"dev": true,
"funding": [
{
@@ -1472,7 +1580,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.8",
+ "nanoid": "^3.3.17",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
diff --git a/Server/package.json b/Server/package.json
index 4c6bdba0..fc952180 100644
--- a/Server/package.json
+++ b/Server/package.json
@@ -7,9 +7,9 @@
"build": "webpack"
},
"dependencies": {
- "@github/copilot-language-server": "1.488.0",
- "@github/copilot-language-server-darwin-arm64": "1.488.0",
- "@github/copilot-language-server-darwin-x64": "1.488.0",
+ "@github/copilot-language-server": "1.537.0",
+ "@github/copilot-language-server-darwin-arm64": "1.537.0",
+ "@github/copilot-language-server-darwin-x64": "1.537.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"monaco-editor": "0.52.2"
diff --git a/Tool/Sources/ConversationServiceProvider/LSPTypes.swift b/Tool/Sources/ConversationServiceProvider/LSPTypes.swift
index 88b86933..eda80b2c 100644
--- a/Tool/Sources/ConversationServiceProvider/LSPTypes.swift
+++ b/Tool/Sources/ConversationServiceProvider/LSPTypes.swift
@@ -48,6 +48,7 @@ public struct CopilotModel: Codable, Equatable {
public let isChatFallback: Bool
public let capabilities: CopilotModelCapabilities
public let billing: CopilotModelBilling?
+ public let customModel: CopilotModelCustomModel?
public let degradationReason: String?
public let modelPickerCategory: String?
public let modelPickerPriceCategory: String?
@@ -73,7 +74,7 @@ public struct CopilotModelCapabilitiesLimits: Codable, Equatable {
public struct CopilotModelCapabilitiesSupports: Codable, Equatable {
public let vision: Bool
public let reasoningEfforts: [String]?
- public let supportsReasoningEffortLevel: Bool?
+ public let supportsReasoningEffortLevel: Bool
}
public struct CopilotModelBilling: Codable, Equatable, Hashable {
@@ -81,20 +82,54 @@ public struct CopilotModelBilling: Codable, Equatable, Hashable {
public let multiplier: Float
public let tokenBasedBillingEnabled: Bool?
public let tokenPrices: CopilotModelBillingTokenPrices?
+ public let promo: CopilotModelBillingPromo?
- public init(isPremium: Bool, multiplier: Float, tokenBasedBillingEnabled: Bool? = nil, tokenPrices: CopilotModelBillingTokenPrices? = nil) {
+ public init(
+ isPremium: Bool,
+ multiplier: Float,
+ tokenBasedBillingEnabled: Bool? = nil,
+ tokenPrices: CopilotModelBillingTokenPrices? = nil,
+ promo: CopilotModelBillingPromo? = nil
+ ) {
self.isPremium = isPremium
self.multiplier = multiplier
self.tokenBasedBillingEnabled = tokenBasedBillingEnabled
self.tokenPrices = tokenPrices
+ self.promo = promo
}
}
public struct CopilotModelBillingTokenPrices: Codable, Equatable, Hashable {
+ public let batchSize: Int?
+ public let `default`: CopilotModelTokenPriceTier?
+ public let longContext: CopilotModelTokenPriceTier?
+
+ public var cachePrice: Float? { `default`?.cachePrice ?? longContext?.cachePrice }
+ public var inputPrice: Float? { `default`?.inputPrice ?? longContext?.inputPrice }
+ public var outputPrice: Float? { `default`?.outputPrice ?? longContext?.outputPrice }
+ public var tokenUnit: Int? { batchSize }
+}
+
+public struct CopilotModelTokenPriceTier: Codable, Equatable, Hashable {
public let cachePrice: Float?
+ public let cacheWritePrice: Float?
public let inputPrice: Float?
public let outputPrice: Float?
- public let tokenUnit: Int?
+ public let maxContext: Int?
+}
+
+public struct CopilotModelBillingPromo: Codable, Equatable, Hashable {
+ public let id: String
+ public let discountPercent: Float
+ public let endsAt: String
+ public let message: String
+}
+
+public struct CopilotModelCustomModel: Codable, Equatable {
+ public let keyName: String?
+ public let ownerName: String?
+ public let ownerType: String?
+ public let provider: String?
}
// MARK: ChatModes
diff --git a/marketplace.json b/marketplace.json
new file mode 100644
index 00000000..7dd23f7e
--- /dev/null
+++ b/marketplace.json
@@ -0,0 +1,17 @@
+{
+ "name": "GitHub Copilot",
+ "description": "GitHub's AI pair programmer",
+ "publisher": {
+ "name": "GitHub",
+ "url": "https://github.com/github",
+ "verified": true
+ },
+ "repository": "https://github.com/github/CopilotForXcode",
+ "license": "proprietary",
+ "plugins": [
+ {
+ "path": ".agent-plugin",
+ "type": "acp-agent"
+ }
+ ]
+}