Commit Graph
26 Commits
Author SHA1 Message Date
Sai Charan 741f5bb32a fix: support Immich v3.2.0
-  v3.2.0 renamed asset_face.personId to personGroupId and dropped person.id
in favour of a (ownerId, personGroupId) key, breaking every face/person
query.
2026-09-14 07:43:20 +00:00
Varun Raj Manoharan 7d2ee70f62 Merge pull request #301 from jonvdveen/feat/remove-tag-action
feat: Remove Tag workflow action to complement Add Tag
2026-07-10 21:20:43 +05:30
Varun Raj 40e9e0dde2 fix: resolve tag via Immich API instead of local DB table in remove_tag
The local tag table can lag behind Immich's own tag state (e.g. tags
created directly in Immich, or before this app's sync ran), causing
remove_tag to silently no-op on a tag that actually exists. Mirror the
sibling "tag" action's approach and resolve against the Immich API,
matching on the tag's full-path "value" field. Drops the now-unused
db/sql local lookup.
2026-07-10 15:48:29 +00:00
Varun Raj Manoharan 800751d493 Merge pull request #297 from jonvdveen/feat/paginate-workflow-triggers
feat: paginate workflow asset queries — remove the silent 10,000-asset cap
2026-07-10 19:36:36 +05:30
Varun Raj Manoharan ca301ee8e4 Merge pull request #298 from jonvdveen/feat/tag-condition
feat: Tag condition for workflow IF/SWITCH nodes (hierarchical, any/all/none)
2026-07-10 19:35:57 +05:30
Varun Raj 2be22df94c Merge remote-tracking branch 'origin/prerelease' into feat/resolution-condition 2026-07-10 14:03:40 +00:00
Varun Raj b66c8218bc fix: parameterize tag contains_any IN-list to close SQL injection vector
The id list was built via raw string interpolation into sql.raw().
Switch to sql.join with proper parameter binding, matching the
pattern used by the other match branches in this function.
2026-07-10 13:59:52 +00:00
jonvdveenandClaude Fable 5 95ede2efd7 feat: Remove Tag workflow action to complement Add Tag
Removes a tag (by name, matching the tag's full path value) from the
matched assets via DELETE /tags/:id/assets. The tag is looked up
without creating it — removing a tag that doesn't exist is a no-op
rather than an error, so add/remove pairs are safe in the same
workflow.

Registered in the node palette, action node, run-detail view, and
action config (same tag-name field as Add Tag).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:54:43 -06:00
jonvdveenandClaude Fable 5 1431b8523e feat: five library-cleanup conditions for workflow IF/SWITCH nodes
Adds condition types common in smart-album systems of other photo
managers (Apple Photos, Lightroom, Google Photos):

- File Size: min/max in MB (fractional) over asset_exif.fileSizeInByte
- File Name / Path: contains / not contains / starts with / ends with
  against originalFileName or originalPath (ILIKE, wildcards escaped so
  user text matches literally)
- File Extension: is any of / is none of a comma-separated list,
  case-insensitive, matched after the last dot
- Face Count: min/max visible, non-deleted detected faces — 'how many
  people', complementing the person condition's 'who'
- Time of Day: from/to hour over localDateTime (capture wall-clock
  time, no timezone math); From > To wraps past midnight (22 to 5)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:51:02 -06:00
jonvdveenandClaude Fable 5 b473bfdc5d feat: resolution condition for workflow IF/SWITCH nodes (megapixels, short/long edge)
Adds a "Resolution" condition type filtering assets by image
dimensions, useful for isolating low-resolution images for cleanup or
selecting high-resolution ones.

Three metrics with optional min/max bounds:
- Megapixels (width x height / 1e6, fractional values allowed)
- Short edge in pixels (LEAST of width/height)
- Long edge in pixels (GREATEST of width/height)

Short/long edge are orientation-agnostic, so a 4000x3000 landscape and
a 3000x4000 portrait are treated identically. Uses the exifImageWidth/
exifImageHeight columns on asset_exif, which the condition queries
already join; assets without recorded dimensions never match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:23:57 -06:00
jonvdveenandClaude Fable 5 37e0606122 feat: tag condition for workflow IF/SWITCH nodes
Adds a "Tag" condition type that filters assets by Immich tags, with
the same match modes as the person condition (has any of / has all of /
has none of). Selected tags also match their child tags via Immich's
tag_closure hierarchy table, mirroring how tag browsing behaves in
Immich itself.

- conditionBuilder: tag case with EXISTS subqueries on tag_asset,
  descendant-inclusive via tag_closure (plus a direct id check so a
  missing self-closure row can't drop matches)
- ConditionEditor: Tag entry + TagPicker multi-select (PersonPicker
  pattern) with tag color chips
- conditionSummary: node label ("Tag any of: ...")
- new GET /api/tags route + client handler + drizzle schema for
  Immich's tag table

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 19:43:02 -06:00
jonvdveenandClaude Fable 5 00aa50ba66 feat: paginate workflow queries so large libraries are fully scanned
All workflow trigger queries were capped at .limit(10000) with no
ORDER BY and no pagination, so on libraries larger than 10k assets an
all_assets ("full library scan") trigger silently evaluated an
arbitrary 10k subset. The IF/SWITCH condition queries had the same cap,
and bulk actions sent every asset id in a single Immich API request.

- resolveAssetTrigger: keyset pagination (ORDER BY id, batches of 5000)
  for all three trigger types
- IF/SWITCH: evaluate conditions against the incoming asset set in
  chunks instead of one capped inArray query
- actionExecutor: call Immich bulk endpoints in batches of 1000 ids

Verified on a 26,063-asset library (Immich v3.0.1): all_assets now
resolves 26,063 (previously 10,000), a person-filter IF matched 813
assets vs 142 under the cap, and a 25,250-asset remove_from_album
branch completed via batched requests.

Fixes #296.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 18:56:25 -06:00
sai80082 af4cfceb47 fix: migrate to Immich v3.0 API and DB schema
- Updated albumColumns and AlbumThumbnail components to display placeholder when no thumbnail is available.
- added album_user table (album ownership moved here, role='owner')
- drop asset.deviceId/deviceAssetId and albums.ownerId
- asset.duration varchar -> integer (milliseconds)
- removed isArchived instead use visibility
2026-07-02 20:13:29 +05:30
Varun d0a7894a25 feat: per-user settings, workflow API key, cron scheduler, and engine logging
- Add ownerId to settings table for per-user key-value storage
- Add settings KV API endpoint scoped by user
- Add workflow API key config in settings page
- Action executor uses per-user workflow API key, falls back to session auth
- Bootstrap cron scheduler on server start via instrumentation hook
- Re-register/unregister cron on workflow enable/disable/delete
- Downgrade node-cron to v3 for Turbopack compatibility
- Add structured console logs to workflow engine for all steps
- Enabled toggle saves immediately to server
- Schedule popover saves immediately to server
- Use react-hot-toast instead of shadcn toast in workflow editor
2026-04-07 20:38:59 +05:30
Varun c7a7ea3023 feat: add smart auto-albums with visual workflow editor
- Visual node-based workflow editor using React Flow
- Asset triggers: new asset, asset updated, all assets (with lookback buffer)
- Logic nodes: if/switch with combinable conditions (person, location, date, camera, EXIF, favorites, album membership)
- Action nodes: create album, add/remove from album, favorite, unfavorite, archive, tag
- Workflow-level triggers: manual run, cron schedule, webhook
- Debug mode: dry run with step-by-step logs and asset previews
- Run history with per-node asset tracking
- Run detail page with annotated read-only graph
- Processed asset tracking to prevent duplicate processing
- Multi-person picker with face thumbnails
- Album picker dropdown for actions
- JSON import/export for workflow sharing
- Workflow list page with create, delete, enable/disable
2026-04-07 19:20:43 +05:30
Varun Raj 263212c8b9 fix: album creation flow
Signed-off-by: Varun Raj <varun@skcript.com>
2025-07-27 18:04:35 +05:30
Varun Raj b9d7e54c8a feat: remember the last location used 2025-07-27 11:44:35 +05:30
Varun Raj 9fcda54e4f feat: added proper validations for errors with messages
Signed-off-by: Varun Raj <varun@skcript.com>
2025-01-19 10:31:44 +05:30
Varun Raj ac0db7a741 feat: added error debug message in root layout
Signed-off-by: Varun Raj <varun@skcript.com>
2024-12-01 19:22:13 +05:30
Varun Raj 23c341cba5 feat: added secure cookie env
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-09-07 19:37:18 +05:30
Varun Raj 62fc820bc7 fix: removed unused packages
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-09-04 20:11:30 +05:30
Varun Raj 5e71e1eeeb feat: setup auth flow to work in parallel with api key
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-09-03 08:11:25 +05:30
Varun Raj 86ae90b16a feat: added proper error messages on load
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-08-29 09:08:32 +05:30
Varun Raj 28d3deabcd feat: added current user validation to apis
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-08-22 10:08:42 +05:30
Varun Raj a8bce40b3a feat: option to edit image
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-08-17 23:03:39 +05:30
Varun Raj f4c84e0e89 feat: initial setup 🚀
Signed-off-by: Varun Raj <mailme@varunraj.in>
2024-08-17 17:15:34 +05:30