create-stylus-ide 1.0.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 (135) hide show
  1. package/Readme.MD +1515 -0
  2. package/cli.js +28 -0
  3. package/frontend/.vscode/settings.json +9 -0
  4. package/frontend/app/api/chat/route.ts +101 -0
  5. package/frontend/app/api/check-setup/route.ts +93 -0
  6. package/frontend/app/api/cleanup/route.ts +14 -0
  7. package/frontend/app/api/compile/route.ts +95 -0
  8. package/frontend/app/api/compile-stream/route.ts +98 -0
  9. package/frontend/app/api/complete/route.ts +86 -0
  10. package/frontend/app/api/deploy/route.ts +118 -0
  11. package/frontend/app/api/export-abi/route.ts +58 -0
  12. package/frontend/app/favicon.ico +0 -0
  13. package/frontend/app/globals.css +177 -0
  14. package/frontend/app/layout.tsx +29 -0
  15. package/frontend/app/ml/page.tsx +694 -0
  16. package/frontend/app/page.tsx +1132 -0
  17. package/frontend/app/providers.tsx +18 -0
  18. package/frontend/app/qlearning/page.tsx +188 -0
  19. package/frontend/app/raytracing/page.tsx +268 -0
  20. package/frontend/components/abi/ABIDialog.tsx +132 -0
  21. package/frontend/components/ai/AICompletionPopup.tsx +76 -0
  22. package/frontend/components/ai/ChatPanel.tsx +292 -0
  23. package/frontend/components/ai/QuickActions.tsx +128 -0
  24. package/frontend/components/blockchain/BlockchainContractBanner.tsx +64 -0
  25. package/frontend/components/blockchain/BlockchainLoadingDialog.tsx +188 -0
  26. package/frontend/components/deploy/DeployDialog.tsx +334 -0
  27. package/frontend/components/editor/FileTabs.tsx +181 -0
  28. package/frontend/components/editor/MonacoEditor.tsx +306 -0
  29. package/frontend/components/file-tree/ContextMenu.tsx +110 -0
  30. package/frontend/components/file-tree/DeleteConfirmDialog.tsx +61 -0
  31. package/frontend/components/file-tree/FileInputDialog.tsx +97 -0
  32. package/frontend/components/file-tree/FileNode.tsx +60 -0
  33. package/frontend/components/file-tree/FileTree.tsx +259 -0
  34. package/frontend/components/file-tree/FileTreeSkeleton.tsx +26 -0
  35. package/frontend/components/file-tree/FolderNode.tsx +105 -0
  36. package/frontend/components/github/GitHubLoadingDialog.tsx +201 -0
  37. package/frontend/components/github/GitHubMetadataBanner.tsx +61 -0
  38. package/frontend/components/github/LoadFromGitHubDialog.tsx +125 -0
  39. package/frontend/components/github/URLCopyButton.tsx +60 -0
  40. package/frontend/components/interact/ContractInteraction.tsx +323 -0
  41. package/frontend/components/interact/ContractPlaceholder.tsx +41 -0
  42. package/frontend/components/orbit/BenchmarkDialog.tsx +342 -0
  43. package/frontend/components/orbit/OrbitExplorer.tsx +273 -0
  44. package/frontend/components/project/ProjectActions.tsx +176 -0
  45. package/frontend/components/q-learning/ContractConfig.tsx +172 -0
  46. package/frontend/components/q-learning/MazeGrid.tsx +346 -0
  47. package/frontend/components/q-learning/PathAnimation.tsx +384 -0
  48. package/frontend/components/q-learning/QTableHeatmap.tsx +300 -0
  49. package/frontend/components/q-learning/TrainingForm.tsx +349 -0
  50. package/frontend/components/ray-tracing/ContractConfig.tsx +245 -0
  51. package/frontend/components/ray-tracing/MintingForm.tsx +280 -0
  52. package/frontend/components/ray-tracing/RenderCanvas.tsx +228 -0
  53. package/frontend/components/ray-tracing/RenderingPanel.tsx +259 -0
  54. package/frontend/components/ray-tracing/StyleControls.tsx +217 -0
  55. package/frontend/components/setup/SetupGuide.tsx +290 -0
  56. package/frontend/components/ui/KeyboardShortcutHint.tsx +74 -0
  57. package/frontend/components/ui/alert-dialog.tsx +157 -0
  58. package/frontend/components/ui/alert.tsx +66 -0
  59. package/frontend/components/ui/badge.tsx +46 -0
  60. package/frontend/components/ui/button.tsx +62 -0
  61. package/frontend/components/ui/card.tsx +92 -0
  62. package/frontend/components/ui/context-menu.tsx +252 -0
  63. package/frontend/components/ui/dialog.tsx +143 -0
  64. package/frontend/components/ui/dropdown-menu.tsx +257 -0
  65. package/frontend/components/ui/input.tsx +21 -0
  66. package/frontend/components/ui/label.tsx +24 -0
  67. package/frontend/components/ui/progress.tsx +31 -0
  68. package/frontend/components/ui/scroll-area.tsx +58 -0
  69. package/frontend/components/ui/select.tsx +190 -0
  70. package/frontend/components/ui/separator.tsx +28 -0
  71. package/frontend/components/ui/sheet.tsx +139 -0
  72. package/frontend/components/ui/skeleton.tsx +13 -0
  73. package/frontend/components/ui/slider.tsx +63 -0
  74. package/frontend/components/ui/sonner.tsx +40 -0
  75. package/frontend/components/ui/tabs.tsx +66 -0
  76. package/frontend/components/ui/textarea.tsx +18 -0
  77. package/frontend/components/wallet/ConnectButton.tsx +167 -0
  78. package/frontend/components/wallet/FaucetButton.tsx +256 -0
  79. package/frontend/components.json +22 -0
  80. package/frontend/eslint.config.mjs +18 -0
  81. package/frontend/hooks/useAICompletion.ts +75 -0
  82. package/frontend/hooks/useBlockchainLoader.ts +58 -0
  83. package/frontend/hooks/useChats.ts +137 -0
  84. package/frontend/hooks/useCompilation.ts +173 -0
  85. package/frontend/hooks/useFileTabs.ts +178 -0
  86. package/frontend/hooks/useGitHubLoader.ts +50 -0
  87. package/frontend/hooks/useKeyboardShortcuts.ts +47 -0
  88. package/frontend/hooks/usePanelState.ts +115 -0
  89. package/frontend/hooks/useProjectState.ts +276 -0
  90. package/frontend/hooks/useResponsive.ts +29 -0
  91. package/frontend/lib/abi-parser.ts +58 -0
  92. package/frontend/lib/blockchain-api.ts +374 -0
  93. package/frontend/lib/blockchain-explorers.ts +75 -0
  94. package/frontend/lib/blockchain-loader.ts +112 -0
  95. package/frontend/lib/cargo-template.ts +64 -0
  96. package/frontend/lib/compilation.ts +529 -0
  97. package/frontend/lib/constants.ts +31 -0
  98. package/frontend/lib/deployment.ts +176 -0
  99. package/frontend/lib/file-utils.ts +83 -0
  100. package/frontend/lib/github-api.ts +246 -0
  101. package/frontend/lib/github-loader.ts +369 -0
  102. package/frontend/lib/ml-contract-template.txt +900 -0
  103. package/frontend/lib/orbit-chains.ts +181 -0
  104. package/frontend/lib/output-formatter.ts +68 -0
  105. package/frontend/lib/project-manager.ts +632 -0
  106. package/frontend/lib/ray-tracing-abi.ts +206 -0
  107. package/frontend/lib/storage.ts +189 -0
  108. package/frontend/lib/templates.ts +1662 -0
  109. package/frontend/lib/url-parser.ts +188 -0
  110. package/frontend/lib/utils.ts +6 -0
  111. package/frontend/lib/wagmi-config.ts +24 -0
  112. package/frontend/next.config.ts +7 -0
  113. package/frontend/package-lock.json +16259 -0
  114. package/frontend/package.json +60 -0
  115. package/frontend/postcss.config.mjs +7 -0
  116. package/frontend/public/file.svg +1 -0
  117. package/frontend/public/globe.svg +1 -0
  118. package/frontend/public/ml-weights/.gitkeep +0 -0
  119. package/frontend/public/ml-weights/model.pkl +0 -0
  120. package/frontend/public/ml-weights/model_weights.json +27102 -0
  121. package/frontend/public/ml-weights/test_samples.json +7888 -0
  122. package/frontend/public/next.svg +1 -0
  123. package/frontend/public/vercel.svg +1 -0
  124. package/frontend/public/window.svg +1 -0
  125. package/frontend/scripts/check-env.js +52 -0
  126. package/frontend/scripts/setup.js +285 -0
  127. package/frontend/tailwind.config.ts +64 -0
  128. package/frontend/tsconfig.json +34 -0
  129. package/frontend/types/blockchain.ts +63 -0
  130. package/frontend/types/github.ts +54 -0
  131. package/frontend/types/project.ts +106 -0
  132. package/ml-training/README.md +56 -0
  133. package/ml-training/train_tiny_model.py +325 -0
  134. package/ml-training/update_template.py +59 -0
  135. package/package.json +30 -0
