Commit graph

65 commits

Author SHA1 Message Date
michael
d4ce5d99bc Fix audience_brief and research_objective dropped in Stage 2 persona generation
Stage 2 (detailed persona generation) was ignoring the audience brief and
research objective, causing the LLM to guess research context from demographics
alone. Now passes both values through to generate_persona() in all three
endpoints (generate-personas-full, complete-and-save-persona, complete-persona)
and auto-generates prompt customization via customize_persona_prompt() when
they are provided.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 08:40:17 -06:00
michael
850cb25067 Fix GPT-5 Responses API crash on reasoning items with None content
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 08:05:52 -06:00
michael
1708bd75a4 Remove SDK version logging on every Gemini call
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 14:30:42 -06:00
michael
7f4f659501 Bump google-genai to >=1.56.0 to fix aiohttp AssertionError
Version 1.52.0 has a known bug where aiohttp connector is None.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 14:07:38 -06:00
michael
d79c202e8f Fix NameError: use print instead of logger in get_gemini_client
logger is not defined at module level where get_gemini_client() lives.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 13:59:30 -06:00
michael
c9848210bb Add full traceback and SDK version logging for AssertionError debug
This will help identify where exactly the AssertionError is occurring
in the google-genai SDK and what version is installed on the server.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 13:49:47 -06:00
michael
5a825934f8 Add verbose exception debugging for empty error messages
Log full exception details: type, module, str, repr, args, and __dict__
to diagnose why Gemini errors are producing empty messages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 13:39:15 -06:00
michael
1a24c335f7 Add backend/persona_data/ to .gitignore
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 13:29:23 -06:00
michael
b50c0fa2a4 Fix empty error messages from Google GenAI SDK
Catch genai_errors.APIError specifically and extract e.code and e.message
attributes for proper error logging. The generic str(e) was returning empty
strings for Google API errors, making debugging impossible.

- Import google.genai.errors for specific exception handling
- Add APIError catch before generic Exception in generate_content()
- Add APIError catch before generic Exception in generate_contextual_response()
- Properly categorize errors by HTTP code for retry logic (429/500+ retryable)
- Fix time.sleep to await asyncio.sleep in contextual response handler

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 13:26:55 -06:00
michael
ca93d24ac5 Fix WebSocket auth error on initial page load
Skip WebSocket connection attempt when no auth token is available.
Previously, the WebSocketProvider would try to connect immediately
on mount (even on login page) with an empty token, causing
"Invalid token format" errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 12:15:04 -06:00
michael
6ee80e67aa Create fresh LLM clients per call instead of caching
The previous event loop tracking approach still caused issues - when replacing
a cached client, its garbage collection triggers aclose() which tries to close
the aiohttp session on the wrong event loop.

Simplest fix: create a fresh client for each call. The overhead is minimal
compared to the actual LLM API call, and this completely avoids all event
loop mismatch issues in ASGI environments.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 16:56:36 -06:00
michael
94f98b837b Add event loop tracking to LLM client getters
The previous lazy initialization fix wasn't sufficient - the genai.Client
internally caches async structures bound to the event loop at creation time.
With ASGI servers like Hypercorn, subsequent requests may come on different
event loop contexts, causing "Future attached to a different loop" errors.

Now tracks which event loop the client was created on and recreates it if
the loop has changed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 16:46:35 -06:00
michael
36e1752fea Remove __pycache__ files from git tracking
These files are already in .gitignore but were committed previously.
Removing them from tracking to prevent future conflicts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 13:28:19 -06:00
Michael Clervi
893b537b67 changed permissions 2025-12-19 19:26:16 +00:00
michael
45c7a52aeb Fix asyncio event loop mismatch in LLM service
The genai.Client and AsyncOpenAI clients were being created at module
import time, before the Quart/Hypercorn event loop existed. This caused
"Future attached to a different loop" errors when async calls were made,
resulting in autonomous focus group conversations stopping with
"excessive_silence".

