Skip to content

Commit c1f5976

Browse files
committed
Update UI to support function call
1 parent 1224ccd commit c1f5976

File tree

4 files changed

+93
-22
lines changed

4 files changed

+93
-22
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,18 @@ extension ChatProvider {
1919
self.history = (await service.memory.history).map { message in
2020
.init(
2121
id: message.id,
22-
isUser: message.role == .user,
22+
role: {
23+
switch message.role {
24+
case .system: return .ignored
25+
case .user: return .user
26+
case .assistant:
27+
if let text = message.summary ?? message.content, !text.isEmpty {
28+
return .assistant
29+
}
30+
return .ignored
31+
case .function: return .function
32+
}
33+
}(),
2334
text: message.summary ?? message.content ?? ""
2435
)
2536
}

Core/Sources/SuggestionWidget/ChatProvider.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Foundation
2+
import OpenAIService
23
import Preferences
34
import SwiftUI
45

@@ -67,13 +68,20 @@ public final class ChatProvider: ObservableObject {
6768
}
6869

6970
public struct ChatMessage: Equatable {
71+
public enum Role {
72+
case user
73+
case assistant
74+
case function
75+
case ignored
76+
}
77+
7078
public var id: String
71-
public var isUser: Bool
79+
public var role: Role
7280
public var text: String
7381

74-
public init(id: String, isUser: Bool, text: String) {
82+
public init(id: String, role: Role, text: String) {
7583
self.id = id
76-
self.isUser = isUser
84+
self.role = role
7785
self.text = text
7886
}
7987
}

Core/Sources/SuggestionWidget/Styles.swift

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,35 @@ extension MarkdownUI.Theme {
8787
}
8888
}
8989
}
90-
.markdownMargin(top: 0, bottom: 16)
90+
.markdownMargin(top: 4, bottom: 16)
91+
}
92+
}
93+
94+
static func functionCall(fontSize: Double) -> MarkdownUI.Theme {
95+
.gitHub.text {
96+
ForegroundColor(.secondary)
97+
BackgroundColor(Color.clear)
98+
FontSize(fontSize - 1)
99+
}
100+
.list { configuration in
101+
configuration.label
102+
.markdownMargin(top: 4, bottom: 4)
103+
}
104+
.paragraph { configuration in
105+
configuration.label
106+
.markdownMargin(top: 0, bottom: 4)
107+
}
108+
.codeBlock { configuration in
109+
configuration.label
110+
.relativeLineSpacing(.em(0.225))
111+
.markdownTextStyle {
112+
FontFamilyVariant(.monospaced)
113+
FontSize(.em(0.85))
114+
}
115+
.padding(16)
116+
.background(Color(nsColor: .textBackgroundColor).opacity(0.7))
117+
.clipShape(RoundedRectangle(cornerRadius: 6))
118+
.markdownMargin(top: 4, bottom: 4)
91119
}
92120
}
93121
}

Core/Sources/SuggestionWidget/SuggestionPanelContent/ChatPanel.swift

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,21 @@ struct ChatPanelMessages: View {
7474
}
7575

7676
ForEach(chat.history.reversed(), id: \.id) { message in
77-
let text = message.text.isEmpty && !message.isUser ? "..." : message
78-
.text
77+
let text = message.text
7978

80-
if message.isUser {
79+
switch message.role {
80+
case .user:
8181
UserMessage(id: message.id, text: text, chat: chat)
8282
.listRowInsets(EdgeInsets(top: 0, leading: -8, bottom: 0, trailing: -8))
8383
.padding(.vertical, 4)
84-
} else {
84+
case .assistant:
8585
BotMessage(id: message.id, text: text, chat: chat)
8686
.listRowInsets(EdgeInsets(top: 0, leading: -8, bottom: 0, trailing: -8))
8787
.padding(.vertical, 4)
88+
case .function:
89+
FunctionMessage(id: message.id, text: text)
90+
case .ignored:
91+
EmptyView()
8892
}
8993
}
9094
.listItemTint(.clear)
@@ -147,7 +151,7 @@ private struct Instruction: View {
147151
- The text cursor location.
148152
149153
If you'd like me to examine the entire file, simply add `@file` to the beginning of your message.
150-
154+
151155
To use plugins, you can start a message with `/pluginName`.
152156
"""
153157
)
@@ -162,7 +166,7 @@ private struct Instruction: View {
162166
- The text cursor location.
163167
164168
If you would like me to examine the selected code, please prefix your message with `@selection`. If you would like me to examine the entire file, please prefix your message with `@file`.
165-
169+
166170
To use plugins, you can start a message with `/pluginName`.
167171
"""
168172
)
@@ -297,6 +301,21 @@ private struct BotMessage: View {
297301
}
298302
}
299303

