@vertesia/tools-admin-ui 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +120 -0
  3. package/lib/AdminApp.d.ts +13 -0
  4. package/lib/AdminApp.d.ts.map +1 -0
  5. package/lib/AdminContext.d.ts +10 -0
  6. package/lib/AdminContext.d.ts.map +1 -0
  7. package/lib/components/CollectionCard.d.ts +5 -0
  8. package/lib/components/CollectionCard.d.ts.map +1 -0
  9. package/lib/components/DetailPage.d.ts +13 -0
  10. package/lib/components/DetailPage.d.ts.map +1 -0
  11. package/lib/components/EndpointPanel.d.ts +5 -0
  12. package/lib/components/EndpointPanel.d.ts.map +1 -0
  13. package/lib/components/HeroSection.d.ts +9 -0
  14. package/lib/components/HeroSection.d.ts.map +1 -0
  15. package/lib/components/ResourceCard.d.ts +5 -0
  16. package/lib/components/ResourceCard.d.ts.map +1 -0
  17. package/lib/components/ResourceSection.d.ts +10 -0
  18. package/lib/components/ResourceSection.d.ts.map +1 -0
  19. package/lib/components/SearchBar.d.ts +10 -0
  20. package/lib/components/SearchBar.d.ts.map +1 -0
  21. package/lib/components/SummaryBadge.d.ts +5 -0
  22. package/lib/components/SummaryBadge.d.ts.map +1 -0
  23. package/lib/components/index.d.ts +9 -0
  24. package/lib/components/index.d.ts.map +1 -0
  25. package/lib/hooks.d.ts +26 -0
  26. package/lib/hooks.d.ts.map +1 -0
  27. package/lib/index.d.ts +7 -0
  28. package/lib/index.d.ts.map +1 -0
  29. package/lib/pages/HomePage.d.ts +2 -0
  30. package/lib/pages/HomePage.d.ts.map +1 -0
  31. package/lib/pages/InteractionCollection.d.ts +2 -0
  32. package/lib/pages/InteractionCollection.d.ts.map +1 -0
  33. package/lib/pages/InteractionDetail.d.ts +2 -0
  34. package/lib/pages/InteractionDetail.d.ts.map +1 -0
  35. package/lib/pages/SkillCollection.d.ts +2 -0
  36. package/lib/pages/SkillCollection.d.ts.map +1 -0
  37. package/lib/pages/SkillDetail.d.ts +2 -0
  38. package/lib/pages/SkillDetail.d.ts.map +1 -0
  39. package/lib/pages/TemplateCollection.d.ts +2 -0
  40. package/lib/pages/TemplateCollection.d.ts.map +1 -0
  41. package/lib/pages/TemplateDetail.d.ts +2 -0
  42. package/lib/pages/TemplateDetail.d.ts.map +1 -0
  43. package/lib/pages/ToolCollection.d.ts +2 -0
  44. package/lib/pages/ToolCollection.d.ts.map +1 -0
  45. package/lib/pages/TypeCollection.d.ts +2 -0
  46. package/lib/pages/TypeCollection.d.ts.map +1 -0
  47. package/lib/pages/TypeDetail.d.ts +2 -0
  48. package/lib/pages/TypeDetail.d.ts.map +1 -0
  49. package/lib/tools-admin-ui.js +935 -0
  50. package/lib/tools-admin-ui.js.map +1 -0
  51. package/lib/types.d.ts +89 -0
  52. package/lib/types.d.ts.map +1 -0
  53. package/package.json +50 -0
  54. package/src/AdminApp.tsx +87 -0
  55. package/src/AdminContext.ts +17 -0
  56. package/src/admin.css +650 -0
  57. package/src/components/CollectionCard.tsx +23 -0
  58. package/src/components/DetailPage.tsx +40 -0
  59. package/src/components/EndpointPanel.tsx +24 -0
  60. package/src/components/HeroSection.tsx +88 -0
  61. package/src/components/ResourceCard.tsx +25 -0
  62. package/src/components/ResourceSection.tsx +31 -0
  63. package/src/components/SearchBar.tsx +35 -0
  64. package/src/components/SummaryBadge.tsx +9 -0
  65. package/src/components/index.ts +8 -0
  66. package/src/dev/env.ts +14 -0
  67. package/src/dev/main.tsx +37 -0
  68. package/src/hooks.ts +36 -0
  69. package/src/index.ts +6 -0
  70. package/src/pages/HomePage.tsx +99 -0
  71. package/src/pages/InteractionCollection.tsx +59 -0
  72. package/src/pages/InteractionDetail.tsx +92 -0
  73. package/src/pages/SkillCollection.tsx +111 -0
  74. package/src/pages/SkillDetail.tsx +112 -0
  75. package/src/pages/TemplateCollection.tsx +54 -0
  76. package/src/pages/TemplateDetail.tsx +68 -0
  77. package/src/pages/ToolCollection.tsx +55 -0
  78. package/src/pages/TypeCollection.tsx +60 -0
  79. package/src/pages/TypeDetail.tsx +63 -0
  80. package/src/types.ts +304 -0
  81. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools-admin-ui.js","sources":["../src/types.ts","../src/hooks.ts","../src/AdminContext.ts","../src/components/EndpointPanel.tsx","../src/components/SummaryBadge.tsx","../src/components/HeroSection.tsx","../src/components/SearchBar.tsx","../src/components/ResourceCard.tsx","../src/components/ResourceSection.tsx","../src/components/CollectionCard.tsx","../src/components/DetailPage.tsx","../src/pages/HomePage.tsx","../src/pages/InteractionCollection.tsx","../src/pages/InteractionDetail.tsx","../src/pages/ToolCollection.tsx","../src/pages/SkillCollection.tsx","../src/pages/SkillDetail.tsx","../src/pages/TypeCollection.tsx","../src/pages/TypeDetail.tsx","../src/pages/TemplateCollection.tsx","../src/pages/TemplateDetail.tsx","../src/AdminApp.tsx"],"sourcesContent":["/**\n * Types for the admin panel\n */\n\nimport type {\n AgentToolDefinition,\n CatalogInteractionRef,\n InCodeTypeDefinition,\n RenderingTemplateDefinitionRef,\n} from '@vertesia/common';\n\n/**\n * Server info from GET /api\n */\nexport interface ServerInfo {\n message: string;\n version: string;\n endpoints: {\n tools: string[];\n interactions: string[];\n templates: string[];\n mcp: string[];\n };\n}\n\nexport type ResourceType = 'tool' | 'skill' | 'interaction' | 'type' | 'template' | 'mcp';\n\n/**\n * A normalized resource entry for display and search.\n */\nexport interface ResourceItem {\n /** Unique identifier used for fetching details (e.g. \"collection:name\" for interactions). */\n id?: string;\n name: string;\n title: string;\n description: string;\n type: ResourceType;\n tags?: string[];\n url?: string;\n}\n\n/**\n * Metadata about a collection of resources, enriched with type and count client-side.\n */\nexport interface CollectionInfo {\n name: string;\n title: string;\n description: string;\n type: ResourceType;\n count: number;\n}\n\n/**\n * Collection metadata as returned by each API endpoint.\n */\ninterface CollectionMeta {\n name: string;\n title?: string;\n description?: string;\n}\n\n/**\n * Response shapes for each resource endpoint.\n */\ninterface InteractionsResponse {\n interactions: CatalogInteractionRef[];\n collections: CollectionMeta[];\n}\n\ninterface ToolsResponse {\n tools: AgentToolDefinition[];\n collections: CollectionMeta[];\n}\n\ninterface SkillsResponse {\n tools: AgentToolDefinition[];\n collections: CollectionMeta[];\n}\n\ninterface TypesResponse {\n types: InCodeTypeDefinition[];\n collections: CollectionMeta[];\n}\n\ninterface TemplatesResponse {\n templates: RenderingTemplateDefinitionRef[];\n collections: CollectionMeta[];\n}\n\n/**\n * Combined result of processing all endpoint responses.\n */\nexport interface ResourceData {\n collections: CollectionInfo[];\n resources: ResourceItem[];\n}\n\n/**\n * Formats a kebab/snake-case name into a title.\n */\nfunction formatTitle(name: string): string {\n return name.replace(/[-_]/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase());\n}\n\n/**\n * Counts items per collection by matching each item to a collection name.\n * If there is only one collection, all items belong to it.\n */\nfunction countPerCollection<T>(\n items: T[],\n collections: CollectionMeta[],\n extractCollection: (item: T) => string | undefined,\n): Map<string, number> {\n const counts = new Map<string, number>();\n for (const col of collections) counts.set(col.name, 0);\n\n if (collections.length === 1) {\n counts.set(collections[0].name, items.length);\n return counts;\n }\n\n for (const item of items) {\n const colName = extractCollection(item);\n if (colName && counts.has(colName)) {\n counts.set(colName, (counts.get(colName) || 0) + 1);\n }\n }\n\n return counts;\n}\n\n/**\n * Builds collections and a flat resource list from the 5 endpoint responses + MCP endpoints.\n */\nexport function buildResourceData(\n interactionsResp: InteractionsResponse,\n toolsResp: ToolsResponse,\n skillsResp: SkillsResponse,\n typesResp: TypesResponse,\n templatesResp: TemplatesResponse,\n mcpEndpoints?: string[],\n): ResourceData {\n const collections: CollectionInfo[] = [];\n const resources: ResourceItem[] = [];\n\n // --- Interactions (id format: \"collection:name\") ---\n const interCounts = countPerCollection(\n interactionsResp.interactions,\n interactionsResp.collections,\n (i) => i.id.split(':')[0],\n );\n for (const col of interactionsResp.collections) {\n collections.push({\n name: col.name,\n title: col.title || formatTitle(col.name),\n description: col.description || '',\n type: 'interaction',\n count: interCounts.get(col.name) || 0,\n });\n }\n for (const inter of interactionsResp.interactions) {\n resources.push({\n id: inter.id,\n name: inter.name,\n title: inter.title || formatTitle(inter.name),\n description: inter.description || '',\n type: 'interaction',\n tags: inter.tags,\n });\n }\n\n // --- Tools (url format: \"tools/{collection}\") ---\n const toolCounts = countPerCollection(\n toolsResp.tools,\n toolsResp.collections,\n (t) => t.url?.split('/').pop(),\n );\n for (const col of toolsResp.collections) {\n collections.push({\n name: col.name,\n title: col.title || formatTitle(col.name),\n description: col.description || '',\n type: 'tool',\n count: toolCounts.get(col.name) || 0,\n });\n }\n for (const tool of toolsResp.tools) {\n resources.push({\n name: tool.name,\n title: formatTitle(tool.name),\n description: tool.description || '',\n type: 'tool',\n url: tool.url,\n });\n }\n\n // --- Skills (url format: \"skills/{collection}\") ---\n const skillCounts = countPerCollection(\n skillsResp.tools,\n skillsResp.collections,\n (t) => t.url?.split('/').pop(),\n );\n for (const col of skillsResp.collections) {\n collections.push({\n name: col.name,\n title: col.title || formatTitle(col.name),\n description: col.description || '',\n type: 'skill',\n count: skillCounts.get(col.name) || 0,\n });\n }\n for (const skill of skillsResp.tools) {\n resources.push({\n name: skill.name,\n title: formatTitle(skill.name),\n description: skill.description || '',\n type: 'skill',\n url: skill.url,\n });\n }\n\n // --- Types (id format: \"collection:pathName\") ---\n const typeCounts = countPerCollection(\n typesResp.types,\n typesResp.collections,\n (t) => t.id?.split(':')[0],\n );\n for (const col of typesResp.collections) {\n collections.push({\n name: col.name,\n title: col.title || formatTitle(col.name),\n description: col.description || '',\n type: 'type',\n count: typeCounts.get(col.name) || 0,\n });\n }\n for (const t of typesResp.types) {\n resources.push({\n name: t.name,\n title: formatTitle(t.name),\n description: t.description || '',\n type: 'type',\n tags: t.tags,\n });\n }\n\n // --- Templates (path format: \"/api/templates/{collection}/{name}\") ---\n const tmplCounts = countPerCollection(\n templatesResp.templates,\n templatesResp.collections,\n (t) => {\n const segments = t.path?.split('/');\n return segments && segments.length >= 4 ? segments[3] : undefined;\n },\n );\n for (const col of templatesResp.collections) {\n collections.push({\n name: col.name,\n title: col.title || formatTitle(col.name),\n description: col.description || '',\n type: 'template',\n count: tmplCounts.get(col.name) || 0,\n });\n }\n for (const tmpl of templatesResp.templates) {\n resources.push({\n name: tmpl.name,\n title: tmpl.title || formatTitle(tmpl.name),\n description: tmpl.description || '',\n type: 'template',\n tags: tmpl.tags,\n url: tmpl.path,\n });\n }\n\n // --- MCP (derived from serverInfo, no endpoint) ---\n for (const endpoint of mcpEndpoints || []) {\n const name = endpoint.split('/').pop() || endpoint;\n resources.push({\n name,\n title: formatTitle(name),\n description: '',\n type: 'mcp',\n url: endpoint,\n });\n }\n\n return { collections, resources };\n}\n\n/**\n * Filters resources by a search query, matching against name, title, description, type, and tags.\n */\nexport function filterResources(items: ResourceItem[], query: string): ResourceItem[] {\n const q = query.toLowerCase().trim();\n if (!q) return items;\n return items.filter(item =>\n item.name.toLowerCase().includes(q) ||\n item.title.toLowerCase().includes(q) ||\n item.description.toLowerCase().includes(q) ||\n item.type.includes(q) ||\n item.tags?.some(t => t.toLowerCase().includes(q))\n );\n}\n","/**\n * Data fetching hooks for the admin panel.\n */\n\nimport { useFetch } from '@vertesia/ui/core';\nimport type { ServerInfo, ResourceData } from './types.js';\nimport { buildResourceData } from './types.js';\n\n/**\n * Fetches the tool server info (message, version, endpoints).\n */\nexport function useServerInfo(baseUrl: string) {\n return useFetch<ServerInfo>(() =>\n fetch(baseUrl).then(r => r.json()),\n [baseUrl]\n );\n}\n\n/**\n * Fetches all 5 resource endpoints in parallel and builds collections + flat resource list.\n * MCP endpoints are passed separately since they come from serverInfo.\n */\nexport function useResourceData(baseUrl: string, mcpEndpoints?: string[]) {\n return useFetch<ResourceData>(() => {\n const fetchJson = (path: string) => fetch(`${baseUrl}/${path}`).then(r => r.json());\n return Promise.all([\n fetchJson('interactions'),\n fetchJson('tools'),\n fetchJson('skills'),\n fetchJson('types'),\n fetchJson('templates'),\n ]).then(([interactions, tools, skills, types, templates]) =>\n buildResourceData(interactions, tools, skills, types, templates, mcpEndpoints)\n );\n }, [baseUrl, mcpEndpoints]);\n}\n","import { createContext, useContext } from 'react';\nimport type { CollectionInfo, ResourceItem, ServerInfo } from './types.js';\n\nexport interface AdminContextValue {\n serverInfo: ServerInfo;\n collections: CollectionInfo[];\n resources: ResourceItem[];\n baseUrl: string;\n}\n\nexport const AdminContext = createContext<AdminContextValue | undefined>(undefined);\n\nexport function useAdminContext(): AdminContextValue {\n const ctx = useContext(AdminContext);\n if (!ctx) throw new Error('useAdminContext must be used within AdminApp');\n return ctx;\n}\n","import { useState } from 'react';\n\nexport function EndpointPanel({ label, path }: { label: string; path: string }) {\n const [copied, setCopied] = useState(false);\n\n function handleCopy() {\n const url = window.location.origin + path;\n navigator.clipboard.writeText(url);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n }\n\n return (\n <div className=\"vta-endpoint\">\n <div className=\"vta-endpoint-label\">{label}</div>\n <div className=\"vta-endpoint-box\">\n <code className=\"vta-endpoint-code\">{path}</code>\n <button onClick={handleCopy} className=\"vta-copy-btn\" title=\"Copy full URL\">\n {copied ? '\\u2713' : '\\u29C9'}\n </button>\n </div>\n </div>\n );\n}\n","export function SummaryBadge({ count, label }: { count: number; label: string }) {\n if (count === 0) return null;\n return (\n <span className=\"vta-badge\">\n <span className=\"vta-badge-dot\" />\n {count} {label}{count !== 1 ? 's' : ''}\n </span>\n );\n}\n","import type { ResourceItem, ResourceType } from '../types.js';\nimport { EndpointPanel } from './EndpointPanel.js';\nimport { SummaryBadge } from './SummaryBadge.js';\n\ninterface HeroSectionProps {\n title: string;\n version: string;\n resources: ResourceItem[];\n}\n\nfunction getInitials(title: string): string {\n return title.split(/\\s+/).map(w => w[0]).filter(Boolean).slice(0, 2).join('').toUpperCase();\n}\n\nfunction countByType(resources: ResourceItem[]): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const r of resources) {\n counts[r.type] = (counts[r.type] || 0) + 1;\n }\n return counts;\n}\n\nconst badgeLabels: { type: ResourceType; label: string }[] = [\n { type: 'tool', label: 'tool' },\n { type: 'skill', label: 'skill' },\n { type: 'interaction', label: 'interaction' },\n { type: 'type', label: 'content type' },\n { type: 'template', label: 'template' },\n { type: 'mcp', label: 'MCP provider' },\n];\n\nexport function HeroSection({ title, version, resources }: HeroSectionProps) {\n const counts = countByType(resources);\n\n return (\n <header className=\"vta-hero\">\n <div className=\"vta-hero-main\">\n <div className=\"vta-hero-identity\">\n <div className=\"vta-hero-logo\">\n {getInitials(title)}\n </div>\n <div>\n <p className=\"vta-hero-eyebrow\">Tools Server</p>\n <h1 className=\"vta-hero-title\">{title}</h1>\n </div>\n </div>\n\n <p className=\"vta-hero-tagline\">\n Discover the tools, skills, interactions, and content types exposed by this server.\n </p>\n\n <div className=\"vta-hero-summary\">\n {badgeLabels.map(({ type, label }) => (\n <SummaryBadge key={type} count={counts[type] || 0} label={label} />\n ))}\n </div>\n\n <div className=\"vta-hero-links\">\n <a href=\"/app/\" target=\"_blank\" className=\"vta-link-primary\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n <line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" />\n </svg>\n UI Plugin Dev\n </a>\n <a href=\"/lib/plugin.js\" className=\"vta-link-secondary\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"7 10 12 15 17 10\" />\n <line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" />\n </svg>\n Plugin Bundle\n </a>\n </div>\n </div>\n\n <aside className=\"vta-hero-panel\">\n <EndpointPanel label=\"Base endpoint\" path=\"/api\" />\n <EndpointPanel label=\"Package endpoint\" path=\"/api/package\" />\n <p className=\"vta-hero-hint\">\n Use <strong>POST /api/tools/&lt;collection&gt;</strong> or{' '}\n <strong>POST /api/skills/&lt;collection&gt;</strong> to call these from your apps or agents.\n </p>\n <p className=\"vta-hero-version\">v{version}</p>\n </aside>\n </header>\n );\n}\n","interface SearchBarProps {\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n resultCount?: number;\n totalCount?: number;\n}\n\nexport function SearchBar({ value, onChange, placeholder, resultCount, totalCount }: SearchBarProps) {\n const hasQuery = value.trim().length > 0;\n const noResults = hasQuery && resultCount === 0;\n\n return (\n <div className=\"vta-search\">\n <input\n type=\"search\"\n value={value}\n onChange={e => onChange(e.target.value)}\n placeholder={placeholder || 'Search collections...'}\n className=\"vta-search-input\"\n autoComplete=\"off\"\n />\n {hasQuery && !noResults && (\n <p className=\"vta-search-hint\">\n Showing {resultCount} of {totalCount} resources\n </p>\n )}\n {noResults && (\n <p className=\"vta-search-empty\">\n No resources match this search.\n </p>\n )}\n </div>\n );\n}\n","import type { ResourceItem } from '../types.js';\n\nexport function ResourceCard({ resource }: { resource: ResourceItem }) {\n return (\n <div className=\"vta-card\">\n <span className={`vta-card-type vta-card-type--${resource.type}`}>\n {resource.type}\n </span>\n <div className=\"vta-card-title\">{resource.title}</div>\n <div className=\"vta-card-desc\">\n {resource.description || 'No description'}\n </div>\n {resource.tags && resource.tags.length > 0 && (\n <div className=\"vta-card-tags\">\n {resource.tags.map(tag => (\n <span key={tag} className=\"vta-tag\">{tag}</span>\n ))}\n </div>\n )}\n {resource.url && (\n <div className=\"vta-card-url\">{resource.url}</div>\n )}\n </div>\n );\n}\n","import type { ResourceItem } from '../types.js';\nimport { ResourceCard } from './ResourceCard.js';\n\ninterface ResourceSectionProps {\n title: string;\n subtitle: string;\n resources: ResourceItem[];\n showDivider?: boolean;\n}\n\nexport function ResourceSection({ title, subtitle, resources, showDivider }: ResourceSectionProps) {\n if (resources.length === 0) return null;\n\n return (\n <section>\n {showDivider && <hr className=\"vta-divider\" />}\n <div>\n <h2 className=\"vta-section-title\">\n {title}\n <span className=\"vta-section-count\">({resources.length})</span>\n </h2>\n <p className=\"vta-section-subtitle\">{subtitle}</p>\n </div>\n <div className=\"vta-card-grid\">\n {resources.map(r => (\n <ResourceCard key={`${r.type}:${r.name}`} resource={r} />\n ))}\n </div>\n </section>\n );\n}\n","import { NavLink } from '@vertesia/ui/router';\nimport type { CollectionInfo } from '../types.js';\n\nexport function CollectionCard({ collection }: { collection: CollectionInfo }) {\n const href = `/${collection.type}s/${collection.name}`;\n\n return (\n <NavLink href={href} className=\"vta-card-link\">\n <div className=\"vta-card vta-card--link\">\n <span className={`vta-card-type vta-card-type--${collection.type}`}>\n {collection.type}\n </span>\n <div className=\"vta-card-title\">{collection.title}</div>\n <div className=\"vta-card-desc\">\n {collection.description || 'No description'}\n </div>\n <div className=\"vta-card-url\">\n {collection.count} {collection.count === 1 ? 'item' : 'items'}\n </div>\n </div>\n </NavLink>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { ResourceType } from '../types.js';\nimport { NavLink } from '@vertesia/ui/router';\n\ninterface DetailPageProps {\n type: ResourceType;\n title: string;\n description?: string;\n tags?: string[];\n backHref?: string;\n children?: ReactNode;\n}\n\nexport function DetailPage({ type, title, description, tags, backHref = '/', children }: DetailPageProps) {\n return (\n <div className=\"vta-root\">\n <nav className=\"vta-detail-nav\">\n {backHref !== '/' && (\n <NavLink href=\"/\" className=\"vta-detail-back\">Home</NavLink>\n )}\n <NavLink href={backHref} className=\"vta-detail-back\">&larr; Back</NavLink>\n </nav>\n\n <div className=\"vta-detail-header\">\n <span className={`vta-card-type vta-card-type--${type}`}>{type}</span>\n <h1 className=\"vta-detail-title\">{title}</h1>\n {description && <p className=\"vta-detail-desc\">{description}</p>}\n {tags && tags.length > 0 && (\n <div className=\"vta-card-tags\">\n {tags.map(tag => (\n <span key={tag} className=\"vta-tag\">{tag}</span>\n ))}\n </div>\n )}\n </div>\n\n {children}\n </div>\n );\n}\n","import { useMemo, useState } from 'react';\nimport type { ResourceType } from '../types.js';\nimport { filterResources } from '../types.js';\nimport { HeroSection, SearchBar, ResourceSection, CollectionCard } from '../components/index.js';\nimport { useAdminContext } from '../AdminContext.js';\n\nconst sections: { type: ResourceType; title: string; subtitle: string }[] = [\n { type: 'tool', title: 'Tools', subtitle: 'Remote tools available to agents via Vertesia.' },\n { type: 'skill', title: 'Skills', subtitle: 'Reusable instructions and scripts packaged as tools.' },\n { type: 'interaction', title: 'Interactions', subtitle: 'Conversation blueprints surfaced in the Vertesia UI.' },\n { type: 'type', title: 'Content Types', subtitle: 'Schema definitions for structured content in the data store.' },\n { type: 'template', title: 'Rendering Templates', subtitle: 'Document and presentation templates for content generation.' },\n { type: 'mcp', title: 'MCP Providers', subtitle: 'Remote MCP servers available through this tools server.' },\n];\n\nexport function HomePage() {\n const { serverInfo, collections, resources } = useAdminContext();\n const [search, setSearch] = useState('');\n\n const filtered = useMemo(() =>\n filterResources(resources, search),\n [resources, search]\n );\n\n const isSearching = search.trim().length > 0;\n\n return (\n <div className=\"vta-root\">\n <HeroSection\n title={serverInfo.message.replace('Vertesia Tools API', 'Tools Server')}\n version={serverInfo.version}\n resources={resources}\n />\n\n <SearchBar\n value={search}\n onChange={setSearch}\n placeholder=\"Search tools, skills, interactions, types, templates...\"\n resultCount={filtered.length}\n totalCount={resources.length}\n />\n\n {isSearching ? (\n /* Search mode: show individual resource cards */\n sections.map((section, i) => {\n const sectionItems = filtered.filter(r => r.type === section.type);\n return (\n <ResourceSection\n key={section.type}\n title={section.title}\n subtitle={section.subtitle}\n resources={sectionItems}\n showDivider={i > 0}\n />\n );\n })\n ) : (\n /* Browse mode: show collection cards grouped by type */\n sections.map((section, i) => {\n const sectionCollections = collections.filter(c => c.type === section.type);\n const mcpResources = section.type === 'mcp'\n ? resources.filter(r => r.type === 'mcp')\n : [];\n\n if (sectionCollections.length === 0 && mcpResources.length === 0) return null;\n\n return (\n <section key={section.type}>\n {i > 0 && <hr className=\"vta-divider\" />}\n <div>\n <h2 className=\"vta-section-title\">\n {section.title}\n <span className=\"vta-section-count\">\n ({sectionCollections.length}{sectionCollections.length === 1\n ? ' collection' : ' collections'})\n </span>\n </h2>\n <p className=\"vta-section-subtitle\">{section.subtitle}</p>\n </div>\n <div className=\"vta-card-grid\">\n {sectionCollections.map(col => (\n <CollectionCard key={`${col.type}:${col.name}`} collection={col} />\n ))}\n {mcpResources.map(r => (\n <div key={r.name} className=\"vta-card\">\n <span className=\"vta-card-type vta-card-type--mcp\">mcp</span>\n <div className=\"vta-card-title\">{r.title}</div>\n <div className=\"vta-card-desc\">{r.description || 'No description'}</div>\n {r.url && <div className=\"vta-card-url\">{r.url}</div>}\n </div>\n ))}\n </div>\n </section>\n );\n })\n )}\n </div>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams, NavLink } from '@vertesia/ui/router';\nimport type { CatalogInteractionRef } from '@vertesia/common';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\nexport function InteractionCollection() {\n const collection = useParams('collection');\n const { baseUrl } = useAdminContext();\n\n const { data: interactions, isLoading, error } = useFetch<CatalogInteractionRef[]>(\n () => fetch(`${baseUrl}/interactions/${collection}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection]\n );\n\n if (isLoading) {\n return <div className=\"vta-loading\">Loading collection...</div>;\n }\n\n if (error || !interactions) {\n return <div className=\"vta-error\">Failed to load collection &ldquo;{collection}&rdquo;.</div>;\n }\n\n return (\n <DetailPage\n type=\"interaction\"\n title={collection}\n description={`${interactions.length} interaction${interactions.length !== 1 ? 's' : ''} in this collection.`}\n >\n <div className=\"vta-card-grid\">\n {interactions.map(inter => (\n <NavLink\n key={inter.id}\n href={`/interactions/${collection}/${inter.name}`}\n className=\"vta-card-link\"\n >\n <div className=\"vta-card vta-card--link\">\n <span className=\"vta-card-type vta-card-type--interaction\">interaction</span>\n <div className=\"vta-card-title\">{inter.title || inter.name}</div>\n <div className=\"vta-card-desc\">\n {inter.description || 'No description'}\n </div>\n {inter.tags && inter.tags.length > 0 && (\n <div className=\"vta-card-tags\">\n {inter.tags.map(tag => (\n <span key={tag} className=\"vta-tag\">{tag}</span>\n ))}\n </div>\n )}\n </div>\n </NavLink>\n ))}\n </div>\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams } from '@vertesia/ui/router';\nimport type { InteractionSpec } from '@vertesia/common';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\nimport { useUserSession } from '@vertesia/ui/session';\n\ntype InteractionResponse = InteractionSpec & { id: string };\n\nexport function InteractionDetail() {\n const { client } = useUserSession();\n const params = useParams();\n const collection = params.collection;\n const name = params.name;\n const { baseUrl } = useAdminContext();\n\n const { data: interaction, isLoading, error } = useFetch<InteractionResponse>(\n () => client.getRawJWT().then(token => fetch(`${baseUrl}/interactions/${collection}/${name}`, {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })).then(r => {\n if (!r.ok) throw new Error(`Failed to load interaction: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection, name]\n );\n\n if (isLoading) {\n return <div className=\"vta-loading\">Loading interaction...</div>;\n }\n\n if (error || !interaction) {\n return <div className=\"vta-error\">Failed to load interaction &ldquo;{name}&rdquo;.</div>;\n }\n\n const { agent_runner_options } = interaction;\n const hasAgentFlags = agent_runner_options &&\n (agent_runner_options.is_agent || agent_runner_options.is_tool || agent_runner_options.is_skill);\n\n return (\n <DetailPage\n type=\"interaction\"\n title={interaction.title || interaction.name}\n description={interaction.description}\n tags={interaction.tags}\n backHref={`/interactions/${collection}`}\n >\n {/* Prompts */}\n {interaction.prompts && interaction.prompts.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Prompts</h2>\n {interaction.prompts.map((prompt, i) => (\n <div key={i} className=\"vta-detail-card\">\n <div className=\"vta-detail-card-header\">\n <span className={`vta-detail-role vta-detail-role--${prompt.role}`}>\n {prompt.role}\n </span>\n {prompt.name && (\n <span className=\"vta-detail-prompt-name\">{prompt.name}</span>\n )}\n </div>\n <pre className=\"vta-detail-code\">{prompt.content}</pre>\n </div>\n ))}\n </div>\n )}\n\n {/* Result schema */}\n {interaction.result_schema && (\n <div className=\"vta-detail-section\">\n <h2>Result Schema</h2>\n <pre className=\"vta-detail-code\">\n {JSON.stringify(interaction.result_schema, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Agent runner options */}\n {hasAgentFlags && (\n <div className=\"vta-detail-section\">\n <h2>Agent Runner</h2>\n <div className=\"vta-detail-flags\">\n {agent_runner_options.is_agent && <span className=\"vta-detail-flag\">Agent</span>}\n {agent_runner_options.is_tool && <span className=\"vta-detail-flag\">Tool</span>}\n {agent_runner_options.is_skill && <span className=\"vta-detail-flag\">Skill</span>}\n </div>\n </div>\n )}\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams } from '@vertesia/ui/router';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\ninterface ToolDef {\n name: string;\n description?: string;\n input_schema?: Record<string, unknown>;\n}\n\ninterface ToolCollectionResponse {\n title: string;\n description: string;\n tools: ToolDef[];\n}\n\nexport function ToolCollection() {\n const collection = useParams('collection');\n const { baseUrl } = useAdminContext();\n\n const { data, isLoading, error } = useFetch<ToolCollectionResponse>(\n () => fetch(`${baseUrl}/tools/${collection}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection]\n );\n\n if (isLoading) return <div className=\"vta-loading\">Loading collection...</div>;\n if (error || !data) return <div className=\"vta-error\">Failed to load tool collection &ldquo;{collection}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"tool\"\n title={data.title || collection}\n description={data.description || `${data.tools.length} tool${data.tools.length !== 1 ? 's' : ''} in this collection.`}\n >\n {data.tools.map(tool => (\n <div key={tool.name} className=\"vta-detail-card\">\n <div className=\"vta-detail-card-header\">\n <span className=\"vta-card-type vta-card-type--tool\">tool</span>\n <div className=\"vta-card-title\">{tool.name}</div>\n </div>\n <div className=\"vta-card-desc\">{tool.description || 'No description'}</div>\n {tool.input_schema && (\n <pre className=\"vta-detail-code\">\n {JSON.stringify(tool.input_schema, null, 2)}\n </pre>\n )}\n </div>\n ))}\n </DetailPage>\n );\n}\n","import { useMemo } from 'react';\nimport { useFetch } from '@vertesia/ui/core';\nimport { useParams, NavLink } from '@vertesia/ui/router';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\ninterface SkillToolDef {\n name: string;\n description?: string;\n related_tools?: string[];\n}\n\ninterface SkillCollectionResponse {\n title: string;\n description: string;\n tools: SkillToolDef[];\n}\n\ninterface WidgetInfo {\n skill: string;\n collection: string;\n url: string;\n}\n\ninterface WidgetsResponse {\n widgets: Record<string, WidgetInfo>;\n}\n\n/** Strip the learn_ prefix added by the SDK when exposing skills as tools. */\nfunction skillDisplayName(name: string): string {\n return name.startsWith('learn_') ? name.slice(6) : name;\n}\n\nexport function SkillCollection() {\n const collection = useParams('collection');\n const { baseUrl } = useAdminContext();\n\n const { data, isLoading, error } = useFetch<SkillCollectionResponse>(\n () => fetch(`${baseUrl}/skills/${collection}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection]\n );\n\n const { data: widgetsData } = useFetch<WidgetsResponse>(\n () => fetch(`${baseUrl}/package?scope=widgets`).then(r => r.ok ? r.json() : { widgets: {} }),\n [baseUrl]\n );\n\n const collectionWidgets = useMemo(() => {\n if (!widgetsData?.widgets) return [];\n return Object.entries(widgetsData.widgets)\n .filter(([_, w]) => w.collection === collection)\n .map(([name, w]) => ({ name, ...w }));\n }, [widgetsData, collection]);\n\n if (isLoading) return <div className=\"vta-loading\">Loading collection...</div>;\n if (error || !data) return <div className=\"vta-error\">Failed to load skill collection &ldquo;{collection}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"skill\"\n title={data.title || collection}\n description={data.description || `${data.tools.length} skill${data.tools.length !== 1 ? 's' : ''} in this collection.`}\n >\n {/* Widgets provided by this collection */}\n {collectionWidgets.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Widgets</h2>\n <div className=\"vta-detail-flags\">\n {collectionWidgets.map(w => (\n <span key={w.name} className=\"vta-detail-flag\">\n {w.name}\n <span className=\"vta-card-url\" style={{ marginLeft: '0.5rem' }}>\n (skill: {w.skill})\n </span>\n </span>\n ))}\n </div>\n </div>\n )}\n\n <div className=\"vta-card-grid\">\n {data.tools.map(skill => {\n const displayName = skillDisplayName(skill.name);\n return (\n <NavLink\n key={skill.name}\n href={`/skills/${collection}/${displayName}`}\n className=\"vta-card-link\"\n >\n <div className=\"vta-card vta-card--link\">\n <span className=\"vta-card-type vta-card-type--skill\">skill</span>\n <div className=\"vta-card-title\">{displayName}</div>\n <div className=\"vta-card-desc\">{skill.description || 'No description'}</div>\n {skill.related_tools && skill.related_tools.length > 0 && (\n <div className=\"vta-card-tags\">\n {skill.related_tools.map(t => (\n <span key={t} className=\"vta-tag\">{t}</span>\n ))}\n </div>\n )}\n </div>\n </NavLink>\n );\n })}\n </div>\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams } from '@vertesia/ui/router';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\ninterface SkillDefinitionResponse {\n name: string;\n title?: string;\n description: string;\n instructions: string;\n content_type: 'md' | 'jst';\n input_schema?: Record<string, unknown>;\n related_tools?: string[];\n execution?: {\n language: string;\n packages?: string[];\n };\n scripts?: string[];\n widgets?: string[];\n}\n\nexport function SkillDetail() {\n const params = useParams();\n const collection = params.collection;\n const name = params.name;\n const { baseUrl } = useAdminContext();\n\n const { data: skill, isLoading, error } = useFetch<SkillDefinitionResponse>(\n () => fetch(`${baseUrl}/skills/${collection}/${name}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load skill: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection, name]\n );\n\n if (isLoading) return <div className=\"vta-loading\">Loading skill...</div>;\n if (error || !skill) return <div className=\"vta-error\">Failed to load skill &ldquo;{name}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"skill\"\n title={skill.title || skill.name}\n description={skill.description}\n backHref={`/skills/${collection}`}\n >\n {/* Widgets */}\n {skill.widgets && skill.widgets.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Widgets</h2>\n <div className=\"vta-detail-flags\">\n {skill.widgets.map(w => (\n <span key={w} className=\"vta-detail-flag\">{w}</span>\n ))}\n </div>\n </div>\n )}\n\n {/* Scripts */}\n {skill.scripts && skill.scripts.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Scripts</h2>\n <div className=\"vta-detail-flags\">\n {skill.scripts.map(s => (\n <span key={s} className=\"vta-detail-flag\">{s}</span>\n ))}\n </div>\n </div>\n )}\n\n {/* Related tools */}\n {skill.related_tools && skill.related_tools.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Related Tools</h2>\n <div className=\"vta-detail-flags\">\n {skill.related_tools.map(t => (\n <span key={t} className=\"vta-detail-flag\">{t}</span>\n ))}\n </div>\n </div>\n )}\n\n {/* Execution environment */}\n {skill.execution && (\n <div className=\"vta-detail-section\">\n <h2>Execution</h2>\n <div className=\"vta-detail-flags\">\n <span className=\"vta-detail-flag\">{skill.execution.language}</span>\n {skill.execution.packages?.map(p => (\n <span key={p} className=\"vta-detail-flag\">{p}</span>\n ))}\n </div>\n </div>\n )}\n\n {/* Instructions */}\n <div className=\"vta-detail-section\">\n <h2>Instructions {skill.content_type === 'jst' && <span className=\"vta-tag\">JST template</span>}</h2>\n <pre className=\"vta-detail-code\">{skill.instructions}</pre>\n </div>\n\n {/* Input schema */}\n {skill.input_schema && (\n <div className=\"vta-detail-section\">\n <h2>Input Schema</h2>\n <pre className=\"vta-detail-code\">\n {JSON.stringify(skill.input_schema, null, 2)}\n </pre>\n </div>\n )}\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams, NavLink } from '@vertesia/ui/router';\nimport type { InCodeTypeDefinition } from '@vertesia/common';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\nexport function TypeCollection() {\n const collection = useParams('collection');\n const { baseUrl } = useAdminContext();\n\n const { data: types, isLoading, error } = useFetch<InCodeTypeDefinition[]>(\n () => fetch(`${baseUrl}/types/${collection}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection]\n );\n\n if (isLoading) return <div className=\"vta-loading\">Loading collection...</div>;\n if (error || !types) return <div className=\"vta-error\">Failed to load type collection &ldquo;{collection}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"type\"\n title={collection}\n description={`${types.length} content type${types.length !== 1 ? 's' : ''} in this collection.`}\n >\n <div className=\"vta-card-grid\">\n {types.map(t => {\n const typeName = t.id?.split(':')[1] || t.name;\n return (\n <NavLink\n key={t.name}\n href={`/types/${collection}/${typeName}`}\n className=\"vta-card-link\"\n >\n <div className=\"vta-card vta-card--link\">\n <span className=\"vta-card-type vta-card-type--type\">type</span>\n <div className=\"vta-card-title\">{t.name}</div>\n <div className=\"vta-card-desc\">{t.description || 'No description'}</div>\n {t.tags && t.tags.length > 0 && (\n <div className=\"vta-card-tags\">\n {t.tags.map(tag => (\n <span key={tag} className=\"vta-tag\">{tag}</span>\n ))}\n </div>\n )}\n <div className=\"vta-card-url\">\n {t.is_chunkable && 'chunkable'}\n {t.is_chunkable && t.strict_mode && ' · '}\n {t.strict_mode && 'strict'}\n </div>\n </div>\n </NavLink>\n );\n })}\n </div>\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams } from '@vertesia/ui/router';\nimport type { InCodeTypeDefinition } from '@vertesia/common';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\nexport function TypeDetail() {\n const params = useParams();\n const collection = params.collection;\n const name = params.name;\n const { baseUrl } = useAdminContext();\n\n const { data: typeDef, isLoading, error } = useFetch<InCodeTypeDefinition>(\n () => fetch(`${baseUrl}/types/${collection}/${name}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load type: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection, name]\n );\n\n if (isLoading) return <div className=\"vta-loading\">Loading type...</div>;\n if (error || !typeDef) return <div className=\"vta-error\">Failed to load type &ldquo;{name}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"type\"\n title={typeDef.name}\n description={typeDef.description}\n tags={typeDef.tags}\n backHref={`/types/${collection}`}\n >\n {/* Flags */}\n {(typeDef.is_chunkable || typeDef.strict_mode) && (\n <div className=\"vta-detail-section\">\n <div className=\"vta-detail-flags\">\n {typeDef.is_chunkable && <span className=\"vta-detail-flag\">Chunkable</span>}\n {typeDef.strict_mode && <span className=\"vta-detail-flag\">Strict Mode</span>}\n </div>\n </div>\n )}\n\n {/* Object Schema */}\n {typeDef.object_schema && (\n <div className=\"vta-detail-section\">\n <h2>Object Schema</h2>\n <pre className=\"vta-detail-code\">\n {JSON.stringify(typeDef.object_schema, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Table Layout */}\n {typeDef.table_layout && typeDef.table_layout.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Table Layout</h2>\n <pre className=\"vta-detail-code\">\n {JSON.stringify(typeDef.table_layout, null, 2)}\n </pre>\n </div>\n )}\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams, NavLink } from '@vertesia/ui/router';\nimport type { RenderingTemplateDefinitionRef } from '@vertesia/common';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\nexport function TemplateCollection() {\n const collection = useParams('collection');\n const { baseUrl } = useAdminContext();\n\n const { data: templates, isLoading, error } = useFetch<RenderingTemplateDefinitionRef[]>(\n () => fetch(`${baseUrl}/templates/${collection}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection]\n );\n\n if (isLoading) return <div className=\"vta-loading\">Loading collection...</div>;\n if (error || !templates) return <div className=\"vta-error\">Failed to load template collection &ldquo;{collection}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"template\"\n title={collection}\n description={`${templates.length} template${templates.length !== 1 ? 's' : ''} in this collection.`}\n >\n <div className=\"vta-card-grid\">\n {templates.map(tmpl => (\n <NavLink\n key={tmpl.name}\n href={`/templates/${collection}/${tmpl.name}`}\n className=\"vta-card-link\"\n >\n <div className=\"vta-card vta-card--link\">\n <div className=\"vta-card-type vta-card-type--template\">\n {tmpl.type || 'template'}\n </div>\n <div className=\"vta-card-title\">{tmpl.title || tmpl.name}</div>\n <div className=\"vta-card-desc\">{tmpl.description || 'No description'}</div>\n {tmpl.tags && tmpl.tags.length > 0 && (\n <div className=\"vta-card-tags\">\n {tmpl.tags.map(tag => (\n <span key={tag} className=\"vta-tag\">{tag}</span>\n ))}\n </div>\n )}\n </div>\n </NavLink>\n ))}\n </div>\n </DetailPage>\n );\n}\n","import { useFetch } from '@vertesia/ui/core';\nimport { useParams } from '@vertesia/ui/router';\nimport { useAdminContext } from '../AdminContext.js';\nimport { DetailPage } from '../components/DetailPage.js';\n\ninterface TemplateDefinitionResponse {\n name: string;\n title?: string;\n description: string;\n type: 'presentation' | 'document';\n tags?: string[];\n assets: string[];\n instructions: string;\n}\n\nexport function TemplateDetail() {\n const params = useParams();\n const collection = params.collection;\n const name = params.name;\n const { baseUrl } = useAdminContext();\n\n const { data: template, isLoading, error } = useFetch<TemplateDefinitionResponse>(\n () => fetch(`${baseUrl}/templates/${collection}/${name}`).then(r => {\n if (!r.ok) throw new Error(`Failed to load template: ${r.statusText}`);\n return r.json();\n }),\n [baseUrl, collection, name]\n );\n\n if (isLoading) return <div className=\"vta-loading\">Loading template...</div>;\n if (error || !template) return <div className=\"vta-error\">Failed to load template &ldquo;{name}&rdquo;.</div>;\n\n return (\n <DetailPage\n type=\"template\"\n title={template.title || template.name}\n description={template.description}\n tags={template.tags}\n backHref={`/templates/${collection}`}\n >\n {/* Type badge & Assets */}\n <div className=\"vta-detail-section\">\n <div className=\"vta-detail-flags\">\n <span className=\"vta-detail-flag\">{template.type}</span>\n </div>\n </div>\n\n {template.assets && template.assets.length > 0 && (\n <div className=\"vta-detail-section\">\n <h2>Assets</h2>\n <div className=\"vta-detail-flags\">\n {template.assets.map(asset => (\n <span key={asset} className=\"vta-detail-flag\">\n {asset.split('/').pop()}\n </span>\n ))}\n </div>\n </div>\n )}\n\n {/* Instructions */}\n <div className=\"vta-detail-section\">\n <h2>Instructions</h2>\n <pre className=\"vta-detail-code\">{template.instructions}</pre>\n </div>\n </DetailPage>\n );\n}\n","import type { Route } from '@vertesia/ui/router';\nimport { NestedRouterProvider, RouteComponent } from '@vertesia/ui/router';\nimport { useServerInfo, useResourceData } from './hooks.js';\nimport { AdminContext } from './AdminContext.js';\nimport { HomePage } from './pages/HomePage.js';\nimport { InteractionCollection } from './pages/InteractionCollection.js';\nimport { InteractionDetail } from './pages/InteractionDetail.js';\nimport { ToolCollection } from './pages/ToolCollection.js';\nimport { SkillCollection } from './pages/SkillCollection.js';\nimport { SkillDetail } from './pages/SkillDetail.js';\nimport { TypeCollection } from './pages/TypeCollection.js';\nimport { TypeDetail } from './pages/TypeDetail.js';\nimport { TemplateCollection } from './pages/TemplateCollection.js';\nimport { TemplateDetail } from './pages/TemplateDetail.js';\nimport adminStyles from './admin.css?inline';\n\nconst routes: Route[] = [\n { path: '/', Component: HomePage },\n { path: '/interactions/:collection', Component: InteractionCollection },\n { path: '/interactions/:collection/:name', Component: InteractionDetail },\n { path: '/tools/:collection', Component: ToolCollection },\n { path: '/skills/:collection', Component: SkillCollection },\n { path: '/skills/:collection/:name', Component: SkillDetail },\n { path: '/types/:collection', Component: TypeCollection },\n { path: '/types/:collection/:name', Component: TypeDetail },\n { path: '/templates/:collection', Component: TemplateCollection },\n { path: '/templates/:collection/:name', Component: TemplateDetail },\n];\n\nexport interface AdminAppProps {\n /**\n * Base URL for the tool server API.\n * @default '/api'\n */\n baseUrl?: string;\n}\n\n/**\n * Admin app shell — loads data, provides context, and renders nested routes.\n * CSS is inlined into the JS bundle via Vite's `?inline` import.\n */\nexport function AdminApp({ baseUrl = '/api' }: AdminAppProps) {\n const { data: serverInfo, isLoading: loadingInfo, error: infoError } = useServerInfo(baseUrl);\n const { data: resourceData, isLoading: loadingData, error: dataError } = useResourceData(\n baseUrl,\n serverInfo?.endpoints.mcp,\n );\n\n const isLoading = loadingInfo || loadingData;\n const error = infoError || dataError;\n\n if (isLoading) {\n return (\n <>\n <style>{adminStyles}</style>\n <div className=\"vta-loading\">Loading...</div>\n </>\n );\n }\n\n if (error) {\n return (\n <>\n <style>{adminStyles}</style>\n <div className=\"vta-error\">Failed to load server info. Is the API running?</div>\n </>\n );\n }\n\n if (!serverInfo || !resourceData) return null;\n\n return (\n <>\n <style>{adminStyles}</style>\n <AdminContext.Provider value={{\n serverInfo,\n collections: resourceData.collections,\n resources: resourceData.resources,\n baseUrl,\n }}>\n <NestedRouterProvider routes={routes}>\n <RouteComponent />\n </NestedRouterProvider>\n </AdminContext.Provider>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Types for the admin panel
3
+ */
4
+ import type { AgentToolDefinition, CatalogInteractionRef, InCodeTypeDefinition, RenderingTemplateDefinitionRef } from '@vertesia/common';
5
+ /**
6
+ * Server info from GET /api
7
+ */
8
+ export interface ServerInfo {
9
+ message: string;
10
+ version: string;
11
+ endpoints: {
12
+ tools: string[];
13
+ interactions: string[];
14
+ templates: string[];
15
+ mcp: string[];
16
+ };
17
+ }
18
+ export type ResourceType = 'tool' | 'skill' | 'interaction' | 'type' | 'template' | 'mcp';
19
+ /**
20
+ * A normalized resource entry for display and search.
21
+ */
22
+ export interface ResourceItem {
23
+ /** Unique identifier used for fetching details (e.g. "collection:name" for interactions). */
24
+ id?: string;
25
+ name: string;
26
+ title: string;
27
+ description: string;
28
+ type: ResourceType;
29
+ tags?: string[];
30
+ url?: string;
31
+ }
32
+ /**
33
+ * Metadata about a collection of resources, enriched with type and count client-side.
34
+ */
35
+ export interface CollectionInfo {
36
+ name: string;
37
+ title: string;
38
+ description: string;
39
+ type: ResourceType;
40
+ count: number;
41
+ }
42
+ /**
43
+ * Collection metadata as returned by each API endpoint.
44
+ */
45
+ interface CollectionMeta {
46
+ name: string;
47
+ title?: string;
48
+ description?: string;
49
+ }
50
+ /**
51
+ * Response shapes for each resource endpoint.
52
+ */
53
+ interface InteractionsResponse {
54
+ interactions: CatalogInteractionRef[];
55
+ collections: CollectionMeta[];
56
+ }
57
+ interface ToolsResponse {
58
+ tools: AgentToolDefinition[];
59
+ collections: CollectionMeta[];
60
+ }
61
+ interface SkillsResponse {
62
+ tools: AgentToolDefinition[];
63
+ collections: CollectionMeta[];
64
+ }
65
+ interface TypesResponse {
66
+ types: InCodeTypeDefinition[];
67
+ collections: CollectionMeta[];
68
+ }
69
+ interface TemplatesResponse {
70
+ templates: RenderingTemplateDefinitionRef[];
71
+ collections: CollectionMeta[];
72
+ }
73
+ /**
74
+ * Combined result of processing all endpoint responses.
75
+ */
76
+ export interface ResourceData {
77
+ collections: CollectionInfo[];
78
+ resources: ResourceItem[];
79
+ }
80
+ /**
81
+ * Builds collections and a flat resource list from the 5 endpoint responses + MCP endpoints.
82
+ */
83
+ export declare function buildResourceData(interactionsResp: InteractionsResponse, toolsResp: ToolsResponse, skillsResp: SkillsResponse, typesResp: TypesResponse, templatesResp: TemplatesResponse, mcpEndpoints?: string[]): ResourceData;
84
+ /**
85
+ * Filters resources by a search query, matching against name, title, description, type, and tags.
86
+ */
87
+ export declare function filterResources(items: ResourceItem[], query: string): ResourceItem[];
88
+ export {};
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACR,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,8BAA8B,EACjC,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE;QACP,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,GAAG,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC;CACL;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC;AAE1F;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB,6FAA6F;IAC7F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,UAAU,cAAc;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,UAAU,oBAAoB;IAC1B,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,WAAW,EAAE,cAAc,EAAE,CAAC;CACjC;AAED,UAAU,aAAa;IACnB,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CACjC;AAED,UAAU,cAAc;IACpB,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CACjC;AAED,UAAU,aAAa;IACnB,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;CACjC;AAED,UAAU,iBAAiB;IACvB,SAAS,EAAE,8BAA8B,EAAE,CAAC;IAC5C,WAAW,EAAE,cAAc,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,SAAS,EAAE,YAAY,EAAE,CAAC;CAC7B;AAoCD;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,gBAAgB,EAAE,oBAAoB,EACtC,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,iBAAiB,EAChC,YAAY,CAAC,EAAE,MAAM,EAAE,GACxB,YAAY,CAmJd;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAUpF"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@vertesia/tools-admin-ui",
3
+ "version": "0.9.0",
4
+ "description": "Shared admin UI for Vertesia tool servers",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "files": [
8
+ "lib",
9
+ "src"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./lib/index.d.ts",
14
+ "import": "./lib/tools-admin-ui.js"
15
+ }
16
+ },
17
+ "peerDependencies": {
18
+ "react": "^19.0.0",
19
+ "react-dom": "^19.0.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/react": "^19.2.3",
23
+ "@types/react-dom": "^19.2.3",
24
+ "@vitejs/plugin-react": "^5.1.2",
25
+ "react": "^19.2.3",
26
+ "react-dom": "^19.2.3",
27
+ "typescript": "^5.9.3",
28
+ "vite": "^7.3.0"
29
+ },
30
+ "dependencies": {
31
+ "@vertesia/common": "1.0.0-dev.20260227.104700Z",
32
+ "@vertesia/ui": "1.0.0-dev.20260227.104700Z"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/vertesia/composableai.git",
37
+ "directory": "packages/tools-admin-ui"
38
+ },
39
+ "keywords": [
40
+ "vertesia",
41
+ "tools",
42
+ "admin",
43
+ "ui",
44
+ "react"
45
+ ],
46
+ "scripts": {
47
+ "build": "rm -rf lib tsconfig.tsbuildinfo && tsc --build && vite build --mode lib",
48
+ "dev": "vite dev"
49
+ }
50
+ }
@@ -0,0 +1,87 @@
1
+ import type { Route } from '@vertesia/ui/router';
2
+ import { NestedRouterProvider, RouteComponent } from '@vertesia/ui/router';
3
+ import { useServerInfo, useResourceData } from './hooks.js';
4
+ import { AdminContext } from './AdminContext.js';
5
+ import { HomePage } from './pages/HomePage.js';
6
+ import { InteractionCollection } from './pages/InteractionCollection.js';
7
+ import { InteractionDetail } from './pages/InteractionDetail.js';
8
+ import { ToolCollection } from './pages/ToolCollection.js';
9
+ import { SkillCollection } from './pages/SkillCollection.js';
10
+ import { SkillDetail } from './pages/SkillDetail.js';
11
+ import { TypeCollection } from './pages/TypeCollection.js';
12
+ import { TypeDetail } from './pages/TypeDetail.js';
13
+ import { TemplateCollection } from './pages/TemplateCollection.js';
14
+ import { TemplateDetail } from './pages/TemplateDetail.js';
15
+ import adminStyles from './admin.css?inline';
16
+
17
+ const routes: Route[] = [
18
+ { path: '/', Component: HomePage },
19
+ { path: '/interactions/:collection', Component: InteractionCollection },
20
+ { path: '/interactions/:collection/:name', Component: InteractionDetail },
21
+ { path: '/tools/:collection', Component: ToolCollection },
22
+ { path: '/skills/:collection', Component: SkillCollection },
23
+ { path: '/skills/:collection/:name', Component: SkillDetail },
24
+ { path: '/types/:collection', Component: TypeCollection },
25
+ { path: '/types/:collection/:name', Component: TypeDetail },
26
+ { path: '/templates/:collection', Component: TemplateCollection },
27
+ { path: '/templates/:collection/:name', Component: TemplateDetail },
28
+ ];
29
+
30
+ export interface AdminAppProps {
31
+ /**
32
+ * Base URL for the tool server API.
33
+ * @default '/api'
34
+ */
35
+ baseUrl?: string;
36
+ }
37
+
38
+ /**
39
+ * Admin app shell — loads data, provides context, and renders nested routes.
40
+ * CSS is inlined into the JS bundle via Vite's `?inline` import.
41
+ */
42
+ export function AdminApp({ baseUrl = '/api' }: AdminAppProps) {
43
+ const { data: serverInfo, isLoading: loadingInfo, error: infoError } = useServerInfo(baseUrl);
44
+ const { data: resourceData, isLoading: loadingData, error: dataError } = useResourceData(
45
+ baseUrl,
46
+ serverInfo?.endpoints.mcp,
47
+ );
48
+
49
+ const isLoading = loadingInfo || loadingData;
50
+ const error = infoError || dataError;
51
+
52
+ if (isLoading) {
53
+ return (
54
+ <>
55
+ <style>{adminStyles}</style>
56
+ <div className="vta-loading">Loading...</div>
57
+ </>
58
+ );
59
+ }
60
+
61
+ if (error) {
62
+ return (
63
+ <>
64
+ <style>{adminStyles}</style>
65
+ <div className="vta-error">Failed to load server info. Is the API running?</div>
66
+ </>
67
+ );
68
+ }
69
+
70
+ if (!serverInfo || !resourceData) return null;
71
+
72
+ return (
73
+ <>
74
+ <style>{adminStyles}</style>
75
+ <AdminContext.Provider value={{
76
+ serverInfo,
77
+ collections: resourceData.collections,
78
+ resources: resourceData.resources,
79
+ baseUrl,
80
+ }}>
81
+ <NestedRouterProvider routes={routes}>
82
+ <RouteComponent />
83
+ </NestedRouterProvider>
84
+ </AdminContext.Provider>
85
+ </>
86
+ );
87
+ }
@@ -0,0 +1,17 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { CollectionInfo, ResourceItem, ServerInfo } from './types.js';
3
+
4
+ export interface AdminContextValue {
5
+ serverInfo: ServerInfo;
6
+ collections: CollectionInfo[];
7
+ resources: ResourceItem[];
8
+ baseUrl: string;
9
+ }
10
+
11
+ export const AdminContext = createContext<AdminContextValue | undefined>(undefined);
12
+
13
+ export function useAdminContext(): AdminContextValue {
14
+ const ctx = useContext(AdminContext);
15
+ if (!ctx) throw new Error('useAdminContext must be used within AdminApp');
16
+ return ctx;
17
+ }