Skip to content

Commit c6a870a

Browse files
committed
Migrate extension service to use new way to setup model
1 parent b639bbc commit c6a870a

File tree

25 files changed

+1017
-264
lines changed

25 files changed

+1017
-264
lines changed

Copilot for Xcode.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Core/Package.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,13 @@ let package = Package(
261261
dependencies: [
262262
"GitHubCopilotService",
263263
.product(name: "Preferences", package: "Tool"),
264+
.product(name: "Keychain", package: "Tool"),
265+
]
266+
),
267+
.testTarget(
268+
name: "ServiceUpdateMigrationTests",
269+
dependencies: [
270+
"ServiceUpdateMigration",
264271
]
265272
),
266273
.target(

Core/Sources/ChatContextCollectors/WebChatContextCollector/SearchFunction.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ struct SearchFunction: ChatGPTFunction {
7272
subscriptionKey: UserDefaults.shared.value(for: \.bingSearchSubscriptionKey),
7373
searchURL: UserDefaults.shared.value(for: \.bingSearchEndpoint)
7474
)
75+
76+
#warning("request chat service to pass in the token length")
77+
7578
let result = try await bingSearch.search(
7679
query: arguments.query,
7780
numberOfResult: UserDefaults.shared.value(for: \.chatGPTMaxToken) > 5000 ? 5 : 3,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import Foundation
2+
import GitHubCopilotService
3+
4+
func migrateFromLowerThanOrEqualToVersion135() throws {
5+
// 0. Create the application support folder if it doesn't exist
6+
7+
let urls = try GitHubCopilotBaseService.createFoldersIfNeeded()
8+
9+
// 1. Move the undefined folder in application support into a sub folder called `GitHub
10+
// Copilot/support`
11+
12+
let undefinedFolderURL = urls.applicationSupportURL.appendingPathComponent("undefined")
13+
var isUndefinedADirectory: ObjCBool = false
14+
let isUndefinedExisted = FileManager.default.fileExists(
15+
atPath: undefinedFolderURL.path,
16+
isDirectory: &isUndefinedADirectory
17+
)
18+
if isUndefinedExisted, isUndefinedADirectory.boolValue {
19+
try FileManager.default.moveItem(
20+
at: undefinedFolderURL,
21+
to: urls.supportURL.appendingPathComponent("undefined")
22+
)
23+
}
24+
25+
// 2. Copy the GitHub copilot language service to `GitHub Copilot/executable`
26+
27+
let copilotFolderURL = urls.executableURL.appendingPathComponent("copilot")
28+
var copilotIsFolder: ObjCBool = false
29+
let executable = Bundle.main.resourceURL?.appendingPathComponent("copilot")
30+
if let executable,
31+
FileManager.default.fileExists(atPath: executable.path, isDirectory: &copilotIsFolder),
32+
!FileManager.default.fileExists(atPath: copilotFolderURL.path)
33+
{
34+
try FileManager.default.copyItem(
35+
at: executable,
36+
to: urls.executableURL.appendingPathComponent("copilot")
37+
)
38+
}
39+
40+
// 3. Use chmod to change the permission of the executable to 755
41+
42+
try FileManager.default.setAttributes(
43+
[.posixPermissions: 0o755],
44+
ofItemAtPath: copilotFolderURL.path
45+
)
46+
}
47+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import AIModel
2+
import Foundation
3+
import Keychain
4+
import Preferences
5+
6+
func migrateTo230(
7+
defaults: UserDefaults = .shared,
8+
keychain: KeychainType = Keychain(scope: "apikey")
9+
) throws {
10+
let key = UserDefaultPreferenceKeys().embeddingModels.key
11+
if defaults.value(forKey: key) != nil { return }
12+
13+
let chatModelOpenAIId = UUID().uuidString
14+
let chatModelAzureOpenAIId = UUID().uuidString
15+
let embeddingModelOpenAIId = UUID().uuidString
16+
let embeddingModelAzureOpenAIId = UUID().uuidString
17+
18+
let openAIAPIKeyName = "OpenAI"
19+
let openAIAPIKey = defaults.deprecatedValue(for: \.openAIAPIKey)
20+
if !openAIAPIKey.isEmpty {
21+
try keychain.update(openAIAPIKey, key: openAIAPIKeyName)
22+
}
23+
24+
let azureOpenAIAPIKeyName = "Azure OpenAI"
25+
let azureOpenAIAPIKey = defaults.deprecatedValue(for: \.azureOpenAIAPIKey)
26+
if !azureOpenAIAPIKey.isEmpty {
27+
try keychain.update(azureOpenAIAPIKey, key: azureOpenAIAPIKeyName)
28+
}
29+
30+
defaults.setupDefaultValue(for: \.chatModels, defaultValue: {
31+
let openAIModel = ChatGPTModel(rawValue: defaults.deprecatedValue(for: \.chatGPTModel))
32+
33+
let openAI = ChatModel(
34+
id: chatModelOpenAIId,
35+
name: "OpenAI",
36+
format: .openAI,
37+
info: .init(
38+
apiKeyName: openAIAPIKeyName,
39+
baseURL: defaults.deprecatedValue(for: \.openAIBaseURL),
40+
maxTokens: openAIModel?.maxToken ?? defaults
41+
.deprecatedValue(for: \.chatGPTMaxToken),
42+
modelName: openAIModel?.rawValue ?? defaults
43+
.deprecatedValue(for: \.chatGPTModel)
44+
)
45+
)
46+
let azureOpenAI = ChatModel(
47+
id: chatModelAzureOpenAIId,
48+
name: "Azure OpenAI",
49+
format: .azureOpenAI,
50+
info: .init(
51+
apiKeyName: azureOpenAIAPIKeyName,
52+
baseURL: defaults.deprecatedValue(for: \.azureOpenAIBaseURL),
53+
maxTokens: defaults.deprecatedValue(for: \.chatGPTMaxToken),
54+
modelName: defaults
55+
.deprecatedValue(for: \.azureChatGPTDeployment)
56+
)
57+
)
58+
59+
return [openAI, azureOpenAI]
60+
}())
61+
62+
defaults.setupDefaultValue(for: \.defaultChatFeatureChatModelId, defaultValue: {
63+
if defaults.deprecatedValue(for: \.chatFeatureProvider) == .azureOpenAI {
64+
return chatModelAzureOpenAIId
65+
}
66+
return chatModelOpenAIId
67+
}())
68+
69+
defaults.setupDefaultValue(for: \.embeddingModels, defaultValue: {
70+
let openAIModel = OpenAIEmbeddingModel(
71+
rawValue: defaults.deprecatedValue(for: \.embeddingModel)
72+
)
73+
74+
let openAI = EmbeddingModel(
75+
id: embeddingModelOpenAIId,
76+
name: "OpenAI",
77+
format: .openAI,
78+
info: .init(
79+
apiKeyName: openAIAPIKeyName,
80+
baseURL: defaults.deprecatedValue(for: \.openAIBaseURL),
81+
maxTokens: openAIModel?.maxToken ?? 8191,
82+
modelName: openAIModel?.rawValue ?? defaults.deprecatedValue(for: \.embeddingModel)
83+
)
84+
)
85+
86+
let azureOpenAI = EmbeddingModel(
87+
id: embeddingModelAzureOpenAIId,
88+
name: "Azure OpenAI",
89+
format: .azureOpenAI,
90+
info: .init(
91+
apiKeyName: azureOpenAIAPIKeyName,
92+
baseURL: defaults.deprecatedValue(for: \.azureOpenAIBaseURL),
93+
maxTokens: 8191,
94+
modelName: defaults
95+
.deprecatedValue(for: \.azureEmbeddingDeployment)
96+
)
97+
)
98+
99+
return [openAI, azureOpenAI]
100+
}())
101+
102+
defaults.setupDefaultValue(for: \.defaultChatFeatureEmbeddingModelId, defaultValue: {
103+
if defaults.deprecatedValue(for: \.embeddingFeatureProvider) == .azureOpenAI {
104+
return embeddingModelAzureOpenAIId
105+
}
106+
return embeddingModelOpenAIId
107+
}())
108+
}
109+
Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Configs
22
import Foundation
3-
import GitHubCopilotService
43
import Preferences
54

65
extension UserDefaultPreferenceKeys {
@@ -27,50 +26,8 @@ public struct ServiceUpdateMigrator {
2726
if old <= 135 {
2827
try migrateFromLowerThanOrEqualToVersion135()
2928
}
29+
if old <= 229 {
30+
try migrateTo230()
31+
}
3032
}
3133
}
32-
33-
func migrateFromLowerThanOrEqualToVersion135() throws {
34-
// 0. Create the application support folder if it doesn't exist
35-
36-
let urls = try GitHubCopilotBaseService.createFoldersIfNeeded()
37-
38-
// 1. Move the undefined folder in application support into a sub folder called `GitHub
39-
// Copilot/support`
40-
41-
let undefinedFolderURL = urls.applicationSupportURL.appendingPathComponent("undefined")
42-
var isUndefinedADirectory: ObjCBool = false
43-
let isUndefinedExisted = FileManager.default.fileExists(
44-
atPath: undefinedFolderURL.path,
45-
isDirectory: &isUndefinedADirectory
46-
)
47-
if isUndefinedExisted, isUndefinedADirectory.boolValue {
48-
try FileManager.default.moveItem(
49-
at: undefinedFolderURL,
50-
to: urls.supportURL.appendingPathComponent("undefined")
51-
)
52-
}
53-
54-
// 2. Copy the GitHub copilot language service to `GitHub Copilot/executable`
55-
56-
let copilotFolderURL = urls.executableURL.appendingPathComponent("copilot")
57-
var copilotIsFolder: ObjCBool = false
58-
let executable = Bundle.main.resourceURL?.appendingPathComponent("copilot")
59-
if let executable,
60-
FileManager.default.fileExists(atPath: executable.path, isDirectory: &copilotIsFolder),
61-
!FileManager.default.fileExists(atPath: copilotFolderURL.path)
62-
{
63-
try FileManager.default.copyItem(
64-
at: executable,
65-
to: urls.executableURL.appendingPathComponent("copilot")
66-
)
67-
}
68-
69-
// 3. Use chmod to change the permission of the executable to 755
70-
71-
try FileManager.default.setAttributes(
72-
[.posixPermissions: 0o755],
73-
ofItemAtPath: copilotFolderURL.path
74-
)
75-
}
76-

Core/Tests/ActiveDocumentChatContextCollectorTests/UnknownLanguageFocusedCodeFinderTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import XCTest
22
import Foundation
3+
import FocusedCodeFinder
34

45
@testable import ActiveDocumentChatContextCollector
56

Core/Tests/PromptToCodeServiceTests/ExtractCodeFromChatGPTTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import XCTest
33

44
final class ExtractCodeFromChatGPTTests: XCTestCase {
55
func test_extract_from_no_code_block() {
6-
let api = OpenAIPromptToCodeAPI()
6+
let api = OpenAIPromptToCodeService()
77
let result = api.extractCodeAndDescription(from: """
88
hello world!
99
""")
@@ -13,7 +13,7 @@ final class ExtractCodeFromChatGPTTests: XCTestCase {
1313
}
1414

1515
func test_extract_from_incomplete_code_block() {
16-
let api = OpenAIPromptToCodeAPI()
16+
let api = OpenAIPromptToCodeService()
1717
let result = api.extractCodeAndDescription(from: """
1818
```swift
1919
func foo() {}
@@ -24,7 +24,7 @@ final class ExtractCodeFromChatGPTTests: XCTestCase {
2424
}
2525

2626
func test_extract_from_complete_code_block() {
27-
let api = OpenAIPromptToCodeAPI()
27+
let api = OpenAIPromptToCodeService()
2828
let result = api.extractCodeAndDescription(from: """
2929
```swift
3030
func foo() {}
@@ -40,7 +40,7 @@ final class ExtractCodeFromChatGPTTests: XCTestCase {
4040
}
4141

4242
func test_extract_from_incomplete_code_block_without_language() {
43-
let api = OpenAIPromptToCodeAPI()
43+
let api = OpenAIPromptToCodeService()
4444
let result = api.extractCodeAndDescription(from: """
4545
```
4646
func foo() {}
@@ -51,7 +51,7 @@ final class ExtractCodeFromChatGPTTests: XCTestCase {
5151
}
5252

5353
func test_extract_from_code_block_without_language() {
54-
let api = OpenAIPromptToCodeAPI()
54+
let api = OpenAIPromptToCodeService()
5555
let result = api.extractCodeAndDescription(from: """
5656
```
5757
func foo() {}

0 commit comments

Comments
 (0)