Commit graph

118 commits

Author SHA1 Message Date
0fdb673a70
feat(tts): per-sentence glow synced to audio via Web Audio pause detection
When Auto-Play TTS reads a message, wrap its sentences in spans and advance a
glow highlight on detected inter-sentence silences (RMS dips), with a
char-proportional fallback. Comma/clause pauses are detected too, reserved for
a future word-level highlight. Tunable via window.GLOW.
2026-05-29 11:52:08 -04:00
57a5b6f243
feat(thinking): toggle to enable/disable model thinking mode
Add a Thinking on/off button next to Auto-Play TTS. When OFF (default),
the client sends enable_thinking=false with each chat_message and the
server passes chat_template_kwargs.enable_thinking=false to self-hosted
OpenAI-compatible endpoints (Qwen3-style), suppressing chain-of-thought
to save tokens rather than merely hiding it. Skips the param for
api.openai.com (which would 400) and o1/o3 (always think); templates that
ignore the kwarg simply drop it. Client-side reasoning suppression remains
as a fallback. State persists to localStorage across desktop and mobile.
2026-05-29 11:43:10 -04:00
e50fe6e830
streaming: forward reasoning_content to client as separate channel
Qwen3.x / Deepseek-R1 / o1 stream model thinking via
delta.reasoning_content during SSE; the final answer arrives later via
delta.content. Both server streaming paths (OpenAI client + llama-cpp
Python lib) now extract reasoning_content per chunk and emit it via the
same socketio "message_chunk" event with a `reasoning_content` field
(distinct from `content`). Reasoning is forwarded but NOT accumulated
into the buffer that persists to the DB — it's transient model-private
state, not part of the saved message.

Frontend (templates/chat.html): the message_chunk handler dispatches
on payload shape. On `reasoning_content`: lazy-create a
<details class="message-thinking"> block at the top of the message
wrapper, append text, return early (no buffer/markdown render). On
`content`: if a thinking block exists and is still open, auto-collapse
it to "thinking (click to expand)" before standard content rendering.

If a response never thinks, no thinking DOM element is created — no
visual artefact at all. Compatible with all existing message_chunk
listeners; reasoning_content is purely additive.
2026-05-25 14:49:43 -04:00
d7fcfc8935 Clean up debug code, keep Send button
Root cause found: uncloseai extension was clobbering window.sendMessage.
Fixed in uncloseai.com repo by namespacing under window.uncloseai.
2026-02-23 19:55:55 -05:00
c06b3706f2 Debug send failure - self-contained handler with visible error output 2026-02-23 19:39:04 -05:00
844ed05cf0 Add Send button and inline keydown handler for chat
Belt-and-suspenders: inline onkeydown on textarea ensures Enter
works regardless of JS event listener registration order, plus
a visible Send button as clickable fallback.
2026-02-23 19:30:00 -05:00
47bf62ef66 Add streaming TTS using MediaSource API for instant playback
- Audio starts playing as soon as ~1KB arrives instead of waiting for full download
- Browser-aware format detection (webm+opus for Firefox, mp3 for Chrome)
- Falls back to buffered download if MediaSource not supported
- Updated speakText() and speakTextQueued() to use streaming
- Cache blobs instead of Audio objects for cleaner replay
2026-01-28 07:53:11 -05:00
c6e6e81c3c Fix artifact API - use correct parameter and field names
Correct the artifact implementation to match Unsandbox API:
- Request parameter: return_artifact (boolean, singular)
- Response field: artifacts (array, plural)
- Data field: content_base64 (not data/content)

Changes:
- Backend: Changed artifacts to return_artifact in request body
- Frontend: Use return_artifact in execute request
- Frontend: Look for artifacts array in response (not artifact singleton)
- Frontend: Decode content_base64 field (not data/content)
- Frontend: Use filename field (primary) over name
- Remove debug console.log statements
- Update CLAUDE.md with correct API contract

The API parameter is singular but response is plural - this is intentional
design by Unsandbox API. Request enables artifact collection, response
returns array of generated artifacts.
2026-01-20 09:07:25 -05:00
acee097d3b Add debug logging for artifact structure
Add console.log statements to see actual artifact object structure:
- Log artifacts array when received
- Log each artifact object and its keys
- Log download attempt with artifact keys and data presence

