diff --git a/src/agent_env/explorer/app.py b/src/agent_env/explorer/app.py index 7e175a46..a2bdcd0b 100644 --- a/src/agent_env/explorer/app.py +++ b/src/agent_env/explorer/app.py @@ -196,11 +196,11 @@ async def _not_found(request, exc: NotFoundError): # The five (id, version) collections behind Task/Env/Agent/Universe/Evals Hub. # Universes Hub reads /artifacts?type=environment_universe — no route of its own. - app.include_router(versioned_router(prefix=f"{API}/artifacts", tag="artifacts", collection="artifacts")) - app.include_router(versioned_router(prefix=f"{API}/envs", tag="envs", collection="envs")) - app.include_router(versioned_router(prefix=f"{API}/tasks", tag="tasks", collection="tasks")) - app.include_router(versioned_router(prefix=f"{API}/agents", tag="agents", collection="a2a_agents")) - app.include_router(versioned_router(prefix=f"{API}/evals", tag="evals", collection="evals")) + app.include_router(versioned_router(prefix=f"{API}/artifacts", tag="artifacts", collection="artifacts", noun="artifact")) + app.include_router(versioned_router(prefix=f"{API}/envs", tag="envs", collection="envs", noun="environment")) + app.include_router(versioned_router(prefix=f"{API}/tasks", tag="tasks", collection="tasks", noun="task")) + app.include_router(versioned_router(prefix=f"{API}/agents", tag="agents", collection="a2a_agents", noun="agent")) + app.include_router(versioned_router(prefix=f"{API}/evals", tag="evals", collection="evals", noun="eval")) app.include_router(runs_router.router) app.include_router(objects_router.router) app.include_router(conversations_router.router) @@ -224,12 +224,12 @@ def _health() -> dict: "runner": get_runner().type, } - app.get("/health")(_health) + app.get("/health", summary="Health")(_health) static = static_dir or settings["static_dir"] or packaged_ui_dir() if not (static and Path(static).is_dir()): # Serve health at "/" only when no UI is mounted (else the SPA owns "/"). - app.get("/")(_health) + app.get("/", include_in_schema=False)(_health) if static and Path(static).is_dir(): _mount_spa(app, Path(static)) diff --git a/src/agent_env/explorer/openapi_docs.py b/src/agent_env/explorer/openapi_docs.py index 385cb860..71a6bb60 100644 --- a/src/agent_env/explorer/openapi_docs.py +++ b/src/agent_env/explorer/openapi_docs.py @@ -207,9 +207,9 @@ def enrich_openapi_schema(schema: dict[str, Any]) -> dict[str, Any]: "this install — including any added through .agentenv/config.toml." ), "counts": { - "artifacts": len(primitives["artifacts"]), - "envs": len(primitives["envs"]), - "taskSteps": len(primitives["taskSteps"]), + "artifactTypes": len(primitives["artifacts"]), + "envTypes": len(primitives["envs"]), + "taskStepTypes": len(primitives["taskSteps"]), "operations": sum( 1 for ops in (schema.get("paths") or {}).values() diff --git a/src/agent_env/explorer/routers/common.py b/src/agent_env/explorer/routers/common.py index 007446ba..4993743d 100644 --- a/src/agent_env/explorer/routers/common.py +++ b/src/agent_env/explorer/routers/common.py @@ -100,13 +100,15 @@ def versioned_router( prefix: str, tag: str, collection: str, + noun: str, id_field: str = "id", ) -> APIRouter: """List / get / versions over one ``(id, version)`` collection (artifacts, envs, tasks, - agents, evals).""" + agents, evals). ``noun`` names the entity in each route's summary, which the Docs nav + lists without its path.""" router = APIRouter(prefix=prefix, tags=[tag]) - @router.get("", response_model=PaginatedResponse) + @router.get("", response_model=PaginatedResponse, summary=f"List {noun.title()}s") def list_items( limit: int = Query(50, ge=1, le=500), offset: int = Query(0, ge=0), @@ -147,7 +149,7 @@ def list_items( has_more=offset + len(items) < total, ) - @router.get("/{entity_id}") + @router.get("/{entity_id}", summary=f"Get {noun.title()}") def get_item(entity_id: str, version: Optional[int] = None) -> dict: store = docs() if version is not None: @@ -159,7 +161,7 @@ def get_item(entity_id: str, version: Optional[int] = None) -> dict: raise HTTPException(status_code=404, detail=f"{tag} {entity_id} not found") return _enrich_universe(doc, store, collection) - @router.get("/{entity_id}/versions") + @router.get("/{entity_id}/versions", summary=f"List {noun.title()} Versions") def list_versions( entity_id: str, limit: int = Query(100, ge=1, le=500), diff --git a/src/agent_env/explorer/ui/public/android-chrome-192x192.png b/src/agent_env/explorer/ui/public/android-chrome-192x192.png index 3cce1369..ebb7a455 100644 Binary files a/src/agent_env/explorer/ui/public/android-chrome-192x192.png and b/src/agent_env/explorer/ui/public/android-chrome-192x192.png differ diff --git a/src/agent_env/explorer/ui/public/android-chrome-512x512.png b/src/agent_env/explorer/ui/public/android-chrome-512x512.png index 869f1925..65fb1b84 100644 Binary files a/src/agent_env/explorer/ui/public/android-chrome-512x512.png and b/src/agent_env/explorer/ui/public/android-chrome-512x512.png differ diff --git a/src/agent_env/explorer/ui/public/apple-touch-icon.png b/src/agent_env/explorer/ui/public/apple-touch-icon.png index ee622467..93c7e393 100644 Binary files a/src/agent_env/explorer/ui/public/apple-touch-icon.png and b/src/agent_env/explorer/ui/public/apple-touch-icon.png differ diff --git a/src/agent_env/explorer/ui/public/favicon.ico b/src/agent_env/explorer/ui/public/favicon.ico index 051d01a1..9a0319b7 100644 Binary files a/src/agent_env/explorer/ui/public/favicon.ico and b/src/agent_env/explorer/ui/public/favicon.ico differ diff --git a/src/agent_env/explorer/ui/public/favicon.svg b/src/agent_env/explorer/ui/public/favicon.svg index a66ba8d3..b58dce47 100644 --- a/src/agent_env/explorer/ui/public/favicon.svg +++ b/src/agent_env/explorer/ui/public/favicon.svg @@ -1,11 +1 @@ - - - - - + \ No newline at end of file diff --git a/src/agent_env/explorer/ui/public/logos/agent-env-logo.svg b/src/agent_env/explorer/ui/public/logos/agent-env-logo.svg deleted file mode 100644 index 4cee40cb..00000000 --- a/src/agent_env/explorer/ui/public/logos/agent-env-logo.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/agent_env/explorer/ui/public/logos/agentenv-icon.svg b/src/agent_env/explorer/ui/public/logos/agentenv-icon.svg new file mode 100644 index 00000000..8cd4280b --- /dev/null +++ b/src/agent_env/explorer/ui/public/logos/agentenv-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/agent_env/explorer/ui/public/logos/scale-logo.svg b/src/agent_env/explorer/ui/public/logos/scale-logo.svg new file mode 100644 index 00000000..05c566de --- /dev/null +++ b/src/agent_env/explorer/ui/public/logos/scale-logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/agent_env/explorer/ui/public/site.webmanifest b/src/agent_env/explorer/ui/public/site.webmanifest index cf2d9c73..798399c2 100644 --- a/src/agent_env/explorer/ui/public/site.webmanifest +++ b/src/agent_env/explorer/ui/public/site.webmanifest @@ -1 +1 @@ -{"name":"AgentEnvExplorer","short_name":"AgentEnvExplorer","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} +{"name":"AgentEnv Explorer","short_name":"AgentEnv Explorer","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} diff --git a/src/agent_env/explorer/ui/src/components/docs-page.tsx b/src/agent_env/explorer/ui/src/components/docs-page.tsx index 2e69070b..3699f495 100644 --- a/src/agent_env/explorer/ui/src/components/docs-page.tsx +++ b/src/agent_env/explorer/ui/src/components/docs-page.tsx @@ -1,7 +1,7 @@ import { Fragment, useEffect, useMemo, useState } from 'react'; import type { CSSProperties, ReactNode } from 'react'; import { Code2, FileJson, Search, Server, Shapes } from 'lucide-react'; -import { apiFetch, BACKEND_URL } from './shared'; +import { apiFetch, BACKEND_URL, FRAMEWORK_DOCS_URL } from './shared'; type JsonSchema = Record; @@ -115,9 +115,9 @@ const METHOD_CLASS: Record = { const PRIMITIVE_GROUPS: PrimitiveGroup[] = ['artifacts', 'envs', 'taskSteps']; const PRIMITIVE_LABEL: Record = { - artifacts: 'Artifacts', - envs: 'Environments', - taskSteps: 'Task Steps', + artifacts: 'Artifact Types', + envs: 'Environment Types', + taskSteps: 'Task Step Types', }; const ENDPOINT_NAV_LIMIT = 120; @@ -431,7 +431,7 @@ function OverviewPane({

