1- import { randomUUID } from "node:crypto"
2-
31import type { ChatCompletionsPayload } from "~/services/copilot/create-chat-completions"
42
53export type HeaderMode = "savings" | "compatible"
64
75export interface RequestHeaders {
86 "X-Initiator" : "user" | "agent"
9- "X-Interaction-Id" ?: string
107}
118
12- /**
13- * Simple session manager for compatible mode
14- */
15- class SessionManager {
16- private sessionId : string = randomUUID ( )
17-
18- newSession ( ) : string {
19- this . sessionId = randomUUID ( )
20- return this . sessionId
21- }
22-
23- getCurrentSession ( ) : string {
24- return this . sessionId
25- }
26- }
27-
28- const sessionManager = new SessionManager ( )
29-
309/**
3110 * Generate headers based on mode
3211 */
3312export function generateSessionHeaders (
3413 payload : ChatCompletionsPayload ,
3514 mode : HeaderMode ,
3615) : RequestHeaders {
37- return mode === "savings" ?
38- {
39- "X-Initiator" : getSavingsInitiator ( payload ) ,
40- }
41- : {
42- "X-Initiator" : getCompatibleInitiator ( payload ) ,
43- "X-Interaction-Id" : getSessionId ( payload ) ,
44- }
16+ return {
17+ "X-Initiator" :
18+ mode === "savings" ?
19+ getSavingsInitiator ( payload )
20+ : getCompatibleInitiator ( payload ) ,
21+ }
4522}
4623
4724/**
48- * Savings mode: default behavior
25+ * Savings mode: if any message is assistant or tool, then it is agent
4926 */
5027function getSavingsInitiator (
5128 payload : ChatCompletionsPayload ,
@@ -58,42 +35,11 @@ function getSavingsInitiator(
5835}
5936
6037/**
61- * Compatible mode: replicate VS Code extension logic
38+ * Compatible mode: if last message is user then it is user
6239 */
6340function getCompatibleInitiator (
6441 payload : ChatCompletionsPayload ,
6542) : "user" | "agent" {
66- // VS Code: userInitiatedRequest = iterationNumber === 0 && !isContinuation
67- const hasAssistantMessage = payload . messages . some (
68- ( msg ) => msg . role === "assistant" ,
69- )
70- const hasToolCalls = payload . messages . some (
71- ( msg ) => msg . tool_calls && msg . tool_calls . length > 0 ,
72- )
73- const hasToolMessages = payload . messages . some ( ( msg ) => msg . role === "tool" )
74-
75- const isFirstIteration = ! hasAssistantMessage
76- const isContinuation = hasToolCalls || hasToolMessages
77-
78- return isFirstIteration && ! isContinuation ? "user" : "agent"
79- }
80-
81- /**
82- * Detect if this is the start of a new conversation
83- */
84- function isStartOfConversation ( payload : ChatCompletionsPayload ) : boolean {
85- const hasAssistantMessage = payload . messages . some (
86- ( msg ) => msg . role === "assistant" ,
87- )
88- return ! hasAssistantMessage
89- }
90-
91- /**
92- * Get session ID for compatible mode
93- */
94- function getSessionId ( payload : ChatCompletionsPayload ) : string {
95- if ( isStartOfConversation ( payload ) ) {
96- return sessionManager . newSession ( )
97- }
98- return sessionManager . getCurrentSession ( )
43+ const lastMessage = payload . messages . at ( - 1 )
44+ return lastMessage ?. role === "user" ? "user" : "agent"
9945}
0 commit comments