feat(apify): LinkedIn scrape returns posts when `posts` is requested
Summary
Implements recoupable/chat#1838. Contract: recoupable/docs#260 — merge order docs → api. Base is main per the current direct-to-main flow; I'll sync test after merge.
One-file change: startLinkedinProfileScraping(handle, posts?) — when posts is defined, runs harvestapi/linkedin-profile-posts with {targetUrls: [url], maxPosts: posts}; when omitted, the existing profile actor with byte-identical input (unit-tested). Handle guards (in/company/school legacy rows), full-URL passthrough, webhooks, and error handling unchanged and re-asserted for the posts branch.
This closes the last platform gap in the posts param: LinkedIn post items carry engagement (likes, comments, shares, reaction-type breakdown) — richer than the connector, which can't see comments/shares on personal posts and has no list-my-posts endpoint at all.
Billing: no change needed (per the #1838 evaluation). Actor pricing $0.002/post + $0.00005 start, verified on live run aKsHPucJ3thxuosSd (5 posts → $0.01005, exactly list). Under the shipped 5 + posts rule: posts=100 → ~$0.20 cost vs $1.05 charged (~5.2× margin); YouTube remains the binding worst case.
Tests (TDD, red → green)
3 new cases written first and confirmed failing (2 RED before implementation):
- posts=20 → posts actor +
{targetUrls, maxPosts: 20} - posts branch keeps full-URL passthrough + invalid-handle guards
- posts omitted → profile actor, byte-identical legacy input
lib/apify: 77/77. Full suite passes. tsc --noEmit: 200 pre-existing errors, none new. ESLint clean.
Preview verification to follow as a PR comment (pinned check: post 7478135671589634048 shows comments: 1).
🤖 Generated with Claude Code
Summary by cubic
Adds optional posts depth to LinkedIn scraping: when provided, we return recent post items with engagement counts via harvestapi/linkedin-profile-posts; when omitted, we keep the existing profile snapshot.
- New Features
startLinkedinProfileScraping(handle, posts?)selectsharvestapi/linkedin-profile-postswith{ targetUrls: [url], maxPosts: posts }whenpostsis set.- When
postsis omitted, usesharvestapi/linkedin-profile-scraperwith{ urls: [url] }.