Commit Graph
29 Commits
Author SHA1 Message Date
Linus Rath d7cb895ebf Merge branch 'feat/assistant-everywhere' into feat/assistant-d
# Conflicts:
#	lib/__tests__/plugin-permission-coverage.test.ts
2026-11-03 01:19:42 +01:00
Linus Rath 55d9c81210 Merge more actions for the assistant (package C) 2026-11-03 01:13:47 +01:00
Linus Rath 6c3e68ce4e Merge branch 'feat/assistant-everywhere' into feat/assistant-d 2026-11-03 01:01:29 +01:00
Linus Rath 989cfc64a4 fix: offer a plugin the invitation and settings calls only once it was granted their permission 2026-11-03 00:55:50 +01:00
Linus Rath 37aaf05d6d fix: spend a plugin's undo token only once its undo went through, so a failed undo can be tried again 2026-11-03 00:51:30 +01:00
Linus Rath 169100eb12 fix: take the setting names app.getSettings gives, and check hidden, gated and restricted settings on undo too 2026-11-03 00:47:35 +01:00
Linus Rath 22a783efe0 fix: check an invitation's sender also when it claims one of the user's own addresses 2026-11-03 00:43:16 +01:00
Linus Rath 6ef1397a53 fix: refuse to switch the out-of-office on for a plugin while it forwards mail or that can't be read 2026-11-03 00:42:30 +01:00
Linus Rath f8de35dd85 feat: let plugins count a conversation's messages, and read only the newest 50
api.email.getThread fetches only the newest 50 messages of a thread
(Thread/get, then Email/get for those ids) instead of all of them with
their bodies. api.email.getThreadCount answers the number of messages
from Thread/get, with its own rate limit.

plugin-host-thread.test.ts now expects getThreadEmails to be called with
{ newest: 50 }, the new option that limits what is fetched.
2026-11-03 00:38:07 +01:00
Linus Rath d68970126e feat: tell plugins when the open message's attachments can't be read from this login 2026-11-03 00:33:59 +01:00
Linus Rath 9ce4d01807 fix: keep the reader still while the list changes, and give Pro tabs no list ticks 2026-11-03 00:30:56 +01:00
Linus Rath 23c410ddea fix: ask the server whether a folder is shared before a plugin's move, filter or archive files mail there 2026-11-03 00:29:02 +01:00
Linus Rath 08bc05a20b Merge branch 'feat/assistant-everywhere' into feat/assistant-b 2026-11-03 00:24:50 +01:00
Linus Rath 267ca40522 Merge branch 'feat/assistant-everywhere' into feat/assistant-c 2026-11-03 00:24:12 +01:00
Linus Rath 12dc2ce3c8 feat: let plugins find, read, attach, save and create files in Files 2026-11-03 00:17:46 +01:00
Linus Rath 82c3c969be fix: keep calendar.deleteEvent working for callers whose client names no account 2026-11-03 00:00:17 +01:00
Linus Rath a256beb918 fix: tell each plugin whether it may show the side panel
api.host.features.sidePanel now says whether this plugin may offer the
app-side-panel (ui:side-panel granted), not only that the webmail has
it. A plugin enabled before an update added the permission can then say
so instead of offering a switch that does nothing. The host computes the
assistant's flags per plugin for a frame's init and for each push.

plugin-host-features.test.ts: the host bridge assertions take the
assistant's flags as the test plugin sees them (it lacks ui:side-panel,
so sidePanel is false there).
2026-11-02 23:54:52 +01:00
Linus Rath 4356ccadb7 fix: load the attachment readers only when needed and read two files at a time at most 2026-11-02 23:37:34 +01:00
Linus Rath 89df82adce fix: answer an invitation whose event lies outside the calendar's loaded weeks 2026-11-02 23:29:43 +01:00
Linus Rath d3d150d2c4 fix: let plugins answer invitations found by a search of the user's own mail 2026-11-02 23:20:54 +01:00
Linus Rath fd30fdcd27 feat: let plugins answer invitations, add filter rules, change many messages and change settings, with undo
The AI assistant's "more actions" need host calls today's plugin API
lacks. Area c of lib/plugin-sandbox/assistant adds them:

- `calendar.respond(emailId, status)`, new permission calendar:respond:
  answers an invitation of the user's own account through
  lib/calendar-rsvp.ts, like the reader's banner
- `calendar.deleteEvent` now returns an undo token for a single event;
  `calendar.undoDelete` creates it again from the host's copy
- `filters.list/create/undo` over Settings > Filters' model; forward,
  redirect, reject, discard and keep are refused, and so are folders
  that are shared or not the account's own
- `email.batch/undoBatch`: up to 200 messages through the store's
  batch functions, restore points first, one entry in the undo history
- `vacation.get` also says whether the out-of-office forwards mail
- `app.describeSettings`, `app.setSettings` and `app.undoSettings`, new
  permission settings:change, over the allow-list in
  lib/settings-schema.ts, refusing locked, hidden, restricted and gated
  settings when the change is made

Undo tokens stay in the host for 30 minutes, bound to the plugin and
the account. app.getSettings now shows every setting setSettings may
change. settings:write's text is reworded to what it gates (tags).
plugin-host-api-app-info gains a test; its other assertions are as
they were.
2026-11-02 23:14:23 +01:00
Linus Rath 8139214aea feat: tell the reader panel which messages are ticked in the list 2026-11-02 22:12:01 +01:00
Linus Rath 398ee1ef06 feat: let plugins read a whole conversation 2026-11-02 22:07:32 +01:00
Linus Rath 2de7821e35 feat: let plugins see a message's pictures, shrunk in the app 2026-11-02 22:04:52 +01:00
Linus Rath 8fcd647215 feat: let plugins show a side panel next to Calendar, Contacts, Files and Settings 2026-11-02 21:59:36 +01:00
Linus Rath bda658bada feat: tell plugins the Content-ID and alt text of a message's inline images
EmailReadView.attachments gain cid and alt for images the HTML shows
inline. plugin-projection.test.ts now expects the cid on its inline
logo, since the view carries it.
2026-11-02 21:58:16 +01:00
Linus Rath bda99e1df8 feat: let plugins read the text of attachments
api.email.getAttachmentText reads PDF (pdf.js), Word, Excel, PowerPoint
and OpenDocument files (own reader over fflate and DOMParser, unpacking
capped at 50 MB), text, CSV, HTML, calendar and address files, and
answers with a status for what it can't read. The extraction lives in
lib/attachment-text so Files can use it too.

The sandbox runtime now copies every flag the host sends into
api.host.features; before, it kept only the three core flags, so the
assistant's flags never reached a plugin. The host bridge assertions in
plugin-host-features.test.ts compare against the core flags plus the
assistant's (withAssistant), since the init payload and host-change now
carry attachmentText too.
2026-11-02 21:53:05 +01:00
Linus Rath e044299dea chore: drop lint directives the assistant's area files don't need 2026-11-02 21:21:39 +01:00
Linus Rath f7ff8212a3 refactor: give the AI assistant's host APIs one set of files per area
The assistant's new host calls come in four areas (context, actions,
Files, the panel in every view), built side by side. Each area gets its
own files under lib/plugin-sandbox/assistant for its permissions, method
table, dispatcher, host feature flags and sandbox methods; the shared
files only read the merged result. No area adds anything yet. The host
features test now compares against the core flags plus the areas' flags.
2026-11-02 21:21:06 +01:00