@@ -0,0 +1,369 @@
1
+ /**
2
+ * GitHub repository loader - converts GitHub repos to ProjectState
3
+ */
4
+
5
+ import { ProjectState, ProjectFile } from "@/types/project";
6
+ import { GitHubURLInfo } from "@/lib/url-parser";
7
+ import { githubAPI } from "@/lib/github-api";
8
+ import { createProject } from "@/lib/project-manager";
9
+ import { GitHubFile } from "@/types/github";
10
+
11
+ export interface GitHubLoadProgress {
12
+ stage:
13
+ | "validating"
14
+ | "fetching-tree"
15
+ | "downloading-files"
16
+ | "complete"
17
+ | "error";
18
+ message: string;
19
+ progress: number; // 0-100
20
+ filesTotal?: number;
21
+ filesDownloaded?: number;
22
+ currentFile?: string;
23
+ }
24
+
25
+ /**
26
+ * Filter files to only include those in a specific folder
27
+ */
28
+ function filterFilesByPath(
29
+ files: GitHubFile[], // ✅ CHANGE: was { path: string }[]
30
+ folderPath: string
31
+ ): GitHubFile[] {
32
+ // ✅ CHANGE: was { path: string }[]
33
+ // Normalize folder path (remove trailing slash)
34
+ const normalizedPath = folderPath.endsWith("/")
35
+ ? folderPath.slice(0, -1)
36
+ : folderPath;
37
+
38
+ return files.filter((file) => {
39
+ // File must start with the folder path
40
+ if (!file.path.startsWith(normalizedPath + "/")) {
41
+ return false;
42
+ }
43
+ return true;
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Strip folder prefix from file paths
49
+ * Example: "src/lib.rs" with prefix "src" becomes "lib.rs"
50
+ */
51
+ function stripPathPrefix(path: string, prefix: string): string {
52
+ const normalizedPrefix = prefix.endsWith("/") ? prefix : prefix + "/";
53
+
54
+ if (path.startsWith(normalizedPrefix)) {
55
+ return path.substring(normalizedPrefix.length);
56
+ }
57
+
58
+ return path;
59
+ }
60
+
61
+ /**
62
+ * Validate if repository has Rust/Stylus files
63
+ */
64
+ function validateStylusRepo(files: { path: string }[]): {
65
+ isValid: boolean;
66
+ hasRust: boolean;
67
+ hasCargo: boolean;
68
+ warnings: string[];
69
+ } {
70
+ const hasRust = files.some((f) => f.path.endsWith(".rs"));
71
+ const hasCargo = files.some(
72
+ (f) => f.path === "Cargo.toml" || f.path.endsWith("/Cargo.toml")
73
+ );
74
+ const warnings: string[] = [];
75
+
76
+ if (!hasRust) {
77
+ warnings.push("No Rust files (.rs) found in repository");
78
+ }
79
+
80
+ if (!hasCargo) {
81
+ warnings.push("No Cargo.toml found - this may not be a valid Rust project");
82
+ }
83
+
84
+ // Check for common non-Rust repos
85
+ const hasPackageJson = files.some((f) => f.path === "package.json");
86
+ const hasPyFiles = files.some((f) => f.path.endsWith(".py"));
87
+ const hasGoFiles = files.some((f) => f.path.endsWith(".go"));
88
+
89
+ if (hasPackageJson && !hasRust) {
90
+ warnings.push(
91
+ "This appears to be a JavaScript/TypeScript project, not Rust"
92
+ );
93
+ }
94
+ if (hasPyFiles && !hasRust) {
95
+ warnings.push("This appears to be a Python project, not Rust");
96
+ }
97
+ if (hasGoFiles && !hasRust) {
98
+ warnings.push("This appears to be a Go project, not Rust");
99
+ }
100
+
101
+ return {
102
+ isValid: hasRust,
103
+ hasRust,
104
+ hasCargo,
105
+ warnings,
106
+ };
107
+ }
108
+
109
+ export type ProgressCallback = (progress: GitHubLoadProgress) => void;
110
+
111
+ /**
112
+ * Load GitHub repository and convert to ProjectState
113
+ */
114
+ export async function loadGitHubRepo(
115
+ urlInfo: GitHubURLInfo,
116
+ onProgress?: ProgressCallback
117
+ ): Promise<ProjectState> {
118
+ const { owner, repo, branch, file } = urlInfo;
119
+
120
+ try {
121
+ // Stage 1: Validate repository
122
+ onProgress?.({
123
+ stage: "validating",
124
+ message: `Checking repository ${owner}/${repo}...`,
125
+ progress: 10,
126
+ });
127
+
128
+ const repoInfo = await githubAPI.getRepo(owner, repo);
129
+ const targetBranch = branch || repoInfo.default_branch;
130
+
131
+ // Check if specific branch exists
132
+ if (branch && branch !== repoInfo.default_branch) {
133
+ const branchExists = await githubAPI.branchExists(owner, repo, branch);
134
+ if (!branchExists) {
135
+ throw new Error(
136
+ `Branch "${branch}" not found. Available branch: ${repoInfo.default_branch}`
137
+ );
138
+ }
139
+ }
140
+
141
+ // Stage 2: Fetch repository tree
142
+ onProgress?.({
143
+ stage: "fetching-tree",
144
+ message: "Fetching repository structure...",
145
+ progress: 30,
146
+ });
147
+
148
+ const tree = await githubAPI.getRepoTree(owner, repo, targetBranch);
149
+
150
+ // Check if repo is empty
151
+ if (tree.tree.length === 0) {
152
+ throw new Error("Repository is empty. No files found.");
153
+ }
154
+
155
+ // Validate it's a Rust/Stylus project
156
+ const validation = validateStylusRepo(tree.tree);
157
+
158
+ if (!validation.isValid) {
159
+ throw new Error(
160
+ `Not a valid Stylus project:\n${validation.warnings.join("\n")}`
161
+ );
162
+ }
163
+
164
+ // Show warnings but continue
165
+ if (validation.warnings.length > 0) {
166
+ console.warn("Repository warnings:", validation.warnings);
167
+ }
168
+
169
+ // Filter for relevant files only (Rust, TOML, MD, etc.)
170
+ let relevantFiles = tree.tree.filter((item) => {
171
+ if (item.type !== "blob") return false;
172
+
173
+ const ext = item.path.split(".").pop()?.toLowerCase();
174
+ return ["rs", "toml", "md", "txt", "lock", "gitignore"].includes(
175
+ ext || ""
176
+ );
177
+ });
178
+
179
+ // ✅ NEW: Filter by folder path if specified
180
+ if (urlInfo.path) {
181
+ const beforeFilter = relevantFiles.length;
182
+ relevantFiles = filterFilesByPath(relevantFiles, urlInfo.path);
183
+
184
+ console.log(
185
+ `Filtered to folder "${urlInfo.path}": ${beforeFilter} → ${relevantFiles.length} files`
186
+ );
187
+
188
+ if (relevantFiles.length === 0) {
189
+ throw new Error(`No files found in folder "${urlInfo.path}"`);
190
+ }
191
+ }
192
+
193
+ if (relevantFiles.length === 0) {
194
+ throw new Error("No Rust or configuration files found in repository");
195
+ }
196
+
197
+ // Stage 3: Download files
198
+ onProgress?.({
199
+ stage: "downloading-files",
200
+ message: `Downloading ${relevantFiles.length} files...`,
201
+ progress: 50,
202
+ filesTotal: relevantFiles.length,
203
+ filesDownloaded: 0,
204
+ });
205
+
206
+ const files: ProjectFile[] = [];
207
+ const failedFiles: string[] = [];
208
+ let downloadedCount = 0;
209
+
210
+ for (const item of relevantFiles) {
211
+ try {
212
+ onProgress?.({
213
+ stage: "downloading-files",
214
+ message: `Downloading ${item.path}...`,
215
+ progress: 50 + (downloadedCount / relevantFiles.length) * 40,
216
+ filesTotal: relevantFiles.length,
217
+ filesDownloaded: downloadedCount,
218
+ currentFile: item.path,
219
+ });
220
+
221
+ // Use raw content API (faster and no base64 decoding needed)
222
+ const content = await githubAPI.getRawFileContent(
223
+ owner,
224
+ repo,
225
+ item.path,
226
+ targetBranch
227
+ );
228
+
229
+ // Determine language from extension
230
+ const ext = item.path.split(".").pop()?.toLowerCase() || "text";
231
+ const languageMap: Record<string, ProjectFile["language"]> = {
232
+ rs: "rust",
233
+ toml: "toml",
234
+ md: "markdown",
235
+ txt: "text",
236
+ lock: "text",
237
+ gitignore: "gitignore",
238
+ };
239
+
240
+ // ✅ NEW: Strip folder prefix if loading specific folder
241
+ const displayPath = urlInfo.path
242
+ ? stripPathPrefix(item.path, urlInfo.path)
243
+ : item.path;
244
+
245
+ files.push({
246
+ id: `github-${item.sha}`,
247
+ name: displayPath.split("/").pop() || displayPath,
248
+ path: displayPath, // Use stripped path
249
+ content,
250
+ language: languageMap[ext] || "text",
251
+ modified: false,
252
+ isOpen: false,
253
+ createdAt: new Date(),
254
+ updatedAt: new Date(),
255
+ });
256
+
257
+ downloadedCount++;
258
+ } catch (error) {
259
+ console.warn(`Failed to download ${item.path}:`, error);
260
+ failedFiles.push(item.path);
261
+ // Continue with other files
262
+ }
263
+ }
264
+
265
+ if (files.length === 0) {
266
+ throw new Error("Failed to download any files from repository");
267
+ }
268
+
269
+ // Warn about failed files
270
+ if (failedFiles.length > 0) {
271
+ console.warn(
272
+ `Failed to download ${failedFiles.length} files:`,
273
+ failedFiles
274
+ );
275
+ }
276
+
277
+ // Stage 4: Create project
278
+ onProgress?.({
279
+ stage: "complete",
280
+ message: "Building project...",
281
+ progress: 95,
282
+ });
283
+
284
+ // Create project from files
285
+ const project = createProject(`${owner}-${repo}`, "github");
286
+
287
+ // Replace default files with GitHub files
288
+ project.files = files;
289
+
290
+ // If specific file was requested, mark it as active
291
+ if (file) {
292
+ const targetFile = files.find((f) => f.path === file);
293
+ if (targetFile) {
294
+ targetFile.isOpen = true;
295
+ project.activeFilePath = targetFile.path;
296
+ } else {
297
+ console.warn(`Requested file "${file}" not found in repository`);
298
+ }
299
+ }
300
+
301
+ // If no file specified or file not found, open first .rs file by default
302
+ if (!project.activeFilePath) {
303
+ const firstRustFile = files.find((f) => f.language === "rust");
304
+ if (firstRustFile) {
305
+ firstRustFile.isOpen = true;
306
+ project.activeFilePath = firstRustFile.path;
307
+ }
308
+ }
309
+
310
+ // Update project metadata
311
+ project.name = urlInfo.path ? `${repo}/${urlInfo.path}` : repo;
312
+ project.metadata = {
313
+ source: "github",
314
+ owner,
315
+ repo,
316
+ branch: targetBranch,
317
+ url: urlInfo.rawUrl,
318
+ loadedAt: new Date().toISOString(),
319
+ folderPath: urlInfo.path, // ✅ NEW: Track loaded folder
320
+ };
321
+
322
+ onProgress?.({
323
+ stage: "complete",
324
+ message: `Loaded ${files.length} files from ${owner}/${repo}${
325
+ failedFiles.length > 0 ? ` (${failedFiles.length} files skipped)` : ""
326
+ }`,
327
+ progress: 100,
328
+ filesTotal: files.length,
329
+ filesDownloaded: files.length,
330
+ });
331
+
332
+ return project;
333
+ } catch (error) {
334
+ let errorMessage = "Unknown error occurred";
335
+
336
+ if (error instanceof Error) {
337
+ errorMessage = error.message;
338
+ }
339
+
340
+ onProgress?.({
341
+ stage: "error",
342
+ message: errorMessage,
343
+ progress: 0,
344
+ });
345
+
346
+ throw error;
347
+ }
348
+ }
349
+
350
+ /**
351
+ * Validate if repository is suitable for Stylus IDE
352
+ */
353
+ export function validateGitHubRepo(tree: { path: string }[]): {
354
+ isValid: boolean;
355
+ reason?: string;
356
+ } {
357
+ const hasRustFiles = tree.some((item) => item.path.endsWith(".rs"));
358
+ const hasCargoToml = tree.some((item) => item.path === "Cargo.toml");
359
+
360
+ if (!hasRustFiles) {
361
+ return { isValid: false, reason: "No Rust files found" };
362
+ }
363
+
364
+ if (!hasCargoToml) {
365
+ return { isValid: false, reason: "No Cargo.toml found" };
366
+ }
367
+
368
+ return { isValid: true };
369
+ }