nitrostack 1.0.72 → 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.
Files changed (240) hide show
  1. package/dist/auth/api-key.js.map +1 -1
  2. package/dist/auth/client.js.map +1 -1
  3. package/dist/auth/index.d.ts +2 -1
  4. package/dist/auth/index.d.ts.map +1 -1
  5. package/dist/auth/index.js +3 -0
  6. package/dist/auth/index.js.map +1 -1
  7. package/dist/auth/middleware.d.ts +1 -1
  8. package/dist/auth/middleware.d.ts.map +1 -1
  9. package/dist/auth/middleware.js.map +1 -1
  10. package/dist/auth/secure-secret.d.ts +136 -0
  11. package/dist/auth/secure-secret.d.ts.map +1 -0
  12. package/dist/auth/secure-secret.js +182 -0
  13. package/dist/auth/secure-secret.js.map +1 -0
  14. package/dist/auth/server-metadata.d.ts.map +1 -1
  15. package/dist/auth/server-metadata.js.map +1 -1
  16. package/dist/auth/simple-jwt.d.ts +100 -14
  17. package/dist/auth/simple-jwt.d.ts.map +1 -1
  18. package/dist/auth/simple-jwt.js +19 -9
  19. package/dist/auth/simple-jwt.js.map +1 -1
  20. package/dist/auth/token-store.js +1 -1
  21. package/dist/auth/token-store.js.map +1 -1
  22. package/dist/auth/token-validation.js +1 -1
  23. package/dist/auth/token-validation.js.map +1 -1
  24. package/dist/cli/commands/build.js +1 -1
  25. package/dist/cli/commands/build.js.map +1 -1
  26. package/dist/cli/commands/generate-types.js +12 -12
  27. package/dist/cli/commands/generate-types.js.map +1 -1
  28. package/dist/cli/commands/generate.d.ts +8 -1
  29. package/dist/cli/commands/generate.d.ts.map +1 -1
  30. package/dist/cli/commands/generate.js +13 -12
  31. package/dist/cli/commands/generate.js.map +1 -1
  32. package/dist/cli/commands/init.js +1 -1
  33. package/dist/cli/commands/init.js.map +1 -1
  34. package/dist/cli/commands/upgrade.d.ts +10 -0
  35. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  36. package/dist/cli/commands/upgrade.js +221 -0
  37. package/dist/cli/commands/upgrade.js.map +1 -0
  38. package/dist/cli/index.js +7 -0
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/core/app-decorator.d.ts +4 -3
  41. package/dist/core/app-decorator.d.ts.map +1 -1
  42. package/dist/core/app-decorator.js +67 -28
  43. package/dist/core/app-decorator.js.map +1 -1
  44. package/dist/core/builders.d.ts +19 -7
  45. package/dist/core/builders.d.ts.map +1 -1
  46. package/dist/core/builders.js +15 -8
  47. package/dist/core/builders.js.map +1 -1
  48. package/dist/core/component.d.ts +8 -8
  49. package/dist/core/component.d.ts.map +1 -1
  50. package/dist/core/component.js +3 -2
  51. package/dist/core/component.js.map +1 -1
  52. package/dist/core/config-module.d.ts +11 -4
  53. package/dist/core/config-module.d.ts.map +1 -1
  54. package/dist/core/config-module.js +1 -1
  55. package/dist/core/config-module.js.map +1 -1
  56. package/dist/core/decorators/cache.decorator.d.ts +9 -9
  57. package/dist/core/decorators/cache.decorator.d.ts.map +1 -1
  58. package/dist/core/decorators/cache.decorator.js +3 -3
  59. package/dist/core/decorators/cache.decorator.js.map +1 -1
  60. package/dist/core/decorators/health-check.decorator.d.ts +3 -3
  61. package/dist/core/decorators/health-check.decorator.d.ts.map +1 -1
  62. package/dist/core/decorators/health-check.decorator.js +2 -2
  63. package/dist/core/decorators/health-check.decorator.js.map +1 -1
  64. package/dist/core/decorators/rate-limit.decorator.d.ts +5 -4
  65. package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -1
  66. package/dist/core/decorators/rate-limit.decorator.js +3 -3
  67. package/dist/core/decorators/rate-limit.decorator.js.map +1 -1
  68. package/dist/core/decorators.d.ts +47 -29
  69. package/dist/core/decorators.d.ts.map +1 -1
  70. package/dist/core/decorators.js +9 -9
  71. package/dist/core/decorators.js.map +1 -1
  72. package/dist/core/di/container.d.ts +21 -4
  73. package/dist/core/di/container.d.ts.map +1 -1
  74. package/dist/core/di/container.js +11 -7
  75. package/dist/core/di/container.js.map +1 -1
  76. package/dist/core/di/injectable.decorator.d.ts +5 -3
  77. package/dist/core/di/injectable.decorator.d.ts.map +1 -1
  78. package/dist/core/di/injectable.decorator.js.map +1 -1
  79. package/dist/core/errors.d.ts +4 -4
  80. package/dist/core/errors.d.ts.map +1 -1
  81. package/dist/core/errors.js.map +1 -1
  82. package/dist/core/events/event-emitter.d.ts +3 -3
  83. package/dist/core/events/event-emitter.d.ts.map +1 -1
  84. package/dist/core/events/event-emitter.js.map +1 -1
  85. package/dist/core/events/event.decorator.d.ts +5 -5
  86. package/dist/core/events/event.decorator.d.ts.map +1 -1
  87. package/dist/core/events/event.decorator.js +10 -6
  88. package/dist/core/events/event.decorator.js.map +1 -1
  89. package/dist/core/events/log-emitter.d.ts +7 -1
  90. package/dist/core/events/log-emitter.d.ts.map +1 -1
  91. package/dist/core/events/log-emitter.js.map +1 -1
  92. package/dist/core/filters/exception-filter.decorator.d.ts +5 -5
  93. package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -1
  94. package/dist/core/filters/exception-filter.decorator.js +3 -3
  95. package/dist/core/filters/exception-filter.decorator.js.map +1 -1
  96. package/dist/core/filters/exception-filter.interface.d.ts +14 -5
  97. package/dist/core/filters/exception-filter.interface.d.ts.map +1 -1
  98. package/dist/core/guards/apikey.guard.d.ts +1 -1
  99. package/dist/core/guards/apikey.guard.d.ts.map +1 -1
  100. package/dist/core/guards/guard.interface.d.ts +1 -1
  101. package/dist/core/guards/guard.interface.d.ts.map +1 -1
  102. package/dist/core/guards/jwt.guard.d.ts +1 -1
  103. package/dist/core/guards/jwt.guard.d.ts.map +1 -1
  104. package/dist/core/guards/oauth.guard.d.ts +1 -1
  105. package/dist/core/guards/oauth.guard.d.ts.map +1 -1
  106. package/dist/core/guards/use-guards.decorator.d.ts +3 -3
  107. package/dist/core/guards/use-guards.decorator.d.ts.map +1 -1
  108. package/dist/core/guards/use-guards.decorator.js +1 -1
  109. package/dist/core/guards/use-guards.decorator.js.map +1 -1
  110. package/dist/core/index.d.ts +2 -2
  111. package/dist/core/index.d.ts.map +1 -1
  112. package/dist/core/index.js.map +1 -1
  113. package/dist/core/interceptors/interceptor.decorator.d.ts +4 -4
  114. package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -1
  115. package/dist/core/interceptors/interceptor.decorator.js +2 -2
  116. package/dist/core/interceptors/interceptor.decorator.js.map +1 -1
  117. package/dist/core/interceptors/interceptor.interface.d.ts +3 -3
  118. package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -1
  119. package/dist/core/logger.d.ts.map +1 -1
  120. package/dist/core/logger.js.map +1 -1
  121. package/dist/core/middleware/middleware.decorator.d.ts +4 -4
  122. package/dist/core/middleware/middleware.decorator.d.ts.map +1 -1
  123. package/dist/core/middleware/middleware.decorator.js +2 -2
  124. package/dist/core/middleware/middleware.decorator.js.map +1 -1
  125. package/dist/core/middleware/middleware.interface.d.ts +3 -3
  126. package/dist/core/middleware/middleware.interface.d.ts.map +1 -1
  127. package/dist/core/module.d.ts +33 -14
  128. package/dist/core/module.d.ts.map +1 -1
  129. package/dist/core/module.js +11 -6
  130. package/dist/core/module.js.map +1 -1
  131. package/dist/core/oauth-module.d.ts +9 -3
  132. package/dist/core/oauth-module.d.ts.map +1 -1
  133. package/dist/core/oauth-module.js +4 -3
  134. package/dist/core/oauth-module.js.map +1 -1
  135. package/dist/core/pipes/pipe.decorator.d.ts +14 -5
  136. package/dist/core/pipes/pipe.decorator.d.ts.map +1 -1
  137. package/dist/core/pipes/pipe.decorator.js +2 -2
  138. package/dist/core/pipes/pipe.decorator.js.map +1 -1
  139. package/dist/core/pipes/pipe.interface.d.ts +9 -4
  140. package/dist/core/pipes/pipe.interface.d.ts.map +1 -1
  141. package/dist/core/prompt.d.ts +13 -4
  142. package/dist/core/prompt.d.ts.map +1 -1
  143. package/dist/core/prompt.js +2 -2
  144. package/dist/core/prompt.js.map +1 -1
  145. package/dist/core/resource.d.ts +7 -2
  146. package/dist/core/resource.d.ts.map +1 -1
  147. package/dist/core/resource.js +2 -2
  148. package/dist/core/resource.js.map +1 -1
  149. package/dist/core/server.d.ts +49 -3
  150. package/dist/core/server.d.ts.map +1 -1
  151. package/dist/core/server.js +61 -34
  152. package/dist/core/server.js.map +1 -1
  153. package/dist/core/tool.d.ts +44 -16
  154. package/dist/core/tool.d.ts.map +1 -1
  155. package/dist/core/tool.js +19 -6
  156. package/dist/core/tool.js.map +1 -1
  157. package/dist/core/transports/discovery-http-server.d.ts +7 -1
  158. package/dist/core/transports/discovery-http-server.d.ts.map +1 -1
  159. package/dist/core/transports/discovery-http-server.js.map +1 -1
  160. package/dist/core/transports/http-server.d.ts +2 -2
  161. package/dist/core/transports/http-server.d.ts.map +1 -1
  162. package/dist/core/transports/http-server.js +1 -1
  163. package/dist/core/transports/http-server.js.map +1 -1
  164. package/dist/core/transports/streamable-http.d.ts +4 -4
  165. package/dist/core/transports/streamable-http.d.ts.map +1 -1
  166. package/dist/core/transports/streamable-http.js +1 -1
  167. package/dist/core/transports/streamable-http.js.map +1 -1
  168. package/dist/core/types.d.ts +87 -15
  169. package/dist/core/types.d.ts.map +1 -1
  170. package/dist/core/widgets/widget-registry.d.ts +2 -2
  171. package/dist/core/widgets/widget-registry.d.ts.map +1 -1
  172. package/dist/core/widgets/widget-registry.js +1 -1
  173. package/dist/core/widgets/widget-registry.js.map +1 -1
  174. package/dist/testing/index.d.ts +44 -17
  175. package/dist/testing/index.d.ts.map +1 -1
  176. package/dist/testing/index.js +5 -8
  177. package/dist/testing/index.js.map +1 -1
  178. package/dist/ui-next/index.d.ts +1 -1
  179. package/dist/ui-next/index.d.ts.map +1 -1
  180. package/dist/ui-next/index.js.map +1 -1
  181. package/dist/widgets/hooks/useWidgetSDK.d.ts +5 -5
  182. package/dist/widgets/runtime/WidgetLayout.js.map +1 -1
  183. package/dist/widgets/sdk.d.ts +5 -5
  184. package/dist/widgets/sdk.d.ts.map +1 -1
  185. package/dist/widgets/sdk.js.map +1 -1
  186. package/package.json +1 -1
  187. package/src/studio/app/api/auth/fetch-metadata/route.ts +3 -2
  188. package/src/studio/app/api/auth/register-client/route.ts +3 -2
  189. package/src/studio/app/api/chat/route.ts +31 -17
  190. package/src/studio/app/api/health/checks/route.ts +5 -4
  191. package/src/studio/app/api/init/route.ts +3 -2
  192. package/src/studio/app/api/ping/route.ts +3 -2
  193. package/src/studio/app/api/prompts/[name]/route.ts +4 -3
  194. package/src/studio/app/api/prompts/route.ts +3 -2
  195. package/src/studio/app/api/resources/[...uri]/route.ts +3 -2
  196. package/src/studio/app/api/resources/route.ts +3 -2
  197. package/src/studio/app/api/roots/route.ts +3 -2
  198. package/src/studio/app/api/sampling/route.ts +3 -2
  199. package/src/studio/app/api/tools/[name]/call/route.ts +3 -2
  200. package/src/studio/app/api/tools/route.ts +4 -3
  201. package/src/studio/app/api/widget-examples/route.ts +5 -4
  202. package/src/studio/app/auth/callback/page.tsx +3 -2
  203. package/src/studio/app/chat/page.tsx +481 -105
  204. package/src/studio/app/health/page.tsx +1 -1
  205. package/src/studio/app/logs/page.tsx +2 -2
  206. package/src/studio/app/page.tsx +5 -5
  207. package/src/studio/app/prompts/page.tsx +2 -2
  208. package/src/studio/app/settings/page.tsx +3 -2
  209. package/src/studio/app/tools/page.tsx +3 -3
  210. package/src/studio/components/LogMessage.tsx +1 -1
  211. package/src/studio/components/MarkdownRenderer.tsx +245 -348
  212. package/src/studio/components/Sidebar.tsx +18 -3
  213. package/src/studio/components/VoiceOrbOverlay.tsx +12 -6
  214. package/src/studio/components/WidgetErrorBoundary.tsx +48 -0
  215. package/src/studio/components/WidgetRenderer.tsx +168 -215
  216. package/src/studio/components/ops/OpsCanvas.tsx +748 -0
  217. package/src/studio/components/ops/OpsNodeDetailPanel.tsx +150 -0
  218. package/src/studio/components/ops/OpsSummaryBar.tsx +90 -0
  219. package/src/studio/components/ops/index.ts +5 -0
  220. package/src/studio/components/ops/nodes/BaseNode.tsx +65 -0
  221. package/src/studio/components/ops/nodes/LLMCallNode.tsx +34 -0
  222. package/src/studio/components/ops/nodes/LLMResponseNode.tsx +33 -0
  223. package/src/studio/components/ops/nodes/ToolCallNode.tsx +30 -0
  224. package/src/studio/components/ops/nodes/ToolResultNode.tsx +43 -0
  225. package/src/studio/components/ops/nodes/UserPromptNode.tsx +34 -0
  226. package/src/studio/components/ops/nodes/WidgetRenderNode.tsx +23 -0
  227. package/src/studio/components/ops/nodes/index.ts +8 -0
  228. package/src/studio/components/tools/ToolsCanvas.tsx +2 -2
  229. package/src/studio/lib/api.ts +61 -42
  230. package/src/studio/lib/http-client-transport.ts +2 -2
  231. package/src/studio/lib/llm-service.ts +126 -47
  232. package/src/studio/lib/mcp-client.ts +9 -6
  233. package/src/studio/lib/ops-store.ts +427 -0
  234. package/src/studio/lib/ops-tracker.ts +416 -0
  235. package/src/studio/lib/ops-types.ts +164 -0
  236. package/src/studio/lib/store.ts +8 -11
  237. package/src/studio/lib/types.ts +228 -38
  238. package/src/studio/lib/widget-loader.ts +2 -2
  239. package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +19 -22
  240. package/dist/cli/build-widgets.mjs +0 -165
