Skip to content

Commit e4d0dbc

Browse files
majdyzclaude
andauthored
feat(platform): add Agent Output Demo field to marketplace submission form (#11538)
## Summary - Add Agent Output Demo field to marketplace agent submission form, positioned below the Description field - Store agent output demo URLs in database for future CoPilot integration - Implement proper video/image ordering on marketplace pages - Add shared YouTube URL validation utility to eliminate code duplication ## Changes Made ### Frontend - **Agent submission form**: Added Agent Output Demo field with YouTube URL validation - **Edit agent form**: Added Agent Output Demo field for existing submissions - **Marketplace display**: Implemented proper video/image ordering: 1. YouTube/Overview video (if exists) 2. First image (hero) 3. Agent Output Demo (if exists) 4. Additional images - **Shared utilities**: Created `validateYouTubeUrl` function in `src/lib/utils.ts` ### Backend - **Database schema**: Added `agentOutputDemoUrl` field to `StoreListingVersion` model - **Database views**: Updated `StoreAgent` view to include `agent_output_demo` field - **API models**: Added `agent_output_demo_url` to submission requests and `agent_output_demo` to responses - **Database migration**: Added migration to create new column and update view - **Test files**: Updated all test files to include the new required field ## Test Plan - [x] Frontend form validation works correctly for YouTube URLs - [x] Database migration applies successfully - [x] Backend API accepts and returns the new field - [x] Marketplace displays videos in correct order - [x] Both frontend and backend formatting/linting pass - [x] All test files include required field to prevent failures 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude <[email protected]>
1 parent 8e476c3 commit e4d0dbc

File tree

17 files changed

+188
-49
lines changed

17 files changed

+188
-49
lines changed

autogpt_platform/backend/backend/data/onboarding.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ async def get_recommended_agents(user_id: str) -> list[StoreAgentDetails]:
432432
slug=agent.slug,
433433
agent_name=agent.agent_name,
434434
agent_video=agent.agent_video or "",
435+
agent_output_demo=agent.agent_output_demo or "",
435436
agent_image=agent.agent_image,
436437
creator=agent.creator_username,
437438
creator_avatar=agent.creator_avatar,

autogpt_platform/backend/backend/server/v2/store/db.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ async def get_store_agent_details(
327327
slug=agent.slug,
328328
agent_name=agent.agent_name,
329329
agent_video=agent.agent_video or "",
330+
agent_output_demo=agent.agent_output_demo or "",
330331
agent_image=agent.agent_image,
331332
creator=agent.creator_username or "",
332333
creator_avatar=agent.creator_avatar or "",
@@ -397,6 +398,7 @@ async def get_store_agent_by_version_id(
397398
slug=agent.slug,
398399
agent_name=agent.agent_name,
399400
agent_video=agent.agent_video or "",
401+
agent_output_demo=agent.agent_output_demo or "",
400402
agent_image=agent.agent_image,
401403
creator=agent.creator_username or "",
402404
creator_avatar=agent.creator_avatar or "",
@@ -683,6 +685,7 @@ async def create_store_submission(
683685
slug: str,
684686
name: str,
685687
video_url: str | None = None,
688+
agent_output_demo_url: str | None = None,
686689
image_urls: list[str] = [],
687690
description: str = "",
688691
instructions: str | None = None,
@@ -777,6 +780,7 @@ async def create_store_submission(
777780
agentGraphVersion=agent_version,
778781
name=name,
779782
videoUrl=video_url,
783+
agentOutputDemoUrl=agent_output_demo_url,
780784
imageUrls=image_urls,
781785
description=description,
782786
instructions=instructions,
@@ -849,6 +853,7 @@ async def edit_store_submission(
849853
store_listing_version_id: str,
850854
name: str,
851855
video_url: str | None = None,
856+
agent_output_demo_url: str | None = None,
852857
image_urls: list[str] = [],
853858
description: str = "",
854859
sub_heading: str = "",
@@ -930,6 +935,7 @@ async def edit_store_submission(
930935
store_listing_id=current_version.storeListingId,
931936
name=name,
932937
video_url=video_url,
938+
agent_output_demo_url=agent_output_demo_url,
933939
image_urls=image_urls,
934940
description=description,
935941
sub_heading=sub_heading,
@@ -947,6 +953,7 @@ async def edit_store_submission(
947953
data=prisma.types.StoreListingVersionUpdateInput(
948954
name=name,
949955
videoUrl=video_url,
956+
agentOutputDemoUrl=agent_output_demo_url,
950957
imageUrls=image_urls,
951958
description=description,
952959
categories=categories,
@@ -1008,6 +1015,7 @@ async def create_store_version(
10081015
store_listing_id: str,
10091016
name: str,
10101017
video_url: str | None = None,
1018+
agent_output_demo_url: str | None = None,
10111019
image_urls: list[str] = [],
10121020
description: str = "",
10131021
instructions: str | None = None,
@@ -1077,6 +1085,7 @@ async def create_store_version(
10771085
agentGraphVersion=agent_version,
10781086
name=name,
10791087
videoUrl=video_url,
1088+
agentOutputDemoUrl=agent_output_demo_url,
10801089
imageUrls=image_urls,
10811090
description=description,
10821091
instructions=instructions,

autogpt_platform/backend/backend/server/v2/store/model.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class StoreAgentDetails(pydantic.BaseModel):
4444
slug: str
4545
agent_name: str
4646
agent_video: str
47+
agent_output_demo: str
4748
agent_image: list[str]
4849
creator: str
4950
creator_avatar: str
@@ -121,6 +122,7 @@ class StoreSubmission(pydantic.BaseModel):
121122

122123
# Additional fields for editing
123124
video_url: str | None = None
125+
agent_output_demo_url: str | None = None
124126
categories: list[str] = []
125127

126128

@@ -157,6 +159,7 @@ class StoreSubmissionRequest(pydantic.BaseModel):
157159
name: str
158160
sub_heading: str
159161
video_url: str | None = None
162+
agent_output_demo_url: str | None = None
160163
image_urls: list[str] = []
161164
description: str = ""
162165
instructions: str | None = None
@@ -169,6 +172,7 @@ class StoreSubmissionEditRequest(pydantic.BaseModel):
169172
name: str
170173
sub_heading: str
171174
video_url: str | None = None
175+
agent_output_demo_url: str | None = None
172176
image_urls: list[str] = []
173177
description: str = ""
174178
instructions: str | None = None

autogpt_platform/backend/backend/server/v2/store/model_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def test_store_agent_details():
6262
slug="test-agent",
6363
agent_name="Test Agent",
6464
agent_video="video.mp4",
65+
agent_output_demo="demo.mp4",
6566
agent_image=["image1.jpg", "image2.jpg"],
6667
creator="creator1",
6768
creator_avatar="avatar.jpg",

autogpt_platform/backend/backend/server/v2/store/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ async def create_submission(
438438
slug=submission_request.slug,
439439
name=submission_request.name,
440440
video_url=submission_request.video_url,
441+
agent_output_demo_url=submission_request.agent_output_demo_url,
441442
image_urls=submission_request.image_urls,
442443
description=submission_request.description,
443444
instructions=submission_request.instructions,
@@ -481,6 +482,7 @@ async def edit_submission(
481482
store_listing_version_id=store_listing_version_id,
482483
name=submission_request.name,
483484
video_url=submission_request.video_url,
485+
agent_output_demo_url=submission_request.agent_output_demo_url,
484486
image_urls=submission_request.image_urls,
485487
description=submission_request.description,
486488
instructions=submission_request.instructions,

autogpt_platform/backend/backend/server/v2/store/routes_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ def test_get_agent_details(
378378
slug="test-agent",
379379
agent_name="Test Agent",
380380
agent_video="video.mp4",
381+
agent_output_demo="demo.mp4",
381382
agent_image=["image1.jpg", "image2.jpg"],
382383
creator="creator1",
383384
creator_avatar="avatar1.jpg",
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
-- AlterTable
2+
ALTER TABLE "StoreListingVersion" ADD COLUMN "agentOutputDemoUrl" TEXT;
3+
4+
-- Drop and recreate the StoreAgent view with agentOutputDemoUrl field
5+
DROP VIEW IF EXISTS "StoreAgent";
6+
7+
CREATE OR REPLACE VIEW "StoreAgent" AS
8+
WITH latest_versions AS (
9+
SELECT
10+
"storeListingId",
11+
MAX(version) AS max_version
12+
FROM "StoreListingVersion"
13+
WHERE "submissionStatus" = 'APPROVED'
14+
GROUP BY "storeListingId"
15+
),
16+
agent_versions AS (
17+
SELECT
18+
"storeListingId",
19+
array_agg(DISTINCT version::text ORDER BY version::text) AS versions
20+
FROM "StoreListingVersion"
21+
WHERE "submissionStatus" = 'APPROVED'
22+
GROUP BY "storeListingId"
23+
)
24+
SELECT
25+
sl.id AS listing_id,
26+
slv.id AS "storeListingVersionId",
27+
slv."createdAt" AS updated_at,
28+
sl.slug,
29+
COALESCE(slv.name, '') AS agent_name,
30+
slv."videoUrl" AS agent_video,
31+
slv."agentOutputDemoUrl" AS agent_output_demo,
32+
COALESCE(slv."imageUrls", ARRAY[]::text[]) AS agent_image,
33+
slv."isFeatured" AS featured,
34+
p.username AS creator_username, -- Allow NULL for malformed sub-agents
35+
p."avatarUrl" AS creator_avatar, -- Allow NULL for malformed sub-agents
36+
slv."subHeading" AS sub_heading,
37+
slv.description,
38+
slv.categories,
39+
slv.search,
40+
COALESCE(ar.run_count, 0::bigint) AS runs,
41+
COALESCE(rs.avg_rating, 0.0)::double precision AS rating,
42+
COALESCE(av.versions, ARRAY[slv.version::text]) AS versions,
43+
slv."isAvailable" AS is_available,
44+
COALESCE(sl."useForOnboarding", false) AS "useForOnboarding"
45+
FROM "StoreListing" sl
46+
JOIN latest_versions lv
47+
ON sl.id = lv."storeListingId"
48+
JOIN "StoreListingVersion" slv
49+
ON slv."storeListingId" = lv."storeListingId"
50+
AND slv.version = lv.max_version
51+
AND slv."submissionStatus" = 'APPROVED'
52+
JOIN "AgentGraph" a
53+
ON slv."agentGraphId" = a.id
54+
AND slv."agentGraphVersion" = a.version
55+
LEFT JOIN "Profile" p
56+
ON sl."owningUserId" = p."userId"
57+
LEFT JOIN "mv_review_stats" rs
58+
ON sl.id = rs."storeListingId"
59+
LEFT JOIN "mv_agent_run_counts" ar
60+
ON a.id = ar."agentGraphId"
61+
LEFT JOIN agent_versions av
62+
ON sl.id = av."storeListingId"
63+
WHERE sl."isDeleted" = false
64+
AND sl."hasApprovedVersion" = true;

autogpt_platform/backend/schema.prisma

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -701,10 +701,11 @@ view StoreAgent {
701701
storeListingVersionId String
702702
updated_at DateTime
703703
704-
slug String
705-
agent_name String
706-
agent_video String?
707-
agent_image String[]
704+
slug String
705+
agent_name String
706+
agent_video String?
707+
agent_output_demo String?
708+
agent_image String[]
708709
709710
featured Boolean @default(false)
710711
creator_username String?
@@ -833,13 +834,14 @@ model StoreListingVersion {
833834
AgentGraph AgentGraph @relation(fields: [agentGraphId, agentGraphVersion], references: [id, version])
834835
835836
// Content fields
836-
name String
837-
subHeading String
838-
videoUrl String?
839-
imageUrls String[]
840-
description String
841-
instructions String?
842-
categories String[]
837+
name String
838+
subHeading String
839+
videoUrl String?
840+
agentOutputDemoUrl String?
841+
imageUrls String[]
842+
description String
843+
instructions String?
844+
categories String[]
843845
844846
isFeatured Boolean @default(false)
845847

autogpt_platform/backend/snapshots/agt_details

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"slug": "test-agent",
44
"agent_name": "Test Agent",
55
"agent_video": "video.mp4",
6+
"agent_output_demo": "demo.mp4",
67
"agent_image": [
78
"image1.jpg",
89
"image2.jpg"

autogpt_platform/backend/snapshots/sub_success

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"reviewed_at": null,
2424
"changes_summary": null,
2525
"video_url": "test.mp4",
26+
"agent_output_demo_url": null,
2627
"categories": [
2728
"test-category"
2829
]

0 commit comments

Comments
 (0)