Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions Core/Sources/ChatService/ChatService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,12 @@ public final class ChatService: ChatServiceType, ObservableObject {
}

public func updateToolCallStatus(toolCallId: String, status: AgentToolCall.ToolCallStatus, payload: Any? = nil) {
if status == .cancelled {
resetOngoingRequest(with: .cancelled)
return
}

// Send the tool call result back to the server
if let toolCallRequest = self.pendingToolCallRequests[toolCallId], status == .accepted {
if let toolCallRequest = self.pendingToolCallRequests[toolCallId], status == .accepted || status == .cancelled {
self.pendingToolCallRequests.removeValue(forKey: toolCallId)
let toolResult = LanguageModelToolConfirmationResult(result: .Accept)
let toolResult = LanguageModelToolConfirmationResult(
result: status == .accepted ? .Accept : .Dismiss
)
let jsonResult = try? JSONEncoder().encode(toolResult)
let jsonValue = (try? JSONDecoder().decode(JSONValue.self, from: jsonResult ?? Data())) ?? JSONValue.null
toolCallRequest.completion(
Expand Down
5 changes: 4 additions & 1 deletion Core/Sources/ConversationTab/Chat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -784,9 +784,12 @@ struct Chat {
let chatContext: ChatContext = .from(message, projectURL: projectURL)
state.editor.setContext(chatContext, for: mode)
state.editorMode = mode
let isReceivingMessage = service.isReceivingMessage

return .run { send in
await send(.stopRespondingButtonTapped)
if isReceivingMessage {
await send(.stopRespondingButtonTapped)
}
}
}

Expand Down
9 changes: 7 additions & 2 deletions Core/Sources/ConversationTab/ChatPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,20 @@ public struct ChatPanel: View {
if let _ = chat.history.last?.followUp {
ChatFollowUp(chat: chat)
.scaledPadding(.vertical, 8)
.scaledPadding(.horizontal, 16)
.dimWithExitEditMode(chat)
}
}

if chat.fileEditMap.count > 0 {
WorkingSetView(chat: chat)
.dimWithExitEditMode(chat)
.scaledPadding(.horizontal, 16)
}

ChatPanelInputArea(chat: chat, r: r, editorMode: .input)
.chatPanelInputAreaPadding(.input)
.dimWithExitEditMode(chat)
.scaledPadding(.horizontal, 16)
}
.scaledPadding(.vertical, 12)
.background(Color.chatWindowBackgroundColor)
Expand Down Expand Up @@ -183,7 +185,7 @@ struct ChatPanelMessages: View {
}
}
.listStyle(.plain)
.padding(.horizontal, -8)
.scaledPadding(.leading, 8)
.listRowBackground(EmptyView())
.modify { view in
if #available(macOS 13.0, *) {
Expand Down Expand Up @@ -406,13 +408,15 @@ struct ChatHistory: View {
// check point
CheckPoint(chat: chat, messageId: message.id)
.padding(.vertical, 8)
.padding(.trailing, 8)
}
}

// Show up check point for redo
if message.id == pendingCheckpointMessageId {
CheckPoint(chat: chat, messageId: message.id)
.padding(.vertical, 8)
.padding(.trailing, 8)
}
}
.dimWithExitEditMode(
Expand Down Expand Up @@ -445,6 +449,7 @@ struct ChatHistoryItem: View {
requestType: message.requestType
)
.scaledPadding(.leading, chat.editorMode.isEditingUserMessage && chat.editorMode.editingUserMessageId == message.id ? 0 : 20)
.scaledPadding(.trailing, 8)
case .assistant:
BotMessage(
message: message,
Expand Down
6 changes: 5 additions & 1 deletion Core/Sources/ConversationTab/ModelPicker/ModelPicker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,13 @@ struct ModelPicker: View {
HStack(spacing: 0) {
// Custom segmented control with color change
ChatModePicker(chatMode: $chatMode, onScopeChange: switchModelsForScope)
.onAppear() {
.onAppear {
updateAgentPicker()
}
.onReceive(
NotificationCenter.default.publisher(for: .gitHubCopilotChatModeDidChange)) { _ in
updateAgentPicker()
}

if chatMode == "Agent" {
mcpButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ struct RunInTerminalToolView: View {

toolView
}
.padding(8)
.scaledPadding(8)
.cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
Expand Down Expand Up @@ -123,7 +123,7 @@ struct RunInTerminalToolView: View {
Text(command!)
.textSelection(.enabled)
.scaledFont(size: chatFontSize, design: .monospaced)
.padding(8)
.scaledPadding(8)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundStyle(codeForegroundColor)
.background(codeBackgroundColor)
Expand All @@ -147,19 +147,23 @@ struct RunInTerminalToolView: View {
.frame(maxWidth: .infinity, alignment: .leading)

HStack {
Button("Cancel") {
Button(action: {
chat.send(.toolCallCancelled(tool.id))
}) {
Text("Skip")
.scaledFont(.body)
}
.scaledFont(.body)

Button("Continue") {

Button(action: {
chat.send(.toolCallAccepted(tool.id))
}) {
Text("Allow")
.scaledFont(.body)
}
.scaledFont(.body)
.buttonStyle(BorderedProminentButtonStyle())
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 4)
.scaledPadding(.top, 4)
}
}
}
Expand Down
12 changes: 0 additions & 12 deletions Core/Sources/ConversationTab/ViewExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,6 @@ extension View {
self.hoverForeground(isHovered: isHovered, defaultColor: .secondary)
}

// MARK: - Chat Panel Input Area
func chatPanelInputAreaPadding(_ mode: Chat.EditorMode) -> some View {
var trailingPadding: CGFloat
switch mode {
case .input:
trailingPadding = 16
case .editUserMessage:
trailingPadding = 8
}
return self.padding(.trailing, trailingPadding)
}

// MARK: - Editor Mode

/// Dims the view when in edit mode and provides tap/keyboard exit functionality
Expand Down
2 changes: 1 addition & 1 deletion Core/Sources/ConversationTab/Views/BotMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ private struct TurnStatusView: View {
}

private var cancelStatus: some View {
statusView(icon: "slash.circle", iconColor: .secondary, text: "Cancelled")
statusView(icon: "slash.circle", iconColor: .secondary, text: "Stopped")
}

private var errorStatus: some View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ struct InputAreaTextEditor: View {
}
.overlay {
RoundedRectangle(cornerRadius: 6)
.stroke(Color(nsColor: .controlColor), lineWidth: 1)
.stroke(.quaternary, lineWidth: 1)
}
.background {
if isEditorActive {
Expand Down Expand Up @@ -452,14 +452,22 @@ struct InputAreaTextEditor: View {

@ViewBuilder
func makeCurrentEditorView(_ ref: ConversationFileReference) -> some View {
let toggleTrailingPadding: CGFloat = {
if #available(macOS 26.0, *) {
return 8
} else {
return 4
}
}()

HStack(spacing: 0) {
makeContextFileNameView(url: ref.url, isCurrentEditor: true, selection: ref.selection)

Toggle("", isOn: $isCurrentEditorContextEnabled)
.toggleStyle(SwitchToggleStyle(tint: .blue))
.controlSize(.mini)
.frame(width: 34)
.padding(.trailing, 4)
.padding(.trailing, toggleTrailingPadding)
.onChange(of: isCurrentEditorContextEnabled) { newValue in
enableCurrentEditorContext = newValue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ struct ProgressToolCalls: View {
RunInTerminalToolView(tool: tool, chat: chat)
} else if tool.invokeParams != nil && tool.status == .waitForConfirmation {
ToolConfirmationView(tool: tool, chat: chat)
.scaledPadding(8)
} else {
ToolStatusItemView(tool: tool)
}
Expand All @@ -64,20 +63,26 @@ struct ToolConfirmationView: View {
.frame(maxWidth: .infinity, alignment: .leading)

HStack {
Button("Cancel") {
Button(action: {
chat.send(.toolCallCancelled(tool.id))
}) {
Text("Skip")
.scaledFont(.body)
}
.scaledFont(.body)

Button("Continue") {

Button(action: {
chat.send(.toolCallAccepted(tool.id))
}) {
Text("Allow")
.scaledFont(.body)
}
.buttonStyle(BorderedProminentButtonStyle())
.scaledFont(.body)

}
.frame(maxWidth: .infinity, alignment: .leading)
.scaledPadding(.top, 4)
}
.scaledPadding(8)
.cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
Expand Down
1 change: 0 additions & 1 deletion Core/Sources/ConversationTab/Views/UserMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ private struct MessageInputArea: View {
editorMode: editorMode
)
.frame(maxWidth: .infinity)
.chatPanelInputAreaPadding(editorMode)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct ChatHistoryView: View {
var body: some View {
WithPerceptionTracking {

VStack(alignment: .center, spacing: 8) {
VStack(alignment: .center, spacing: 0) {
Header(isChatHistoryVisible: $isChatHistoryVisible)
.scaledFrame(height: 32)
.scaledPadding(.leading, 12)
Expand All @@ -28,6 +28,7 @@ struct ChatHistoryView: View {
ChatHistorySearchBarView(searchText: $searchText)
.scaledPadding(.leading, 12)
.scaledPadding(.trailing, 8)
.scaledPadding(.vertical, 8)

ItemView(store: store, searchText: $searchText, isChatHistoryVisible: $isChatHistoryVisible)
.scaledPadding(.leading, 12)
Expand Down Expand Up @@ -222,6 +223,7 @@ struct ChatHistoryItemView: View {
.padding(.horizontal, 12)
}
.frame(maxHeight: .infinity)
.contentShape(Rectangle())
.onHover(perform: {
isHovered = $0
})
Expand Down
1 change: 0 additions & 1 deletion Core/Sources/SuggestionWidget/ChatWindowView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ struct ChatView: View {
Divider()

ChatTabContainer(store: store)
.scaledPadding(.horizontal, 16)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/Images/screen-record-permission-request.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 47 additions & 2 deletions TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ common issues:
- [Extension Permission](#extension-permission) - Allows GitHub Copilot to integrate with Xcode
- [Accessibility Permission](#accessibility-permission) - Enables real-time code suggestions
- [Background Permission](#background-permission) - Allows extension to connect with host app
- [Files & Folders Permission](#files--folders-permission) - Allows GitHub Copilot for Xcode to access files and folders
- [Screen & System Audio Recording Permission](#screen--system-audio-recording-permission-optional) (Optional) - Allow GitHub Copilot for Xcode to capture screen when using Copilot Vision

Please note that GitHub Copilot for Xcode may not work properly if any necessary permissions are missing.

Expand All @@ -30,7 +32,8 @@ Or you can navigate to the permission manually depending on your OS version:

| macOS | Location |
| :--- | :--- |
| 15 | System Settings > General > Login Items > Extensions > Xcode Source Editor |
| 26 | System Settings > General > Login Items & Extensions > Extensions > By Category > Xcode Source Editor |
| 15 | System Settings > General > Login Items & Extensions > Extensions > Xcode Source Editor |
| 13 & 14 | System Settings > Privacy & Security > Extensions > Xcode Source Editor |
| 12 | System Preferences > Extensions |

Expand Down Expand Up @@ -74,15 +77,57 @@ Please ensure that this permission is enabled. You can manually navigate to the

| macOS | Location |
| :--- | :--- |
| 26 | System Settings > General > Login Items & Extensions > App Background Activity |
| 15 | System Settings > General > Login Items & Extensions > Allow in the Background |
| 13 & 14 | System Settings > General > Login Items > Allow in the Background |

Ensure that "GitHub Copilot for Xcode" is enabled in the list of allowed background items. Without this permission, the extension may not be able to properly communicate with the host app, which can result in inconsistent behavior or reduced functionality.

## Files & Folders Permission

GitHub Copilot for Xcode needs permission to read your project’s files so it can:

- Use actual file contents as contextual grounding when you ask questions in Ask and Agent mode (instead of generic language-only answers)
- Safely apply or preview multi-file edits in Agent modes (e.g. refactors, adding tests, updating related types)
- Improve precision by leveraging nearby code, patterns, and naming conventions

<p align="center">
<img alt="Files & Folders Permission" src="./Docs/Images/document-folder-permission-request.png" width="400" />
</p>

When first prompted macOS shows a dialog asking to allow access to folders. Click "Allow".
If you clicked "Don't Allow" or nothing appears:

| macOS | Location |
| :--- | :--- |
| 13 & 14 & 15 & 26 | System Settings > Privacy & Security > Files and Folders |
| 12 | System Preferences > Security & Privacy > Privacy > Files and Folders |

In the list, expand `GitHub Copilot for Xcode` and enable the toggles for any relevant locations (e.g. “Documents” if your repositories live there). If your code is elsewhere (e.g. `~/Developer`), macOS may instead prompt dynamically the next time Copilot tries to read those paths—accept when prompted.

## Screen & System Audio Recording Permission (Optional)

This permission is only needed if you choose to use Copilot Vision (screen-based context capture).

Copilot does NOT require screen recording for standard inline suggestions, chat, or agent operations.

<p align="center">
<img alt="Screen & System Audio Recording Permission" src="./Docs/Images/screen-record-permission-request.png" width="400" />
</p>

This permission is typically granted automatically when you first use Copilot Vision and try to capture screen in GitHub Copilot for Xcode. You can also manually navigate to the background permission setting based on your macOS version:

| macOS | Location |
| :--- | :--- |
| 14 & 15 & 26 | System Settings > Privacy & Security > Screen & System Audio Recording |
| 13 | System Settings > Privacy & Security > Screen Recording |
| 12 | System Preferences > Security & Privacy > Privacy > Screen Recording |

Check `GitHub Copilot for Xcode` and restart the app.

## Logs

Logs can be found in `~/Library/Logs/GitHubCopilot/` the most recent log file
Logs can be found in `~/Library/Logs/GitHubCopilot/`. The most recent log file
is:

```
Expand Down