This will help diagnose why artifacts show metadata but fail on download/view.
2026-01-20 08:50:29 -05:00
7a54952191 Fix artifact handling - use base64 from response payload
Artifacts are returned as base64-encoded data directly in the job response
payload, not as URLs. Previous implementation incorrectly tried to fetch
artifacts from URLs via a proxy endpoint.

Changes:
- Remove /api/code/artifacts proxy endpoint (not needed)
- Update downloadArtifact() to decode base64 and trigger download
- Update viewArtifact() to decode base64 and display inline:
  * Images: rendered as data URLs (data:image/png;base64,...)
  * Videos: decoded to blob URLs with controls
  * Text: decoded and displayed in <pre> blocks
- Update CLAUDE.md with correct artifact format and implementation details
- Add artifact response format example showing base64 data structure

Artifact format in response:
{
  "artifacts": [{
    "name": "output.png",
    "type": "image/png",
    "data": "base64string...",
    "size": 12345
  }]
}
2026-01-20 08:38:37 -05:00
5576179ffa Add comprehensive artifact support for code execution
Implement full artifact support for Unsandbox code execution, enabling
download and inline viewing of generated files (binaries, images, videos).

Backend changes (app.py):
- Update /api/code/execute to accept artifacts parameter
- Add /api/code/artifacts/<path> proxy endpoint for authenticated downloads
- Use SDK's _make_request for full parameter support
- Support artifacts in execution request body

Frontend changes (templates/chat.html):
- Pass artifacts=true in all code execution requests
- Display artifacts section with file info (name, type, size)
- Add download button for all artifact types
- Add view button with inline display for images/videos (disabled for binaries)
- Implement formatFileSize, downloadArtifact, viewArtifact helper functions
- Images and videos render directly in chat
- Text files display in formatted <pre> blocks

Documentation (CLAUDE.md):
- Document artifact support section
- List supported artifact types
- Describe frontend and backend features
- Update frontend integration notes

Artifact types supported:
- Compiled binaries (executables from C, C++, Rust, Go, etc.)
- Images (PNG, JPG, GIF, SVG)
- Videos (MP4, WebM)
- Text/data files (JSON, CSV, TXT)
2026-01-20 08:34:35 -05:00
331c11e8f7 Only truncate large code blocks on page refresh, not during streaming 2025-12-15 11:31:43 -05:00
6e279c0ed5 Use backend proxy for Unsandbox API calls to keep API key secure 2025-12-07 14:54:35 -05:00
ff9d8011a6 Fix model/voice localStorage persistence on page refresh
Remove race condition where syncDropdownsAndQueryString() was called before
dropdowns were populated, causing empty values to overwrite localStorage.
Model and voice restoration now happens only in populateModelDropdown() and
populateVoiceDropdown() after async fetch completes.
2025-12-07 11:29:06 -05:00
0d19e0b9ce Fix model selection persistence: populate both dropdowns, validate stored value 2025-12-07 10:17:43 -05:00
589406d11d Fix CORS proxy URL to cors-proxy.uncloseai.com 2025-12-07 08:49:28 -05:00
19b8ce4037 Add external image URL support via CORS proxy
- Fetch external images through proxy.unturf.com (respects robots.txt)
- Convert fetched images to base64 for vision API
- Cache both fetched images and descriptions
- Shows "Fetching image..." for external URLs, "Generating description..." for base64
- Handles 403 responses when blocked by robots.txt
2025-12-07 08:47:36 -05:00
d9976ffe31 Fix image hover: use mouseover instead of mouseenter for event delegation 2025-12-07 08:39:58 -05:00
bd2dbf7ed5 Add vision model support with auto alt-text on image hover
Backend:
- Track VISION_MODELS list at startup from available endpoints
- Add is_vision_model() to detect vision-capable models (*-vl*, *vision*, gpt-4o)
- Add extract_base64_from_img_tag() and build_message_content() helpers
- Modify chat_gpt() to include base64 images for vision models
- Add GET /vision endpoint for vision availability status
- Add POST /vision/describe endpoint for image alt-text generation

