Skip to content

Releases: arvindrk/twitter-agent

v1.1.1

07 May 18:48

Choose a tag to compare

v1.1.1 — 2026-05-07

Bug Fixes

Outbound engagement: home feed replaces static search queries

Previously the outbound engagement pipeline seeded candidates from a fixed list of
STATIC_QUERIES via searchTweets. This produced shallow, repetitive candidate sets
with no personalisation. The pipeline now calls getHomeFeed(100) — the authenticated
user's reverse-chronological home timeline — which surfaces tweets from accounts the
user already follows and is more representative of the account's actual network.

Database: enum-to-text cast for Neon HTTP driver

getAlreadyActedPairs, getCooledDownAuthorIds, and getFollowedAuthorIds all compare
against the outbound_action PostgreSQL enum column. The Neon HTTP driver fails to infer
the correct type for parameterized enum values, causing every batch DB query to throw
"Failed query" and crash the run. Fixed by adding an explicit ::text cast on the
action column in all three queries.

Outbound agent: camelCase field mapping for XDK responses

SearchRecentData was reading author_id and public_metrics directly from API
responses, but the XDK client transforms all field names to camelCase before returning.
Updated field names to authorId and publicMetrics to match the actual response shape.

Breaking Changes / Removals

Reply action permanently disabled for outbound engagement

The X API v2 returns HTTP 403 Forbidden with the message
"Reply to this conversation is not allowed because you have not been mentioned or
otherwise engaged by the author"
for any automated reply to a user who has not
previously interacted with the account. Outbound replies cannot succeed under this
constraint.

Removed entirely:

  • reply field from the outbound engagement agent Zod schema and system prompt
  • 280-character retry block in the agent (was only needed for reply content)
  • isReplySafe post-processing step in the outbound agent
  • replyToTweet call and reply execution block in the outbound service
  • "reply" from getAlreadyActedPairs query and the fully-acted candidate filter
  • replies cap from CAPS
  • replied counter from the service return type and log line
  • replySettings from SearchedTweet interface and getHomeFeed field requests

The reply action remains fully available for inbound engagement (webhook-driven
replies to mentions, which are explicitly allowed by the API).

Reliability

xAI "Service Unavailable" no longer crashes outbound runs

Transient xAI API outages ("Failed after 3 attempts. Last error: Service Unavailable")
previously propagated as unhandled exceptions, marking the entire cron run as failed
and preventing any subsequent attempt until the next schedule tick. The agent call is
now wrapped in a try-catch: on any error the run logs a warning and returns
{ liked: 0, retweeted: 0, followed: 0, skipped: 0 } instead of throwing. The next
scheduled run will retry automatically.

Tests

  • Removed stale agent tests: "blocks reply containing AI-disclosure text" and
    "retries and accepts short reply when initial reply exceeds 280 chars" — both tests
    exercised logic that no longer exists.
  • Updated CandidateTweet and OutboundDecision local types in agent and service
    test files to match the stripped schema.
  • Removed replyToTweet from the x module mock and RunResult type in service tests.
  • Caps test updated: likes ≤ 10, retweets ≤ 3, follows ≤ 3 (reply cap removed).
  • Cooldown test description updated to reflect that only follow is suppressed for
    cooled-down authors (reply is gone).

v1.1.0

02 May 08:22

Choose a tag to compare

v1.1.0

New Features

Engagement System

  • Added runEngagement agent (src/agents/engagement.ts) — replies to incoming mentions using thread context and a configurable close/probe stance via grok-4-1-fast-non-reasoning
  • Added engagement_log table with claim / markEngagementDone / markEngagementFailed helpers for idempotent, at-most-once reply processing
  • Added X webhook routes (GET /webhook/x CRC challenge, POST /webhook/x event dispatch) with full test coverage
  • Added scripts/subscribe-webhook.ts — one-shot script to register the webhook URL and subscribe the authed user via X AAA

