Skip to content

Commit 365050d

Browse files
committed
Merge branch 'release/0.30.5'
2 parents 50c9a8e + d586dad commit 365050d

42 files changed

Lines changed: 507 additions & 244 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Core/Sources/ChatPlugin/TerminalChatPlugin.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public actor TerminalChatPlugin: ChatPlugin {
3434
}
3535

3636
do {
37-
let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL
38-
let projectURL = XcodeInspector.shared.realtimeActiveProjectURL
37+
let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
38+
let projectURL = await XcodeInspector.shared.safe.realtimeActiveProjectURL
3939

4040
var environment = [String: String]()
4141
if let fileURL {

Core/Sources/ChatService/ChatService.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,14 @@ public final class ChatService: ObservableObject {
217217
guard let info else { return }
218218

219219
let templateProcessor = CustomCommandTemplateProcessor()
220-
mutateSystemPrompt(info.specifiedSystemPrompt.map(templateProcessor.process))
221-
mutateExtraSystemPrompt(info.extraSystemPrompt.map(templateProcessor.process) ?? "")
220+
if let specifiedSystemPrompt = info.specifiedSystemPrompt {
221+
await mutateSystemPrompt(templateProcessor.process(specifiedSystemPrompt))
222+
}
223+
if let extraSystemPrompt = info.extraSystemPrompt {
224+
await mutateExtraSystemPrompt(templateProcessor.process(extraSystemPrompt))
225+
} else {
226+
mutateExtraSystemPrompt("")
227+
}
222228

223229
let customCommandPrefix = {
224230
if let name = info.name { return "[\(name)] " }
@@ -250,9 +256,9 @@ public final class ChatService: ObservableObject {
250256
let templateProcessor = CustomCommandTemplateProcessor()
251257
if let systemPrompt {
252258
if overwriteSystemPrompt {
253-
mutateSystemPrompt(templateProcessor.process(systemPrompt))
259+
await mutateSystemPrompt(templateProcessor.process(systemPrompt))
254260
} else {
255-
mutateExtraSystemPrompt(templateProcessor.process(systemPrompt))
261+
await mutateExtraSystemPrompt(templateProcessor.process(systemPrompt))
256262
}
257263
}
258264
return try await sendAndWait(content: templateProcessor.process(prompt))
@@ -265,10 +271,10 @@ public final class ChatService: ObservableObject {
265271
) async throws -> String {
266272
let templateProcessor = CustomCommandTemplateProcessor()
267273
if let systemPrompt {
268-
mutateSystemPrompt(templateProcessor.process(systemPrompt))
274+
await mutateSystemPrompt(templateProcessor.process(systemPrompt))
269275
}
270276
if let extraSystemPrompt {
271-
mutateExtraSystemPrompt(templateProcessor.process(extraSystemPrompt))
277+
await mutateExtraSystemPrompt(templateProcessor.process(extraSystemPrompt))
272278
}
273279
return try await sendAndWait(content: templateProcessor.process(prompt))
274280
}

Core/Sources/ChatService/ContextAwareAutoManagedChatGPTMemory.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public final class ContextAwareAutoManagedChatGPTMemory: ChatGPTMemory {
4444
systemPrompt: """
4545
\(chatService?.systemPrompt ?? "")
4646
\(chatService?.extraSystemPrompt ?? "")
47-
""",
47+
""".trimmingCharacters(in: .whitespacesAndNewlines),
4848
content: content ?? ""
4949
)
5050
return await memory.generatePrompt()

Core/Sources/ChatService/CustomCommandTemplateProcessor.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import XcodeInspector
66
public struct CustomCommandTemplateProcessor {
77
public init() {}
88

9-
public func process(_ text: String) -> String {
10-
let info = getEditorInformation()
9+
public func process(_ text: String) async -> String {
10+
let info = await getEditorInformation()
1111
let editorContent = info.editorContent
1212
let updatedText = text
1313
.replacingOccurrences(of: "{{selected_code}}", with: """
@@ -38,9 +38,9 @@ public struct CustomCommandTemplateProcessor {
3838
let documentURL: URL?
3939
}
4040

41-
func getEditorInformation() -> EditorInformation {
42-
let editorContent = XcodeInspector.shared.focusedEditor?.getContent()
43-
let documentURL = XcodeInspector.shared.activeDocumentURL
41+
func getEditorInformation() async -> EditorInformation {
42+
let editorContent = await XcodeInspector.shared.safe.focusedEditor?.getContent()
43+
let documentURL = await XcodeInspector.shared.safe.activeDocumentURL
4444
let language = documentURL.map(languageIdentifierFromFileURL) ?? .plaintext
4545

4646
return .init(

Core/Sources/ChatService/DynamicContextController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ final class DynamicContextController {
106106
let contextualSystemPrompt = """
107107
\(language.isEmpty ? "" : "You must always reply in \(language)")
108108
\(systemPrompt)
109-
"""
109+
""".trimmingCharacters(in: .whitespacesAndNewlines)
110110
await memory.mutateSystemPrompt(contextualSystemPrompt)
111111
await memory.mutateContextSystemPrompt(contextSystemPrompt)
112112
await memory.mutateRetrievedContent(retrievedContent.map(\.document))

Core/Sources/HostApp/AccountSettings/GitHubCopilotView.swift

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct GitHubCopilotView: View {
1919
@AppStorage(\.gitHubCopilotProxyUsername) var gitHubCopilotProxyUsername
2020
@AppStorage(\.gitHubCopilotProxyPassword) var gitHubCopilotProxyPassword
2121
@AppStorage(\.gitHubCopilotUseStrictSSL) var gitHubCopilotUseStrictSSL
22+
@AppStorage(\.gitHubCopilotEnterpriseURI) var gitHubCopilotEnterpriseURI
2223
@AppStorage(\.gitHubCopilotIgnoreTrailingNewLines)
2324
var gitHubCopilotIgnoreTrailingNewLines
2425
@AppStorage(\.disableGitHubCopilotSettingsAutoRefreshOnAppear)
@@ -157,15 +158,15 @@ struct GitHubCopilotView: View {
157158
) {
158159
Text("Path to Node (v18+)")
159160
}
160-
161+
161162
Text(
162163
"Provide the path to the executable if it can't be found by the app, shim executable is not supported"
163164
)
164165
.lineLimit(10)
165166
.foregroundColor(.secondary)
166167
.font(.callout)
167168
.dynamicHeightTextInFormWorkaround()
168-
169+
169170
Picker(selection: $settings.runNodeWith) {
170171
ForEach(NodeRunner.allCases, id: \.rawValue) { runner in
171172
switch runner {
@@ -180,7 +181,7 @@ struct GitHubCopilotView: View {
180181
} label: {
181182
Text("Run Node with")
182183
}
183-
184+
184185
Group {
185186
switch settings.runNodeWith {
186187
case .env:
@@ -257,6 +258,10 @@ struct GitHubCopilotView: View {
257258
}
258259
.opacity(isRunningAction ? 0.8 : 1)
259260
.disabled(isRunningAction)
261+
262+
Button("Refresh Configuration for Enterprise and Proxy") {
263+
refreshConfiguration()
264+
}
260265
}
261266

262267
SettingsDivider("Advanced")
@@ -276,6 +281,17 @@ struct GitHubCopilotView: View {
276281
Toggle("Verbose Log", isOn: $settings.gitHubCopilotVerboseLog)
277282
}
278283

284+
SettingsDivider("Enterprise")
285+
286+
Form {
287+
TextField(
288+
text: $settings.gitHubCopilotEnterpriseURI,
289+
prompt: Text("Leave it blank if non is available.")
290+
) {
291+
Text("Auth Provider URL")
292+
}
293+
}
294+
279295
SettingsDivider("Proxy")
280296

281297
Form {
@@ -403,6 +419,25 @@ struct GitHubCopilotView: View {
403419
}
404420
}
405421
}
422+
423+
func refreshConfiguration() {
424+
NotificationCenter.default.post(
425+
name: .gitHubCopilotShouldRefreshEditorInformation,
426+
object: nil
427+
)
428+
429+
Task {
430+
let service = try getService()
431+
do {
432+
try await service.postNotification(
433+
name: Notification.Name
434+
.gitHubCopilotShouldRefreshEditorInformation.rawValue
435+
)
436+
} catch {
437+
toast(error.localizedDescription, .error)
438+
}
439+
}
440+
}
406441
}
407442

408443
struct ActivityIndicatorView: NSViewRepresentable {

Core/Sources/PromptToCodeService/OpenAIPromptToCodeService.swift

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,23 @@ public final class OpenAIPromptToCodeService: PromptToCodeServiceType {
3131
return userPreferredLanguage.isEmpty ? "" : " in \(userPreferredLanguage)"
3232
}()
3333

34-
let editor: EditorInformation = XcodeInspector.shared.getFocusedEditorContent() ?? .init(
35-
editorContent: .init(
36-
content: source.content,
37-
lines: source.lines,
38-
selections: [source.range],
39-
cursorPosition: .outOfScope,
40-
lineAnnotations: []
41-
),
42-
selectedContent: code,
43-
selectedLines: [],
44-
documentURL: source.documentURL,
45-
workspaceURL: source.projectRootURL,
46-
projectRootURL: source.projectRootURL,
47-
relativePath: "",
48-
language: source.language
49-
)
34+
let editor: EditorInformation = await XcodeInspector.shared.getFocusedEditorContent()
35+
?? .init(
36+
editorContent: .init(
37+
content: source.content,
38+
lines: source.lines,
39+
selections: [source.range],
40+
cursorPosition: .outOfScope,
41+
lineAnnotations: []
42+
),
43+
selectedContent: code,
44+
selectedLines: [],
45+
documentURL: source.documentURL,
46+
workspaceURL: source.projectRootURL,
47+
projectRootURL: source.projectRootURL,
48+
relativePath: "",
49+
language: source.language
50+
)
5051

5152
let rule: String = {
5253
func generateDescription(index: Int) -> String {

Core/Sources/Service/RealtimeSuggestionController.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public actor RealtimeSuggestionController {
4545
private func handleFocusElementChange(_ sourceEditor: SourceEditor) {
4646
Task { // Notify suggestion service for open file.
4747
try await Task.sleep(nanoseconds: 500_000_000)
48-
guard let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL else { return }
48+
guard let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
49+
else { return }
4950
_ = try await Service.shared.workspacePool
5051
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
5152
}
@@ -58,15 +59,16 @@ public actor RealtimeSuggestionController {
5859
editorObservationTask = nil
5960

6061
editorObservationTask = Task { [weak self] in
61-
if let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL {
62+
if let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL {
6263
await PseudoCommandHandler().invalidateRealtimeSuggestionsIfNeeded(
6364
fileURL: fileURL,
6465
sourceEditor: sourceEditor
6566
)
6667
}
6768

68-
let valueChange = notificationsFromEditor.filter { $0.kind == .valueChanged }
69-
let selectedTextChanged = notificationsFromEditor
69+
let valueChange = await notificationsFromEditor.notifications()
70+
.filter { $0.kind == .valueChanged }
71+
let selectedTextChanged = await notificationsFromEditor.notifications()
7072
.filter { $0.kind == .selectedTextChanged }
7173

7274
await withTaskGroup(of: Void.self) { [weak self] group in
@@ -92,7 +94,8 @@ public actor RealtimeSuggestionController {
9294
}
9395
group.addTask {
9496
let handler = {
95-
guard let fileURL = XcodeInspector.shared.activeDocumentURL else { return }
97+
guard let fileURL = await XcodeInspector.shared.safe.activeDocumentURL
98+
else { return }
9699
await PseudoCommandHandler().invalidateRealtimeSuggestionsIfNeeded(
97100
fileURL: fileURL,
98101
sourceEditor: sourceEditor
@@ -118,7 +121,8 @@ public actor RealtimeSuggestionController {
118121

119122
Task { @WorkspaceActor in // Get cache ready for real-time suggestions.
120123
guard UserDefaults.shared.value(for: \.preCacheOnFileOpen) else { return }
121-
guard let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL else { return }
124+
guard let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
125+
else { return }
122126
let (_, filespace) = try await Service.shared.workspacePool
123127
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
124128

@@ -127,7 +131,7 @@ public actor RealtimeSuggestionController {
127131
// avoid the command get called twice
128132
filespace.codeMetadata.uti = ""
129133
do {
130-
try await XcodeInspector.shared.latestActiveXcode?
134+
try await XcodeInspector.shared.safe.latestActiveXcode?
131135
.triggerCopilotCommand(name: "Real-time Suggestions")
132136
} catch {
133137
if filespace.codeMetadata.uti?.isEmpty ?? true {
@@ -141,7 +145,7 @@ public actor RealtimeSuggestionController {
141145
func triggerPrefetchDebounced(force: Bool = false) {
142146
inflightPrefetchTask = Task(priority: .utility) { @WorkspaceActor in
143147
try? await Task.sleep(nanoseconds: UInt64(
144-
max(UserDefaults.shared.value(for: \.realtimeSuggestionDebounce), 0.15)
148+
max(UserDefaults.shared.value(for: \.realtimeSuggestionDebounce), 0.25)
145149
* 1_000_000_000
146150
))
147151

@@ -151,7 +155,7 @@ public actor RealtimeSuggestionController {
151155
else { return }
152156

153157
if UserDefaults.shared.value(for: \.disableSuggestionFeatureGlobally),
154-
let fileURL = XcodeInspector.shared.activeDocumentURL,
158+
let fileURL = await XcodeInspector.shared.safe.activeDocumentURL,
155159
let (workspace, _) = try? await Service.shared.workspacePool
156160
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
157161
{
@@ -188,7 +192,7 @@ public actor RealtimeSuggestionController {
188192
}
189193

190194
func notifyEditingFileChange(editor: AXUIElement) async {
191-
guard let fileURL = XcodeInspector.shared.activeDocumentURL,
195+
guard let fileURL = await XcodeInspector.shared.safe.activeDocumentURL,
192196
let (workspace, _) = try? await Service.shared.workspacePool
193197
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
194198
else { return }

Core/Sources/Service/SuggestionCommandHandler/PseudoCommandHandler.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ struct PseudoCommandHandler {
159159
}
160160
}() else {
161161
do {
162-
try await XcodeInspector.shared.latestActiveXcode?
162+
try await XcodeInspector.shared.safe.latestActiveXcode?
163163
.triggerCopilotCommand(name: command.name)
164164
} catch {
165165
let presenter = PresentInWindowSuggestionPresenter()
@@ -183,7 +183,7 @@ struct PseudoCommandHandler {
183183
throw CancellationError()
184184
}
185185
do {
186-
try await XcodeInspector.shared.latestActiveXcode?
186+
try await XcodeInspector.shared.safe.latestActiveXcode?
187187
.triggerCopilotCommand(name: "Accept Prompt to Code")
188188
} catch {
189189
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
@@ -238,7 +238,7 @@ struct PseudoCommandHandler {
238238
throw CancellationError()
239239
}
240240
do {
241-
try await XcodeInspector.shared.latestActiveXcode?
241+
try await XcodeInspector.shared.safe.latestActiveXcode?
242242
.triggerCopilotCommand(name: "Accept Suggestion")
243243
} catch {
244244
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
@@ -288,7 +288,7 @@ struct PseudoCommandHandler {
288288
}
289289

290290
func dismissSuggestion() async {
291-
guard let documentURL = XcodeInspector.shared.activeDocumentURL else { return }
291+
guard let documentURL = await XcodeInspector.shared.safe.activeDocumentURL else { return }
292292
guard let (_, filespace) = try? await Service.shared.workspacePool
293293
.fetchOrCreateWorkspaceAndFilespace(fileURL: documentURL) else { return }
294294

@@ -377,14 +377,14 @@ extension PseudoCommandHandler {
377377
return (content, split, [range], range.start)
378378
}
379379

380-
func getFileURL() -> URL? {
381-
XcodeInspector.shared.realtimeActiveDocumentURL
380+
func getFileURL() async -> URL? {
381+
await XcodeInspector.shared.safe.realtimeActiveDocumentURL
382382
}
383383

384384
@WorkspaceActor
385385
func getFilespace() async -> Filespace? {
386386
guard
387-
let fileURL = getFileURL(),
387+
let fileURL = await getFileURL(),
388388
let (_, filespace) = try? await Service.shared.workspacePool
389389
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
390390
else { return nil }
@@ -394,7 +394,10 @@ extension PseudoCommandHandler {
394394
@WorkspaceActor
395395
func getEditorContent(sourceEditor: SourceEditor?) async -> EditorContent? {
396396
guard let filespace = await getFilespace(),
397-
let sourceEditor = sourceEditor ?? XcodeInspector.shared.focusedEditor
397+
let sourceEditor = await {
398+
if let sourceEditor { sourceEditor }
399+
else { await XcodeInspector.shared.safe.focusedEditor }
400+
}()
398401
else { return nil }
399402
if Task.isCancelled { return nil }
400403
let content = sourceEditor.getContent()

0 commit comments

Comments
 (0)