Skip to content

Conversation

@jacob8919
Copy link

@jacob8919 jacob8919 commented Jan 11, 2026

Summary

This PR introduces comprehensive Laravel framework support to autocoder, along with several quality-of-life improvements and bug fixes.

Major Features

  • Laravel Framework Integration: Full support for Laravel projects with tech stack selection wizard

    • Framework options: React + Node.js, Laravel + React, Laravel + Vue, Laravel + Livewire, Laravel API-only
    • Database selection: SQLite, MySQL, PostgreSQL, MariaDB
    • Testing frameworks: Vitest/Jest (Node.js) or Pest/PHPUnit (Laravel)
    • Laravel Boost MCP server integration with 15 specialized tools
    • Laravel-specific prompt templates and expanded command allowlist
  • File Upload Enhancements: Extended spec creation chat to accept markdown (.md) and text (.txt) files

    • New TextFileAttachment model with UTF-8 validation
    • Files display as expandable accordions in chat messages

Improvements

  • Increased debug log history capacity from 100 to 1000 lines
  • Added SQLite timeout parameter to prevent database lock errors in MCP features server
  • Expanded security allowlist with PHP/Laravel commands (pint, pgrep, etc.)

Bug Fixes

  • Fixed Laravel Boost MCP server naming convention (hyphen vs. underscore)
  • Corrected Laravel initializer template with proper Boost installation via Composer

Files Changed

23 files modified across frontend components, backend services, and configuration files.

Testing

  • Laravel project creation workflow tested
  • Tech stack selection wizard validated
  • File upload functionality verified with .md and .txt files
  • Database lock error scenario tested

Screenshots

Add any relevant screenshots here


🤖 Co-authored with Claude Opus 4.5

Summary by CodeRabbit

  • New Features

    • Added Laravel framework support with automated project scaffolding and configuration workflows
    • Enabled text file attachments (.md, .txt) alongside images in spec creation
    • Introduced tech stack configuration UI for selecting framework, database, and testing options during project setup
  • Improvements

    • Enhanced database connection stability with timeout handling
    • Expanded security controls for PHP and Laravel development tools

✏️ Tip: You can customize this high-level summary in your review settings.

jacob8919 and others added 9 commits January 10, 2026 14:09
Add Laravel framework support during project creation:
- Add tech stack selection wizard (framework, database, testing)
- Support Laravel + React/Vue/Livewire/API starter kits
- Add Laravel Boost MCP server integration
- Create Laravel-specific prompt templates
- Add PHP/Laravel commands to security allowlist
- Auto-detect framework from app_spec.txt at runtime

Framework options:
- React + Node.js (default)
- Laravel + React (Inertia.js)
- Laravel + Vue (Inertia.js)
- Laravel + Livewire
- Laravel API Only

Database options: SQLite, MySQL, PostgreSQL, MariaDB
Testing options: Vitest/Jest (Node.js), Pest/PHPUnit (Laravel)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove invalid --boost flag from laravel new commands (doesn't exist)
- Make database option dynamic, reading from app_spec.txt <database> tag
- Add separate Laravel Boost installation via Composer
- Use --no-interaction flag for php artisan boost:install to skip prompts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… laravel_boost)

The Laravel Boost MCP server exposes tools with hyphen naming (mcp__laravel-boost__*),
but we were configuring it with underscore (mcp__laravel_boost__*), causing permission
errors when the agent tried to use Laravel Boost tools.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the 15 MCP tools available from Laravel Boost so the agent
knows to use them instead of bash commands where appropriate.

- Add tools table with purpose and examples
- Add guidance on when to use MCP vs bash commands
- Update database verification step to reference MCP tools
- Update Laravel Log section to recommend MCP tools first

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow users to upload markdown and text files in addition to images
when creating a project spec. This enables uploading detailed spec
documents instead of typing them manually.

Changes:
- Add TextFileAttachment model with UTF-8 validation (schemas.py)
- Update backend to send text files as text content blocks to Claude
- Add FileAttachment discriminated union type (ImageAttachment | TextAttachment)
- Display text files as compact chips in pending attachments
- Show sent text files as expandable accordions in chat messages
- Update file input to accept .md and .txt files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…es server

The features database was missing the timeout parameter in create_engine(),
causing immediate "database is locked" failures when encountering WAL artifacts
from other processes. This matches the pattern already used in registry.py.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

This pull request adds comprehensive Laravel framework support to the project scaffolding system. It introduces Laravel-specific templates, framework detection, interactive tech stack configuration (framework/database/testing choices), Laravel Boost MCP tool integration, enhanced file attachment handling (text + images), and end-to-end framework-aware workflows for both backend and frontend.

Changes

