mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-24 20:28:16 +02:00
feat: compose new email with contact autocomplete and AI drafting (#616)
* feat: compose new email with contact autocomplete and AI drafting - Add a compose-new-email box to the email view with a recipient field that autocompletes from Gmail contacts (keyboard navigation, match highlighting, avatar chips) - Build contact indices in core: gmail_sent_contacts syncs the SENT label via the Gmail API for full coverage of people you've emailed, with gmail_contacts as an instant local-snapshot fallback; both are pre-warmed at startup so the first keystroke is instant - Add generateOneShot() one-shot text generation for the composer's "write with AI", resolving to the active default model/provider - Add getAccountName() (parsed from a recent SENT message's From header, no extra OAuth scope) so AI drafts sign off with the real name - New IPC channels: gmail:searchContacts, gmail:getAccountName, llm:generate, llm:getDefaultModel * feat: attachments, undo/redo, and unified compose for new emails - Merge ComposeNewBox into ComposeBox via a new 'new' mode, memoizing the component so inbox sync ticks no longer jank the open composer. - Add file attachments: stage files in the renderer (25MB cap), pass raw base64 over IPC, and build a multipart/mixed MIME on send. - Add undo/redo buttons to the compose toolbar. - Single Write/Edit AI bar that generates a draft, then iteratively rewrites it; drop the hardcoded Gemini Flash model and use the default Copilot model. - Suppress inbox reloads while the compose-new modal is open. - Log llm:generate provider/model/output for debugging. * fix: remove redundant Subject placeholder in composer The subject row already has a 'Subject' gutter label, so the input's placeholder repeated the word — an empty field read 'Subject' twice. Drop the placeholder to match the To/Cc/Bcc fields. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3fe7f307ab
commit
c38ddef93f
6 changed files with 772 additions and 62 deletions
|
|
@ -190,6 +190,15 @@ const ipcSchemas = {
|
|||
bodyText: z.string(),
|
||||
inReplyTo: z.string().optional(),
|
||||
references: z.string().optional(),
|
||||
attachments: z
|
||||
.array(
|
||||
z.object({
|
||||
filename: z.string(),
|
||||
mimeType: z.string(),
|
||||
contentBase64: z.string(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
messageId: z.string().optional(),
|
||||
|
|
@ -211,6 +220,12 @@ const ipcSchemas = {
|
|||
email: z.string().nullable(),
|
||||
}),
|
||||
},
|
||||
'gmail:getAccountName': {
|
||||
req: z.object({}),
|
||||
res: z.object({
|
||||
name: z.string().nullable(),
|
||||
}),
|
||||
},
|
||||
'gmail:archiveThread': {
|
||||
req: z.object({ threadId: z.string().min(1) }),
|
||||
res: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
||||
|
|
@ -388,6 +403,27 @@ const ipcSchemas = {
|
|||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'llm:getDefaultModel': {
|
||||
req: z.null(),
|
||||
res: z.object({
|
||||
model: z.string(),
|
||||
provider: z.string(),
|
||||
}),
|
||||
},
|
||||
'llm:generate': {
|
||||
req: z.object({
|
||||
prompt: z.string().min(1),
|
||||
system: z.string().optional(),
|
||||
model: z.string().optional(),
|
||||
provider: z.string().optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
text: z.string().optional(),
|
||||
model: z.string().optional(),
|
||||
provider: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'models:saveConfig': {
|
||||
req: LlmModelConfig,
|
||||
res: z.object({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue