77
88import { Client , Events , GatewayIntentBits , ThreadAutoArchiveDuration } from "discord.js" ;
99import { spawn } from "bun" ;
10+ import { join } from "path" ;
1011
1112// Environment variables
1213const DISCORD_TOKEN = process . env . DISCORD_TOKEN ;
1314const GITHUB_REPO = process . env . GITHUB_REPO ;
1415
16+ // Session storage configuration
17+ const DATA_DIR = process . env . CLAUDE_CONFIG_DIR || "/app/data" ;
18+ const SESSIONS_FILE = join ( DATA_DIR , "thread-sessions.json" ) ;
19+
20+ // Session storage utilities using Bun file methods
21+ async function loadSessions ( ) {
22+ try {
23+ const file = Bun . file ( SESSIONS_FILE ) ;
24+ if ( await file . exists ( ) ) {
25+ return await file . json ( ) ;
26+ }
27+ return { } ;
28+ } catch ( error ) {
29+ console . error ( "Error loading sessions:" , error ) ;
30+ return { } ;
31+ }
32+ }
33+
34+ async function saveSessions ( sessions ) {
35+ try {
36+ await Bun . write ( SESSIONS_FILE , JSON . stringify ( sessions , null , 2 ) ) ;
37+ } catch ( error ) {
38+ console . error ( "Error saving sessions:" , error ) ;
39+ }
40+ }
41+
42+ async function storeThreadSession ( threadId , sessionId , title ) {
43+ const sessions = await loadSessions ( ) ;
44+ sessions [ threadId ] = { sessionId, title, createdAt : new Date ( ) . toISOString ( ) } ;
45+ await saveSessions ( sessions ) ;
46+ console . log ( `Stored session: ${ threadId } -> ${ sessionId } (${ title } )` ) ;
47+ }
48+
49+ async function getThreadSession ( threadId ) {
50+ const sessions = await loadSessions ( ) ;
51+ return sessions [ threadId ] || null ;
52+ }
53+
1554if ( ! DISCORD_TOKEN ) {
1655 console . error ( "Error: DISCORD_TOKEN environment variable is not set" ) ;
1756 process . exit ( 1 ) ;
@@ -422,14 +461,7 @@ function isNewBobbyCall(message) {
422461// Check if this is a follow-up in a Bobby thread
423462function isThreadFollowUp ( message ) {
424463 return message . channel . isThread ( ) &&
425- message . channel . name . startsWith ( 'Bobby -' ) ;
426- }
427-
428- // Extract session ID from thread name
429- function extractSessionId ( threadName ) {
430- // Match new format: "Bobby - Title - session-id"
431- const match = threadName . match ( / B o b b y - .+ - ( [ a - f 0 - 9 - ] + ) $ / ) ;
432- return match ? match [ 1 ] : null ;
464+ message . channel . name . startsWith ( 'Bobby' ) ;
433465}
434466
435467// Discord client ready event
@@ -496,9 +528,9 @@ client.on(Events.MessageCreate, async (message) => {
496528 console . log ( `New Bobby call: "${ query } " from ${ message . author . username } ` ) ;
497529
498530 try {
499- // Create a new thread
531+ // Create a new thread with simple naming
500532 const thread = await message . startThread ( {
501- name : `Bobby [PENDING] ` ,
533+ name : `Bobby Analysis ` ,
502534 autoArchiveDuration : ThreadAutoArchiveDuration . OneDay ,
503535 reason : 'Bobby analysis request' ,
504536 } ) ;
@@ -511,21 +543,17 @@ client.on(Events.MessageCreate, async (message) => {
511543 await processWithClaude ( query , thread , null ) ;
512544
513545 if ( success && sessionId ) {
514- // Update thread name with session ID and title
546+ // Store session data in JSON file instead of thread name
515547 const finalTitle = threadTitle || "Analysis" ;
516- const newThreadName = `Bobby - ${ finalTitle } - ${ sessionId } ` ;
548+ await storeThreadSession ( thread . id , sessionId , finalTitle ) ;
517549
550+ // Update thread name with a clean title
518551 try {
519- await thread . setName ( newThreadName ) ;
520- console . log ( `Updated thread name to: ${ newThreadName } ` ) ;
552+ await thread . setName ( `Bobby - ${ finalTitle } ` ) ;
553+ console . log ( `Updated thread name to: Bobby - ${ finalTitle } ` ) ;
521554 } catch ( renameError ) {
522555 console . error ( "Error renaming thread:" , renameError ) ;
523- // Fallback name if title is too long or other error
524- try {
525- await thread . setName ( `Bobby - ${ sessionId } ` ) ;
526- } catch ( fallbackError ) {
527- console . error ( "Error setting fallback thread name:" , fallbackError ) ;
528- }
556+ // Keep default name if renaming fails
529557 }
530558 }
531559
@@ -549,18 +577,20 @@ client.on(Events.MessageCreate, async (message) => {
549577 return ;
550578 }
551579
552- const sessionId = extractSessionId ( message . channel . name ) ;
553- console . log ( `Thread follow-up: "${ query } " in session ${ sessionId } ` ) ;
580+ const sessionData = await getThreadSession ( message . channel . id ) ;
581+ console . log ( `Thread follow-up: "${ query } " in thread ${ message . channel . id } ` ) ;
554582
555- if ( ! sessionId ) {
556- await message . reply ( "⚠️ Could not find session ID . Please start a new conversation by mentioning Bobby in the main channel." ) ;
583+ if ( ! sessionData || ! sessionData . sessionId ) {
584+ await message . reply ( "⚠️ Could not find session data . Please start a new conversation by mentioning Bobby in the main channel." ) ;
557585 return ;
558586 }
559587
588+ console . log ( `Using session ID: ${ sessionData . sessionId } (${ sessionData . title } )` ) ;
589+
560590 try {
561591 await message . channel . sendTyping ( ) ;
562592 const { success, response, isBug } =
563- await processWithClaude ( query , message . channel , sessionId ) ;
593+ await processWithClaude ( query , message . channel , sessionData . sessionId ) ;
564594
565595 if ( ! success ) {
566596 await message . channel . send ( "Sorry, I encountered an error while processing your request." ) ;
0 commit comments