Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions web-ui/src/lib/mcpCustomTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export type McpCustomToolsResolution = {
source: 'artifacts_custom_tools' | 'services_operations'
expoId: string
serviceId: string
/** Control-plane artifact id when tools come from `RESHAPR_CUSTOM_TOOLS`. */
artifactId?: string
/** Full `RESHAPR_CUSTOM_TOOLS` artifact YAML when tools come from that artifact. */
artifactYaml?: string
}
Expand Down Expand Up @@ -225,6 +227,7 @@ type ServiceRow = {
}

type ArtifactRow = {
id?: string
type?: string
content?: string | null
}
Expand Down Expand Up @@ -291,6 +294,7 @@ export async function resolveMcpCustomToolsForService(
source: 'artifacts_custom_tools',
expoId: '',
serviceId,
artifactId: yamlArtifact?.id,
artifactYaml: yamlArtifact?.content ?? undefined,
}
}
Expand Down Expand Up @@ -324,6 +328,7 @@ export async function resolveMcpCustomToolsForService(
source: 'artifacts_custom_tools',
expoId: expo.id,
serviceId,
artifactId: yamlArtifact?.id,
artifactYaml: yamlArtifact?.content ?? undefined,
}
}
Expand Down
6 changes: 4 additions & 2 deletions web-ui/src/lib/mcpPrompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type McpPromptsClient = {
}

export type McpPromptArtifactYaml = {
id: string
name: string
content: string
}
Expand All @@ -49,6 +50,7 @@ type ServiceRow = {
}