Cohort / File(s) Summary
Laravel Templates & Initialization
.claude/templates/laravel/app_spec.template.txt, .claude/templates/laravel/coding_prompt.template.md, .claude/templates/laravel/coding_prompt_yolo.template.md, .claude/templates/laravel/initializer_prompt.template.md
Added four comprehensive Laravel project templates: specification template with project structure and design tokens, standard coding workflow with testing/verification steps, YOLO mode rapid prototyping (tests disabled), and initializer prompt for bootstrapping new Laravel projects.
Framework Detection & Prompt Selection
prompts.py
Introduced detect_framework_from_spec() to infer framework from app spec, added LARAVEL_TEMPLATES_DIR constant, and extended scaffold_project_prompts() to select framework-specific templates with fallback to base templates.
Agent & Client Framework Awareness
agent.py, client.py
Updated agent to detect framework at startup and thread is_laravel flag through client creation. Extended create_client() signature with is_laravel parameter; when true, includes LARAVEL_BOOST_TOOLS in allowed tools and configures Laravel Boost MCP server.
Framework-Aware Project Scaffolding
server/routers/projects.py, server/routers/spec_creation.py, server/schemas.py
Modified create_project to detect Laravel framework and pass to scaffold step. Added TechStackConfig model with framework/database/testing enums and helper methods (is_laravel(), get_default_testing(), get_laravel_starter_kit()). Added to ProjectCreate as optional tech_stack field.
Multi-Format Attachment Support
server/schemas.py, server/services/spec_chat_session.py
Introduced TextFileAttachment for text files (UTF-8 validated, size-capped). Created union type `FileAttachment = ImageAttachment
Command & Security Whitelisting
security.py, api/database.py
Extended ALLOWED_COMMANDS with PHP/Laravel tools (php, composer, laravel, artisan, pest, pint) and process inspection (pgrep). Allowed php/artisan in pkill validation. Added 30-second database connection timeout.
Interactive Tech Stack Selection
start.py
Added ask_framework_choice(), ask_database_choice(), ask_testing_choice() prompts. Extended ensure_project_scaffolded() with framework parameter. Reworked create_new_project_flow() to collect tech stack before scaffolding and display summary.
Frontend Tech Stack UI
ui/src/components/NewProjectModal.tsx
Introduced two-step tech stack flow: framework selection (react_node, laravel_react, laravel_vue, laravel_livewire, laravel_api with auto-default testing) and database/testing options. Updated project creation payload to include techStack.
File Attachment Type System
ui/src/lib/types.ts
Added discriminated union for attachments: ImageAttachment now carries type: 'image'; new TextAttachment with type: 'text' and decoded textContent. Created FileAttachment union. Added comprehensive tech stack type definitions (FrameworkChoice, DatabaseChoice, TestingFramework, TechStackConfig, option interfaces).
Attachment Rendering & API Integration
ui/src/components/ChatMessage.tsx, ui/src/components/SpecCreationChat.tsx, ui/src/hooks/useProjects.ts, ui/src/hooks/useSpecChat.ts, ui/src/lib/api.ts
Updated ChatMessage to expand/collapse text attachments alongside images. Extended SpecCreationChat to accept .md/.txt files, validate MIME types, and display previews. Updated API layer and hooks to pass techStack?: TechStackConfig through project creation and spec chat flows.
Minor Updates
ui/src/components/ExpandProjectChat.tsx, ui/src/hooks/useWebSocket.ts
Added type field to attachment objects. Increased log retention from 100 to 1000 lines.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend as Frontend UI
    participant Backend as Backend API
    participant Agent as AI Agent
    participant MCPTools as Laravel Boost MCP
    participant FileSystem as Project Directory

    User->>Frontend: Start New Project
    Frontend->>Frontend: Ask framework choice
    User->>Frontend: Select Laravel
    Frontend->>Frontend: Display tech stack UI
    User->>Frontend: Select database & testing
    Frontend->>Backend: POST /projects/create with techStack
    
    Backend->>Backend: Detect framework from spec
    Backend->>Backend: Create ProjectCreate with tech_stack
    Backend->>Agent: Initialize with is_laravel=true
    
    Agent->>Agent: Load Laravel-specific templates
    Agent->>Agent: Create client with LARAVEL_BOOST_TOOLS
    Agent->>MCPTools: Initialize Laravel Boost MCP server
    
    Agent->>Backend: Call scaffold_project_prompts(framework="laravel")
    Backend->>FileSystem: Select from LARAVEL_TEMPLATES_DIR
    Backend->>Agent: Provide Laravel initializer prompt
    
    Agent->>MCPTools: Execute feature_create_bulk via MCP
    MCPTools->>FileSystem: Create features, migrations, models
    
    Agent->>Backend: Run artisan commands (migrate, etc.)
    Backend->>FileSystem: Bootstrap Laravel app
    
    Agent->>Frontend: Report project ready
    Frontend->>User: Show Laravel project initialized
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 Hops of joy for Laravel's debut!
Framework flags and templates too,
Attachments dance both text and image bright,
MCP tools make Boost take flight!
From Vue to Livewire, the choice is free,
A rabbit-built system, wild and free!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.47% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding Laravel framework support, tech stack selection, and file upload enhancements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
security.py (1)

184-233: pkill allowing php is potentially too broad (can kill non-dev PHP processes).

pkill php is a pattern match and can hit php-fpm/other PHP processes. If the intent is “only kill Laravel dev server”, consider requiring -f and matching a more specific command line (e.g., php artisan serve) for PHP-related kills, or requiring -x for exact-name matches where possible.

Proposed tightening (one possible direction)
 def validate_pkill_command(command_string: str) -> tuple[bool, str]:
@@
     allowed_process_names = {
@@
-        # PHP/Laravel dev servers
-        "php",
-        "artisan",
+        # PHP/Laravel dev servers (prefer full-cmdline match via -f)
+        # Keep "php" out of the simple-name allowlist to avoid killing unrelated php/php-fpm processes.
+        "artisan",
     }
@@
-    if target in allowed_process_names:
-        return True, ""
+    if target in allowed_process_names:
+        return True, ""
+
+    # Allow php only when using -f with an artisan command line
+    # e.g. pkill -f "php artisan serve"
+    if "php" == target and "-f" in tokens and "artisan" in command_string:
+        return True, ""
ui/src/components/ChatMessage.tsx (1)

155-206: Harden window.open + be defensive about missing textContent.

window.open(url, '_blank') should include noopener,noreferrer to avoid reverse-tabnabbing, and text attachments should render something sensible if textContent is empty/undefined.

Proposed diff
- onClick={() => window.open(attachment.previewUrl, '_blank')}
+ onClick={() => window.open(attachment.previewUrl, '_blank', 'noopener,noreferrer')}

...
- {attachment.textContent}
+ {attachment.textContent ?? '(no content)'}
🤖 Fix all issues with AI agents
In @security.py:
- Around line 35-41: ALLOWED_COMMANDS is missing "phpstan" which breaks
templates that run ./vendor/bin/phpstan analyse; update the ALLOWED_COMMANDS
list to include "phpstan" (and optionally remove unused "pest" if you confirm
tests are always run via "php artisan test"); keep the note that "artisan" in
validate_pkill_command.allowed_process_names remains correct for stopping dev
servers but does not enable "php artisan ..." usage — ensure any template that
expects direct "artisan" execution is adjusted or the template is updated to
call "php" + "artisan" appropriately.

In @ui/src/components/SpecCreationChat.tsx:
- Around line 157-170: The code in SpecCreationChat.tsx uses atob(base64Data) to
build textContent which garbles non-ASCII UTF-8 characters; replace the atob
usage in the TextAttachment creation (the textContent variable) with proper
UTF-8 decoding by converting base64Data to a Uint8Array and decoding it via new
TextDecoder('utf-8'). Ensure the updated textContent is used when constructing
the TextAttachment and then call setPendingAttachments((prev) => [...prev,
attachment]) as before.
🧹 Nitpick comments (12)
ui/src/hooks/useWebSocket.ts (1)

20-20: LGTM! Aligns with PR objectives to expand debug log retention.

The 10x increase (100→1000) in retained log lines supports richer debugging workflows introduced in this PR. The slicing logic on line 79 correctly maintains the limit.

Optional operational note: Retaining 10x more logs increases memory usage proportionally. If logs are verbose or multiple WebSocket connections are active simultaneously, monitor memory consumption in production or consider implementing log level filtering or pagination for very large log volumes.

api/database.py (1)

87-87: Good addition to prevent lock contention errors.

The 30-second timeout is appropriate and directly addresses the "database is locked" errors mentioned in the PR objectives. This gives SQLite sufficient time to acquire locks in concurrent access scenarios.

Optional enhancement: Consider enabling WAL mode for better concurrency.

For improved concurrent read/write performance, you could optionally enable SQLite's Write-Ahead Logging (WAL) mode:

♻️ Optional WAL mode enhancement
 def create_database(project_dir: Path) -> tuple:
     """
     Create database and return engine + session maker.
 
     Args:
         project_dir: Directory containing the project
 
     Returns:
         Tuple of (engine, SessionLocal)
     """
     db_url = get_database_url(project_dir)
     engine = create_engine(db_url, connect_args={"check_same_thread": False, "timeout": 30})
     Base.metadata.create_all(bind=engine)
+    
+    # Enable WAL mode for better concurrency
+    with engine.connect() as conn:
+        conn.execute(text("PRAGMA journal_mode=WAL"))
+        conn.commit()
 
     # Migrate existing databases to add in_progress column
     _migrate_add_in_progress_column(engine)

WAL mode allows concurrent readers while a writer is active, reducing lock contention beyond what the timeout alone provides.

ui/src/components/ExpandProjectChat.tsx (1)

111-127: Guard base64 parsing + prefer crypto.randomUUID() for attachment IDs.

dataUrl.split(',')[1] can be undefined (unexpected DataURL), and the current ID generation can collide in theory. Suggest a small hardening tweak.

Proposed diff
 reader.onload = (e) => {
   const dataUrl = e.target?.result as string
-  const base64Data = dataUrl.split(',')[1]
+  const base64Data = dataUrl.split(',')[1]
+  if (!base64Data) {
+    setError(`Failed to parse file data: ${file.name}`)
+    return
+  }

   const attachment: ImageAttachment = {
     type: 'image',
-    id: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
+    id: crypto.randomUUID(),
     filename: file.name,
     mimeType: file.type as 'image/jpeg' | 'image/png',
     base64Data,
     previewUrl: dataUrl,
     size: file.size,
   }
client.py (1)

264-274: Consider pinning the Laravel Boost MCP package version (and confirm env contract).

Playwright uses @latest; Laravel Boost currently doesn’t. If the package expects a specific version or additional args/env (beyond PROJECT_DIR), startup can break.

Possible diff (if you want parity with Playwright)
 mcp_servers["laravel-boost"] = {
   "command": "npx",
-  "args": ["@anthropic/laravel-boost"],
+  "args": ["@anthropic/laravel-boost@latest"],
   "env": {
     **os.environ,
     "PROJECT_DIR": str(project_dir.resolve()),
   },
 }
agent.py (1)

142-149: Consider explicit handling of None from framework detection.

The framework detection logic assumes that detect_framework_from_spec returns either "laravel" or "nodejs". According to the context, it can also return None when the spec file is not found. Currently, is_laravel will be False when framework is None, which effectively defaults to Node.js behavior.

If this is intentional for backward compatibility, consider adding a comment to clarify. Otherwise, you may want to log a warning when framework detection returns None.

💡 Optional enhancement to handle None explicitly
 # Detect framework from spec
 framework = detect_framework_from_spec(project_dir)
+if framework is None:
+    print("Framework: Not detected (defaulting to Node.js)")
+    is_laravel = False
+elif framework == "laravel":
-is_laravel = framework == "laravel"
-if is_laravel:
     print("Framework: Laravel (with Laravel Boost MCP)")
+    is_laravel = True
 else:
     print("Framework: Node.js")
+    is_laravel = False
 print()
.claude/templates/laravel/initializer_prompt.template.md (2)

104-127: Add language specifier to fenced code block.

The fenced code block lacks a language specifier, which can affect syntax highlighting and linting. Since this shows tool usage syntax, consider using a generic identifier.

📝 Suggested fix
-```
+```text
 Use the feature_create_bulk tool with features=[
   {
     "category": "functional",

357-359: Add language specifier to fenced code block.

Similar to the earlier block, this tool usage example should have a language specifier for consistency.

📝 Suggested fix
-```
+```text
 Use the feature_get_next tool
</details>

</blockquote></details>
<details>
<summary>server/services/spec_chat_session.py (1)</summary><blockquote>

`294-301`: **Move import to module level.**

The `import base64 as b64` inside the function is executed on every call with text attachments. While functional, this is unconventional and slightly inefficient. The module already has access to base64 functionality.



<details>
<summary>♻️ Proposed fix</summary>

Add at the top of the file (around line 9):
```python
import base64

