Commit graph

238 commits

Author SHA1 Message Date
f7862bc54a
feat(profile): let guests manage their localStorage username
/profile previously required auth and returned a raw JSON 401 for
guests. Now it renders a guest variant: edit guestUsername in
localStorage, clear it to re-prompt on next visit, or sign in to
claim a permanent username. Unifies the two username flows
(authed DB display_name vs guest localStorage) under one page.
2026-06-10 12:50:51 -04:00
d405ebc6f9
ui: drop misleading homepage stats (active users, active rooms)
Active Users counted all-time distinct UserSession usernames, not anyone
currently online. Active Rooms counted any room that ever received a
single message, with no decay. Both read as live metrics but aren't.

Keep Public Rooms and (when signed in) Private Rooms — those are real
counts users can verify by browsing.
2026-06-02 09:19:11 -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
8110080a4f fix(code-exec): surface real Unsandbox errors instead of flat 500
/api/code/execute and /api/code/jobs (GET+DELETE) swallowed every
exception into a print() and returned a generic 500, making the
"Failed to execute code" failure undebuggable on deployed boxes
where buffered stdout is lost.

Add _unsandbox_error_response helper: passes the upstream HTTP
status + response body through to the JSON response and prints a
full traceback. Credentials live in request headers, never in
response bodies, so echoing the upstream body exposes no secrets.
2026-05-18 19:07:02 -04: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
b53ee2168b modified: app.py 2026-01-20 08:58:19 -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
27a0df3d12 Migrate to official Unsandbox Python SDK
Replace manual HMAC authentication with official Unsandbox Python SDK (un.py).
Simplifies code execution proxy endpoints by using SDK methods: execute_async,
get_job, and cancel_job. Removes ~40 lines of manual HTTP/auth code.

Changes:
- Add official Unsandbox Python SDK (un.py)
- Refactor app.py proxy endpoints to use SDK methods
- Update CLAUDE.md documentation with SDK setup and usage
- Remove manual HMAC signing code
- Maintain backward compatibility with existing API endpoints
2026-01-20 08:21:58 -05:00
0d5d2c27be Switch Unsandbox API auth to HMAC-SHA256 with public/secret keys
Replace simple Bearer token auth with HMAC-SHA256 signature scheme:
- UNSANDBOX_PUBLIC_KEY for account identification (Bearer token)
- UNSANDBOX_SECRET_KEY for request signing (never transmitted)
- X-Timestamp header for replay attack prevention
- X-Signature header with HMAC-SHA256(secret, ts:method:path:body)
2025-12-28 13:44:38 -05:00
5329bccdec Add Open Graph and Twitter Card meta tags for social sharing
- Add helper functions to extract first image and generate description from chat messages
- Update base.html and index.html with og:image, og:description, twitter:card meta tags
- Chat rooms now use first image from messages for unfurling instead of site logo
- Description shows first 500 chars of room content for link previews
- Add default OG image (black with OC) as fallback when no image found
2025-12-15 08:17:01 -05:00
50404f62d9 Fix F824 lint error and add lint instructions to CLAUDE.md 2025-12-07 15:34:35 -05:00
8c128878c4 Fix is_base64_image() to detect all image formats, add debug logging
- is_base64_image() now detects any base64 image (jpeg, png, gif, webp, etc.)
  not just the hardcoded jpeg/png patterns
