Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Core/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ let package = Package(
.package(path: "../ChatPlugins"),
.package(url: "https://github.com/apple/swift-async-algorithms", from: "1.0.0"),
.package(url: "https://github.com/gonzalezreal/swift-markdown-ui", from: "2.4.1"),
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.0.0"),
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.6.4"),
.package(url: "https://github.com/pointfreeco/swift-parsing", from: "0.12.1"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.0.0"),
.package(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ struct APIKeyManagementView: View {
state: \.apiKeySubmission,
action: \.apiKeySubmission
)) { store in
APIKeySubmissionView(store: store)
.frame(minWidth: 400)
WithPerceptionTracking {
APIKeySubmissionView(store: store)
.frame(minWidth: 400)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct ChatModelEdit {
var customHeaders: [ChatModel.Info.CustomHeaderInfo.HeaderField] = []
var openAICompatibleSupportsMultipartMessageContent = true
var requiresBeginWithUserMessage = false
var customBody: String = ""
}

enum Action: Equatable, BindableAction {
Expand Down Expand Up @@ -302,7 +303,8 @@ extension ChatModel {
.openAICompatibleSupportsMultipartMessageContent,
requiresBeginWithUserMessage: state.requiresBeginWithUserMessage
),
customHeaderInfo: .init(headers: state.customHeaders)
customHeaderInfo: .init(headers: state.customHeaders),
customBodyInfo: .init(jsonBody: state.customBody)
)
)
}
Expand All @@ -328,7 +330,8 @@ extension ChatModel {
customHeaders: info.customHeaderInfo.headers,
openAICompatibleSupportsMultipartMessageContent: info.openAICompatibleInfo
.supportsMultipartMessageContent,
requiresBeginWithUserMessage: info.openAICompatibleInfo.requiresBeginWithUserMessage
requiresBeginWithUserMessage: info.openAICompatibleInfo.requiresBeginWithUserMessage,
customBody: info.customBodyInfo.jsonBody
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ struct ChatModelEditView: View {
.controlSize(.small)
}
}

CustomBodyEdit(store: store)
.disabled({
switch store.format {
case .openAI, .openAICompatible, .claude:
return false
default:
return true
}
}())
CustomHeaderEdit(store: store)
.disabled({
switch store.format {
case .openAI, .openAICompatible, .ollama, .gitHubCopilot, .claude:
return false
default:
return true
}
}())

Spacer()

Expand Down Expand Up @@ -230,6 +249,79 @@ struct ChatModelEditView: View {
}
}

struct CustomBodyEdit: View {
@Perception.Bindable var store: StoreOf<ChatModelEdit>
@State private var isEditing = false
@Dependency(\.namespacedToast) var toast

var body: some View {
Button("Custom Body") {
isEditing = true
}
.sheet(isPresented: $isEditing) {
WithPerceptionTracking {
VStack {
TextEditor(text: $store.customBody)
.font(Font.system(.body, design: .monospaced))
.padding(4)
.frame(minHeight: 120)
.multilineTextAlignment(.leading)
.overlay(
RoundedRectangle(cornerRadius: 4)
.stroke(Color(nsColor: .separatorColor), lineWidth: 1)
)
.handleToast(namespace: "CustomBodyEdit")

Text(
"The custom body will be added to the request body. Please use it to add parameters that are not yet available in the form. It should be a valid JSON object."
)
.foregroundColor(.secondary)
.font(.callout)
.padding(.bottom)

Button(action: {
if store.customBody.trimmingCharacters(in: .whitespacesAndNewlines)
.isEmpty
{
isEditing = false
return
}
guard let _ = try? JSONSerialization
.jsonObject(with: store.customBody.data(using: .utf8) ?? Data())
else {
toast("Invalid JSON object", .error, "CustomBodyEdit")
return
}
isEditing = false
}) {
Text("Done")
}
.keyboardShortcut(.defaultAction)
}
.padding()
.frame(width: 600, height: 500)
.background(Color(nsColor: .windowBackgroundColor))
}
}
}
}

struct CustomHeaderEdit: View {
@Perception.Bindable var store: StoreOf<ChatModelEdit>
@State private var isEditing = false

var body: some View {
Button("Custom Headers") {
isEditing = true
}
.sheet(isPresented: $isEditing) {
WithPerceptionTracking {
CustomHeaderSettingsView(headers: $store.customHeaders)
}
}
}
}

struct OpenAIForm: View {
@Perception.Bindable var store: StoreOf<ChatModelEdit>
var body: some View {
Expand Down Expand Up @@ -300,7 +392,6 @@ struct ChatModelEditView: View {

struct OpenAICompatibleForm: View {
@Perception.Bindable var store: StoreOf<ChatModelEdit>
@State var isEditingCustomHeader = false

var body: some View {
WithPerceptionTracking {
Expand Down Expand Up @@ -340,16 +431,10 @@ struct ChatModelEditView: View {
Toggle(isOn: $store.openAICompatibleSupportsMultipartMessageContent) {
Text("Support multi-part message content")
}

Toggle(isOn: $store.requiresBeginWithUserMessage) {
Text("Requires the first message to be from the user")
}

Button("Custom Headers") {
isEditingCustomHeader.toggle()
}
}.sheet(isPresented: $isEditingCustomHeader) {
CustomHeaderSettingsView(headers: $store.customHeaders)
}
}
}
Expand Down Expand Up @@ -394,7 +479,6 @@ struct ChatModelEditView: View {

struct OllamaForm: View {
@Perception.Bindable var store: StoreOf<ChatModelEdit>
@State var isEditingCustomHeader = false

var body: some View {
WithPerceptionTracking {
Expand All @@ -411,20 +495,13 @@ struct ChatModelEditView: View {
TextField(text: $store.ollamaKeepAlive, prompt: Text("Default Value")) {
Text("Keep Alive")
}

Button("Custom Headers") {
isEditingCustomHeader.toggle()
}


VStack(alignment: .leading, spacing: 8) {
Text(Image(systemName: "exclamationmark.triangle.fill")) + Text(
" For more details, please visit [https://ollama.com](https://ollama.com)."
)
}
.padding(.vertical)

}.sheet(isPresented: $isEditingCustomHeader) {
CustomHeaderSettingsView(headers: $store.customHeaders)
}
}
}
Expand Down Expand Up @@ -475,7 +552,6 @@ struct ChatModelEditView: View {

struct GitHubCopilotForm: View {
@Perception.Bindable var store: StoreOf<ChatModelEdit>
@State var isEditingCustomHeader = false

var body: some View {
WithPerceptionTracking {
Expand Down Expand Up @@ -507,10 +583,6 @@ struct ChatModelEditView: View {
Text("Support multi-part message content")
}

Button("Custom Headers") {
isEditingCustomHeader.toggle()
}

VStack(alignment: .leading, spacing: 8) {
Text(Image(systemName: "exclamationmark.triangle.fill")) + Text(
" Please login in the GitHub Copilot settings to use the model."
Expand All @@ -522,8 +594,6 @@ struct ChatModelEditView: View {
}
.dynamicHeightTextInFormWorkaround()
.padding(.vertical)
}.sheet(isPresented: $isEditingCustomHeader) {
CustomHeaderSettingsView(headers: $store.customHeaders)
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion Core/Sources/KeyBindingManager/TabToAcceptSuggestion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ final class TabToAcceptSuggestion {
}
guard let filespace = workspacePool.fetchFilespaceIfExisted(fileURL: fileURL)
else {
Logger.service.info("TabToAcceptSuggestion: No file found")
Logger.service.info(
"TabToAcceptSuggestion: No file found for file \(fileURL.lastPathComponent)"
)
return .unchanged
}
guard let presentingSuggestion = filespace.presentingSuggestion
Expand Down
4 changes: 4 additions & 0 deletions Core/Tests/ServiceTests/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ func completion(text: String, range: CursorRange, uuid: String = "") -> CodeSugg
}

class MockSuggestionService: GitHubCopilotSuggestionServiceType {
func cancelOngoingTask(workDoneToken: String) async {
fatalError()
}

func notifyChangeTextDocument(fileURL: URL, content: String, version: Int) async throws {
fatalError()
}
Expand Down
Loading