forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChatService.swift
More file actions
86 lines (72 loc) · 2.93 KB
/
ChatService.swift
File metadata and controls
86 lines (72 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import ChatPlugins
import Combine
import Foundation
import OpenAIService
let defaultSystemPrompt = """
You are an AI programming assistant.
You reply should be concise, clear, informative and logical.
You MUST reply in the format of markdown.
You MUST embed every code you provide in a markdown code block.
You MUST add the programming language name at the start of the markdown code block.
If you are asked to help perform a task, you MUST think step-by-step, then describe each step concisely.
If you are asked to explain code, you MUST explain it step-by-step in a ordered list.
Make your answer short and structured.
"""
public final class ChatService: ObservableObject {
public let chatGPTService: any ChatGPTServiceType
let pluginController: ChatPluginController
let contextController: DynamicContextController
var cancellable = Set<AnyCancellable>()
var systemPrompt = defaultSystemPrompt
var extraSystemPrompt = ""
public init<T: ChatGPTServiceType>(chatGPTService: T) {
self.chatGPTService = chatGPTService
pluginController = ChatPluginController(
chatGPTService: chatGPTService,
plugins:
TerminalChatPlugin.self,
AITerminalChatPlugin.self
)
contextController = DynamicContextController(chatGPTService: chatGPTService)
chatGPTService.objectWillChange.sink { [weak self] _ in
self?.objectWillChange.send()
}.store(in: &cancellable)
}
public func send(content: String) async throws {
let handledInPlugin = try await pluginController.handleContent(content)
if handledInPlugin { return }
try await contextController.updatePromptToMatchContent(systemPrompt: """
\(systemPrompt)
\(extraSystemPrompt)
""")
_ = try await chatGPTService.send(content: content, summary: nil)
}
public func stopReceivingMessage() async {
await pluginController.stopResponding()
await chatGPTService.stopReceivingMessage()
}
public func clearHistory() async {
await pluginController.cancel()
await chatGPTService.clearHistory()
}
public func deleteMessage(id: String) async {
await chatGPTService.mutateHistory { messages in
messages.removeAll(where: { $0.id == id })
}
}
public func resendMessage(id: String) async throws {
if let message = (await chatGPTService.history).first(where: { $0.id == id }) {
try await send(content: message.content)
}
}
/// Setting it to `nil` to reset the system prompt
public func mutateSystemPrompt(_ newPrompt: String?) {
systemPrompt = newPrompt ?? defaultSystemPrompt
}
public func mutateExtraSystemPrompt(_ newPrompt: String) {
extraSystemPrompt = newPrompt
}
public func mutateHistory(_ mutator: @escaping (inout [ChatMessage]) -> Void) async {
await chatGPTService.mutateHistory(mutator)
}
}