The 'จัดกลุ่มอัตโนมัติ' button was hidden inside v-if='agentGroups.length > 0'
— chicken-and-egg problem. Now shows trigger button when profiles exist
but groups don't, and groups section after categorization.
Backend:
- Add /api/agent-group/categorize endpoint — AI groups agents by role
- Add /api/agent-group/filter endpoint — filter by selected groups
- Groups with default_enabled=false (advertiser, brand) are unchecked
Frontend:
- Add agent groups section in Step2EnvSetup.vue
- 'Auto-categorize' button triggers AI grouping
- Show groups with checkboxes (enabled groups checked, disabled unchecked)
- Auto-remove unchecked agents when proceeding to Step 3
- Show selected count summary
- Add marketing metadata to 'Not allowed' list in ontology prompt
- Strengthen exclude_self filter instruction
- Add exclude_rules support from template filter rules
- Update business_ad template with more excluded types
- OntologyGenerator.generate() now accepts template_filter_rules parameter
- When template_id is provided, API loads filter rules from templates.json
- Filter rules injected into ontology system prompt:
- exclude_self: don't create entity for the business/brand that uploaded data
- exclude_types: don't create specific entity types
- focus: guide LLM to focus on specific entity categories
- API endpoint accepts template_id in form data
- Add use cases section with 4 scenario cards (news, policy, business, fiction)
- Rewrite Thai home section text to be natural (not translated from Chinese)
- Add use case locale keys for th/en/zh
- Add CSS for use cases grid with hover effects
Root cause found in container: camel-ai v0.2.78 openai_model.py L117 reads
os.environ.get('OPENAI_API_BASE_URL') — NOT OPENAI_BASE_URL.
Fix: Set BOTH env vars (OPENAI_BASE_URL for OpenAI SDK + OPENAI_API_BASE_URL for camel-ai).
Keep model_config_dict={} empty so nothing spreads to create().
Also fix Step 2 Thai truncation: \w regex doesn't match Thai tone marks (Mn category).
Use explicit Unicode range \u0E00-\u0E7F instead.
1. Restore OPENAI_API_KEY/OPENAI_BASE_URL env vars for camel-ai factory check
(keep api_key/base_url in model_config_dict for client constructor)
2. Add Thai-supporting font-family to .profile-realname
(JetBrains Mono doesn't render Thai diacritics)
3. Keep model_config_dict with api_key and base_url for camel-ai client
camel-ai v0.2.78 reads OPENAI_API_KEY from env and auto-passes it to
chat.completions.create() which doesn't accept it (TypeError).
Fix: pass api_key and base_url through model_config_dict so camel-ai
extracts them for the OpenAI client constructor only.
camel-ai's OpenAI model reads OPENAI_BASE_URL, not OPENAI_API_BASE_URL.
This caused all simulation LLM calls to go to api.openai.com instead of
the configured provider (DeepSeek, Xiaomi Mimo, etc), resulting in 401.
The error interceptor was re-throwing the generic axios Error object
instead of extracting the actual error message from the response body.
Now extracts error.response.data.error for meaningful error messages.
- Extract error from err.response.data.error (axios error response)
- Log full error to console for debugging
- Show actual backend error message instead of generic 'Error'
- Add isEnvAlive check on mount via /api/simulation/env-status
- Show warning banner when simulation env is not running
- Add alert() on survey failure for visibility
- Add envNotRunning translation key for th/en/zh
- Time config: translate all Chinese instructions and field descriptions
- Event config: translate hot topics/narrative direction instructions
- Agent config: translate entity type descriptions and field labels
- Profile generator: translate all persona prompt fields and instructions
- Country field: changed from 'use Chinese' to 'use English'
- simulation_config_generator.py: translate all LLM prompts and system messages
- oasis_profile_generator.py: translate profile generation prompts
Ensures get_language_instruction() controls output language instead of
being overridden by Chinese prompt context.
- Interview prompt prefix: Chinese -> English
- Sub-query decomposition: Chinese -> English
- Agent selection: Chinese -> English
- Interview questions: Chinese -> English
- Interview summary: Chinese -> English
- Error messages: Chinese -> English
- to_text() labels: Chinese -> English
This ensures get_language_instruction() actually controls output language
instead of being overridden by Chinese prompt context.
- Add locales/th.json with 629 translated keys
- Add Thai to languages.json with llmInstruction for report generation
- Backend auto-loads new locale files from locales/ directory
- Set VITE_API_BASE_URL=https://opinion-api.moreminimore.com for
frontend-backend split deployment
- Vite proxy also uses API_BACKEND_URL env var as target
- Falls back to same-origin proxy for local dev
When deployed behind a reverse proxy (e.g. opinion.moreminimore.com),
hardcoding http://localhost:5001 causes the browser to try connecting
to the user's own machine. Empty baseURL + vite proxy fixes this.
The Shanda sponsor logo's alt text was `666ghj%2MiroFish | Shanda`,
missing the `F` from the URL-encoded `/`. Every other badge in both
READMEs uses the correct `666ghj%2FMiroFish`. Bring this one in line
with the rest.
- Add return type annotation (list[str]) to Config.validate()
- Add type annotations (msg: str, -> None) to logger convenience functions
- Add FileParser.is_supported() classmethod for checking file format support