Skip to content

Commit d52b1ad

Browse files
authored
Merge pull request #847 from github/release/0.49.174
Pre-release 0.49.174
2 parents 8869299 + 3f39d29 commit d52b1ad

42 files changed

Lines changed: 2512 additions & 663 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/auto-create-release-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
env:
4646
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4747
run: |
48-
gh pr checks "${{ github.ref_name }}" --watch --required
48+
gh pr checks "${{ github.ref_name }}" --watch
4949
5050
- name: Merge pull request
5151
env:

Core/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ let package = Package(
269269
.product(name: "GitHubCopilotService", package: "Tool"),
270270
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
271271
.product(name: "Status", package: "Tool"),
272+
.product(name: "Logger", package: "Tool"),
272273
]
273274
),
274275

Core/Sources/ChatService/ChatService.swift

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public protocol ChatServiceType {
3030
references: [ConversationAttachedReference],
3131
model: String?,
3232
modelProviderName: String?,
33+
reasoningEffort: String?,
3334
agentMode: Bool,
3435
customChatModeId: String?,
3536
userLanguage: String?,
@@ -363,6 +364,7 @@ public final class ChatService: ChatServiceType, ObservableObject {
363364
references: [ConversationAttachedReference],
364365
model: String? = nil,
365366
modelProviderName: String? = nil,
367+
reasoningEffort: String? = nil,
366368
agentMode: Bool = false,
367369
customChatModeId: String? = nil,
368370
userLanguage: String? = nil,
@@ -469,6 +471,7 @@ public final class ChatService: ChatServiceType, ObservableObject {
469471
references: references,
470472
model: model,
471473
modelProviderName: modelProviderName,
474+
reasoningEffort: reasoningEffort,
472475
agentMode: agentMode,
473476
customChatModeId: customChatModeId,
474477
userLanguage: userLanguage,
@@ -500,6 +503,7 @@ public final class ChatService: ChatServiceType, ObservableObject {
500503
references: [ConversationAttachedReference],
501504
model: String? = nil,
502505
modelProviderName: String? = nil,
506+
reasoningEffort: String? = nil,
503507
agentMode: Bool = false,
504508
customChatModeId: String? = nil,
505509
userLanguage: String? = nil,
@@ -526,6 +530,7 @@ public final class ChatService: ChatServiceType, ObservableObject {
526530
references: references,
527531
model: model,
528532
modelProviderName: modelProviderName,
533+
reasoningEffort: reasoningEffort,
529534
agentMode: agentMode,
530535
customChatModeId: customChatModeId,
531536
userLanguage: userLanguage,
@@ -537,7 +542,10 @@ public final class ChatService: ChatServiceType, ObservableObject {
537542
await memory.mutateHistory { history in
538543
if let index = history.firstIndex(where: { $0.id == response.turnId && $0.role.isAssistant }) {
539544
history[index].modelName = response.modelName
545+
let modelProviderName = response.modelInfo?.providerName ?? response.modelProviderName
546+
history[index].modelProviderName = modelProviderName
540547
history[index].billingMultiplier = response.billingMultiplier
548+
history[index].reasoningEffort = response.modelInfo?.reasoningEffort
541549

542550
self.saveChatMessageToStorage(history[index])
543551
}
@@ -998,6 +1006,16 @@ public final class ChatService: ChatServiceType, ObservableObject {
9981006
}
9991007
}
10001008

1009+
private func strippingRequestIDs(from message: String) -> String {
1010+
// "Request ID:" always appears before "GitHub Request ID:", so cutting at the first
1011+
// occurrence removes both along with the preceding separator (". " or " | ")
1012+
guard let range = message.range(of: "Request ID:", options: .caseInsensitive) else {
1013+
return message
1014+
}
1015+
return String(message[..<range.lowerBound])
1016+
.trimmingCharacters(in: CharacterSet(charactersIn: " |\t\n\r"))
1017+
}
1018+
10011019
private func handleProgressEnd(token: String, progress: ConversationProgressEnd) {
10021020
guard let workDoneToken = activeRequestId, workDoneToken == token else { return }
10031021

@@ -1011,12 +1029,13 @@ public final class ChatService: ChatServiceType, ObservableObject {
10111029
Task {
10121030
let selectedModel = lastUserRequest?.model
10131031
let selectedModelProviderName = lastUserRequest?.modelProviderName
1014-
1032+
let isBYOK = selectedModel != nil && selectedModelProviderName != nil
1033+
10151034
var errorMessageText: String
10161035
if let selectedModel = selectedModel, let selectedModelProviderName = selectedModelProviderName {
10171036
errorMessageText = "You've reached your quota limit for your BYOK model \(selectedModel). Please check with \(selectedModelProviderName) for more information."
10181037
} else {
1019-
errorMessageText = CLSError.message
1038+
errorMessageText = strippingRequestIDs(from: CLSError.message)
10201039
}
10211040

10221041
await Status.shared
@@ -1026,10 +1045,12 @@ public final class ChatService: ChatServiceType, ObservableObject {
10261045
chatTabID: chatTabInfo.id,
10271046
panelMessages: [.init(type: .error, title: String(CLSError.code ?? 0), message: errorMessageText, location: .Panel)]
10281047
)
1029-
// will persist in resetongoingRequest()
10301048
await memory.appendMessage(errorMessage)
1031-
1032-
if let lastUserRequest,
1049+
1050+
// TBB messages mention "AI Credits" or "additional overages" — no fallback for TBB
1051+
let isTBB = !isBYOK && (CLSError.message.contains("AI Credits") || CLSError.message.contains("additional overages"))
1052+
if !isTBB,
1053+
let lastUserRequest,
10331054
let currentUserPlan = await Status.shared.currentUserPlan(),
10341055
currentUserPlan != "free" {
10351056
guard let fallbackModel = CopilotModelManager.getFallbackLLM(
@@ -1051,6 +1072,7 @@ public final class ChatService: ChatServiceType, ObservableObject {
10511072
}
10521073
return
10531074
}
1075+
resetOngoingRequest(with: .error)
10541076
}
10551077
} else if CLSError.code == 400 && CLSError.message.contains("model is not supported") {
10561078
Task {

Core/Sources/ConversationTab/Chat.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public struct DisplayedChatMessage: Equatable {
3939
public var turnStatus: ChatMessage.TurnStatus? = nil
4040
public let requestType: RequestType
4141
public var modelName: String? = nil
42+
public var modelProviderName: String? = nil
4243
public var billingMultiplier: Float? = nil
44+
public var reasoningEffort: String? = nil
4345

4446
public init(
4547
id: String,
@@ -60,7 +62,9 @@ public struct DisplayedChatMessage: Equatable {
6062
turnStatus: ChatMessage.TurnStatus? = nil,
6163
requestType: RequestType,
6264
modelName: String? = nil,
63-
billingMultiplier: Float? = nil
65+
modelProviderName: String? = nil,
66+
billingMultiplier: Float? = nil,
67+
reasoningEffort: String? = nil
6468
) {
6569
self.id = id
6670
self.role = role
@@ -80,7 +84,9 @@ public struct DisplayedChatMessage: Equatable {
8084
self.turnStatus = turnStatus
8185
self.requestType = requestType
8286
self.modelName = modelName
87+
self.modelProviderName = modelProviderName
8388
self.billingMultiplier = billingMultiplier
89+
self.reasoningEffort = reasoningEffort
8490
}
8591
}
8692

@@ -739,6 +745,7 @@ struct Chat {
739745
let selectedModelFamily = selectedModel?.modelFamily ?? CopilotModelManager.getDefaultChatModel(
740746
scope: AppState.shared.modelScope()
741747
)?.modelFamily
748+
let reasoningEffort = selectedModel.flatMap { AppState.shared.effectiveReasoningEffort(for: $0) }
742749
let agentMode = AppState.shared.isAgentModeEnabled()
743750
let selectedAgentSubMode = AppState.shared.getSelectedAgentSubMode()
744751
let shouldAttachImages = selectedModel?.supportVision ?? CopilotModelManager.getDefaultChatModel(
@@ -775,6 +782,7 @@ struct Chat {
775782
references: references,
776783
model: selectedModelFamily,
777784
modelProviderName: selectedModel?.providerName,
785+
reasoningEffort: reasoningEffort,
778786
agentMode: agentMode,
779787
customChatModeId: selectedAgentSubMode,
780788
userLanguage: chatResponseLocale
@@ -834,6 +842,7 @@ struct Chat {
834842
references: references,
835843
model: selectedModelFamily,
836844
modelProviderName: selectedModel?.providerName,
845+
reasoningEffort: selectedModel.flatMap { AppState.shared.effectiveReasoningEffort(for: $0) },
837846
agentMode: agentMode,
838847
customChatModeId: selectedAgentSubMode,
839848
userLanguage: chatResponseLocale
@@ -1079,7 +1088,9 @@ struct Chat {
10791088
turnStatus: message.turnStatus,
10801089
requestType: message.requestType,
10811090
modelName: message.modelName,
1082-
billingMultiplier: message.billingMultiplier
1091+
modelProviderName: message.modelProviderName,
1092+
billingMultiplier: message.billingMultiplier,
1093+
reasoningEffort: message.reasoningEffort
10831094
))
10841095

10851096
return all
@@ -1328,14 +1339,15 @@ struct Chat {
13281339
// TODO: if we need to switch to agent mode or keep the current mode
13291340
let selectedAgentSubMode = AppState.shared.getSelectedAgentSubMode()
13301341

1331-
return .run { _ in
1342+
return .run { _ in
13321343
try await service.send(
13331344
UUID().uuidString,
13341345
content: message,
13351346
skillSet: skillSet,
13361347
references: references,
13371348
model: selectedModelFamily,
13381349
modelProviderName: selectedModel?.providerName,
1350+
reasoningEffort: selectedModel.flatMap { AppState.shared.effectiveReasoningEffort(for: $0) },
13391351
agentMode: agentMode,
13401352
customChatModeId: selectedAgentSubMode,
13411353
userLanguage: chatResponseLocale

Core/Sources/ConversationTab/ChatPanel.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private let r: Double = 4
2323
public struct ChatPanel: View {
2424
@Perception.Bindable var chat: StoreOf<Chat>
2525
@Namespace var inputAreaNamespace
26-
@ObservedObject private var rateLimitNotifier = RateLimitNotifierImpl.shared
26+
@ObservedObject private var warningManager = WarningStateManager.shared
2727

2828
public var body: some View {
2929
WithPerceptionTracking {
@@ -56,9 +56,13 @@ public struct ChatPanel: View {
5656
}
5757
}
5858

59-
if let warning = rateLimitNotifier.currentWarning {
60-
RateLimitWarningBanner(message: warning.message) {
61-
rateLimitNotifier.dismissWarning()
59+
if let warning = warningManager.currentWarning {
60+
WarningBanner(
61+
message: warning.message,
62+
severity: warning.severity,
63+
actions: warning.actions
64+
) {
65+
warningManager.dismissWarning()
6266
}
6367
.scaledPadding(.horizontal, 24)
6468
.scaledPadding(.vertical, 8)

Core/Sources/ConversationTab/ModeAndModelPicker/ModeAndModelPickerPicker.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ struct ModeAndModelPicker: View {
135135
selectedModel = nil
136136
}
137137
} else {
138+
if let fresh = freshModel, let current = currentModel,
139+
fresh.supportsReasoningEffortLevel != current.supportsReasoningEffortLevel
140+
|| fresh.reasoningEfforts != current.reasoningEfforts {
141+
AppState.shared.setSelectedModel(fresh)
142+
}
138143
selectedModel = freshModel ?? defaultModel
139144
}
140145
}

0 commit comments

Comments
 (0)