diff --git a/surfsense_backend/app/capabilities/core/access/rest.py b/surfsense_backend/app/capabilities/core/access/rest.py index 328a7c5a1..2047b21ae 100644 --- a/surfsense_backend/app/capabilities/core/access/rest.py +++ b/surfsense_backend/app/capabilities/core/access/rest.py @@ -71,6 +71,7 @@ class CapabilitySummary(BaseModel): name: str description: str + docs_url: str | None = None input_schema: dict output_schema: dict # Empty list = free (billing disabled or an unmetered verb). @@ -145,6 +146,7 @@ def _register_capabilities_list( CapabilitySummary( name=capability.name, description=capability.description, + docs_url=capability.docs_url, input_schema=capability.input_schema.model_json_schema(), output_schema=capability.output_schema.model_json_schema(), ), diff --git a/surfsense_backend/app/capabilities/core/types.py b/surfsense_backend/app/capabilities/core/types.py index ec44d29aa..c87601832 100644 --- a/surfsense_backend/app/capabilities/core/types.py +++ b/surfsense_backend/app/capabilities/core/types.py @@ -62,3 +62,4 @@ class Capability: output_schema: type[BaseModel] executor: Executor billing_unit: BillingUnit | None + docs_url: str | None = None diff --git a/surfsense_backend/app/capabilities/reddit/scrape/definition.py b/surfsense_backend/app/capabilities/reddit/scrape/definition.py index 01fb6db5f..fe00a77be 100644 --- a/surfsense_backend/app/capabilities/reddit/scrape/definition.py +++ b/surfsense_backend/app/capabilities/reddit/scrape/definition.py @@ -10,16 +10,14 @@ from app.capabilities.reddit.scrape.schemas import ScrapeInput, ScrapeOutput REDDIT_SCRAPE = Capability( name="reddit.scrape", description=( - "Scrape public Reddit data. Give it Reddit URLs (post, subreddit, or " - "user) and/or search terms, and it returns structured items — posts " - "(title, body, score, comment count, subreddit, author), their comments, " - "and community/user metadata. Use search_queries (optionally scoped to a " - "community) to discover posts, or urls to pull a known post/subreddit/user." + "Scrape public Reddit posts, comments, and metadata. Use urls or " + "search_queries." ), input_schema=ScrapeInput, output_schema=ScrapeOutput, executor=build_scrape_executor(), billing_unit=BillingUnit.REDDIT_ITEM, + docs_url="/docs/connectors/native/reddit", ) register_capability(REDDIT_SCRAPE) diff --git a/surfsense_web/app/dashboard/[workspace_id]/playground/components/api-reference.tsx b/surfsense_web/app/dashboard/[workspace_id]/playground/components/api-reference.tsx index caf7cf9eb..beed5d525 100644 --- a/surfsense_web/app/dashboard/[workspace_id]/playground/components/api-reference.tsx +++ b/surfsense_web/app/dashboard/[workspace_id]/playground/components/api-reference.tsx @@ -22,10 +22,10 @@ function CopyButton({ text }: { text: string }) { variant="ghost" size="sm" onClick={copy} - className="absolute right-2 top-2 h-7 gap-1.5 px-2 text-xs" + aria-label={copied ? "Copied" : "Copy"} + className="absolute right-2 top-2 h-7 w-7 p-0" > {copied ? : } - {copied ? "Copied" : "Copy"} ); } @@ -91,11 +91,7 @@ export function ApiReference({

API reference

- Call this API from your own project. Create a key in{" "} - User settings and enable API access - for this workspace, then send it as a{" "} - Authorization: Bearer{" "} - header. + Create an API key, enable API access for this workspace, then use the examples below to call this endpoint.

diff --git a/surfsense_web/app/dashboard/[workspace_id]/playground/components/output-viewer.tsx b/surfsense_web/app/dashboard/[workspace_id]/playground/components/output-viewer.tsx index 606548e14..e692734d3 100644 --- a/surfsense_web/app/dashboard/[workspace_id]/playground/components/output-viewer.tsx +++ b/surfsense_web/app/dashboard/[workspace_id]/playground/components/output-viewer.tsx @@ -3,6 +3,7 @@ import { Check, Copy, Download } from "lucide-react"; import { useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; +import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Table, TableBody, @@ -12,7 +13,6 @@ import { TableRow, } from "@/components/ui/table"; import { downloadCsv, rowsToCsv } from "@/lib/playground/csv"; -import { cn } from "@/lib/utils"; const MAX_TABLE_ROWS = 200; @@ -109,34 +109,12 @@ export function OutputViewer({ data, filenameBase }: { data: unknown; filenameBa return (
-
- {items && ( - - )} - -
+ setView(value as "table" | "json")}> + + {items && Table} + JSON + +
{items && items.length > 0 && (
@@ -168,7 +152,7 @@ export function OutputViewer({ data, filenameBase }: { data: unknown; filenameBa {truncated && (

- Showing first {MAX_TABLE_ROWS} of {items.length} items. Use Copy JSON for the full + Showing first {MAX_TABLE_ROWS} of {items.length} items. Switch to JSON for the full output.

)} diff --git a/surfsense_web/app/dashboard/[workspace_id]/playground/components/playground-runner.tsx b/surfsense_web/app/dashboard/[workspace_id]/playground/components/playground-runner.tsx index d80af42f6..030c7c933 100644 --- a/surfsense_web/app/dashboard/[workspace_id]/playground/components/playground-runner.tsx +++ b/surfsense_web/app/dashboard/[workspace_id]/playground/components/playground-runner.tsx @@ -2,15 +2,13 @@ import { Check, - Coins, Copy, Hash, Info, - Loader2, - Play, + Coins, Timer, - X, } from "lucide-react"; +import Link from "next/link"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { toast } from "sonner"; import { Alert, AlertDescription } from "@/components/ui/alert"; @@ -235,7 +233,21 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn -

{capability.description}

+

+ {capability.description} + {capability.docs_url ? ( + <> + {" "} + + Read docs + + . + + ) : null} +

)} @@ -243,8 +255,8 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn
-
- +
+ Pricing: {formatPricing(capability.pricing)} @@ -258,17 +270,12 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn />
- {isRunning && ( - )} diff --git a/surfsense_web/app/dashboard/[workspace_id]/playground/layout-shell.tsx b/surfsense_web/app/dashboard/[workspace_id]/playground/layout-shell.tsx index e17a9a584..59b8ad50b 100644 --- a/surfsense_web/app/dashboard/[workspace_id]/playground/layout-shell.tsx +++ b/surfsense_web/app/dashboard/[workspace_id]/playground/layout-shell.tsx @@ -90,6 +90,6 @@ function getSelectedLabel( const group = groups.find((item) => item.items.some((child) => child.value === activeValue)); const child = group?.items.find((item) => item.value === activeValue); - if (group && child) return `${group.label} / ${child.label}`; + if (group && child) return `${group.label}: ${child.label}`; return "API Playground"; } diff --git a/surfsense_web/components/ui/tabs.tsx b/surfsense_web/components/ui/tabs.tsx index 5dbfc4bc5..693e246f4 100644 --- a/surfsense_web/components/ui/tabs.tsx +++ b/surfsense_web/components/ui/tabs.tsx @@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<