nc1709 1.15.4__py3-none-any.whl

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 (86) hide show
  1. nc1709/__init__.py +13 -0
  2. nc1709/agent/__init__.py +36 -0
  3. nc1709/agent/core.py +505 -0
  4. nc1709/agent/mcp_bridge.py +245 -0
  5. nc1709/agent/permissions.py +298 -0
  6. nc1709/agent/tools/__init__.py +21 -0
  7. nc1709/agent/tools/base.py +440 -0
  8. nc1709/agent/tools/bash_tool.py +367 -0
  9. nc1709/agent/tools/file_tools.py +454 -0
  10. nc1709/agent/tools/notebook_tools.py +516 -0
  11. nc1709/agent/tools/search_tools.py +322 -0
  12. nc1709/agent/tools/task_tool.py +284 -0
  13. nc1709/agent/tools/web_tools.py +555 -0
  14. nc1709/agents/__init__.py +17 -0
  15. nc1709/agents/auto_fix.py +506 -0
  16. nc1709/agents/test_generator.py +507 -0
  17. nc1709/checkpoints.py +372 -0
  18. nc1709/cli.py +3380 -0
  19. nc1709/cli_ui.py +1080 -0
  20. nc1709/cognitive/__init__.py +149 -0
  21. nc1709/cognitive/anticipation.py +594 -0
  22. nc1709/cognitive/context_engine.py +1046 -0
  23. nc1709/cognitive/council.py +824 -0
  24. nc1709/cognitive/learning.py +761 -0
  25. nc1709/cognitive/router.py +583 -0
  26. nc1709/cognitive/system.py +519 -0
  27. nc1709/config.py +155 -0
  28. nc1709/custom_commands.py +300 -0
  29. nc1709/executor.py +333 -0
  30. nc1709/file_controller.py +354 -0
  31. nc1709/git_integration.py +308 -0
  32. nc1709/github_integration.py +477 -0
  33. nc1709/image_input.py +446 -0
  34. nc1709/linting.py +519 -0
  35. nc1709/llm_adapter.py +667 -0
  36. nc1709/logger.py +192 -0
  37. nc1709/mcp/__init__.py +18 -0
  38. nc1709/mcp/client.py +370 -0
  39. nc1709/mcp/manager.py +407 -0
  40. nc1709/mcp/protocol.py +210 -0
  41. nc1709/mcp/server.py +473 -0
  42. nc1709/memory/__init__.py +20 -0
  43. nc1709/memory/embeddings.py +325 -0
  44. nc1709/memory/indexer.py +474 -0
  45. nc1709/memory/sessions.py +432 -0
  46. nc1709/memory/vector_store.py +451 -0
  47. nc1709/models/__init__.py +86 -0
  48. nc1709/models/detector.py +377 -0
  49. nc1709/models/formats.py +315 -0
  50. nc1709/models/manager.py +438 -0
  51. nc1709/models/registry.py +497 -0
  52. nc1709/performance/__init__.py +343 -0
  53. nc1709/performance/cache.py +705 -0
  54. nc1709/performance/pipeline.py +611 -0
  55. nc1709/performance/tiering.py +543 -0
  56. nc1709/plan_mode.py +362 -0
  57. nc1709/plugins/__init__.py +17 -0
  58. nc1709/plugins/agents/__init__.py +18 -0
  59. nc1709/plugins/agents/django_agent.py +912 -0
  60. nc1709/plugins/agents/docker_agent.py +623 -0
  61. nc1709/plugins/agents/fastapi_agent.py +887 -0
  62. nc1709/plugins/agents/git_agent.py +731 -0
  63. nc1709/plugins/agents/nextjs_agent.py +867 -0
  64. nc1709/plugins/base.py +359 -0
  65. nc1709/plugins/manager.py +411 -0
  66. nc1709/plugins/registry.py +337 -0
  67. nc1709/progress.py +443 -0
  68. nc1709/prompts/__init__.py +22 -0
  69. nc1709/prompts/agent_system.py +180 -0
  70. nc1709/prompts/task_prompts.py +340 -0
  71. nc1709/prompts/unified_prompt.py +133 -0
  72. nc1709/reasoning_engine.py +541 -0
  73. nc1709/remote_client.py +266 -0
  74. nc1709/shell_completions.py +349 -0
  75. nc1709/slash_commands.py +649 -0
  76. nc1709/task_classifier.py +408 -0
  77. nc1709/version_check.py +177 -0
  78. nc1709/web/__init__.py +8 -0
  79. nc1709/web/server.py +950 -0
  80. nc1709/web/templates/index.html +1127 -0
  81. nc1709-1.15.4.dist-info/METADATA +858 -0
  82. nc1709-1.15.4.dist-info/RECORD +86 -0
  83. nc1709-1.15.4.dist-info/WHEEL +5 -0
  84. nc1709-1.15.4.dist-info/entry_points.txt +2 -0
  85. nc1709-1.15.4.dist-info/licenses/LICENSE +9 -0
  86. nc1709-1.15.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,867 @@