- Added [Vision] debug logging to trace image fetch/save flow
2025-12-07 13:58:47 -05:00
56800afae5 Fix SQL LIKE query for URLs with special characters (%, _)
URLs like eBay images contain % and _ which have special meaning in SQL
LIKE patterns. Added escape_like_pattern() helper to escape these chars.
This fixes saved base64 images not being found on refresh.
2025-12-07 13:51:40 -05:00
de5bdaaa68 Vision: send only most recent image, keep all text history
- Find the most recent image message
- Include full text conversation history for context
- Only send base64 for the most recent image
- Skip older images entirely (no useful text in them)
2025-12-07 11:44:56 -05:00
305375d9e6 Limit vision model to 2 most recent images to prevent slow/hanging requests
Multiple large base64 images can overwhelm the vision model. Now we:
1. First pass: identify the 2 most recent image messages
2. Second pass: build chat history, skipping older images
2025-12-07 11:42:53 -05:00
38da58c33e Cache fetched external images to avoid re-fetching
- Add find_saved_base64_for_url() to lookup existing saved base64 in DB
- Check for existing saved version before fetching external images
- Prevent duplicate saves in save_fetched_image_as_message()
- Use in-memory cache for faster repeated lookups within same session
2025-12-07 11:18:01 -05:00
116fac4c90 Fix DetachedInstanceError: use room_name parameter instead of room.name
Replace room.name with room_name in chat_gpt, chat_claude, and chat_llama
functions to avoid accessing SQLAlchemy objects outside session context.
2025-12-07 10:59:13 -05:00
da9ed50d38 Fix DetachedInstanceError: save room_id early, use room_name parameter 2025-12-07 10:22:57 -05:00
5928ad3d9d Save fetched external images as new messages in database
- save_fetched_image_as_message() creates a new message with base64 content
- build_message_content() now accepts room_id to persist fetched images
- Fetched images saved with username "system" (added to SYSTEM_USERS)
- Prevents re-fetching: once fetched, base64 version is in chat history
2025-12-07 09:01:01 -05:00
51de5991c4 Add server-side fetching of external images for vision model chat context
- extract_external_image_url() to find http/https URLs in img tags
- fetch_external_image_as_base64() fetches via CORS proxy, converts to base64
- build_message_content() now handles both base64 and external image URLs
- Caches fetched images to avoid re-fetching
- Uses cors-proxy.uncloseai.com for robots.txt compliance
2025-12-07 08:58:18 -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
31fc7946a0 Improve code auto-fix: prefer Qwen Coder with Hermes fallback
Update /api/fix-code endpoint to try MODEL_3 (Qwen Coder) first for
better code generation, with graceful fallback to MODEL_1 (Hermes) if
MODEL_3 is unavailable or returns errors.