Frontend:
- Check vision availability on page load via /vision
- Add hover event delegation on chat images
- On hover: call vision model, cache result, set img.title and img.alt
- Shows cursor:wait while loading description
2025-12-07 08:36:47 -05:00
030b1cc447 Use only stderr for code auto-fix error detection
Update code execution error detection to use stderr exclusively
instead of checking both stdout and stderr. This aligns with the
Unsandbox API's proper stream separation where:
- stdout is for program output
- stderr is for errors/warnings

Changes:
- Remove stdout from error detection logic
- Only trigger auto-fix when exit_code != 0 AND stderr is non-empty
- Send only stderr to /api/fix-code endpoint

This prevents false positives where stdout contains normal output
that was previously being treated as error content.
2025-12-01 11:49:33 -05:00
22ed72da7e Store auto-exec attempt on code block to avoid empty DOM elements
- Use codeBlock.dataset.autoExecAttempt to pass attempt number
- executeCodeBlock transfers attempt to results container
- No longer pre-creates empty results container
- Clean up data attribute after use
2025-11-30 15:17:27 -05:00
5c25229429 Fix classList check for non-element nodes
- Add null check for classList before calling contains()
- Handles case where nextSibling might be a text node
- Prevents 'classList is undefined' error
2025-11-30 14:56:04 -05:00
36e713147a Fix DOM insertion error in auto-exec results container
- Correctly insert results container after button container
- Use buttonContainer.parentNode.insertBefore() instead of preElement
- Add proper styling when creating results container
- Fixes 'Child to insert before is not a child of this node' error
2025-11-30 14:47:17 -05:00
53f3e66943 Post auto-fixed code as new message and auto-execute
- Post fixed code to chat so user can see what was changed
- Store fix data in window.pendingAutoExec for message handler
- Auto-trigger execution on newly posted code block
- Preserve attempt counter across fix iterations
- User now sees: original error → fixed code posted → auto-execution → results
2025-11-30 14:45:43 -05:00
09c6f62083 Fix auto-retry: execute fixed code directly without posting to chat
- Remove chat message posting that prevented automatic re-execution
- Fixed code now executes directly using same blockElement
- Simplify re-execution flow with direct recursive call
- Results display in same execution results container
2025-11-30 14:42:06 -05:00
52cb0e4fdf Fix auto-retry: check stdout for errors (Python sends tracebacks to stdout) 2025-11-30 14:38:59 -05:00
474b12f175 Add full job response logging to debug stderr field 2025-11-30 14:36:18 -05:00
d79a9c8117 Add debug logging for code execution auto-fix retry logic 2025-11-30 14:31:50 -05:00
6400a5eacb Add automatic code error fixing feature
Implements an AI-powered auto-fix system that automatically attempts to
repair code execution errors up to 3 times.

Backend changes (app.py):
- Add /api/fix-code endpoint that uses MODEL_1 (Hermes) to analyze
  stderr output and generate corrected code
- System prompt instructs AI to output only raw fixed code without
  explanations or markdown formatting
- Accepts code, language, stderr, exit_code, and attempt number

Frontend changes (templates/chat.html):
- Modify executeCodeBlock() to detect failed executions (exit_code !== 0)
- Track fix attempts per code block (max 3) using dataset attributes
- Call /api/fix-code when errors are detected
- Display fixed code as new chat message with markdown formatting
- Automatically re-execute the corrected code recursively
- Show progress messages during auto-fix attempts
- Display warning when max attempts (3) are exhausted

Features:
- Fixes common issues: missing imports, syntax errors, type errors
- Posts fixed code to chat for transparency
- Prevents infinite loops with 3-attempt limit
- Graceful error handling with user-friendly status messages
2025-11-30 11:59:46 -05:00
2a85bbe53e Make logged-in username clickable to profile page
- Chat messages: logged-in user's name links to /profile
- User lists (sidebar): logged-in user's name is clickable link
- Previous messages: same profile link logic applied
- Other users still link to /profile/username (future feature)