Changed to lazy initialization - clients are now created on first use
within the running event loop context via get_gemini_client() and
get_openai_client() helper functions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 13:24:23 -06:00
michael
bb16165a83 Remove unused eventlet import and dead emit_with_ack function
Legacy code from Flask-SocketIO migration that's no longer used.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 11:51:23 -06:00
michael
1b98757676 Replace flask_jwt_extended imports with quart_jwt
Fixes ModuleNotFoundError on server by using the custom
Quart-compatible JWT implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 11:49:22 -06:00
michael
a6e1a8a307 Add backend directory creation to deploy script
Creates uploads/ and temp/ directories with correct ownership
before restarting the service, fixing systemd namespace errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 11:43:03 -06:00
michael
947acf780b Fix gitignore to allow src/lib and add missing taskCancellation utility
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 11:38:15 -06:00
michael
517f033ede Pin all Python dependency versions in requirements.txt
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 11:34:48 -06:00
michael
a32512a8f4 Add deployment script for git-based deployments
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 11:13:37 -06:00
michael
6b7f8763c0 Add environment variable to control local login availability
Add VITE_ENABLE_LOCAL_LOGIN env variable to conditionally show/hide
local username/password login on the login screen. When set to 'false'
(production), only Microsoft login is shown. When 'true' (development),
both options are available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 14:20:50 -06:00
michael
8a9c7c3cb6 Improve discussion guide discoverability in Focus Group session
Add prominent "Edit Discussion Guide" button to header and enhance accordion
styling with amber color scheme, "Click to Edit" badge, and visual feedback
to help users discover the inline editing capability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 09:57:32 -06:00
michael
240a1c09f5 Add field-level inline editing for discussion guide items
Users can now edit individual questions and prompts directly without
entering section edit mode. Edit buttons appear on hover for each item,
allowing inline editing of content, time limits, and probe questions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 09:43:12 -06:00
michael
28c7bbc055 Improve Focus Group workflow UX
- Rename "Copy Discussion Guide" button to "Import Discussion Guide from Other Project"
- Reorder tabs from Setup → Review & Edit → Participants to Setup → Participant Selection → Review & Edit
- Rename "Participants" tab to "Participant Selection" for clarity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 09:30:57 -06:00
michael
08dbd5f5a2 Add word count strength indicator for form text fields
Implements a traffic light indicator beneath paragraph fields to guide users
on content adequacy. Shows red (<33%), yellow (33-99%), or green (≥100%) based
on word count progress toward minimum targets.

Fields updated:
- Research Brief: 150 words minimum
- Discussion Topics: 15 words minimum
- Audience Brief: 150 words minimum
- Research Objective: 150 words minimum

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 09:25:31 -06:00
michael
afa7e43051 Improve draft focus group UX with clickable cards and Run Session button
- Make entire draft card clickable to enter setup mode
- Rename "Edit" button to "Continue Setup" for better clarity
- Add "Run Session" button for complete drafts (with discussion guide and participants)
- Prevent checkbox clicks from triggering card navigation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 09:17:41 -06:00
michael
22b3ec19a5 Refactor FocusGroupModerator into smaller components and hooks
Extract business logic and UI into reusable pieces:

Custom Hooks:
- useFocusGroupAutoSave: debounced auto-save with retry logic
- useFolderManagement: folder CRUD operations
- usePersonaFiltering: filter state and persona filtering
- useDiscussionGuideGeneration: guide generation and progress

UI Components:
- SaveStatusIndicator: auto-save status display
- FolderSidebar: folder list and management
- PersonaFilterDialog: persona filter modal
- CopyGuideDialog: copy guide from other focus groups

Tab Components:
- SetupTab: form and asset uploader
- ReviewTab: discussion guide viewer
- ParticipantsTab: persona selection grid