304+
struct FunctionMessage: View {
305+
let id: String
306+
let text: String
307+
@AppStorage(\.chatFontSize) var chatFontSize
308+
309+
var body: some View {
310+
Markdown(text)
311+
.textSelection(.enabled)
312+
.markdownTheme(.functionCall(fontSize: chatFontSize))
313+
.scaleEffect(x: -1, y: -1, anchor: .center)
314+
.padding(.vertical, 2)
315+
.padding(.trailing, 2)
316+
}
317+
}
318+
300319
struct ChatPanelInputArea: View {
301320
@ObservedObject var chat: ChatProvider
302321
@Binding var typedMessage: String
@@ -398,7 +417,7 @@ struct ChatPanelInputArea: View {
398417
chat.send(typedMessage)
399418
typedMessage = ""
400419
}
401-
420+
402421
func chatAutoCompletion(text: String, proposed: [String], range: NSRange) -> [String] {
403422
guard text.count == 1 else { return [] }
404423
let plugins = chat.pluginIdentifiers.map { "/\($0)" }
@@ -407,7 +426,7 @@ struct ChatPanelInputArea: View {
407426
"@selection",
408427
"@file",
409428
]
410-
429+
411430
let result: [String] = availableFeatures
412431
.filter { $0.hasPrefix(text) && $0 != text }
413432
.compactMap {
@@ -584,24 +603,32 @@ struct ChatPanel_Preview: PreviewProvider {
584603
static let history: [ChatMessage] = [
585604
.init(
586605
id: "1",
587-
isUser: true,
606+
role: .user,
588607
text: "**Hello**"
589608
),
590609
.init(
591610
id: "2",
592-
isUser: false,
611+
role: .assistant,
593612
text: """
594613
```swift
595614
func foo() {}
596615
```
597616
**Hey**! What can I do for you?**Hey**! What can I do for you?**Hey**! What can I do for you?**Hey**! What can I do for you?
598617
"""
599618
),
600-
.init(id: "5", isUser: false, text: "Yooo"),
601-
.init(id: "4", isUser: true, text: "Yeeeehh"),
619+
.init(id: "7", role: .ignored, text: "Ignored"),
620+
.init(id: "6", role: .function, text: """
621+
Searching for something...
622+
- abc
623+
- [def](https://1.com)
624+
> hello
625+
> hi
626+
"""),
627+
.init(id: "5", role: .assistant, text: "Yooo"),
628+
.init(id: "4", role: .user, text: "Yeeeehh"),
602629
.init(
603630
id: "3",
604-
isUser: true,
631+
role: .user,
605632
text: #"""
606633
Please buy me a coffee!
607634
| Coffee | Milk |
@@ -624,7 +651,7 @@ struct ChatPanel_Preview: PreviewProvider {
624651
history: ChatPanel_Preview.history,
625652
isReceivingMessage: true
626653
))
627-
.frame(width: 450, height: 700)
654+
.frame(width: 450, height: 1200)
628655
.colorScheme(.dark)
629656
}
630657
}
@@ -700,6 +727,3 @@ struct ChatPanel_Light_Preview: PreviewProvider {
700727
}
701728
}
702729

703-
704-
705-

0 commit comments

Comments
 (0)