Skip to content

Commit d7d3857

Browse files
authored
Codex improvements (#195)
1 parent 736a2eb commit d7d3857

File tree

35 files changed

+114
-67
lines changed

35 files changed

+114
-67
lines changed

app/modules/coreui/CodePreview/Sources/FileChangeExpandablePill.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ public struct FileChangeExpandablePill: View {
192192
}
193193
}
194194
.with(cornerRadius: Constants.cornerRadius, borderColor: colorScheme.textAreaBorderColor)
195-
.padding(.horizontal, 4)
196195
}
197196

198197
let change: FileDiffViewModel

app/modules/coreui/ToolUI/Sources/ToolErrorView.swift

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,35 @@ public struct ToolErrorView: View {
1717
}
1818

1919
public var body: some View {
20-
if toolUseErrorDescription.count > 300 {
21-
VStack(alignment: .leading, spacing: 8) {
22-
HStack {
23-
Text("Tool failed")
24-
.foregroundColor(colorScheme.redError)
25-
26-
Button(action: {
27-
isExpanded.toggle()
28-
}) {
29-
Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
30-
.foregroundColor(.secondary)
20+
if error is CancellationError {
21+
Text("Cancelled")
22+
.foregroundColor(.secondary)
23+
} else {
24+
if toolUseErrorDescription.count > 300 {
25+
VStack(alignment: .leading, spacing: 8) {
26+
HStack {
27+
Button(action: {
28+
isExpanded.toggle()
29+
}) {
30+
Image(systemName: isExpanded ? "chevron.down" : "chevron.right")
31+
.foregroundColor(.secondary)
32+
}
33+
.buttonStyle(.plain)
34+
Text("Tool failed")
35+
.foregroundColor(colorScheme.redError)
3136
}
32-
.buttonStyle(.plain)
33-
}
3437

35-
if isExpanded {
36-
Text(toolUseErrorDescription.asPlainText(colorScheme: colorScheme))
37-
.textSelection(.enabled)
38-
.foregroundColor(.primary)
38+
if isExpanded {
39+
Text(toolUseErrorDescription.asPlainText(colorScheme: colorScheme))
40+
.textSelection(.enabled)
41+
.foregroundColor(.primary)
42+
}
3943
}
44+
} else {
45+
Text(toolUseErrorDescription.asPlainText(colorScheme: colorScheme))
46+
.textSelection(.enabled)
47+
.foregroundColor(colorScheme.redError)
4048
}
41-
} else {
42-
Text(toolUseErrorDescription.asPlainText(colorScheme: colorScheme))
43-
.textSelection(.enabled)
44-
.foregroundColor(colorScheme.redError)
4549
}
4650
}
4751

app/modules/features/Chat/ChatFeature/Tests/ChatViewModelTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,7 @@ extension DependencyValues {
11991199
llmService = MockLLMService(activeModels: [.claudeSonnet, .gpt])
12001200
self.settingsService = settingsService
12011201
userDefaults = mockUserDefaults
1202+
xcodeObserver = MockXcodeObserver(AXState<XcodeState>.unknown)
12021203
}
12031204
}
12041205

app/modules/foundations/ToolFoundation/Sources/DefaultTool/UnknownTool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public final class UnknownTool: Tool {
3333
self.input = input
3434
self.context = context
3535

36-
let (stream, updateStatus) = Status.makeStream(initial: initialStatus ?? .notStarted)
36+
let (stream, updateStatus) = Status.makeStream(initial: initialStatus?.completedOrCancelled ?? .notStarted)
3737
if case .completed = stream.value { updateStatus.finish() }
3838
status = stream
3939
self.updateStatus = updateStatus

app/modules/foundations/ToolFoundation/Sources/TestTool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public struct TestTool: Tool {
4949
isReadonly = callingTool.isReadonly
5050
output = callingTool.output
5151

52-
let (stream, updateStatus) = Status.makeStream(initial: initialStatus ?? .notStarted)
52+
let (stream, updateStatus) = Status.makeStream(initial: initialStatus?.completedOrCancelled ?? .notStarted)
5353
if case .completed = stream.value { updateStatus.finish() }
5454
status = stream
5555
self.updateStatus = updateStatus

app/modules/foundations/ToolFoundation/Sources/Tool.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,18 @@ extension ToolUse {
406406
}
407407
}
408408

409+
extension ToolUseExecutionStatus {
410+
/// Converts in-flight status to cancelled, unless it is already completed or not started.
411+
public var completedOrCancelled: Self {
412+
switch self {
413+
case .notStarted, .completed, .approvalRejected:
414+
self
415+
case .running, .pendingApproval:
416+
.completed(.failure(CancellationError()))
417+
}
418+
}
419+
}
420+
409421
extension AsyncStream.Continuation {
410422
public func complete<Output>(with result: Result<Output, Error>) where Element == ToolUseExecutionStatus<Output> {
411423
yield(.completed(result))

app/modules/foundations/ToolFoundation/Tests/UnknownToolTests.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,28 @@ struct UnknownToolTests {
105105
#expect(type(of: finalToolUse.callingTool) == type(of: originalToolUse.callingTool))
106106
}
107107

108+
@Test
109+
func test_initialInFlightStatusCompletesAsCancelled() {
110+
let tool = TestTool()
111+
let toolUse = TestTool.Use(
112+
callingTool: tool,
113+
toolUseId: "tool-use-id",
114+
input: .null,
115+
context: toolExecutionContext,
116+
internalState: nil,
117+
initialStatus: .running)
118+
119+
if case .completed(let result) = toolUse.status.value {
120+
if case .failure(let error) = result {
121+
#expect(error is CancellationError)
122+
} else {
123+
#expect(false, "Expected failure result when initial status is non-terminal.")
124+
}
125+
} else {
126+
#expect(false, "Expected completed status when initial status is non-terminal.")
127+
}
128+
}
129+
108130
private let toolExecutionContext = ToolExecutionContext()
109131
}
110132

app/modules/plugins/tools/ACPTool/Sources/ACPTool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public final class ACPTool: Tool {
4242
self.input = input
4343
self.internalState = internalState
4444

45-
let (stream, updateStatus) = Status.makeStream(initial: initialStatus ?? .notStarted)
45+
let (stream, updateStatus) = Status.makeStream(initial: initialStatus?.completedOrCancelled ?? .notStarted)
4646
if case .completed = stream.value { updateStatus.finish() }
4747
status = stream
4848
self.updateStatus = updateStatus

app/modules/plugins/tools/ACPTool/Sources/ACPToolView.swift

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import CodePreview
55
import Dependencies
66
import DLS
77
import FileDiffFoundation
8+
import LoggingServiceInterface
89
import Markdown
910
import SwiftUI
1011
import ToolFoundation
@@ -39,15 +40,15 @@ struct ToolUseView: View {
3940
static let hstackSpacing: CGFloat = 4
4041
}
4142

42-
@State private var isExpanded = false
43+
@State private var isExpanded: Bool?
4344
@State private var isHovered = false
4445

4546
@Environment(\.colorScheme) private var colorScheme
4647

4748
@ViewBuilder
4849
private var pendingApprovalView: some View {
4950
VStack(alignment: .leading) {
50-
contentView(content: toolUse.input.content)
51+
contentView(content: toolUse.input.content, isExpandedByDefault: true)
5152

5253
ThreeDotsLoadingAnimation(baseText: "Waiting for approval")
5354
}
@@ -104,11 +105,11 @@ struct ToolUseView: View {
104105
}
105106

106107
@ViewBuilder
107-
private func contentView(content: [ToolsSchema.ACPTool_Content]?) -> some View {
108+
private func contentView(content: [ToolsSchema.ACPTool_Content]?, isExpandedByDefault: Bool = false) -> some View {
108109
if let content {
109110
VStack(alignment: .leading) {
110111
HStack(spacing: Constants.hstackSpacing) {
111-
if isExpanded {
112+
if isExpanded ?? isExpandedByDefault {
112113
Icon(systemName: "chevron.down")
113114
.forTool(with: foregroundColor)
114115
} else if isHovered {
@@ -125,9 +126,9 @@ struct ToolUseView: View {
125126
.foregroundColor(foregroundColor)
126127
}
127128
.tappableTransparentBackground()
128-
.onTapGesture { isExpanded.toggle() }
129+
.onTapGesture { isExpanded = !(isExpanded ?? isExpandedByDefault) }
129130
.acceptClickThrough()
130-
if isExpanded {
131+
if isExpanded ?? isExpandedByDefault {
131132
contentView(for: content)
132133
}
133134
}.onHover { isHovered = $0 }
@@ -146,14 +147,7 @@ struct ToolUseView: View {
146147
@ViewBuilder
147148
private func failureView(error: Error) -> some View {
148149
VStack(alignment: .leading) {
149-
HStack(spacing: Constants.hstackSpacing) {
150-
Icon(systemName: toolIconName)
151-
.forTool(with: foregroundColor)
152-
Text(title)
153-
.lineLimit(1)
154-
.truncationMode(.middle)
155-
.foregroundColor(foregroundColor)
156-
}
150+
contentView(content: toolUse.input.content)
157151
ToolErrorView(error)
158152
}
159153
}
@@ -279,10 +273,9 @@ struct DiffContentView: View {
279273
do {
280274
try await xcodeController.open(file: file, line: nil, column: nil)
281275
} catch {
282-
print("Failed to open file: \(error)")
276+
defaultLogger.error("Failed to open file", error)
283277
}
284278
})
285-
.padding(.leading, 11)
286279
}
287280

288281
@State private var viewModel: FileDiffViewModel

app/modules/plugins/tools/AskFollowUpTool/Sources/AskFollowUpTool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public final class AskFollowUpTool: Tool {
3131
self.input = input
3232
self.context = context
3333

34-
let (stream, updateStatus) = Status.makeStream(initial: initialStatus ?? .notStarted)
34+
let (stream, updateStatus) = Status.makeStream(initial: initialStatus?.completedOrCancelled ?? .notStarted)
3535
if case .completed = stream.value { updateStatus.finish() }
3636
status = stream
3737
self.updateStatus = updateStatus

0 commit comments

Comments
 (0)