Then update the decoding:

                 elif att.mimeType in ('text/plain', 'text/markdown'):
                     # Text file: decode and send as text content block
-                    import base64 as b64
-                    decoded_text = b64.b64decode(att.base64Data).decode('utf-8')
+                    decoded_text = base64.b64decode(att.base64Data).decode('utf-8')
                     # Format with filename header for context
.claude/templates/laravel/coding_prompt_yolo.template.md (1)

40-46: Add language specifiers to MCP tool usage blocks.

Multiple fenced code blocks showing MCP tool usage lack language specifiers. While these are minor formatting issues, adding specifiers improves consistency.

📝 Example fix for lines 40-46
-```
+```text
 # 6. Get progress statistics (passing/total counts)
 Use the feature_get_stats tool

 # 7. Get the next feature to work on
 Use the feature_get_next tool
</details>

This applies similarly to blocks at lines 74-77, 82-84, 112-114, 187-189, and 298-316.

</blockquote></details>
<details>
<summary>start.py (1)</summary><blockquote>

`487-507`: **Consider persisting tech stack choices for template customization.**

The `tech_stack` dict is built with database and testing choices but only used for display. These values could be valuable for pre-populating the app_spec.txt template or passed to the scaffolding function for automatic placeholder replacement.



This could be addressed in a follow-up PR if needed. For now, the display provides useful confirmation to users about their choices.