- {spec.info?.title ?? 'AgentEnvExplorer API'} + {spec.info?.title ?? 'AgentEnv Explorer API'}

Version {spec.info?.version ?? 'unknown'} @@ -450,6 +450,19 @@ function OverviewPane({ {spec.info.description}

)} +

+ This page is the explorer's API reference. For guides to + environments, artifacts, agents, tasks and plugins, see the{' '} + + AgentEnv Framework docs + + . +

diff --git a/src/agent_env/explorer/ui/src/components/shared.tsx b/src/agent_env/explorer/ui/src/components/shared.tsx index f98d4fbe..4b051997 100644 --- a/src/agent_env/explorer/ui/src/components/shared.tsx +++ b/src/agent_env/explorer/ui/src/components/shared.tsx @@ -6,6 +6,8 @@ import Link from 'next/link'; * `/undefined/api/v1/...` — and the catch-all answers 200 text/html, so it fails quietly. */ export const BACKEND_URL = process.env.NEXT_PUBLIC_AGENT_ENV_HUB_BACKEND_URL ?? ''; +export const FRAMEWORK_DOCS_URL = 'https://www.agentenvframework.com/docs'; + export function apiFetch(input: string, init?: RequestInit): Promise { const headers = new Headers(init?.headers); headers.set('x-agent-env-client', 'agent-env-explorer'); diff --git a/src/agent_env/explorer/ui/src/pages/[[...slug]].tsx b/src/agent_env/explorer/ui/src/pages/[[...slug]].tsx index 354aae61..3698e3d6 100644 --- a/src/agent_env/explorer/ui/src/pages/[[...slug]].tsx +++ b/src/agent_env/explorer/ui/src/pages/[[...slug]].tsx @@ -19,8 +19,14 @@ import { Package, PanelLeftClose, PanelLeftOpen, + ExternalLink, } from 'lucide-react'; -import { type Page, type NavGroup, pageToPath } from '../components/shared'; +import { + type Page, + type NavGroup, + pageToPath, + FRAMEWORK_DOCS_URL, +} from '../components/shared'; import { HomePage } from '../components/home-page'; import { EnvironmentsPage } from '../components/environments-page'; import { EnvDetailPage } from '../components/env-detail-page'; @@ -290,13 +296,39 @@ export default function App() { sidebarOpen ? 'px-5' : 'justify-center' } py-5`} > - {sidebarOpen && ( + {sidebarOpen ? ( +
+
+ + + AgentEnv Explorer + +
+
+ Built by + Scale +
+
+ ) : ( AgentEnvExplorer )} @@ -356,9 +388,21 @@ export default function App() {
+ + + {sidebarOpen && 'Framework docs'} +