type ArtifactRow = {
id?: string
type?: string
name?: string
content?: string | null
Expand Down Expand Up @@ -155,8 +157,8 @@ export async function resolveMcpPromptsForService(
for (const artifact of promptArtifacts) {
const label = artifact.name || `RESHAPR_PROMPTS-${artifactYamls.length + 1}`
if (artifact.name) artifactNames.push(artifact.name)
if (artifact.content) {
artifactYamls.push({ name: label, content: artifact.content })
if (artifact.content && artifact.id) {
artifactYamls.push({ id: artifact.id, name: label, content: artifact.content })
}
for (const p of parseReshaprPromptsYaml(artifact.content || '')) {
byName.set(p.name, p)
Expand Down
17 changes: 16 additions & 1 deletion web-ui/src/routes/(app)/mcp-custom-tools/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@

const tools = $derived(result?.tools ?? []);

function artifactEditHref(serviceId: string, artifactId: string): string {
return `/services/${serviceId}/artifacts/${artifactId}`;
}

async function runResolve(url: string) {
const trimmed = url.trim();
if (!trimmed) {
Expand Down Expand Up @@ -276,7 +280,18 @@
{yamlOpen ? 'Hide' : 'Show'}
</span>
</Collapsible.Trigger>
<Collapsible.Content class="border-t px-2 pb-2">
<Collapsible.Content class="space-y-2 border-t px-2 pb-2 pt-2">
{#if result.artifactId}
<div class="flex justify-end px-1">
<Button
variant="outline"
size="sm"
href={artifactEditHref(result.serviceId, result.artifactId)}
>
Edit in Artifacts
</Button>
</div>
{/if}
<ScrollableCode text={result.artifactYaml} maxHeight="min(70vh, 28rem)" class="border-0" />
</Collapsible.Content>
</Collapsible.Root>
Expand Down
28 changes: 25 additions & 3 deletions web-ui/src/routes/(app)/mcp-prompts/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@

const prompts = $derived(result?.prompts ?? []);

function artifactEditHref(serviceId: string, artifactId: string): string {
return `/services/${serviceId}/artifacts/${artifactId}`;
}

function artifactsHubHref(serviceId: string): string {
return `/services/${serviceId}/artifacts`;
}

async function runListPrompts(url: string) {
const trimmed = url.trim();
if (!trimmed) {
Expand Down Expand Up @@ -286,7 +294,12 @@
</Table.Root>
</div>
{:else}
<p class="text-muted-foreground text-sm">No prompts found in the artifact YAML.</p>
<p class="text-muted-foreground text-sm">
No prompts found in the artifact YAML.
<a href={artifactsHubHref(result.serviceId)} class="text-primary hover:underline">
Open Artifacts hub
</a>
</p>
{/if}

{#if result.artifactYamls.length > 0}
Expand All @@ -301,9 +314,18 @@
</span>
</Collapsible.Trigger>
<Collapsible.Content class="space-y-3 border-t p-3">
{#each result.artifactYamls as artifact (artifact.name)}
{#each result.artifactYamls as artifact (artifact.id)}
<div class="space-y-1">
<p class="text-muted-foreground text-xs font-medium">{artifact.name}</p>
<div class="flex flex-wrap items-center justify-between gap-2">
<p class="text-muted-foreground text-xs font-medium">{artifact.name}</p>
<Button
variant="outline"
size="sm"
href={artifactEditHref(result.serviceId, artifact.id)}
>
Edit in Artifacts
</Button>
</div>
<ScrollableCode
text={artifact.content}
maxHeight="min(70vh, 28rem)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@

const tools = $derived(result?.tools ?? []);

const artifactsHubHref = $derived(`/services/${ctx.id}/artifacts`);
const createCustomToolsHref = $derived(
`/services/${ctx.id}/artifacts/new?kind=${encodeURIComponent('CustomTools')}`,
);

function artifactEditHref(artifactId: string): string {
return `/services/${ctx.id}/artifacts/${artifactId}`;
}

async function load() {
if (!ctx.id) return;
loading = true;
Expand Down Expand Up @@ -76,6 +85,11 @@
<Button variant="outline" size="sm" disabled={loading} onclick={() => void load()}>Refresh</Button>
</div>

<p class="text-muted-foreground mb-4 text-sm">
Resolved from <code class="text-xs">RESHAPR_CUSTOM_TOOLS</code> artifacts or service operations. Edit YAML via
<a href={artifactsHubHref} class="text-primary hover:underline">Artifacts</a>.
</p>

{#if error}
<ApiErrorAlert message={error} />
{/if}
Expand Down Expand Up @@ -108,7 +122,14 @@
<Collapsible.Trigger class="text-primary text-sm font-medium hover:underline" type="button">
{yamlOpen ? 'Hide' : 'Show'} RESHAPR_CUSTOM_TOOLS YAML
</Collapsible.Trigger>
<Collapsible.Content class="mt-2">
<Collapsible.Content class="mt-2 space-y-2">
{#if result.artifactId}
<div class="flex justify-end">
<Button variant="outline" size="sm" href={artifactEditHref(result.artifactId)}>
Edit in Artifacts
</Button>
</div>
{/if}
<ScrollableCode text={result.artifactYaml} maxHeight="24rem" />
</Collapsible.Content>
</Collapsible.Root>
Expand All @@ -129,7 +150,14 @@
</Table.Row>
{:else if tools.length === 0}
<Table.Row>
<Table.Cell colspan={2} class="text-muted-foreground">No custom tools resolved.</Table.Cell>
<Table.Cell colspan={2} class="text-muted-foreground">
No custom tools resolved.
{#if !loading && result && result.source === 'services_operations'}
<a href={createCustomToolsHref} class="text-primary hover:underline">
Create CustomTools artifact
</a>
{/if}
</Table.Cell>
</Table.Row>
{:else}
{#each tools as t (t.name)}
Expand Down
25 changes: 21 additions & 4 deletions web-ui/src/routes/(app)/services/[id]/mcp-prompts/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@

const prompts = $derived(result?.prompts ?? []);

const artifactsHubHref = $derived(`/services/${ctx.id}/artifacts`);
const createPromptsHref = $derived(`/services/${ctx.id}/artifacts/new?kind=${encodeURIComponent('Prompts')}`);

function artifactEditHref(artifactId: string): string {
return `/services/${ctx.id}/artifacts/${artifactId}`;
}

function formatArguments(
args: { name: string; description?: string; required?: boolean }[] | undefined,
): string {
Expand Down Expand Up @@ -77,7 +84,7 @@

<p class="text-muted-foreground mb-4 text-sm">
Resolved from <code class="text-xs">RESHAPR_PROMPTS</code> artifacts on this service. Attach prompts via
<a href="/artifacts" class="text-primary hover:underline">Artifacts</a>.
<a href={artifactsHubHref} class="text-primary hover:underline">Artifacts</a>.
</p>

{#if error}
Expand All @@ -100,9 +107,14 @@
{yamlOpen ? 'Hide' : 'Show'} artifact YAML
</Collapsible.Trigger>
<Collapsible.Content class="mt-2 space-y-4">
{#each result.artifactYamls as art (art.name)}
{#each result.artifactYamls as art (art.id)}
<div>
<p class="mb-1 text-sm font-medium">{art.name}</p>
<div class="mb-1 flex flex-wrap items-center justify-between gap-2">
<p class="text-sm font-medium">{art.name}</p>
<Button variant="outline" size="sm" href={artifactEditHref(art.id)}>
Edit in Artifacts
</Button>
</div>
<ScrollableCode text={art.content} maxHeight="16rem" />
</div>
{/each}
Expand All @@ -126,7 +138,12 @@
</Table.Row>
{:else if prompts.length === 0}
<Table.Row>
<Table.Cell colspan={3} class="text-muted-foreground">No prompts.</Table.Cell>
<Table.Cell colspan={3} class="text-muted-foreground">
No prompts.
{#if !loading && result && result.artifactYamls.length === 0}
<a href={createPromptsHref} class="text-primary hover:underline">Create Prompts artifact</a>
{/if}
</Table.Cell>
</Table.Row>
{:else}
{#each prompts as p (p.name)}
Expand Down