Anywhere the logged-in user's name appears, it now links to their
profile settings page for quick access to logout and username change.
2025-11-30 10:02:58 -05:00
41e9e8ae7c Switch code execution to Unsandbox API
- Update CODE_EXEC_URL from code.ai.unturf.com to api.unsandbox.com
- Fix response field handling for Unsandbox API format (flat structure)
- Add exit code display with color coding (green=0, red=error)
- Update displayExecutionResults to handle stdout/stderr/exit_code at top level
- Simplify error handling for timeout/cancelled jobs
- Add comprehensive Unsandbox API documentation to CLAUDE.md
2025-11-30 06:08:17 -05:00
d46818b5dd
Redesign user interface across all pages (#42)
* Redesign UI: unified design system across all pages

- Replace scattered inline CSS with comprehensive single style.css
- Implement modern design system:
  - System font stack (-apple-system, Segoe UI, etc.)
  - Consistent spacing scale (4px base)
  - Unified color tokens for light/dark themes
  - Reusable component classes (buttons, cards, badges, forms)

- Update all templates to use new CSS classes:
  - browse.html: Less chunky, better space usage with room-grid
  - index.html: Cleaner centered card layout
  - auth.html: Streamlined 4-step flow with gradient background
  - profile.html: Modern settings interface
  - search.html: Browse-style card layout

- Chat page improvements:
  - Tighter layouts (240px/280px sidebars instead of 15%/25%)
  - Better message spacing
  - Improved code blocks with proper padding
  - Cleaner utility belt

- Better responsive design and dark mode support

* modified:   app.py
	modified:   templates/base.html
	modified:   templates/profile.html

* Revert standalone pages to original design

- Browse, index, auth, profile restored to original inline CSS
- Chat page improvements preserved in style.css
- Search page still uses improved card layout

* Add dark mode support to index and browse pages

- index.html now supports dark mode with CSS variables
- browse.html now supports dark mode with CSS variables
- Theme persists from localStorage across pages

* Remove theme toggle from chat page

- Theme toggle button removed from desktop chat sidebar
- Theme toggle button removed from mobile chat modal
- Theme management now done via profile page only

* Make usernames clickable links to profile pages in chat

* Update search page to match browse page layout and CSS

* Fix chat layout positioning

* Fix room list auto-update when title changes

* Fix new room creation appearing in sidebar

- Add socketio.emit in create_room_api() to broadcast new rooms
- Update socket handler to add new rooms to sidebar dynamically
- Rooms now appear without hard refresh

* Fix /title and /cancel commands being sent to LLM

- Add missing return statements after command handlers
- Commands now properly terminate message processing
- Prevents commands from being interpreted as chat messages

* Make usernames in user lists clickable links to profiles

- Update updateUserLists() to create links for all usernames
- Add hover effect CSS for user list links
- Works for both active and inactive users
- Works for both desktop and mobile views

* Revert user list profile links and update profile page layout

- Remove profile links from user lists (no backend route for other users)
- Update profile page to full-screen layout like browse page
- Add header with navigation buttons
- Remove centered container, use full-width layout
- Add box shadows to sections for visual separation

* Convert all flexbox layouts to CSS grid

- Replace all display: flex with CSS grid equivalents
- Update templates: profile, browse, search, index, auth
- Update static CSS for consistent grid usage
- Use grid-template-columns, grid-auto-flow, and place-items
- Improve layout consistency across all pages

* Fix chatroom horizontal scrolling

- Add overflow-x: hidden to #chat-container and #chat to prevent horizontal scroll
- Add word-break and overflow-wrap to message content for text wrapping
- Change pre tags from overflow: hidden to overflow-x: auto for individual scrolling
- Add min-width: 0 to grid containers to prevent overflow
- Code blocks can now scroll individually while chatroom wraps content

* Remove duplicate CSS variables and fix XSS vulnerability

- search.html: Remove inline styles, link to style.css
- index.html: Remove duplicate CSS variable blocks, link to style.css
- browse.html: Remove duplicate CSS variable blocks, link to style.css
- chat.html: Fix XSS vulnerability in room list updates
  - Use textContent/createTextNode instead of innerHTML for user data
  - Use DOM methods instead of string concatenation
  - Encode URL components with encodeURIComponent
  - Extract user count from textContent instead of innerHTML regex

* Merge duplicate CSS rules and replace inline styles with design system

style.css:
- Merge duplicate html, body rules (lines 137-143 and 159-167)
- Consolidate typography and layout properties in single rule
- Remove duplicate BASE LAYOUT section

profile.html:
- Replace style.display mutations with classList API
- Add .availability-indicator.show CSS rule for visibility
- Use classList.add('show') and classList.remove('show')
- Consistent with existing .message.show pattern

browse.html:
- Replace hard-coded gradient colors with CSS variables
- Use var(--gradient-start) and var(--gradient-end) for buttons
- Replace #667eea with var(--button-primary) for tabs and room names
- Remove inline .room-badge styles, use .badge .badge-public/.badge-private
- Apply existing badge classes from style.css for dark mode support

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Russell Ballestrini <russell@unturf.com>
2025-11-12 09:24:49 -05:00
e4cabf4be6
otp (#41)
* Add email OTP authentication system and private room management

## Authentication System
- Implement email OTP-based authentication with User and OTPToken models
- Add auth.py module with OTP generation, email sending, and session management
- Create authentication endpoints: /auth/send-otp, /auth/verify-otp, /auth/claim-name, /auth/status, /auth/logout
- Add authentication modal UI with email verification and display name claiming
- Support SMTP configuration via environment variables (optional)

## Room Privacy & Ownership
- Add is_private, is_archived, owner_id, and forked_from_id fields to Room model
- Implement private rooms (single-user, owner-only access)
- Add room forking: users can fork public rooms to public or private
- Add room archive/delete endpoints (owner-only operations)
- Implement access control for private room viewing

## UI Improvements
- Add public/private room tabs in sidebar
- Show authentication prompt in private rooms tab for non-authenticated users
- Add room action buttons (fork, archive, delete) with proper permissions
- Update homepage with statistics (public/private rooms, active users, active rooms)
- Remove model/voice from URL query strings, use localStorage exclusively

## Database Migration
- Create migration 2025011100 for User, OTPToken tables and Room model updates
- Add indexes for email, display_name, is_private, is_archived, owner_id

## Breaking Changes
- URL parameters now only include username (model/voice moved to localStorage)
- Private rooms require authentication to access
- Room creation can now require authentication (for private rooms)

* Update README with authentication and private room documentation

* Simplify README to be less verbose

* Add missing session import to fix linter errors

* Fix migration dependency to resolve multiple heads conflict

* asdf

* Fix SQLAlchemy auto-correlation error in homepage statistics query

* Change tagline from AI-Powered to Machine Learning Powered

* Add dedicated authentication page instead of modal

- Create new /auth route with full-page authentication flow
- Remove modal code from index.html
- Update Sign in link to point to /auth page
- Auth page has 4-step flow: email, OTP, display name, success
- Better UX with gradient background and cleaner design

* Fix migration: remove batch_alter_table to avoid circular dependency

- Use op.add_column() directly instead of batch_alter_table()
- Remove foreign key constraints (defined in models, not needed in migration)
- User and OTPToken tables created by db.create_all() in make init-db
- Fixes CircularDependencyError during migration

* Fix migration: check if columns exist before adding

- Use inspector to check existing columns and indexes
- Only add columns/indexes if they don't already exist
- Handles case where db.create_all() was run before migration
- Fixes 'duplicate column name' error

* Add profile page, room browsing, and updated_at timestamp

Features:
- Profile page with username change and dark/light mode settings
- Browse page for discovering public and private rooms
- Room updated_at timestamp (integer Unix epoch) that updates on new messages
- Dynamic room tabs based on current room type (public/private)
- Fork and delete room actions moved to right sidebar utility belt
- Remove archive feature and success alerts from room actions

Technical changes:
- Add updated_at column to Room model (integer timestamp)
- Add /profile route with authentication requirement
- Add /browse route for room discovery
- Add API endpoints for username availability check and update
- Update room.updated_at on message creation in app.py:1189
- Wider right sidebar (25% instead of 15%) for better button layout
- Profile link on homepage and browse page for authenticated users

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: russell@unturf. <russell@unturf.com>
2025-11-11 22:56:58 -05:00
45f183df37
Add AI-powered artifact filename generation (#39)
* Add AI-powered artifact naming for compiled binaries

Implements intelligent filename generation for downloaded binaries using
Hermes AI to analyze code and generate meaningful 1-3 word filenames.

Changes:
- Add /api/generate-artifact-name endpoint that uses MODEL_1 (Hermes)
- Modify frontend to call naming API before download
- Add ENABLE_AI_ARTIFACT_NAMING environment variable (enabled by default)
- Filenames are descriptive (e.g., "fizzbuzz", "hello-world", "prime-checker")
- Graceful fallback to "compiled_binary" if naming fails or is disabled

The feature can be disabled by setting ENABLE_AI_ARTIFACT_NAMING="false"
in environment variables.

* Rename env var to ENABLE_CODE_GEN_FILENAMES

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 17:43:52 -05:00
14bfce710d
Move download binary button next to Run button (#38)
- Reposition download button from output area to button container
- Place next to Copy and Run buttons with consistent styling
- Button hidden by default, shown only when artifact available
- Remove colored background to match other action buttons

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 16:41:55 -05:00
a260b5fa02
Handle cancellation and timeout recovery (#37)
* Enable binary downloads on timeout/cancellation

When code execution times out or is cancelled, the compiled binary
may still be available. This change ensures displayExecutionResults()
is called for timeout/cancelled jobs, allowing users to download
the binary artifact even when execution doesn't complete normally.

* Fix partial output display for timeout/cancellation

Previous commit broke partial output display by passing job.result
directly to displayExecutionResults(), but for timeout/cancelled jobs
the output is in partial_output field, not stdout.

Now properly maps partial_output to stdout before displaying, so users
see both the error message and any output that was captured before
timeout/cancellation, plus binary downloads if available.

* Add debugging for missing artifact on timeout/cancel

Check multiple possible locations for artifact:
- job.artifact (top level)
- job.result.artifact (nested)

Add console logging to see full job structure when timeout/cancel
occurs so we can understand why the binary isn't appearing.

* Try fetching artifact from separate endpoint on timeout/cancel

When timeout/cancel occurs, the artifact isn't in the job response.
Try fetching from /jobs/{job_id}/artifact endpoint as a fallback.

This explores whether the executor service has a separate artifact
endpoint that we can use to retrieve compiled binaries even when
execution is cancelled or times out.

* Remove debug logging, document artifact limitation

Removed console.log debugging statements now that we've confirmed
the executor service doesn't include artifacts in timeout/cancelled
responses and doesn't have a /jobs/{job_id}/artifact endpoint.

Kept the artifact fetching code with comments for future compatibility
if the executor service adds this feature.

Current limitation: Binary downloads only work for completed executions,
not for timeout/cancelled ones. The binary exists but the executor
service doesn't return it.

* Try multiple artifact endpoint patterns for timeout/cancel

When artifact isn't in the job response, try fetching from:
- /artifacts/{job_id}
- /jobs/{job_id}/artifact
- /jobs/{job_id}/download
- /jobs/{job_id}/binary
- /download/{job_id}
- /binary/{job_id}

Handles both JSON responses and direct binary responses. Logs
each attempt to console so we can see which endpoint (if any) works.

* Revert endpoint searching - artifact should be in /jobs/{id}

According to OpenAPI spec, there are no separate artifact endpoints.
The artifact should be included in GET /jobs/{id} response for ALL
job statuses (completed, cancelled, timeout).

Current limitation: The executor service only includes result.artifact
for "completed" status, not for "cancelled" or "timeout" status.

The frontend code is correct - it checks job.artifact and
job.result.artifact. The issue is the executor service needs to
include the artifact in cancelled/timeout responses.

* Add debug logging for cancelled/timeout artifact checks

Since the executor service was supposedly patched to include artifacts
in GET /jobs/{id} responses even for cancelled/timeout jobs, add
detailed logging to verify:

1. What the full job response looks like
2. Whether artifact is at job.artifact or job.result.artifact
3. Artifact details if found

This will help determine if the patch is deployed and working.

* Add test-artifact Makefile target for testing executor API

Tests binary artifact retrieval from code executor service:
- Compiles C code with return_artifact=true
- Extracts base64 artifact from response
- Decodes and executes the binary

Can test against different URLs:
  make test-artifact URL=https://code.ai.unturf.com

Tested against production and confirmed:
- Artifacts ARE included for completed jobs
- Artifacts are NOT included for cancelled/timeout jobs (even with
  return_artifact=true). Exit code 137 indicates SIGKILL.

* Document confirmed limitation - no artifacts for cancelled jobs

Tested against production executor API (make test-artifact) and confirmed:
- Cancelled jobs return exit_code 137 (SIGKILL)
- NO artifact field in response (neither job.artifact nor job.result.artifact)
- Artifacts only returned for fully completed jobs

Code still checks for artifacts in case this limitation is fixed
in the future, but currently binary downloads will not work for
cancelled/timeout executions.

To fix: Executor service needs to include compiled binary in
response even when execution is killed (compilation succeeded).

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 16:34:05 -05:00
108b6e270f
Add binary download support for compiled code (#35)
- Request compiled binaries via return_artifact parameter
- Add "Download Binary" button when artifact is available
- Support base64 decoding and browser download
- Handle artifact errors gracefully
- Works with C, C++, Rust, Go, Java, and other compiled languages

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 13:38:41 -05:00
ccedf063a0
Fix action buttons position - insert after <pre> not inside it (#36)
Problem:
- Buttons were being inserted as children of <pre> element
- This caused buttons to appear inside code blocks with wrong styling
- Template caching made changes appear to require "two commits"

Solution:
- Change insertion point from block.parentNode to preElement.parentNode
- This places buttons as siblings of <pre>, not children
- Add TEMPLATES_AUTO_RELOAD=True to prevent Flask template caching

Technical Details:
- block is the <code> element
- block.parentNode is the <pre> element
- preElement.parentNode.insertBefore puts buttons after <pre>
- Previous code put buttons inside <pre> after <code>

DOM Structure Before:
  <pre>
    <code>...</code>
    <buttons> <!-- Wrong: inside pre -->
  </pre>

DOM Structure After:
  <pre>
    <code>...</code>
  </pre>
  <buttons> <!-- Correct: after pre -->

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 13:38:03 -05:00
76b8058e92
Move copy and run buttons below code (#34)
* Move code block buttons below code instead of above

- Modified addCopyButtonToCodeBlock to insert button container after code block
- Updated truncateCodeBlock to remove duplicate buttons before adding its own
- Ensures clean button placement for both regular and truncated code blocks

* Refactor code block button rendering for efficiency

- Process blocks in optimal order: truncate → highlight → line numbers → buttons
- Eliminate redundant button creation/removal cycle
- truncateCodeBlock now only truncates and returns boolean
- addCopyButtonToCodeBlock handles all button creation (including Show More)
- Buttons always appear below code blocks after full processing

This prevents wasteful creation and immediate deletion of buttons for truncated blocks.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 13:22:40 -05:00
bafd2194ab
- Add download button next to Play button for all messages (#33)
* Add download button for TTS audio

- Add download button next to Play button for all messages
- Button is initially hidden and appears after TTS audio is generated
- Works for both manual play and auto-play modes
- Works for both regular and streaming messages
- Handles cached audio properly
- Download filename includes message ID and voice name

* Refactor: Extract download button logic into helper function

- Create enableDownloadButton() helper to eliminate code duplication
- Replace 4 identical blocks (56 lines) with 4 function calls (4 lines)
- Improves maintainability and follows DRY principle
- Handles both cached and fresh audio in both speakText functions

* Remove hardcoded voice fallbacks, use API or empty list

- Remove hardcoded voice options from HTML dropdown
- Remove all fallbacks to default voices (tts-1:onyx)
- If voices API fails, leave dropdown empty instead of falling back
- localStorage persistence for voice selection already implemented
- Voices API caching already working (1-minute cache like models)
- Voice selection now purely driven by API response

* Fix: Make download button visible after TTS audio loads

- Add download button to previous_messages handler (was missing)
- Change display from "" to "inline-block" for visibility
- Download button now appears properly after TTS processes

* Add debug logging for download button issue

- Add console.log to trace enableDownloadButton execution
- Change === to == for messageId comparison (handle type coercion)
- Log wrapper status, button status, and ID matching
- This will help identify why download button doesn't appear

* Remove debug logging, keep type coercion fix

- Remove console.log statements now that issue is identified
- Keep == comparison (was the actual fix)
- Add comment explaining why == instead of ===
- dataset.messageId is string, messageId param is number

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 09:56:57 -05:00
6bc896b9b0 Fix TTS voice selection validation breaking API calls
Remove obsolete VALID_VOICES validation that was rejecting the new
"model:voice" format from the voices endpoint integration. The old
validation expected simple voice names like "onyx" but the new format
uses "tts-1:onyx", causing validation to fail and produce malformed
API requests that returned HTTP 400 errors.

Changes:
- Remove VALID_VOICES constant (no longer needed)
- Update syncInputsAndQueryString() to accept any voice value from dropdown
- Default to "tts-1:onyx" format if no value present

Fixes the TTS errors seen in production where voice selection was
failing with HTTP 400 status.
2025-11-09 15:32:38 -05:00
Claude
d7ea04a3f9
Integrate voices endpoint with dynamic model and voice selection
Update TTS implementation to fetch available voices from the API and
support multiple TTS models:

- Add VOICES_API_URL constant for /v1/voices endpoint
- Create populateVoiceDropdown() to dynamically populate voice options
- Group voices by model using optgroups in the dropdown
- Implement voice fetching with localStorage caching (1 minute)
- Update speakText() to parse model:voice from dropdown value
- Update speakTextQueued() to use dynamic model and voice
- Add backward compatibility for legacy voice-only format
- Update both desktop and mobile voice selectors
- Add fallback to tts-1:onyx if voice fetch fails

Voice dropdown now displays all available models (tts-1, tts-1-hd,
tts-1-silero, tts-1-kokoro) with their respective voices organized
by optgroups for better UX.
2025-11-09 20:08:37 +00:00
Claude
6fa1b15188
Add auto-growing textarea for chat input
- Textarea now automatically expands as user types multiline messages
- Resets to minimum height after message is sent
- CSS: Set min-height (60px) and max-height (400px) with auto overflow
- Removed fixed rows attribute to allow dynamic height
- Disabled manual resize to prevent user confusion
- Provides better UX for composing longer messages
2025-11-08 23:02:24 +00:00
Claude
5a74092c77
Improve code execution output styling for dark mode
Added CSS variables for code execution result colors that adapt to theme:
- --text-info: Blue for informational text (language labels)
- --text-success: Green for successful output
- --text-error: Red for errors and warnings

Updated JavaScript to use CSS variables instead of hard-coded colors,
ensuring proper contrast and readability in both light and dark modes.
2025-11-08 17:03:50 +00:00
Claude
5f01ffbef1
Move inline CSS to stylesheet
- Moved all theme-related inline styles to CSS rules
- Created proper selectors for labels, inputs, and buttons
- Added utility-belt class to mobile menu for consistent styling
- Removed redundant inline style attributes
2025-11-08 15:41:45 +00:00
Claude
314651e910
Add dark/light mode theme switcher with localStorage persistence
- Added CSS variables for light and dark themes
- Implemented theme toggle buttons in both desktop sidebar and mobile menu
- Added JavaScript logic to switch themes and persist choice in localStorage
- Applied dark theme styling to all UI elements including code blocks
- Theme is applied immediately on page load to prevent flash
2025-11-08 15:39:23 +00:00
e74827061e modified: templates/chat.html 2025-11-08 06:56:18 -05:00
b95390f34c Implement async code execution with smart polling and cancel button
- Switch from sync /execute to async /execute/async with polling
- Poll intervals: 300ms, 750ms, 1450ms, 2350ms, 3000ms, 4600ms, 6600ms+
- Show cancel button after 3 seconds if job still running
- Display partial output when cancelled or timed out
- Add Copy and Run buttons to bottom of truncated code blocks (next to Show More)
- Prevents accidental cancels and DoS from spam-clicking
2025-11-07 19:32:47 -05:00
4f3dd882ba modified: CLAUDE.md
modified:   templates/chat.html
	new file:   test_code_execution.html
2025-11-07 13:31:27 -05:00
f0c7ea2cf5 Add copy button to messages and fix model/voice persistence
- Add copy button after edit button for all messages
- Fix model/voice settings persistence when creating new rooms
- Save model/voice selections to localStorage for better state management
- Ensure settings are loaded from localStorage if not in URL parameters
2025-09-09 17:57:16 -04:00