devobin 1.0.0__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 (47) hide show
  1. devobin/__init__.py +4 -0
  2. devobin/app.py +42 -0
  3. devobin/cli/__init__.py +1 -0
  4. devobin/cli/chat.py +831 -0
  5. devobin/cli/commands.py +362 -0
  6. devobin/cli/slash_menu.py +74 -0
  7. devobin/cli/terminal.py +155 -0
  8. devobin/cli/ui.py +129 -0
  9. devobin/config/__init__.py +1 -0
  10. devobin/config/settings.py +124 -0
  11. devobin/core/__init__.py +1 -0
  12. devobin/core/analyzer.py +166 -0
  13. devobin/core/executor.py +244 -0
  14. devobin/core/memory.py +78 -0
  15. devobin/core/optimizer.py +106 -0
  16. devobin/core/prompt_builder.py +513 -0
  17. devobin/core/researcher.py +283 -0
  18. devobin/core/rtl.py +93 -0
  19. devobin/core/scanner.py +206 -0
  20. devobin/core/tools.py +283 -0
  21. devobin/core/validator.py +235 -0
  22. devobin/main.py +33 -0
  23. devobin/output/__init__.py +1 -0
  24. devobin/providers/__init__.py +85 -0
  25. devobin/providers/anthropic_provider.py +72 -0
  26. devobin/providers/google_provider.py +90 -0
  27. devobin/providers/ollama_provider.py +81 -0
  28. devobin/providers/openai_provider.py +102 -0
  29. devobin/storage/__init__.py +1 -0
  30. devobin/storage/database.py +207 -0
  31. devobin/ui/__init__.py +1 -0
  32. devobin/ui/ask_modal.py +96 -0
  33. devobin/ui/chat_screen.py +1029 -0
  34. devobin/ui/command_palette.py +131 -0
  35. devobin/ui/connect_modal.py +166 -0
  36. devobin/ui/export_modal.py +159 -0
  37. devobin/ui/history_modal.py +137 -0
  38. devobin/ui/memory_modal.py +88 -0
  39. devobin/ui/model_modal.py +143 -0
  40. devobin/ui/permission_modal.py +92 -0
  41. devobin/ui/project_modal.py +133 -0
  42. devobin/ui/settings_modal.py +89 -0
  43. devobin-1.0.0.dist-info/METADATA +364 -0
  44. devobin-1.0.0.dist-info/RECORD +47 -0
  45. devobin-1.0.0.dist-info/WHEEL +4 -0
  46. devobin-1.0.0.dist-info/entry_points.txt +2 -0
  47. devobin-1.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,513 @@