1
+ """
2
+ Next.js Agent for NC1709
3
+ Scaffolds Next.js projects, pages, components, and API routes
4
+ """
5
+ import os
6
+ import json
7
+ from pathlib import Path
8
+ from typing import Dict, Any, Optional, List
9
+
10
+ from ..base import (
11
+ Plugin, PluginMetadata, PluginCapability,
12
+ ActionResult
13
+ )
14
+
15
+
16
+ class NextJSAgent(Plugin):
17
+ """
18
+ Next.js scaffolding and development agent.
19
+
20
+ Provides:
21
+ - Project scaffolding (App Router or Pages Router)
22
+ - Page generation
23
+ - Component generation (with TypeScript support)
24
+ - API route generation
25
+ - Layout generation
26
+ - Middleware setup
27
+ """
28
+
29
+ METADATA = PluginMetadata(
30
+ name="nextjs",
31
+ version="1.0.0",
32
+ description="Next.js project scaffolding and development",
33
+ author="NC1709 Team",
34
+ capabilities=[
35
+ PluginCapability.CODE_GENERATION,
36
+ PluginCapability.PROJECT_SCAFFOLDING
37
+ ],
38
+ keywords=[
39
+ "nextjs", "next", "react", "typescript", "javascript",
40
+ "component", "page", "api", "route", "layout",
41
+ "middleware", "frontend", "ssr", "ssg"
42
+ ],
43
+ config_schema={
44
+ "project_path": {"type": "string", "default": "."},
45
+ "use_typescript": {"type": "boolean", "default": True},
46
+ "use_app_router": {"type": "boolean", "default": True},
47
+ "styling": {"type": "string", "enum": ["tailwind", "css-modules", "styled-components"], "default": "tailwind"}
48
+ }
49
+ )
50
+
51
+ @property
52
+ def metadata(self) -> PluginMetadata:
53
+ return self.METADATA
54
+
55
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
56
+ super().__init__(config)
57
+ self._project_path: Optional[Path] = None
58
+
59
+ def initialize(self) -> bool:
60
+ """Initialize the Next.js agent"""
61
+ self._project_path = Path(self._config.get("project_path", ".")).resolve()
62
+ return True
63
+
64
+ def cleanup(self) -> None:
65
+ """Cleanup resources"""
66
+ pass
67
+
68
+ def _register_actions(self) -> None:
69
+ """Register Next.js actions"""
70
+ self.register_action(
71
+ "scaffold",
72
+ self.scaffold_project,
73
+ "Create a new Next.js project structure",
74
+ parameters={
75
+ "name": {"type": "string", "required": True},
76
+ "typescript": {"type": "boolean", "default": True},
77
+ "tailwind": {"type": "boolean", "default": True}
78
+ }
79
+ )
80
+
81
+ self.register_action(
82
+ "page",
83
+ self.create_page,
84
+ "Generate a new page",
85
+ parameters={
86
+ "path": {"type": "string", "required": True},
87
+ "name": {"type": "string", "required": True}
88
+ }
89
+ )
90
+
91
+ self.register_action(
92
+ "component",
93
+ self.create_component,
94
+ "Generate a React component",
95
+ parameters={
96
+ "name": {"type": "string", "required": True},
97
+ "props": {"type": "object", "default": {}},
98
+ "client": {"type": "boolean", "default": False}
99
+ }
100
+ )
101
+
102
+ self.register_action(
103
+ "api",
104
+ self.create_api_route,
105
+ "Generate an API route",
106
+ parameters={
107
+ "path": {"type": "string", "required": True},
108
+ "methods": {"type": "array", "default": ["GET"]}
109
+ }
110
+ )
111
+
112
+ self.register_action(
113
+ "layout",
114
+ self.create_layout,
115
+ "Generate a layout component",
116
+ parameters={
117
+ "path": {"type": "string", "default": ""},
118
+ "name": {"type": "string", "default": "Layout"}
119
+ }
120
+ )
121
+
122
+ self.register_action(
123
+ "analyze",
124
+ self.analyze_project,
125
+ "Analyze existing Next.js project structure"
126
+ )
127
+
128
+ def scaffold_project(
129
+ self,
130
+ name: str,
131
+ typescript: bool = True,
132
+ tailwind: bool = True
133
+ ) -> ActionResult:
134
+ """Create a new Next.js project structure
135
+
136
+ Args:
137
+ name: Project name
138
+ typescript: Use TypeScript
139
+ tailwind: Include Tailwind CSS
140
+
141
+ Returns:
142
+ ActionResult
143
+ """
144
+ project_dir = self._project_path / name
145
+ ext = "tsx" if typescript else "jsx"
146
+ style_ext = "module.css"
147
+
148
+ if project_dir.exists():
149
+ return ActionResult.fail(f"Directory '{name}' already exists")
150
+
151
+ try:
152
+ # Create directory structure (App Router)
153
+ dirs = [
154
+ project_dir,
155
+ project_dir / "app",
156
+ project_dir / "app" / "api",
157
+ project_dir / "components",
158
+ project_dir / "lib",
159
+ project_dir / "public",
160
+ project_dir / "styles",
161
+ ]
162
+
163
+ for d in dirs:
164
+ d.mkdir(parents=True, exist_ok=True)
165
+
166
+ # Create package.json
167
+ package_json = self._generate_package_json(name, typescript, tailwind)
168
+ (project_dir / "package.json").write_text(json.dumps(package_json, indent=2))
169
+
170
+ # Create root layout
171
+ layout_content = self._generate_root_layout(typescript, tailwind)
172
+ (project_dir / "app" / f"layout.{ext}").write_text(layout_content)
173
+
174
+ # Create home page
175
+ page_content = self._generate_home_page(typescript)
176
+ (project_dir / "app" / f"page.{ext}").write_text(page_content)
177
+
178
+ # Create global styles
179
+ if tailwind:
180
+ globals_css = self._generate_tailwind_globals()
181
+ (project_dir / "app" / "globals.css").write_text(globals_css)
182
+
183
+ # Create tailwind config
184
+ tailwind_config = self._generate_tailwind_config(typescript)
185
+ config_ext = "ts" if typescript else "js"
186
+ (project_dir / f"tailwind.config.{config_ext}").write_text(tailwind_config)
187
+
188
+ # Create postcss config
189
+ postcss_config = self._generate_postcss_config()
190
+ (project_dir / "postcss.config.js").write_text(postcss_config)
191
+ else:
192
+ globals_css = self._generate_basic_globals()
193
+ (project_dir / "app" / "globals.css").write_text(globals_css)
194
+
195
+ # Create next.config
196
+ next_config = self._generate_next_config(typescript)
197
+ config_ext = "mjs"
198
+ (project_dir / f"next.config.{config_ext}").write_text(next_config)
199
+
200
+ if typescript:
201
+ # Create tsconfig
202
+ tsconfig = self._generate_tsconfig()
203
+ (project_dir / "tsconfig.json").write_text(json.dumps(tsconfig, indent=2))
204
+
205
+ # Create example component
206
+ component_content = self._generate_example_component(typescript)
207
+ (project_dir / "components" / f"Button.{ext}").write_text(component_content)
208
+
209
+ # Create example API route
210
+ api_content = self._generate_example_api(typescript)
211
+ api_dir = project_dir / "app" / "api" / "hello"
212
+ api_dir.mkdir(exist_ok=True)
213
+ (api_dir / f"route.{ext[:2]}").write_text(api_content)
214
+
215
+ # Create .gitignore
216
+ gitignore = self._generate_gitignore()
217
+ (project_dir / ".gitignore").write_text(gitignore)
218
+
219
+ # Create README
220
+ readme = self._generate_readme(name)
221
+ (project_dir / "README.md").write_text(readme)
222
+
223
+ files_created = len(list(project_dir.rglob("*")))
224
+
225
+ return ActionResult.ok(
226
+ message=f"Created Next.js project '{name}' with {files_created} files",
227
+ data={
228
+ "project_path": str(project_dir),
229
+ "typescript": typescript,
230
+ "tailwind": tailwind,
231
+ "next_steps": [
232
+ f"cd {name}",
233
+ "npm install",
234
+ "npm run dev"
235
+ ]
236
+ }
237
+ )
238
+
239
+ except Exception as e:
240
+ return ActionResult.fail(str(e))
241
+
242
+ def create_page(
243
+ self,
244
+ path: str,
245
+ name: str
246
+ ) -> ActionResult:
247
+ """Generate a new page
248
+
249
+ Args:
250
+ path: Page path (e.g., "dashboard" or "users/[id]")
251
+ name: Page component name
252
+
253
+ Returns:
254
+ ActionResult with generated code
255
+ """
256
+ use_ts = self._config.get("use_typescript", True)
257
+ ext = "tsx" if use_ts else "jsx"
258
+
259
+ # Detect dynamic segments
260
+ is_dynamic = "[" in path
261
+
262
+ code = self._generate_page_code(name, path, is_dynamic, use_ts)
263
+
264
+ return ActionResult.ok(
265
+ message=f"Generated page at app/{path}/page.{ext}",
266
+ data={
267
+ "code": code,
268
+ "path": f"app/{path}/page.{ext}",
269
+ "dynamic": is_dynamic
270
+ }
271
+ )
272
+
273
+ def create_component(
274
+ self,
275
+ name: str,
276
+ props: Dict[str, str] = None,
277
+ client: bool = False
278
+ ) -> ActionResult:
279
+ """Generate a React component
280
+
281
+ Args:
282
+ name: Component name
283
+ props: Props definition
284
+ client: Whether it's a client component
285
+
286
+ Returns:
287
+ ActionResult with generated code
288
+ """
289
+ props = props or {}
290
+ use_ts = self._config.get("use_typescript", True)
291
+ ext = "tsx" if use_ts else "jsx"
292
+
293
+ code = self._generate_component_code(name, props, client, use_ts)
294
+
295
+ return ActionResult.ok(
296
+ message=f"Generated component '{name}'",
297
+ data={
298
+ "code": code,
299
+ "path": f"components/{name}.{ext}",
300
+ "client": client
301
+ }
302
+ )
303
+
304
+ def create_api_route(
305
+ self,
306
+ path: str,
307
+ methods: List[str] = None
308
+ ) -> ActionResult:
309
+ """Generate an API route
310
+
311
+ Args:
312
+ path: Route path
313
+ methods: HTTP methods to handle
314
+
315
+ Returns:
316
+ ActionResult with generated code
317
+ """
318
+ methods = methods or ["GET"]
319
+ use_ts = self._config.get("use_typescript", True)
320
+ ext = "ts" if use_ts else "js"
321
+
322
+ code = self._generate_api_route_code(path, methods, use_ts)
323
+
324
+ return ActionResult.ok(
325
+ message=f"Generated API route at app/api/{path}/route.{ext}",
326
+ data={
327
+ "code": code,
328
+ "path": f"app/api/{path}/route.{ext}",
329
+ "methods": methods
330
+ }
331
+ )
332
+
333
+ def create_layout(
334
+ self,
335
+ path: str = "",
336
+ name: str = "Layout"
337
+ ) -> ActionResult:
338
+ """Generate a layout component
339
+
340
+ Args:
341
+ path: Layout path
342
+ name: Layout name
343
+
344
+ Returns:
345
+ ActionResult with generated code
346
+ """
347
+ use_ts = self._config.get("use_typescript", True)
348
+ ext = "tsx" if use_ts else "jsx"
349
+
350
+ code = self._generate_layout_code(name, use_ts)
351
+
352
+ layout_path = f"app/{path}/layout.{ext}" if path else f"app/layout.{ext}"
353
+
354
+ return ActionResult.ok(
355
+ message=f"Generated layout at {layout_path}",
356
+ data={
357
+ "code": code,
358
+ "path": layout_path
359
+ }
360
+ )
361
+
362
+ def analyze_project(self) -> ActionResult:
363
+ """Analyze existing Next.js project structure
364
+
365
+ Returns:
366
+ ActionResult with project analysis
367
+ """
368
+ # Look for Next.js indicators
369
+ package_json = self._project_path / "package.json"
370
+
371
+ if not package_json.exists():
372
+ return ActionResult.fail("No package.json found")
373
+
374
+ try:
375
+ pkg = json.loads(package_json.read_text())
376
+ deps = {**pkg.get("dependencies", {}), **pkg.get("devDependencies", {})}
377
+
378
+ if "next" not in deps:
379
+ return ActionResult.fail("Not a Next.js project (next not in dependencies)")
380
+ except Exception:
381
+ return ActionResult.fail("Could not parse package.json")
382
+
383
+ analysis = {
384
+ "project_path": str(self._project_path),
385
+ "next_version": deps.get("next", "unknown"),
386
+ "typescript": "typescript" in deps,
387
+ "tailwind": "tailwindcss" in deps,
388
+ "app_router": (self._project_path / "app").exists(),
389
+ "pages_router": (self._project_path / "pages").exists(),
390
+ "pages": [],
391
+ "components": [],
392
+ "api_routes": []
393
+ }
394
+
395
+ # Scan for pages
396
+ app_dir = self._project_path / "app"
397
+ if app_dir.exists():
398
+ for page in app_dir.rglob("page.*"):
399
+ rel_path = page.relative_to(app_dir)
400
+ route = "/" + str(rel_path.parent).replace("\\", "/")
401
+ if route == "/.":
402
+ route = "/"
403
+ analysis["pages"].append(route)
404
+
405
+ # Scan for API routes
406
+ api_dir = app_dir / "api"
407
+ if api_dir.exists():
408
+ for route in api_dir.rglob("route.*"):
409
+ rel_path = route.relative_to(api_dir)
410
+ api_path = "/api/" + str(rel_path.parent).replace("\\", "/")
411
+ analysis["api_routes"].append(api_path)
412
+
413
+ # Scan for components
414
+ components_dir = self._project_path / "components"
415
+ if components_dir.exists():
416
+ for comp in components_dir.rglob("*.tsx"):
417
+ analysis["components"].append(comp.stem)
418
+ for comp in components_dir.rglob("*.jsx"):
419
+ analysis["components"].append(comp.stem)
420
+
421
+ return ActionResult.ok(
422
+ message=f"Analyzed Next.js project with {len(analysis['pages'])} pages",
423
+ data=analysis
424
+ )
425
+
426
+ # Code generation helpers
427
+
428
+ def _generate_package_json(self, name: str, typescript: bool, tailwind: bool) -> dict:
429
+ """Generate package.json"""
430
+ pkg = {
431
+ "name": name,
432
+ "version": "0.1.0",
433
+ "private": True,
434
+ "scripts": {
435
+ "dev": "next dev",
436
+ "build": "next build",
437
+ "start": "next start",
438
+ "lint": "next lint"
439
+ },
440
+ "dependencies": {
441
+ "next": "14.0.0",
442
+ "react": "^18",
443
+ "react-dom": "^18"
444
+ },
445
+ "devDependencies": {
446
+ "eslint": "^8",
447
+ "eslint-config-next": "14.0.0"
448
+ }
449
+ }
450
+
451
+ if typescript:
452
+ pkg["devDependencies"].update({
453
+ "typescript": "^5",
454
+ "@types/node": "^20",
455
+ "@types/react": "^18",
456
+ "@types/react-dom": "^18"
457
+ })
458
+
459
+ if tailwind:
460
+ pkg["devDependencies"].update({
461
+ "tailwindcss": "^3.3.0",
462
+ "autoprefixer": "^10.0.1",
463
+ "postcss": "^8"
464
+ })
465
+
466
+ return pkg
467
+
468
+ def _generate_root_layout(self, typescript: bool, tailwind: bool) -> str:
469
+ """Generate root layout"""
470
+ props_type = ": { children: React.ReactNode }" if typescript else ""
471
+
472
+ return f'''import type {{ Metadata }} from 'next'
473
+ import './globals.css'
474
+
475
+ export const metadata: Metadata = {{
476
+ title: 'My App',
477
+ description: 'Built with Next.js',
478
+ }}
479
+
480
+ export default function RootLayout({{
481
+ children,
482
+ }}{props_type}) {{
483
+ return (
484
+ <html lang="en">
485
+ <body{' className="antialiased"' if tailwind else ''}>{{children}}</body>
486
+ </html>
487
+ )
488
+ }}
489
+ '''
490
+
491
+ def _generate_home_page(self, typescript: bool) -> str:
492
+ """Generate home page"""
493
+ return '''export default function Home() {
494
+ return (
495
+ <main className="flex min-h-screen flex-col items-center justify-center p-24">
496
+ <h1 className="text-4xl font-bold">Welcome to Next.js</h1>
497
+ <p className="mt-4 text-lg text-gray-600">
498
+ Get started by editing app/page.tsx
499
+ </p>
500
+ </main>
501
+ )
502
+ }
503
+ '''
504
+
505
+ def _generate_tailwind_globals(self) -> str:
506
+ """Generate Tailwind CSS globals"""
507
+ return '''@tailwind base;
508
+ @tailwind components;
509
+ @tailwind utilities;
510
+ '''
511
+
512
+ def _generate_basic_globals(self) -> str:
513
+ """Generate basic CSS globals"""
514
+ return '''* {
515
+ box-sizing: border-box;
516
+ padding: 0;
517
+ margin: 0;
518
+ }
519
+
520
+ html,
521
+ body {
522
+ max-width: 100vw;
523
+ overflow-x: hidden;
524
+ }
525
+
526
+ a {
527
+ color: inherit;
528
+ text-decoration: none;
529
+ }
530
+ '''
531
+
532
+ def _generate_tailwind_config(self, typescript: bool) -> str:
533
+ """Generate Tailwind config"""
534
+ if typescript:
535
+ return '''import type { Config } from 'tailwindcss'
536
+
537
+ const config: Config = {
538
+ content: [
539
+ './pages/**/*.{js,ts,jsx,tsx,mdx}',
540
+ './components/**/*.{js,ts,jsx,tsx,mdx}',
541
+ './app/**/*.{js,ts,jsx,tsx,mdx}',
542
+ ],
543
+ theme: {
544
+ extend: {},
545
+ },
546
+ plugins: [],
547
+ }
548
+ export default config
549
+ '''
550
+ return '''/** @type {import('tailwindcss').Config} */
551
+ module.exports = {
552
+ content: [
553
+ './pages/**/*.{js,ts,jsx,tsx,mdx}',
554
+ './components/**/*.{js,ts,jsx,tsx,mdx}',
555
+ './app/**/*.{js,ts,jsx,tsx,mdx}',
556
+ ],
557
+ theme: {
558
+ extend: {},
559
+ },
560
+ plugins: [],
561
+ }
562
+ '''
563
+
564
+ def _generate_postcss_config(self) -> str:
565
+ """Generate PostCSS config"""
566
+ return '''module.exports = {
567
+ plugins: {
568
+ tailwindcss: {},
569
+ autoprefixer: {},
570
+ },
571
+ }
572
+ '''
573
+
574
+ def _generate_next_config(self, typescript: bool) -> str:
575
+ """Generate next.config"""
576
+ return '''/** @type {import('next').NextConfig} */
577
+ const nextConfig = {}
578
+
579
+ export default nextConfig
580
+ '''
581
+
582
+ def _generate_tsconfig(self) -> dict:
583
+ """Generate tsconfig.json"""
584
+ return {
585
+ "compilerOptions": {
586
+ "lib": ["dom", "dom.iterable", "esnext"],
587
+ "allowJs": True,
588
+ "skipLibCheck": True,
589
+ "strict": True,
590
+ "noEmit": True,
591
+ "esModuleInterop": True,
592
+ "module": "esnext",
593
+ "moduleResolution": "bundler",
594
+ "resolveJsonModule": True,
595
+ "isolatedModules": True,
596
+ "jsx": "preserve",
597
+ "incremental": True,
598
+ "plugins": [{"name": "next"}],
599
+ "paths": {"@/*": ["./*"]}
600
+ },
601
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
602
+ "exclude": ["node_modules"]
603
+ }
604
+
605
+ def _generate_example_component(self, typescript: bool) -> str:
606
+ """Generate example component"""
607
+ props_interface = '''
608
+ interface ButtonProps {
609
+ children: React.ReactNode
610
+ onClick?: () => void
611
+ variant?: 'primary' | 'secondary'
612
+ }
613
+ ''' if typescript else ''
614
+
615
+ props_type = ": ButtonProps" if typescript else ""
616
+
617
+ return f'''"use client"
618
+ {props_interface}
619
+ export default function Button({{ children, onClick, variant = 'primary' }}{props_type}) {{
620
+ const baseStyles = "px-4 py-2 rounded-lg font-medium transition-colors"
621
+ const variants = {{
622
+ primary: "bg-blue-500 text-white hover:bg-blue-600",
623
+ secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300"
624
+ }}
625
+
626
+ return (
627
+ <button
628
+ onClick={{onClick}}
629
+ className={{`${{baseStyles}} ${{variants[variant]}}`}}
630
+ >
631
+ {{children}}
632
+ </button>
633
+ )
634
+ }}
635
+ '''
636
+
637
+ def _generate_example_api(self, typescript: bool) -> str:
638
+ """Generate example API route"""
639
+ type_import = "import { NextRequest, NextResponse } from 'next/server'\n\n" if typescript else ""
640
+
641
+ return f'''{type_import}export async function GET() {{
642
+ return Response.json({{ message: 'Hello from API' }})
643
+ }}
644
+
645
+ export async function POST(request{': NextRequest' if typescript else ''}) {{
646
+ const data = await request.json()
647
+ return Response.json({{ received: data }})
648
+ }}
649
+ '''
650
+
651
+ def _generate_gitignore(self) -> str:
652
+ """Generate .gitignore"""
653
+ return '''# dependencies
654
+ /node_modules
655
+ /.pnp
656
+ .pnp.js
657
+
658
+ # testing
659
+ /coverage
660
+
661
+ # next.js
662
+ /.next/
663
+ /out/
664
+
665
+ # production
666
+ /build
667
+
668
+ # misc
669
+ .DS_Store
670
+ *.pem
671
+
672
+ # debug
673
+ npm-debug.log*
674
+ yarn-debug.log*
675
+ yarn-error.log*
676
+
677
+ # local env files
678
+ .env*.local
679
+
680
+ # typescript
681
+ *.tsbuildinfo
682
+ next-env.d.ts
683
+ '''
684
+
685
+ def _generate_readme(self, name: str) -> str:
686
+ """Generate README.md"""
687
+ return f'''# {name}
688
+
689
+ This is a [Next.js](https://nextjs.org/) project.
690
+
691
+ ## Getting Started
692
+
693
+ First, install dependencies:
694
+
695
+ ```bash
696
+ npm install
697
+ ```
698
+
699
+ Then, run the development server:
700
+
701
+ ```bash
702
+ npm run dev
703
+ ```
704
+
705
+ Open [http://localhost:3000](http://localhost:3000) with your browser.
706
+
707
+ ## Project Structure
708
+
709
+ ```
710
+ ├── app/
711
+ │ ├── layout.tsx # Root layout
712
+ │ ├── page.tsx # Home page
713
+ │ └── api/ # API routes
714
+ ├── components/ # React components
715
+ ├── lib/ # Utility functions
716
+ └── public/ # Static files
717
+ ```
718
+
719
+ ## Learn More
720
+
721
+ - [Next.js Documentation](https://nextjs.org/docs)
722
+ - [Learn Next.js](https://nextjs.org/learn)
723
+ '''
724
+
725
+ def _generate_page_code(self, name: str, path: str, is_dynamic: bool, typescript: bool) -> str:
726
+ """Generate page code"""
727
+ props = ""
728
+ if is_dynamic and typescript:
729
+ # Extract param name
730
+ import re
731
+ params = re.findall(r'\[(\w+)\]', path)
732
+ if params:
733
+ props = f"{{ params }}: {{ params: {{ {params[0]}: string }} }}"
734
+
735
+ return f'''export default function {name}Page({props}) {{
736
+ return (
737
+ <div className="p-8">
738
+ <h1 className="text-2xl font-bold">{name}</h1>
739
+ {f'<p>ID: {{params.{params[0]}}}</p>' if is_dynamic and 'params' in locals() else ''}
740
+ </div>
741
+ )
742
+ }}
743
+ '''
744
+
745
+ def _generate_component_code(
746
+ self,
747
+ name: str,
748
+ props: Dict[str, str],
749
+ client: bool,
750
+ typescript: bool
751
+ ) -> str:
752
+ """Generate component code"""
753
+ use_client = '"use client"\n\n' if client else ''
754
+
755
+ if typescript and props:
756
+ interface = f"interface {name}Props {{\n"
757
+ for prop_name, prop_type in props.items():
758
+ interface += f" {prop_name}: {prop_type}\n"
759
+ interface += "}\n\n"
760
+ else:
761
+ interface = ""
762
+
763
+ props_destructure = ", ".join(props.keys()) if props else ""
764
+ props_type = f": {name}Props" if typescript and props else ""
765
+
766
+ return f'''{use_client}{interface}export default function {name}({{ {props_destructure} }}{props_type}) {{
767
+ return (
768
+ <div>
769
+ <h2>{name} Component</h2>
770
+ </div>
771
+ )
772
+ }}
773
+ '''
774
+
775
+ def _generate_api_route_code(self, path: str, methods: List[str], typescript: bool) -> str:
776
+ """Generate API route code"""
777
+ code = ""
778
+
779
+ if typescript:
780
+ code += "import { NextRequest, NextResponse } from 'next/server'\n\n"
781
+
782
+ for method in methods:
783
+ method_upper = method.upper()
784
+ if method_upper == "GET":
785
+ code += f'''export async function GET() {{
786
+ return Response.json({{ message: 'GET /{path}' }})
787
+ }}
788
+
789
+ '''
790
+ elif method_upper == "POST":
791
+ code += f'''export async function POST(request{': NextRequest' if typescript else ''}) {{
792
+ const data = await request.json()
793
+ return Response.json({{ message: 'POST /{path}', data }})
794
+ }}
795
+
796
+ '''
797
+ elif method_upper == "PUT":
798
+ code += f'''export async function PUT(request{': NextRequest' if typescript else ''}) {{
799
+ const data = await request.json()
800
+ return Response.json({{ message: 'PUT /{path}', data }})
801
+ }}
802
+
803
+ '''
804
+ elif method_upper == "DELETE":
805
+ code += f'''export async function DELETE() {{
806
+ return Response.json({{ message: 'DELETE /{path}' }})
807
+ }}
808
+
809
+ '''
810
+
811
+ return code.strip() + '\n'
812
+
813
+ def _generate_layout_code(self, name: str, typescript: bool) -> str:
814
+ """Generate layout code"""
815
+ props_type = ": { children: React.ReactNode }" if typescript else ""
816
+
817
+ return f'''export default function {name}({{
818
+ children,
819
+ }}{props_type}) {{
820
+ return (
821
+ <div>
822
+ <header className="p-4 border-b">
823
+ <nav>Navigation</nav>
824
+ </header>
825
+ <main>{{children}}</main>
826
+ <footer className="p-4 border-t">
827
+ Footer
828
+ </footer>
829
+ </div>
830
+ )
831
+ }}
832
+ '''
833
+
834
+ def can_handle(self, request: str) -> float:
835
+ """Check if request is Next.js-related"""
836
+ request_lower = request.lower()
837
+
838
+ high_conf = ["nextjs", "next.js", "next js", "react component", "app router"]
839
+ for kw in high_conf:
840
+ if kw in request_lower:
841
+ return 0.9
842
+
843
+ med_conf = ["react", "component", "page", "layout", "typescript"]
844
+ for kw in med_conf:
845
+ if kw in request_lower:
846
+ return 0.5
847
+
848
+ return super().can_handle(request)
849
+
850
+ def handle_request(self, request: str, **kwargs) -> Optional[ActionResult]:
851
+ """Handle a natural language request"""
852
+ request_lower = request.lower()
853
+
854
+ if "scaffold" in request_lower or "new project" in request_lower:
855
+ words = request.split()
856
+ name = "my_app"
857
+ for i, word in enumerate(words):
858
+ if word.lower() in ["project", "called", "named"]:
859
+ if i + 1 < len(words):
860
+ name = words[i + 1].strip("'\"")
861
+ break
862
+ return self.scaffold_project(name=name)
863
+
864
+ if "analyze" in request_lower:
865
+ return self.analyze_project()
866
+
867
+ return None