ai-agent-router 0.1.0

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 (166) hide show
  1. package/.claude/commands/openspec/apply.md +23 -0
  2. package/.claude/commands/openspec/archive.md +27 -0
  3. package/.claude/commands/openspec/proposal.md +28 -0
  4. package/.claude/settings.local.json +12 -0
  5. package/.claude/skills/ui-ux-pro-max/SKILL.md +228 -0
  6. package/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
  7. package/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
  8. package/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
  9. package/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
  10. package/.claude/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  11. package/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  12. package/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  13. package/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  14. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  15. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  16. package/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  17. package/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  18. package/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  19. package/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  20. package/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  21. package/.claude/skills/ui-ux-pro-max/data/styles.csv +59 -0
  22. package/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
  23. package/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-311.pyc +0 -0
  25. package/.claude/skills/ui-ux-pro-max/scripts/core.py +238 -0
  26. package/.claude/skills/ui-ux-pro-max/scripts/search.py +61 -0
  27. package/.cursor/commands/openspec-apply.md +23 -0
  28. package/.cursor/commands/openspec-archive.md +27 -0
  29. package/.cursor/commands/openspec-proposal.md +28 -0
  30. package/.cursor/commands/ui-ux-pro-max.md +226 -0
  31. package/.eslintrc.json +3 -0
  32. package/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  33. package/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  34. package/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  35. package/.shared/ui-ux-pro-max/data/products.csv +97 -0
  36. package/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  37. package/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  38. package/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  39. package/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  40. package/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  41. package/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  42. package/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  43. package/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  44. package/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  45. package/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  46. package/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  47. package/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  48. package/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  49. package/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  50. package/.shared/ui-ux-pro-max/scripts/core.py +238 -0
  51. package/.shared/ui-ux-pro-max/scripts/search.py +61 -0
  52. package/AGENTS.md +18 -0
  53. package/CLAUDE.md +18 -0
  54. package/IMPLEMENTATION.md +157 -0
  55. package/LICENSE +21 -0
  56. package/README.md +165 -0
  57. package/dist/.next/types/app/api/config/route.js +52 -0
  58. package/dist/.next/types/app/api/gateway/[...path]/route.js +52 -0
  59. package/dist/.next/types/app/api/gateway/route.js +52 -0
  60. package/dist/.next/types/app/api/logs/route.js +52 -0
  61. package/dist/.next/types/app/api/models/route.js +52 -0
  62. package/dist/.next/types/app/api/providers/route.js +52 -0
  63. package/dist/.next/types/app/api/providers/test/route.js +52 -0
  64. package/dist/.next/types/app/api/service/start/route.js +52 -0
  65. package/dist/.next/types/app/api/service/status/route.js +52 -0
  66. package/dist/.next/types/app/api/service/stop/route.js +52 -0
  67. package/dist/.next/types/app/layout.js +22 -0
  68. package/dist/.next/types/app/logs/page.js +22 -0
  69. package/dist/.next/types/app/models/page.js +22 -0
  70. package/dist/.next/types/app/page.js +22 -0
  71. package/dist/.next/types/app/providers/page.js +22 -0
  72. package/dist/src/app/api/config/route.js +43 -0
  73. package/dist/src/app/api/gateway/[...path]/route.js +83 -0
  74. package/dist/src/app/api/gateway/route.js +63 -0
  75. package/dist/src/app/api/logs/route.js +34 -0
  76. package/dist/src/app/api/models/route.js +152 -0
  77. package/dist/src/app/api/providers/route.js +118 -0
  78. package/dist/src/app/api/providers/test/route.js +154 -0
  79. package/dist/src/app/api/service/start/route.js +55 -0
  80. package/dist/src/app/api/service/status/route.js +17 -0
  81. package/dist/src/app/api/service/stop/route.js +20 -0
  82. package/dist/src/app/components/ConfirmDialog.jsx +31 -0
  83. package/dist/src/app/components/Nav.jsx +45 -0
  84. package/dist/src/app/components/Toast.jsx +37 -0
  85. package/dist/src/app/components/ToastProvider.jsx +21 -0
  86. package/dist/src/app/layout.jsx +13 -0
  87. package/dist/src/app/logs/page.jsx +210 -0
  88. package/dist/src/app/models/page.jsx +291 -0
  89. package/dist/src/app/page.jsx +236 -0
  90. package/dist/src/app/providers/page.jsx +402 -0
  91. package/dist/src/cli/index.js +90 -0
  92. package/dist/src/db/database.js +69 -0
  93. package/dist/src/db/queries.js +261 -0
  94. package/dist/src/db/schema.js +67 -0
  95. package/dist/src/server/crypto.js +22 -0
  96. package/dist/src/server/gateway-server.js +200 -0
  97. package/dist/src/server/gateway.js +76 -0
  98. package/dist/src/server/logger.js +72 -0
  99. package/dist/src/server/providers/anthropic.js +52 -0
  100. package/dist/src/server/providers/gemini.js +64 -0
  101. package/dist/src/server/providers/index.js +16 -0
  102. package/dist/src/server/providers/openai.js +86 -0
  103. package/dist/src/server/providers/types.js +1 -0
  104. package/dist/src/server/service-manager.js +286 -0
  105. package/docs/TODO.md +19 -0
  106. package/next.config.js +7 -0
  107. package/openspec/AGENTS.md +456 -0
  108. package/openspec/changes/add-logging/proposal.md +18 -0
  109. package/openspec/changes/add-logging/specs/core/spec.md +21 -0
  110. package/openspec/changes/add-logging/tasks.md +16 -0
  111. package/openspec/changes/add-provider-test-connection/proposal.md +22 -0
  112. package/openspec/changes/add-provider-test-connection/specs/model-provider/spec.md +68 -0
  113. package/openspec/changes/add-provider-test-connection/tasks.md +31 -0
  114. package/openspec/changes/improve-gateway-startup/design.md +137 -0
  115. package/openspec/changes/improve-gateway-startup/proposal.md +33 -0
  116. package/openspec/changes/improve-gateway-startup/specs/api-gateway/spec.md +94 -0
  117. package/openspec/changes/improve-gateway-startup/specs/web-ui/spec.md +67 -0
  118. package/openspec/changes/improve-gateway-startup/tasks.md +47 -0
  119. package/openspec/changes/init-api-gateway/design.md +185 -0
  120. package/openspec/changes/init-api-gateway/proposal.md +30 -0
  121. package/openspec/changes/init-api-gateway/specs/api-gateway/spec.md +42 -0
  122. package/openspec/changes/init-api-gateway/specs/cli-tool/spec.md +40 -0
  123. package/openspec/changes/init-api-gateway/specs/model-management/spec.md +47 -0
  124. package/openspec/changes/init-api-gateway/specs/model-provider/spec.md +33 -0
  125. package/openspec/changes/init-api-gateway/specs/request-logging/spec.md +54 -0
  126. package/openspec/changes/init-api-gateway/specs/web-ui/spec.md +49 -0
  127. package/openspec/changes/init-api-gateway/tasks.md +84 -0
  128. package/openspec/project.md +58 -0
  129. package/package.json +51 -0
  130. package/postcss.config.js +6 -0
  131. package/src/app/api/config/route.ts +62 -0
  132. package/src/app/api/gateway/[...path]/route.ts +118 -0
  133. package/src/app/api/gateway/route.ts +77 -0
  134. package/src/app/api/logs/route.ts +48 -0
  135. package/src/app/api/models/route.ts +210 -0
  136. package/src/app/api/providers/route.ts +162 -0
  137. package/src/app/api/providers/test/route.ts +182 -0
  138. package/src/app/api/service/start/route.ts +73 -0
  139. package/src/app/api/service/status/route.ts +22 -0
  140. package/src/app/api/service/stop/route.ts +27 -0
  141. package/src/app/components/ConfirmDialog.tsx +63 -0
  142. package/src/app/components/Nav.tsx +66 -0
  143. package/src/app/components/Toast.tsx +61 -0
  144. package/src/app/components/ToastProvider.tsx +43 -0
  145. package/src/app/globals.css +71 -0
  146. package/src/app/layout.tsx +22 -0
  147. package/src/app/logs/page.tsx +261 -0
  148. package/src/app/models/page.tsx +500 -0
  149. package/src/app/page.tsx +742 -0
  150. package/src/app/providers/page.tsx +558 -0
  151. package/src/cli/index.ts +95 -0
  152. package/src/db/database.ts +125 -0
  153. package/src/db/queries.ts +339 -0
  154. package/src/db/schema.ts +117 -0
  155. package/src/server/crypto.ts +48 -0
  156. package/src/server/gateway-server.ts +306 -0
  157. package/src/server/gateway.ts +163 -0
  158. package/src/server/logger.ts +96 -0
  159. package/src/server/providers/anthropic.ts +121 -0
  160. package/src/server/providers/gemini.ts +112 -0
  161. package/src/server/providers/index.ts +20 -0
  162. package/src/server/providers/openai.ts +235 -0
  163. package/src/server/providers/types.ts +20 -0
  164. package/src/server/service-manager.ts +321 -0
  165. package/tailwind.config.js +16 -0
  166. package/tsconfig.json +29 -0
