8000 feat(automations): new assets as emails, calendar events, files, uploads, web pages and imports by adeelahmad · Pull Request #435 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(automations): new assets as emails, calendar events, files, uploads, web pages and imports - #435

Merged
adeelahmad merged 3 commits into
mainfrom
claude/project-thread-pss8a6
Oct 15, 2026
Merged

adeelahmad merged 3 commits into
mainfrom
claude/project-thread-pss8a6

Conversation

@adeelahmad
@adeelahmad adeelahmad commented Oct 15, 2026 •
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: every new asset in the stream of activities was a plain asset.added, so an automation couldn't say "when an email from the school arrives" and the timeline couldn't tell an email from an upload.

After: a new asset is an activity of the most specific kind its row tells, each a child of asset.added (a trigger on asset.added still matches them all):

Kind Object adds Example summary
email.received from, to, cc, subject, list, mailbox, date, snippet, attachments Work mail received “School trip on Friday” from office@stmarys.org
calendar_event.added startTime, endTime, location, organizer, attendees, calendar Family calendar added the event “Parents' evening” on 2026-10-20
file.added path, mediaType, size, duration Office share added “Minutes”
upload.added path (file name), mediaType, size, duration Sam uploaded “Call with the school”
web_page.saved href, site Sam saved “Museum opening hours” from museum.example.org
import.received via (hook, paste, file) Phone shortcut imported “Shopping list”

How: the kind comes from the row's content type and where it came from (mail or calendar source, import hook, web, remote, the uploads folder, an import), never from reading the file. Actors are named from what Lens writes down (sources and watches, people by account id or email, import hooks by id or by name, routines, sensors, automations, the assistant) by events_content.actors, a few batched queries per page with names kept 30 seconds. Every asset's object also carries its recognised content type now (it was only a chosen one). Outside text (subjects, addresses, snippets, places, file names, page addresses) is listed in lens.untrusted.

So nothing is parsed on read, a message's addressing is kept on the resource as it is listed (recording.mail; Cc now kept apart, Gmail's snippet kept), a calendar event's times, place and people as it is imported (recording.event, calendars.details), and an email's attachment count and the start of its text once it is read (convert.email_info, into the existing recording.email, whose API schema EmailInfo now names attachments and snippet). Older rows are read without those fields.

Workflow studio M2 (content sources), part 1 of 3. Jobs, deletions and calendar moves come next, then comments, notes and graph changes.

Motivation and Context

Workflow studio plan, module M2 (/mnt/project-files/workflow-studio/briefs/M2.md): make what arrives in the archive readable as specific activities for triggers (M6), pickers (M11), variables (M9) and the timeline (M10).

Defaults taken (reversible): an uploaded .eml counts as email.received (content type decides first); a file an email held stays asset.added; a video saved from a URL is web_page.saved; the page address is object.href so object.url stays the Lens link, as on every other kind; duration is in seconds.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (make hooks checks it on commit).
  • I added or updated tests.
  • My change requires documentation updates, and I have updated docs/ accordingly.
  • Users need more than the title to understand it, so I wrote it under ## Unreleased in CHANGELOG.md. (n/a: the title says it)

Done questions (AGENTS.md)

  • Goal: delivers this part of M2, merged on green CI.
  • Agents: the new kinds show in GET /api/v1/activities and /kinds, and the MCP and assistant timeline and event_kinds tools.
  • Zero setup: nothing to install or set.
  • Fewest clicks and keystrokes: n/a, no UI (the timeline page is M10).
  • Configurable: n/a, no new settings.
  • Light: reads rows already written; a few batched queries per page, names cached.
  • Private and secure: data stays in the database; outside text marked untrusted. Threat model: n/a, no new surface (the studio's entries are M12).
  • Cost: no model calls; nothing on the ingest path changes cost.
  • User decides: nothing acts on these yet; defaults unchanged.
  • Upgrades: two new optional fields (recording.mail, recording.event); older rows read without them, so no upgrade step.
  • Honest: docs/automations.md labels these built and the rest of M2 planned.
  • Tests, docs and generated files updated (EmailInfo gained two fields; client regenerated with make openapi).
  • Open standards: Activity Streams 2.0 field names (startTime, endTime, mediaType, href); no new dependencies.
  • Result reported with evidence; "refine later" items written in docs/automations.md.

Tests: tests/domain/test_events_content.py, one per kind through the real code paths (sources._ingest with a mail and a calendar entry, a storage file, uploads.take, webcapture.create, import_hooks.accept_text and accept_file, ingest.import_text), actors, and paging 600 assets with one timestamp.

🤖 Generated with Claude Code

https://claude.ai/code/session_019nbuG2q5wEXeUxWb8vr5HJ

…ads, web pages and imports

A new asset is now an activity of the most specific kind its row tells:
email.received, calendar_event.added, file.added, upload.added,
web_page.saved or import.received, all children of asset.added, each
with its own fields (who an email was from and to, an event's times and
place, a file's path, type and size, a page's site) and outside text
marked untrusted. Actors are named from what Lens writes down (sources,
watches, people by account or email, import hooks, routines, sensors,
automations) in a few queries per page.

Mail addressing and event times are kept on the resource when it is
made (recording.mail, recording.event), and an email's attachments and
the start of its text once it is read, so nothing is parsed on read.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nbuG2q5wEXeUxWb8vr5HJ
@adeelahmad adeelahmad self-assigned this Oct 15, 2026
… the API

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nbuG2q5wEXeUxWb8vr5HJ
…-pss8a6

# Conflicts:
#	docs/automations.md
#	docs/database.md
@adeelahmad
adeelahmad merged commit 352186b into main Oct 15, 2026
10 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-pss8a6 branch October 15, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0