Skip to content

feat(rules): add "Title Contains" condition to Rule Engine (#1670)#2354

Merged
MohamedBassem merged 3 commits intokarakeep-app:mainfrom
mokhovyk:rule-engine-title-contain
Jan 18, 2026
Merged

feat(rules): add "Title Contains" condition to Rule Engine (#1670)#2354
MohamedBassem merged 3 commits intokarakeep-app:mainfrom
mokhovyk:rule-engine-title-contain

Conversation

@mokhovyk
Copy link
Contributor

@mokhovyk mokhovyk commented Jan 6, 2026

Adds two new conditions to the Rule Engine:

  • "Title Contains"
  • "Title Does Not Contain"

This allows users to create automation rules based on bookmark titles. Solved #1670

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

Walkthrough

Adds two title-based condition types (titleContains, titleDoesNotContain) across types, UI, backend evaluation, translations, and tests; passes an eventType prop through ConditionBuilder to conditionally expose title-related options.

Changes

Cohort / File(s) Summary
UI Components
apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx, apps/web/components/dashboard/rules/RuleEngineRuleEditor.tsx
ConditionBuilder gains an eventType prop (propagated to nested builders); condition selector hides title options for bookmarkAdded; added handlers, Heading icon import, and input fields for titleContains / titleDoesNotContain.
Translations
apps/web/lib/i18n/locales/en/translation.json
Added common.rules.conditions_types.title_contains and common.rules.conditions_types.title_does_not_contain.
Type Definitions
packages/shared/types/rules.ts
Added zTitleContainsCondition and zTitleDoesNotContainCondition; included them in nonRecursiveCondition and zRuleEngineConditionSchema, updating the exported RuleEngineCondition union.
Business Logic
packages/trpc/lib/ruleEngine.ts
Fetch now includes bookmark title; added bookmarkTitle accessor and titleContains / titleDoesNotContain cases in doesBookmarkMatchConditions.
Tests
packages/trpc/lib/__tests__/ruleEngine.test.ts
Seeded bookmark with title and added tests for matching/non-matching titleContains and titleDoesNotContain behaviors.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature being added: two new conditions for the Rule Engine that enable title-based automation rules.
Description check ✅ Passed The description clearly relates to the changeset by explaining the two new conditions being added and their purpose for creating automation rules based on bookmark titles.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link

greptile-apps bot commented Jan 6, 2026

Greptile Summary

Adds two new condition types to the Rule Engine: "Title Contains" and "Title Does Not Contain", enabling users to create automation rules based on bookmark titles.

Key Changes

  • Type System: Added zTitleContainsCondition and zTitleDoesNotContainCondition schemas with validation requiring non-empty strings
  • Rule Engine Logic: Implemented condition handlers using .includes() for case-sensitive string matching with null-safe fallback to empty string
  • UI Components: Added Heading icon and input fields for the new conditions in the condition builder
  • Test Coverage: Comprehensive tests verify both conditions work correctly with matching and non-matching cases
  • Internationalization: Added English translations for the new condition labels

The implementation follows existing patterns from urlContains/urlDoesNotContain conditions and properly handles edge cases where titles may be null.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is clean, well-tested, and follows existing patterns exactly. All changes are additive with no modifications to existing functionality, proper type safety throughout, comprehensive test coverage, and correct null handling
  • No files require special attention

Important Files Changed

Filename Overview
packages/trpc/lib/ruleEngine.ts Added titleContains and titleDoesNotContain condition handlers with proper null handling
packages/shared/types/rules.ts Added type definitions and validation for title-based conditions
apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx Added UI components for title conditions with Heading icon and input fields
packages/trpc/lib/tests/ruleEngine.test.ts Added comprehensive test coverage for both titleContains and titleDoesNotContain conditions
apps/web/lib/i18n/locales/en/translation.json Added English translations for title_contains and title_does_not_contain labels

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as RuleEngineConditionBuilder
    participant Types as rules.ts (Zod)
    participant Engine as RuleEngine
    participant DB as Database

    User->>UI: Select "Title Contains" condition
    UI->>UI: handleTypeChange("titleContains")
    UI->>UI: onChange({type: "titleContains", str: ""})
    
    User->>UI: Enter search string
    UI->>UI: Update condition.str value
    
    User->>UI: Save rule
    UI->>Types: Validate rule schema
    Types->>Types: Check str.length > 0
    Types-->>UI: Validation success
    
    UI->>DB: Save rule with condition
    
    Note over Engine: When bookmark event occurs
    
    Engine->>DB: Fetch bookmark with title
    DB-->>Engine: Bookmark data
    
    Engine->>Engine: doesBookmarkMatchConditions(condition)
    Engine->>Engine: Check (bookmark.title ?? "").includes(condition.str)
    Engine-->>Engine: Return true/false
    
    alt Condition matches
        Engine->>Engine: Execute rule actions
        Engine->>DB: Apply actions (add tag, etc)
    end
Loading

@greptile-apps
Copy link

greptile-apps bot commented Jan 6, 2026

Greptile found no issues!

From now on, if a review finishes and we haven't found any issues, we will not post anything, but you can confirm that we reviewed your changes in the status check section.

This feature can be toggled off in your Code Review Settings by deselecting "Create a status check for each PR".

@MohamedBassem
Copy link
Collaborator

Hey, thanks for opening the PR! Although the logic itself is correct, title contains is tricky though, because the rule engine is evaluated when the bookmark is "created" but it usually gets a title when its "crawled". So this rule will only work for bookmarks created with the API and explicitly setting a title. Or with other triggers like "tagging", or lists, etc. So we might need to hide this "action" in the "bookmark created" condition otherwise it'll be confusing to people.

);
}
case "titleContains": {
return (this.bookmark.title ?? "").includes(condition.str);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crawled bookmarks has their links in this.bookmark.content.title (if they're links) with no user overrides. So this might need to be something like:

this.bookmark.title ?? (this bookmark.type == BookmarkTypes.LINK ? this.bookmark.content.title : "")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed

@mokhovyk
Copy link
Contributor Author

Hey, thanks for opening the PR! Although the logic itself is correct, title contains is tricky though, because the rule engine is evaluated when the bookmark is "created" but it usually gets a title when its "crawled". So this rule will only work for bookmarks created with the API and explicitly setting a title. Or with other triggers like "tagging", or lists, etc. So we might need to hide this "action" in the "bookmark created" condition otherwise it'll be confusing to people.

Thanks for the clarification. I’ve updated the PR to hide this action under the “bookmark created” condition to avoid confusion

@MohamedBassem MohamedBassem merged commit c56cf4e into karakeep-app:main Jan 18, 2026
6 checks passed
@MohamedBassem
Copy link
Collaborator

Thank you!

MohamedBassem pushed a commit that referenced this pull request Feb 8, 2026
…2354)

* feat(rules): add "Title Contains" condition to Rule Engine (#1670)

* feat(rules): hide title conditions for bookmark created trigger

* fix typecheck
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