@@ -0,0 +1,321 @@
1
+ import { spawn, ChildProcess, exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import { getServiceStatus, setServiceStatus, updateServiceStatus, clearServiceStatus } from '@/db/queries';
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+ import net from 'net';
7
+
8
+ const execAsync = promisify(exec);
9
+
10
+ export interface ServiceStatusResponse {
11
+ status: 'running' | 'stopped';
12
+ port?: number;
13
+ pid?: number | null;
14
+ started_at?: string | null;
15
+ error?: string;
16
+ }
17
+
18
+ class ServiceManager {
19
+ private childProcess: ChildProcess | null = null;
20
+ private isStarting: boolean = false;
21
+
22
+ /**
23
+ * Check if a process with the given PID exists
24
+ */
25
+ private async checkProcessExists(pid: number): Promise<boolean> {
26
+ try {
27
+ // Use 'ps' command to check if process exists
28
+ // This works on Unix-like systems (macOS, Linux)
29
+ await execAsync(`ps -p ${pid} -o pid=`);
30
+ return true;
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Check if a port is available
38
+ */
39
+ private async checkPortAvailable(port: number): Promise<boolean> {
40
+ return new Promise((resolve) => {
41
+ const server = net.createServer();
42
+
43
+ server.listen(port, () => {
44
+ server.once('close', () => resolve(true));
45
+ server.close();
46
+ });
47
+
48
+ server.on('error', () => {
49
+ resolve(false);
50
+ });
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Check if a port is in use and get process info
56
+ */
57
+ private async checkPortInUse(port: number): Promise<{ inUse: boolean; processInfo?: string }> {
58
+ return new Promise((resolve) => {
59
+ const server = net.createServer();
60
+
61
+ server.listen(port, () => {
62
+ server.once('close', () => resolve({ inUse: false }));
63
+ server.close();
64
+ });
65
+
66
+ server.on('error', (err: any) => {
67
+ if (err.code === 'EADDRINUSE') {
68
+ // Try to get process info
69
+ execAsync(`lsof -ti:${port} 2>/dev/null || echo ''`)
70
+ .then(({ stdout }) => {
71
+ const pid = stdout.trim();
72
+ if (pid) {
73
+ resolve({ inUse: true, processInfo: `Port ${port} is in use by process ${pid}` });
74
+ } else {
75
+ resolve({ inUse: true, processInfo: `Port ${port} is already in use` });
76
+ }
77
+ })
78
+ .catch(() => {
79
+ resolve({ inUse: true, processInfo: `Port ${port} is already in use` });
80
+ });
81
+ } else {
82
+ resolve({ inUse: false });
83
+ }
84
+ });
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Get current service status, verifying process existence
90
+ */
91
+ async getStatus(): Promise<ServiceStatusResponse> {
92
+ const dbStatus = getServiceStatus();
93
+
94
+ if (!dbStatus) {
95
+ return { status: 'stopped' };
96
+ }
97
+
98
+ // If status is running, verify process actually exists
99
+ if (dbStatus.status === 'running' && dbStatus.pid) {
100
+ const processExists = await this.checkProcessExists(dbStatus.pid);
101
+ if (!processExists) {
102
+ // Process doesn't exist, update database
103
+ updateServiceStatus({ status: 'stopped', pid: null });
104
+ return { status: 'stopped' };
105
+ }
106
+ }
107
+
108
+ return {
109
+ status: dbStatus.status,
110
+ port: dbStatus.port,
111
+ pid: dbStatus.pid,
112
+ started_at: dbStatus.started_at,
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Start the gateway service
118
+ */
119
+ async start(port: number): Promise<ServiceStatusResponse> {
120
+ // Prevent concurrent starts
121
+ if (this.isStarting) {
122
+ return { status: 'stopped', error: 'Service is already starting' };
123
+ }
124
+
125
+ // Check if service is already running
126
+ const currentStatus = await this.getStatus();
127
+ if (currentStatus.status === 'running') {
128
+ return { status: 'running', error: 'Service is already running', port: currentStatus.port, pid: currentStatus.pid };
129
+ }
130
+
131
+ // Check port availability with more details
132
+ const portCheck = await this.checkPortInUse(port);
133
+ if (portCheck.inUse) {
134
+ // In development, if port 3000 is in use, suggest using a different port
135
+ const isDev = process.env.NODE_ENV !== 'production';
136
+ if (isDev && port === 3000) {
137
+ return {
138
+ status: 'stopped',
139
+ error: `Port 3000 is already in use (likely by the development server). Please configure a different port (e.g., 3001) in the settings.`
140
+ };
141
+ }
142
+ return { status: 'stopped', error: portCheck.processInfo || `Port ${port} is already in use` };
143
+ }
144
+
145
+ this.isStarting = true;
146
+
147
+ try {
148
+ const cliPath = path.join(process.cwd(), 'dist', 'src', 'cli', 'index.js');
149
+ const tsCliPath = path.join(process.cwd(), 'src', 'cli', 'index.ts');
150
+
151
+ let child: ChildProcess;
152
+
153
+ // Create isolated environment for child process
154
+ // Remove Next.js dev server specific env vars to avoid conflicts
155
+ const childEnv = { ...process.env };
156
+ // Remove PORT if it might conflict
157
+ if (childEnv.PORT && parseInt(childEnv.PORT) === 3000) {
158
+ delete childEnv.PORT;
159
+ }
160
+ // Remove Next.js specific env vars that might cause conflicts
161
+ delete childEnv.NEXT_TELEMETRY_DISABLED;
162
+ // Gateway server doesn't need Next.js, so we can use any NODE_ENV
163
+ childEnv.NODE_ENV = process.env.NODE_ENV || 'production';
164
+
165
+ // Check if compiled code exists
166
+ if (fs.existsSync(cliPath)) {
167
+ // Use compiled JavaScript
168
+ child = spawn(process.execPath, [cliPath, 'start', '-p', port.toString()], {
169
+ detached: false, // Keep attached for proper tracking
170
+ stdio: ['ignore', 'pipe', 'pipe'],
171
+ cwd: process.cwd(),
172
+ env: childEnv,
173
+ });
174
+ } else if (fs.existsSync(tsCliPath)) {
175
+ // In development, try to use tsx via npx
176
+ // Note: tsx should be installed as dev dependency for this to work
177
+ child = spawn('npx', ['--yes', 'tsx', tsCliPath, 'start', '-p', port.toString()], {
178
+ detached: false, // Keep attached for proper tracking
179
+ stdio: ['ignore', 'pipe', 'pipe'],
180
+ cwd: process.cwd(),
181
+ env: childEnv,
182
+ shell: true, // Use shell to resolve npx
183
+ });
184
+ } else {
185
+ this.isStarting = false;
186
+ return {
187
+ status: 'stopped',
188
+ error: 'CLI not found. Please run "npm run build" first, or ensure src/cli/index.ts exists.'
189
+ };
190
+ }
191
+
192
+ this.childProcess = child;
193
+
194
+ // Collect error output for better error messages
195
+ let errorOutput = '';
196
+ let hasExited = false;
197
+ let exitCode: number | null = null;
198
+
199
+ // Handle process output (optional, for debugging)
200
+ // Use setImmediate to avoid blocking the event loop
201
+ child.stdout?.on('data', (data) => {
202
+ setImmediate(() => {
203
+ const output = data.toString();
204
+ // Only log if it's not empty and not just whitespace
205
+ if (output.trim()) {
206
+ console.log(`[Gateway Service] ${output}`);
207
+ }
208
+ });
209
+ });
210
+
211
+ child.stderr?.on('data', (data) => {
212
+ setImmediate(() => {
213
+ const errorText = data.toString();
214
+ console.error(`[Gateway Service Error] ${errorText}`);
215
+ errorOutput += errorText;
216
+ });
217
+ });
218
+
219
+ // Handle process exit
220
+ child.on('exit', (code, signal) => {
221
+ hasExited = true;
222
+ exitCode = code;
223
+ console.log(`[Gateway Service] Process exited with code ${code}, signal ${signal}`);
224
+ this.childProcess = null;
225
+ this.isStarting = false;
226
+
227
+ // Update database status
228
+ updateServiceStatus({ status: 'stopped', pid: null });
229
+ });
230
+
231
+ // Wait a bit to see if process starts successfully
232
+ await new Promise((resolve) => setTimeout(resolve, 2000));
233
+
234
+ // Check if process exited during startup
235
+ if (hasExited || child.killed || child.exitCode !== null) {
236
+ this.isStarting = false;
237
+ this.childProcess = null;
238
+
239
+ // Extract meaningful error message
240
+ let errorMessage = 'Service failed to start';
241
+ if (errorOutput) {
242
+ // Try to extract the main error message
243
+ const errorMatch = errorOutput.match(/Error: ([^\n]+)/);
244
+ if (errorMatch) {
245
+ errorMessage = errorMatch[1];
246
+ } else if (errorOutput.includes('production build')) {
247
+ errorMessage = 'Production build not found. Please run "npm run build" first, or use development mode.';
248
+ } else {
249
+ // Use first meaningful line of error
250
+ const lines = errorOutput.split('\n').filter(line => line.trim());
251
+ if (lines.length > 0) {
252
+ errorMessage = lines[0].substring(0, 200); // Limit length
253
+ }
254
+ }
255
+ }
256
+
257
+ return { status: 'stopped', error: errorMessage };
258
+ }
259
+
260
+ // Save status to database
261
+ const pid = child.pid || null;
262
+ const startedAt = new Date().toISOString();
263
+ setServiceStatus({
264
+ status: 'running',
265
+ port,
266
+ pid,
267
+ started_at: startedAt,
268
+ });
269
+
270
+ this.isStarting = false;
271
+
272
+ return {
273
+ status: 'running',
274
+ port,
275
+ pid,
276
+ started_at: startedAt,
277
+ };
278
+ } catch (error: any) {
279
+ this.isStarting = false;
280
+ this.childProcess = null;
281
+ return { status: 'stopped', error: error.message || 'Failed to start service' };
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Stop the gateway service
287
+ */
288
+ async stop(): Promise<ServiceStatusResponse> {
289
+ const currentStatus = await this.getStatus();
290
+
291
+ if (currentStatus.status === 'stopped') {
292
+ return { status: 'stopped' };
293
+ }
294
+
295
+ try {
296
+ // If we have a reference to the child process, kill it
297
+ if (this.childProcess) {
298
+ this.childProcess.kill('SIGTERM');
299
+ this.childProcess = null;
300
+ } else if (currentStatus.pid) {
301
+ // Try to kill by PID
302
+ try {
303
+ process.kill(currentStatus.pid, 'SIGTERM');
304
+ } catch (error) {
305
+ // Process might not exist
306
+ console.warn(`Failed to kill process ${currentStatus.pid}:`, error);
307
+ }
308
+ }
309
+
310
+ // Update database status
311
+ updateServiceStatus({ status: 'stopped', pid: null });
312
+
313
+ return { status: 'stopped' };
314
+ } catch (error: any) {
315
+ return { status: 'stopped', error: error.message || 'Failed to stop service' };
316
+ }
317
+ }
318
+ }
319
+
320
+ // Export singleton instance
321
+ export const serviceManager = new ServiceManager();
@@ -0,0 +1,16 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ content: [
4
+ './app/**/*.{js,ts,jsx,tsx,mdx}',
5
+ './src/app/**/*.{js,ts,jsx,tsx,mdx}',
6
+ ],
7
+ theme: {
8
+ extend: {
9
+ colors: {
10
+ background: 'var(--background)',
11
+ foreground: 'var(--foreground)',
12
+ },
13
+ },
14
+ },
15
+ plugins: [],
16
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
5
+ "jsx": "preserve",
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "resolveJsonModule": true,
9
+ "allowJs": true,
10
+ "strict": true,
11
+ "noEmit": false,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "incremental": true,
16
+ "isolatedModules": true,
17
+ "plugins": [
18
+ {
19
+ "name": "next"
20
+ }
21
+ ],
22
+ "paths": {
23
+ "@/*": ["./src/*"]
24
+ },
25
+ "outDir": "./dist"
26
+ },
27
+ "include": ["next-env.d.ts", "src/**/*.ts", "src/**/*.tsx", ".next/types/**/*.ts"],
28
+ "exclude": ["node_modules", "dist"]
29
+ }