@@ -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: any, jwtToken?: string, apiKey?: string) {
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: any) {
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: any[];
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: any) {
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: any;
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 : any;
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: any;
50
+ private EventSourceImpl: typeof EventSource;
51
51
 
52
52
  constructor(options: HttpClientTransportOptions) {
53
53
  this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
@@ -1,6 +1,8 @@
1
1
  // LLM Service for Studio
2
2
  // Supports OpenAI and Gemini
3
3
 
4
+ import type { JsonValue, JsonObject } from './types';
5
+
4
6
  export type LLMProvider = 'openai' | 'gemini';
5
7
 
6
8
  export interface ChatMessage {
@@ -19,7 +21,7 @@ export interface ChatMessage {
19
21
  export interface ToolCall {
20
22
  id: string;
21
23
  name: string;
22
- arguments: any;
24
+ arguments: JsonValue;
23
25
  }
24
26
 
25
27
  export interface ChatResponse {
@@ -28,30 +30,108 @@ export interface ChatResponse {
28
30
  finishReason?: string;
29
31
  }
30
32
 
33
+ /**
34
+ * Tool definition for LLM
35
+ */
36
+ interface LLMTool {
37
+ name: string;
38
+ description?: string;
39
+ inputSchema?: JsonObject;
40
+ }
41
+
42
+ /**
43
+ * OpenAI message content part
44
+ */
45
+ interface OpenAIContentPart {
46
+ type: 'text' | 'image_url';
47
+ text?: string;
48
+ image_url?: { url: string };
49
+ }
50
+
51
+ /**
52
+ * OpenAI tool call from response
53
+ */
54
+ interface OpenAIToolCall {
55
+ id: string;
56
+ type: 'function';
57
+ function: {
58
+ name: string;
59
+ arguments: string;
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Gemini function call part
65
+ */
66
+ interface GeminiFunctionPart {
67
+ functionCall?: {
68
+ name: string;
69
+ args: JsonObject;
70
+ };
71
+ functionResponse?: {
72
+ name: string;
73
+ response: { content: string };
74
+ };
75
+ text?: string;
76
+ }
77
+
78
+ /**
79
+ * Gemini content entry
80
+ */
81
+ interface GeminiContent {
82
+ role: 'user' | 'model' | 'function';
83
+ parts: GeminiFunctionPart[];
84
+ }
85
+
86
+ /**
87
+ * Gemini parameter schema property
88
+ */
89
+ interface GeminiParameterProperty {
90
+ type: string;
91
+ description: string;
92
+ enum?: JsonValue[];
93
+ }
94
+
95
+ /**
96
+ * Gemini parameters schema
97
+ */
98
+ interface GeminiParameters {
99
+ type: string;
100
+ properties: Record<string, GeminiParameterProperty>;
101
+ required: string[];
102
+ }
103
+
31
104
  export class LLMService {
32
105
  // System prompt to improve tool usage (especially for Gemini)
33
- private getSystemPrompt(tools: any[]): string {
34
- return `You are an intelligent AI assistant with access to ${tools.length} powerful tools. Your goal is to help users accomplish their tasks efficiently and intelligently.
106
+ private getSystemPrompt(tools: LLMTool[]): string {
107
+ return `You are an intelligent AI assistant with access to ${tools.length} powerful tools. Your goal is to help users accomplish their tasks efficiently and accurately.
108
+
109
+ **CRITICAL: ONLY DO WHAT THE USER ASKS**
110
+
111
+ ⚠️ **THE MOST IMPORTANT RULE**: Only perform the specific task the user requested. Do NOT assume additional steps or chain unrelated tools.
112
+
113
+ Examples:
114
+ - "show me airports in london" → ONLY search airports in london. Do NOT search for flights.
115
+ - "search flights from A to B" → ONLY search those flights. Do NOT book them.
116
+ - "book this flight" → ONLY proceed with booking for the specified flight.
35
117
 
36
118
  **CORE PRINCIPLES FOR TOOL USAGE:**
37
119
 
38
- 1. **Be Proactive & Infer Context**:
39
- - Infer obvious information instead of asking (e.g., "Bangalore" → Karnataka, India; "New York" NY, USA)
40
- - Use common sense defaults when reasonable
41
- - Don't ask for information you can deduce from context
120
+ 1. **Answer EXACTLY What Was Asked**:
121
+ - If user asks "show airports in X", only call search_airports for X
122
+ - If user asks "search flights", only search flights - don't book
123
+ - NEVER assume the user wants additional steps beyond their request
124
+ - Ask before doing more than requested
42
125
 
43
- 2. **Chain Tools Intelligently**:
44
- - Use multiple tools in sequence to accomplish complex tasks
45
- - If a task requires multiple steps, execute them automatically
46
- - Example: login fetch data process → display results
47
- - Don't ask permission for each step in an obvious workflow
126
+ 2. **Infer Context When Helpful** (but don't over-extend):
127
+ - Infer obvious location info (e.g., "Bangalore" Karnataka, India)
128
+ - Use common sense defaults for required parameters
129
+ - But NEVER infer that user wants additional operations
48
130
 
49
131
  3. **Maintain Context Awareness**:
50
132
  - Remember information from previous tool calls in THIS conversation
51
133
  - Extract and reuse data (IDs, names, values) from previous tool results
52
134
  - Example: If browse_products returned products with IDs, use those IDs for add_to_cart
53
- - Match user requests to previous data (e.g., "apple" → find product with name "Apple" → use its ID)
54
- - Track state across the conversation (logged in status, product IDs, order IDs, etc.)
55
135
  - NEVER ask for information you already have from a previous tool call
56
136
 
57
137
  4. **Use Smart Defaults**:
@@ -59,25 +139,18 @@ export class LLMService {
59
139
  - Common defaults: page=1, limit=10, sort=recent, etc.
60
140
  - Only ask for clarification when truly ambiguous
61
141
 
62
- 5. **Minimize User Friction**:
63
- - Don't ask for every detail - use inference and defaults
64
- - Chain related operations seamlessly
65
- - Provide concise summaries after multi-step operations
66
- - Be conversational but efficient
67
-
68
- 6. **Handle Errors Gracefully**:
142
+ 5. **Handle Errors Gracefully**:
69
143
  - If authentication required, guide user to login
70
144
  - If prerequisite missing, suggest the required step
71
145
  - If operation fails, explain why and suggest alternatives
72
146
  - Always provide a helpful next step
73
147
 
74
- 7. **Tool Call Best Practices**:
148
+ 6. **Tool Call Best Practices**:
75
149
  - Read tool descriptions carefully to understand their purpose
76
150
  - Use exact parameter names as specified in the schema
77
151
  - Pay attention to required vs optional parameters
78
152
  - If a tool says "Requires authentication" - CALL IT ANYWAY! Auth is handled automatically
79
153
  - Don't ask for credentials preemptively - only if a tool explicitly fails
80
- - Look for examples in tool schemas for guidance
81
154
 
82
155
  **AUTHENTICATION HANDLING:**
83
156
 
@@ -90,17 +163,23 @@ export class LLMService {
90
163
 
91
164
  **EXAMPLES:**
92
165
 
166
+ **Stay Focused - Don't Over-Extend:**
167
+ ✅ User: "show me airports in london" → Call search_airports("london") → Show results → STOP
168
+ ❌ User: "show me airports in london" → search_airports → then search New York → then search flights (WRONG!)
169
+
170
+ ✅ User: "search flights from NYC to LAX" → Call search_flights → Show results → STOP
171
+ ❌ User: "search flights from NYC to LAX" → search → then automatically book (WRONG!)
172
+
93
173
  **Authentication:**
94
174
  User: "whoami" → Call whoami tool directly (don't ask for login)
95
175
  User: "show my orders" → Call get_order_history directly (don't ask for login)
96
- User: "what's in my cart" → Call view_cart directly (don't ask for login)
97
176
 
98
177
  **Context Awareness:**
99
178
  1. browse_products returns: [{id: "prod-3", name: "Apple", price: 0.99}, ...]
100
179
  2. User: "add apple to cart" → Extract ID "prod-3" from previous result → Call add_to_cart({product_id: "prod-3", quantity: 1})
101
- 3. User: "add 2 more" → Remember prod-3 → Call add_to_cart({product_id: "prod-3", quantity: 2})
102
180
 
103
181
  **NEVER do this:**
182
+ ❌ User: "show airports" → Then automatically search flights (User didn't ask!)
104
183
  ❌ User: "add apple to cart" → "What is the product ID?" (You already have it!)
105
184
  ❌ User: "add to cart" → "Which product?" (Look at conversation context!)
106
185
 
@@ -140,7 +219,7 @@ User: "list all resources"
140
219
  async chat(
141
220
  provider: LLMProvider,
142
221
  messages: ChatMessage[],
143
- tools: any[],
222
+ tools: LLMTool[],
144
223
  apiKey: string
145
224
  ): Promise<ChatResponse> {
146
225
  // Inject system prompt at the beginning if not already present
@@ -164,7 +243,7 @@ User: "list all resources"
164
243
 
165
244
  private async chatOpenAI(
166
245
  messages: ChatMessage[],
167
- tools: any[],
246
+ tools: LLMTool[],
168
247
  apiKey: string
169
248
  ): Promise<ChatResponse> {
170
249
  const formattedMessages = messages.map((msg) => {
@@ -194,7 +273,7 @@ User: "list all resources"
194
273
 
195
274
  if (msg.role === 'user' && msg.file) {
196
275
  // Handle file attachments for OpenAI
197
- const contentParts: any[] = [
276
+ const contentParts: OpenAIContentPart[] = [
198
277
  { type: 'text', text: msg.content || ' ' } // Ensure some text exists
199
278
  ];
200
279
 
@@ -247,9 +326,9 @@ User: "list all resources"
247
326
 
248
327
  console.log('Formatted messages for OpenAI:', JSON.stringify(formattedMessages, null, 2));
249
328
 
250
- const requestBody: any = {
329
+ const requestBody: JsonObject = {
251
330
  model: 'gpt-4-turbo-preview',
252
- messages: formattedMessages,
331
+ messages: formattedMessages as JsonValue,
253
332
  };
254
333
 
255
334
  if (tools.length > 0) {
@@ -309,10 +388,10 @@ User: "list all resources"
309
388
  };
310
389
 
311
390
  if (choice.message.tool_calls) {
312
- result.toolCalls = choice.message.tool_calls.map((tc: any) => ({
391
+ result.toolCalls = (choice.message.tool_calls as OpenAIToolCall[]).map((tc) => ({
313
392
  id: tc.id,
314
393
  name: tc.function?.name || '',
315
- arguments: JSON.parse(tc.function?.arguments || '{}'),
394
+ arguments: JSON.parse(tc.function?.arguments || '{}') as JsonValue,
316
395
  }));
317
396
  result.message.toolCalls = result.toolCalls;
318
397
  }
@@ -322,11 +401,11 @@ User: "list all resources"
322
401
 
323
402
  private async chatGemini(
324
403
  messages: ChatMessage[],
325
- tools: any[],
404
+ tools: LLMTool[],
326
405
  apiKey: string
327
406
  ): Promise<ChatResponse> {
328
407
  // Convert messages to Gemini format
329
- const contents: any[] = [];
408
+ const contents: GeminiContent[] = [];
330
409
  let systemInstruction = '';
331
410
 
332
411
  // Group consecutive tool messages together for Gemini
@@ -342,7 +421,7 @@ User: "list all resources"
342
421
 
343
422
  if (msg.role === 'tool') {
344
423
  // Collect all consecutive tool messages and group them into ONE function response
345
- const functionParts: any[] = [];
424
+ const functionParts: GeminiFunctionPart[] = [];
346
425
 
347
426
  while (i < messages.length && messages[i].role === 'tool') {
348
427
  const toolMsg = messages[i];
@@ -364,7 +443,7 @@ User: "list all resources"
364
443
  });
365
444
  } else if (msg.role === 'assistant' && msg.toolCalls && msg.toolCalls.length > 0) {
366
445
  // Assistant message with tool calls
367
- const parts: any[] = [];
446
+ const parts: GeminiFunctionPart[] = [];
368
447
 
369
448
  if (msg.content) {
370
449
  parts.push({ text: msg.content });
@@ -374,7 +453,7 @@ User: "list all resources"
374
453
  parts.push({
375
454
  functionCall: {
376
455
  name: tc.name,
377
- args: tc.arguments,
456
+ args: tc.arguments as JsonObject,
378
457
  },
379
458
  });
380
459
  }
@@ -386,7 +465,7 @@ User: "list all resources"
386
465
  i++;
387
466
  } else {
388
467
  // Regular user or assistant message
389
- const parts: any[] = [];
468
+ const parts: GeminiFunctionPart[] = [];
390
469
 
391
470
  if (msg.content) {
392
471
  parts.push({ text: msg.content });
@@ -448,8 +527,8 @@ User: "list all resources"
448
527
  // console.log('Formatted contents for Gemini:', JSON.stringify(contents, null, 2));
449
528
 
450
529
  // Prepare request body
451
- const requestBody: any = {
452
- contents,
530
+ const requestBody: JsonObject = {
531
+ contents: contents as JsonValue,
453
532
  };
454
533
 
455
534
  // Add system instruction if present
@@ -470,24 +549,24 @@ User: "list all resources"
470
549
  delete cleanSchema.additionalProperties;
471
550
 
472
551
  // Convert to Gemini's expected format
473
- const parameters: any = {
474
- type: cleanSchema.type || 'OBJECT',
552
+ const parameters: GeminiParameters = {
553
+ type: (cleanSchema.type as string) || 'OBJECT',
475
554
  properties: {},
476
- required: cleanSchema.required || [],
555
+ required: (cleanSchema.required as string[]) || [],
477
556
  };
478
557
 
479
558
  // Convert properties
480
559
  if (cleanSchema.properties) {
481
560
  for (const [key, value] of Object.entries(cleanSchema.properties)) {
482
- const prop: any = value;
561
+ const prop = value as JsonObject;
483
562
  parameters.properties[key] = {
484
- type: this.convertTypeToGemini(prop.type),
485
- description: prop.description || '',
563
+ type: this.convertTypeToGemini(prop.type as string | undefined),
564
+ description: (prop.description as string) || '',
486
565
  };
487
566
 
488
567
  // Handle enums
489
568
  if (prop.enum) {
490
- parameters.properties[key].enum = prop.enum;
569
+ parameters.properties[key].enum = prop.enum as JsonValue[];
491
570
  }
492
571
  }
493
572
  }
@@ -116,7 +116,7 @@ export class McpClient {
116
116
  // Start the HTTP transport (establish SSE connection)
117
117
  await this.transport.start();
118
118
  } else {
119
- throw new Error(`Unknown transport type: ${(config as any).type}`);
119
+ throw new Error(`Unknown transport type: ${(config as McpClientConfig).type}`);
120
120
  }
121
121
 
122
122
  // Create client
@@ -198,7 +198,7 @@ export class McpClient {
198
198
  return await this.client.listTools();
199
199
  }
200
200
 
201
- async callTool(name: string, args: any) {
201
+ async callTool(name: string, args: Record<string, unknown>) {
202
202
  if (!this.client) throw new Error('Not connected');
203
203
  return await this.client.callTool({ name, arguments: args });
204
204
  }
@@ -218,7 +218,7 @@ export class McpClient {
218
218
  return await this.client.listPrompts();
219
219
  }
220
220
 
221
- async getPrompt(name: string, args: any) {
221
+ async getPrompt(name: string, args: Record<string, string>) {
222
222
  if (!this.client) throw new Error('Not connected');
223
223
  return await this.client.getPrompt({ name, arguments: args });
224
224
  }
@@ -233,13 +233,16 @@ export class McpClient {
233
233
  return await this.client.listRoots();
234
234
  }
235
235
 
236
- async executeTool(name: string, args: any) {
236
+ async executeTool(name: string, args: Record<string, unknown>) {
237
237
  return await this.callTool(name, args);
238
238
  }
239
239
 
240
- async createCompletion(params: any) {
240
+ async createCompletion(params: {
241
+ ref: string;
242
+ argument: { name: string; value: string };
243
+ }) {
241
244
  if (!this.client) throw new Error('Not connected');
242
- return await this.client.createCompletion(params);
245
+ return await this.client.complete(params);
243
246
  }
244
247
  }
245
248