Skip to content

Commit bf7d6c4

Browse files
committed
Merge tag '0.11.0' into develop
2 parents 381e64d + 3aec08a commit bf7d6c4

File tree

10 files changed

+74
-29
lines changed

10 files changed

+74
-29
lines changed

Core/Sources/CopilotService/CopilotService.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ public class CopilotBaseService {
5151
try? FileManager.default
5252
.createDirectory(at: supportURL, withIntermediateDirectories: false)
5353
}
54+
var userEnvPath = ProcessInfo.processInfo.userEnvironment["PATH"] ?? ""
55+
if userEnvPath.isEmpty {
56+
userEnvPath = "/usr/bin:/usr/local/bin" // fallback
57+
}
5458
let executionParams = {
5559
let nodePath = UserDefaults.shared.value(for: \.nodePath)
5660
return Process.ExecutionParameters(
@@ -65,7 +69,7 @@ public class CopilotBaseService {
6569
"--stdio",
6670
],
6771
environment: [
68-
"PATH": "/usr/bin:/usr/local/bin",
72+
"PATH": userEnvPath,
6973
],
7074
currentDirectoryURL: supportURL
7175
)

Core/Sources/OpenAIService/ChatGPTService.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ public actor ChatGPTService: ChatGPTServiceType {
128128
Task {
129129
do {
130130
let (trunks, cancel) = try await api()
131+
guard isReceivingMessage else {
132+
continuation.finish()
133+
return
134+
}
131135
cancelTask = cancel
132136
for try await trunk in trunks {
133137
guard let delta = trunk.choices.first?.delta else { continue }

Core/Sources/OpenAIService/CompletionStreamAPI.swift

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,28 +89,34 @@ struct OpenAICompletionStreamAPI: CompletionStreamAPI {
8989
let error = try? decoder.decode(ChatGPTError.self, from: data)
9090
throw error ?? ChatGPTServiceError.responseInvalid
9191
}
92-
93-
return (
94-
AsyncThrowingStream<CompletionStreamDataTrunk, Error> { continuation in
95-
Task {
96-
do {
97-
for try await line in result.lines {
98-
let prefix = "data: "
99-
guard line.hasPrefix(prefix),
100-
let content = line.dropFirst(prefix.count).data(using: .utf8),
101-
let trunk = try? JSONDecoder()
102-
.decode(CompletionStreamDataTrunk.self, from: content)
103-
else { continue }
104-
continuation.yield(trunk)
105-
}
106-
continuation.finish()
107-
} catch {
108-
continuation.finish(throwing: error)
92+
93+
var receivingDataTask: Task<Void, Error>?
94+
95+
let stream = AsyncThrowingStream<CompletionStreamDataTrunk, Error> { continuation in
96+
receivingDataTask = Task {
97+
do {
98+
for try await line in result.lines {
99+
if Task.isCancelled { break }
100+
let prefix = "data: "
101+
guard line.hasPrefix(prefix),
102+
let content = line.dropFirst(prefix.count).data(using: .utf8),
103+
let trunk = try? JSONDecoder()
104+
.decode(CompletionStreamDataTrunk.self, from: content)
105+
else { continue }
106+
continuation.yield(trunk)
109107
}
108+
continuation.finish()
109+
} catch {
110+
continuation.finish(throwing: error)
110111
}
111-
},
112+
}
113+
}
114+
115+
return (
116+
stream,
112117
Cancellable {
113118
result.task.cancel()
119+
receivingDataTask?.cancel()
114120
}
115121
)
116122
}

Core/Sources/Service/GUI/WidgetDataSource.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ final class WidgetDataSource {
88

99
var globalChat: ChatService?
1010
var chats = [URL: ChatService]()
11+
var globalChatProvider: ChatProvider?
12+
var chatProviders = [URL: ChatProvider]()
1113

1214
private init() {}
1315

1416
@discardableResult
1517
func createChatIfNeeded(for url: URL) -> ChatService {
1618
let useGlobalChat = UserDefaults.shared.value(for: \.useGlobalChat)
1719
let chat: ChatService
20+
1821
if useGlobalChat {
1922
chat = globalChat ?? ChatService(chatGPTService: ChatGPTService())
2023
globalChat = chat
@@ -77,8 +80,10 @@ extension WidgetDataSource: SuggestionWidgetDataSource {
7780
onCloseChat: { [weak self] in
7881
if UserDefaults.shared.value(for: \.useGlobalChat) {
7982
self?.globalChat = nil
83+
self?.globalChatProvider = nil
8084
} else {
8185
self?.chats[url] = nil
86+
self?.chatProviders[url] = nil
8287
}
8388
let presenter = PresentInWindowSuggestionPresenter()
8489
presenter.closeChatRoom(fileURL: url)
@@ -94,12 +99,20 @@ extension WidgetDataSource: SuggestionWidgetDataSource {
9499
}
95100

96101
if useGlobalChat {
97-
if let globalChat {
98-
return buildChatProvider(globalChat)
102+
if let globalChatProvider {
103+
return globalChatProvider
104+
} else if let globalChat {
105+
let new = buildChatProvider(globalChat)
106+
self.globalChatProvider = new
107+
return new
99108
}
100109
} else {
101-
if let service = chats[url] {
102-
return buildChatProvider(service)
110+
if let provider = chatProviders[url] {
111+
return provider
112+
} else if let service = chats[url] {
113+
let new = buildChatProvider(service)
114+
self.chatProviders[url] = new
115+
return new
103116
}
104117
}
105118

Core/Sources/Service/ScheduledCleaner.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public final class ScheduledCleaner {
1515
for (url, filespace) in filespaces {
1616
if filespace.isExpired {
1717
WidgetDataSource.shared.chats[url] = nil
18+
WidgetDataSource.shared.chatProviders[url] = nil
1819
}
1920
}
2021
// cleanup workspace

Core/Sources/SuggestionWidget/ChatProvider.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Foundation
22
import SwiftUI
33

44
public final class ChatProvider: ObservableObject {
5+
let id = UUID()
56
@Published public var history: [ChatMessage] = []
67
@Published public var isReceivingMessage = false
78
public var onMessageSend: (String) -> Void

Core/Sources/SuggestionWidget/SuggestionWidgetController.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,9 @@ extension SuggestionWidgetController {
444444
}
445445

446446
if let chat = await dataSource?.chatForFile(at: fileURL) {
447-
suggestionPanelViewModel.chat = chat
447+
if suggestionPanelViewModel.chat?.id != chat.id {
448+
suggestionPanelViewModel.chat = chat
449+
}
448450
} else {
449451
suggestionPanelViewModel.chat = nil
450452
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Or install it manually, by downloading the `Copilot for Xcode.app` from the late
5959
Then set it up with the following steps:
6060

6161
1. Open the app, the app will create a launch agent to setup a background running Service that does the real job.
62-
2. Optionally setup the path to Node. The default value is just `node`, Copilot for Xcode.app will try to find the Node from `/usr/bin:/usr/local/bin`. If your Node is installed somewhere else, you can run `which node` from terminal to get the path.
62+
2. Optionally setup the path to Node. The default value is just `node`, Copilot for Xcode.app will try to find the Node from the PATH available in a login shell. If your Node is installed somewhere else, you can run `which node` from terminal to get the path.
6363

6464
### Enable the Extension
6565

Version.xcconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
APP_VERSION = 0.10.0
2-
APP_BUILD = 70
1+
APP_VERSION = 0.11.0
2+
APP_BUILD = 80

appcast.xml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
33
<channel>
44
<title>Copilot for Xcode</title>
5+
<item>
6+
<title>0.11.0</title>
7+
<pubDate>Sat, 08 Apr 2023 23:32:22 +0800</pubDate>
8+
<sparkle:version>80</sparkle:version>
9+
<sparkle:shortVersionString>0.11.0</sparkle:shortVersionString>
10+
<sparkle:minimumSystemVersion>12.0</sparkle:minimumSystemVersion>
11+
<sparkle:releaseNotesLink>
12+
https://github.com/intitni/CopilotForXcode/releases/tag/0.11.0
13+
</sparkle:releaseNotesLink>
14+
<enclosure
15+
url="https://github.com/intitni/CopilotForXcode/releases/download/0.11.0/Copilot.for.Xcode.app.zip"
16+
length="19040986" type="application/octet-stream"
17+
sparkle:edSignature="VqjW63XWJdCnQYlRzOqQrKSNVp5E4S2GswlpbOh4aUW2grgget1BCcHUFKQqsc45gbGM7U79SVN236ZNjdL2CA==" />
18+
</item>
19+
520
<item>
621
<title>0.10.0</title>
722
<pubDate>Fri, 31 Mar 2023 23:12:28 +0800</pubDate>
@@ -18,8 +33,7 @@
1833
</item>
1934

2035
<item>
21-
<title>
22-
0.9.0</title>
36+
<title>0.9.0</title>
2337
<pubDate>Sat, 25 Mar 2023 23:43:42 +0800</pubDate>
2438
<sparkle:version>62</sparkle:version>
2539
<sparkle:shortVersionString>0.9.0</sparkle:shortVersionString>

0 commit comments

Comments
 (0)