1
+ """Prompt compiler — generates production-ready engineering instruction files."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+ from devobin.core.analyzer import AnalysisResult
8
+ from devobin.core.researcher import ResearchTopic
9
+
10
+
11
+ @dataclass
12
+ class PromptSection:
13
+ """A section of the compiled prompt."""
14
+
15
+ title: str
16
+ level: int = 2
17
+ content: list[str] = field(default_factory=list)
18
+
19
+
20
+ def _tech_list(names: list[str]) -> str:
21
+ return ", ".join(f"`{n}`" for n in names) if names else "Not specified"
22
+
23
+
24
+ def _generate_filename(analysis: AnalysisResult, project_name: str | None = None) -> str:
25
+ """Generate a clean filename from the analysis or project name."""
26
+ if project_name:
27
+ slug = project_name.lower().strip()
28
+ slug = slug.replace(" ", "_").replace("-", "_")
29
+ slug = "".join(c for c in slug if c.isalnum() or c == "_")
30
+ return f"{slug}_prompt.md"
31
+
32
+ # Auto-generate from detected technologies
33
+ parts = []
34
+ for tech in analysis.detected_techs[:3]:
35
+ name = tech.name.lower().replace(" ", "_").replace(".", "")
36
+ parts.append(name)
37
+
38
+ if analysis.project_type and analysis.project_type != "general":
39
+ parts.append(analysis.project_type.replace(" ", "_"))
40
+
41
+ if parts:
42
+ return "_".join(parts) + "_prompt.md"
43
+
44
+ return "project_prompt.md"
45
+
46
+
47
+ def build_prompt(
48
+ analysis: AnalysisResult,
49
+ research: dict[str, ResearchTopic],
50
+ user_context: str = "",
51
+ memory_context: str = "",
52
+ project_name: str | None = None,
53
+ project_map=None,
54
+ ) -> tuple[str, str]:
55
+ """Build the complete engineering instruction file.
56
+
57
+ Returns:
58
+ (filename, content) tuple
59
+ """
60
+ sections: list[PromptSection] = []
61
+
62
+ # ── Header ────────────────────────────────────────────────────
63
+ sections.append(PromptSection("DevObin Engineering Instructions", level=1, content=[
64
+ "> Auto-generated by DevObin AI — Prompt Enhancement Layer",
65
+ f"> Project type: **{analysis.project_type or 'General Application'}**",
66
+ "",
67
+ ]))
68
+
69
+ # ── Detected Workspace (from real file scan) ──────────────────
70
+ if project_map is not None and getattr(project_map, "total_files", 0):
71
+ sections.append(PromptSection("Detected Workspace", level=2, content=[
72
+ project_map.to_context(max_chars=6000),
73
+ "",
74
+ ]))
75
+
76
+ # ── Role ──────────────────────────────────────────────────────
77
+ role_lines = _determine_role(analysis)
78
+ sections.append(PromptSection("Role", level=2, content=role_lines + [""]))
79
+
80
+ # ── Project Goal ──────────────────────────────────────────────
81
+ goal_lines = _determine_goal(analysis)
82
+ sections.append(PromptSection("Project Goal", level=2, content=goal_lines + [""]))
83
+
84
+ # ── Technology Stack ──────────────────────────────────────────
85
+ stack_lines = []
86
+ categories = {}
87
+ for tech in analysis.detected_techs:
88
+ categories.setdefault(tech.category, []).append(tech.name)
89
+
90
+ cat_labels = {
91
+ "framework": "Backend Framework",
92
+ "frontend": "Frontend",
93
+ "database": "Database",
94
+ "language": "Language",
95
+ "tool": "Tool",
96
+ "cloud": "Cloud",
97
+ "pattern": "Pattern",
98
+ "domain": "Domain",
99
+ }
100
+
101
+ for cat, names in categories.items():
102
+ stack_lines.append(f"- **{cat_labels.get(cat, cat.title())}**: {_tech_list(names)}")
103
+
104
+ if not stack_lines:
105
+ stack_lines = ["- Not explicitly specified — use your best judgment based on the project description."]
106
+
107
+ sections.append(PromptSection("Technology Stack", level=2, content=stack_lines + [""]))
108
+
109
+ # ── Technical Constraints ─────────────────────────────────────
110
+ constraints = _determine_constraints(analysis)
111
+ sections.append(PromptSection("Technical Constraints", level=2, content=constraints + [""]))
112
+
113
+ # ── Required Sections / Features ──────────────────────────────
114
+ features = _determine_features(analysis)
115
+ sections.append(PromptSection("Required Sections", level=2, content=features + [""]))
116
+
117
+ # ── Implementation Details ────────────────────────────────────
118
+ impl_details = _determine_implementation(analysis, research)
119
+ sections.append(PromptSection("Implementation Details", level=2, content=impl_details + [""]))
120
+
121
+ # ── Architecture Rules ────────────────────────────────────────
122
+ arch_rules = [
123
+ "Follow SOLID principles throughout the codebase",
124
+ "Apply Clean Architecture: separate concerns into layers",
125
+ "Use dependency injection for loose coupling",
126
+ "Keep functions focused — single responsibility",
127
+ "Design for testability from the start",
128
+ "Use meaningful naming conventions",
129
+ "Write self-documenting code; avoid unnecessary comments",
130
+ ]
131
+
132
+ for name, topic in research.items():
133
+ if topic.architecture_rules:
134
+ arch_rules.append(f"\n**{name} Architecture:**")
135
+ arch_rules.extend([f"- {r}" for r in topic.architecture_rules])
136
+
137
+ sections.append(PromptSection("Architecture Rules", level=2, content=arch_rules + [""]))
138
+
139
+ # ── Responsive Design (only if project has a UI) ───────────────
140
+ has_ui = any(t.category in ("frontend",) for t in analysis.detected_techs)
141
+ if has_ui:
142
+ responsive = _determine_responsive(analysis)
143
+ sections.append(PromptSection("Responsive Design", level=2, content=responsive + [""]))
144
+
145
+ # ── UI/UX Quality (only if project has a UI) ──────────────────
146
+ if has_ui:
147
+ ui_rules = _determine_ui_quality(analysis)
148
+ sections.append(PromptSection("UI/UX Quality", level=2, content=ui_rules + [""]))
149
+
150
+ # ── Framework Best Practices ──────────────────────────────────
151
+ framework_rules: list[str] = []
152
+ for name, topic in research.items():
153
+ if topic.best_practices:
154
+ framework_rules.append(f"### {name}")
155
+ framework_rules.extend([f"- {bp}" for bp in topic.best_practices])
156
+ framework_rules.append("")
157
+
158
+ if framework_rules:
159
+ sections.append(PromptSection("Framework Best Practices", level=2, content=framework_rules + [""]))
160
+
161
+ # ── Security Rules ────────────────────────────────────────────
162
+ security_rules = [
163
+ "Validate and sanitize ALL user inputs at system boundaries",
164
+ "Use parameterized queries — never concatenate user input into queries",
165
+ "Implement proper authentication and authorization checks on every endpoint",
166
+ "Use HTTPS everywhere in production",
167
+ "Store secrets in environment variables, never in code or version control",
168
+ "Implement rate limiting on public endpoints",
169
+ "Use Content Security Policy (CSP) headers",
170
+ "Log security events for audit trails",
171
+ ]
172
+
173
+ for name, topic in research.items():
174
+ if topic.security_rules:
175
+ security_rules.append(f"\n**{name} Security:**")
176
+ security_rules.extend([f"- {r}" for r in topic.security_rules])
177
+
178
+ sections.append(PromptSection("Security Rules", level=2, content=security_rules + [""]))
179
+
180
+ # ── Performance Rules ─────────────────────────────────────────
181
+ perf_rules = [
182
+ "Profile before optimizing — measure, don't guess",
183
+ "Implement caching at appropriate layers",
184
+ "Use async/concurrent processing for I/O-bound operations",
185
+ "Paginate all list endpoints",
186
+ "Optimize database queries — avoid N+1",
187
+ "Implement proper logging and monitoring",
188
+ "Design for horizontal scalability",
189
+ ]
190
+
191
+ for name, topic in research.items():
192
+ if topic.performance_tips:
193
+ perf_rules.append(f"\n**{name} Performance:**")
194
+ perf_rules.extend([f"- {t}" for t in topic.performance_tips])
195
+
196
+ sections.append(PromptSection("Performance Rules", level=2, content=perf_rules + [""]))
197
+
198
+ # ── Common Mistakes ───────────────────────────────────────────
199
+ mistakes: list[str] = []
200
+ for name, topic in research.items():
201
+ if topic.common_mistakes:
202
+ mistakes.append(f"**{name}:**")
203
+ mistakes.extend([f"- Avoid: {m}" for m in topic.common_mistakes])
204
+ mistakes.append("")
205
+
206
+ if mistakes:
207
+ sections.append(PromptSection("Common Mistakes to Avoid", level=2, content=mistakes + [""]))
208
+
209
+ # ── Development Workflow ──────────────────────────────────────
210
+ workflow = [
211
+ "1. **Analyze requirements** — break down into concrete deliverables",
212
+ "2. **Design architecture** — propose system design before coding",
213
+ "3. **Explain decisions** — justify architectural choices with trade-offs",
214
+ "4. **Create implementation plan** — break work into small, testable units",
215
+ "5. **Implement step by step** — build incrementally with tests",
216
+ "6. **Test thoroughly** — write unit, integration, and edge-case tests",
217
+ "7. **Optimize** — profile and optimize critical paths only when needed",
218
+ "8. **Document** — add API docs and deployment instructions",
219
+ ]
220
+ sections.append(PromptSection("Development Workflow", level=2, content=workflow + [""]))
221
+
222
+ # ── User Context / Memory ─────────────────────────────────────
223
+ if memory_context:
224
+ sections.append(PromptSection("User Preferences (from DevObin Memory)", level=2, content=[
225
+ memory_context,
226
+ "",
227
+ ]))
228
+
229
+ if user_context:
230
+ sections.append(PromptSection("Additional Context", level=2, content=[
231
+ user_context,
232
+ "",
233
+ ]))
234
+
235
+ # ── Assemble ──────────────────────────────────────────────────
236
+ lines: list[str] = []
237
+ for section in sections:
238
+ if section.level == 1:
239
+ lines.append(f"# {section.title}")
240
+ else:
241
+ lines.append(f"{'#' * section.level} {section.title}")
242
+ lines.extend(section.content)
243
+
244
+ filename = _generate_filename(analysis, project_name)
245
+ return filename, "\n".join(lines)
246
+
247
+
248
+ # ── Section generators ────────────────────────────────────────────
249
+
250
+
251
+ def _determine_role(analysis: AnalysisResult) -> list[str]:
252
+ """Determine the appropriate role based on detected tech."""
253
+ categories = {t.category for t in analysis.detected_techs}
254
+
255
+ if "frontend" in categories and "framework" not in categories:
256
+ return [
257
+ "You are a senior frontend engineer specialized in modern web interfaces.",
258
+ "Your implementation must be pixel-perfect, responsive, and follow accessibility standards.",
259
+ ]
260
+ if "frontend" in categories and "framework" in categories:
261
+ return [
262
+ "You are a senior full-stack engineer specialized in modern web applications.",
263
+ "Your implementation must be production-ready, well-tested, and follow industry best practices.",
264
+ ]
265
+ if "framework" in categories:
266
+ return [
267
+ "You are a senior backend architect specialized in API design and server-side engineering.",
268
+ "Your implementation must be scalable, secure, and follow clean architecture principles.",
269
+ ]
270
+ if analysis.project_type in ("saas",):
271
+ return [
272
+ "You are a senior SaaS architect specialized in multi-tenant applications.",
273
+ "Your implementation must handle scaling, security, and tenant isolation.",
274
+ ]
275
+
276
+ return [
277
+ "You are a senior software architect and production engineer.",
278
+ "Your implementation must be production-ready, well-tested, and follow industry best practices.",
279
+ ]
280
+
281
+
282
+ def _determine_goal(analysis: AnalysisResult) -> list[str]:
283
+ """Determine the project goal from analysis."""
284
+ lines = [f"Build: {analysis.description}", ""]
285
+
286
+ if analysis.project_type and analysis.project_type != "general":
287
+ lines.append(f"Project type: **{analysis.project_type}**")
288
+
289
+ if analysis.detected_techs:
290
+ tech_names = [t.name for t in analysis.detected_techs]
291
+ lines.append(f"Technologies: {', '.join(tech_names)}")
292
+
293
+ return lines
294
+
295
+
296
+ def _determine_constraints(analysis: AnalysisResult) -> list[str]:
297
+ """Determine technical constraints from analysis."""
298
+ constraints = []
299
+ has_ui = any(t.category in ("frontend",) for t in analysis.detected_techs)
300
+
301
+ # Check for single-file mentions
302
+ desc_lower = analysis.description.lower()
303
+ if any(phrase in desc_lower for phrase in ["one file", "single file", "یک فایل", "یه فایل", "mega file", "همه چی"]):
304
+ constraints.append("- The entire project must exist in ONE file")
305
+ constraints.append("- Include HTML, CSS, and JavaScript in the same file")
306
+ constraints.append("- No external frameworks or dependencies")
307
+
308
+ if "no framework" in desc_lower or "vanilla" in desc_lower:
309
+ constraints.append("- Use vanilla JavaScript only — no frameworks")
310
+ constraints.append("- No external dependencies")
311
+
312
+ if analysis.project_type == "ecommerce":
313
+ constraints.append("- Must handle product data (can use mock/placeholder data)")
314
+ constraints.append("- Cart state must persist (use localStorage)")
315
+
316
+ if not constraints:
317
+ constraints.append("- Follow standard project structure for the detected technologies")
318
+ if has_ui:
319
+ constraints.append("- Use modern ES6+ features where supported")
320
+ else:
321
+ constraints.append("- Use idiomatic patterns for the detected language")
322
+ constraints.append("- Follow PEP 8 / official style guide for the language")
323
+
324
+ return constraints
325
+
326
+
327
+ def _determine_features(analysis: AnalysisResult) -> list[str]:
328
+ """Determine required features/sections from analysis."""
329
+ features = []
330
+ desc_lower = analysis.description.lower()
331
+
332
+ # Ecommerce features
333
+ if analysis.project_type == "ecommerce" or "shop" in desc_lower or "store" in desc_lower or "فروشگاه" in desc_lower:
334
+ features.extend([
335
+ "**Header** — Logo, navigation, search bar, cart icon with counter",
336
+ "**Mega Menu** — Multi-column dropdown with categories, subcategories, icons/images",
337
+ "**Hero Section** — Banner with CTA button",
338
+ "**Product Grid/Slider** — Product cards with image, title, price, add-to-cart",
339
+ "**Shopping Cart** — Slide-out or modal cart with items, quantities, total",
340
+ "**Categories Section** — Category cards with icons",
341
+ "**Footer** — Links, social media, newsletter signup",
342
+ ])
343
+
344
+ # Blog features
345
+ if "blog" in desc_lower or "وبلاگ" in desc_lower:
346
+ features.extend([
347
+ "**Header** — Logo, navigation, search",
348
+ "**Featured Posts** — Hero cards with images",
349
+ "**Post List** — Card grid with title, excerpt, date, author",
350
+ "**Sidebar** — Categories, tags, popular posts",
351
+ "**Post Detail** — Full article with rich content",
352
+ "**Footer** — Links, social, about",
353
+ ])
354
+
355
+ # Dashboard features
356
+ if "dashboard" in desc_lower or "پنل" in desc_lower:
357
+ features.extend([
358
+ "**Sidebar Navigation** — Collapsible menu with icons",
359
+ "**Top Bar** — Search, notifications, user profile",
360
+ "**Stats Cards** — KPIs with charts",
361
+ "**Data Table** — Sortable, filterable, paginated",
362
+ "**Charts** — Line, bar, pie charts for analytics",
363
+ ])
364
+
365
+ # Landing page
366
+ if "landing" in desc_lower or "لندینگ" in desc_lower:
367
+ features.extend([
368
+ "**Hero Section** — Headline, subheadline, CTA",
369
+ "**Features Section** — 3-4 feature cards with icons",
370
+ "**Social Proof** — Testimonials or logos",
371
+ "**Pricing** — Pricing tiers with CTA buttons",
372
+ "**FAQ** — Accordion-style FAQ section",
373
+ "**Footer** — Links, newsletter signup",
374
+ ])
375
+
376
+ if not features:
377
+ # Only add frontend features if the project actually has a UI component
378
+ has_ui = any(t.category in ("frontend",) for t in analysis.detected_techs)
379
+ if has_ui:
380
+ features.append("- Define required UI sections based on project type")
381
+ features.append("- Include header, main content area, and footer at minimum")
382
+ else:
383
+ features.append("- Define required modules/components based on the detected stack")
384
+ features.append("- List all API endpoints, CLI commands, or library interfaces to implement")
385
+ features.append("- Specify data models, schemas, or type definitions needed")
386
+
387
+ return features
388
+
389
+
390
+ def _determine_implementation(analysis: AnalysisResult, research: dict[str, ResearchTopic]) -> list[str]:
391
+ """Determine implementation details."""
392
+ details = []
393
+ desc_lower = analysis.description.lower()
394
+ has_ui = any(t.category in ("frontend",) for t in analysis.detected_techs)
395
+
396
+ if any(phrase in desc_lower for phrase in ["mega menu", "مگا منو", "menu", "منو"]):
397
+ details.extend([
398
+ "**Mega Menu:**",
399
+ "- Multi-column dropdown layout",
400
+ "- Product categories with subcategories",
401
+ "- Icons or thumbnail images per category",
402
+ "- Desktop: hover to open, with transition animation",
403
+ "- Mobile: tap to toggle, full-width overlay",
404
+ "- Smooth open/close animations (CSS transitions)",
405
+ ])
406
+
407
+ if analysis.project_type == "ecommerce" or "shop" in desc_lower or "فروشگاه" in desc_lower:
408
+ details.extend([
409
+ "**Product Slider:**",
410
+ "- Horizontal scrolling product carousel",
411
+ "- Arrow navigation (prev/next)",
412
+ "- Dot indicators",
413
+ "- Auto-play with pause on hover",
414
+ "",
415
+ "**Shopping Cart:**",
416
+ "- Slide-out panel or modal",
417
+ "- Add/remove items",
418
+ "- Quantity +/- controls",
419
+ "- Live total calculation",
420
+ "- localStorage persistence",
421
+ "- Empty cart state",
422
+ "",
423
+ "**Mobile Menu:**",
424
+ "- Hamburger icon toggle",
425
+ "- Full-screen overlay menu",
426
+ "- Nested category accordion",
427
+ "- Close button + swipe gesture",
428
+ ])
429
+
430
+ if not details:
431
+ if has_ui:
432
+ details.append("- Implement all interactive features with clean JavaScript")
433
+ details.append("- Use event delegation for dynamic elements")
434
+ details.append("- Handle loading, empty, and error states")
435
+ else:
436
+ details.append("- Implement core business logic with clean, well-structured code")
437
+ details.append("- Use type hints and docstrings for all public interfaces")
438
+ details.append("- Handle error states and edge cases gracefully")
439
+ details.append("- Write unit tests for core functionality")
440
+
441
+ return details
442
+
443
+
444
+ def _determine_responsive(analysis: AnalysisResult) -> list[str]:
445
+ """Determine responsive design requirements."""
446
+ return [
447
+ "**Breakpoints:**",
448
+ "- Desktop: > 1024px",
449
+ "- Tablet: 768px - 1024px",
450
+ "- Mobile: < 768px",
451
+ "",
452
+ "**Desktop:**",
453
+ "- Full mega menu with hover interaction",
454
+ "- Multi-column product grid (3-4 columns)",
455
+ "- Sticky header",
456
+ "",
457
+ "**Tablet:**",
458
+ "- Condensed navigation",
459
+ "- 2-column product grid",
460
+ "- Adjusted typography scale",
461
+ "",
462
+ "**Mobile:**",
463
+ "- Hamburger menu with full-screen overlay",
464
+ "- Single-column layout",
465
+ "- Touch-friendly tap targets (min 44px)",
466
+ "- Swipe gestures for carousels",
467
+ "- Bottom navigation bar (optional)",
468
+ ]
469
+
470
+
471
+ def _determine_ui_quality(analysis: AnalysisResult) -> list[str]:
472
+ """Determine UI/UX quality requirements."""
473
+ desc_lower = analysis.description.lower()
474
+
475
+ rules = [
476
+ "**Design Style:**",
477
+ "- Modern, clean, professional ecommerce design",
478
+ "- Consistent spacing system (8px grid)",
479
+ "- Clear visual hierarchy",
480
+ "",
481
+ "**Typography:**",
482
+ "- Use system font stack or Google Fonts",
483
+ "- Maximum 2-3 font weights",
484
+ "- Readable line height (1.5-1.6)",
485
+ "- Responsive font sizes (clamp or media queries)",
486
+ "",
487
+ "**Colors:**",
488
+ "- Define primary, secondary, and accent colors",
489
+ "- Ensure WCAG AA contrast ratios",
490
+ "- Use CSS custom properties for theming",
491
+ "",
492
+ "**Spacing:**",
493
+ "- Consistent padding/margin scale",
494
+ "- Visual breathing room between sections",
495
+ "",
496
+ "**Animations:**",
497
+ "- Smooth transitions (200-300ms ease)",
498
+ "- Hover effects on interactive elements",
499
+ "- Loading skeleton states",
500
+ "- Subtle micro-interactions",
501
+ ]
502
+
503
+ if "rtl" in desc_lower or "فارسی" in desc_lower or "persian" in desc_lower:
504
+ rules.extend([
505
+ "",
506
+ "**RTL Support:**",
507
+ "- Use dir='rtl' on html element",
508
+ "- Logical properties (margin-inline, padding-inline)",
509
+ "- Mirrored layout for RTL languages",
510
+ "- Proper text alignment",
511
+ ])
512
+
513
+ return rules