</blockquote></details>
<details>
<summary>ui/src/components/NewProjectModal.tsx (1)</summary><blockquote>

`31-80`: **Consider extracting constants to a shared location.**

These option constants are well-defined and correctly typed. However, since the same options may be needed in other components or for server-side validation, consider moving them to `lib/constants.ts` or colocating with the types in `lib/types.ts` to enable reuse and ensure consistency.

</blockquote></details>
<details>
<summary>server/schemas.py (1)</summary><blockquote>

`291-316`: **Minor: Error message substring check may be fragile.**

The exception handling on line 314 checks for `'not valid UTF-8'` but the actual error raised on line 312 is `'File is not valid UTF-8 text'`. This works but is fragile if error messages change.



<details>
<summary>♻️ Suggested improvement</summary>

Consider using a custom exception class or restructuring to avoid substring matching:

```diff
     @field_validator('base64Data')
     @classmethod
     def validate_base64_and_size(cls, v: str) -> str:
         """Validate that base64 data is valid UTF-8 text and within size limit."""
         try:
             decoded = base64.b64decode(v)
-            if len(decoded) > MAX_FILE_SIZE:
-                raise ValueError(
-                    f'File size ({len(decoded) / (1024 * 1024):.1f} MB) exceeds '
-                    f'maximum of {MAX_FILE_SIZE // (1024 * 1024)} MB'
-                )
-            # Validate it's valid UTF-8 text
-            decoded.decode('utf-8')
-            return v
-        except UnicodeDecodeError:
-            raise ValueError('File is not valid UTF-8 text')
-        except Exception as e:
-            if 'File size' in str(e) or 'not valid UTF-8' in str(e):
-                raise
-            raise ValueError(f'Invalid base64 data: {e}')
+        except Exception as e:
+            raise ValueError(f'Invalid base64 data: {e}')
+        
+        if len(decoded) > MAX_FILE_SIZE:
+            raise ValueError(
+                f'File size ({len(decoded) / (1024 * 1024):.1f} MB) exceeds '
+                f'maximum of {MAX_FILE_SIZE // (1024 * 1024)} MB'
+            )
+        
+        try:
+            decoded.decode('utf-8')
+        except UnicodeDecodeError:
+            raise ValueError('File is not valid UTF-8 text')
+        
+        return v
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 334b655 and e9c3e4e.

📒 Files selected for processing (23)
  • .claude/templates/laravel/app_spec.template.txt
  • .claude/templates/laravel/coding_prompt.template.md
  • .claude/templates/laravel/coding_prompt_yolo.template.md
  • .claude/templates/laravel/initializer_prompt.template.md
  • agent.py
  • api/database.py
  • client.py
  • prompts.py
  • security.py
  • server/routers/projects.py
  • server/routers/spec_creation.py
  • server/schemas.py
  • server/services/spec_chat_session.py
  • start.py
  • ui/src/components/ChatMessage.tsx
  • ui/src/components/ExpandProjectChat.tsx
  • ui/src/components/NewProjectModal.tsx
  • ui/src/components/SpecCreationChat.tsx
  • ui/src/hooks/useProjects.ts
  • ui/src/hooks/useSpecChat.ts
  • ui/src/hooks/useWebSocket.ts
  • ui/src/lib/api.ts
  • ui/src/lib/types.ts
🧰 Additional context used
📓 Path-based instructions (7)
ui/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

ui/src/**/*.{ts,tsx}: Use TypeScript for React components in the UI (React 18 with TypeScript)
Use React Query (TanStack Query) for API calls and data fetching in the UI
Use Radix UI for component primitives in the React UI
Run ESLint to lint React UI code

Files:

  • ui/src/hooks/useWebSocket.ts
  • ui/src/components/ChatMessage.tsx
  • ui/src/lib/types.ts
  • ui/src/components/ExpandProjectChat.tsx
  • ui/src/hooks/useProjects.ts
  • ui/src/components/NewProjectModal.tsx
  • ui/src/lib/api.ts
  • ui/src/hooks/useSpecChat.ts
  • ui/src/components/SpecCreationChat.tsx
.claude/templates/**/*.template.md

📄 CodeRabbit inference engine (CLAUDE.md)

Prompt templates should follow a fallback chain: project-specific in {project_dir}/prompts/{name}.md, then base template in .claude/templates/{name}.template.md

Files:

  • .claude/templates/laravel/coding_prompt.template.md
  • .claude/templates/laravel/initializer_prompt.template.md
  • .claude/templates/laravel/coding_prompt_yolo.template.md
*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Python backend should use the ClaudeSDKClient configuration in client.py with security hooks and MCP servers

Files:

  • prompts.py
  • start.py
  • security.py
  • agent.py
  • client.py
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use SQLite with SQLAlchemy ORM for database access and feature management

Files:

  • prompts.py
  • start.py
  • server/routers/spec_creation.py
  • server/services/spec_chat_session.py
  • server/schemas.py
  • api/database.py
  • security.py
  • server/routers/projects.py
  • agent.py
  • client.py
server/routers/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use FastAPI for REST API endpoints in the server/routers/ directory

Files:

  • server/routers/spec_creation.py
  • server/routers/projects.py
security.py

📄 CodeRabbit inference engine (CLAUDE.md)

Implement bash command validation using the ALLOWED_COMMANDS whitelist in security.py

Files:

  • security.py
agent.py

📄 CodeRabbit inference engine (CLAUDE.md)

Agent sessions should auto-continue with a 3-second delay between sessions

Files:

  • agent.py
🧠 Learnings (8)
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to .claude/templates/**/*.template.md : Prompt templates should follow a fallback chain: project-specific in {project_dir}/prompts/{name}.md, then base template in .claude/templates/{name}.template.md

Applied to files:

  • .claude/templates/laravel/coding_prompt.template.md
  • .claude/templates/laravel/initializer_prompt.template.md
  • prompts.py
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Two-agent pattern: Initializer Agent reads app spec and creates features in first session; Coding Agent implements features one by one in subsequent sessions

Applied to files:

  • .claude/templates/laravel/initializer_prompt.template.md
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to ui/src/**/*.{ts,tsx} : Use TypeScript for React components in the UI (React 18 with TypeScript)

Applied to files:

  • ui/src/lib/types.ts
  • ui/src/hooks/useProjects.ts
  • ui/src/components/SpecCreationChat.tsx
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to ui/src/**/*.{ts,tsx} : Use React Query (TanStack Query) for API calls and data fetching in the UI

Applied to files:

  • ui/src/hooks/useProjects.ts
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to security.py : Implement bash command validation using the ALLOWED_COMMANDS whitelist in security.py

Applied to files:

  • security.py
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to mcp_server/**/*.py : Use MCP (Model Context Protocol) servers for agent tools: feature_mcp.py for feature management, with tools: feature_get_stats, feature_get_next, feature_get_for_regression, feature_mark_passing, feature_skip, feature_create_bulk

Applied to files:

  • client.py
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Defense-in-depth security model: OS-level sandbox for bash commands, filesystem restricted to project directory, bash commands validated against ALLOWED_COMMANDS whitelist

Applied to files:

  • client.py
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to *.py : Python backend should use the ClaudeSDKClient configuration in client.py with security hooks and MCP servers

Applied to files:

  • client.py
🧬 Code graph analysis (13)
start.py (2)
server/schemas.py (1)
  • is_laravel (62-64)
prompts.py (1)
  • scaffold_project_prompts (148-202)
server/routers/spec_creation.py (2)
server/schemas.py (2)
  • ImageAttachment (267-288)
  • TextFileAttachment (291-316)
ui/src/lib/types.ts (2)
  • ImageAttachment (214-222)
  • FileAttachment (236-236)
server/services/spec_chat_session.py (3)
server/schemas.py (2)
  • ImageAttachment (267-288)
  • TextFileAttachment (291-316)
ui/src/lib/types.ts (2)
  • ImageAttachment (214-222)
  • FileAttachment (236-236)
server/services/expand_chat_session.py (2)
  • _make_multimodal_message (42-51)
  • _query_claude (239-340)
ui/src/components/ExpandProjectChat.tsx (1)
ui/src/hooks/useExpandChat.ts (1)
  • a (305-309)
ui/src/hooks/useProjects.ts (2)
server/schemas.py (1)
  • TechStackConfig (56-80)
ui/src/lib/types.ts (1)
  • TechStackConfig (388-392)
ui/src/components/NewProjectModal.tsx (1)
ui/src/lib/types.ts (6)
  • FrameworkOption (394-400)
  • DatabaseOption (402-407)
  • TestingOption (409-415)
  • FrameworkChoice (377-382)
  • TestingFramework (386-386)
  • TechStackConfig (388-392)
server/schemas.py (1)
ui/src/lib/types.ts (6)
  • FrameworkChoice (377-382)
  • DatabaseChoice (384-384)
  • TestingFramework (386-386)
  • TechStackConfig (388-392)
  • FileAttachment (236-236)
  • ImageAttachment (214-222)
ui/src/lib/api.ts (2)
server/schemas.py (2)
  • TechStackConfig (56-80)
  • ProjectSummary (103-108)
ui/src/lib/types.ts (2)
  • TechStackConfig (388-392)
  • ProjectSummary (13-18)
server/routers/projects.py (1)
server/schemas.py (1)
  • is_laravel (62-64)
agent.py (3)
prompts.py (1)
  • detect_framework_from_spec (25-50)
server/schemas.py (1)
  • is_laravel (62-64)
client.py (1)
  • create_client (132-293)
client.py (1)
server/schemas.py (1)
  • is_laravel (62-64)
ui/src/hooks/useSpecChat.ts (1)
ui/src/lib/types.ts (1)
  • FileAttachment (236-236)
ui/src/components/SpecCreationChat.tsx (2)
ui/src/lib/types.ts (3)
  • FileAttachment (236-236)
  • ImageAttachment (214-222)
  • TextAttachment (225-233)
server/schemas.py (1)
  • ImageAttachment (267-288)
🪛 LanguageTool
.claude/templates/laravel/app_spec.template.txt

[style] ~248-~248: Using many exclamation marks might seem excessive (in this case: 17 exclamation marks for a text that’s 3681 characters long)
Context: ... </design_system> <key_interactions> ...

(EN_EXCESSIVE_EXCLAMATION)

.claude/templates/laravel/coding_prompt.template.md

[style] ~129-~129: ‘almost NEVER’ might be wordy. Consider a shorter alternative.
Context: ...ure (EXTREMELY RARE) Skipping should almost NEVER happen. Only skip for truly external ...

(EN_WORDINESS_PREMIUM_ALMOST_NEVER)


[style] ~381-~381: Consider using a different verb for a more formal wording.
Context: ...ou completed - Any issues discovered or fixed - What should be worked on next - Curre...

(FIX_RESOLVE)

.claude/templates/laravel/coding_prompt_yolo.template.md

[style] ~91-~91: ‘almost NEVER’ might be wordy. Consider a shorter alternative.
Context: ...ure (EXTREMELY RARE) Skipping should almost NEVER happen. Only skip for truly external ...

(EN_WORDINESS_PREMIUM_ALMOST_NEVER)


[style] ~220-~220: Consider using a different verb for a more formal wording.
Context: ...ou completed - Any issues discovered or fixed - What should be worked on next - Curre...

(FIX_RESOLVE)

🪛 markdownlint-cli2 (0.18.1)
.claude/templates/laravel/coding_prompt.template.md

29-29: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


60-60: Bare URL used

(MD034, no-bare-urls)


61-61: Bare URL used

(MD034, no-bare-urls)


74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


112-112: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


119-119: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


150-150: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


190-190: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


235-235: Bare URL used

(MD034, no-bare-urls)


256-256: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


342-342: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


346-346: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


500-500: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


540-540: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

.claude/templates/laravel/initializer_prompt.template.md

104-104: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


357-357: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

.claude/templates/laravel/coding_prompt_yolo.template.md

29-29: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


60-60: Bare URL used

(MD034, no-bare-urls)


61-61: Bare URL used

(MD034, no-bare-urls)


74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


112-112: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


119-119: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


150-150: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


190-190: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


235-235: Bare URL used

(MD034, no-bare-urls)


256-256: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


342-342: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


346-346: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (41)
security.py (1)

47-49: pgrep is not currently used in the codebase; the whitelist approach is sufficient protection.

pgrep is listed in the ALLOWED_COMMANDS allowlist but is not invoked anywhere in the codebase. Since usage would require explicit code changes (subject to review), and the whitelist mechanism itself prevents arbitrary flag injection, no additional flag-level restrictions are needed at this time.

client.py (2)

132-190: LGTM: Laravel tools gated behind is_laravel and stay out of YOLO/Node flows by default.

The conditional extension of both allowed_tools and permissions_list is the right pattern for keeping the security surface minimal outside Laravel projects. Based on learnings, this matches the repo’s allowlist-based security model.


99-117: The Laravel Boost MCP package (@anthropic/laravel-boost) does not exist on the public npm registry and cannot be verified.

The tool IDs in LARAVEL_BOOST_TOOLS cannot be validated because the source package is unavailable. Before this code runs, confirm:

  1. The package name is correct and the package is published (public or private registry)
  2. The exact tool names exported by the package match these identifiers
  3. The npx invocation path is accessible in your environment

Without these validations, the allowlist will either fail silently or fail loudly at runtime.

ui/src/lib/api.ts (1)

54-69: Good propagation of tech stack selection via tech_stack payload.

tech_stack: techStack will be omitted when undefined (JSON.stringify behavior), so this stays backwards-compatible for callers that don’t pass a tech stack.

ui/src/components/ChatMessage.tsx (1)

8-30: Stateful expand/collapse via Set is clean and avoids mutation.

server/routers/projects.py (1)

172-179: The code is correct. The lazy import mechanism in this file properly assigns _scaffold_project_prompts via _init_imports() (called at line 133 before the function usage at line 178). The scaffold_project_prompts function signature accepts framework: str = "nodejs" and supports both "nodejs" and "laravel" values as documented, matching the framework types passed from lines 173-176.

server/routers/spec_creation.py (2)

17-17: LGTM! Import and type annotation updated correctly.

The imports now include both TextFileAttachment and the union type FileAttachment, and the attachment list typing correctly reflects the expanded attachment model.

Also applies to: 257-257


256-275: The MIME type string literals in the attachment parsing logic correctly match the schema definitions. The router uses 'image/jpeg', 'image/png', 'text/plain', and 'text/markdown', which exactly correspond to the Literal types defined in schemas.py. No changes needed.

agent.py (1)

190-190: LGTM! Framework-aware client creation.

The is_laravel flag is correctly passed to create_client, enabling framework-specific MCP server configuration and tool availability.

.claude/templates/laravel/coding_prompt.template.md (3)

1-62: LGTM! Clear orientation and startup instructions.

Steps 1 and 2 provide comprehensive orientation commands and server startup procedures tailored for Laravel projects. The instructions correctly reference Laravel-specific URLs and commands.


494-531: LGTM! Clear feature tool usage boundaries.

The feature tool usage rules effectively prevent token waste by restricting queries to specific, necessary operations. The explicit "DO NOT" list helps prevent exploratory queries that would bloat context.


464-491: Tool names in template are correct.

All 15 Laravel Boost MCP tools listed match the actual tools defined in client.py (lines 101-116). The template uses simplified names (e.g., database_query, list_routes) for documentation clarity, which correctly correspond to the actual tool names with hyphens and prefixes (e.g., mcp__laravel-boost__database-query).

ui/src/hooks/useSpecChat.ts (1)

6-6: LGTM! Attachment type generalized correctly.

The hook now accepts FileAttachment[] instead of ImageAttachment[], enabling support for both image and text file attachments. The type changes are applied consistently across the import, function signature, and implementation.

Also applies to: 25-25, 367-367

ui/src/hooks/useProjects.ts (1)

7-7: LGTM! Tech stack configuration parameter added correctly.

The techStack parameter is properly typed as optional and passed through to the API layer, enabling framework/database/testing selection during project creation. The change is backward compatible since the parameter is optional.

Also applies to: 32-37

.claude/templates/laravel/app_spec.template.txt (1)

1-359: LGTM!

Well-structured Laravel project specification template. The sections comprehensively cover Laravel-specific configuration (starter kits, Pest/PHPUnit, Boost MCP), technology choices, and implementation guidance. Port assignments (8000 for Laravel, 5173 for Vite) are correct for the standard Laravel development setup.

.claude/templates/laravel/initializer_prompt.template.md (1)

246-320: LGTM!

The init.sh script template is well-designed with proper error handling (set -e), conditional checks for existing dependencies, concurrent server management with proper cleanup via trap, and support for both Inertia-based and API-only Laravel projects.

ui/src/components/SpecCreationChat.tsx (1)

338-365: LGTM!

The conditional rendering correctly differentiates between image and text attachments. The text file preview shows appropriate metadata (filename, size) without overwhelming the UI, and the FileText icon provides good visual distinction.

prompts.py (2)

25-50: LGTM!

The framework detection logic is well-structured with a clear hierarchy: check for explicit <laravel_specific> tag first, then fall back to keyword detection, with sensible defaults. The backward-compatible default to 'nodejs' is appropriate.


165-189: LGTM!

The framework-aware template selection with fallback chain is correctly implemented. The code properly handles the case where Laravel templates don't exist by falling back to base templates with an appropriate warning. This aligns with the coding guideline for prompt template fallback chains.

server/services/spec_chat_session.py (1)

280-306: LGTM on attachment type handling.

The logic correctly handles both image and text attachments by checking mimeType. The text file formatting with filename headers provides good context for Claude to understand the attached content.

.claude/templates/laravel/coding_prompt_yolo.template.md (2)

1-10: LGTM!

The YOLO mode header clearly communicates the trade-offs: skipping browser testing in favor of static analysis (Pint, PHPStan) for rapid prototyping. The synchronization comment with coding_prompt.template.md is helpful for maintainability.


262-289: Excellent MCP tools reference table.

The Laravel Boost MCP tools table provides clear guidance on when to use MCP tools vs bash commands. This practical comparison (e.g., tinker MCP for one-liners vs php artisan tinker for interactive REPL) helps agents make efficient choices.

start.py (2)

192-229: LGTM!

The framework choice function provides a clear menu with helpful descriptions for each option. The default handling (empty string = option 1) follows good CLI UX patterns. The returned dict structure with is_laravel flag enables downstream framework-specific logic.


260-296: LGTM!

The testing choice function correctly adapts options based on framework context (Pest/PHPUnit for Laravel, Vitest/Jest for Node.js). The conditional structure is clean and the defaults are sensible (Pest for Laravel, Vitest for Node.js).

ui/src/components/NewProjectModal.tsx (9)

12-25: LGTM!

Clean imports with proper type imports from the types module. The Check icon is correctly imported for the selection UI.


82-90: LGTM!

Helper functions are concise and correctly mirror the server-side TechStackConfig.is_laravel() and get_default_testing() methods, ensuring consistent behavior.


113-125: LGTM!

State initialization and derived availableTestingOptions are correctly implemented. The filter ensures only testing frameworks appropriate for the selected stack are shown.


156-164: LGTM!

handleFrameworkSelect correctly updates the framework and resets the testing option to the appropriate default for that framework, preventing invalid combinations (e.g., selecting Jest with Laravel).


262-266: LGTM!

State is correctly reset to defaults when the modal closes, ensuring a clean state for subsequent project creation.


270-282: LGTM!

Back navigation correctly traverses all new steps and clears state appropriately.


186-191: LGTM!

Both manual and Claude project creation paths correctly include the techStack configuration in the API payload.

Also applies to: 203-208


407-477: LGTM!

The framework selection UI is well-structured with clear visual feedback for selection state, appropriate use of semantic buttons, and consistent styling.


479-575: LGTM!

The tech options UI correctly presents database and filtered testing framework options. The grid layout is consistent with the framework selection step.

ui/src/lib/types.ts (3)

214-236: LGTM!

Good use of discriminated union pattern with the type field for ImageAttachment and TextAttachment. This enables exhaustive type checking when handling attachments. The FileAttachment union type cleanly combines both.


239-247: LGTM!

ChatMessage.attachments correctly uses the new FileAttachment[] union type to support both image and text attachments.


377-415: LGTM!

Tech stack types are well-defined and correctly align with server-side schemas.py definitions. The TestingOption.forFramework field provides a clear UI-friendly way to filter options.

server/schemas.py (5)

28-54: LGTM!

The enums are well-structured using str, Enum for proper JSON serialization. The values align with frontend FrameworkChoice, DatabaseChoice, and TestingFramework types.


56-81: LGTM!

TechStackConfig is well-designed with sensible defaults and useful helper methods. The testing: TestingFramework | None = None approach with get_default_testing() allows flexible defaulting on the server side.


92-92: LGTM!

Optional tech_stack field maintains backward compatibility with existing API consumers.


263-264: LGTM!

Consolidating to a single MAX_FILE_SIZE constant simplifies maintenance and ensures consistent limits across file types.


319-320: LGTM!

The FileAttachment type alias correctly creates a union type matching the frontend definition for consistent typing across the stack.

Comment on lines +35 to +41
# PHP/Laravel development
"php",
"composer",
"laravel",
"artisan",
"pest",
"pint", # Laravel code style fixer
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find invocations of Laravel/PHP test tooling to confirm which basenames must be allowlisted
rg -n --hidden -S '\b(phpunit|pest|pint|artisan|composer)\b' -g'!.git/**' | head -100

Repository: leonvanzyl/autocoder

Length of output: 9593


🏁 Script executed:

#!/bin/bash
# Also search for vendor/bin invocations that might require special handling
rg -n --hidden -S '\./vendor/bin/|composer require|php artisan' -g'!.git/**' | head -100

Repository: leonvanzyl/autocoder

Length of output: 7783


🏁 Script executed:

#!/bin/bash
# Check the security.py file to see current ALLOWED_COMMANDS and validate_pkill_command implementation
cat -n security.py | sed -n '1,250p'

Repository: leonvanzyl/autocoder

Length of output: 8420


Add phpstan to ALLOWED_COMMANDS; clarify that artisan in the allowlist only supports direct execution (not the typical php artisan form).

Your analysis is correct: extract_commands("php artisan ...") extracts only php, so the artisan entry in ALLOWED_COMMANDS (line 39) does not enable typical Laravel usage. However, artisan in validate_pkill_command.allowed_process_names (line 202) is appropriate for stopping dev servers.

Missing: The templates invoke ./vendor/bin/phpstan analyse (e.g., coding_prompt_yolo.template.md:167), but phpstan is not in ALLOWED_COMMANDS. Either add phpstan or remove the template reference if it is not expected to run. Additionally, pest in ALLOWED_COMMANDS (line 40) is not invoked directly; tests use php artisan test instead.

🤖 Prompt for AI Agents
In @security.py around lines 35 - 41, ALLOWED_COMMANDS is missing "phpstan"
which breaks templates that run ./vendor/bin/phpstan analyse; update the
ALLOWED_COMMANDS list to include "phpstan" (and optionally remove unused "pest"
if you confirm tests are always run via "php artisan test"); keep the note that
"artisan" in validate_pkill_command.allowed_process_names remains correct for
stopping dev servers but does not enable "php artisan ..." usage — ensure any
template that expects direct "artisan" execution is adjusted or the template is
updated to call "php" + "artisan" appropriately.

Comment on lines +157 to 170
} else {
// Text file attachment - decode for display
const textContent = atob(base64Data)
const attachment: TextAttachment = {
type: 'text',
id,
filename: file.name,
mimeType: file.type as 'text/plain' | 'text/markdown',
base64Data,
textContent,
size: file.size,
}
setPendingAttachments((prev) => [...prev, attachment])
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

UTF-8 decoding issue with atob() for non-ASCII text.

The atob() function returns a binary string where each character represents one byte. For UTF-8 encoded text with non-ASCII characters (e.g., emojis, accented letters), this will produce garbled output. Use TextDecoder for proper UTF-8 handling.

🐛 Proposed fix
         } else {
-          // Text file attachment - decode for display
-          const textContent = atob(base64Data)
+          // Text file attachment - decode UTF-8 for display
+          const binaryString = atob(base64Data)
+          const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0))
+          const textContent = new TextDecoder('utf-8').decode(bytes)
           const attachment: TextAttachment = {
             type: 'text',
             id,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else {
// Text file attachment - decode for display
const textContent = atob(base64Data)
const attachment: TextAttachment = {
type: 'text',
id,
filename: file.name,
mimeType: file.type as 'text/plain' | 'text/markdown',
base64Data,
textContent,
size: file.size,
}
setPendingAttachments((prev) => [...prev, attachment])
}
} else {
// Text file attachment - decode UTF-8 for display
const binaryString = atob(base64Data)
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0))
const textContent = new TextDecoder('utf-8').decode(bytes)
const attachment: TextAttachment = {
type: 'text',
id,
filename: file.name,
mimeType: file.type as 'text/plain' | 'text/markdown',
base64Data,
textContent,
size: file.size,
}
setPendingAttachments((prev) => [...prev, attachment])
}
🤖 Prompt for AI Agents
In @ui/src/components/SpecCreationChat.tsx around lines 157 - 170, The code in
SpecCreationChat.tsx uses atob(base64Data) to build textContent which garbles
non-ASCII UTF-8 characters; replace the atob usage in the TextAttachment
creation (the textContent variable) with proper UTF-8 decoding by converting
base64Data to a Uint8Array and decoding it via new TextDecoder('utf-8'). Ensure
the updated textContent is used when constructing the TextAttachment and then
call setPendingAttachments((prev) => [...prev, attachment]) as before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant