Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
705e681
feat(ai-agents): initialize project structure with TypeScript and Bun
madidnyc Jan 19, 2026
f55835f
feat(ai-agents): define core TypeScript interfaces
madidnyc Jan 19, 2026
3313617
chore(ai-agents): update progress for task 1.2
madidnyc Jan 19, 2026
c7f4381
feat(ai-agents): implement config loading with validation
madidnyc Jan 19, 2026
94b6f2e
chore(ai-agents): update progress for Task 1.4 verification
madidnyc Jan 19, 2026
5693ce4
feat(ai-agents): add structured JSON logger
madidnyc Jan 19, 2026
9481ac2
feat(ai-agents): implement SQLite schema and basic queries
madidnyc Jan 19, 2026
6b10ae6
chore(ai-agents): update progress for Task 1.7 verification
madidnyc Jan 19, 2026
bccf64c
feat(ai-agents): implement Twitter search poller with Bird
madidnyc Jan 19, 2026
1031ee7
feat(ai-agents): implement filter pipeline for content and deduplication
madidnyc Jan 19, 2026
5ec8f79
chore(ai-agents): update progress for Task 1.10 verification
madidnyc Jan 19, 2026
fa36044
feat(ai-agents): implement Manus API client with polling
madidnyc Jan 19, 2026
eeee545
feat(ai-agents): implement PDF to PNG conversion with compression
madidnyc Jan 19, 2026
f87250b
chore(ai-agents): update progress for Task 1.13 verification
madidnyc Jan 19, 2026
72f944c
feat(ai-agents): implement PDF generation orchestrator
madidnyc Jan 19, 2026
2929bba
feat(ai-agents): implement randomized reply templates
madidnyc Jan 19, 2026
8b79249
chore(ai-agents): update progress for Task 1.16 verification
madidnyc Jan 19, 2026
77c9bb6
feat(ai-agents): implement Twitter responder with media upload
madidnyc Jan 19, 2026
76b1a40
feat(ai-agents): implement main poll loop skeleton
madidnyc Jan 19, 2026
a9cd6fb
chore(ai-agents): update progress for task 1.18
madidnyc Jan 19, 2026
3ee3635
chore(ai-agents): pass quality checkpoint
madidnyc Jan 19, 2026
23dbe5f
chore(ai-agents): update progress for Task 1.19 verification
madidnyc Jan 19, 2026
999eb65
feat(ai-agents): complete full pipeline integration
madidnyc Jan 19, 2026
b5d2493
chore(ai-agents): mark task 1.20 complete
madidnyc Jan 19, 2026
ac2f386
feat(ai-agents): add author cache seeding with known influencers
madidnyc Jan 19, 2026
1888cf1
chore(ai-agents): pass quality checkpoint
madidnyc Jan 19, 2026
a7f81d2
chore(ai-agents): update progress for Task 1.22 verification
madidnyc Jan 19, 2026
8aeedb6
feat(ai-agents): add E2E validation script for POC pipeline
madidnyc Jan 19, 2026
1cbbb88
chore(ai-agents): update progress for Task 1.24 POC verification
madidnyc Jan 19, 2026
6536d5e
refactor(ai-agents): add follower count filtering with cache
madidnyc Jan 19, 2026
a34f1a3
chore(spec): mark task 2.1 complete - follower count filtering
madidnyc Jan 19, 2026
3dc78e8
refactor(ai-agents): add rate limit enforcement to filter
madidnyc Jan 19, 2026
511fd89
chore(ai-agents): mark task 2.2 complete
madidnyc Jan 19, 2026
77f277c
chore(ai-agents): update progress for Task 2.3 verification
madidnyc Jan 19, 2026
4ff957b
refactor(ai-agents): add retry utility with exponential backoff
madidnyc Jan 19, 2026
64948c2
refactor(ai-agents): implement circuit breaker for Manus API
madidnyc Jan 19, 2026
230326c
chore(ai-agents): pass quality checkpoint for Task 2.6
madidnyc Jan 19, 2026
e4780c6
refactor(ai-agents): integrate retry and circuit breaker
madidnyc Jan 19, 2026
c864916
chore(ai-agents): update progress for task 2.7
madidnyc Jan 19, 2026
70d57d6
refactor(ai-agents): add comprehensive error handling
madidnyc Jan 19, 2026
b771df4
chore(ai-agents): pass quality checkpoint for Task 2.9
madidnyc Jan 19, 2026
08de739
refactor(ai-agents): implement graceful shutdown
madidnyc Jan 19, 2026
3087eb4
refactor(ai-agents): add automatic daily rate limit reset
madidnyc Jan 19, 2026
6d932df
chore(ai-agents): pass quality checkpoint for Task 2.12
madidnyc Jan 19, 2026
d9157fb
test(ai-agents): add config validation unit tests
madidnyc Jan 19, 2026
c641676
test(ai-agents): add filter pipeline unit tests
madidnyc Jan 19, 2026
9df9112
docs(ai-agents): update progress for Task 3.2
madidnyc Jan 19, 2026
cb1e46e
chore(ai-agents): pass quality checkpoint
madidnyc Jan 19, 2026
6f795a7
chore(ai-agents): pass quality checkpoint for Task 3.3
madidnyc Jan 19, 2026
b5ccc79
test(ai-agents): add reply template unit tests
madidnyc Jan 19, 2026
8d04fc0
docs(ai-agents): update progress for Task 3.4
madidnyc Jan 19, 2026
d88cc4c
test(ai-agents): add database operations unit tests
madidnyc Jan 19, 2026
a2dd773
chore(ai-agents): fix test configuration for vitest + bun
madidnyc Jan 19, 2026
69d3617
chore(ai-agents): pass quality checkpoint for Task 3.6
madidnyc Jan 19, 2026
5df4838
test(ai-agents): add filter+DB integration tests
madidnyc Jan 19, 2026
b0063a1
test(ai-agents): add Manus API integration tests
madidnyc Jan 19, 2026
1b8b757
chore(ai-agents): pass quality checkpoint for Task 3.9
madidnyc Jan 19, 2026
8c44091
test(ai-agents): add E2E pipeline test with mocks
madidnyc Jan 19, 2026
5971c6b
test(ai-agents): add real Twitter search E2E test
madidnyc Jan 19, 2026
cf37ea2
chore(ai-agents): pass quality checkpoint for Task 3.12
madidnyc Jan 19, 2026
c882d2d
chore(ai-agents): configure Biome and Oxlint
madidnyc Jan 19, 2026
8fed85d
chore(ai-agents): enable strict type checking
madidnyc Jan 19, 2026
a8a74d3
chore(ai-agents): pass full local CI for Task 4.3
madidnyc Jan 19, 2026
96ecb2a
docs(ai-agents): add comprehensive README
madidnyc Jan 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions ai-agents-responder/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# AI Agents Twitter Auto-Responder Configuration
# Copy this file to .env and fill in your values

# =============================================================================
# TWITTER / BIRD AUTHENTICATION (choose one method)
# =============================================================================

# Option 1: Cookie source (recommended for macOS)
# Uses browser cookies automatically - values: "safari" or "chrome"
BIRD_COOKIE_SOURCE=safari

# Option 2: Manual tokens (alternative to cookie source)
# Get these from browser dev tools when logged into Twitter
# AUTH_TOKEN=your_auth_token_here
# CT0=your_ct0_csrf_token_here

# =============================================================================
# MANUS API - PDF Generation
# =============================================================================

# Required: Your Manus API key
MANUS_API_KEY=your_manus_api_key_here

# Optional: Manus API timeout in milliseconds (default: 120000 = 2 minutes)
# Range: 60000 - 300000 (1 - 5 minutes)
MANUS_TIMEOUT_MS=120000

# =============================================================================
# DATABASE
# =============================================================================

# SQLite database path (default: ./data/responder.db)
DATABASE_PATH=./data/responder.db

# =============================================================================
# RATE LIMITS - Conservative defaults to avoid spam detection
# =============================================================================

# Maximum replies per day (default: 15)
MAX_DAILY_REPLIES=15

# Minimum gap between replies in minutes (default: 10)
MIN_GAP_MINUTES=10

# Maximum replies to same author per day (default: 1)
MAX_PER_AUTHOR_PER_DAY=1

# =============================================================================
# FILTERS
# =============================================================================

# Minimum follower count for target authors (default: 50000)
MIN_FOLLOWER_COUNT=50000

# Maximum tweet age in minutes to consider (default: 30)
MAX_TWEET_AGE_MINUTES=30

# Minimum tweet content length in characters (default: 100)
MIN_TWEET_LENGTH=100

# =============================================================================
# POLLING
# =============================================================================

# Poll interval in milliseconds (default: 60000 = 1 minute)
POLL_INTERVAL_MS=60000

# Number of tweets to fetch per search (default: 50)
SEARCH_COUNT=50

# =============================================================================
# FEATURES
# =============================================================================

# Dry-run mode: log actions without actually posting (default: false)
# Set to "true" for testing
DRY_RUN=false

# =============================================================================
# LOGGING
# =============================================================================

# Log level: info, warn, error (default: info)
LOG_LEVEL=info
35 changes: 35 additions & 0 deletions ai-agents-responder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Environment variables - never commit credentials
.env
.env.local
.env.*.local

# Database files - contain runtime state
data/*.db
data/*.db-wal
data/*.db-shm
*.db

# Dependencies
node_modules/

# Build output
dist/

# Test artifacts
coverage/
.vitest/

# Editor files
.idea/
.vscode/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db

# Debug logs
*.log
npm-debug.log*
250 changes: 250 additions & 0 deletions ai-agents-responder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
# AI Agents Twitter Auto-Responder

A fully automated system that monitors X/Twitter for AI-related posts from influential accounts (50K+ followers) and replies with high-value, professionally formatted PDF summaries to drive visibility for Zaigo Labs' AI services business.

## Overview

This standalone application implements a 5-stage pipeline:

1. **Poll**: Search Twitter for AI agents content using Bird
2. **Filter**: Validate candidates (followers, recency, deduplication, rate limits)
3. **Generate**: Create PDF summary via Manus API
4. **Convert**: Transform PDF to PNG (Twitter doesn't render PDFs inline)
5. **Reply**: Post reply with PNG attachment

**Critical constraint**: Complete pipeline in < 5 minutes to achieve top reply visibility.

## Prerequisites

- **Bun** >= 1.0 (runtime and package manager)
- **Twitter/X credentials** (one of the following):
- Browser cookie source (macOS Safari or Chrome)
- Manual AUTH_TOKEN + CT0 tokens
- **Manus API key** for PDF generation

## Setup

### 1. Clone and install dependencies

```bash
cd ai-agents-responder
bun install
```

### 2. Configure environment

```bash
cp .env.example .env
```

Edit `.env` with your credentials:

```bash
# Twitter Authentication (choose one method)
# Option 1: Browser cookies (recommended for macOS)
BIRD_COOKIE_SOURCE=safari

# Option 2: Manual tokens (get from browser dev tools)
# AUTH_TOKEN=your_auth_token_here
# CT0=your_ct0_csrf_token_here

# Manus API (required)
MANUS_API_KEY=your_manus_api_key_here
```

### 3. Seed the database

Pre-populate the author cache with known AI influencers:

```bash
bun run seed-db
```

This seeds 12 high-follower AI accounts for faster filtering (avoids API lookups).

### 4. Run type check and lint

```bash
bun run check-types
bun run lint
```

## Usage

### Dry-run mode (recommended for testing)

Test the full pipeline without actually posting to Twitter:

```bash
DRY_RUN=true bun run start
```

In dry-run mode:
- All pipeline stages execute normally
- Manus API is called, PDFs are generated
- Replies are logged but NOT posted
- Database records are marked with `DRY_RUN:` prefix

### Production mode

```bash
bun run start
```

Or with development mode (auto-restart on file changes):

```bash
bun run dev
```

### Running tests

```bash
# Run all tests (unit + integration + E2E)
bun run test

# Run only vitest tests (config, filter, templates)
bun run test:vitest

# Run only bun tests (database, integration, E2E)
bun run test:bun
```

## Configuration

All configuration is via environment variables. See `.env.example` for full documentation.

| Variable | Default | Description |
|----------|---------|-------------|
| `BIRD_COOKIE_SOURCE` | - | Browser to extract cookies from (`safari` or `chrome`) |
| `AUTH_TOKEN` / `CT0` | - | Manual Twitter tokens (alternative to cookie source) |
| `MANUS_API_KEY` | - | **Required**: Manus API key for PDF generation |
| `MANUS_TIMEOUT_MS` | 120000 | Manus task timeout (60000-300000) |
| `DATABASE_PATH` | `./data/responder.db` | SQLite database location |
| `MAX_DAILY_REPLIES` | 15 | Maximum replies per day |
| `MIN_GAP_MINUTES` | 10 | Minimum gap between replies |
| `MAX_PER_AUTHOR_PER_DAY` | 1 | Max replies to same author per day |
| `MIN_FOLLOWER_COUNT` | 50000 | Minimum followers for target authors |
| `MAX_TWEET_AGE_MINUTES` | 30 | Maximum tweet age to consider |
| `MIN_TWEET_LENGTH` | 100 | Minimum tweet content length |
| `POLL_INTERVAL_MS` | 60000 | Poll interval (60 seconds) |
| `DRY_RUN` | false | Enable dry-run mode |
| `LOG_LEVEL` | info | Logging level (info/warn/error) |

## Architecture

```
ai-agents-responder/
├── src/
│ ├── index.ts # Main orchestrator with poll loop
│ ├── poller.ts # Bird search wrapper
│ ├── filter.ts # Multi-stage filter pipeline
│ ├── generator.ts # Manus API + PDF→PNG conversion
│ ├── responder.ts # Bird reply with media upload
│ ├── manus-client.ts # Manus API client
│ ├── pdf-converter.ts # PDF to PNG conversion
│ ├── reply-templates.ts # Randomized reply text
│ ├── database.ts # SQLite operations (bun:sqlite)
│ ├── config.ts # Environment validation
│ ├── logger.ts # Structured JSON logging
│ ├── types.ts # TypeScript interfaces
│ └── utils/
│ ├── retry.ts # Exponential backoff
│ ├── circuit-breaker.ts # Manus failure protection
│ └── errors.ts # Error classification
├── scripts/
│ ├── seed-db.ts # Seed known influencers
│ └── e2e-test.sh # E2E validation script
├── data/
│ ├── responder.db # SQLite database (gitignored)
│ └── seed-authors.json # Initial influencer list
└── __tests__/ # Test suites
```

For detailed architecture documentation, see [specs/ai-agents/design.md](../specs/ai-agents/design.md).

## Troubleshooting

### Authentication errors (401)

**Problem**: `HTTP 401 Unauthorized` from Twitter API

**Solutions**:
1. If using `BIRD_COOKIE_SOURCE=safari`:
- Ensure you're logged into Twitter in Safari
- Try `BIRD_COOKIE_SOURCE=chrome` if Safari doesn't work
2. If using manual tokens:
- Tokens expire frequently; refresh from browser dev tools
- Get AUTH_TOKEN from `auth_token` cookie
- Get CT0 from `ct0` cookie

### Manus API timeout

**Problem**: PDF generation exceeds timeout

**Solutions**:
1. Increase timeout: `MANUS_TIMEOUT_MS=180000` (3 minutes)
2. Check Manus API status at https://open.manus.ai
3. Circuit breaker may be open (30-minute cooldown after 3 failures)

### No eligible tweets found

**Problem**: Filter rejects all candidates

**Causes and solutions**:
1. **Low followers**: Reduce `MIN_FOLLOWER_COUNT=10000` for testing
2. **Tweet too old**: Increase `MAX_TWEET_AGE_MINUTES=60`
3. **Short content**: Reduce `MIN_TWEET_LENGTH=50`
4. **Rate limited**: Check `daily_count` in database
5. **Already replied**: Check `replied_tweets` table

### Database errors

**Problem**: SQLite errors or corruption

**Solutions**:
1. Delete and recreate: `rm data/responder.db && bun run seed-db`
2. Check disk space
3. Ensure `data/` directory exists with write permissions

### PNG too large (>5MB)

**Problem**: Converted PNG exceeds Twitter's 5MB limit

**Solution**: The converter automatically compresses to 80% quality. If still too large, the tweet is skipped with an error log.

## Rate Limiting Strategy

Conservative defaults prevent spam detection:

- **10-15 replies/day**: Well under Twitter's limits
- **10-minute gaps**: Natural engagement pattern
- **1 reply per author per day**: Avoid appearing stalker-ish
- **Circuit breaker**: 30-minute cooldown after 3 Manus failures

## Logs

Logs are structured JSON written to stdout:

```json
{"timestamp":"2026-01-19T12:00:00.000Z","level":"info","component":"orchestrator","event":"cycle_complete","metadata":{"duration":125000,"status":"processed"}}
```

Key events to monitor:
- `cycle_complete` - Successful poll cycle
- `reply_posted` - Reply successfully posted
- `circuit_breaker_transition` - Manus protection state change
- `auth_error` - Authentication failure (requires re-auth)

## Specs Directory

Detailed specification documents are available in the specs directory:

- [specs/ai-agents/requirements.md](../specs/ai-agents/requirements.md) - Functional requirements
- [specs/ai-agents/design.md](../specs/ai-agents/design.md) - Technical design
- [specs/ai-agents/tasks.md](../specs/ai-agents/tasks.md) - Implementation tasks
- [specs/ai-agents/.progress.md](../specs/ai-agents/.progress.md) - Development progress

## License

Internal Zaigo Labs project. All rights reserved.
Loading