Reduces FocusGroupModerator from 2,396 to ~600 lines (75% reduction).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 09:11:21 -06:00
michael
4bf325483e Fix tab not switching to Review after discussion guide generation
The useEffect that reverts to Setup tab on cancellation was incorrectly
firing after successful generation. Added check for discussionGuide to
only revert when generation was actually cancelled (no guide exists).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 08:51:37 -06:00
michael
96b9bfeedd Add LLM-generated one-line summaries for focus groups in list view
- Create focus_group_summary_service.py to generate concise summaries
- Add prompt template for summary generation
- Integrate summary generation after discussion guide creation
- Display summary under focus group title in list view with fallback to description

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 08:51:28 -06:00
michael
f0ac4a14de Collapse Customer Data Upload into accordion to reduce visual prominence
The upload section had more prominence than Audience Brief and Research
Objective, causing users to focus there first. Now collapsed by default
with "(Optional)" label to de-emphasize relative to primary inputs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 09:34:28 -06:00
michael
e10a569bc2 Improve Customer Data Upload guidance with clearer instructions
- Add tooltip explaining what data improves persona accuracy
- Add "What data should I upload?" section with bullet list
- Update "What's included in the personas?" section with revised copy
- Add PowerPoint support to allowed file types
- Make FieldTooltip example prop optional for simpler tooltips

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 08:26:45 -06:00
michael
e5aa05739e Fix persona selection grid to use 2x2 layout for consistency
Changed the Select Participants grid from 3 columns to 2 columns on large screens to match the visual pattern used elsewhere in the platform.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 08:05:26 -06:00
michael
5eaf81ec18 Rename Asset Upload to Upload Your Stimulus with clearer description
Updated the asset upload section in the Focus Group flow to use more
intuitive terminology and provide better guidance about its purpose.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 07:55:54 -06:00
michael
ec23bed0b6 Rename Cooper Profile to Attitudinal Profile for clarity
The term "Cooper Profile" confused non-UX users. Renamed to "Attitudinal
Profile" to align with user language and documentation terminology.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 07:44:21 -06:00
michael
bbd3f2c828 Add contextual descriptions to AI model selection dropdowns
Users can now see helpful context next to each model option:
- Gemini 3 Pro (Slow, best for most tasks)
- GPT-4.1 (Fast, best for speed)
- GPT-5 (Slow, best for complex tasks)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 16:27:57 -06:00
michael
578dc60b11 Add tooltip help icons to Audience Brief and Research Objective fields
Clarifies the distinction between these form fields by adding (?) tooltip
icons with explanatory text and expandable examples. Updates placeholder
text and removes redundant FormDescription elements.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 16:10:21 -06:00
michael
25fcbc826f Redesign Enhance Brief to auto-apply changes with assumptions modal
- Replace suggestions panel with auto-apply: enhanced text now populates form fields automatically
- Add modal showing assumptions made during enhancement (3-5 bullet points)
- Reduce prompt scope by 50% for more focused, impactful enhancements
- Update backend to return enhanced text + assumptions instead of suggestions array

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 15:57:11 -06:00
michael
567db4227c Move creativity slider to collapsible Advanced Controls section
- Wrap temperature slider in accordion labeled "Advanced Controls"
- Rename "AI Creativity Level (Temperature)" to "Creativity Level"
- Replace numeric labels with descriptive terms (More Focused & Consistent / More Diverse & Creative)
- Remove "Current" value display
- Change default from 1.0 to 0.75 (centered position)
- Update description with user-friendly language about variance and hallucination risk

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 15:07:45 -06:00
michael
03bb650ec6 Replace inline progress bars with modal progress dialogs for better visibility
- Created new reusable ProgressModal component with animated progress bar
- Converted all inline GenerationProgressBar usages to modal dialogs:
  - AIRecruiter.tsx: Persona generation
  - FocusGroupModerator.tsx: Discussion guide generation
  - FocusGroupSession.tsx: Key themes extraction
  - SyntheticUsers.tsx: Persona summary generation
  - PersonaModificationModal.tsx: Persona modification
- Modal features: auto-dismiss after completion, non-dismissible during operation,
  cancel support, progress animation from 0-90% over 54 seconds
- Fixed broken theme generation state calls in FocusGroupSession.tsx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 11:03:31 -06:00
michael
4d9b0afde7 upgraded to Gemini 3.0 Pro (gemini-3-pro-preview) from Gemini 2.5 Pro
- Upgraded google-genai package from 1.31.0 to 1.52.0
- Updated DEFAULT_MODEL in llm_service.py to gemini-3-pro-preview
- Updated all backend routes, services, and models with new model string
- Updated all frontend components with new model string and display labels
- Updated CLAUDE.md documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 10:37:36 -06:00
michael
d3aca7c309 added retry logic and smart field completion for persona generation, increased OpenAI timeout
- persona generation now retries up to 2 times on failure
- missing persona fields are intelligently completed based on context
- expanded required field validation from 5 to 9 fields
- prompt now explicitly lists all required fields with validation instructions
- fixed discussion guide cancellation check to handle object responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 09:39:58 -06:00
michael
7c68f5d0e4 truncated long folder names so the buttons are still visible, migrated legacy folders to new format 2025-09-11 10:40:01 -05:00
michael
db3a418d3c aligned manual persona editor tabs and fields with view-only mode - removed tabs and fields from manual edit mode that don't show up in view-only detail mode 2025-09-10 23:05:02 -05:00
michael
f1cc094318 added full persona profile export in bulk actions menu (CSV, JSON and Markdown formats) 2025-09-10 22:38:35 -05:00
michael
abc9731e4a added hierarchical folders (just two levels) with drag and drop management 2025-09-10 19:53:06 -05:00
michael
e29d2a0bb9 made long actions cancellable (like persona generation, etc.), increased variety of persona generation with prompt changes and temperature variable, reduced length of key theme quotes, bug fixes 2025-09-10 16:24:05 -05:00
michael
8288cb9f5e fixed age to be a single number instead of range, fixed language for AI model to include thematic analysis, and added review/revert/save function to AI persona modification mechanism 2025-09-08 16:10:03 -05:00
michael
1b977ec517 graceful handling of expired JWT token 2025-09-03 13:15:00 -05:00
michael
6a40936508 major refactor of entire application - migrate sync -> async including pymongo -> motor, flask -> quart, google-generativeai -> google-genai 2025-08-27 15:20:56 -05:00