Skip to content

Add FilterJoin and four AI filter plugins (Claude, Gemini, OpenAI, SakuraAI) - #154

Merged
id774 merged 1 commit into
masterfrom
claude/automaticruby-ai-digest-plugins-krxd0d
Aug 17, 2026
Merged

Add FilterJoin and four AI filter plugins (Claude, Gemini, OpenAI, SakuraAI)#154
id774 merged 1 commit into
masterfrom
claude/automaticruby-ai-digest-plugins-krxd0d

Conversation

@id774

@id774 id774 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

This PR adds five new filter plugins to the Automatic Ruby framework:

Summary

Introduces a content joining filter and four AI service integrations that transform item descriptions using external AI APIs. These plugins enable recipes to summarize, translate, extract, or reformat feed content through various AI providers.

Key Changes

FilterJoin (plugins/filter/join.rb)

  • Combines all items in a pipeline into a single item with a formatted description
  • Preserves item structure with numbered sections for each article
  • Returns empty pipeline if no items exist (prevents empty items from being published)
  • Configurable title with default "Joined items"

Four AI Filter Plugins (Claude, Gemini, OpenAI, SakuraAI)

  • Each plugin sends item descriptions to its respective AI service under a Recipe-provided prompt
  • Replaces descriptions with AI responses while preserving all other item properties
  • Shared behavior across all four:
    • Required settings: token, model, prompt
    • Optional retry configuration (retry, interval)
    • Skips items with empty descriptions (logs warning, continues)
    • Validates settings before first request
    • Retries only on transient failures (network, 429, 5xx)
    • Fails immediately on permanent errors (invalid settings, refused requests, malformed responses)
    • TLS certificate verification enabled
    • Credentials never logged or exposed in exceptions

Service-Specific Implementations

  • FilterClaude: Uses Anthropic Messages API with x-api-key header, requires API version header, supports configurable max_tokens (default 4096)
  • FilterGemini: Uses Google's generateContent API with x-goog-api-key header, model name in URL path
  • FilterOpenAI: Uses OpenAI Responses API with bearer token authentication
  • FilterSakuraAI: Uses Sakura AI Engine's OpenAI-compatible chat completions endpoint with bearer token

Notable Implementation Details

  • Each AI plugin is independent rather than a single plugin with a provider setting, allowing services to evolve separately without affecting others
  • Plugins are not summarizers—the prompt setting determines the transformation (summarization, translation, extraction, etc.)
  • One request per item enables flexible pipeline ordering: FilterJoin→AI filter produces one summary of everything; AI filter→FilterJoin produces individual summaries joined together
  • Comprehensive test suites verify request format, authentication, response parsing, and error handling without reaching actual services
  • Documentation updated in doc/PLUGINS.md with detailed configuration tables and usage examples

https://claude.ai/code/session_01BxW4ugoPVEk6gn8g2hogpU

FilterJoin joins every item in the pipeline into one item carrying each
item's title, link and body under a numbered heading. It builds that item
with RSS::Maker rather than FeedMaker.create_pipeline, which drops an item
whose link is nil, because the joined item has no permalink of its own and
inventing one would name a source for text that is not only from it. An
input with no items produces an empty pipeline rather than an empty item.

FilterOpenAI, FilterClaude, FilterGemini and FilterSakuraAI each replace an
item's description with what one service's API answers to the Recipe's
prompt. They are four plugins rather than one with a provider setting: the
endpoints, authentication, request bodies, answers, errors and models
differ, each moves without asking the others, and a Recipe names the
service it sends text to. None of them is a summarizer -- the prompt is the
instruction and the description is the text it applies to, and a Recipe
without a prompt is refused rather than given a default one.

Each asks once per item, replaces only the description, and retries the
network, a 429 and a 5xx while raising at once on a refused request, an
answer that is not JSON, an answer whose shape is not the documented one,
or a missing setting. A failure never leaves an empty description behind.
Credentials are Recipe settings: never logged, never in an exception
message, never written into an item, and TLS is verified.

Specs cover both sides with no network and no credential, and the
catalogue, the counts, the optional-dependency table and VERSIONS are
updated in the same change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BxW4ugoPVEk6gn8g2hogpU
@id774
id774 merged commit 62e1202 into master Aug 17, 2026
8 checks passed
@id774
id774 deleted the claude/automaticruby-ai-digest-plugins-krxd0d branch August 17, 2026 12:28
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