@@ -73,6 +73,9 @@ func (c *openaiCommand) newConversation(match matcher.Result, message msg.Messag
7373}
7474
7575func (c * openaiCommand ) startConversation (message msg.Ref , text string ) bool {
76+ // Parse hashtags and get cleaned text
77+ cleanText , hashtagOptions := ParseHashtags (text )
78+
7679 messageHistory := make ([]ChatMessage , 0 )
7780
7881 if c .cfg .InitialSystemMessage != "" {
@@ -82,6 +85,28 @@ func (c *openaiCommand) startConversation(message msg.Ref, text string) bool {
8285 })
8386 }
8487
88+ // Handle #message-history hashtag
89+ if hashtagOptions .MessageHistory > 0 {
90+ channelMessages , err := c .getChannelHistory (message .GetChannel (), hashtagOptions .MessageHistory )
91+ if err != nil {
92+ c .ReplyError (message , fmt .Errorf ("can't load channel history: %w" , err ))
93+ return true
94+ }
95+
96+ // Add channel history as context
97+ messageHistory = append (messageHistory , ChatMessage {
98+ Role : roleSystem ,
99+ Content : fmt .Sprintf ("Recent channel conversation history (last %d messages):" , hashtagOptions .MessageHistory ),
100+ })
101+
102+ for _ , channelMsg := range channelMessages {
103+ messageHistory = append (messageHistory , ChatMessage {
104+ Role : roleUser ,
105+ Content : fmt .Sprintf ("User <@%s> wrote: %s" , channelMsg .User , channelMsg .Text ),
106+ })
107+ }
108+ }
109+
85110 var storageIdentifier string
86111 if message .GetThread () != "" {
87112 // "openai" was triggered within a existing thread. -> fetch the whole thread history as context
@@ -106,10 +131,10 @@ func (c *openaiCommand) startConversation(message msg.Ref, text string) bool {
106131 if c .cfg .LogTexts {
107132 log .Infof ("openai thread context: %s" , messageHistory )
108133 }
109- } else if linkRe .MatchString (text ) {
134+ } else if linkRe .MatchString (cleanText ) {
110135 // a link to another thread was posted -> use this messages as context
111- link := linkRe .FindStringSubmatch (text )
112- text = linkRe .ReplaceAllString (text , "" )
136+ link := linkRe .FindStringSubmatch (cleanText )
137+ cleanText = linkRe .ReplaceAllString (cleanText , "" )
113138
114139 relatedMessage := msg.MessageRef {
115140 Channel : link [2 ],
@@ -134,7 +159,7 @@ func (c *openaiCommand) startConversation(message msg.Ref, text string) bool {
134159 storageIdentifier = getIdentifier (message .GetChannel (), message .GetTimestamp ())
135160 }
136161
137- c .callAndStore (messageHistory , storageIdentifier , message , text )
162+ c .callAndStore (messageHistory , storageIdentifier , message , cleanText , hashtagOptions )
138163 return true
139164}
140165
@@ -145,6 +170,9 @@ func (c *openaiCommand) reply(message msg.Ref, text string) bool {
145170 return false
146171 }
147172
173+ // Parse hashtags from reply message
174+ cleanText , hashtagOptions := ParseHashtags (text )
175+
148176 // Load the chat history from storage.
149177 identifier := getIdentifier (message .GetChannel (), message .GetThread ())
150178
@@ -156,24 +184,40 @@ func (c *openaiCommand) reply(message msg.Ref, text string) bool {
156184 }
157185
158186 // Call the API and send the last messages as history to give a proper context
159- c .callAndStore (messages , identifier , message , text )
187+ c .callAndStore (messages , identifier , message , cleanText , hashtagOptions )
160188
161189 return true
162190}
163191
164192// call the GPT-3 API, sends the response to the user, and stores the updated chat history.
165- func (c * openaiCommand ) callAndStore (messages []ChatMessage , storageIdentifier string , message msg.Ref , inputText string ) {
193+ func (c * openaiCommand ) callAndStore (messages []ChatMessage , storageIdentifier string , message msg.Ref , inputText string , options HashtagOptions ) {
166194 // Append the actual user input to the message list.
167195 messages = append (messages , ChatMessage {
168196 Role : roleUser ,
169197 Content : inputText ,
170198 })
171199
172- messages , inputTokens , truncatedMessages := truncateMessages (c .cfg .Model , messages )
200+ // Create a custom config based on hashtag options
201+ customCfg := c .cfg
202+
203+ // Apply model override if specified
204+ if options .Model != "" {
205+ customCfg .Model = options .Model
206+ }
207+
208+ // Apply reasoning effort if specified
209+ if options .ReasoningEffort == "none" {
210+ // User explicitly requested no reasoning effort with #no-thinking
211+ customCfg .ReasoningEffort = ""
212+ } else if options .ReasoningEffort != "" {
213+ customCfg .ReasoningEffort = options .ReasoningEffort
214+ }
215+
216+ messages , inputTokens , truncatedMessages := truncateMessages (customCfg .Model , messages )
173217 if truncatedMessages > 0 {
174218 c .SendMessage (
175219 message ,
176- fmt .Sprintf ("Note: The token length of %d exceeded! %d messages were not sent" , getMaxTokensForModel (c . cfg .Model ), truncatedMessages ),
220+ fmt .Sprintf ("Note: The token length of %d exceeded! %d messages were not sent" , getMaxTokensForModel (customCfg .Model ), truncatedMessages ),
177221 slack .MsgOptionTS (message .GetTimestamp ()),
178222 )
179223 }
@@ -186,7 +230,8 @@ func (c *openaiCommand) callAndStore(messages []ChatMessage, storageIdentifier s
186230
187231 startTime := time .Now ()
188232
189- response , err := CallChatGPT (c .cfg , messages , true )
233+ // Use customCfg instead of c.cfg
234+ response , err := CallChatGPT (customCfg , messages , true )
190235 if err != nil {
191236 c .ReplyError (message , fmt .Errorf ("openai error: %w" , err ))
192237 return
@@ -254,7 +299,16 @@ func (c *openaiCommand) callAndStore(messages []ChatMessage, storageIdentifier s
254299 logFields := log.Fields {
255300 "input_tokens" : inputTokens ,
256301 "output_tokens" : outputTokens ,
257- "model" : c .cfg .Model ,
302+ "model" : customCfg .Model ,
303+ }
304+ if options .Model != "" {
305+ logFields ["model_override" ] = options .Model
306+ }
307+ if options .ReasoningEffort != "" {
308+ logFields ["reasoning_effort" ] = customCfg .ReasoningEffort
309+ }
310+ if options .MessageHistory > 0 {
311+ logFields ["message_history_count" ] = options .MessageHistory
258312 }
259313 if c .cfg .LogTexts {
260314 logFields ["input_text" ] = inputText
@@ -297,15 +351,49 @@ func (c *openaiCommand) GetTemplateFunction() template.FuncMap {
297351 }
298352}
299353
354+ // getChannelHistory fetches the last N messages from a channel (excluding threads)
355+ func (c * openaiCommand ) getChannelHistory (channel string , count int ) ([]slack.Message , error ) {
356+ params := & slack.GetConversationHistoryParameters {
357+ ChannelID : channel ,
358+ Limit : count ,
359+ }
360+
361+ response , err := c .GetConversationHistory (params )
362+ if err != nil {
363+ return nil , err
364+ }
365+
366+ // Filter out messages that are thread replies (have ThreadTimestamp set)
367+ mainMessages := make ([]slack.Message , 0 )
368+ for _ , message := range response .Messages {
369+ // Only include main channel messages, not thread replies
370+ if message .ThreadTimestamp == "" || message .ThreadTimestamp == message .Timestamp {
371+ mainMessages = append (mainMessages , message )
372+ }
373+ }
374+
375+ // Reverse to get chronological order (API returns newest first)
376+ for i := range len (mainMessages ) / 2 {
377+ j := len (mainMessages ) - i - 1
378+ mainMessages [i ], mainMessages [j ] = mainMessages [j ], mainMessages [i ]
379+ }
380+
381+ return mainMessages , nil
382+ }
383+
300384func (c * openaiCommand ) GetHelp () []bot.Help {
301385 return []bot.Help {
302386 {
303387 Command : "openai <question>" ,
304- Description : "Starts a chatgpt/openai conversation in a new thread" ,
388+ Description : "Starts a chatgpt/openai conversation in a new thread. Supports hashtags for advanced options: #model-<name> (e.g., #model-gpt-4o), #high-thinking/#medium-thinking/#low-thinking/#no-thinking for reasoning control, #message-history or #message-history-<N> to include recent channel messages as context " ,
305389 Category : category ,
306390 Examples : []string {
307391 "openai whats 1+1?" ,
308392 "chatgpt whats 1+1?" ,
393+ "openai #model-gpt-4o explain quantum computing" ,
394+ "chatgpt #high-thinking #model-o1 solve this complex problem" ,
395+ "openai #message-history-20 what did we discuss about the deployment?" ,
396+ "chatgpt #model-gpt-4 #low-thinking #message-history quick summary please" ,
309397 },
310398 },
311399 {
0 commit comments