nitrostack 1.0.71 → 1.0.73
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.
- package/dist/auth/api-key.js.map +1 -1
- package/dist/auth/client.js.map +1 -1
- package/dist/auth/index.d.ts +2 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +3 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/middleware.d.ts +1 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js.map +1 -1
- package/dist/auth/secure-secret.d.ts +136 -0
- package/dist/auth/secure-secret.d.ts.map +1 -0
- package/dist/auth/secure-secret.js +182 -0
- package/dist/auth/secure-secret.js.map +1 -0
- package/dist/auth/server-metadata.d.ts.map +1 -1
- package/dist/auth/server-metadata.js.map +1 -1
- package/dist/auth/simple-jwt.d.ts +100 -14
- package/dist/auth/simple-jwt.d.ts.map +1 -1
- package/dist/auth/simple-jwt.js +19 -9
- package/dist/auth/simple-jwt.js.map +1 -1
- package/dist/auth/token-store.js +1 -1
- package/dist/auth/token-store.js.map +1 -1
- package/dist/auth/token-validation.js +1 -1
- package/dist/auth/token-validation.js.map +1 -1
- package/dist/cli/commands/build.js +1 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/generate-types.js +12 -12
- package/dist/cli/commands/generate-types.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +8 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +13 -12
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/init.js +1 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts +10 -0
- package/dist/cli/commands/upgrade.d.ts.map +1 -0
- package/dist/cli/commands/upgrade.js +221 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/app-decorator.d.ts +4 -3
- package/dist/core/app-decorator.d.ts.map +1 -1
- package/dist/core/app-decorator.js +67 -28
- package/dist/core/app-decorator.js.map +1 -1
- package/dist/core/builders.d.ts +19 -7
- package/dist/core/builders.d.ts.map +1 -1
- package/dist/core/builders.js +15 -8
- package/dist/core/builders.js.map +1 -1
- package/dist/core/component.d.ts +8 -8
- package/dist/core/component.d.ts.map +1 -1
- package/dist/core/component.js +3 -2
- package/dist/core/component.js.map +1 -1
- package/dist/core/config-module.d.ts +11 -4
- package/dist/core/config-module.d.ts.map +1 -1
- package/dist/core/config-module.js +1 -1
- package/dist/core/config-module.js.map +1 -1
- package/dist/core/decorators/cache.decorator.d.ts +9 -9
- package/dist/core/decorators/cache.decorator.d.ts.map +1 -1
- package/dist/core/decorators/cache.decorator.js +3 -3
- package/dist/core/decorators/cache.decorator.js.map +1 -1
- package/dist/core/decorators/health-check.decorator.d.ts +3 -3
- package/dist/core/decorators/health-check.decorator.d.ts.map +1 -1
- package/dist/core/decorators/health-check.decorator.js +2 -2
- package/dist/core/decorators/health-check.decorator.js.map +1 -1
- package/dist/core/decorators/rate-limit.decorator.d.ts +5 -4
- package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -1
- package/dist/core/decorators/rate-limit.decorator.js +3 -3
- package/dist/core/decorators/rate-limit.decorator.js.map +1 -1
- package/dist/core/decorators.d.ts +47 -29
- package/dist/core/decorators.d.ts.map +1 -1
- package/dist/core/decorators.js +9 -9
- package/dist/core/decorators.js.map +1 -1
- package/dist/core/di/container.d.ts +21 -4
- package/dist/core/di/container.d.ts.map +1 -1
- package/dist/core/di/container.js +11 -7
- package/dist/core/di/container.js.map +1 -1
- package/dist/core/di/injectable.decorator.d.ts +5 -3
- package/dist/core/di/injectable.decorator.d.ts.map +1 -1
- package/dist/core/di/injectable.decorator.js.map +1 -1
- package/dist/core/errors.d.ts +4 -4
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/events/event-emitter.d.ts +3 -3
- package/dist/core/events/event-emitter.d.ts.map +1 -1
- package/dist/core/events/event-emitter.js.map +1 -1
- package/dist/core/events/event.decorator.d.ts +5 -5
- package/dist/core/events/event.decorator.d.ts.map +1 -1
- package/dist/core/events/event.decorator.js +10 -6
- package/dist/core/events/event.decorator.js.map +1 -1
- package/dist/core/events/log-emitter.d.ts +7 -1
- package/dist/core/events/log-emitter.d.ts.map +1 -1
- package/dist/core/events/log-emitter.js.map +1 -1
- package/dist/core/filters/exception-filter.decorator.d.ts +5 -5
- package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -1
- package/dist/core/filters/exception-filter.decorator.js +3 -3
- package/dist/core/filters/exception-filter.decorator.js.map +1 -1
- package/dist/core/filters/exception-filter.interface.d.ts +14 -5
- package/dist/core/filters/exception-filter.interface.d.ts.map +1 -1
- package/dist/core/guards/apikey.guard.d.ts +1 -1
- package/dist/core/guards/apikey.guard.d.ts.map +1 -1
- package/dist/core/guards/guard.interface.d.ts +1 -1
- package/dist/core/guards/guard.interface.d.ts.map +1 -1
- package/dist/core/guards/jwt.guard.d.ts +1 -1
- package/dist/core/guards/jwt.guard.d.ts.map +1 -1
- package/dist/core/guards/oauth.guard.d.ts +1 -1
- package/dist/core/guards/oauth.guard.d.ts.map +1 -1
- package/dist/core/guards/use-guards.decorator.d.ts +3 -3
- package/dist/core/guards/use-guards.decorator.d.ts.map +1 -1
- package/dist/core/guards/use-guards.decorator.js +1 -1
- package/dist/core/guards/use-guards.decorator.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/interceptors/interceptor.decorator.d.ts +4 -4
- package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -1
- package/dist/core/interceptors/interceptor.decorator.js +2 -2
- package/dist/core/interceptors/interceptor.decorator.js.map +1 -1
- package/dist/core/interceptors/interceptor.interface.d.ts +3 -3
- package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -1
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js.map +1 -1
- package/dist/core/middleware/middleware.decorator.d.ts +4 -4
- package/dist/core/middleware/middleware.decorator.d.ts.map +1 -1
- package/dist/core/middleware/middleware.decorator.js +2 -2
- package/dist/core/middleware/middleware.decorator.js.map +1 -1
- package/dist/core/middleware/middleware.interface.d.ts +3 -3
- package/dist/core/middleware/middleware.interface.d.ts.map +1 -1
- package/dist/core/module.d.ts +33 -14
- package/dist/core/module.d.ts.map +1 -1
- package/dist/core/module.js +11 -6
- package/dist/core/module.js.map +1 -1
- package/dist/core/oauth-module.d.ts +9 -3
- package/dist/core/oauth-module.d.ts.map +1 -1
- package/dist/core/oauth-module.js +4 -3
- package/dist/core/oauth-module.js.map +1 -1
- package/dist/core/pipes/pipe.decorator.d.ts +14 -5
- package/dist/core/pipes/pipe.decorator.d.ts.map +1 -1
- package/dist/core/pipes/pipe.decorator.js +2 -2
- package/dist/core/pipes/pipe.decorator.js.map +1 -1
- package/dist/core/pipes/pipe.interface.d.ts +9 -4
- package/dist/core/pipes/pipe.interface.d.ts.map +1 -1
- package/dist/core/prompt.d.ts +13 -4
- package/dist/core/prompt.d.ts.map +1 -1
- package/dist/core/prompt.js +2 -2
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/resource.d.ts +7 -2
- package/dist/core/resource.d.ts.map +1 -1
- package/dist/core/resource.js +2 -2
- package/dist/core/resource.js.map +1 -1
- package/dist/core/server.d.ts +49 -3
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +61 -34
- package/dist/core/server.js.map +1 -1
- package/dist/core/tool.d.ts +44 -16
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +19 -6
- package/dist/core/tool.js.map +1 -1
- package/dist/core/transports/discovery-http-server.d.ts +7 -1
- package/dist/core/transports/discovery-http-server.d.ts.map +1 -1
- package/dist/core/transports/discovery-http-server.js.map +1 -1
- package/dist/core/transports/http-server.d.ts +2 -2
- package/dist/core/transports/http-server.d.ts.map +1 -1
- package/dist/core/transports/http-server.js +1 -1
- package/dist/core/transports/http-server.js.map +1 -1
- package/dist/core/transports/streamable-http.d.ts +4 -4
- package/dist/core/transports/streamable-http.d.ts.map +1 -1
- package/dist/core/transports/streamable-http.js +1 -1
- package/dist/core/transports/streamable-http.js.map +1 -1
- package/dist/core/types.d.ts +87 -15
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/widgets/widget-registry.d.ts +2 -2
- package/dist/core/widgets/widget-registry.d.ts.map +1 -1
- package/dist/core/widgets/widget-registry.js +1 -1
- package/dist/core/widgets/widget-registry.js.map +1 -1
- package/dist/testing/index.d.ts +44 -17
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +5 -8
- package/dist/testing/index.js.map +1 -1
- package/dist/ui-next/index.d.ts +1 -1
- package/dist/ui-next/index.d.ts.map +1 -1
- package/dist/ui-next/index.js.map +1 -1
- package/dist/widgets/hooks/useWidgetSDK.d.ts +5 -5
- package/dist/widgets/runtime/WidgetLayout.js.map +1 -1
- package/dist/widgets/sdk.d.ts +5 -5
- package/dist/widgets/sdk.d.ts.map +1 -1
- package/dist/widgets/sdk.js.map +1 -1
- package/package.json +1 -1
- package/src/studio/app/api/auth/fetch-metadata/route.ts +3 -2
- package/src/studio/app/api/auth/register-client/route.ts +3 -2
- package/src/studio/app/api/chat/route.ts +33 -17
- package/src/studio/app/api/health/checks/route.ts +5 -4
- package/src/studio/app/api/init/route.ts +3 -2
- package/src/studio/app/api/ping/route.ts +3 -2
- package/src/studio/app/api/prompts/[name]/route.ts +4 -3
- package/src/studio/app/api/prompts/route.ts +3 -2
- package/src/studio/app/api/resources/[...uri]/route.ts +3 -2
- package/src/studio/app/api/resources/route.ts +3 -2
- package/src/studio/app/api/roots/route.ts +3 -2
- package/src/studio/app/api/sampling/route.ts +3 -2
- package/src/studio/app/api/tools/[name]/call/route.ts +3 -2
- package/src/studio/app/api/tools/route.ts +4 -3
- package/src/studio/app/api/widget-examples/route.ts +5 -4
- package/src/studio/app/auth/callback/page.tsx +9 -8
- package/src/studio/app/chat/page.tsx +1535 -468
- package/src/studio/app/chat/page.tsx.backup +1046 -187
- package/src/studio/app/globals.css +361 -191
- package/src/studio/app/health/page.tsx +73 -77
- package/src/studio/app/layout.tsx +9 -11
- package/src/studio/app/logs/page.tsx +31 -32
- package/src/studio/app/page.tsx +136 -232
- package/src/studio/app/prompts/page.tsx +115 -97
- package/src/studio/app/resources/page.tsx +115 -124
- package/src/studio/app/settings/page.tsx +1083 -127
- package/src/studio/app/tools/page.tsx +343 -0
- package/src/studio/components/EnlargeModal.tsx +76 -65
- package/src/studio/components/LogMessage.tsx +6 -6
- package/src/studio/components/MarkdownRenderer.tsx +246 -349
- package/src/studio/components/Sidebar.tsx +165 -210
- package/src/studio/components/SplashScreen.tsx +109 -0
- package/src/studio/components/ToolCard.tsx +50 -41
- package/src/studio/components/VoiceOrbOverlay.tsx +475 -0
- package/src/studio/components/WidgetErrorBoundary.tsx +48 -0
- package/src/studio/components/WidgetRenderer.tsx +169 -211
- package/src/studio/components/ops/OpsCanvas.tsx +748 -0
- package/src/studio/components/ops/OpsNodeDetailPanel.tsx +150 -0
- package/src/studio/components/ops/OpsSummaryBar.tsx +90 -0
- package/src/studio/components/ops/index.ts +5 -0
- package/src/studio/components/ops/nodes/BaseNode.tsx +65 -0
- package/src/studio/components/ops/nodes/LLMCallNode.tsx +34 -0
- package/src/studio/components/ops/nodes/LLMResponseNode.tsx +33 -0
- package/src/studio/components/ops/nodes/ToolCallNode.tsx +30 -0
- package/src/studio/components/ops/nodes/ToolResultNode.tsx +43 -0
- package/src/studio/components/ops/nodes/UserPromptNode.tsx +34 -0
- package/src/studio/components/ops/nodes/WidgetRenderNode.tsx +23 -0
- package/src/studio/components/ops/nodes/index.ts +8 -0
- package/src/studio/components/tools/ToolsCanvas.tsx +327 -0
- package/src/studio/lib/api.ts +61 -42
- package/src/studio/lib/http-client-transport.ts +2 -2
- package/src/studio/lib/llm-service.ts +126 -47
- package/src/studio/lib/mcp-client.ts +9 -6
- package/src/studio/lib/ops-store.ts +427 -0
- package/src/studio/lib/ops-tracker.ts +416 -0
- package/src/studio/lib/ops-types.ts +164 -0
- package/src/studio/lib/store.ts +23 -11
- package/src/studio/lib/types.ts +228 -38
- package/src/studio/lib/widget-loader.ts +2 -2
- package/src/studio/package-lock.json +3303 -0
- package/src/studio/package.json +3 -1
- package/src/studio/public/NitroStudio Isotype Color.png +0 -0
- package/src/studio/tailwind.config.ts +63 -17
- package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +19 -22
- package/dist/cli/build-widgets.mjs +0 -165
- package/src/studio/app/auth/page.tsx +0 -560
- package/src/studio/app/ping/page.tsx +0 -209
|
@@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
|
|
|
4
4
|
import { useStudioStore } from '@/lib/store';
|
|
5
5
|
import { api } from '@/lib/api';
|
|
6
6
|
import type { Prompt } from '@/lib/types';
|
|
7
|
-
import {
|
|
7
|
+
import { DocumentTextIcon, ArrowPathIcon, XMarkIcon, PlayIcon, ExclamationCircleIcon } from '@heroicons/react/24/outline';
|
|
8
8
|
|
|
9
9
|
export default function PromptsPage() {
|
|
10
10
|
const { prompts, setPrompts, loading, setLoading } = useStudioStore();
|
|
@@ -54,23 +54,16 @@ export default function PromptsPage() {
|
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
56
|
<div className="fixed inset-0 flex flex-col bg-background" style={{ left: 'var(--sidebar-width, 15rem)' }}>
|
|
57
|
-
{/*
|
|
58
|
-
<div className="sticky top-0 z-10 border-b border-border/50 px-6 py-
|
|
59
|
-
<
|
|
60
|
-
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center shadow-md">
|
|
61
|
-
<FileText className="w-5 h-5 text-white" strokeWidth={2.5} />
|
|
62
|
-
</div>
|
|
63
|
-
<div>
|
|
64
|
-
<h1 className="text-lg font-bold text-foreground">Prompts</h1>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
57
|
+
{/* Minimal Professional Header */}
|
|
58
|
+
<div className="sticky top-0 z-10 border-b border-border/50 px-6 py-4 flex items-center justify-between bg-card/50 backdrop-blur-sm">
|
|
59
|
+
<h1 className="text-lg font-semibold text-foreground">Prompts</h1>
|
|
67
60
|
<button onClick={loadPrompts} className="btn btn-primary text-sm px-4 py-2 gap-2">
|
|
68
|
-
<
|
|
61
|
+
<ArrowPathIcon className="h-4 w-4" />
|
|
69
62
|
Refresh
|
|
70
63
|
</button>
|
|
71
64
|
</div>
|
|
72
65
|
|
|
73
|
-
{/* Content
|
|
66
|
+
{/* Content */}
|
|
74
67
|
<div className="flex-1 overflow-y-auto overflow-x-hidden">
|
|
75
68
|
<div className="max-w-7xl mx-auto px-6 py-6">
|
|
76
69
|
<input
|
|
@@ -90,7 +83,7 @@ export default function PromptsPage() {
|
|
|
90
83
|
</div>
|
|
91
84
|
) : filteredPrompts.length === 0 ? (
|
|
92
85
|
<div className="empty-state">
|
|
93
|
-
<
|
|
86
|
+
<ExclamationCircleIcon className="empty-state-icon" />
|
|
94
87
|
<p className="empty-state-title">
|
|
95
88
|
{searchQuery ? 'No prompts found' : 'No prompts available'}
|
|
96
89
|
</p>
|
|
@@ -99,35 +92,42 @@ export default function PromptsPage() {
|
|
|
99
92
|
</p>
|
|
100
93
|
</div>
|
|
101
94
|
) : (
|
|
102
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-
|
|
95
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
103
96
|
{filteredPrompts.map((prompt) => (
|
|
104
97
|
<div
|
|
105
98
|
key={prompt.name}
|
|
106
|
-
className="card
|
|
99
|
+
className="group relative bg-card/50 border border-border/50 rounded-xl p-5 cursor-pointer transition-all duration-200 hover:bg-card hover:border-border hover:shadow-lg animate-fade-in"
|
|
107
100
|
onClick={() => {
|
|
108
101
|
setSelectedPrompt(prompt);
|
|
109
102
|
setPromptArgs({});
|
|
110
103
|
setPromptResult(null);
|
|
111
104
|
}}
|
|
112
105
|
>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
{/* Gradient hover effect */}
|
|
107
|
+
<div className="absolute inset-0 rounded-xl bg-gradient-to-br from-primary/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
108
|
+
|
|
109
|
+
<div className="relative">
|
|
110
|
+
<div className="flex items-center gap-3 mb-3">
|
|
111
|
+
<div className="w-8 h-8 rounded-lg bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-colors">
|
|
112
|
+
<DocumentTextIcon className="w-4 h-4 text-primary" />
|
|
113
|
+
</div>
|
|
114
|
+
<h3 className="text-sm font-medium text-foreground group-hover:text-primary transition-colors truncate">
|
|
115
|
+
{prompt.name}
|
|
116
|
+
</h3>
|
|
116
117
|
</div>
|
|
117
|
-
<h3 className="font-semibold text-foreground">{prompt.name}</h3>
|
|
118
|
-
</div>
|
|
119
118
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
<p className="text-xs text-muted-foreground/80 line-clamp-2 mb-3 leading-relaxed">
|
|
120
|
+
{prompt.description || 'No description'}
|
|
121
|
+
</p>
|
|
123
122
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
123
|
+
{prompt.arguments && prompt.arguments.length > 0 && (
|
|
124
|
+
<div className="flex items-center gap-1.5">
|
|
125
|
+
<span className="text-[10px] font-medium px-2 py-0.5 rounded-full bg-muted/50 text-muted-foreground">
|
|
126
|
+
{prompt.arguments.length} arg{prompt.arguments.length !== 1 ? 's' : ''}
|
|
127
|
+
</span>
|
|
128
|
+
</div>
|
|
129
|
+
)}
|
|
130
|
+
</div>
|
|
131
131
|
</div>
|
|
132
132
|
))}
|
|
133
133
|
</div>
|
|
@@ -135,93 +135,111 @@ export default function PromptsPage() {
|
|
|
135
135
|
</div>
|
|
136
136
|
</div>
|
|
137
137
|
|
|
138
|
-
{/* Prompt Executor
|
|
138
|
+
{/* Prompt Executor Side Drawer */}
|
|
139
139
|
{selectedPrompt && (
|
|
140
140
|
<div
|
|
141
|
-
className="fixed inset-0 z-50 flex
|
|
142
|
-
style={{ backgroundColor: 'rgba(0, 0, 0, 0.85)' }}
|
|
141
|
+
className="fixed inset-0 z-50 flex justify-end bg-background/80 backdrop-blur-sm animate-fade-in"
|
|
143
142
|
onClick={() => setSelectedPrompt(null)}
|
|
144
143
|
>
|
|
145
144
|
<div
|
|
146
|
-
className="
|
|
145
|
+
className="relative w-full max-w-2xl h-full bg-card border-l border-border shadow-2xl overflow-hidden animate-slide-in-right flex flex-col"
|
|
147
146
|
onClick={(e) => e.stopPropagation()}
|
|
148
147
|
>
|
|
149
|
-
|
|
148
|
+
{/* Header */}
|
|
149
|
+
<div className="flex items-center justify-between px-6 py-4 border-b border-border bg-card">
|
|
150
150
|
<div className="flex items-center gap-3">
|
|
151
151
|
<div className="w-10 h-10 rounded-lg bg-blue-500/10 flex items-center justify-center">
|
|
152
|
-
<
|
|
152
|
+
<DocumentTextIcon className="w-5 h-5 text-blue-500" />
|
|
153
|
+
</div>
|
|
154
|
+
<div>
|
|
155
|
+
<h2 className="text-lg font-bold text-foreground">{selectedPrompt.name}</h2>
|
|
156
|
+
<p className="text-xs text-muted-foreground">Prompt Executor</p>
|
|
153
157
|
</div>
|
|
154
|
-
<h2 className="text-xl font-bold text-foreground">{selectedPrompt.name}</h2>
|
|
155
158
|
</div>
|
|
156
159
|
<button
|
|
157
160
|
onClick={() => setSelectedPrompt(null)}
|
|
158
|
-
className="btn btn-ghost w-
|
|
161
|
+
className="btn btn-ghost w-8 h-8 p-0 flex items-center justify-center rounded-full hover:bg-muted"
|
|
162
|
+
aria-label="Close"
|
|
159
163
|
>
|
|
160
|
-
<
|
|
164
|
+
<XMarkIcon className="w-5 h-5" />
|
|
161
165
|
</button>
|
|
162
166
|
</div>
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
168
|
+
{/* Scrollable Content */}
|
|
169
|
+
<div className="flex-1 overflow-y-auto bg-muted/5 p-6">
|
|
170
|
+
|
|
171
|
+
<div className="bg-card p-4 rounded-xl border border-border mb-6">
|
|
172
|
+
<p className="text-sm text-foreground leading-relaxed">
|
|
173
|
+
{selectedPrompt.description || 'No description available'}
|
|
174
|
+
</p>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<form onSubmit={handleExecutePrompt} className="space-y-6">
|
|
178
|
+
<div className="space-y-4">
|
|
179
|
+
{selectedPrompt.arguments && selectedPrompt.arguments.length > 0 ? (
|
|
180
|
+
selectedPrompt.arguments.map((arg) => (
|
|
181
|
+
<div key={arg.name}>
|
|
182
|
+
<label className="block text-sm font-medium text-foreground mb-2">
|
|
183
|
+
{arg.name}
|
|
184
|
+
{arg.required && <span className="text-destructive ml-1">*</span>}
|
|
185
|
+
</label>
|
|
186
|
+
<input
|
|
187
|
+
type="text"
|
|
188
|
+
className="input w-full"
|
|
189
|
+
value={promptArgs[arg.name] || ''}
|
|
190
|
+
onChange={(e) =>
|
|
191
|
+
setPromptArgs({ ...promptArgs, [arg.name]: e.target.value })
|
|
192
|
+
}
|
|
193
|
+
required={arg.required}
|
|
194
|
+
placeholder={arg.description || `Enter ${arg.name}`}
|
|
195
|
+
/>
|
|
196
|
+
{arg.description && (
|
|
197
|
+
<p className="text-xs text-muted-foreground mt-1">{arg.description}</p>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
200
|
+
))
|
|
201
|
+
) : (
|
|
202
|
+
<div className="p-4 bg-muted/30 rounded-lg border border-border border-dashed text-center">
|
|
203
|
+
<p className="text-sm text-muted-foreground">No arguments required</p>
|
|
204
|
+
</div>
|
|
205
|
+
)}
|
|
194
206
|
</div>
|
|
195
|
-
)}
|
|
196
207
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
208
|
+
<div className="sticky bottom-0 -mx-6 -mb-6 p-6 bg-card border-t border-border mt-auto">
|
|
209
|
+
<button type="submit" className="btn btn-primary w-full gap-2 py-3" disabled={executing}>
|
|
210
|
+
<PlayIcon className="w-4 h-4" />
|
|
211
|
+
{executing ? 'Executing...' : 'Execute Prompt'}
|
|
212
|
+
</button>
|
|
213
|
+
</div>
|
|
214
|
+
</form>
|
|
215
|
+
|
|
216
|
+
{/* Result */}
|
|
217
|
+
{promptResult && (
|
|
218
|
+
<div className="mt-8 pt-8 border-t border-border animate-fade-in">
|
|
219
|
+
<div className="flex items-center justify-between mb-3">
|
|
220
|
+
<h3 className="font-semibold text-foreground">Messages</h3>
|
|
221
|
+
<div className="badge badge-success text-xs">Generated</div>
|
|
222
|
+
</div>
|
|
223
|
+
<div className="space-y-3">
|
|
224
|
+
{promptResult.messages?.map((msg: { role: string; content: string | { text?: string } }, idx: number) => {
|
|
225
|
+
// Extract text from content (can be string or object with type/text)
|
|
226
|
+
const contentText = typeof msg.content === 'string'
|
|
227
|
+
? msg.content
|
|
228
|
+
: (msg.content as { text?: string })?.text || JSON.stringify(msg.content);
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<div key={idx} className="bg-card border border-border p-4 rounded-xl shadow-sm">
|
|
232
|
+
<div className="text-xs text-muted-foreground mb-2 uppercase font-bold tracking-wider opacity-70">
|
|
233
|
+
{msg.role}
|
|
234
|
+
</div>
|
|
235
|
+
<div className="text-sm whitespace-pre-wrap text-foreground font-mono leading-relaxed">{contentText}</div>
|
|
217
236
|
</div>
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
})}
|
|
237
|
+
);
|
|
238
|
+
})}
|
|
239
|
+
</div>
|
|
222
240
|
</div>
|
|
223
|
-
|
|
224
|
-
|
|
241
|
+
)}
|
|
242
|
+
</div>
|
|
225
243
|
</div>
|
|
226
244
|
</div>
|
|
227
245
|
)}
|
|
@@ -5,7 +5,7 @@ import { useStudioStore } from '@/lib/store';
|
|
|
5
5
|
import { api } from '@/lib/api';
|
|
6
6
|
import { WidgetRenderer } from '@/components/WidgetRenderer';
|
|
7
7
|
import type { Resource } from '@/lib/types';
|
|
8
|
-
import {
|
|
8
|
+
import { CubeIcon, ArrowPathIcon, PaintBrushIcon, ArrowsPointingOutIcon, SparklesIcon, ExclamationCircleIcon } from '@heroicons/react/24/outline';
|
|
9
9
|
|
|
10
10
|
interface WidgetExample {
|
|
11
11
|
name: string;
|
|
@@ -52,13 +52,13 @@ export default function ResourcesPage() {
|
|
|
52
52
|
const data = await api.getWidgetExamples();
|
|
53
53
|
console.log('📦 Widget examples response:', data);
|
|
54
54
|
console.log('📦 Number of widgets loaded:', data.widgets?.length || 0);
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
if (data.widgets && data.widgets.length > 0) {
|
|
57
57
|
console.log('📦 First widget:', data.widgets[0]);
|
|
58
58
|
} else {
|
|
59
59
|
console.warn('⚠️ No widgets returned from API. Check MCP server logs.');
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
setWidgets(data.widgets || []);
|
|
63
63
|
} catch (error) {
|
|
64
64
|
console.error('❌ Failed to load widget examples:', error);
|
|
@@ -68,9 +68,9 @@ export default function ResourcesPage() {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
const isUIWidget = (resource: Resource) => {
|
|
71
|
-
return resource.mimeType === 'text/html' ||
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
return resource.mimeType === 'text/html' ||
|
|
72
|
+
resource.uri.startsWith('widget://') ||
|
|
73
|
+
resource._meta?.['ui/widget'] === true;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
const filteredResources = resources.filter(
|
|
@@ -97,9 +97,9 @@ export default function ResourcesPage() {
|
|
|
97
97
|
const handleWidgetEnlarge = useCallback((e: React.MouseEvent, widget: WidgetMetadata) => {
|
|
98
98
|
e.preventDefault();
|
|
99
99
|
e.stopPropagation();
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
const exampleIndex = getSelectedExample(widget.uri);
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
setTimeout(() => {
|
|
104
104
|
openEnlargeModal('resource', {
|
|
105
105
|
uri: widget.uri,
|
|
@@ -112,18 +112,11 @@ export default function ResourcesPage() {
|
|
|
112
112
|
|
|
113
113
|
return (
|
|
114
114
|
<div className="fixed inset-0 flex flex-col bg-background" style={{ left: 'var(--sidebar-width, 15rem)' }}>
|
|
115
|
-
{/*
|
|
116
|
-
<div className="sticky top-0 z-10 border-b border-border/50 px-6 py-
|
|
117
|
-
<
|
|
118
|
-
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center shadow-md">
|
|
119
|
-
<Package className="w-5 h-5 text-white" strokeWidth={2.5} />
|
|
120
|
-
</div>
|
|
121
|
-
<div>
|
|
122
|
-
<h1 className="text-lg font-bold text-foreground">Resources</h1>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
115
|
+
{/* Minimal Professional Header */}
|
|
116
|
+
<div className="sticky top-0 z-10 border-b border-border/50 px-6 py-4 flex items-center justify-between bg-card/50 backdrop-blur-sm">
|
|
117
|
+
<h1 className="text-lg font-semibold text-foreground">Resources</h1>
|
|
125
118
|
<button onClick={loadResources} className="btn btn-primary text-sm px-4 py-2 gap-2">
|
|
126
|
-
<
|
|
119
|
+
<ArrowPathIcon className="h-4 w-4" />
|
|
127
120
|
Refresh
|
|
128
121
|
</button>
|
|
129
122
|
</div>
|
|
@@ -142,114 +135,115 @@ export default function ResourcesPage() {
|
|
|
142
135
|
{/* UI Widgets Section */}
|
|
143
136
|
{(loadingWidgets || widgets.length > 0) && (
|
|
144
137
|
<div className="mb-12">
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
{loadingWidgets ? (
|
|
151
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
152
|
-
{[1, 2].map((i) => (
|
|
153
|
-
<div key={i} className="card skeleton h-96"></div>
|
|
154
|
-
))}
|
|
155
|
-
</div>
|
|
156
|
-
) : filteredWidgets.length === 0 ? (
|
|
157
|
-
<div className="card p-8 text-center">
|
|
158
|
-
<AlertCircle className="w-12 h-12 text-muted-foreground mx-auto mb-3" />
|
|
159
|
-
<p className="text-muted-foreground">
|
|
160
|
-
{searchQuery ? 'No widgets match your search' : 'No UI widgets configured'}
|
|
161
|
-
</p>
|
|
162
|
-
</div>
|
|
163
|
-
) : (
|
|
164
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
165
|
-
{filteredWidgets.map((widget) => (
|
|
166
|
-
<div key={widget.uri} className="card card-hover p-6 animate-fade-in">
|
|
167
|
-
<div className="flex items-center gap-3 mb-4">
|
|
168
|
-
<div className="w-10 h-10 rounded-lg bg-purple-500/10 flex items-center justify-center">
|
|
169
|
-
<Palette className="w-5 h-5 text-purple-500" />
|
|
170
|
-
</div>
|
|
171
|
-
<div className="flex-1">
|
|
172
|
-
<h3 className="font-semibold text-foreground">{widget.name}</h3>
|
|
173
|
-
<span className="badge badge-success text-xs mt-1">
|
|
174
|
-
{widget.examples.length} example{widget.examples.length !== 1 ? 's' : ''}
|
|
175
|
-
</span>
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
138
|
+
<h2 className="text-2xl font-bold text-foreground mb-6 flex items-center gap-2">
|
|
139
|
+
<PaintBrushIcon className="w-6 h-6 text-primary" />
|
|
140
|
+
UI Widgets {widgets.length > 0 && `(${filteredWidgets.length})`}
|
|
141
|
+
</h2>
|
|
178
142
|
|
|
179
|
-
|
|
180
|
-
|
|
143
|
+
{loadingWidgets ? (
|
|
144
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
145
|
+
{[1, 2].map((i) => (
|
|
146
|
+
<div key={i} className="card skeleton h-96"></div>
|
|
147
|
+
))}
|
|
148
|
+
</div>
|
|
149
|
+
) : filteredWidgets.length === 0 ? (
|
|
150
|
+
<div className="card p-8 text-center">
|
|
151
|
+
<ExclamationCircleIcon className="w-12 h-12 text-muted-foreground mx-auto mb-3" />
|
|
152
|
+
<p className="text-muted-foreground">
|
|
153
|
+
{searchQuery ? 'No widgets match your search' : 'No UI widgets configured'}
|
|
181
154
|
</p>
|
|
155
|
+
</div>
|
|
156
|
+
) : (
|
|
157
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
158
|
+
{filteredWidgets.map((widget) => (
|
|
159
|
+
<div key={widget.uri} className="card card-hover p-6 animate-fade-in">
|
|
160
|
+
{/* Clean Header */}
|
|
161
|
+
<div className="flex items-center gap-3 mb-3">
|
|
162
|
+
<PaintBrushIcon className="h-5 w-5 text-secondary flex-shrink-0" />
|
|
163
|
+
<div className="flex-1 min-w-0">
|
|
164
|
+
<h3 className="font-medium text-[15px] text-foreground leading-tight truncate">{widget.name}</h3>
|
|
165
|
+
<div className="flex items-center gap-1.5 text-xs text-muted-foreground leading-none mt-1">
|
|
166
|
+
<span>Widget</span>
|
|
167
|
+
<span className="text-muted-foreground/40">•</span>
|
|
168
|
+
<span>{widget.examples.length} example{widget.examples.length !== 1 ? 's' : ''}</span>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
182
172
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
173
|
+
<p className="text-sm text-muted-foreground mb-3 line-clamp-2">
|
|
174
|
+
{widget.description}
|
|
175
|
+
</p>
|
|
186
176
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
{widget.examples.length > 0 && (() => {
|
|
199
|
-
const selectedIdx = getSelectedExample(widget.uri);
|
|
200
|
-
const selectedExample = widget.examples[selectedIdx];
|
|
201
|
-
return (
|
|
202
|
-
<div className="relative mb-4 rounded-lg overflow-hidden border border-border bg-muted/20">
|
|
203
|
-
<div className="absolute top-2 left-2 z-10 flex items-center gap-1 bg-primary/90 backdrop-blur-sm text-black px-2 py-1 rounded-md text-xs font-semibold shadow-lg">
|
|
204
|
-
<Sparkles className="w-3 h-3" />
|
|
205
|
-
{selectedExample.name}
|
|
206
|
-
</div>
|
|
207
|
-
<div className="h-64">
|
|
208
|
-
<WidgetRenderer
|
|
209
|
-
uri={widget.uri}
|
|
210
|
-
data={selectedExample.data}
|
|
211
|
-
/>
|
|
177
|
+
<p className="text-xs text-muted-foreground mb-4 font-mono truncate bg-muted/30 px-2 py-1 rounded">
|
|
178
|
+
{widget.uri}
|
|
179
|
+
</p>
|
|
180
|
+
|
|
181
|
+
{widget.tags && widget.tags.length > 0 && (
|
|
182
|
+
<div className="flex flex-wrap gap-2 mb-4">
|
|
183
|
+
{widget.tags.map((tag) => (
|
|
184
|
+
<span key={tag} className="badge badge-secondary text-xs">
|
|
185
|
+
#{tag}
|
|
186
|
+
</span>
|
|
187
|
+
))}
|
|
212
188
|
</div>
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
189
|
+
)}
|
|
190
|
+
|
|
191
|
+
{/* Widget Preview with selected example */}
|
|
192
|
+
{widget.examples.length > 0 && (() => {
|
|
193
|
+
const selectedIdx = getSelectedExample(widget.uri);
|
|
194
|
+
const selectedExample = widget.examples[selectedIdx];
|
|
195
|
+
return (
|
|
196
|
+
<div className="relative mb-4 rounded-lg overflow-hidden border border-border bg-muted/20">
|
|
197
|
+
<div className="absolute top-2 left-2 z-10 flex items-center gap-1 bg-primary/90 backdrop-blur-sm text-black px-2 py-1 rounded-md text-xs font-semibold shadow-lg">
|
|
198
|
+
<SparklesIcon className="w-3 h-3" />
|
|
199
|
+
{selectedExample.name}
|
|
200
|
+
</div>
|
|
201
|
+
<div className="h-64">
|
|
202
|
+
<WidgetRenderer
|
|
203
|
+
uri={widget.uri}
|
|
204
|
+
data={selectedExample.data}
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
})()}
|
|
210
|
+
|
|
211
|
+
{/* Example Selector (if more than 1) */}
|
|
212
|
+
{widget.examples.length > 1 && (
|
|
213
|
+
<select
|
|
214
|
+
className="input text-sm mb-4"
|
|
215
|
+
value={getSelectedExample(widget.uri)}
|
|
216
|
+
onChange={(e) => handleExampleChange(widget.uri, parseInt(e.target.value))}
|
|
217
|
+
>
|
|
218
|
+
{widget.examples.map((example, idx) => (
|
|
219
|
+
<option key={idx} value={idx}>
|
|
220
|
+
{example.name}
|
|
221
|
+
</option>
|
|
222
|
+
))}
|
|
223
|
+
</select>
|
|
224
|
+
)}
|
|
225
|
+
|
|
226
|
+
<button
|
|
227
|
+
onClick={(e) => handleWidgetEnlarge(e, widget)}
|
|
228
|
+
className="btn btn-secondary w-full gap-2"
|
|
229
|
+
>
|
|
230
|
+
<ArrowsPointingOutIcon className="w-4 h-4" />
|
|
231
|
+
Enlarge
|
|
232
|
+
</button>
|
|
233
|
+
</div>
|
|
234
|
+
))}
|
|
239
235
|
</div>
|
|
240
|
-
)
|
|
241
|
-
</div>
|
|
242
|
-
)}
|
|
236
|
+
)}
|
|
243
237
|
</div>
|
|
244
238
|
)}
|
|
245
239
|
|
|
246
240
|
{/* MCP Resources Section */}
|
|
247
241
|
<div>
|
|
248
242
|
<h2 className="text-2xl font-bold text-foreground mb-6 flex items-center gap-2">
|
|
249
|
-
<
|
|
243
|
+
<CubeIcon className="w-6 h-6 text-primary" />
|
|
250
244
|
MCP Resources {resources.length > 0 && `(${filteredResources.length})`}
|
|
251
245
|
</h2>
|
|
252
|
-
|
|
246
|
+
|
|
253
247
|
{/* Resources Grid */}
|
|
254
248
|
{loading.resources ? (
|
|
255
249
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
@@ -259,7 +253,7 @@ export default function ResourcesPage() {
|
|
|
259
253
|
</div>
|
|
260
254
|
) : filteredResources.length === 0 ? (
|
|
261
255
|
<div className="empty-state">
|
|
262
|
-
<
|
|
256
|
+
<CubeIcon className="empty-state-icon" />
|
|
263
257
|
<p className="empty-state-title">
|
|
264
258
|
{searchQuery ? 'No resources found' : 'No resources available'}
|
|
265
259
|
</p>
|
|
@@ -271,16 +265,13 @@ export default function ResourcesPage() {
|
|
|
271
265
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
272
266
|
{filteredResources.map((resource) => (
|
|
273
267
|
<div key={resource.uri} className="card card-hover p-6 animate-fade-in">
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
</
|
|
279
|
-
<div>
|
|
280
|
-
<
|
|
281
|
-
<span className="badge badge-primary text-xs mt-1">
|
|
282
|
-
Resource
|
|
283
|
-
</span>
|
|
268
|
+
{/* Clean Header */}
|
|
269
|
+
<div className="flex items-center gap-3 mb-3">
|
|
270
|
+
<CubeIcon className="h-5 w-5 text-primary flex-shrink-0" />
|
|
271
|
+
<div className="flex-1 min-w-0">
|
|
272
|
+
<h3 className="font-medium text-[15px] text-foreground leading-tight truncate">{resource.name}</h3>
|
|
273
|
+
<div className="flex items-center gap-1.5 text-xs text-muted-foreground leading-none mt-1">
|
|
274
|
+
<span>Resource</span>
|
|
284
275
|
</div>
|
|
285
276
|
</div>
|
|
286
277
|
</div>
|