/ buddy / prompt.ts
prompt.ts
 1  import { feature } from 'bun:bundle'
 2  import type { Message } from '../types/message.js'
 3  import type { Attachment } from '../utils/attachments.js'
 4  import { getGlobalConfig } from '../utils/config.js'
 5  import { getCompanion } from './companion.js'
 6  
 7  export function companionIntroText(name: string, species: string): string {
 8    return `# Companion
 9  
10  A small ${species} named ${name} sits beside the user's input box and occasionally comments in a speech bubble. You're not ${name} — it's a separate watcher.
11  
12  When the user addresses ${name} directly (by name), its bubble will answer. Your job in that moment is to stay out of the way: respond in ONE line or less, or just answer any part of the message meant for you. Don't explain that you're not ${name} — they know. Don't narrate what ${name} might say — the bubble handles that.`
13  }
14  
15  export function getCompanionIntroAttachment(
16    messages: Message[] | undefined,
17  ): Attachment[] {
18    if (!feature('BUDDY')) return []
19    const companion = getCompanion()
20    if (!companion || getGlobalConfig().companionMuted) return []
21  
22    // Skip if already announced for this companion.
23    for (const msg of messages ?? []) {
24      if (msg.type !== 'attachment') continue
25      if (msg.attachment.type !== 'companion_intro') continue
26      if (msg.attachment.name === companion.name) return []
27    }
28  
29    return [
30      {
31        type: 'companion_intro',
32        name: companion.name,
33        species: companion.species,
34      },
35    ]
36  }