nitrostack 1.0.75 → 1.0.77
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 +1 -1
- package/src/studio/app/auth/callback/page.tsx +4 -4
- package/src/studio/app/auth/page.tsx +51 -0
- package/src/studio/app/settings/page.tsx +25 -3
- package/src/studio/components/WidgetRenderer.tsx +5 -3
- package/templates/typescript-oauth/README.md +0 -2
- package/templates/typescript-oauth/package.json +0 -1
- package/templates/typescript-pizzaz/README.md +0 -2
- package/templates/typescript-pizzaz/package.json +0 -1
- package/templates/typescript-pizzaz/src/widgets/app/pizza-list/page.tsx +2 -2
- package/templates/typescript-pizzaz/src/widgets/app/pizza-shop/page.tsx +2 -2
- package/templates/typescript-starter/README.md +0 -2
- package/templates/typescript-starter/package.json +0 -1
- package/templates/typescript-starter/src/modules/calculator/calculator.tools.ts +1 -1
package/package.json
CHANGED
|
@@ -103,9 +103,9 @@ function OAuthCallback() {
|
|
|
103
103
|
setStatus('success');
|
|
104
104
|
setMessage('Authorization successful! Redirecting...');
|
|
105
105
|
|
|
106
|
-
// Redirect back to auth
|
|
106
|
+
// Redirect back to settings auth tab after 2 seconds
|
|
107
107
|
setTimeout(() => {
|
|
108
|
-
router.push('/auth');
|
|
108
|
+
router.push('/settings?tab=auth');
|
|
109
109
|
}, 2000);
|
|
110
110
|
} else {
|
|
111
111
|
setStatus('error');
|
|
@@ -147,10 +147,10 @@ function OAuthCallback() {
|
|
|
147
147
|
<h1 className="text-2xl font-bold text-foreground mb-2">Authorization Failed</h1>
|
|
148
148
|
<p className="text-muted-foreground mb-4">{message}</p>
|
|
149
149
|
<button
|
|
150
|
-
onClick={() => router.push('/auth')}
|
|
150
|
+
onClick={() => router.push('/settings?tab=auth')}
|
|
151
151
|
className="btn btn-primary"
|
|
152
152
|
>
|
|
153
|
-
Back to
|
|
153
|
+
Back to Settings
|
|
154
154
|
</button>
|
|
155
155
|
</>
|
|
156
156
|
)}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { useRouter, useSearchParams } from 'next/navigation';
|
|
5
|
+
import { Suspense } from 'react';
|
|
6
|
+
import { ArrowPathIcon } from '@heroicons/react/24/outline';
|
|
7
|
+
|
|
8
|
+
function AuthRedirect() {
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const searchParams = useSearchParams();
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
// Preserve any query parameters that might be relevant
|
|
14
|
+
const params = new URLSearchParams();
|
|
15
|
+
params.set('tab', 'auth');
|
|
16
|
+
|
|
17
|
+
// Forward any existing params (like success messages)
|
|
18
|
+
searchParams.forEach((value, key) => {
|
|
19
|
+
if (key !== 'tab') {
|
|
20
|
+
params.set(key, value);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
router.replace(`/settings?${params.toString()}`);
|
|
25
|
+
}, [router, searchParams]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="fixed inset-0 flex items-center justify-center bg-background" style={{ left: 'var(--sidebar-width, 15rem)' }}>
|
|
29
|
+
<div className="text-center">
|
|
30
|
+
<ArrowPathIcon className="w-8 h-8 text-primary animate-spin mx-auto mb-4" />
|
|
31
|
+
<p className="text-muted-foreground">Redirecting to authentication settings...</p>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default function AuthPage() {
|
|
38
|
+
return (
|
|
39
|
+
<Suspense fallback={
|
|
40
|
+
<div className="fixed inset-0 flex items-center justify-center bg-background" style={{ left: 'var(--sidebar-width, 15rem)' }}>
|
|
41
|
+
<div className="text-center">
|
|
42
|
+
<ArrowPathIcon className="w-8 h-8 text-primary animate-spin mx-auto mb-4" />
|
|
43
|
+
<p className="text-muted-foreground">Loading...</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
}>
|
|
47
|
+
<AuthRedirect />
|
|
48
|
+
</Suspense>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect } from 'react';
|
|
3
|
+
import { useState, useEffect, Suspense } from 'react';
|
|
4
|
+
import { useSearchParams } from 'next/navigation';
|
|
4
5
|
import { api } from '@/lib/api';
|
|
5
6
|
import { useStudioStore } from '@/lib/store';
|
|
6
7
|
import {
|
|
@@ -23,7 +24,9 @@ import {
|
|
|
23
24
|
ChatBubbleLeftIcon,
|
|
24
25
|
} from '@heroicons/react/24/outline';
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
function SettingsContent() {
|
|
28
|
+
const searchParams = useSearchParams();
|
|
29
|
+
|
|
27
30
|
// Auth State
|
|
28
31
|
const { oauthState, setOAuthState } = useStudioStore();
|
|
29
32
|
const initialServerUrl =
|
|
@@ -236,7 +239,11 @@ export default function SettingsPage() {
|
|
|
236
239
|
}
|
|
237
240
|
};
|
|
238
241
|
|
|
239
|
-
|
|
242
|
+
// Get initial tab from URL query param
|
|
243
|
+
const initialTab = searchParams.get('tab') as 'general' | 'chat' | 'auth' | 'ping' | null;
|
|
244
|
+
const [activeTab, setActiveTab] = useState<'general' | 'chat' | 'auth' | 'ping'>(
|
|
245
|
+
initialTab && ['general', 'chat', 'auth', 'ping'].includes(initialTab) ? initialTab : 'general'
|
|
246
|
+
);
|
|
240
247
|
const [transport, setTransport] = useState<'stdio' | 'http'>('stdio');
|
|
241
248
|
const {
|
|
242
249
|
connection,
|
|
@@ -1153,3 +1160,18 @@ export default function SettingsPage() {
|
|
|
1153
1160
|
</div>
|
|
1154
1161
|
);
|
|
1155
1162
|
}
|
|
1163
|
+
|
|
1164
|
+
export default function SettingsPage() {
|
|
1165
|
+
return (
|
|
1166
|
+
<Suspense fallback={
|
|
1167
|
+
<div className="fixed inset-0 flex items-center justify-center bg-background" style={{ left: 'var(--sidebar-width, 15rem)' }}>
|
|
1168
|
+
<div className="text-center">
|
|
1169
|
+
<SettingsIcon className="w-8 h-8 text-muted-foreground animate-pulse mx-auto mb-4" />
|
|
1170
|
+
<p className="text-muted-foreground">Loading settings...</p>
|
|
1171
|
+
</div>
|
|
1172
|
+
</div>
|
|
1173
|
+
}>
|
|
1174
|
+
<SettingsContent />
|
|
1175
|
+
</Suspense>
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
@@ -24,13 +24,15 @@ export function WidgetRenderer({ uri, data, className = '' }: WidgetRendererProp
|
|
|
24
24
|
|
|
25
25
|
// Minimum height to prevent collapse
|
|
26
26
|
const MIN_HEIGHT = 50;
|
|
27
|
+
// Maximum height to prevent infinite growth (widgets using 100vh can cause feedback loops)
|
|
28
|
+
const MAX_HEIGHT = 2000;
|
|
27
29
|
|
|
28
|
-
// Stable handler for resize messages
|
|
30
|
+
// Stable handler for resize messages
|
|
29
31
|
const handleResize = useCallback((height: number) => {
|
|
30
32
|
if (!mountedRef.current) return;
|
|
31
33
|
if (height && typeof height === 'number' && height > 0) {
|
|
32
|
-
//
|
|
33
|
-
const newHeight = Math.max(MIN_HEIGHT, height);
|
|
34
|
+
// Clamp height between min and max to prevent infinite growth
|
|
35
|
+
const newHeight = Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, height));
|
|
34
36
|
setContentHeight(newHeight);
|
|
35
37
|
}
|
|
36
38
|
}, []);
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "NitroStack Flight Booking - Real-time flight search and booking with Duffel API integration",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"postinstall": "nitrostack install --skip-widgets || true",
|
|
9
8
|
"dev": "nitrostack dev",
|
|
10
9
|
"build": "nitrostack build",
|
|
11
10
|
"start": "npm run build && nitrostack start",
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "NitroStack Pizza Shop Finder - Interactive map widgets with Mapbox integration",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"postinstall": "nitrostack install --skip-widgets || true",
|
|
9
8
|
"dev": "nitrostack dev",
|
|
10
9
|
"build": "nitrostack build",
|
|
11
10
|
"start": "npm run build && nitrostack start",
|
|
@@ -117,8 +117,8 @@ export default function PizzaListWidget() {
|
|
|
117
117
|
return (
|
|
118
118
|
<div style={{
|
|
119
119
|
background: isDark ? '#0a0a0a' : '#f9fafb',
|
|
120
|
-
minHeight: '
|
|
121
|
-
maxHeight: maxHeight || '
|
|
120
|
+
minHeight: '400px',
|
|
121
|
+
maxHeight: maxHeight || '600px',
|
|
122
122
|
overflow: 'auto',
|
|
123
123
|
}}>
|
|
124
124
|
{/* Header */}
|
|
@@ -71,8 +71,8 @@ export default function PizzaShopWidget() {
|
|
|
71
71
|
return (
|
|
72
72
|
<div style={{
|
|
73
73
|
background: isDark ? '#0a0a0a' : '#f9fafb',
|
|
74
|
-
minHeight: '
|
|
75
|
-
maxHeight: maxHeight || '
|
|
74
|
+
minHeight: '500px',
|
|
75
|
+
maxHeight: maxHeight || '800px',
|
|
76
76
|
overflow: 'auto',
|
|
77
77
|
}}>
|
|
78
78
|
{/* Hero Image */}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "NitroStack starter template - Learn MCP server basics with a simple calculator example",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"postinstall": "nitrostack install --skip-widgets || true",
|
|
9
8
|
"dev": "nitrostack dev",
|
|
10
9
|
"build": "nitrostack build",
|
|
11
10
|
"start": "npm run build && nitrostack start",
|
|
@@ -114,7 +114,7 @@ export class CalculatorTools {
|
|
|
114
114
|
fs.writeFileSync(filePath, buffer);
|
|
115
115
|
ctx.logger.info(`Saved file to ${filePath}`);
|
|
116
116
|
} catch (e) {
|
|
117
|
-
ctx.logger.error('Failed to save file', e);
|
|
117
|
+
ctx.logger.error('Failed to save file', { error: e instanceof Error ? e.message : String(e) });
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|