This ensures the auto-fix feature works reliably even when specialized
code models are temporarily unavailable (e.g., 502 errors).
2025-11-30 12:04:51 -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
d8a7cc89b6 Fix gevent fork error and improve OTP email handling
- Disable Flask reloader to prevent gevent threading conflicts
- Remove SMTP configuration guard, attempt localhost:25 first
- Add graceful fallback chain: localhost → configured SMTP → console
- Catch socket errors and continue workflow in development
- Make SMTP environment variables truly optional
2025-11-30 06:53:51 -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
3f9b1827c7
Use underscores instead of dashes for AI-generated filenames (#40)
Updated the artifact filename generator to use snake_case (underscores)
instead of kebab-case (dashes) for better consistency with Python
naming conventions.

Changes:
- Updated AI prompt examples to show underscore format
- Modified filename processing to replace spaces with underscores
- Updated validation regex to accept underscores instead of dashes
- Changed docstring to reflect underscore usage

Examples: hello_world, prime_checker, array_sort (instead of hello-world, etc.)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 17:55:35 -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
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
Claude
39e39e80f1
Fix flake8 F824 errors - remove unused global declarations
Remove unnecessary global declarations for MODEL_CLIENT_MAP that are never reassigned
2025-11-10 19:39:36 +00:00
Claude
22db7a9a8a
Run black formatter on all Python files
Format code according to black style guidelines for consistency
2025-11-10 19:37:05 +00:00
Claude
fd78927e7c
Fix MODEL_X references to use dynamic model registry
When MODEL_X references (MODEL_0, MODEL_1, etc.) are used, the code now
properly looks up actual model names from the dynamic registry (MODEL_CLIENT_MAP)
instead of hardcoding "model" or requiring MODEL_NAME_X environment variables.

Changes:
- app.py: Look up models from MODEL_CLIENT_MAP for the specified endpoint
- guarded_ai.py: Query endpoints for actual model names at initialization
- guarded_ai.py: Use dynamic registry for MODEL_X lookups

This fixes the "model not found" error when using activities with MODEL_X
references like activity37.
2025-11-08 19:58:21 +00:00
Claude
8cebcbf118
Add MODEL_X reference support to app.py
Critical fix for activity model configuration:
- Handle MODEL_1, MODEL_2, MODEL_3 references in get_openai_client_and_model()
- Look up MODEL_ENDPOINT_{n}, MODEL_API_KEY_{n}, MODEL_NAME_{n} from environment
- Fall back gracefully to default model if MODEL_{n} not configured
- Matches implementation in research/guarded_ai.py

Fixes error: 'NoneType' object has no attribute 'chat'
This error occurred when activities tried to use classifier_model="MODEL_1"
but the app didn't know how to resolve the MODEL_X reference.

Now activity37 (programming languages) will work correctly with:
- classifier_model: "MODEL_1" (Hermes for classification)
- feedback_model: "MODEL_3" (Qwen3-Coder for code generation)
2025-11-08 19:47:32 +00:00
2811dad67b Refactor activity functions into separate activity.py module
Moved all activity-related functions from app.py to a new activity.py
module to improve code organization and maintainability. This reduces
app.py from 2852 lines to 1552 lines.

Changes:
- Created activity.py with 16 activity-related functions
- Updated app.py to import and initialize activity module
- Updated test_app.py to import activity module
- All 34 unit tests pass successfully
2025-10-22 20:23:06 -04:00
77e2c04ec0 Use selected model for activity AI operations
Pass the selected model parameter through the entire activity workflow
to ensure all AI operations (categorization, translation, feedback
generation, and grading) use the user's chosen model instead of
defaulting to the system default. Falls back to default when no model
is selected.
2025-10-22 20:04:20 -04:00
8a6170d57b Remove STFU system from feedback filtering
- Remove STFU check from app.py feedback filtering logic
- Update tests to remove STFU-specific test cases
- Simplify empty content filtering to just check for actual content
2025-08-11 17:20:59 -04:00
fca7addaa5 Fix battleship AI hallucination bug with skip_condition system
Add skip_condition logic to feedback prompts to prevent AI from generating
false ship destruction messages when no ships were actually destroyed.

Changes:
- Add skip_condition parameter support in provide_feedback_prompts()
- Support all_null, all_false, and all_true condition types
- Apply skip_condition to battleship Ship Status and Game Over prompts
- Add comprehensive unit tests covering all skip condition scenarios
- Test real battleship scenario that was causing hallucinations

This prevents the AI from creating false positive ship destruction messages
when metadata indicates no ships were actually sunk (all null values).
2025-08-11 17:04:17 -04:00
acdf653eaa Enhance user experience with multiple improvements
- Add username field to right sidebar and mobile modal with 'guest' default
- Implement real-time username sync with URL query string updates
- Add opencompletion.com button and new room creation in left sidebar
- Implement room name slugification (e.g. "a whole new world" → "a-whole-new-world")
- Create shared utils.js for common functions like slugify
- Add single search result auto-redirect functionality
- Remove redundant UI elements ("Create New Room" header, docs link)
- Preserve user settings (username, model, voice) across redirects and room creation

Technical improvements:
- Consolidated duplicate code into shared utility functions
- Enhanced search logic with parameter preservation
- Improved mobile/desktop sync for all input fields
- Better URL handling and query string management
2025-08-11 16:01:51 -04:00
dada6b3f22 Add comprehensive integration tests for streaming protocol
- Created test_streaming_protocol_simple.py with 3 passing tests
- Created test_streaming_protocol.py with comprehensive test suite
- Tests verify new protocol format with separate username/model fields
- Tests confirm content separation from metadata for clean TTS processing
- Added debug logging for Game Over feedback prompt
- All tests validate the streaming refactoring works correctly
2025-08-11 14:13:36 -04:00
4e122e708c Refactor streaming protocol to separate username/model from content
Backend changes:
- Send username, model_name, and is_first_chunk as separate fields
- Keep actual content separate from header formatting
- Cleaner separation of concerns in streaming protocol

Frontend changes:
- Build display content with header only for visual rendering
- Keep messageBuffers clean (content only) for TTS processing
- TTS now processes pure content without username headers

This fixes the issue where TTS was reading 'fxhp (model):' prefix
2025-08-11 13:46:51 -04:00
1808c915e1 Automatically return to activity chooser when activity completes
- Added activity_status emit with active: false when activity ends
- Now matches behavior of activity cancellation
- Users will automatically see activity chooser when activity finishes
2025-08-11 13:10:28 -04:00
f3d4dd89bc Add debug output for Game Over metadata filtering to investigate STFU bug when game actually ends 2025-08-11 12:47:25 -04:00
f90df2ae57 modified: activity_yaml_validator.py
modified:   app.py
	modified:   research/activity29-battleship.yaml
	modified:   research/activity29-testship.yaml
	modified:   research/guarded_ai.py
	modified:   tests/functional/test_activity_flows.py
	modified:   tests/functional/test_battleship_pre_script.py
	modified:   tests/functional/test_guarded_ai.py
	modified:   tests/unit/test_activity_yaml_validator.py
	modified:   tests/unit/test_app_feedback.py
	modified:   tests/unit/test_guarded_ai.py
2025-08-11 12:39:42 -04:00
d4d697db59 Implement per-prompt metadata filtering and fix battleship feedback system
Major improvements to battleship game feedback accuracy and user experience:

## New Multi-Prompt Feedback System
- Replaced single feedback with 3 specialized prompts: Shot Report, Ship Status, Game Over
- Each prompt has individual metadata filtering to see only relevant data
- Shot Report only sees hit/miss data, Ship Status only sees ship destruction data
- Added STFU token system to suppress empty messages (filtered out automatically)

## Technical Implementation
- Added per-prompt metadata_filter support in YAML structure
- Updated app.py and guarded_ai.py to handle prompt-specific filtering
- Legacy single-prompt system still works with transition-level filtering
- Added comprehensive test suite for feedback system validation

## User Experience Fixes
- Fixed TTS queue blocking JavaScript execution (async promises instead of await)
- Ship Status now correctly reports who destroyed which ship (role confusion fixed)
- Game Over only appears when game actually ends (no more random messages)
- Maintained dramatic storytelling while ensuring factual accuracy

## Battleship-Specific Improvements
- Ship destruction messages only appear when ships actually sink
- Clear separation of concerns: hits/misses vs ship destruction vs game over
- Eliminated false positive ship destruction reports
- Fixed role reversal where wrong player got credit for destruction

The battleship narrator now provides accurate, contextual feedback while preserving the dramatic naval warfare atmosphere.
2025-08-11 11:39:49 -04:00
e28dc11f04 Improve user experience with battleship feedback and auto-play TTS
- Fix battleship feedback perspective confusion with better Hermes prompting
- Add auto-play TTS button with localStorage persistence and queueing system
- Move activity controls below model/voice selectors in sidebar
- Add activity controls to mobile hamburger menu
- Fix model/activity dropdowns to stay within container bounds
- Filter activities API to only show .yaml/.yml files
- Clean up system message labels by moving to usernames (System (Feedback), System (Question))
- Apply black formatting to app.py
2025-08-11 09:34:29 -04:00
45a8f60cd2 Significantly improve test coverage with comprehensive integration tests
Major improvements:
- app.py coverage: 15% → 25% (+10 percentage points)
- research/guarded_ai.py coverage: 68% → 81% (+13 percentage points)
- Overall project coverage: 68% → 72% (+4 percentage points)

Key changes:
- Add comprehensive Flask integration tests for app.py activity functions
- Test real database operations with in-memory SQLite
- Add extensive guarded_ai.py error handling and client management tests
- Enhanced Makefile with comprehensive test targets
- Updated requirements-test.txt with flake8
- All 135 tests now passing with proper test coverage

The integration tests use real Flask environment, actual YAML processing,
and genuine database operations instead of mocks for accurate coverage.
2025-08-10 20:52:56 -04:00
1ca6f67c3d Fix code quality issues from PR review
- Add matplotlib.use("Agg") backend configuration to prevent runtime errors in headless environments
- Add error handling guards for script results that might return None
- Fix AI targeting logic to exclude already-fired cells in super hunter and hunter modes
- Update CLAUDE.md with matplotlib best practices
2025-08-10 16:01:58 -04:00
29573eaa75 Enhance battleship activity with improved user input handling and feedback
- Add user_response to pre-script metadata for better game state management
- Implement metadata_feedback_filter to control feedback data exposure
- Improve ship destruction announcements and game over messaging
- Add debug logging for ship sinking events
- Include test ship configuration file
2025-08-10 14:49:03 -04:00