X Client Extensions

  • replyToTweet(text, replyToId) — posts a reply scoped to a conversation thread
  • fetchThreadContext(tweetId) — fetches parent tweet chain up to 5 levels deep for conversation context

Bug Fixes

  • markEngagementFailed now swallows secondary DB errors to prevent double-throw on error paths
  • Removed max(280) from Zod schema; tweet truncation now happens in code, preventing validation rejections on edge-case posts
  • Strengthened CRC challenge test to assert correct HMAC response shape

Test Coverage

  • Added researcher.test.ts — covers return value, message forwarding, empty text, and error propagation
  • Added engagement.test.ts — covers reply generation, thread formatting, and stance behavior
  • Extended writer.test.ts and scheduler.test.ts with empty-array and error-propagation edge cases
  • app.test.ts — added mock call verification for claimPost, markPublished, markFailed, publishTweet; refactored to makeDbPost factory with beforeEach reset to eliminate state leaks
  • x.test.ts — added fetchThreadContext coverage and fixed env teardown
  • Test runner now reports per-file line/function coverage via --coverage

Chore

  • Documented X_USER_ID and X_BEARER_TOKEN in .env.example (required for webhook subscription)

v1.0.1

30 Apr 03:30

Choose a tag to compare

v1.0.1

Bug Fixes

  • resetStalePosts() now called at the start of every scan cycle — posts stuck in processing were never recovered
  • getPostsDue limit raised from 5 to 10 posts per scan
  • DATABASE_URL guarded with explicit env() check
  • Catch blocks narrowed to err: unknown with instanceof Error guards throughout
  • Unused text field dropped from publishTweet return value
  • Scheduler system prompt: corrected account description
  • Researcher: improved logging clarity for query availability

Testing & CI/CD

  • 33 tests across 5 files — zero AI tokens used
  • Covers: route auth, pipeline merge logic, tweet validation, agent output shape, HTTP edge cases
  • CI workflow runs typecheck + tests on every push and PR; deploy gates on CI green
  • Fixed CI test isolation: Bun 1.3.x shares mock.module state across files; runner now spawns each file in its own process
  • CI badge added to README

Refactoring

  • Extracted rejectThreadPost() in app.ts to remove duplication
  • sanitizeContent exported from writer for testability
  • lap() timing helper extracted, .js import extensions normalized
  • Scripts moved to scripts/ directory

Community

  • Added CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md

v1.0.0

28 Apr 17:03

Choose a tag to compare

Changelog

v1.0.0 — Initial Release

Core Pipeline

  • Three-stage autonomous pipeline: Researcher → Writer → Scheduler
  • Researcher uses grok-4-latest via Responses API with webSearch + xSearch tools (multi-step, up to 10 steps)
  • Writer uses grok-4-latest via Chat Completions to produce 4–6 structured posts
  • Scheduler uses grok-4-1-fast to assign ISO 8601 posting times

X (Twitter) Integration

  • OAuth1 client via @xdevplatform/xdk
  • Tweet poster with validation and error handling
  • POST /test/post endpoint for direct publishing

HTTP Server

  • Hono server on port 3010
  • GET /cron/daily — triggers full pipeline async (202 response)
  • POST /cron/execute-post — publishes a scheduled post by ID; supports scan mode for cron-job.org polling

Database

  • Neon/Postgres with Drizzle ORM
  • Schema for scheduled posts
  • getPostsDue query with ORDER BY scheduled_at, limited to 5 rows per tick

Infrastructure

  • Dockerized with Dockerfile + docker-compose
  • GitHub Actions workflow for automated deploy to AWS EC2 via ECR
  • Nginx reverse proxy config
  • External cron triggers via cron-job.org (daily pipeline + publish-due scan)

DX

  • dotenvx for env injection; .env.example provided
  • Timestamped console logging across pipeline and agents
  • npx tsc --noEmit compile check
  • Test scripts for each agent and cron endpoint