-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathFeatureFlagNotifier.swift
More file actions
121 lines (110 loc) · 4.93 KB
/
FeatureFlagNotifier.swift
File metadata and controls
121 lines (110 loc) · 4.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import Combine
import SwiftUI
import JSONRPC
public extension Notification.Name {
static let gitHubCopilotFeatureFlagsDidChange = Notification
.Name("com.github.CopilotForXcode.CopilotFeatureFlagsDidChange")
}
public enum ExperimentValue: Hashable, Codable {
case string(String)
case number(Double)
case boolean(Bool)
case stringArray([String])
}
public typealias ActiveExperimentForFeatureFlags = [String: ExperimentValue]
public struct DidChangeFeatureFlagsParams: Hashable, Codable {
let envelope: [String: JSONValue]
let token: [String: String]
let activeExps: ActiveExperimentForFeatureFlags
let byok: Bool?
}
public struct FeatureFlags: Hashable, Codable {
public var restrictedTelemetry: Bool
public var snippy: Bool
public var chat: Bool
public var inlineChat: Bool
public var projectContext: Bool
public var agentMode: Bool
public var mcp: Bool
public var ccr: Bool // Copilot Code Review
public var byok: Bool
public var editorPreviewFeatures: Bool
public var activeExperimentForFeatureFlags: ActiveExperimentForFeatureFlags
public var agentModeAutoApproval: Bool
public init(
restrictedTelemetry: Bool = true,
snippy: Bool = true,
chat: Bool = true,
inlineChat: Bool = true,
projectContext: Bool = true,
agentMode: Bool = true,
mcp: Bool = true,
ccr: Bool = true,
byok: Bool = true,
editorPreviewFeatures: Bool = true,
activeExperimentForFeatureFlags: ActiveExperimentForFeatureFlags = [:],
agentModeAutoApproval: Bool = true
) {
self.restrictedTelemetry = restrictedTelemetry
self.snippy = snippy
self.chat = chat
self.inlineChat = inlineChat
self.projectContext = projectContext
self.agentMode = agentMode
self.mcp = mcp
self.ccr = ccr
self.byok = byok
self.editorPreviewFeatures = editorPreviewFeatures
self.activeExperimentForFeatureFlags = activeExperimentForFeatureFlags
self.agentModeAutoApproval = agentModeAutoApproval
}
}
public protocol FeatureFlagNotifier {
var didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams { get }
var featureFlagsDidChange: PassthroughSubject<FeatureFlags, Never> { get }
func handleFeatureFlagNotification(_ didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams)
}
public class FeatureFlagNotifierImpl: FeatureFlagNotifier {
public var didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams
public var featureFlags: FeatureFlags
public static let shared = FeatureFlagNotifierImpl()
public var featureFlagsDidChange: PassthroughSubject<FeatureFlags, Never>
init(
didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams = .init(
envelope: [:],
token: [:],
activeExps: [:],
byok: nil
),
featureFlags: FeatureFlags = FeatureFlags(),
featureFlagsDidChange: PassthroughSubject<FeatureFlags, Never> = PassthroughSubject<FeatureFlags, Never>()
) {
self.didChangeFeatureFlagsParams = didChangeFeatureFlagsParams
self.featureFlags = featureFlags
self.featureFlagsDidChange = featureFlagsDidChange
}
private func updateFeatureFlags() {
let xcodeChat = self.didChangeFeatureFlagsParams.envelope["xcode_chat"]?.boolValue != false
let chatEnabled = self.didChangeFeatureFlagsParams.envelope["chat_enabled"]?.boolValue != false
self.featureFlags.restrictedTelemetry = self.didChangeFeatureFlagsParams.token["rt"] != "0"
self.featureFlags.snippy = self.didChangeFeatureFlagsParams.token["sn"] != "0"
self.featureFlags.chat = xcodeChat && chatEnabled
self.featureFlags.inlineChat = chatEnabled
self.featureFlags.agentMode = self.didChangeFeatureFlagsParams.token["agent_mode"] != "0"
self.featureFlags.mcp = self.didChangeFeatureFlagsParams.token["mcp"] != "0"
self.featureFlags.ccr = self.didChangeFeatureFlagsParams.token["ccr"] != "0"
self.featureFlags.byok = self.didChangeFeatureFlagsParams.byok != false
self.featureFlags.editorPreviewFeatures = self.didChangeFeatureFlagsParams.token["editor_preview_features"] != "0"
self.featureFlags.activeExperimentForFeatureFlags = self.didChangeFeatureFlagsParams.activeExps
self.featureFlags.agentModeAutoApproval = self.didChangeFeatureFlagsParams.token["agent_mode_auto_approval"] != "0"
}
public func handleFeatureFlagNotification(_ didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams) {
self.didChangeFeatureFlagsParams = didChangeFeatureFlagsParams
updateFeatureFlags()
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.featureFlagsDidChange.send(self.featureFlags)
DistributedNotificationCenter.default().post(name: .gitHubCopilotFeatureFlagsDidChange, object: nil)
}
}
}