feat: add agent output sharing support#613
Conversation
|
@PeswikaBavagni-30 is attempting to deploy a commit to the aditthyass' projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning Review limit reached
More reviews will be available in 46 minutes and 53 seconds. Learn how PR review limits work. To continue reviewing without waiting, enable usage-based billing in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Note
|
| Layer / File(s) | Summary |
|---|---|
Database schema: shared_outputs table and RLS supabase/migrations/20260623000000_create_shared_outputs.sql |
Creates shared_outputs table (UUID PK, JSONB inputs, output_type constraint, 7-day expiry window check), enables RLS with insert/select policies for anon and authenticated roles, and adds an index on expires_at. |
Share formatting utilities, API client, and tests src/lib/shareOutputFormat.js, src/lib/shareOutput.js, test/shareOutput.test.js, package.json |
shareOutputFormat.js exports SHARE_EXPIRY_DAYS, getShareableInputs, and buildShareCard. shareOutput.js provides createSharedOutput (POST) and getSharedOutput (GET), re-exporting the format utilities. Tests cover both formatting functions; node --test script is added to package.json. |
Server-side API handlers api/share.js, api/share/[id].js, vite.config.js |
api/share.js handles POST with validation, inputs normalization, UUID/expiry generation, and Supabase insert. api/share/[id].js handles GET with expiry filtering. vite.config.js adds an api-server-middleware plugin replicating both handlers for local dev. |
Toast notification system src/lib/useToast.jsx, src/index.css, src/main.jsx |
ToastProvider manages a toasts array, exposes addToast (auto-removes after 3 s) and removeToast, and renders an accessible fixed toast container. useToast hook enforces provider presence. CSS adds @keyframes toastIn and .animate-toast-in. main.jsx wraps the app with ToastProvider above AgentsProvider. |
ShareMenu component and OutputRenderer toolbar update src/components/ShareMenu.jsx, src/components/OutputRenderer.jsx, src/components/AgentRunner.jsx |
ShareMenu adds a dropdown with "Copy Card" and "Create Link" actions, clipboard fallback, and toast feedback. OutputRenderer gains agent, inputs, and showToolbar props; the toolbar is gated by showToolbar and renders ShareMenu when agent is provided. AgentRunner passes agent and inputs to OutputRenderer. |
SharedOutputPage and route registration src/pages/SharedOutputPage.jsx, src/App.jsx |
SharedOutputPage fetches shared output by id via getSharedOutput, handles loading/error/data states with unmount safety, and renders the output via OutputRenderer with showToolbar={false}. The /share/:id route is registered in App.jsx. |
Sequence Diagram(s)
sequenceDiagram
participant User
participant ShareMenu
participant shareOutput.js
participant APIHandler
participant Supabase
User->>ShareMenu: clicks "Create Link"
ShareMenu->>shareOutput.js: createSharedOutput({agent, inputs, output})
shareOutput.js->>APIHandler: POST /api/share {agentName, output, inputs}
APIHandler->>Supabase: insert into shared_outputs
Supabase-->>APIHandler: inserted row
APIHandler-->>shareOutput.js: {shareId, url}
shareOutput.js-->>ShareMenu: {id, url}
ShareMenu->>User: copies URL to clipboard + shows toast
rect rgba(99, 179, 237, 0.5)
note over User,Supabase: Viewing a shared link
end
User->>SharedOutputPage: navigates to /share/:id
SharedOutputPage->>shareOutput.js: getSharedOutput(id)
shareOutput.js->>APIHandler: GET /api/share/:id
APIHandler->>Supabase: select where id=? and expires_at > now()
Supabase-->>APIHandler: row or null
APIHandler-->>shareOutput.js: 200/404/500
shareOutput.js-->>SharedOutputPage: sharedOutput or null/error
SharedOutputPage->>User: renders OutputRenderer with showToolbar=false
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related issues
- feat: share agent output as a formatted card or shareable link #568: This PR directly implements the requested share feature: a "Share" button with copy-card and create-link options, a 7-day expiring shareable URL backed by Supabase, and a public read-only view page.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 5.56% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title 'feat: add agent output sharing support' accurately summarizes the main feature addition: implementing a sharing system for agent outputs with both card copy and shareable link capabilities. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
|
Hey @PeswikaBavagni-30! 👋
|
|
hey @PeswikaBavagni-30! 👋 |
|
|
|
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
api/share.js (3)
61-61: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winConsider sanitizing database error messages.
Returning
error.messagedirectly from Supabase could leak schema or constraint details to clients. For production, consider logging the full error server-side and returning a generic message like "Failed to create shared output" to clients.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@api/share.js` at line 61, The error response at line 61 in the error handling block returns the raw `error.message` directly to the client, which could expose sensitive database schema or constraint information. Modify this error handling to log the full error object server-side for debugging purposes, while returning a generic error message like "Failed to create shared output" to the client instead of the raw error message.
27-32: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider validating output length and outputType before insert.
The handler validates that
agentNameandoutputare non-empty, but doesn't check:
outputlength (RLS policy enforces ≤100,000 chars)outputTypeis one of 'markdown', 'text', 'json' (schema CHECK constraint enforces this)If either constraint is violated, the insert will fail and return a generic 500 error. Validating in the handler would allow returning a clear 400 error with a specific message.
📋 Suggested validation additions
if (!output || typeof output !== 'string' || !output.trim()) { return res.status(400).json({ error: 'output is required and must be a non-empty string' }) } +if (output.length > 100000) { + return res.status(400).json({ error: 'output must not exceed 100,000 characters' }) +} + +const validOutputTypes = ['markdown', 'text', 'json'] +if (outputType && !validOutputTypes.includes(outputType)) { + return res.status(400).json({ error: `outputType must be one of: ${validOutputTypes.join(', ')}` }) +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@api/share.js` around lines 27 - 32, The validation block for agentName and output is incomplete and missing checks for output length and outputType value. Add validation after the existing non-empty string checks to verify that output does not exceed 100,000 characters (enforced by the RLS policy) and that outputType is one of the allowed values: 'markdown', 'text', or 'json' (enforced by the schema CHECK constraint). Return a 400 status with a descriptive error message for each validation failure, similar to the existing validation pattern, so that constraint violations produce clear client errors instead of generic 500 errors on insert.
11-11: 🔒 Security & Privacy | 🔵 TrivialNote: CORS allows all origins.
The
Access-Control-Allow-Origin: *header permits any domain to create shared outputs via this endpoint. Combined with anonymous insert allowed by the RLS policy, this could be abused. The 100KB output limit and 7-day expiry in the RLS policy provide some protection, but consider whether you need additional safeguards (rate limiting, origin restrictions, or CAPTCHA for public endpoints).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@api/share.js` at line 11, The `Access-Control-Allow-Origin: *` header in the setHeader call permits requests from any origin, which combined with anonymous insert capabilities creates a security risk. Replace the wildcard '*' with specific allowed origins that your application controls, or implement additional safeguards such as rate limiting middleware, origin validation logic, or CAPTCHA verification for the share endpoint to prevent abuse while maintaining functionality.vite.config.js (3)
24-26: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winSupabase client recreated per request in dev middleware.
Line 26 creates a new Supabase client for every request to
/api/share, while the production handlers (api/share.js, api/share/[id].js) create the client once at module scope. For better dev performance, consider moving client creation outside the request handler.⚡ Suggested optimization
+const supabaseUrl = process.env.VITE_SUPABASE_URL || 'http://localhost:54321' +const supabaseAnonKey = process.env.VITE_SUPABASE_ANON_KEY || 'dummy' +const supabase = createClient(supabaseUrl, supabaseAnonKey) + export default defineConfig({ plugins: [ react(), { name: 'api-server-middleware', configureServer(server) { server.middlewares.use(async (req, res, next) => { if (req.url && req.url.startsWith('/api/share')) { // ... CORS setup ... - const supabaseUrl = process.env.VITE_SUPABASE_URL || 'http://localhost:54321' - const supabaseAnonKey = process.env.VITE_SUPABASE_ANON_KEY || 'dummy' - const supabase = createClient(supabaseUrl, supabaseAnonKey)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vite.config.js` around lines 24 - 26, The Supabase client initialization (lines creating supabaseUrl, supabaseAnonKey, and calling createClient) is currently happening inside the dev middleware request handler, causing a new client to be instantiated for every request. Move the client creation logic outside the middleware handler function so it executes once at module initialization time, matching the pattern used in the production handlers api/share.js and api/share/[id].js. This will improve dev server performance by reusing the same client instance across requests instead of recreating it each time.
40-51: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider adding the same validations as suggested for api/share.js.
The dev middleware duplicates the POST handler logic from api/share.js. The same validation improvements (output length check, outputType validation) would apply here. Keeping both implementations in sync ensures consistent behavior across dev and production environments.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vite.config.js` around lines 40 - 51, The validation checks for agentName and output in the dev middleware are missing the additional validations that exist in api/share.js. Add a validation check for output length to ensure it meets the minimum length requirement, and add a validation check for outputType to ensure it is provided and matches an expected type. Place these additional validation checks after the existing output validation check but following the same pattern: verify the condition, set statusCode to 400, set the Content-Type header to application/json, and return an error response with a descriptive message before processing continues.
10-146: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffCode duplication between dev middleware and production API handlers.
The middleware duplicates all logic from api/share.js (POST) and api/share/[id].js (GET). While necessary for dev vs production environments, this creates a maintenance burden—changes must be manually synchronized across three files. Consider documenting this relationship or exploring ways to share validation/payload logic.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vite.config.js` around lines 10 - 146, The middleware in the configureServer function duplicates all the validation logic and payload construction for both the POST request (checking agentName, output, and parsing inputs) and the GET request (database queries and error handling) that exists in the actual API handlers. Extract the shared validation logic (such as agentName and output validation), the payload construction logic, and the database query logic into separate utility functions in a shared file that can be imported and reused by both the middleware and the api/share.js and api/share/[id].js handlers. This will centralize the logic and ensure changes only need to be made in one place rather than across all three files.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/ShareMenu.jsx`:
- Around line 38-67: The setTimeout calls in handleCopyCard and handleCreateLink
are not tracked or cleaned up, creating race conditions and potential memory
leaks. Store timeout IDs in a useRef, clear any existing timeout before creating
a new one in both functions to prevent overlapping timeouts, and add a useEffect
cleanup function that clears the timeout when the component unmounts or
dependencies change.
In `@src/lib/useToast.jsx`:
- Around line 9-17: The addToast function needs two fixes: First, store the
timeout ID returned by setTimeout along with each toast object so that when
removeToast is called, the timeout can be cleared using clearTimeout to prevent
unnecessary state updates after manual dismissal. Second, replace the Date.now()
ID generation with a counter (incrementing on each call) or UUID library to
ensure unique IDs and prevent collisions when multiple toasts are added within
the same millisecond. Modify the toast object structure to include the timeoutId
and update the removeToast function to clear the timeout before removing the
toast from state.
---
Nitpick comments:
In `@api/share.js`:
- Line 61: The error response at line 61 in the error handling block returns the
raw `error.message` directly to the client, which could expose sensitive
database schema or constraint information. Modify this error handling to log the
full error object server-side for debugging purposes, while returning a generic
error message like "Failed to create shared output" to the client instead of the
raw error message.
- Around line 27-32: The validation block for agentName and output is incomplete
and missing checks for output length and outputType value. Add validation after
the existing non-empty string checks to verify that output does not exceed
100,000 characters (enforced by the RLS policy) and that outputType is one of
the allowed values: 'markdown', 'text', or 'json' (enforced by the schema CHECK
constraint). Return a 400 status with a descriptive error message for each
validation failure, similar to the existing validation pattern, so that
constraint violations produce clear client errors instead of generic 500 errors
on insert.
- Line 11: The `Access-Control-Allow-Origin: *` header in the setHeader call
permits requests from any origin, which combined with anonymous insert
capabilities creates a security risk. Replace the wildcard '*' with specific
allowed origins that your application controls, or implement additional
safeguards such as rate limiting middleware, origin validation logic, or CAPTCHA
verification for the share endpoint to prevent abuse while maintaining
functionality.
In `@vite.config.js`:
- Around line 24-26: The Supabase client initialization (lines creating
supabaseUrl, supabaseAnonKey, and calling createClient) is currently happening
inside the dev middleware request handler, causing a new client to be
instantiated for every request. Move the client creation logic outside the
middleware handler function so it executes once at module initialization time,
matching the pattern used in the production handlers api/share.js and
api/share/[id].js. This will improve dev server performance by reusing the same
client instance across requests instead of recreating it each time.
- Around line 40-51: The validation checks for agentName and output in the dev
middleware are missing the additional validations that exist in api/share.js.
Add a validation check for output length to ensure it meets the minimum length
requirement, and add a validation check for outputType to ensure it is provided
and matches an expected type. Place these additional validation checks after the
existing output validation check but following the same pattern: verify the
condition, set statusCode to 400, set the Content-Type header to
application/json, and return an error response with a descriptive message before
processing continues.
- Around line 10-146: The middleware in the configureServer function duplicates
all the validation logic and payload construction for both the POST request
(checking agentName, output, and parsing inputs) and the GET request (database
queries and error handling) that exists in the actual API handlers. Extract the
shared validation logic (such as agentName and output validation), the payload
construction logic, and the database query logic into separate utility functions
in a shared file that can be imported and reused by both the middleware and the
api/share.js and api/share/[id].js handlers. This will centralize the logic and
ensure changes only need to be made in one place rather than across all three
files.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 79a7652b-a730-4048-85f4-81e5583f1bdb
⛔ Files ignored due to path filters (5)
package-lock.jsonis excluded by!**/package-lock.json,!package-lock.jsonscreenshots/copy_as_card_workflow.pngis excluded by!**/*.pngscreenshots/public_share_page.pngis excluded by!**/*.pngscreenshots/share_button_visible.pngis excluded by!**/*.pngscreenshots/shareable_link_workflow.pngis excluded by!**/*.png
📒 Files selected for processing (16)
api/share.jsapi/share/[id].jspackage.jsonsrc/App.jsxsrc/components/AgentRunner.jsxsrc/components/OutputRenderer.jsxsrc/components/ShareMenu.jsxsrc/index.csssrc/lib/shareOutput.jssrc/lib/shareOutputFormat.jssrc/lib/useToast.jsxsrc/main.jsxsrc/pages/SharedOutputPage.jsxsupabase/migrations/20260623000000_create_shared_outputs.sqltest/shareOutput.test.jsvite.config.js
| const handleCopyCard = async () => { | ||
| setError('') | ||
| try { | ||
| await copyText(buildShareCard({ | ||
| agentName: agent.name, | ||
| inputs: getShareableInputs(inputs, agent.inputs), | ||
| output, | ||
| })) | ||
| setStatus('copied-card') | ||
| addToast('Copied as formatted card') | ||
| setTimeout(() => setStatus('idle'), 2000) | ||
| } catch { | ||
| setError('Could not copy the card. Please try again.') | ||
| } | ||
| } | ||
|
|
||
| const handleCreateLink = async () => { | ||
| setError('') | ||
| setStatus('creating-link') | ||
| try { | ||
| const shared = await createSharedOutput({ agent, inputs, output }) | ||
| await copyText(shared.url) | ||
| setStatus('copied-link') | ||
| addToast('Share link copied') | ||
| setTimeout(() => setStatus('idle'), 2500) | ||
| } catch { | ||
| setStatus('idle') | ||
| setError('Could not create a shareable link. Please try again.') | ||
| } | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Clean up status timeouts to prevent race conditions.
Both handleCopyCard and handleCreateLink create setTimeout calls (lines 48, 62) that reset the status state, but these timeouts are not tracked or cleaned up. This causes:
- Race conditions: Rapidly clicking either button multiple times creates overlapping timeouts that can reset status unexpectedly.
- Memory leaks: If the component unmounts before the timeout fires, the setState call still executes.
🔧 Proposed fix
export default function ShareMenu({ agent, inputs, output }) {
const [open, setOpen] = useState(false)
const [status, setStatus] = useState('idle')
const [error, setError] = useState('')
const menuRef = useRef(null)
+ const timeoutRef = useRef(null)
const { addToast } = useToast()
useEffect(() => {
if (!open) return undefined
const closeMenu = (event) => {
if (!menuRef.current?.contains(event.target)) setOpen(false)
}
document.addEventListener('mousedown', closeMenu)
return () => document.removeEventListener('mousedown', closeMenu)
}, [open])
+
+ useEffect(() => {
+ return () => {
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
+ }
+ }, [])
const handleCopyCard = async () => {
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
setError('')
try {
await copyText(buildShareCard({
agentName: agent.name,
inputs: getShareableInputs(inputs, agent.inputs),
output,
}))
setStatus('copied-card')
addToast('Copied as formatted card')
- setTimeout(() => setStatus('idle'), 2000)
+ timeoutRef.current = setTimeout(() => setStatus('idle'), 2000)
} catch {
setError('Could not copy the card. Please try again.')
}
}
const handleCreateLink = async () => {
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
setError('')
setStatus('creating-link')
try {
const shared = await createSharedOutput({ agent, inputs, output })
await copyText(shared.url)
setStatus('copied-link')
addToast('Share link copied')
- setTimeout(() => setStatus('idle'), 2500)
+ timeoutRef.current = setTimeout(() => setStatus('idle'), 2500)
} catch {
setStatus('idle')
setError('Could not create a shareable link. Please try again.')
}
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/ShareMenu.jsx` around lines 38 - 67, The setTimeout calls in
handleCopyCard and handleCreateLink are not tracked or cleaned up, creating race
conditions and potential memory leaks. Store timeout IDs in a useRef, clear any
existing timeout before creating a new one in both functions to prevent
overlapping timeouts, and add a useEffect cleanup function that clears the
timeout when the component unmounts or dependencies change.
| const addToast = (message, type = 'success') => { | ||
| const id = Date.now() | ||
| setToasts((prev) => [...prev, { id, message, type }]) | ||
|
|
||
| // Auto-remove after 3 seconds | ||
| setTimeout(() => { | ||
| removeToast(id) | ||
| }, 3000) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Clean up the auto-dismiss timeout to prevent memory leaks.
Two concerns:
-
Timeout leak: When a toast is manually dismissed (line 49), the scheduled
setTimeoutstill fires 3 seconds later, causing an unnecessary state update. If the component unmounts before the timeout, this triggers a React warning. -
ID collision risk:
Date.now()can produce duplicate IDs if two toasts are added within the same millisecond (e.g., during rapid user actions or batch operations).
🔧 Proposed fix
export function ToastProvider({ children }) {
const [toasts, setToasts] = useState([])
+ const timeoutsRef = useRef(new Map())
const addToast = (message, type = 'success') => {
- const id = Date.now()
+ const id = `${Date.now()}-${Math.random()}`
setToasts((prev) => [...prev, { id, message, type }])
// Auto-remove after 3 seconds
- setTimeout(() => {
+ const timeoutId = setTimeout(() => {
removeToast(id)
}, 3000)
+ timeoutsRef.current.set(id, timeoutId)
}
const removeToast = (id) => {
+ const timeoutId = timeoutsRef.current.get(id)
+ if (timeoutId) {
+ clearTimeout(timeoutId)
+ timeoutsRef.current.delete(id)
+ }
setToasts((prev) => prev.filter((t) => t.id !== id))
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lib/useToast.jsx` around lines 9 - 17, The addToast function needs two
fixes: First, store the timeout ID returned by setTimeout along with each toast
object so that when removeToast is called, the timeout can be cleared using
clearTimeout to prevent unnecessary state updates after manual dismissal.
Second, replace the Date.now() ID generation with a counter (incrementing on
each call) or UUID library to ensure unique IDs and prevent collisions when
multiple toasts are added within the same millisecond. Modify the toast object
structure to include the timeoutId and update the removeToast function to clear
the timeout before removing the toast from state.
#568
Currently, AgentRunner displays agent outputs, but users have no convenient way to share them. Users must manually copy text, which loses formatting, metadata, and context.
This Pull Request implements a complete sharing system with two options:
Changes Made
1. Backend Server & Local Dev Middleware
api/share.jsto handlePOST /api/share. Validates inputs, generates UUID and 7-day expiration time, and stores the sharing record in the Supabaseshared_outputstable.api/share/[id].jsto handleGET /api/share/:id. Fetches the record and validates that the sharing link has not expired.vite.config.jsto route request paths/api/shareand/api/share/:idin local development.2. Frontend Changes
src/lib/shareOutput.jsto fetch from the newly added API endpoints instead of making direct client-side database calls.src/lib/useToast.jsxand wrapped the application insidesrc/main.jsx.src/components/ShareMenu.jsxto calluseToastto trigger success alerts upon successfully copying the formatted card or creating a link."Shared via AgentRunner"tosrc/pages/SharedOutputPage.jsx.src/index.css.Database / Schema Updates
Table
shared_outputswas created in Supabase with the following schema:id(uuid primary key)agent_id(text not null)agent_name(text not null)inputs(jsonb not null default '{}'::jsonb)output(text not null)output_type(text not null default 'markdown' check (output_type in ('markdown', 'text', 'json')))created_at(timestamptz not null default now())expires_at(timestamptz not null)API Endpoints Added
POST /api/share: Create a new shared output. Expiry set to 7 days.GET /api/share/:id: Get shared output if not expired. Returns 404 on expired or missing links.Screenshots
1. Share Button Visible
2. Copy as Formatted Card
3. Shareable Link Workflow
4. Public Share Page
Testing Performed
npm run test(all tests passed).npm run build(compilation succeeded).Summary by CodeRabbit
New Features
Tests