feat(agents): render tool parameters in modal

- Add parameters to tool API responses (agents + collections)
- Update ToolInfo interface to include parameters
- Render parameters grouped by required/optional
- Show parameter name, type, description, and default value
- Style with design system patterns (fieldsets, badges, etc.)
This commit is contained in:
Ajax Davis 2026-01-17 04:35:25 +10:00
parent 3e0923fc4a
commit f8302c92d6
9 changed files with 3550 additions and 246 deletions

View file

@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View file

@ -60,6 +60,7 @@ export async function GET(_request: NextRequest, context: RouteContext) {
id: true,
name: true,
description: true,
parameters: true,
package: {
select: {
npmPackageName: true,

View file

@ -86,6 +86,7 @@ export async function GET(
id: true,
name: true,
description: true,
parameters: true,
package: {
select: {
npmPackageName: true,

View file

@ -4,6 +4,14 @@ import { Button } from '@tpmjs/ui/Button/Button';
import { Icon } from '@tpmjs/ui/Icon/Icon';
import { useCallback, useState } from 'react';
export interface ToolParameter {
name: string;
type: string;
description: string;
required: boolean;
default?: unknown;
}
export interface ToolInfo {
id: string;
toolId: string;
@ -11,6 +19,7 @@ export interface ToolInfo {
id: string;
name: string;
description: string | null;
parameters: ToolParameter[] | null;
package: {
npmPackageName: string;
category: string;

View file

@ -18,6 +18,9 @@ export function ToolDetailsModal({ tool, open, onClose }: ToolDetailsModalProps)
if (!tool) return null;
const toolPageUrl = `/tool/${tool.tool.package.npmPackageName}/${tool.tool.name}`;
const parameters = tool.tool.parameters || [];
const requiredParams = parameters.filter((p) => p.required);
const optionalParams = parameters.filter((p) => !p.required);
return (
<Modal open={open} onClose={onClose} size="lg">
@ -58,19 +61,60 @@ export function ToolDetailsModal({ tool, open, onClose }: ToolDetailsModalProps)
)}
<div className="flex items-center gap-2">
<Badge variant="secondary">{tool.tool.package.category}</Badge>
{parameters.length > 0 && (
<Badge variant="outline">
{parameters.length} param{parameters.length !== 1 ? 's' : ''}
</Badge>
)}
</div>
</div>
</fieldset>
{/* note about parameters */}
{/* parameters fieldset */}
<fieldset className="border border-dashed border-border p-4">
<legend className="px-2 font-mono text-xs text-foreground-tertiary lowercase">
parameters
</legend>
<p className="text-sm text-foreground-secondary">
This tool accepts parameters defined in its input schema. View the full tool page for
detailed parameter documentation and usage examples.
</p>
{parameters.length === 0 ? (
<p className="text-sm text-foreground-tertiary italic">No parameters defined</p>
) : (
<div className="space-y-4">
{/* Required parameters */}
{requiredParams.length > 0 && (
<div>
<div className="flex items-center gap-2 mb-3">
<div className="w-2 h-2 rounded-full bg-error" />
<span className="font-mono text-xs text-foreground-secondary uppercase tracking-wide">
Required ({requiredParams.length})
</span>
</div>
<div className="space-y-3">
{requiredParams.map((param) => (
<ParameterRow key={param.name} param={param} />
))}
</div>
</div>
)}
{/* Optional parameters */}
{optionalParams.length > 0 && (
<div className={requiredParams.length > 0 ? 'pt-4 border-t border-dashed border-border/50' : ''}>
<div className="flex items-center gap-2 mb-3">
<div className="w-2 h-2 rounded-full bg-foreground-tertiary" />
<span className="font-mono text-xs text-foreground-secondary uppercase tracking-wide">
Optional ({optionalParams.length})
</span>
</div>
<div className="space-y-3">
{optionalParams.map((param) => (
<ParameterRow key={param.name} param={param} />
))}
</div>
</div>
)}
</div>
)}
</fieldset>
</div>
@ -94,3 +138,37 @@ export function ToolDetailsModal({ tool, open, onClose }: ToolDetailsModalProps)
</Modal>
);
}
interface ParameterRowProps {
param: {
name: string;
type: string;
description: string;
required: boolean;
default?: unknown;
};
}
function ParameterRow({ param }: ParameterRowProps) {
return (
<div className="group p-3 rounded-lg bg-surface-secondary/30 hover:bg-surface-secondary/50 transition-colors">
<div className="flex items-start justify-between gap-3 mb-1.5">
<code className="font-mono text-sm text-foreground font-medium">{param.name}</code>
<code className="font-mono text-xs px-1.5 py-0.5 rounded bg-surface-secondary text-foreground-secondary">
{param.type}
</code>
</div>
{param.description && (
<p className="text-sm text-foreground-secondary leading-relaxed">{param.description}</p>
)}
{param.default !== undefined && (
<div className="mt-2 flex items-center gap-2">
<span className="text-xs text-foreground-tertiary">default:</span>
<code className="font-mono text-xs px-1.5 py-0.5 rounded bg-primary/10 text-primary">
{JSON.stringify(param.default)}
</code>
</div>
)}
</div>
);
}

File diff suppressed because it is too large Load diff

View file

@ -3,26 +3,146 @@
* This file provides metadata for the blocks validator
*/
import {
deleteJob,
execute,
// Execution tools
executeCodeAsync,
getJob,
listJobs,
execute,
run,
runAsync,
// Job tools
getJob,
listJobs,
deleteJob,
// Languages tools
getLanguages,
getShells,
// Session tools
createSession,
getSession,
listSessions,
executeInSession,
freezeSession,
unfreezeSession,
lockSession,
unlockSession,
createSessionSnapshot,
restoreSession,
deleteSession,
// Service tools
createService,
getService,
listServices,
executeInService,
freezeService,
unfreezeService,
lockService,
unlockService,
redeployService,
getServiceLogs,
createServiceSnapshot,
getServiceEnv,
setServiceEnv,
deleteServiceEnv,
deleteService,
// Snapshot tools
createSnapshot,
getSnapshot,
listSnapshots,
lockSnapshot,
unlockSnapshot,
restoreSnapshot,
cloneSnapshot,
deleteSnapshot,
// Image tools
publishImage,
getImage,
listImages,
lockImage,
unlockImage,
grantImageAccess,
revokeImageAccess,
transferImage,
setImageVisibility,
spawnFromImage,
getImageTrustedKeys,
deleteImage,
// System tools
healthCheck,
getClusterStatus,
getSystemStats,
listPools,
} from './src/index.js';
export const block = {
name: 'unsandbox',
description: 'Execute code in a secure sandbox environment supporting 42+ languages',
tools: {
// Execution tools
executeCodeAsync,
getJob,
execute,
run,
runAsync,
// Job tools
getJob,
listJobs,
deleteJob,
// Languages tools
getLanguages,
getShells,
// Session tools
createSession,
getSession,
listSessions,
executeInSession,
freezeSession,
unfreezeSession,
lockSession,
unlockSession,
createSessionSnapshot,
restoreSession,
deleteSession,
// Service tools
createService,
getService,
listServices,
executeInService,
freezeService,
unfreezeService,
lockService,
unlockService,
redeployService,
getServiceLogs,
createServiceSnapshot,
getServiceEnv,
setServiceEnv,
deleteServiceEnv,
deleteService,
// Snapshot tools
createSnapshot,
getSnapshot,
listSnapshots,
lockSnapshot,
unlockSnapshot,
restoreSnapshot,
cloneSnapshot,
deleteSnapshot,
// Image tools
publishImage,
getImage,
listImages,
lockImage,
unlockImage,
grantImageAccess,
revokeImageAccess,
transferImage,
setImageVisibility,
spawnFromImage,
getImageTrustedKeys,
deleteImage,
// System tools
healthCheck,
getClusterStatus,
getSystemStats,
listPools,
},
};

View file

@ -1,6 +1,6 @@
{
"name": "@tpmjs/tools-unsandbox",
"version": "0.1.1",
"version": "0.1.2",
"description": "Execute code in a secure sandbox environment. Supports 42+ programming languages with async execution, input files, and compiled artifacts.",
"type": "module",
"keywords": [
@ -50,10 +50,6 @@
"name": "executeCodeAsync",
"description": "Execute code asynchronously in a secure sandbox. Returns a job_id immediately. Use getJob to check status and retrieve results. Supports 42+ languages."
},
{
"name": "getJob",
"description": "Get the status and results of an async code execution job by job_id."
},
{
"name": "execute",
"description": "Execute code synchronously in a secure sandbox. Waits for completion and returns results directly. Best for quick scripts."
@ -66,6 +62,10 @@
"name": "runAsync",
"description": "Execute code asynchronously with automatic language detection via shebang. Returns job_id for polling."
},
{
"name": "getJob",
"description": "Get the status and results of an async code execution job by job_id."
},
{
"name": "listJobs",
"description": "List all active code execution jobs with their current status."
@ -73,6 +73,214 @@
{
"name": "deleteJob",
"description": "Cancel an active code execution job by job_id."
},
{
"name": "getLanguages",
"description": "Get list of all supported programming languages with their metadata including extensions, version, and capabilities."
},
{
"name": "getShells",
"description": "Get list of available shell interpreters (bash, zsh, etc.) with their versions and capabilities."
},
{
"name": "createSession",
"description": "Create a new persistent session with configurable language, resources, and networking. Sessions maintain state across executions."
},
{
"name": "getSession",
"description": "Get details of a session including status, resource usage, and configuration."
},
{
"name": "listSessions",
"description": "List all sessions with optional filtering by status (active, frozen, locked)."
},
{
"name": "executeInSession",
"description": "Execute code in an existing session. State and files persist between executions."
},
{
"name": "freezeSession",
"description": "Freeze a session to pause execution and reduce resource usage while preserving state."
},
{
"name": "unfreezeSession",
"description": "Unfreeze a frozen session to resume execution."
},
{
"name": "lockSession",
"description": "Lock a session to prevent modifications or deletion."
},
{
"name": "unlockSession",
"description": "Unlock a locked session to allow modifications."
},
{
"name": "createSessionSnapshot",
"description": "Create a snapshot of the current session state for backup or cloning."
},
{
"name": "restoreSession",
"description": "Restore a session from a snapshot."
},
{
"name": "deleteSession",
"description": "Delete a session and release all associated resources."
},
{
"name": "createService",
"description": "Create a long-running service with persistent state, networking, and auto-restart capabilities."
},
{
"name": "getService",
"description": "Get details of a service including status, endpoints, and resource usage."
},
{
"name": "listServices",
"description": "List all services with optional filtering by status."
},
{
"name": "executeInService",
"description": "Execute a command or code snippet in a running service."
},
{
"name": "freezeService",
"description": "Freeze a service to pause execution while preserving state."
},
{
"name": "unfreezeService",
"description": "Unfreeze a frozen service to resume execution."
},
{
"name": "lockService",
"description": "Lock a service to prevent modifications or deletion."
},
{
"name": "unlockService",
"description": "Unlock a locked service to allow modifications."
},
{
"name": "redeployService",
"description": "Redeploy a service with updated configuration or code."
},
{
"name": "getServiceLogs",
"description": "Get logs from a service with optional filtering by time range and log level."
},
{
"name": "createServiceSnapshot",
"description": "Create a snapshot of the current service state."
},
{
"name": "getServiceEnv",
"description": "Get environment variables configured for a service."
},
{
"name": "setServiceEnv",
"description": "Set or update environment variables for a service."
},
{
"name": "deleteServiceEnv",
"description": "Delete an environment variable from a service."
},
{
"name": "deleteService",
"description": "Delete a service and release all associated resources."
},
{
"name": "createSnapshot",
"description": "Create a snapshot from any source (session, service, or existing snapshot)."
},
{
"name": "getSnapshot",
"description": "Get details of a snapshot including metadata and creation info."
},
{
"name": "listSnapshots",
"description": "List all snapshots with optional filtering by source type."
},
{
"name": "lockSnapshot",
"description": "Lock a snapshot to prevent deletion or modification."
},
{
"name": "unlockSnapshot",
"description": "Unlock a locked snapshot to allow modifications."
},
{
"name": "restoreSnapshot",
"description": "Restore a session or service from a snapshot."
},
{
"name": "cloneSnapshot",
"description": "Clone a snapshot to create a new independent copy."
},
{
"name": "deleteSnapshot",
"description": "Delete a snapshot and free associated storage."
},
{
"name": "publishImage",
"description": "Publish a snapshot as a reusable image for spawning new sessions or services."
},
{
"name": "getImage",
"description": "Get details of a published image including metadata and access info."
},
{
"name": "listImages",
"description": "List all images with optional filtering by visibility and ownership."
},
{
"name": "lockImage",
"description": "Lock an image to prevent modifications or deletion."
},
{
"name": "unlockImage",
"description": "Unlock a locked image to allow modifications."
},
{
"name": "grantImageAccess",
"description": "Grant access to a private image for specific users or API keys."
},
{
"name": "revokeImageAccess",
"description": "Revoke access to an image from specific users or API keys."
},
{
"name": "transferImage",
"description": "Transfer ownership of an image to another user."
},
{
"name": "setImageVisibility",
"description": "Set image visibility to public or private."
},
{
"name": "spawnFromImage",
"description": "Spawn a new session or service from an image."
},
{
"name": "getImageTrustedKeys",
"description": "Get list of API keys that have access to a private image."
},
{
"name": "deleteImage",
"description": "Delete an image and free associated storage."
},
{
"name": "healthCheck",
"description": "Check the health status of the Unsandbox API service."
},
{
"name": "getClusterStatus",
"description": "Get status of the execution cluster including node availability and capacity."
},
{
"name": "getSystemStats",
"description": "Get system statistics including resource utilization and job metrics."
},
{
"name": "listPools",
"description": "List available execution pools with their configurations and current status."
}
]
},

File diff suppressed because it is too large Load diff