Skip to content

Commit 4d7635a

Browse files
committed
Merge branch 'feature/extra-system-prompt-in-prompt-to-code' into develop
2 parents 413d387 + 3f7efb1 commit 4d7635a

12 files changed

Lines changed: 106 additions & 36 deletions

File tree

Copilot for Xcode/CustomCommandView.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,10 @@ struct EditCustomCommandView: View {
176176
self.systemPrompt = systemPrompt ?? ""
177177
self.prompt = prompt ?? ""
178178
continuousMode = false
179-
case let .promptToCode(prompt, continuousMode):
179+
case let .promptToCode(extraSystemPrompt, prompt, continuousMode):
180180
commandType = .promptToCode
181181
self.prompt = prompt ?? ""
182-
systemPrompt = ""
182+
systemPrompt = extraSystemPrompt ?? ""
183183
self.continuousMode = continuousMode ?? false
184184
case .none:
185185
commandType = .chatWithSelection
@@ -214,6 +214,7 @@ struct EditCustomCommandView: View {
214214
systemPromptTextField(title: "Extra System Prompt")
215215
promptTextField
216216
case .promptToCode:
217+
systemPromptTextField(title: "Extra System Prompt")
217218
promptTextField
218219
continuousModeToggle
219220
case .customChat:
@@ -244,7 +245,11 @@ struct EditCustomCommandView: View {
244245
prompt: prompt
245246
)
246247
case .promptToCode:
247-
return .promptToCode(prompt: prompt, continuousMode: continuousMode)
248+
return .promptToCode(
249+
extraSystemPrompt: systemPrompt,
250+
prompt: prompt,
251+
continuousMode: continuousMode
252+
)
248253
case .customChat:
249254
return .customChat(systemPrompt: systemPrompt, prompt: prompt)
250255
}
@@ -335,7 +340,11 @@ struct CustomCommandView_Preview: PreviewProvider {
335340
),
336341
.init(
337342
name: "Refactor Code",
338-
feature: .promptToCode(prompt: "Refactor", continuousMode: false)
343+
feature: .promptToCode(
344+
extraSystemPrompt: nil,
345+
prompt: "Refactor",
346+
continuousMode: false
347+
)
339348
),
340349
.init(
341350
name: "Tell Me A Joke",

Copilot for Xcode/SettingsView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ struct SettingsView: View {
165165
case .openAI:
166166
Text("OpenAI").tag($0)
167167
case .githubCopilot:
168-
Text("GitHub Copilot (Less Accurate)").tag($0)
168+
Text("GitHub Copilot (Implement for experiment, barely works, don't use.)").tag($0)
169169
}
170170
}
171171
} label: {

Core/Sources/Preferences/CustomCommand.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public struct CustomCommand: Codable {
55
///
66
/// Keep everything optional so nothing will break when the format changes.
77
public enum Feature: Codable {
8-
case promptToCode(prompt: String?, continuousMode: Bool?)
8+
case promptToCode(extraSystemPrompt: String?, prompt: String?, continuousMode: Bool?)
99
case chatWithSelection(extraSystemPrompt: String?, prompt: String?)
1010
case customChat(systemPrompt: String?, prompt: String?)
1111
}

Core/Sources/Preferences/Keys.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ public extension UserDefaultPreferenceKeys {
236236
.init(
237237
name: "Add Documentation to Selection",
238238
feature: .promptToCode(
239+
extraSystemPrompt: nil,
239240
prompt: "Add documentation on top of the code. Use triple slash if the language supports it.",
240241
continuousMode: false
241242
)

Core/Sources/PromptToCodeService/CopilotPromptToCodeAPI.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ final class CopilotPromptToCodeAPI: PromptToCodeAPI {
1818
requirement: String,
1919
projectRootURL: URL,
2020
fileURL: URL,
21-
allCode: String
21+
allCode: String,
22+
extraSystemPrompt: String?
2223
) async throws -> AsyncThrowingStream<(code: String, description: String), Error> {
2324
let copilotService = CopilotSuggestionService(projectRootURL: projectRootURL)
2425
let relativePath = {
@@ -36,14 +37,25 @@ final class CopilotPromptToCodeAPI: PromptToCodeAPI {
3637
return filePath
3738
}()
3839

39-
let comment = """
40-
// update the following code, \(requirement.split(separator: "\n").joined(separator: " ")).
41-
\(code.split(separator: "\n").map { "//\($0)" }.joined(separator: "\n"))
40+
func convertToComment(_ s: String) -> String {
41+
s.split(separator: "\n").map { "// \($0)" }.joined(separator: "\n")
42+
}
4243

44+
let comment = """
45+
// A file to refactor the following code
46+
//
47+
// Code:
48+
// ```
49+
\(convertToComment(code))
50+
// ```
51+
//
52+
// Requirements:
53+
\(convertToComment((extraSystemPrompt ?? "\n") + requirement))
54+
//
4355
4456
45-
// Path: \(relativePath)
4657
58+
// end of file
4759
"""
4860
let lineCount = comment.breakLines().count
4961

@@ -53,7 +65,7 @@ final class CopilotPromptToCodeAPI: PromptToCodeAPI {
5365
let result = try await copilotService.getCompletions(
5466
fileURL: fileURL,
5567
content: comment,
56-
cursorPosition: .init(line: lineCount - 4, character: 0),
68+
cursorPosition: .init(line: lineCount - 3, character: 0),
5769
tabSize: indentSize,
5870
indentSize: indentSize,
5971
usesTabsForIndentation: usesTabsForIndentation,

Core/Sources/PromptToCodeService/OpenAIPromptToCodeAPI.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ final class OpenAIPromptToCodeAPI: PromptToCodeAPI {
2020
requirement: String,
2121
projectRootURL: URL,
2222
fileURL: URL,
23-
allCode: String
23+
allCode: String,
24+
extraSystemPrompt: String?
2425
) async throws -> AsyncThrowingStream<(code: String, description: String), Error> {
2526
let userPreferredLanguage = UserDefaults.shared.value(for: \.chatGPTLanguage)
2627
let textLanguage = userPreferredLanguage.isEmpty ? "" : "in \(userPreferredLanguage)"
@@ -38,25 +39,33 @@ final class OpenAIPromptToCodeAPI: PromptToCodeAPI {
3839
Please reply to me start with the code block, followed by a clear and concise description in 1-3 sentences about what you did \(
3940
textLanguage
4041
).
42+
43+
\(extraSystemPrompt ?? "")
4144
"""
4245
} else {
4346
return """
47+
# Description
48+
4449
You are a senior programer in writing code in \(language.rawValue).
4550
4651
Please mutate the following code fragment with my requirements. Keep the original indentation. Do not add comments unless told to.
4752
4853
Please reply to me start with the code block followed by a clear and concise description about what you did in 1-3 sentences \(
4954
textLanguage
5055
).
56+
57+
\(extraSystemPrompt ?? "")
5158
59+
# Code
60+
5261
```
5362
\(code)
5463
```
5564
"""
5665
}
5766
}()
5867

59-
let chatGPTService = ChatGPTService(systemPrompt: prompt, temperature: 0.5)
68+
let chatGPTService = ChatGPTService(systemPrompt: prompt, temperature: 0.3)
6069
service = chatGPTService
6170
let stream = try await chatGPTService.send(content: requirement)
6271
return .init { continuation in

Core/Sources/PromptToCodeService/PromptToCodeService.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public final class PromptToCodeService: ObservableObject {
5353
public var projectRootURL: URL
5454
public var fileURL: URL
5555
public var allCode: String
56+
public var extraSystemPrompt: String?
5657

5758
public init(
5859
code: String,
@@ -62,7 +63,8 @@ public final class PromptToCodeService: ObservableObject {
6263
usesTabsForIndentation: Bool,
6364
projectRootURL: URL,
6465
fileURL: URL,
65-
allCode: String
66+
allCode: String,
67+
extraSystemPrompt: String? = nil
6668
) {
6769
self.code = code
6870
self.selectionRange = selectionRange
@@ -73,6 +75,7 @@ public final class PromptToCodeService: ObservableObject {
7375
self.fileURL = fileURL
7476
self.allCode = allCode
7577
self.history = .empty
78+
self.extraSystemPrompt = extraSystemPrompt
7679
}
7780

7881
public func modifyCode(prompt: String) async throws {
@@ -93,7 +96,8 @@ public final class PromptToCodeService: ObservableObject {
9396
requirement: prompt,
9497
projectRootURL: projectRootURL,
9598
fileURL: fileURL,
96-
allCode: allCode
99+
allCode: allCode,
100+
extraSystemPrompt: extraSystemPrompt
97101
)
98102
for try await fragment in stream {
99103
code = fragment.code
@@ -145,7 +149,8 @@ protocol PromptToCodeAPI {
145149
requirement: String,
146150
projectRootURL: URL,
147151
fileURL: URL,
148-
allCode: String
152+
allCode: String,
153+
extraSystemPrompt: String?
149154
) async throws -> AsyncThrowingStream<(code: String, description: String), Error>
150155

151156
func stopResponding()

Core/Sources/Service/GUI/PromptToCodeProvider+Service.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ import PromptToCodeService
33
import SuggestionWidget
44

55
extension PromptToCodeProvider {
6-
convenience init(service: PromptToCodeService, onClosePromptToCode: @escaping () -> Void) {
6+
convenience init(
7+
service: PromptToCodeService,
8+
name: String?,
9+
onClosePromptToCode: @escaping () -> Void
10+
) {
711
self.init(
812
code: service.code,
913
language: service.language.rawValue,
1014
description: "",
1115
startLineIndex: service.selectionRange.start.line,
12-
startLineColumn: service.selectionRange.start.character
16+
startLineColumn: service.selectionRange.start.character,
17+
name: name
1318
)
1419

1520
var cancellables = Set<AnyCancellable>()
@@ -44,18 +49,18 @@ extension PromptToCodeProvider {
4449
}
4550
}
4651
}
47-
52+
4853
onStopRespondingTap = {
4954
service.stopResponding()
5055
}
51-
56+
5257
onAcceptSuggestionTapped = {
5358
Task { @ServiceActor in
5459
let handler = PseudoCommandHandler()
5560
await handler.acceptSuggestion()
5661
}
5762
}
58-
63+
5964
onContinuousToggleClick = {
6065
service.isContinuous.toggle()
6166
}

Core/Sources/Service/GUI/WidgetDataSource.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ final class WidgetDataSource {
9191
selectionRange: CursorRange,
9292
language: CopilotLanguage,
9393
identSize: Int = 4,
94-
usesTabsForIndentation: Bool = false
94+
usesTabsForIndentation: Bool = false,
95+
extraSystemPrompt: String?,
96+
name: String?
9597
) async -> PromptToCodeService {
9698
let build = {
9799
let service = PromptToCodeService(
@@ -102,10 +104,12 @@ final class WidgetDataSource {
102104
usesTabsForIndentation: usesTabsForIndentation,
103105
projectRootURL: projectURL,
104106
fileURL: url,
105-
allCode: allCode
107+
allCode: allCode,
108+
extraSystemPrompt: extraSystemPrompt
106109
)
107110
let provider = PromptToCodeProvider(
108111
service: service,
112+
name: name,
109113
onClosePromptToCode: { [weak self] in
110114
self?.removePromptToCode(for: url)
111115
let presenter = PresentInWindowSuggestionPresenter()

Core/Sources/Service/SuggestionCommandHandler/WindowBaseCommandHandler.swift

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,13 @@ struct WindowBaseCommandHandler: SuggestionCommandHandler {
248248
func promptToCode(editor: EditorContent) async throws -> UpdatedContent? {
249249
Task {
250250
do {
251-
try await presentPromptToCode(editor: editor, prompt: nil, isContinuous: false)
251+
try await presentPromptToCode(
252+
editor: editor,
253+
extraSystemPrompt: nil,
254+
prompt: nil,
255+
isContinuous: false,
256+
name: nil
257+
)
252258
} catch {
253259
presenter.presentError(error)
254260
}
@@ -293,19 +299,23 @@ extension WindowBaseCommandHandler {
293299
extraSystemPrompt: nil,
294300
sendingMessageImmediately: prompt
295301
)
296-
case let .promptToCode(prompt, continuousMode):
302+
case let .promptToCode(extraSystemPrompt, prompt, continuousMode):
297303
try await presentPromptToCode(
298304
editor: editor,
305+
extraSystemPrompt: extraSystemPrompt,
299306
prompt: prompt,
300-
isContinuous: continuousMode ?? false
307+
isContinuous: continuousMode ?? false,
308+
name: command.name
301309
)
302310
}
303311
}
304312

305313
func presentPromptToCode(
306314
editor: EditorContent,
315+
extraSystemPrompt: String?,
307316
prompt: String?,
308-
isContinuous: Bool
317+
isContinuous: Bool,
318+
name: String?
309319
) async throws {
310320
presenter.markAsProcessing(true)
311321
defer { presenter.markAsProcessing(false) }
@@ -323,7 +333,7 @@ extension WindowBaseCommandHandler {
323333
guard var selection = editor.selections.last,
324334
selection.start != selection.end
325335
else { return ("", .cursor(editor.cursorPosition)) }
326-
336+
327337
let isMultipleLine = selection.start.line != selection.end.line
328338
let isSpaceOnlyBeforeStartPositionOnTheSameLine = {
329339
guard selection.start.line >= 0, selection.start.line < editor.lines.count else {
@@ -333,10 +343,12 @@ extension WindowBaseCommandHandler {
333343
guard selection.start.character > 0, selection.start.character < line.count else {
334344
return false
335345
}
336-
let substring = line[line.startIndex..<line.index(line.startIndex, offsetBy: selection.start.character)]
337-
return substring.allSatisfy({ $0.isWhitespace })
346+
let substring =
347+
line[line.startIndex..<line
348+
.index(line.startIndex, offsetBy: selection.start.character)]
349+
return substring.allSatisfy { $0.isWhitespace }
338350
}()
339-
351+
340352
if isMultipleLine || isSpaceOnlyBeforeStartPositionOnTheSameLine {
341353
// when there are multiple lines start from char 0 so that it can keep the
342354
// indentation.
@@ -357,11 +369,13 @@ extension WindowBaseCommandHandler {
357369
selectedCode: code,
358370
allCode: editor.content,
359371
selectionRange: selection,
360-
language: codeLanguage
372+
language: codeLanguage,
373+
extraSystemPrompt: extraSystemPrompt,
374+
name: name
361375
)
362376

363377
promptToCode.isContinuous = isContinuous
364-
if let prompt {
378+
if let prompt, !prompt.isEmpty {
365379
Task { try await promptToCode.modifyCode(prompt: prompt) }
366380
}
367381

@@ -402,7 +416,7 @@ extension WindowBaseCommandHandler {
402416
```
403417
"""
404418
}()
405-
419+
406420
if let extraSystemPrompt {
407421
systemPrompt += "\n\(extraSystemPrompt)"
408422
}

0 commit comments

Comments
 (0)