← Public packages
@kody/mailroom
Offline-first PWA for your Kody mailbox: sent and received threads, copy-prompt for agents, no send.
src/prompt-text.ts
86 lines · 2.5 KB · TypeScriptimport { messageWhen, snippetFrom, threadKey } from './threads.ts'
import type { MailMessage, MailSummary } from './types.ts'
export function textFromMessage(
message: Pick<MailMessage, 'text_body' | 'html_body' | 'subject'>,
): string {
const text = String(message.text_body || '').trim()
if (text) return text
const html = String(message.html_body || '')
.replace(/<style[\s\S]*?<\/style>/gi, '\n')
.replace(/<script[\s\S]*?<\/script>/gi, '\n')
.replace(/<br\s*\/?>/gi, '\n')
.replace(/<\/p>/gi, '\n')
.replace(/<[^>]+>/g, ' ')
.replace(/[ \t]+\n/g, '\n')
.replace(/\n{3,}/g, '\n\n')
.replace(/[ \t]{2,}/g, ' ')
.trim()
return html || String(message.subject || '').trim()
}
export function buildMessagePrompt(message: MailMessage): string {
const when = messageWhen(message)
const body = textFromMessage(message)
return `Discuss this email with me. I am looking at it in Kody Mailroom (read-only; do not send).
Subject: ${message.subject || '(no subject)'}
Direction: ${message.direction}
From: ${message.from_address || message.envelope_from || ''}
To: ${(message.to_addresses || []).join(', ')}
When: ${when}
Message id: ${message.id}
Thread id: ${threadKey(message)}
${body}
Fetch the stored message again:
\`\`\`ts
import { kody } from 'kody:runtime'
const message = await kody.emailMessageGet({
message_id: ${JSON.stringify(message.id)},
})
\`\`\`
`
}
export function buildThreadPrompt(input: {
id: string
subject?: string | null
messages: Array<MailMessage | MailSummary>
}): string {
const lines = input.messages.map((message, index) => {
const body =
'text_body' in message || 'html_body' in message
? textFromMessage(message as MailMessage)
: snippetFrom(message)
return `--- Message ${index + 1} (${message.direction}) ---
From: ${message.from_address || message.envelope_from || ''}
To: ${(message.to_addresses || []).join(', ')}
When: ${messageWhen(message)}
Id: ${message.id}
${body}`
})
const first = input.messages[0]
const threadId = input.id || (first ? threadKey(first) : '')
return `Discuss this email thread with me. I am looking at it in Kody Mailroom (read-only; do not send).
Subject: ${input.subject || first?.subject || '(no subject)'}
Thread id: ${threadId}
Messages: ${input.messages.length}
${lines.join('\n\n')}
Fetch the thread's latest stored message:
\`\`\`ts
import { kody } from 'kody:runtime'
const { messages } = await kody.emailMessageList({ limit: 100 })
const thread = messages.filter((message) => (message.thread_id || message.id) === ${JSON.stringify(threadId)})
\`\`\`
`
}