Commit graph

1110 commits

Author SHA1 Message Date
Cursor Agent
3d5f345033
Upgrade Pest from v4 to v5 (PHPUnit 13).
Bump pestphp/pest, pest-plugin-laravel, and pest-plugin-browser to ^5.0.
pest-plugin-laravel v5 requires Laravel ^13.23, so the framework lock is
updated accordingly. Refresh agent docs/skills for the Pest 5 / PHPUnit 13
baseline.

Co-authored-by: Paulo Castellano <hello@paulocastellano.com>
2026-07-31 01:40:50 +00:00
Paulo Castellano
b16e0bd9a5
Merge pull request #205 from trypostit/fix/mcp-upload-rate-limit-and-reel-durations
Fix MCP upload rate limits and Instagram Reel duration caps
2026-07-24 23:57:03 -03:00
Paulo Castellano
d35cc5277f Enforce carousel min slides in Generate and expose min_media_count on API/MCP.
GenerateNodeValidator and the Generate UI now respect ContentType::minMediaCount, and content-type listings share accept/min flags via toListingArray().

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 23:51:10 -03:00
Paulo Castellano
4cbdfa37d7 Hide video-only formats in the automation Generate node.
AI generate only produces images, so Video Pin / Reel / TikTok Video are filtered out in previewOnly and rejected server-side with a clear error.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 23:29:58 -03:00
Paulo Castellano
6bfb88dede Fix Generate node clamping image count to 0 for Pinterest.
Empty-account mount was clamping target_slide_count to 0 and never raising it when a media-required account was selected, so Pinterest showed a false requires-media error after picking a board.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 23:26:32 -03:00
Paulo Castellano
b9194b9c7d Surface Pinterest board truncation in the web editors.
Share {boards, truncated} via ListPinterestBoards into Inertia and warn in the board picker when pagination stopped early, matching API/MCP.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 23:02:40 -03:00
Paulo Castellano
d8e43bcfbb Unwrap Pinterest board lists for the web editors.
getBoards now returns {boards, truncated}; pass only the boards array into Inertia pinterestBoards so post and automation pickers keep receiving an array.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:54:20 -03:00
Paulo Castellano
e4779dfcdf Clamp media byte caps to upload limits and surface truncated board lists.
Align editor/API/MCP size ceilings with trypost.media hard caps, return truncated from Pinterest board pagination stop conditions, and rename the signed-upload claim key and rate limiter away from the MCP-only naming.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:49:04 -03:00
Paulo Castellano
0d4e5fd963 Restore media-rule parity and release failed MCP upload tokens.
Keep Instagram feed requiring media and Discord/Telegram accepting GIFs after centralization, skip the empty workspace rate-limit bucket, and clear the signed upload claim when persistence fails so retries work.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:37:57 -03:00
Paulo Castellano
491895cbd9 Page through all Pinterest boards until the bookmark ends.
Replace the 20-page hard stop with a while-loop that follows bookmarks to completion, keeping only safety breaks for a repeated cursor or an absurd page ceiling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:12:50 -03:00
Paulo Castellano
c040ba4686 Authorize API social accounts via SocialAccountPolicy.
Replace repeated workspace_id checks with PostPolicy-style denyAsNotFound tenancy so cross-tenant lookups stay 404 without leaking existence.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:09:35 -03:00
Paulo Castellano
7b986fca9c Centralize content-type media rules on the ContentType enum.
Share the full editor rule set (sizes, durations, accepts, aspect bounds) via Inertia so useMediaRules no longer hardcodes MB/GB math, and expose per-type byte caps on API/MCP content-type listings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:01:48 -03:00
Paulo Castellano
b28b18ef72 Address PR review: stream MCP uploads and close listing gaps.
Stream signed uploads through addMediaFromPath, return per-type max_bytes, harden Pinterest/Discord listing errors and pagination, and keep frontend duration fallbacks when Inertia once-props have not synced.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 22:00:07 -03:00
Paulo Castellano
ff0bfa8a06 Expose Pinterest board IDs via MCP and REST API.
Agents need board_id to publish pins; list boards per connected account so create/update can set platforms[].meta.board_id.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:47:51 -03:00
Paulo Castellano
b1cc1a6f1e Raise MCP upload IP backstop to 1200/min.
Give ChatGPT's shared egress more headroom across tenants while keeping the per-workspace cap at 60.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:44:52 -03:00
Paulo Castellano
3d4a42c7b0 Share content-type video duration caps to the frontend via Inertia.
Keep ContentType as the single source of truth and stop hardcoding maxVideoDurationSec in useMediaRules.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:36:53 -03:00
Paulo Castellano
302d902f75 Move signed upload URL TTL into config/trypost.php.
Keep API media upload settings out of the Laravel AI package config so they are not overwritten on package updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:33:39 -03:00
Paulo Castellano
3175fbe8c2 Centralize MCP upload size caps on trypost.media.
Drop the separate ai.mcp.upload.max_size_mb default and reuse Media\Type limits so MCP matches web/API (1GB video ceiling with per-type enforcement).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:29:41 -03:00
Paulo Castellano
564f157e44 Fix MCP upload rate limits and Instagram Reel duration caps.
Key signed uploads by workspace so ChatGPT's shared egress IPs don't throttle tenants together, raise the MCP upload cap to 300MB, and expose accurate Reel max durations via API/MCP.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:21:39 -03:00
Paulo Castellano
596ad491ef
Merge pull request #203 from trypostit/feature/post-created-via
Track post creation origin with created_via
2026-07-24 12:29:47 -03:00
Paulo Castellano
2aef07dde6 Defer PostCreated with DB::afterCommit in the observer.
Keep after-commit local to created(), matching the saved() job hook, instead of marking the event itself.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 12:17:43 -03:00
Paulo Castellano
254b7d514b Revert observer-wide after-commit; keep saved() job hook.
PostCreated already waits for commit via ShouldDispatchAfterCommit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 12:08:37 -03:00
Paulo Castellano
52f6506b3c Scope after-commit to PostCreated instead of the whole observer.
Restore the saved() automation afterCommit hook and let the event wait for commit on its own.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 12:08:16 -03:00
Paulo Castellano
d1d38865ef Dispatch PostCreated from PostObserver on every create.
Centralize provenance/broadcast/PostHog triggers so CreatePost and DuplicatePost no longer fire the event by hand.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 12:01:01 -03:00
Paulo Castellano
8b1ce057c3 Fire PostCreated on duplicate and drop unused PostHog eager load.
Duplicates now sync usage and track post.created like CreatePost; TrackPost only eager-loads what capture needs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:56:44 -03:00
Paulo Castellano
2c50a60790 Capture post.created to PostHog with created_via.
Dispatch TrackPost from PostCreated so we can chart which entry points create the most posts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:44:47 -03:00
Paulo Castellano
227ee45c2b Simplify created_via persistence to a plain data_get.
Callers already pass a CreatedVia enum or omit it; drop the defensive resolver.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:38:22 -03:00
Paulo Castellano
588891767b Leave created_via null when omitted or invalid.
Provenance is optional analytics — only persist a CreatedVia value when callers set a valid one.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:36:02 -03:00
Paulo Castellano
a545d29cfb Treat created_via as non-blocking analytics data.
Default to web when the value is missing, null, or invalid so post creation never fails over provenance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:34:24 -03:00
Paulo Castellano
459f4dd5a5 Harden created_via: require it, cover duplicate and all entry points.
Reject CreatePost calls without CreatedVia, set Web on DuplicatePost, and assert wiring for templates, AI, automation, and API spoof attempts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:30:15 -03:00
Paulo Castellano
26d0b2cdb2 chore: added strict types 2026-07-24 11:22:28 -03:00
Paulo Castellano
06f83a6571 Track post creation origin via created_via.
Persist whether a post was created through web, MCP, API, or automation so we can attribute entry points without guessing from request context.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:19:01 -03:00
Paulo Castellano
e2c43339e2
Merge pull request #202 from trypostit/fix/x-media-upload-finalize-json-body
fix(x): send JSON body on chunked media upload finalize
2026-07-24 11:03:34 -03:00
Paulo Castellano
38d74e358d fix(x): poll official media upload STATUS endpoint
Use GET /2/media/upload?media_id=&command=STATUS per X API docs, and persist
redacted raw_response on SocialPublishException failures for supportability.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 10:43:32 -03:00
Paulo Castellano
35e7b703b6 fix(x): harden chunked media upload handling and coverage
Fail hard when media processing fails, map media-specific X invalid-request
errors clearly, and cover GIF/large-image/amplify/finalize/append failure paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 10:30:34 -03:00
Paulo Castellano
8f4d33cc11 fix(x): send JSON body on chunked media upload finalize
X rejects empty finalize requests with "Request body must be a JSON object",
breaking video and large-media posts that use the chunked upload flow.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 10:25:40 -03:00
Paulo Castellano
8c7102afa6
Merge pull request #201 from trypostit/feat/laravel-boost-cursor
feat: wire Laravel Boost for Cursor (Sail + skills)
2026-07-23 13:22:03 -03:00
Paulo Castellano
dcfcd1589a refactor: standardize command usage in documentation and update agent settings
- Replaced `vendor/bin/sail` with `php` in documentation to unify command instructions.
- Updated `.mcp.json` and `.cursor/mcp.json` to reflect changes for Laravel Boost.
- Enhanced clarity in skill documentation for Cashier, Horizon, MCP, Passport, Pest, and Wayfinder.
- Disabled Sail support in `boost.json` and introduced "codex" as a new agent.
2026-07-23 12:50:01 -03:00
Paulo Castellano
3c9ceda872 refactor: update documentation to remove Sail references and improve command usage
- Replaced instances of `vendor/bin/sail` with `php` in various documentation files to standardize command usage.
- Updated `.mcp.json` and `.cursor/mcp.json` to reflect the new command for Laravel Boost.
- Adjusted skill documentation files for Cashier, Horizon, MCP, Passport, Pest, and Wayfinder to enhance clarity and ensure proper command execution.
- Disabled Sail support in `boost.json` and added "codex" as a new agent.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 12:44:14 -03:00
Paulo Castellano
0c4acb04e8 refactor: update commands to use Sail and improve documentation
- Changed command from `php artisan` to `vendor/bin/sail artisan` in various documentation files to ensure consistency with the use of Laravel Sail.
- Updated `.mcp.json` to reflect the new command for Laravel Boost.
- Added new agent "cursor" in `boost.json` and enabled Sail support.
- Updated PHP version in `CLAUDE.md` from 8.4 to 8.5.
- Made minor adjustments to various skill documentation files to enhance clarity and ensure proper command usage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 12:42:12 -03:00
Paulo Castellano
80c478541e
Merge pull request #199 from trypostit/fix/youtube-shorts-3-minutes
fix: raise YouTube Shorts max duration to 3 minutes
2026-07-23 12:24:05 -03:00
Paulo Castellano
8964dda8f2 fix: raise YouTube Shorts max duration to 3 minutes
YouTube Shorts now allow videos up to 3 minutes. The dashboard media rules still capped uploads at 60s (API/MCP already had no duration gate), so align the frontend validation, content-type copy, and unit test.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 12:06:15 -03:00
Paulo Castellano
71df3bf801
Merge pull request #198 from trypostit/fix/chunked-upload-unicode-filename
fix: allow unicode filenames in chunked asset uploads
2026-07-23 12:00:01 -03:00
Paulo Castellano
246022e9bc test: cover ChunkedAssetReceiver and ChunkReceipt paths
Adds dedicated tests for local assemble, multipart complete/progress, MediaResource response shape, and orphan R2 cleanup when media registration fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:51:13 -03:00
Paulo Castellano
a4f5c35ead fix: refresh assets gallery after deleting an upload
The uploads grid is client-fetched, so an Inertia delete with preserveState left the stale list on screen until a hard refresh.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:38:29 -03:00
Paulo Castellano
c1b28159b2 refactor: split HasMedia path storage into image vs stream helpers
Keep the image-normalize vs binary-stream split, but move each path into a focused private method so addMediaFromPath stays linear.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:23:05 -03:00
Paulo Castellano
66dbf438ee style: use interpolated medias/{$filename} paths
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:21:52 -03:00
Paulo Castellano
2ba5ce2b3f refactor: pull chunked upload orchestration out of AssetController
Controller only authorizes and returns ChunkReceipt. Multipart vs local assemble lives in ChunkedAssetReceiver; JSON shape comes from MediaResource.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:18:10 -03:00
Paulo Castellano
08ce75d2ec refactor: harden chunked cloud uploads after full PR review
Fix real edge cases: enforce 5MiB non-final parts, track offsets for ordered/idempotent chunks, size from bytes received, delete orphaned R2 objects if Media create fails, and split the controller into clearer paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:16:39 -03:00
Paulo Castellano
3c59dce349 test: cover chunked uploads across local, public, and S3 disks
Dataset for multipart strategy selection plus HTTP paths for assemble (local/public/images) and multipart (s3/r2/spaces videos).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:09:44 -03:00