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
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useMemo } from 'react';
|
|
4
|
+
import ReactFlow, {
|
|
5
|
+
Background,
|
|
6
|
+
Controls,
|
|
7
|
+
Edge,
|
|
8
|
+
Node,
|
|
9
|
+
ReactFlowProvider,
|
|
10
|
+
useNodesState,
|
|
11
|
+
useEdgesState,
|
|
12
|
+
Handle,
|
|
13
|
+
Position,
|
|
14
|
+
MarkerType,
|
|
15
|
+
} from 'reactflow';
|
|
16
|
+
import 'reactflow/dist/style.css';
|
|
17
|
+
import { Tool, Resource, Prompt } from '@/lib/types';
|
|
18
|
+
import { WrenchScrewdriverIcon, BoltIcon, SparklesIcon, CubeIcon, DocumentTextIcon, GlobeAltIcon } from '@heroicons/react/24/outline';
|
|
19
|
+
|
|
20
|
+
interface ToolsCanvasProps {
|
|
21
|
+
tools: Tool[];
|
|
22
|
+
resources?: Resource[];
|
|
23
|
+
prompts?: Prompt[];
|
|
24
|
+
onToolClick?: (tool: Tool) => void;
|
|
25
|
+
onResourceClick?: (resource: Resource) => void;
|
|
26
|
+
onPromptClick?: (prompt: Prompt) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Custom Agent Node (Center)
|
|
30
|
+
const AgentNode = ({ data }: { data: { label: string } }) => {
|
|
31
|
+
return (
|
|
32
|
+
<div className="relative group">
|
|
33
|
+
{/* Glow Effect */}
|
|
34
|
+
<div className="absolute -inset-4 bg-primary/20 rounded-full blur-xl group-hover:bg-primary/30 transition-all duration-500"></div>
|
|
35
|
+
|
|
36
|
+
<div className="relative w-32 h-32 rounded-full border-2 border-primary bg-card/90 backdrop-blur-md shadow-2xl flex flex-col items-center justify-center z-10 animate-pulse-slow">
|
|
37
|
+
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center mb-2">
|
|
38
|
+
<CubeIcon className="w-7 h-7 text-primary" />
|
|
39
|
+
</div>
|
|
40
|
+
<div className="text-[10px] font-mono text-primary uppercase tracking-widest mb-1">AGENT</div>
|
|
41
|
+
<div className="text-xs font-bold text-foreground text-center px-4 leading-tight">{data.label}</div>
|
|
42
|
+
|
|
43
|
+
<Handle type="source" position={Position.Top} className="!bg-primary !w-3 !h-3 !border-2 !border-background" />
|
|
44
|
+
<Handle type="source" position={Position.Right} className="!bg-primary !w-3 !h-3 !border-2 !border-background" />
|
|
45
|
+
<Handle type="source" position={Position.Bottom} className="!bg-primary !w-3 !h-3 !border-2 !border-background" />
|
|
46
|
+
<Handle type="source" position={Position.Left} className="!bg-primary !w-3 !h-3 !border-2 !border-background" />
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Custom Tool Node (Satellite)
|
|
53
|
+
const ToolNode = ({ data }: { data: { tool: Tool } }) => {
|
|
54
|
+
const Icon = data.tool.name.toLowerCase().includes('run') || data.tool.name.toLowerCase().includes('exec')
|
|
55
|
+
? BoltIcon
|
|
56
|
+
: data.tool.description?.toLowerCase().includes('ai')
|
|
57
|
+
? SparklesIcon
|
|
58
|
+
: WrenchScrewdriverIcon;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div className="w-[200px] rounded-lg border border-teal-500/20 bg-card/80 backdrop-blur-sm shadow-xl p-4 transition-all duration-300 hover:border-teal-500/60 hover:shadow-teal-500/10 group cursor-pointer">
|
|
62
|
+
<Handle type="target" position={Position.Left} className="!bg-muted-foreground !w-2 !h-2" />
|
|
63
|
+
|
|
64
|
+
<div className="flex items-start gap-3">
|
|
65
|
+
<div className="w-8 h-8 rounded-lg bg-teal-500/10 flex items-center justify-center shrink-0 group-hover:bg-teal-500/20 transition-colors">
|
|
66
|
+
<Icon className="w-4 h-4 text-teal-500 group-hover:text-teal-400 transition-colors" />
|
|
67
|
+
</div>
|
|
68
|
+
<div>
|
|
69
|
+
<div className="text-[10px] font-mono text-teal-500 uppercase tracking-wider mb-0.5">TOOL</div>
|
|
70
|
+
<div className="font-semibold text-foreground text-sm line-clamp-1">{data.tool.name}</div>
|
|
71
|
+
<div className="text-xs text-muted-foreground line-clamp-2 mt-1">{data.tool.description}</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
{/* Argument Pills */}
|
|
76
|
+
{data.tool.inputSchema?.properties && Object.keys(data.tool.inputSchema.properties).length > 0 && (
|
|
77
|
+
<div className="flex flex-wrap gap-1 mt-3">
|
|
78
|
+
{Object.keys(data.tool.inputSchema.properties).slice(0, 3).map(arg => (
|
|
79
|
+
<span key={arg} className="px-1.5 py-0.5 rounded text-[10px] bg-muted/50 text-muted-foreground border border-border">
|
|
80
|
+
{arg}
|
|
81
|
+
</span>
|
|
82
|
+
))}
|
|
83
|
+
{Object.keys(data.tool.inputSchema.properties).length > 3 && (
|
|
84
|
+
<span className="px-1.5 py-0.5 rounded text-[10px] bg-muted/50 text-muted-foreground border border-border">+{Object.keys(data.tool.inputSchema.properties).length - 3}</span>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Custom Resource Node
|
|
93
|
+
const ResourceNode = ({ data }: { data: { resource: Resource } }) => {
|
|
94
|
+
return (
|
|
95
|
+
<div className="w-[200px] rounded-lg border border-indigo-500/20 bg-card/80 backdrop-blur-sm shadow-xl p-4 transition-all duration-300 hover:border-indigo-500/60 hover:shadow-indigo-500/10 group cursor-pointer">
|
|
96
|
+
<Handle type="target" position={Position.Left} className="!bg-muted-foreground !w-2 !h-2" />
|
|
97
|
+
|
|
98
|
+
<div className="flex items-start gap-3">
|
|
99
|
+
<div className="w-8 h-8 rounded-lg bg-indigo-500/10 flex items-center justify-center shrink-0 group-hover:bg-indigo-500/20 transition-colors">
|
|
100
|
+
<CubeIcon className="w-4 h-4 text-indigo-500 group-hover:text-indigo-400 transition-colors" />
|
|
101
|
+
</div>
|
|
102
|
+
<div>
|
|
103
|
+
<div className="text-[10px] font-mono text-indigo-500 uppercase tracking-wider mb-0.5">RESOURCE</div>
|
|
104
|
+
<div className="font-semibold text-foreground text-sm line-clamp-1">{data.resource.name}</div>
|
|
105
|
+
<div className="text-xs text-muted-foreground line-clamp-2 mt-1">{data.resource.uri}</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
<div className="flex flex-wrap gap-1 mt-3">
|
|
109
|
+
<span className="px-1.5 py-0.5 rounded text-[10px] bg-indigo-500/5 text-indigo-500 border border-indigo-500/10">
|
|
110
|
+
{data.resource.mimeType || 'text/plain'}
|
|
111
|
+
</span>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Custom Prompt Node
|
|
118
|
+
const PromptNode = ({ data }: { data: { prompt: Prompt } }) => {
|
|
119
|
+
return (
|
|
120
|
+
<div className="w-[200px] rounded-lg border border-amber-500/20 bg-card/80 backdrop-blur-sm shadow-xl p-4 transition-all duration-300 hover:border-amber-500/60 hover:shadow-amber-500/10 group cursor-pointer">
|
|
121
|
+
<Handle type="target" position={Position.Left} className="!bg-muted-foreground !w-2 !h-2" />
|
|
122
|
+
|
|
123
|
+
<div className="flex items-start gap-3">
|
|
124
|
+
<div className="w-8 h-8 rounded-lg bg-amber-500/10 flex items-center justify-center shrink-0 group-hover:bg-amber-500/20 transition-colors">
|
|
125
|
+
<DocumentTextIcon className="w-4 h-4 text-amber-500 group-hover:text-amber-400 transition-colors" />
|
|
126
|
+
</div>
|
|
127
|
+
<div>
|
|
128
|
+
<div className="text-[10px] font-mono text-amber-500 uppercase tracking-wider mb-0.5">PROMPT</div>
|
|
129
|
+
<div className="font-semibold text-foreground text-sm line-clamp-1">{data.prompt.name}</div>
|
|
130
|
+
<div className="text-xs text-muted-foreground line-clamp-2 mt-1">{data.prompt.description || 'No description'}</div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{/* Arguments */}
|
|
135
|
+
{data.prompt.arguments && data.prompt.arguments.length > 0 && (
|
|
136
|
+
<div className="flex flex-wrap gap-1 mt-3">
|
|
137
|
+
{data.prompt.arguments.slice(0, 3).map(arg => (
|
|
138
|
+
<span key={arg.name} className="px-1.5 py-0.5 rounded text-[10px] bg-amber-500/5 text-amber-500 border border-amber-500/10">
|
|
139
|
+
{arg.name}
|
|
140
|
+
</span>
|
|
141
|
+
))}
|
|
142
|
+
{data.prompt.arguments.length > 3 && (
|
|
143
|
+
<span className="px-1.5 py-0.5 rounded text-[10px] bg-muted/50 text-muted-foreground border border-border">+{data.prompt.arguments.length - 3}</span>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const nodeTypes = {
|
|
152
|
+
agent: AgentNode,
|
|
153
|
+
tool: ToolNode,
|
|
154
|
+
resource: ResourceNode,
|
|
155
|
+
prompt: PromptNode,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export function ToolsCanvas({ tools, resources = [], prompts = [], onToolClick, onResourceClick, onPromptClick }: ToolsCanvasProps) {
|
|
159
|
+
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
160
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
|
161
|
+
|
|
162
|
+
// Calculate Layout (Categorical Zones)
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
const centerX = 400;
|
|
165
|
+
const centerY = 300;
|
|
166
|
+
const zoneRadius = 350; // Distance of zone centers from main center
|
|
167
|
+
|
|
168
|
+
const newNodes: Node[] = [
|
|
169
|
+
{
|
|
170
|
+
id: 'agent-root',
|
|
171
|
+
type: 'agent',
|
|
172
|
+
position: { x: centerX - 64, y: centerY - 64 }, // Center minus half width/height
|
|
173
|
+
data: { label: 'NitroStack Agent' },
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
const newEdges: Edge[] = [];
|
|
178
|
+
|
|
179
|
+
// Helper to place items in a grid within a zone
|
|
180
|
+
const placeItemsInZone = (items: (Tool | Resource | Prompt)[], type: string, startX: number, startY: number, cols: number = 3) => {
|
|
181
|
+
items.forEach((item, index) => {
|
|
182
|
+
const col = index % cols;
|
|
183
|
+
const row = Math.floor(index / cols);
|
|
184
|
+
|
|
185
|
+
// Grid spacing
|
|
186
|
+
const gapX = 240;
|
|
187
|
+
const gapY = 150;
|
|
188
|
+
|
|
189
|
+
const x = startX + (col * gapX);
|
|
190
|
+
const y = startY + (row * gapY);
|
|
191
|
+
|
|
192
|
+
let nodeId = '';
|
|
193
|
+
let nodeData = {};
|
|
194
|
+
let strokeColor = '#52525b';
|
|
195
|
+
|
|
196
|
+
if (type === 'tool') {
|
|
197
|
+
const tool = item as Tool;
|
|
198
|
+
nodeId = `tool-${tool.name}`;
|
|
199
|
+
nodeData = { tool };
|
|
200
|
+
strokeColor = '#14b8a6'; // Teal
|
|
201
|
+
} else if (type === 'resource') {
|
|
202
|
+
const resource = item as Resource;
|
|
203
|
+
nodeId = `resource-${resource.uri}`;
|
|
204
|
+
nodeData = { resource };
|
|
205
|
+
strokeColor = '#6366f1'; // Indigo
|
|
206
|
+
} else if (type === 'prompt') {
|
|
207
|
+
const prompt = item as Prompt;
|
|
208
|
+
nodeId = `prompt-${prompt.name}`;
|
|
209
|
+
nodeData = { prompt };
|
|
210
|
+
strokeColor = '#f59e0b'; // Amber
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
newNodes.push({
|
|
214
|
+
id: nodeId,
|
|
215
|
+
type: type,
|
|
216
|
+
position: { x, y },
|
|
217
|
+
data: nodeData,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
newEdges.push({
|
|
221
|
+
id: `e-root-${nodeId}`,
|
|
222
|
+
source: 'agent-root',
|
|
223
|
+
target: nodeId,
|
|
224
|
+
type: 'default',
|
|
225
|
+
animated: true,
|
|
226
|
+
style: { stroke: strokeColor, strokeWidth: 1.5, opacity: 0.3 },
|
|
227
|
+
markerEnd: {
|
|
228
|
+
type: MarkerType.ArrowClosed,
|
|
229
|
+
color: strokeColor,
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 1. Prompts (Top Left)
|
|
236
|
+
// Center of zone is approx (-zoneRadius, -zoneRadius) relative to main center
|
|
237
|
+
// We'll define start point for the grid
|
|
238
|
+
if (prompts && prompts.length > 0) {
|
|
239
|
+
const startX = centerX - 600;
|
|
240
|
+
const startY = centerY - 400;
|
|
241
|
+
placeItemsInZone(prompts, 'prompt', startX, startY, 2);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// 2. Resources (Top Right)
|
|
245
|
+
if (resources && resources.length > 0) {
|
|
246
|
+
const startX = centerX + 200;
|
|
247
|
+
const startY = centerY - 400;
|
|
248
|
+
placeItemsInZone(resources, 'resource', startX, startY, 2);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 3. Tools (Bottom)
|
|
252
|
+
if (tools && tools.length > 0) {
|
|
253
|
+
// Center the tools grid at the bottom
|
|
254
|
+
const cols = 4;
|
|
255
|
+
const gridWidth = Math.min(tools.length, cols) * 240;
|
|
256
|
+
const startX = centerX - (gridWidth / 2) + 100; // Adjust to center
|
|
257
|
+
const startY = centerY + 200;
|
|
258
|
+
placeItemsInZone(tools, 'tool', startX, startY, cols);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
setNodes(newNodes);
|
|
262
|
+
setEdges(newEdges);
|
|
263
|
+
}, [tools, resources, prompts, setNodes, setEdges]); // Re-calc when any data changes
|
|
264
|
+
|
|
265
|
+
const handleNodeClick = useCallback((event: React.MouseEvent, node: Node) => {
|
|
266
|
+
if (node.type === 'tool' && node.data.tool && onToolClick) {
|
|
267
|
+
onToolClick(node.data.tool);
|
|
268
|
+
} else if (node.type === 'resource' && node.data.resource && onResourceClick) {
|
|
269
|
+
onResourceClick(node.data.resource);
|
|
270
|
+
} else if (node.type === 'prompt' && node.data.prompt && onPromptClick) {
|
|
271
|
+
onPromptClick(node.data.prompt);
|
|
272
|
+
}
|
|
273
|
+
}, [onToolClick, onResourceClick, onPromptClick]);
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<div className="w-full h-full min-h-[600px] bg-[#09090b] rounded-xl overflow-hidden border border-border/50 shadow-inner relative group/canvas">
|
|
277
|
+
<ReactFlow
|
|
278
|
+
nodes={nodes}
|
|
279
|
+
edges={edges}
|
|
280
|
+
onNodesChange={onNodesChange}
|
|
281
|
+
onEdgesChange={onEdgesChange}
|
|
282
|
+
nodeTypes={nodeTypes}
|
|
283
|
+
onNodeClick={handleNodeClick}
|
|
284
|
+
fitView
|
|
285
|
+
className="bg-[#09090b]" // Zinc-950 dark background
|
|
286
|
+
>
|
|
287
|
+
<Background
|
|
288
|
+
color="#27272a" // Zinc-800 dots
|
|
289
|
+
gap={20}
|
|
290
|
+
size={1.5}
|
|
291
|
+
variant="dots"
|
|
292
|
+
/>
|
|
293
|
+
<Controls
|
|
294
|
+
position="bottom-right"
|
|
295
|
+
showInteractive={false}
|
|
296
|
+
className="!flex !flex-row !gap-1 !p-1 !bg-card/90 !backdrop-blur !border !border-border !rounded-lg !shadow-lg !m-4"
|
|
297
|
+
/>
|
|
298
|
+
</ReactFlow>
|
|
299
|
+
|
|
300
|
+
{/* Legend / Key */}
|
|
301
|
+
<div className="absolute top-4 left-4 flex gap-3 pointer-events-none">
|
|
302
|
+
<div className="bg-card/80 backdrop-blur px-3 py-1.5 rounded-lg border border-border text-xs text-muted-foreground">
|
|
303
|
+
Interactive Canvas
|
|
304
|
+
</div>
|
|
305
|
+
<div className="flex gap-2">
|
|
306
|
+
<span className="flex items-center gap-1.5 px-2 py-1 bg-teal-500/10 border border-teal-500/20 rounded-md text-[10px] text-teal-500 uppercase tracking-wide font-medium">
|
|
307
|
+
<WrenchScrewdriverIcon className="w-3 h-3" /> Tools
|
|
308
|
+
</span>
|
|
309
|
+
<span className="flex items-center gap-1.5 px-2 py-1 bg-indigo-500/10 border border-indigo-500/20 rounded-md text-[10px] text-indigo-500 uppercase tracking-wide font-medium">
|
|
310
|
+
<CubeIcon className="w-3 h-3" /> Resources
|
|
311
|
+
</span>
|
|
312
|
+
<span className="flex items-center gap-1.5 px-2 py-1 bg-amber-500/10 border border-amber-500/20 rounded-md text-[10px] text-amber-500 uppercase tracking-wide font-medium">
|
|
313
|
+
<DocumentTextIcon className="w-3 h-3" /> Prompts
|
|
314
|
+
</span>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export default function ToolsCanvasWrapper(props: ToolsCanvasProps) {
|
|
322
|
+
return (
|
|
323
|
+
<ReactFlowProvider>
|
|
324
|
+
<ToolsCanvas {...props} />
|
|
325
|
+
</ReactFlowProvider>
|
|
326
|
+
)
|
|
327
|
+
}
|
package/src/studio/lib/api.ts
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
// NitroStack Studio API Client
|
|
2
2
|
|
|
3
|
+
import type {
|
|
4
|
+
JsonValue,
|
|
5
|
+
ChatMessage,
|
|
6
|
+
PKCEParams,
|
|
7
|
+
ClientRegistration,
|
|
8
|
+
} from './types';
|
|
9
|
+
|
|
3
10
|
const API_BASE = typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000';
|
|
4
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Client registration metadata for OAuth
|
|
14
|
+
*/
|
|
15
|
+
interface ClientRegistrationMetadata {
|
|
16
|
+
client_name?: string;
|
|
17
|
+
redirect_uris: string[];
|
|
18
|
+
token_endpoint_auth_method?: string;
|
|
19
|
+
grant_types?: string[];
|
|
20
|
+
response_types?: string[];
|
|
21
|
+
[key: string]: JsonValue | undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
5
24
|
export class StudioAPI {
|
|
6
25
|
private baseUrl: string;
|
|
7
26
|
private initialized: boolean = false;
|
|
@@ -11,7 +30,7 @@ export class StudioAPI {
|
|
|
11
30
|
}
|
|
12
31
|
|
|
13
32
|
// Initialize MCP connection (call once on app start)
|
|
14
|
-
async initialize() {
|
|
33
|
+
async initialize(): Promise<void> {
|
|
15
34
|
if (this.initialized) return;
|
|
16
35
|
try {
|
|
17
36
|
await fetch(`${this.baseUrl}/api/init`, { method: 'POST' });
|
|
@@ -22,111 +41,111 @@ export class StudioAPI {
|
|
|
22
41
|
}
|
|
23
42
|
|
|
24
43
|
// Connection
|
|
25
|
-
async checkConnection() {
|
|
44
|
+
async checkConnection(): Promise<JsonValue> {
|
|
26
45
|
const response = await fetch(`${this.baseUrl}/api/health`);
|
|
27
|
-
return response.json()
|
|
46
|
+
return response.json() as Promise<JsonValue>;
|
|
28
47
|
}
|
|
29
48
|
|
|
30
49
|
// Tools
|
|
31
|
-
async listTools() {
|
|
50
|
+
async listTools(): Promise<JsonValue> {
|
|
32
51
|
const response = await fetch(`${this.baseUrl}/api/tools`);
|
|
33
|
-
return response.json()
|
|
52
|
+
return response.json() as Promise<JsonValue>;
|
|
34
53
|
}
|
|
35
54
|
|
|
36
|
-
async getTools() {
|
|
55
|
+
async getTools(): Promise<JsonValue> {
|
|
37
56
|
return this.listTools();
|
|
38
57
|
}
|
|
39
58
|
|
|
40
|
-
async callTool(name: string, args:
|
|
59
|
+
async callTool(name: string, args: JsonValue, jwtToken?: string, apiKey?: string): Promise<JsonValue> {
|
|
41
60
|
const response = await fetch(`${this.baseUrl}/api/tools/${name}/call`, {
|
|
42
61
|
method: 'POST',
|
|
43
62
|
headers: { 'Content-Type': 'application/json' },
|
|
44
63
|
body: JSON.stringify({ args, jwtToken, apiKey }),
|
|
45
64
|
});
|
|
46
|
-
return response.json()
|
|
65
|
+
return response.json() as Promise<JsonValue>;
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
// Resources
|
|
50
|
-
async getResources() {
|
|
69
|
+
async getResources(): Promise<JsonValue> {
|
|
51
70
|
const response = await fetch(`${this.baseUrl}/api/resources`);
|
|
52
|
-
return response.json()
|
|
71
|
+
return response.json() as Promise<JsonValue>;
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
async getResource(uri: string) {
|
|
74
|
+
async getResource(uri: string): Promise<JsonValue> {
|
|
56
75
|
const response = await fetch(`${this.baseUrl}/api/resources/${encodeURIComponent(uri)}`);
|
|
57
|
-
return response.json()
|
|
76
|
+
return response.json() as Promise<JsonValue>;
|
|
58
77
|
}
|
|
59
78
|
|
|
60
79
|
// Prompts
|
|
61
|
-
async getPrompts() {
|
|
80
|
+
async getPrompts(): Promise<JsonValue> {
|
|
62
81
|
const response = await fetch(`${this.baseUrl}/api/prompts`);
|
|
63
|
-
return response.json()
|
|
82
|
+
return response.json() as Promise<JsonValue>;
|
|
64
83
|
}
|
|
65
84
|
|
|
66
|
-
async executePrompt(name: string, args:
|
|
85
|
+
async executePrompt(name: string, args: Record<string, string>): Promise<JsonValue> {
|
|
67
86
|
const response = await fetch(`${this.baseUrl}/api/prompts/${name}`, {
|
|
68
87
|
method: 'POST',
|
|
69
88
|
headers: { 'Content-Type': 'application/json' },
|
|
70
89
|
body: JSON.stringify(args),
|
|
71
90
|
});
|
|
72
|
-
return response.json()
|
|
91
|
+
return response.json() as Promise<JsonValue>;
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
// Ping
|
|
76
|
-
async ping() {
|
|
95
|
+
async ping(): Promise<JsonValue> {
|
|
77
96
|
const response = await fetch(`${this.baseUrl}/api/ping`);
|
|
78
|
-
return response.json()
|
|
97
|
+
return response.json() as Promise<JsonValue>;
|
|
79
98
|
}
|
|
80
99
|
|
|
81
100
|
// Sampling
|
|
82
|
-
async sample(params: { prompt: string; maxTokens: number; model?: string }) {
|
|
101
|
+
async sample(params: { prompt: string; maxTokens: number; model?: string }): Promise<JsonValue> {
|
|
83
102
|
const response = await fetch(`${this.baseUrl}/api/sampling`, {
|
|
84
103
|
method: 'POST',
|
|
85
104
|
headers: { 'Content-Type': 'application/json' },
|
|
86
105
|
body: JSON.stringify(params),
|
|
87
106
|
});
|
|
88
|
-
return response.json()
|
|
107
|
+
return response.json() as Promise<JsonValue>;
|
|
89
108
|
}
|
|
90
109
|
|
|
91
110
|
// Roots
|
|
92
|
-
async getRoots() {
|
|
111
|
+
async getRoots(): Promise<JsonValue> {
|
|
93
112
|
const response = await fetch(`${this.baseUrl}/api/roots`);
|
|
94
|
-
return response.json()
|
|
113
|
+
return response.json() as Promise<JsonValue>;
|
|
95
114
|
}
|
|
96
115
|
|
|
97
116
|
// Chat
|
|
98
117
|
async chat(params: {
|
|
99
118
|
provider: string;
|
|
100
|
-
messages:
|
|
119
|
+
messages: ChatMessage[];
|
|
101
120
|
apiKey: string; // LLM API key (OpenAI/Gemini)
|
|
102
121
|
jwtToken?: string; // MCP server JWT token
|
|
103
122
|
mcpApiKey?: string; // MCP server API key
|
|
104
|
-
}) {
|
|
123
|
+
}): Promise<JsonValue> {
|
|
105
124
|
const response = await fetch(`${this.baseUrl}/api/chat`, {
|
|
106
125
|
method: 'POST',
|
|
107
126
|
headers: { 'Content-Type': 'application/json' },
|
|
108
127
|
body: JSON.stringify(params),
|
|
109
128
|
});
|
|
110
|
-
return response.json()
|
|
129
|
+
return response.json() as Promise<JsonValue>;
|
|
111
130
|
}
|
|
112
131
|
|
|
113
132
|
// Auth (OAuth 2.1)
|
|
114
|
-
async discoverAuth(url: string, type: 'resource' | 'auth-server') {
|
|
133
|
+
async discoverAuth(url: string, type: 'resource' | 'auth-server'): Promise<JsonValue> {
|
|
115
134
|
const response = await fetch(`${this.baseUrl}/api/auth/fetch-metadata`, {
|
|
116
135
|
method: 'POST',
|
|
117
136
|
headers: { 'Content-Type': 'application/json' },
|
|
118
137
|
body: JSON.stringify({ url, type }),
|
|
119
138
|
});
|
|
120
|
-
return response.json()
|
|
139
|
+
return response.json() as Promise<JsonValue>;
|
|
121
140
|
}
|
|
122
141
|
|
|
123
|
-
async registerClient(endpoint: string, metadata:
|
|
142
|
+
async registerClient(endpoint: string, metadata: ClientRegistrationMetadata): Promise<ClientRegistration> {
|
|
124
143
|
const response = await fetch(`${this.baseUrl}/api/auth/register-client`, {
|
|
125
144
|
method: 'POST',
|
|
126
145
|
headers: { 'Content-Type': 'application/json' },
|
|
127
146
|
body: JSON.stringify({ endpoint, metadata }),
|
|
128
147
|
});
|
|
129
|
-
return response.json()
|
|
148
|
+
return response.json() as Promise<ClientRegistration>;
|
|
130
149
|
}
|
|
131
150
|
|
|
132
151
|
async startOAuthFlow(params: {
|
|
@@ -135,30 +154,30 @@ export class StudioAPI {
|
|
|
135
154
|
redirectUri: string;
|
|
136
155
|
scope: string;
|
|
137
156
|
resource: string;
|
|
138
|
-
}) {
|
|
157
|
+
}): Promise<JsonValue> {
|
|
139
158
|
const response = await fetch(`${this.baseUrl}/api/auth/start-flow`, {
|
|
140
159
|
method: 'POST',
|
|
141
160
|
headers: { 'Content-Type': 'application/json' },
|
|
142
161
|
body: JSON.stringify(params),
|
|
143
162
|
});
|
|
144
|
-
return response.json()
|
|
163
|
+
return response.json() as Promise<JsonValue>;
|
|
145
164
|
}
|
|
146
165
|
|
|
147
166
|
async exchangeToken(params: {
|
|
148
167
|
code: string;
|
|
149
|
-
pkce:
|
|
168
|
+
pkce: PKCEParams;
|
|
150
169
|
tokenEndpoint: string;
|
|
151
170
|
clientId: string;
|
|
152
171
|
clientSecret?: string;
|
|
153
172
|
redirectUri: string;
|
|
154
173
|
resource: string;
|
|
155
|
-
}) {
|
|
174
|
+
}): Promise<JsonValue> {
|
|
156
175
|
const response = await fetch(`${this.baseUrl}/api/auth/exchange-token`, {
|
|
157
176
|
method: 'POST',
|
|
158
177
|
headers: { 'Content-Type': 'application/json' },
|
|
159
178
|
body: JSON.stringify(params),
|
|
160
179
|
});
|
|
161
|
-
return response.json()
|
|
180
|
+
return response.json() as Promise<JsonValue>;
|
|
162
181
|
}
|
|
163
182
|
|
|
164
183
|
async refreshToken(params: {
|
|
@@ -167,13 +186,13 @@ export class StudioAPI {
|
|
|
167
186
|
clientId: string;
|
|
168
187
|
clientSecret?: string;
|
|
169
188
|
resource: string;
|
|
170
|
-
}) {
|
|
189
|
+
}): Promise<JsonValue> {
|
|
171
190
|
const response = await fetch(`${this.baseUrl}/api/auth/refresh-token`, {
|
|
172
191
|
method: 'POST',
|
|
173
192
|
headers: { 'Content-Type': 'application/json' },
|
|
174
193
|
body: JSON.stringify(params),
|
|
175
194
|
});
|
|
176
|
-
return response.json()
|
|
195
|
+
return response.json() as Promise<JsonValue>;
|
|
177
196
|
}
|
|
178
197
|
|
|
179
198
|
async revokeToken(params: {
|
|
@@ -181,25 +200,25 @@ export class StudioAPI {
|
|
|
181
200
|
revocationEndpoint: string;
|
|
182
201
|
clientId: string;
|
|
183
202
|
clientSecret?: string;
|
|
184
|
-
}) {
|
|
203
|
+
}): Promise<JsonValue> {
|
|
185
204
|
const response = await fetch(`${this.baseUrl}/api/auth/revoke-token`, {
|
|
186
205
|
method: 'POST',
|
|
187
206
|
headers: { 'Content-Type': 'application/json' },
|
|
188
207
|
body: JSON.stringify(params),
|
|
189
208
|
});
|
|
190
|
-
return response.json()
|
|
209
|
+
return response.json() as Promise<JsonValue>;
|
|
191
210
|
}
|
|
192
211
|
|
|
193
212
|
// Health
|
|
194
|
-
async getHealth() {
|
|
213
|
+
async getHealth(): Promise<JsonValue> {
|
|
195
214
|
const response = await fetch(`${this.baseUrl}/api/health/checks`);
|
|
196
|
-
return response.json()
|
|
215
|
+
return response.json() as Promise<JsonValue>;
|
|
197
216
|
}
|
|
198
217
|
|
|
199
218
|
// Widget Examples
|
|
200
|
-
async getWidgetExamples() {
|
|
219
|
+
async getWidgetExamples(): Promise<JsonValue> {
|
|
201
220
|
const response = await fetch(`${this.baseUrl}/api/widget-examples`);
|
|
202
|
-
return response.json()
|
|
221
|
+
return response.json() as Promise<JsonValue>;
|
|
203
222
|
}
|
|
204
223
|
}
|
|
205
224
|
|
|
@@ -11,7 +11,7 @@ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
|
11
11
|
import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
|
|
12
12
|
|
|
13
13
|
// EventSource type that works in both browser and Node.js
|
|
14
|
-
type EventSourceType = typeof EventSource extends { prototype: infer T } ? T :
|
|
14
|
+
type EventSourceType = typeof EventSource extends { prototype: infer T } ? T : EventSource;
|
|
15
15
|
|
|
16
16
|
export interface HttpClientTransportOptions {
|
|
17
17
|
/**
|
|
@@ -47,7 +47,7 @@ export class HttpClientTransport implements Transport {
|
|
|
47
47
|
private closeHandler?: () => void;
|
|
48
48
|
private errorHandler?: (error: Error) => void;
|
|
49
49
|
private isConnected = false;
|
|
50
|
-
private EventSourceImpl:
|
|
50
|
+
private EventSourceImpl: typeof EventSource;
|
|
51
51
|
|
|
52
52
|
constructor(options: HttpClientTransportOptions) {
|
|
53
53
|
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|