Feat/twitter post reader#122
Merged
Merged
Conversation
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Implement extractTweetId function to parse and extract tweet IDs from various Twitter/X URL formats including: - x.com and twitter.com domains - Mobile variants (mobile.x.com, mobile.twitter.com) - URLs with query parameters, www prefix, and trailing slashes Validates URL structure and throws error for invalid formats. Comprehensive test coverage with 25 test cases. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Implement formatTweet function to convert Tweet objects into readable text format including: - Author name and username - Tweet text content - Engagement metrics (likes, retweets, replies, views) - Media attachments (photos and videos) - Mentions, hashtags, and URLs - Relative timestamp conversion (e.g., '2 hours ago') Handles null/undefined optional fields gracefully. Refactored with helper functions for improved maintainability. 15 comprehensive test cases covering all scenarios. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Move extractTweetId to src/utils/extractTweetId.ts - Move formatTweet to src/utils/formatTweet.ts with helper functions - Update src/actions/readTweet.ts to re-export utilities - Split tests by responsibility: - src/test/extractTweetId.test.ts (23 tests) - src/test/formatTweet.test.ts (15 tests) - Follow plugin-depin structure pattern - All 38 tests still passing Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Implement AC4-6: Comprehensive error handling for Twitter tweet reading with user-friendly error messages and robust error recovery. Changes: - Added error handling for invalid URL formats (AC4) - Added error handling for deleted/protected/non-existent tweets (AC5) - Added error handling for rate limit errors (AC6) - Created 15 comprehensive tests for all error scenarios - Added type guards for API error type safety - Added null safety checks in formatTweet utility - Added tweet structure validation before formatting - Wrapped formatTweet call in defensive try-catch - Extracted URL regex pattern as constant All 53 tests passing (23 URL parsing + 15 formatting + 15 error handling) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Add READ_TWEET to similes array (plugin-depin pattern compliance) - Import and export readTweetAction from plugin index.ts - Add readTweetAction to plugin actions array - Extract plugin name and description to constants - Add 29 integration tests for AC7-8 (action properties, plugin integration, coverage validation) - All 82 tests passing (23 URL parsing + 15 formatting + 15 error handling + 29 integration) - Refactored for code quality with named constants Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Reduce global AGENTS.md from 174 to 85 lines - Reduce plugin-twitter AGENTS.md from 730 to 75 lines - Remove internal duplications between docs - Remove redundant explanations and examples - Keep only critical gotchas and actionable commands - Follow Factory AGENTS.md best practices (≤150 lines)
Codecov Report❌ Patch coverage is
❌ Your project status has failed because the head coverage (52.00%) is below the target coverage (70.00%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #122 +/- ##
==========================================
+ Coverage 50.87% 52.00% +1.13%
==========================================
Files 180 188 +8
Lines 24441 25036 +595
Branches 2251 2379 +128
==========================================
+ Hits 12435 13021 +586
- Misses 11962 11971 +9
Partials 44 44 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Fixed TypeScript module resolution error by creating local type definitions instead of importing from @elizaos/client-twitter/src/types which is not exposed through package exports. This avoids adding an unnecessary dependency on the client package while maintaining type safety. Changes: - Created src/types.ts with local Tweet, Photo, Video, and Mention types - Updated imports in formatTweet.ts and formatTweet.test.ts to use local types
Added TwitterReadClient that works independently of loaded Twitter client: - Minimal TwitterApiV2 wrapper (125 lines) - Returns raw API responses for LLM processing - Works with just TWITTER_BEARER_TOKEN env var - No transformation logic - LLM handles data interpretation Tests: - 28 comprehensive tests (100% coverage for client.ts) - Tests constructor, getTweet(), error handling - Mocks twitter-api-v2 appropriately - All 112 package tests pass Dependencies: - Added twitter-api-v2@^1.27.0 to package.json
Added tweetResponseTemplate for persona-aware, contextual responses: - Provides structured template with recent messages, tweet data, and user request - Instructions guide LLM to analyze tweets in character's voice - Exported from index.ts for character configurations - Follows pattern used in plugin-depin (ASK_SENTAI) Template enables: - Content summarization - Metrics analysis (likes, retweets, views) - Media attachments description - Hashtags/mentions/URLs highlighting - Author discussion - Flexible responses based on user's question
Major refactoring following established plugin patterns: - Removed formatTweet dependency (162 lines deleted) - Handler now passes raw tweet data to LLM via template - Added state management with updateRecentMessageState - Integrated with generateMessageResponse for LLM processing - Works independently of loaded Twitter client Test improvements: - Added 17 new tests (61 total, up from 44) - Coverage: 100% (was 70.43%) - New tests cover: state management, generic errors, lightweight client creation - All 112 package tests pass Handler flow: 1. Validate URL and extract tweet ID 2. Get/create Twitter client (runtime or lightweight) 3. Fetch raw tweet data 4. Pass to LLM via template context 5. Generate persona-aware response Benefits: - Works without Twitter client loaded - LLM generates natural, contextual responses - Follows ASK_SENTAI pattern (plugin-depin) - Simpler, more maintainable code
Removed heavy formatting logic now that LLM handles responses: - Deleted src/utils/formatTweet.ts (162 lines) - Deleted src/test/formatTweet.test.ts (15 tests, 384 lines) - No longer needed with LLM-driven approach Total reduction: 546 lines of code
Documentation improvements: - Archived TDD context to archive/tdd-context-readTweet-coverage-2026-02-03.md - Updated AGENTS.md with: - Current coverage metrics (100% statements, 97.36% branches) - LLM-driven architecture pattern - Lightweight Twitter client documentation - Updated file structure - New code patterns (state management, LLM mocking) - Migration history with commit references - Expanded common pitfalls section
Remove invalid 'state' parameter and add required 'modelClass' and 'tags' parameters to generateMessageResponse call. Add ModelClass import. - Remove: state parameter (not in function signature) - Add: modelClass: ModelClass.LARGE (required) - Add: tags: ["read-tweet"] (required) - Add: message: message (optional, for context) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Move bearer token validation from handler to validate function to fail fast when TWITTER_BEARER_TOKEN is not configured. The validate function now checks for the presence of a non-empty bearer token before attempting to execute the action. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add extractImageUrls function to extract image URLs from tweet data's photos array and add them to state for use in LLM context generation. Changes: - Add extractImageUrls helper function to handle photo extraction - Call extractImageUrls in readTweetHandler after fetching tweet data - Add imageUrls to state before LLM context composition - Update tweetResponseTemplate to display image URLs when present - Add tests for extracting images from tweets with photos, empty photos, and undefined photos Acceptance Criteria Implemented: - AC1: When a tweet contains 1-4 images, extract all image URLs from the tweet data Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add IImageDescriptionService import and use generic type parameter with getService to fix TypeScript error. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Fixed template rendering of image descriptions which was displaying
"[object Object]" instead of properly formatted image metadata.
**Changes**:
- Updated template to use Handlebars iteration syntax for imageDescriptions array
- Added templatingEngine: "handlebars" parameter to composeContext call
- Each image now displays title and description on separate lines
- Added fallback message when no images present
**Before**: Images in Tweet: [object Object]
**After**:
Images in Tweet:
- Image: [title]
Description: [description]
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Implement cache-aside pattern for tweet caching in READ_TWEET action:
- Cache hit returns cached tweet without API call
- Cache miss triggers API fetch and caches result
- Graceful degradation on cache errors
- Cache key format: twitter/tweets/{tweetId}
All 149 tests passing with comprehensive TDD coverage.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Split the monolithic readTweet.ts file into focused modules: - types.ts: All TypeScript type definitions - utils.ts: Utility functions for tweet processing - clientUtils.ts: Twitter client management - readTweet.ts: Core handler logic (45% reduction in size) Benefits: - Better code organization by concern - Improved maintainability and readability - Enhanced reusability of utility functions - All 145 tests passing - 96.57% statement coverage maintained Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Consolidated redundant test cases to reduce duplication: - AC6: Rate limit tests (3 → 1) - AC10: Error handling tests (7 → 3) - AC4: Cache manager tests (7 → 3) - AC1: Cache hit tests (5 → 2) Results: - 94 tests (down from 104) - 2835 lines (down from 2987) - 96.57% statement coverage maintained - 93.18% branch coverage maintained - All critical functionality preserved Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…ity-first design Remove all hardcoded error messages from readTweet action and use LLM-generated, persona-aware responses for all scenarios while maintaining security by NOT exposing internal API details to the LLM. **Security-First Approach:** - Only safe error types exposed to LLM (invalid_url, tweet_not_found, etc.) - Raw API codes (404, 403, 429) never reach LLM - Raw API error messages never reach LLM - Rate limit timing details never reach LLM - Internal implementation details abstracted away **Implementation:** - Added SAFE_ERROR_TYPES constant with 8 safe error types - Created mapApiErrorToSafeType() for internal error mapping - Created processTweetError() for LLM-driven error responses - Created tweetErrorResponseTemplate with Handlebars conditionals - Refactored all 9 error paths to use safe mapping + LLM - Removed hardcoded error message constants **Error Type Mapping:** - 404 → tweet_not_found - 403 (protected/suspended) → tweet_protected - 403 (other) → tweet_forbidden - 429 → rate_limited (no timing details) - Invalid URL → invalid_url - Client null → client_error - Data null → data_unavailable - Catch-all → api_error **Testing:** - Added 21 new tests for safe error type mapping - Updated 21+ tests to verify LLM invocation vs exact strings - All 166 tests passing - Lint passing (0 errors) - Build successful **Benefits:** - Consistent character voice across all responses - Contextual, persona-aware error messages - Automatic internationalization via LLM - No hardcoded strings to maintain - Extensible error handling with safe abstractions Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Root AGENTS.md: Updated to reflect actual package layout (21+ packages) - plugin-twitter AGENTS.md: Updated to reflect modular action structure - Removed outdated migration history and stale coverage stats - Streamlined both documents to follow init skill template - Focused on actionable patterns over historical context Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Risks
Background