Skip to content

Commit e1c32ff

Browse files
committed
fix review comment
chang default model for copilot refactor the message handler about copilot remove useless console ouput
1 parent 6e825b2 commit e1c32ff

File tree

11 files changed

+310
-113
lines changed

11 files changed

+310
-113
lines changed

packages/types/src/providers/copilot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const copilotDefaultModelId = "claude-sonnet-4"
1+
export const copilotDefaultModelId = "gpt-4.1"
22

33
export const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98"
44
export const GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code"

src/api/providers/fetchers/copilot.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,6 @@ export class CopilotAuthenticator {
173173
expires_in: deviceData.expires_in,
174174
interval: deviceData.interval || 5,
175175
})
176-
} else {
177-
// Fallback to console logging
178-
console.log(`\n🔐 Copilot Authentication Required`)
179-
console.log(`Please visit: ${deviceData.verification_uri}`)
180-
console.log(`Enter code: ${deviceData.user_code}`)
181-
console.log(`Waiting for authentication...\n`)
182176
}
183177

184178
// Step 3: Poll for access token
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { MessageHandlerStrategy, MessageHandlerContext } from "../types"
2+
import { CopilotAuthenticator } from "../../../../api/providers/fetchers/copilot"
3+
4+
/**
5+
* Strategy for handling authenticateCopilot message
6+
*/
7+
export class AuthenticateCopilotStrategy implements MessageHandlerStrategy {
8+
async handle(context: MessageHandlerContext): Promise<boolean> {
9+
const { provider } = context
10+
11+
// Start device code authentication for Copilot
12+
try {
13+
const authenticator = CopilotAuthenticator.getInstance()
14+
15+
// Set up callbacks
16+
authenticator.setDeviceCodeCallback((deviceInfo) => {
17+
provider.postMessageToWebview({
18+
type: "copilotDeviceCode",
19+
copilotDeviceCode: {
20+
user_code: deviceInfo.user_code,
21+
verification_uri: deviceInfo.verification_uri,
22+
expires_in: deviceInfo.expires_in,
23+
},
24+
})
25+
})
26+
27+
authenticator.setAuthTimeoutCallback((error) => {
28+
provider.postMessageToWebview({
29+
type: "copilotAuthError",
30+
error: error,
31+
})
32+
})
33+
34+
await authenticator.getApiKey() // This will trigger the device code flow
35+
provider.postMessageToWebview({
36+
type: "copilotAuthStatus",
37+
copilotAuthenticated: true,
38+
})
39+
return true
40+
} catch (error) {
41+
console.error("Failed to authenticate with Copilot:", error)
42+
provider.postMessageToWebview({
43+
type: "copilotAuthError",
44+
error: error instanceof Error ? error.message : "Authentication failed",
45+
})
46+
return false
47+
}
48+
}
49+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { MessageHandlerStrategy, MessageHandlerContext } from "../types"
2+
import { CopilotAuthenticator } from "../../../../api/providers/fetchers/copilot"
3+
4+
/**
5+
* Strategy for handling checkCopilotAuth message
6+
*/
7+
export class CheckCopilotAuthStrategy implements MessageHandlerStrategy {
8+
async handle(context: MessageHandlerContext): Promise<boolean> {
9+
const { provider } = context
10+
11+
try {
12+
const authenticator = CopilotAuthenticator.getInstance()
13+
const isAuthenticated = await authenticator.isAuthenticated()
14+
15+
provider.postMessageToWebview({
16+
type: "copilotModels",
17+
copilotAuthenticated: isAuthenticated,
18+
})
19+
return true
20+
} catch (error) {
21+
console.error("Failed to check Copilot auth:", error)
22+
provider.postMessageToWebview({
23+
type: "copilotModels",
24+
copilotAuthenticated: false,
25+
error: error instanceof Error ? error.message : "Unknown error",
26+
})
27+
return true
28+
}
29+
}
30+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { MessageHandlerStrategy, MessageHandlerContext } from "../types"
2+
import { CopilotAuthenticator } from "../../../../api/providers/fetchers/copilot"
3+
4+
/**
5+
* Strategy for handling clearCopilotAuth message
6+
*/
7+
export class ClearCopilotAuthStrategy implements MessageHandlerStrategy {
8+
async handle(context: MessageHandlerContext): Promise<boolean> {
9+
const { provider } = context
10+
11+
try {
12+
const authenticator = CopilotAuthenticator.getInstance()
13+
await authenticator.clearAuth()
14+
15+
provider.postMessageToWebview({
16+
type: "copilotModels",
17+
copilotModels: {},
18+
success: true,
19+
})
20+
return true
21+
} catch (error) {
22+
console.error("Failed to clear Copilot auth:", error)
23+
provider.postMessageToWebview({
24+
type: "copilotModels",
25+
copilotModels: {},
26+
error: error instanceof Error ? error.message : "Unknown error",
27+
})
28+
return true
29+
}
30+
}
31+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copilot message handling module
3+
*
4+
* This module implements the Strategy pattern for handling Copilot-related messages.
5+
* Each message type has its own dedicated handler that implements the MessageHandler interface.
6+
*
7+
* Supported message types:
8+
* - requestCopilotModels: Fetches available Copilot models
9+
* - authenticateCopilot: Initiates Copilot authentication flow
10+
* - clearCopilotAuth: Clears stored Copilot authentication
11+
* - checkCopilotAuth: Checks current Copilot authentication status
12+
*/
13+
14+
import { RequestCopilotModelsStrategy } from "./requestCopilotModels"
15+
import { AuthenticateCopilotStrategy } from "./authenticateCopilot"
16+
import { ClearCopilotAuthStrategy } from "./clearCopilotAuth"
17+
import { CheckCopilotAuthStrategy } from "./checkCopilotAuth"
18+
import { MessageHandlerRegistry } from "../types"
19+
20+
/**
21+
* Register all Copilot-related message handler strategies
22+
*/
23+
export function registerCopilotStrategies(messageHandlerRegistry: MessageHandlerRegistry): void {
24+
// Register each strategy with its corresponding message type
25+
messageHandlerRegistry.registerStrategy("requestCopilotModels", new RequestCopilotModelsStrategy())
26+
messageHandlerRegistry.registerStrategy("authenticateCopilot", new AuthenticateCopilotStrategy())
27+
messageHandlerRegistry.registerStrategy("clearCopilotAuth", new ClearCopilotAuthStrategy())
28+
messageHandlerRegistry.registerStrategy("checkCopilotAuth", new CheckCopilotAuthStrategy())
29+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { MessageHandlerStrategy, MessageHandlerContext } from "../types"
2+
import { getCopilotModels } from "../../../../api/providers/fetchers/copilot"
3+
import { ModelRecord } from "../../../../shared/api"
4+
5+
/**
6+
* Strategy for handling requestCopilotModels message
7+
*/
8+
export class RequestCopilotModelsStrategy implements MessageHandlerStrategy {
9+
async handle(context: MessageHandlerContext): Promise<boolean> {
10+
const { provider } = context
11+
12+
try {
13+
const copilotModels = await getCopilotModels()
14+
provider.postMessageToWebview({
15+
type: "copilotModels",
16+
copilotModels,
17+
})
18+
return true
19+
} catch (error) {
20+
console.error("Failed to request Copilot models:", error)
21+
// Return empty ModelRecord on error
22+
const emptyModels: ModelRecord = {}
23+
provider.postMessageToWebview({
24+
type: "copilotModels",
25+
copilotModels: emptyModels,
26+
})
27+
return true
28+
}
29+
}
30+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./types"
2+
export * from "./registry"
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { MarketplaceManager } from "../../../services/marketplace"
2+
import { WebviewMessage } from "../../../shared/WebviewMessage"
3+
import { ClineProvider } from "../ClineProvider"
4+
import { registerCopilotStrategies } from "./copilot"
5+
import { MessageHandlerStrategy, MessageHandlerRegistry, MessageHandlerContext } from "./types"
6+
7+
/**
8+
* Central registry for message handler strategies
9+
* Implements strategy pattern with key-based registration
10+
*/
11+
export class DefaultMessageHandlerRegistry implements MessageHandlerRegistry {
12+
private static instance: DefaultMessageHandlerRegistry | null = null
13+
private strategies: Map<string, MessageHandlerStrategy> = new Map()
14+
15+
private constructor() {}
16+
17+
public static getInstance() {
18+
if (DefaultMessageHandlerRegistry.instance === null) {
19+
DefaultMessageHandlerRegistry.instance = new DefaultMessageHandlerRegistry()
20+
registerCopilotStrategies(DefaultMessageHandlerRegistry.instance)
21+
}
22+
return DefaultMessageHandlerRegistry.instance
23+
}
24+
25+
/**
26+
* Registers a strategy for handling a specific message type
27+
*/
28+
registerStrategy(messageType: string, strategy: MessageHandlerStrategy): void {
29+
this.strategies.set(messageType, strategy)
30+
}
31+
32+
/**
33+
* Gets a strategy for the given message type
34+
*/
35+
getStrategy(messageType: string): MessageHandlerStrategy | null {
36+
return this.strategies.get(messageType) || null
37+
}
38+
39+
/**
40+
* Gets all registered message types
41+
*/
42+
getSupportedTypes(): string[] {
43+
return Array.from(this.strategies.keys())
44+
}
45+
46+
async handleMessage(
47+
provider: ClineProvider,
48+
message: WebviewMessage,
49+
marketplaceManager?: MarketplaceManager,
50+
): Promise<boolean> {
51+
const context: MessageHandlerContext = {
52+
provider,
53+
message,
54+
marketplaceManager,
55+
}
56+
57+
const strategy = this.getStrategy(context.message.type)
58+
59+
if (strategy) {
60+
try {
61+
return await strategy.handle(context)
62+
} catch (error) {
63+
console.error(`Error handling message type "${context.message.type}":`, error)
64+
return false
65+
}
66+
}
67+
68+
// Message type not supported by any registered strategy
69+
return false
70+
}
71+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ClineProvider } from "../ClineProvider"
2+
import { WebviewMessage } from "../../../shared/WebviewMessage"
3+
import { MarketplaceManager } from "../../../services/marketplace"
4+
5+
/**
6+
* Context provided to message handlers
7+
*/
8+
export interface MessageHandlerContext {
9+
/** The ClineProvider instance */
10+
provider: ClineProvider
11+
/** The webview message to handle */
12+
message: WebviewMessage
13+
/** Optional marketplace manager */
14+
marketplaceManager?: MarketplaceManager
15+
}
16+
17+
/**
18+
* Strategy interface for handling specific message types
19+
*/
20+
export interface MessageHandlerStrategy {
21+
/**
22+
* Handles a specific webview message type
23+
* @param context The message handler context
24+
* @returns Promise<boolean> indicating whether the message was handled
25+
*/
26+
handle(context: MessageHandlerContext): Promise<boolean>
27+
}
28+
29+
/**
30+
* Registry for message handler strategies
31+
*/
32+
export interface MessageHandlerRegistry {
33+
/**
34+
* Registers a strategy for handling a specific message type
35+
* @param messageType The type of message to handle
36+
* @param strategy The strategy to register
37+
*/
38+
registerStrategy(messageType: string, strategy: MessageHandlerStrategy): void
39+
40+
/**
41+
* Gets a strategy for the given message type
42+
* @param messageType The type of message to handle
43+
* @returns MessageHandlerStrategy instance or null if not supported
44+
*/
45+
getStrategy(messageType: string): MessageHandlerStrategy | null
46+
47+
/**
48+
* Gets all registered message types
49+
* @returns Array of supported message type strings
50+
*/
51+
getSupportedTypes(): string[]
52+
}

0 commit comments

Comments
 (0)