nitrostack 1.0.65 → 1.0.66
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/package.json +2 -1
- package/src/studio/README.md +140 -0
- package/src/studio/app/api/auth/fetch-metadata/route.ts +71 -0
- package/src/studio/app/api/auth/register-client/route.ts +67 -0
- package/src/studio/app/api/chat/route.ts +250 -0
- package/src/studio/app/api/health/checks/route.ts +42 -0
- package/src/studio/app/api/health/route.ts +13 -0
- package/src/studio/app/api/init/route.ts +109 -0
- package/src/studio/app/api/ping/route.ts +13 -0
- package/src/studio/app/api/prompts/[name]/route.ts +21 -0
- package/src/studio/app/api/prompts/route.ts +13 -0
- package/src/studio/app/api/resources/[...uri]/route.ts +18 -0
- package/src/studio/app/api/resources/route.ts +13 -0
- package/src/studio/app/api/roots/route.ts +13 -0
- package/src/studio/app/api/sampling/route.ts +14 -0
- package/src/studio/app/api/tools/[name]/call/route.ts +41 -0
- package/src/studio/app/api/tools/route.ts +23 -0
- package/src/studio/app/api/widget-examples/route.ts +44 -0
- package/src/studio/app/auth/callback/page.tsx +175 -0
- package/src/studio/app/auth/page.tsx +560 -0
- package/src/studio/app/chat/page.tsx +1133 -0
- package/src/studio/app/chat/page.tsx.backup +390 -0
- package/src/studio/app/globals.css +486 -0
- package/src/studio/app/health/page.tsx +179 -0
- package/src/studio/app/layout.tsx +68 -0
- package/src/studio/app/logs/page.tsx +279 -0
- package/src/studio/app/page.tsx +351 -0
- package/src/studio/app/page.tsx.backup +346 -0
- package/src/studio/app/ping/page.tsx +209 -0
- package/src/studio/app/prompts/page.tsx +230 -0
- package/src/studio/app/resources/page.tsx +315 -0
- package/src/studio/app/settings/page.tsx +199 -0
- package/src/studio/branding.md +807 -0
- package/src/studio/components/EnlargeModal.tsx +138 -0
- package/src/studio/components/LogMessage.tsx +153 -0
- package/src/studio/components/MarkdownRenderer.tsx +410 -0
- package/src/studio/components/Sidebar.tsx +295 -0
- package/src/studio/components/ToolCard.tsx +139 -0
- package/src/studio/components/WidgetRenderer.tsx +346 -0
- package/src/studio/lib/api.ts +207 -0
- package/src/studio/lib/http-client-transport.ts +222 -0
- package/src/studio/lib/llm-service.ts +480 -0
- package/src/studio/lib/log-manager.ts +76 -0
- package/src/studio/lib/mcp-client.ts +258 -0
- package/src/studio/lib/store.ts +192 -0
- package/src/studio/lib/theme-provider.tsx +50 -0
- package/src/studio/lib/types.ts +107 -0
- package/src/studio/lib/widget-loader.ts +90 -0
- package/src/studio/middleware.ts +27 -0
- package/src/studio/next.config.js +38 -0
- package/src/studio/package.json +35 -0
- package/src/studio/postcss.config.mjs +10 -0
- package/src/studio/public/nitrocloud.png +0 -0
- package/src/studio/tailwind.config.ts +67 -0
- package/src/studio/tsconfig.json +42 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Widget Loader - Handles dev/prod widget loading
|
|
2
|
+
|
|
3
|
+
export function getWidgetUrl(uri: string): string {
|
|
4
|
+
// Check if we're in dev mode (widget dev server on 3001)
|
|
5
|
+
const isDevMode =
|
|
6
|
+
typeof window !== 'undefined' &&
|
|
7
|
+
(window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
|
|
8
|
+
|
|
9
|
+
if (isDevMode && uri.startsWith('/widgets/')) {
|
|
10
|
+
// Dev mode: load from Next.js dev server
|
|
11
|
+
const widgetPath = uri.replace('/widgets/', '');
|
|
12
|
+
return `http://localhost:3001/${widgetPath}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Production mode: load from same origin
|
|
16
|
+
return uri;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isDevWidget(uri: string): boolean {
|
|
20
|
+
return uri.startsWith('/widgets/') || uri.includes('component://');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function loadWidget(uri: string): Promise<{ html: string; isDevMode: boolean }> {
|
|
24
|
+
const isDevMode =
|
|
25
|
+
typeof window !== 'undefined' &&
|
|
26
|
+
(window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
|
|
27
|
+
|
|
28
|
+
if (isDevMode && uri.startsWith('/widgets/')) {
|
|
29
|
+
// Dev mode: return URL for iframe
|
|
30
|
+
return { html: getWidgetUrl(uri), isDevMode: true };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Production mode: fetch widget HTML
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(`/api/resources/${encodeURIComponent(uri)}`);
|
|
36
|
+
const data = await response.json();
|
|
37
|
+
|
|
38
|
+
if (data.contents && data.contents.length > 0) {
|
|
39
|
+
return { html: data.contents[0].text || '', isDevMode: false };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return { html: '', isDevMode: false };
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Failed to load widget:', error);
|
|
45
|
+
return { html: '', isDevMode: false };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createWidgetHTML(html: string, data: any): string {
|
|
50
|
+
const htmlParts = [
|
|
51
|
+
'<!DOCTYPE html>',
|
|
52
|
+
'<html>',
|
|
53
|
+
'<head>',
|
|
54
|
+
'<meta charset="UTF-8">',
|
|
55
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1.0">',
|
|
56
|
+
'<style>',
|
|
57
|
+
'html, body { margin: 0; padding: 0; background: transparent; }',
|
|
58
|
+
'body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }',
|
|
59
|
+
'</style>',
|
|
60
|
+
'</head>',
|
|
61
|
+
'<body>',
|
|
62
|
+
'<script>',
|
|
63
|
+
'window.openai = ' + JSON.stringify({ toolOutput: data }) + ';',
|
|
64
|
+
'</script>',
|
|
65
|
+
html,
|
|
66
|
+
'</body>',
|
|
67
|
+
'</html>',
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return htmlParts.join('\n');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function postMessageToWidget(iframe: HTMLIFrameElement, data: any, delay: number = 500) {
|
|
74
|
+
iframe.onload = () => {
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
try {
|
|
77
|
+
iframe.contentWindow?.postMessage(
|
|
78
|
+
{
|
|
79
|
+
type: 'toolOutput',
|
|
80
|
+
data,
|
|
81
|
+
},
|
|
82
|
+
'*'
|
|
83
|
+
);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error('Failed to post message to widget:', e);
|
|
86
|
+
}
|
|
87
|
+
}, delay);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Studio Middleware - Widget Proxying
|
|
2
|
+
import { NextResponse } from 'next/server';
|
|
3
|
+
import type { NextRequest } from 'next/server';
|
|
4
|
+
|
|
5
|
+
export function middleware(request: NextRequest) {
|
|
6
|
+
const { pathname } = request.nextUrl;
|
|
7
|
+
|
|
8
|
+
// In development, proxy widget requests to the widget dev server
|
|
9
|
+
if (process.env.NODE_ENV === 'development' && process.env.WIDGETS_DEV_MODE === 'true') {
|
|
10
|
+
const widgetsDevPort = process.env.WIDGETS_DEV_PORT || '3001';
|
|
11
|
+
|
|
12
|
+
// Proxy /widgets/* to widget dev server
|
|
13
|
+
if (pathname.startsWith('/widgets/')) {
|
|
14
|
+
const widgetPath = pathname.replace('/widgets/', '');
|
|
15
|
+
const targetUrl = `http://localhost:${widgetsDevPort}/${widgetPath}`;
|
|
16
|
+
|
|
17
|
+
return NextResponse.rewrite(new URL(targetUrl));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return NextResponse.next();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const config = {
|
|
25
|
+
matcher: ['/widgets/:path*'],
|
|
26
|
+
};
|
|
27
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
|
|
9
|
+
/** @type {import('next').NextConfig} */
|
|
10
|
+
const nextConfig = {
|
|
11
|
+
images: {
|
|
12
|
+
unoptimized: true,
|
|
13
|
+
},
|
|
14
|
+
typescript: {
|
|
15
|
+
ignoreBuildErrors: true,
|
|
16
|
+
},
|
|
17
|
+
eslint: {
|
|
18
|
+
ignoreDuringBuilds: true,
|
|
19
|
+
},
|
|
20
|
+
// Ensure Next transpiles our package when it's nested under node_modules
|
|
21
|
+
transpilePackages: ['nitrostack'],
|
|
22
|
+
webpack: (config) => {
|
|
23
|
+
// Provide @ alias so imports like '@/lib/store' work reliably
|
|
24
|
+
config.resolve.alias = {
|
|
25
|
+
...config.resolve.alias,
|
|
26
|
+
'@': __dirname,
|
|
27
|
+
};
|
|
28
|
+
// Do NOT inject custom TS rules; rely on Next's defaults + transpilePackages
|
|
29
|
+
return config;
|
|
30
|
+
},
|
|
31
|
+
env: {
|
|
32
|
+
MCP_SERVER_PORT: process.env.MCP_SERVER_PORT,
|
|
33
|
+
MCP_TRANSPORT_TYPE: process.env.MCP_TRANSPORT_TYPE,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default nextConfig;
|
|
38
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nitrostack/studio",
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "NitroStack Studio - Visual MCP Server Inspector",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "next dev -p 3000",
|
|
9
|
+
"build": "next build",
|
|
10
|
+
"start": "next start",
|
|
11
|
+
"lint": "next lint",
|
|
12
|
+
"export": "next build && next export"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@fontsource/inter": "^5.2.8",
|
|
16
|
+
"@fontsource/jetbrains-mono": "^5.2.8",
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
18
|
+
"clsx": "^2.1.0",
|
|
19
|
+
"eventsource": "^2.0.2",
|
|
20
|
+
"lucide-react": "^0.546.0",
|
|
21
|
+
"next": "^14.2.5",
|
|
22
|
+
"react": "^18.3.1",
|
|
23
|
+
"react-dom": "^18.3.1",
|
|
24
|
+
"zustand": "^4.5.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^22.10.5",
|
|
28
|
+
"@types/react": "^18.3.3",
|
|
29
|
+
"@types/react-dom": "^18.3.0",
|
|
30
|
+
"autoprefixer": "^10.4.19",
|
|
31
|
+
"postcss": "^8.4.38",
|
|
32
|
+
"tailwindcss": "^3.4.4",
|
|
33
|
+
"typescript": "^5.3.3"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Config } from 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
darkMode: 'class',
|
|
5
|
+
content: [
|
|
6
|
+
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
|
|
7
|
+
'./components/**/*.{js,ts,jsx,tsx,mdx}',
|
|
8
|
+
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
|
9
|
+
],
|
|
10
|
+
theme: {
|
|
11
|
+
extend: {
|
|
12
|
+
colors: {
|
|
13
|
+
// Brand colors - Gold & Black
|
|
14
|
+
primary: {
|
|
15
|
+
DEFAULT: '#d4af37', // Gold
|
|
16
|
+
50: '#fdfcf8',
|
|
17
|
+
100: '#f9f7ed',
|
|
18
|
+
200: '#f2ecd3',
|
|
19
|
+
300: '#ead9a1',
|
|
20
|
+
400: '#e2c870',
|
|
21
|
+
500: '#d4af37', // Main gold
|
|
22
|
+
600: '#b8962b',
|
|
23
|
+
700: '#967824',
|
|
24
|
+
800: '#7a6020',
|
|
25
|
+
900: '#654f1d',
|
|
26
|
+
},
|
|
27
|
+
background: 'hsl(var(--background))',
|
|
28
|
+
foreground: 'hsl(var(--foreground))',
|
|
29
|
+
card: {
|
|
30
|
+
DEFAULT: 'hsl(var(--card))',
|
|
31
|
+
foreground: 'hsl(var(--card-foreground))',
|
|
32
|
+
},
|
|
33
|
+
popover: {
|
|
34
|
+
DEFAULT: 'hsl(var(--popover))',
|
|
35
|
+
foreground: 'hsl(var(--popover-foreground))',
|
|
36
|
+
},
|
|
37
|
+
secondary: {
|
|
38
|
+
DEFAULT: 'hsl(var(--secondary))',
|
|
39
|
+
foreground: 'hsl(var(--secondary-foreground))',
|
|
40
|
+
},
|
|
41
|
+
muted: {
|
|
42
|
+
DEFAULT: 'hsl(var(--muted))',
|
|
43
|
+
foreground: 'hsl(var(--muted-foreground))',
|
|
44
|
+
},
|
|
45
|
+
accent: {
|
|
46
|
+
DEFAULT: 'hsl(var(--accent))',
|
|
47
|
+
foreground: 'hsl(var(--accent-foreground))',
|
|
48
|
+
},
|
|
49
|
+
destructive: {
|
|
50
|
+
DEFAULT: 'hsl(var(--destructive))',
|
|
51
|
+
foreground: 'hsl(var(--destructive-foreground))',
|
|
52
|
+
},
|
|
53
|
+
border: 'hsl(var(--border))',
|
|
54
|
+
input: 'hsl(var(--input))',
|
|
55
|
+
ring: 'hsl(var(--ring))',
|
|
56
|
+
},
|
|
57
|
+
borderRadius: {
|
|
58
|
+
lg: 'var(--radius)',
|
|
59
|
+
md: 'calc(var(--radius) - 2px)',
|
|
60
|
+
sm: 'calc(var(--radius) - 4px)',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
plugins: [],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default config;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": [
|
|
5
|
+
"dom",
|
|
6
|
+
"dom.iterable",
|
|
7
|
+
"esnext"
|
|
8
|
+
],
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"module": "esnext",
|
|
15
|
+
"moduleResolution": "node",
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"isolatedModules": true,
|
|
18
|
+
"jsx": "preserve",
|
|
19
|
+
"incremental": true,
|
|
20
|
+
"plugins": [
|
|
21
|
+
{
|
|
22
|
+
"name": "next"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"paths": {
|
|
26
|
+
"@/*": [
|
|
27
|
+
"./*"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"baseUrl": "."
|
|
31
|
+
},
|
|
32
|
+
"include": [
|
|
33
|
+
"next-env.d.ts",
|
|
34
|
+
"**/*.ts",
|
|
35
|
+
"**/*.tsx",
|
|
36
|
+
".next/types/**/*.ts",
|
|
37
|
+
"../../dist/studio/types/**/*.ts"
|
|
38
|
+
],
|
|
39
|
+
"exclude": [
|
|
40
|
+
"node_modules"
|
|
41
|
+
]
|
|
42
|
+
}
|