Spaces:
Running
Running
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/.gitignore devai_phase4/.pytest_cache/.gitignore | |
| --- devai_phase4_orig/.pytest_cache/.gitignore 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/.pytest_cache/.gitignore 2026-07-06 10:28:54.061919928 +0000 | |
| +# Created by pytest automatically. | |
| +* | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/CACHEDIR.TAG devai_phase4/.pytest_cache/CACHEDIR.TAG | |
| --- devai_phase4_orig/.pytest_cache/CACHEDIR.TAG 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/.pytest_cache/CACHEDIR.TAG 2026-07-06 10:28:54.061919928 +0000 | |
| +Signature: 8a477f597d28d172789f06886806bc55 | |
| +# This file is a cache directory tag created by pytest. | |
| +# For information about cache directory tags, see: | |
| +# https://bford.info/cachedir/spec.html | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/README.md devai_phase4/.pytest_cache/README.md | |
| --- devai_phase4_orig/.pytest_cache/README.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/.pytest_cache/README.md 2026-07-06 10:28:54.061919928 +0000 | |
| +# pytest cache directory # | |
| + | |
| +This directory contains data from the pytest's cache plugin, | |
| +which provides the `--lf` and `--ff` options, as well as the `cache` fixture. | |
| + | |
| +**Do not** commit this to version control. | |
| + | |
| +See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information. | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/v/cache/nodeids devai_phase4/.pytest_cache/v/cache/nodeids | |
| --- devai_phase4_orig/.pytest_cache/v/cache/nodeids 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/.pytest_cache/v/cache/nodeids 2026-07-06 10:28:54.061919928 +0000 | |
| +[ | |
| + "tests/test_phase4_docs_presets.py::test_guides_exist_and_share_same_core_sections", | |
| + "tests/test_phase4_docs_presets.py::test_onboarding_and_ui_hooks_present", | |
| + "tests/test_phase4_docs_presets.py::test_provider_presets_catalog_exists" | |
| +] | |
| \ No newline at end of file | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/CHANGELOG_v4.7.md devai_phase4/CHANGELOG_v4.7.md | |
| --- devai_phase4_orig/CHANGELOG_v4.7.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/CHANGELOG_v4.7.md 2026-07-06 10:28:32.013919928 +0000 | |
| +# DevAI Studio v4.7 Combined Changelog | |
| + | |
| +## Phase 1 — BYOM foundation | |
| +- Added secure encrypted storage for custom provider API keys. | |
| +- Added custom router with provider-aware request building. | |
| +- Added quota/error handling for custom models. | |
| + | |
| +## Phase 2 — Management UI | |
| +- Added three-dot custom model management panel. | |
| +- Added add/edit/delete flows for custom models. | |
| +- Added routing rules editor and quota card visuals. | |
| + | |
| +## Phase 3 — Quota + fallback behavior | |
| +- Added quota exhaustion handling. | |
| +- Added local fallback / ask-for-new-key recovery paths. | |
| +- Added extended tests and screenshots for save/edit/rules flows. | |
| + | |
| +## Phase 4 — Documentation & polish | |
| +- Added `data/provider_presets.json` with curated providers and rule sets. | |
| +- Added `ui/onboarding_tour.py` with driver.js first-run tour. | |
| +- Added Hindi and English BYOM user guides. | |
| +- Added migration guide and searchable troubleshooting KB. | |
| +- Added About-tab docs hub and restart-tour control. | |
| +- Added release assets, extra screenshots, diff patch, and a demo video storyboard. | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/PHASE4_DIFF.patch devai_phase4/PHASE4_DIFF.patch | |
| --- devai_phase4_orig/PHASE4_DIFF.patch 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/PHASE4_DIFF.patch 2026-07-06 10:29:01.289919928 +0000 | |
| +diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/.gitignore devai_phase4/.pytest_cache/.gitignore | |
| +--- devai_phase4_orig/.pytest_cache/.gitignore 1970-01-01 00:00:00.000000000 +0000 | |
| ++++ devai_phase4/.pytest_cache/.gitignore 2026-07-06 10:28:54.061919928 +0000 | |
| +@@ -0,0 +1,2 @@ | |
| ++# Created by pytest automatically. | |
| ++* | |
| +diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/CACHEDIR.TAG devai_phase4/.pytest_cache/CACHEDIR.TAG | |
| +--- devai_phase4_orig/.pytest_cache/CACHEDIR.TAG 1970-01-01 00:00:00.000000000 +0000 | |
| ++++ devai_phase4/.pytest_cache/CACHEDIR.TAG 2026-07-06 10:28:54.061919928 +0000 | |
| +@@ -0,0 +1,4 @@ | |
| ++Signature: 8a477f597d28d172789f06886806bc55 | |
| ++# This file is a cache directory tag created by pytest. | |
| ++# For information about cache directory tags, see: | |
| ++# https://bford.info/cachedir/spec.html | |
| +diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/README.md devai_phase4/.pytest_cache/README.md | |
| +--- devai_phase4_orig/.pytest_cache/README.md 1970-01-01 00:00:00.000000000 +0000 | |
| ++++ devai_phase4/.pytest_cache/README.md 2026-07-06 10:28:54.061919928 +0000 | |
| +@@ -0,0 +1,8 @@ | |
| ++# pytest cache directory # | |
| ++ | |
| ++This directory contains data from the pytest's cache plugin, | |
| ++which provides the `--lf` and `--ff` options, as well as the `cache` fixture. | |
| ++ | |
| ++**Do not** commit this to version control. | |
| ++ | |
| ++See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information. | |
| +diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/.pytest_cache/v/cache/nodeids devai_phase4/.pytest_cache/v/cache/nodeids | |
| +--- devai_phase4_orig/.pytest_cache/v/cache/nodeids 1970-01-01 00:00:00.000000000 +0000 | |
| ++++ devai_phase4/.pytest_cache/v/cache/nodeids 2026-07-06 10:28:54.061919928 +0000 | |
| +@@ -0,0 +1,5 @@ | |
| ++[ | |
| ++ "tests/test_phase4_docs_presets.py::test_guides_exist_and_share_same_core_sections", | |
| ++ "tests/test_phase4_docs_presets.py::test_onboarding_and_ui_hooks_present", | |
| ++ "tests/test_phase4_docs_presets.py::test_provider_presets_catalog_exists" | |
| ++] | |
| +\ No newline at end of file | |
| +diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/CHANGELOG_v4.7.md devai_phase4/CHANGELOG_v4.7.md | |
| +--- devai_phase4_orig/CHANGELOG_v4.7.md 1970-01-01 00:00:00.000000000 +0000 | |
| ++++ devai_phase4/CHANGELOG_v4.7.md 2026-07-06 10:28:32.013919928 +0000 | |
| +@@ -0,0 +1,24 @@ | |
| ++# DevAI Studio v4.7 Combined Changelog | |
| ++ | |
| ++## Phase 1 — BYOM foundation | |
| ++- Added secure encrypted storage for custom provider API keys. | |
| ++- Added custom router with provider-aware request building. | |
| ++- Added quota/error handling for custom models. | |
| ++ | |
| ++## Phase 2 — Management UI | |
| ++- Added three-dot custom model management panel. | |
| ++- Added add/edit/delete flows for custom models. | |
| ++- Added routing rules editor and quota card visuals. | |
| ++ | |
| ++## Phase 3 — Quota + fallback behavior | |
| ++- Added quota exhaustion handling. | |
| ++- Added local fallback / ask-for-new-key recovery paths. | |
| ++- Added extended tests and screenshots for save/edit/rules flows. | |
| ++ | |
| ++## Phase 4 — Documentation & polish | |
| ++- Added `data/provider_presets.json` with curated providers and rule sets. | |
| ++- Added `ui/onboarding_tour.py` with driver.js first-run tour. | |
| ++- Added Hindi and English BYOM user guides. | |
| ++- Added migration guide and searchable troubleshooting KB. | |
| ++- Added About-tab docs hub and restart-tour control. | |
| ++- Added release assets, extra screenshots, diff patch, and a demo video storyboard. | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/data/provider_presets.json devai_phase4/data/provider_presets.json | |
| --- devai_phase4_orig/data/provider_presets.json 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/data/provider_presets.json 2026-07-06 10:26:42.069919928 +0000 | |
| +{ | |
| + "presets": [ | |
| + { | |
| + "provider": "openrouter", | |
| + "display_name": "OpenRouter (100+ models)", | |
| + "description": "एक API key से 100+ models — Claude, GPT, Gemini, Llama सब", | |
| + "signup_url": "https://openrouter.ai/keys", | |
| + "docs_url": "https://openrouter.ai/docs", | |
| + "popular_models": [ | |
| + { | |
| + "model_id": "anthropic/claude-3.5-sonnet", | |
| + "display_name": "Claude 3.5 Sonnet", | |
| + "best_for": [ | |
| + "security", | |
| + "refactor", | |
| + "complex reasoning" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.003, | |
| + "output": 0.015 | |
| + }, | |
| + "context_window": 200000 | |
| + }, | |
| + { | |
| + "model_id": "anthropic/claude-3.5-haiku", | |
| + "display_name": "Claude 3.5 Haiku (fast+cheap)", | |
| + "best_for": [ | |
| + "bug_fix", | |
| + "test_gen" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.001, | |
| + "output": 0.005 | |
| + }, | |
| + "context_window": 200000 | |
| + }, | |
| + { | |
| + "model_id": "openai/gpt-4o", | |
| + "display_name": "GPT-4o", | |
| + "best_for": [ | |
| + "feature", | |
| + "new_app" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.0025, | |
| + "output": 0.01 | |
| + }, | |
| + "context_window": 128000 | |
| + }, | |
| + { | |
| + "model_id": "google/gemini-2.0-flash-exp:free", | |
| + "display_name": "Gemini 2.0 Flash (Free tier)", | |
| + "best_for": [ | |
| + "any" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0, | |
| + "output": 0 | |
| + }, | |
| + "context_window": 1000000, | |
| + "notes": "Free but rate-limited to 15 req/min" | |
| + }, | |
| + { | |
| + "model_id": "deepseek/deepseek-r1", | |
| + "display_name": "DeepSeek R1 (reasoning)", | |
| + "best_for": [ | |
| + "refactor", | |
| + "security" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.00055, | |
| + "output": 0.00219 | |
| + }, | |
| + "context_window": 64000 | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "provider": "anthropic", | |
| + "display_name": "Anthropic (direct)", | |
| + "description": "Claude models directly — lowest latency, no OpenRouter markup", | |
| + "signup_url": "https://console.anthropic.com/", | |
| + "docs_url": "https://docs.anthropic.com/", | |
| + "popular_models": [ | |
| + { | |
| + "model_id": "claude-3-5-sonnet-20241022", | |
| + "display_name": "Claude 3.5 Sonnet (latest)", | |
| + "best_for": [ | |
| + "security", | |
| + "refactor", | |
| + "complex reasoning" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.003, | |
| + "output": 0.015 | |
| + }, | |
| + "context_window": 200000 | |
| + }, | |
| + { | |
| + "model_id": "claude-3-5-haiku-20241022", | |
| + "display_name": "Claude 3.5 Haiku", | |
| + "best_for": [ | |
| + "bug_fix", | |
| + "test_gen" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.0008, | |
| + "output": 0.004 | |
| + }, | |
| + "context_window": 200000 | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "provider": "openai", | |
| + "display_name": "OpenAI (direct)", | |
| + "signup_url": "https://platform.openai.com/api-keys", | |
| + "docs_url": "https://platform.openai.com/docs", | |
| + "popular_models": [ | |
| + { | |
| + "model_id": "gpt-4o", | |
| + "display_name": "GPT-4o", | |
| + "best_for": [ | |
| + "feature", | |
| + "new_app" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.0025, | |
| + "output": 0.01 | |
| + } | |
| + }, | |
| + { | |
| + "model_id": "gpt-4o-mini", | |
| + "display_name": "GPT-4o Mini", | |
| + "best_for": [ | |
| + "bug_fix" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.00015, | |
| + "output": 0.0006 | |
| + } | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "provider": "groq", | |
| + "display_name": "Groq (fastest inference)", | |
| + "description": "Ultra-fast LPU inference — best for iterative dev loops", | |
| + "signup_url": "https://console.groq.com/keys", | |
| + "popular_models": [ | |
| + { | |
| + "model_id": "llama-3.3-70b-versatile", | |
| + "display_name": "Llama 3.3 70B", | |
| + "best_for": [ | |
| + "any" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.00059, | |
| + "output": 0.00079 | |
| + }, | |
| + "notes": "~500 tokens/sec — feels instant" | |
| + }, | |
| + { | |
| + "model_id": "deepseek-r1-distill-llama-70b", | |
| + "display_name": "DeepSeek R1 Distill", | |
| + "best_for": [ | |
| + "refactor" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.00075, | |
| + "output": 0.00099 | |
| + } | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "provider": "together", | |
| + "display_name": "Together AI", | |
| + "signup_url": "https://api.together.xyz/settings/api-keys", | |
| + "popular_models": [ | |
| + { | |
| + "model_id": "Qwen/Qwen2.5-Coder-32B-Instruct", | |
| + "display_name": "Qwen 2.5 Coder 32B", | |
| + "best_for": [ | |
| + "bug_fix", | |
| + "feature" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.0008, | |
| + "output": 0.0008 | |
| + } | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "provider": "deepinfra", | |
| + "display_name": "DeepInfra", | |
| + "signup_url": "https://deepinfra.com/dash/api_keys", | |
| + "popular_models": [ | |
| + { | |
| + "model_id": "meta-llama/Meta-Llama-3.1-405B-Instruct", | |
| + "display_name": "Llama 3.1 405B", | |
| + "best_for": [ | |
| + "complex reasoning" | |
| + ], | |
| + "approx_cost_per_1k_tokens": { | |
| + "input": 0.0027, | |
| + "output": 0.0027 | |
| + } | |
| + } | |
| + ] | |
| + } | |
| + ], | |
| + "example_rule_sets": [ | |
| + { | |
| + "name": "Cost-conscious (Free tier maximizer)", | |
| + "description": "जितना हो सके free models — सिर्फ़ जटिल tasks पर paid", | |
| + "rules": [ | |
| + { | |
| + "model": "google/gemini-2.0-flash-exp:free (OpenRouter)", | |
| + "task_types": [ | |
| + "any" | |
| + ], | |
| + "min_complexity": 0 | |
| + }, | |
| + { | |
| + "model": "anthropic/claude-3.5-sonnet (OpenRouter)", | |
| + "task_types": [ | |
| + "security", | |
| + "refactor" | |
| + ], | |
| + "min_complexity": 8 | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "name": "Speed-focused (dev iteration)", | |
| + "description": "Groq की LPU speed का फायदा — instant feedback loop", | |
| + "rules": [ | |
| + { | |
| + "model": "llama-3.3-70b-versatile (Groq)", | |
| + "task_types": [ | |
| + "bug_fix", | |
| + "test_gen" | |
| + ], | |
| + "min_complexity": 0 | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "name": "Quality-first (enterprise)", | |
| + "description": "हर task पर best-in-class model — cost secondary", | |
| + "rules": [ | |
| + { | |
| + "model": "claude-3-5-sonnet (Anthropic direct)", | |
| + "task_types": [ | |
| + "security", | |
| + "refactor", | |
| + "new_app" | |
| + ], | |
| + "always_use": true | |
| + }, | |
| + { | |
| + "model": "gpt-4o (OpenAI direct)", | |
| + "task_types": [ | |
| + "feature" | |
| + ], | |
| + "min_complexity": 5 | |
| + } | |
| + ] | |
| + }, | |
| + { | |
| + "name": "Privacy-hybrid", | |
| + "description": "Local first, cloud सिर्फ़ security audits पर", | |
| + "rules": [ | |
| + { | |
| + "model": "claude-3-5-sonnet", | |
| + "task_types": [ | |
| + "security" | |
| + ], | |
| + "min_complexity": 7 | |
| + } | |
| + ] | |
| + } | |
| + ] | |
| +} | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/demo/README_demo_script.md devai_phase4/demo/README_demo_script.md | |
| --- devai_phase4_orig/demo/README_demo_script.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/demo/README_demo_script.md 2026-07-06 10:28:33.917919928 +0000 | |
| +# Demo storyboard script | |
| + | |
| +Use the bundled MP4 as a silent walkthrough. Suggested live narration order: | |
| +1. Open Advanced options. | |
| +2. Start BYOM via the three-dot menu. | |
| +3. Choose provider preset and popular model. | |
| +4. Load an example rule set. | |
| +5. Test connection and save the model. | |
| +6. Show quota cards and fallback behavior. | |
| +7. Open About tab docs hub. | |
| Binary files devai_phase4_orig/demo/devai_studio_v4.7_phase4_demo.mp4 and devai_phase4/demo/devai_studio_v4.7_phase4_demo.mp4 differ | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/demo/slides.txt devai_phase4/demo/slides.txt | |
| --- devai_phase4_orig/demo/slides.txt 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/demo/slides.txt 2026-07-06 10:28:32.237919928 +0000 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/01.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/02.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/03.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/04.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/05.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/06.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/07.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/08.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/09.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/10.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/11.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/12.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/13.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/14.png' | |
| +duration 22 | |
| +file '/home/user/work/devai_phase4/demo/story_frames/14.png' | |
| Binary files devai_phase4_orig/demo/story_frames/01.png and devai_phase4/demo/story_frames/01.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/02.png and devai_phase4/demo/story_frames/02.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/03.png and devai_phase4/demo/story_frames/03.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/04.png and devai_phase4/demo/story_frames/04.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/05.png and devai_phase4/demo/story_frames/05.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/06.png and devai_phase4/demo/story_frames/06.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/07.png and devai_phase4/demo/story_frames/07.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/08.png and devai_phase4/demo/story_frames/08.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/09.png and devai_phase4/demo/story_frames/09.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/10.png and devai_phase4/demo/story_frames/10.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/11.png and devai_phase4/demo/story_frames/11.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/12.png and devai_phase4/demo/story_frames/12.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/13.png and devai_phase4/demo/story_frames/13.png differ | |
| Binary files devai_phase4_orig/demo/story_frames/14.png and devai_phase4/demo/story_frames/14.png differ | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/docs/BYOM_USER_GUIDE_EN.md devai_phase4/docs/BYOM_USER_GUIDE_EN.md | |
| --- devai_phase4_orig/docs/BYOM_USER_GUIDE_EN.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/docs/BYOM_USER_GUIDE_EN.md 2026-07-06 10:28:32.013919928 +0000 | |
| +# 🎨 DevAI Studio v4.7 — Bring Your Own Model | |
| + | |
| +## Table of contents | |
| +1. [What is this feature](#1-what-is-this-feature) | |
| +2. [Setup — first model in 5 minutes](#2-setup--first-model-in-5-minutes) | |
| +3. [Choosing a provider](#3-choosing-a-provider) | |
| +4. [Task Rules — which model runs when](#4-task-rules--which-model-runs-when) | |
| +5. [Cost Management](#5-cost-management) | |
| +6. [Quota Exhaustion — what happens](#6-quota-exhaustion--what-happens) | |
| +7. [Security & Privacy](#7-security--privacy) | |
| +8. [Troubleshooting](#8-troubleshooting) | |
| +9. [Advanced: Custom endpoints](#9-advanced-custom-endpoints) | |
| +10. [FAQ](#10-faq) | |
| + | |
| +## 1. What is this feature? | |
| + | |
| +DevAI Studio v4.7 now has three model tiers: local, built-in cloud, and custom BYOM. This feature lets you attach your own API keys to production-grade models. | |
| + | |
| +### Tier summary | |
| +- **Local models** — free, offline, private, but speed depends on your hardware. | |
| +- **Built-in cloud models** — zero setup, quick start, but shared limits. | |
| +- **Custom models** — latest Claude, GPT, Gemini, Groq, Together, DeepInfra, or a custom endpoint; quota and billing belong to you. | |
| + | |
| +### Local models (always available) | |
| +- Qwen2.5-Coder-7B → coding tasks | |
| +- DeepSeek-R1-Distill-8B → complex reasoning | |
| +- InternLM3-8B → security audits | |
| +- Llama-3.2-3B → general chat | |
| +- MiniCPM-V-2.6 → vision (screenshot → code) | |
| +- Phi-3.5-mini → fast small tasks | |
| + | |
| +### What BYOM adds | |
| +- Latest flagship models without waiting for an app release. | |
| +- Personal quota instead of shared free-tier bottlenecks. | |
| +- Task-aware routing: bug fix, feature, refactor, security, tests, deployment, new app. | |
| +- Fallback control: pause and ask for a new key, or continue on a local model. | |
| + | |
| +## 2. Setup — first model in 5 minutes | |
| + | |
| +### Step 1 — Set a master key | |
| +Enter a strong passphrase in the Settings tab. It encrypts every stored API key. Save it in a password manager. If you lose it, re-add the models. | |
| + | |
| +### Step 2 — Pick a provider | |
| +- Fastest start: **OpenRouter** | |
| +- Best direct Claude latency: **Anthropic** | |
| +- Best multimodal generalist: **OpenAI GPT-4o** | |
| +- Fast iterative dev loops: **Groq** | |
| + | |
| +### Step 3 — Create an API key | |
| +Generate a key from the provider dashboard and verify billing or quota before pasting it into the app. | |
| + | |
| +### Step 4 — Studio > Advanced options > ⋮ > Add model | |
| +In the v4.7 UX you can choose a provider preset, then choose a popular model. The UI auto-fills model_id, base URL and a rough cost estimate. | |
| + | |
| +### Step 5 — Choose rules and fallback | |
| +- Task types: where the model is eligible. | |
| +- Min complexity: 0 for broad use, 8-10 for hard jobs only. | |
| +- Always use: overrides all routing rules. | |
| +- Fallback: ask for a new key or switch to a local model. | |
| + | |
| +### Step 6 — Test Connection | |
| +Once you see a green ✅, click Save Model and run a small validation task. | |
| + | |
| +### Recommended first prompt | |
| +```text | |
| +Audit this repository for SQL injection, XSS, hardcoded secrets, insecure dependencies and auth flaws. | |
| +``` | |
| + | |
| +## 3. Choosing a provider | |
| + | |
| +| Provider | Why choose it | Popular models | | |
| +|---|---|---| | |
| +| OpenRouter (100+ models) | एक API key से 100+ models — Claude, GPT, Gemini, Llama सब | Claude 3.5 Sonnet, Claude 3.5 Haiku (fast+cheap), GPT-4o | | |
| +| Anthropic (direct) | Claude models directly — lowest latency, no OpenRouter markup | Claude 3.5 Sonnet (latest), Claude 3.5 Haiku | | |
| +| OpenAI (direct) | OpenAI-compatible endpoint | GPT-4o, GPT-4o Mini | | |
| +| Groq (fastest inference) | Ultra-fast LPU inference — best for iterative dev loops | Llama 3.3 70B, DeepSeek R1 Distill | | |
| +| Together AI | OpenAI-compatible endpoint | Qwen 2.5 Coder 32B | | |
| +| DeepInfra | OpenAI-compatible endpoint | Llama 3.1 405B | | |
| + | |
| +### Quick recommendations | |
| +- Budget-sensitive solo developer: OpenRouter + free/cheap presets | |
| +- Security-review heavy team: Anthropic direct Sonnet | |
| +- UI + multimodal heavy team: GPT-4o | |
| +- Tight iteration loops: Groq Llama 3.3 70B | |
| +- Self-hosted compliance path: Custom endpoint / LiteLLM / vLLM | |
| + | |
| +## 4. Task Rules — which model runs when | |
| + | |
| +The rules engine evaluates task type, complexity score, and explicit overrides. If `always_use=true`, that model wins immediately. If multiple rules match, specificity and saved priority decide the winner. | |
| + | |
| +### Complexity scoring guide | |
| +- 0-2 → tiny edits, log cleanup, one-file tweaks | |
| +- 3-5 → medium bug fix, small feature, unit tests | |
| +- 6-7 → multi-file refactor, architectural reasoning | |
| +- 8-10 → security audits, migrations, large design work | |
| + | |
| +### Example rule sets shipped in v4.7 | |
| +- Cost-conscious (Free tier maximizer) | |
| +- Speed-focused (dev iteration) | |
| +- Quality-first (enterprise) | |
| +- Privacy-hybrid | |
| + | |
| +## 5. Cost Management | |
| + | |
| +### What the UI estimate means | |
| +The popular-model selector shows a rough estimate using **2K input / 500 output tokens**. It is not exact billing, but it is useful for sprint planning and model comparison. | |
| + | |
| +### Budgeting best practices | |
| +- Set hard spend caps in the provider dashboard. | |
| +- Keep a cheap model as the default and reserve premium models for complex tasks. | |
| +- Use task-specific routing so every small request does not hit Claude or GPT-4o. | |
| +- Use local models as fallback to reduce overage exposure. | |
| + | |
| +### Suggested budgets | |
| +| Profile | Monthly strategy | | |
| +|---|---| | |
| +| Solo hobby | Free-tier default + one premium audit model | | |
| +| Freelancer | Speed preset for iteration + Sonnet for client-critical reviews | | |
| +| Small team | Enterprise preset + provider spend caps + weekly dashboard review | | |
| + | |
| +## 6. Quota Exhaustion — what happens | |
| + | |
| +When the provider returns 402 or 429, v4.7 gives two options: | |
| +1. **ask_new_key** → pause and request a replacement key. | |
| +2. **local_model** → continue on the mapped local model. | |
| + | |
| +## 7. Security & Privacy | |
| + | |
| +- API keys are stored with **Fernet (AES-128 + HMAC-SHA256)** encryption at rest. | |
| +- The master key is not stored on disk. | |
| +- Secrets are masked in logs. | |
| +- Writes are atomic and file permissions stay restrictive. | |
| +- DevAI Studio does not add its own telemetry on top of your chosen provider path. | |
| + | |
| +## 8. Troubleshooting | |
| + | |
| +Below is a short version of the top issues. The full searchable knowledge base lives in `docs/TROUBLESHOOTING_KB.md`. | |
| + | |
| +### Issue #1: Invalid API key on Test Connection | |
| + | |
| +**Symptoms:** Red ❌ appears after clicking Test Connection. | |
| + | |
| +**Common causes** | |
| +- Extra spaces in the key | |
| +- Wrong provider selected | |
| +- Key revoked or expired | |
| + | |
| +**Recommended fix** | |
| +1. Regenerate the key from the provider dashboard | |
| +2. Paste it again without leading/trailing spaces | |
| +3. Confirm the provider dropdown matches the key type | |
| + | |
| +### Issue #2: Model replies in the wrong language | |
| + | |
| +**Symptoms:** Responses ignore the language of the prompt or system instruction. | |
| + | |
| +**Common causes** | |
| +- Model preset optimized for another language | |
| +- Task prompt lacks a language instruction | |
| +- Provider-side system prompt contamination | |
| + | |
| +**Recommended fix** | |
| +1. Add an explicit language instruction to the task | |
| +2. Prefer GPT-4o or Claude Sonnet for multilingual work | |
| +3. Test the model directly in the provider console | |
| + | |
| +### Issue #3: Fallback not triggering on 429 | |
| + | |
| +**Symptoms:** Pipeline pauses instead of moving to the chosen fallback behavior. | |
| + | |
| +**Common causes** | |
| +- Saved fallback policy is ask_new_key | |
| +- 429 body is returned as a generic error by a proxy | |
| +- Outdated custom model config | |
| + | |
| +**Recommended fix** | |
| +1. Re-open the model card and verify fallback policy | |
| +2. Retest using direct provider endpoint | |
| +3. Save the model again to refresh metadata | |
| + | |
| +### Issue #4: Pipeline hangs during Coder stage | |
| + | |
| +**Symptoms:** Status remains on coder or reviewer for too long. | |
| + | |
| +**Common causes** | |
| +- Provider latency spike | |
| +- Very large prompt or repository | |
| +- Provider queue saturation | |
| + | |
| +**Recommended fix** | |
| +1. Retry with a smaller ZIP | |
| +2. Switch to a faster preset like Groq or Claude Haiku | |
| +3. Use Private Mode for small/local tasks | |
| + | |
| +### Issue #5: Custom model is used even when disabled | |
| + | |
| +**Symptoms:** Router keeps picking a model after you thought it was inactive. | |
| + | |
| +**Common causes** | |
| +- always_use is enabled | |
| +- Task rules still match any task | |
| +- Priority order favors that model | |
| + | |
| +**Recommended fix** | |
| +1. Edit the model and disable always_use | |
| +2. Change task_types from any to specific categories | |
| +3. Adjust the rule priority matrix | |
| + | |
| +### Issue #6: Base URL looks correct but requests fail | |
| + | |
| +**Symptoms:** Connection test fails with network or 404 errors. | |
| + | |
| +**Common causes** | |
| +- Provider endpoint missing /v1 | |
| +- Anthropic direct uses /messages instead of /chat/completions | |
| +- Proxy strips auth headers | |
| + | |
| +**Recommended fix** | |
| +1. Verify the endpoint in provider docs | |
| +2. Use the built-in preset instead of manual typing | |
| +3. Try a direct provider endpoint to isolate the issue | |
| + | |
| +### Issue #7: Saved model disappears after restart | |
| + | |
| +**Symptoms:** A model is visible in-session but missing later. | |
| + | |
| +**Common causes** | |
| +- Master key changed | |
| +- Encrypted file corrupted | |
| +- Data directory permissions issue | |
| + | |
| +**Recommended fix** | |
| +1. Reuse the same master key | |
| +2. Restore data/custom_models.enc.json from backup | |
| +3. Ensure the process can write to the data folder | |
| + | |
| +### Issue #8: Quota bar never updates | |
| + | |
| +**Symptoms:** Model card always shows unknown quota. | |
| + | |
| +**Common causes** | |
| +- Provider does not expose headers | |
| +- First request never completed successfully | |
| +- Proxy removed rate-limit headers | |
| + | |
| +**Recommended fix** | |
| +1. Run one successful generation | |
| +2. Use a direct provider endpoint if quota visibility matters | |
| +3. Treat the bar as optional and rely on provider dashboard billing | |
| + | |
| +### Issue #9: Anthropic direct fails while OpenRouter works | |
| + | |
| +**Symptoms:** Claude via Anthropic shows HTTP errors. | |
| + | |
| +**Common causes** | |
| +- Anthropic key pasted into OpenRouter provider | |
| +- Account lacks billing | |
| +- Model name typo | |
| + | |
| +**Recommended fix** | |
| +1. Select Anthropic direct provider | |
| +2. Check billing and usage limits | |
| +3. Use a preset rather than a hand-typed model ID | |
| + | |
| +### Issue #10: OpenRouter free tier is rate-limited | |
| + | |
| +**Symptoms:** Requests work, then suddenly slow down or fail. | |
| + | |
| +**Common causes** | |
| +- Free tier cap reached | |
| +- Burst traffic from multiple runs | |
| +- No paid balance | |
| + | |
| +**Recommended fix** | |
| +1. Wait for the reset window | |
| +2. Use a paid key or alternate provider | |
| +3. Route simple tasks to a cheaper preset | |
| + | |
| +### Issue #11: Task Rules matrix saves unexpected priorities | |
| + | |
| +**Symptoms:** The top model in cards differs from the table order. | |
| + | |
| +**Common causes** | |
| +- Priority value duplicates | |
| +- Higher min complexity wins ties | |
| +- Model list sorted after save | |
| + | |
| +**Recommended fix** | |
| +1. Give each model a unique priority | |
| +2. Check min_complexity values | |
| +3. Refresh the panel after saving | |
| + | |
| +### Issue #12: Local fallback quality is poor | |
| + | |
| +**Symptoms:** Fallback works but output quality drops noticeably. | |
| + | |
| +**Common causes** | |
| +- Fallback switched to small local model | |
| +- Task too complex for local model | |
| +- Prompt too large for context | |
| + | |
| +**Recommended fix** | |
| +1. Use ask_new_key for critical work | |
| +2. Trim prompt size | |
| +3. Reserve local fallback for continuation, not best quality | |
| + | |
| +### Issue #13: Edit modal requires a new key unexpectedly | |
| + | |
| +**Symptoms:** Changing provider or model ID forces key replacement. | |
| + | |
| +**Common causes** | |
| +- Security design prevents silent target change | |
| +- Provider changed endpoints | |
| + | |
| +**Recommended fix** | |
| +1. Paste a new key when changing provider/model target | |
| +2. Keep provider/model unchanged to reuse the stored encrypted key | |
| + | |
| +### Issue #14: Model ID preset dropdown is empty | |
| + | |
| +**Symptoms:** Provider selected but no popular models appear. | |
| + | |
| +**Common causes** | |
| +- provider_presets.json missing | |
| +- Provider not curated | |
| +- JSON failed to load | |
| + | |
| +**Recommended fix** | |
| +1. Validate data/provider_presets.json | |
| +2. Choose a curated provider preset | |
| +3. Restart the app after restoring the file | |
| + | |
| +### Issue #15: Tour never starts | |
| + | |
| +**Symptoms:** First-run experience does not appear. | |
| + | |
| +**Common causes** | |
| +- localStorage already marks it complete | |
| +- Advanced options never opened | |
| +- CDN blocked | |
| + | |
| +**Recommended fix** | |
| +1. Use the Restart onboarding tour button in About | |
| +2. Open Advanced options once | |
| +3. Allow driver.js CDN or self-host the asset | |
| + | |
| +## 9. Advanced: Custom endpoints | |
| + | |
| +### Supported patterns | |
| +- **vLLM** — self-hosted OpenAI-compatible gateway. | |
| +- **LiteLLM proxy** — unified multi-provider gateway. | |
| +- **LM Studio HTTP server** — local desktop endpoint for experimentation. | |
| +- **Ollama via proxy bridge** — useful when a team wants one OpenAI-compatible URL. | |
| + | |
| +### Endpoint checklist | |
| +- Use the correct `/v1` base path. | |
| +- Verify auth header behavior. | |
| +- Manually test large context claims. | |
| +- Preserve upstream 401/403/429 status codes through proxies. | |
| + | |
| +## 10. FAQ | |
| + | |
| +### Do I need a separate API key for every provider? | |
| +Yes. Every direct provider has its own key. OpenRouter can expose many models through one key. | |
| + | |
| +### Can I recover stored keys if I forget the master key? | |
| +No. For safety, encrypted keys are not recoverable; re-add the models instead. | |
| + | |
| +### Do custom models replace local models? | |
| +No. They are a third tier. Local models remain available at all times. | |
| + | |
| +### Can I stay on free models only? | |
| +Yes. The cost-conscious preset is designed for that workflow. | |
| + | |
| +### Will local fallback produce the exact same answer? | |
| +Not always, but it preserves continuity when cloud quota is exhausted. | |
| + | |
| +### Are provider presets editable? | |
| +Yes. The JSON file is only a curated default; manual values still work. | |
| + | |
| +### Can the docs and KB be read offline? | |
| +Yes. The markdown files ship inside the release ZIP. | |
| + | |
| +### Are custom endpoints supported? | |
| +Yes, as long as the endpoint is OpenAI-compatible or you can supply a custom base URL. | |
| + | |
| +### Does billing happen inside the app? | |
| +No. Billing is handled by the provider; the app only shows an estimate. | |
| + | |
| +### Is this feature merge-safe for team repositories? | |
| +Yes. Storage is JSON-based and all existing v4.6 APIs stay unchanged. | |
| + | |
| +### Do I need a database migration? | |
| +No. The feature is additive and uses JSON-based storage. | |
| + | |
| +### Will screenshot-to-code flows use custom models? | |
| +Yes, when routing rules allow it and the provider is capable. | |
| + | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/docs/BYOM_USER_GUIDE_HI.md devai_phase4/docs/BYOM_USER_GUIDE_HI.md | |
| --- devai_phase4_orig/docs/BYOM_USER_GUIDE_HI.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/docs/BYOM_USER_GUIDE_HI.md 2026-07-06 10:28:32.013919928 +0000 | |
| +# 🎨 DevAI Studio v4.7 — अपना AI Model जोड़ें (Bring Your Own Model) | |
| + | |
| +## विषय-सूची | |
| +1. [यह feature क्या है](#1-यह-feature-क्या-है) | |
| +2. [Setup — पहला model 5 मिनट में](#2-setup--पहला-model-5-मिनट-में) | |
| +3. [Provider चुनना — कौन-सा best है](#3-provider-चुनना--कौन-सा-best-है) | |
| +4. [Task Rules — कब कौन-सा model](#4-task-rules--कब-कौन-सा-model) | |
| +5. [Cost Management](#5-cost-management) | |
| +6. [Quota Exhaustion — क्या होगा](#6-quota-exhaustion--क्या-होगा) | |
| +7. [Security & Privacy](#7-security--privacy) | |
| +8. [Troubleshooting](#8-troubleshooting) | |
| +9. [Advanced: Custom endpoints](#9-advanced-custom-endpoints) | |
| +10. [FAQ](#10-faq) | |
| + | |
| +## 1. यह Feature क्या है? | |
| + | |
| +DevAI Studio v4.7 में तीन model tiers हैं: local, built-in cloud, और custom BYOM. यह नया feature आपको अपने personal API keys के साथ production-grade models जोड़ने देता है। | |
| + | |
| +### Tier summary | |
| +- **Local models** — free, offline, private, लेकिन speed hardware पर depend करती है। | |
| +- **Built-in cloud models** — quick start, no setup, लेकिन shared limits हैं। | |
| +- **Custom models** — latest Claude, GPT, Gemini, Groq, Together, DeepInfra या custom endpoint; quota और billing आपकी। | |
| + | |
| +### Local models (हमेशा available) | |
| +- Qwen2.5-Coder-7B → coding tasks | |
| +- DeepSeek-R1-Distill-8B → complex reasoning | |
| +- InternLM3-8B → security audits | |
| +- Llama-3.2-3B → general chat | |
| +- MiniCPM-V-2.6 → vision (screenshot → code) | |
| +- Phi-3.5-mini → fast small tasks | |
| + | |
| +### Custom models feature से क्या मिलता है | |
| +- Latest flagship models बिना app update का इंतज़ार किए। | |
| +- आपकी personal quota — shared free-tier bottlenecks से बचाव। | |
| +- Task-aware routing: bug fix, feature, refactor, security, test generation, deployment, new app. | |
| +- Fallback control: pause and ask for a new key, या local model पर continue. | |
| + | |
| +## 2. Setup — पहला Model 5 मिनट में | |
| + | |
| +### Step 1 — Master Key set करें | |
| +Settings tab में strong passphrase डालें। यही आपकी API keys को encrypt करेगी। इसे password manager में save करें। भूल गए तो models फिर से जोड़ने पड़ेंगे। | |
| + | |
| +### Step 2 — Provider चुनें | |
| +- Fastest start: **OpenRouter** | |
| +- Best direct Claude latency: **Anthropic** | |
| +- Best general multimodal experience: **OpenAI GPT-4o** | |
| +- Fast iterative dev loops: **Groq** | |
| + | |
| +### Step 3 — API key बनाएँ | |
| +Provider dashboard में जाकर API key बनाइए और billing/quota verify कीजिए। OpenRouter free-tier भी दे सकता है, पर rate limits जल्दी hit हो सकती हैं। | |
| + | |
| +### Step 4 — Studio > Advanced options > ⋮ > Add model | |
| +नई v4.7 UX में provider preset चुनिए, फिर Popular models dropdown से common model pick कीजिए। इससे model_id, base URL और rough cost estimate अपने-आप भर जाते हैं। | |
| + | |
| +### Step 5 — Rules and fallback चुनें | |
| +- Task types: model किस category के कामों पर eligible होगा। | |
| +- Min complexity: 0 मतलब broad usage, 8-10 मतलब सिर्फ़ tough jobs। | |
| +- Always use: बाकी rules override करेगा। | |
| +- Fallback: नई key माँगे या local model पर switch करे। | |
| + | |
| +### Step 6 — Test Connection | |
| +Green ✅ आने के बाद Save Model दबाएँ। पहला run ideally छोटा security audit या bug-fix prompt होना चाहिए ताकि routing clearly verify हो जाए। | |
| + | |
| +### Recommended first prompt | |
| +```text | |
| +इस repo का security audit करो — SQL injection, XSS, hardcoded secrets, insecure dependencies और auth flaws check करो। | |
| +``` | |
| + | |
| +## 3. Provider चुनना — कौन-सा best है? | |
| + | |
| +| Provider | Why choose it | Popular models | | |
| +|---|---|---| | |
| +| OpenRouter (100+ models) | एक API key से 100+ models — Claude, GPT, Gemini, Llama सब | Claude 3.5 Sonnet, Claude 3.5 Haiku (fast+cheap), GPT-4o | | |
| +| Anthropic (direct) | Claude models directly — lowest latency, no OpenRouter markup | Claude 3.5 Sonnet (latest), Claude 3.5 Haiku | | |
| +| OpenAI (direct) | OpenAI-compatible endpoint | GPT-4o, GPT-4o Mini | | |
| +| Groq (fastest inference) | Ultra-fast LPU inference — best for iterative dev loops | Llama 3.3 70B, DeepSeek R1 Distill | | |
| +| Together AI | OpenAI-compatible endpoint | Qwen 2.5 Coder 32B | | |
| +| DeepInfra | OpenAI-compatible endpoint | Llama 3.1 405B | | |
| + | |
| +### Quick recommendations | |
| +- Budget-sensitive solo developer: OpenRouter + free/cheap presets | |
| +- Security review heavy team: Anthropic direct Sonnet | |
| +- UI + multimodal heavy team: GPT-4o | |
| +- Tight iteration loops: Groq Llama 3.3 70B | |
| +- Self-hosted compliance path: Custom endpoint / LiteLLM / vLLM | |
| + | |
| +## 4. Task Rules — कब कौन-सा model? | |
| + | |
| +Rules engine तीन चीज़ें देखता है: task type, complexity score, और explicit override. अगर `always_use=true` है तो वही model top priority ले लेता है। अगर multiple rules match करें तो higher specificity और saved priority matter करती है। | |
| + | |
| +### Complexity scoring practical guide | |
| +- 0-2 → tiny edits, log cleanup, one-file tweaks | |
| +- 3-5 → medium bug fix, small feature, unit tests | |
| +- 6-7 → multi-file refactor, architectural reasoning | |
| +- 8-10 → security audits, migrations, large design work | |
| + | |
| +### Example rule sets shipped in v4.7 | |
| +- Cost-conscious (Free tier maximizer) | |
| +- Speed-focused (dev iteration) | |
| +- Quality-first (enterprise) | |
| +- Privacy-hybrid | |
| + | |
| +### Recommended patterns | |
| +1. Cheap-first rule for `any` tasks with complexity 0. | |
| +2. Stronger model for `security` and `refactor` from complexity 7 or 8. | |
| +3. Local fallback for continuity, ask_new_key for quality-critical outputs. | |
| + | |
| +## 5. Cost Management | |
| + | |
| +### What the UI estimate means | |
| +Popular-model selection shows a rough estimate using **2K input / 500 output tokens**. यह exact billing नहीं है, पर sprint planning और model comparison के लिए काफी useful है। | |
| + | |
| +### Budgeting best practices | |
| +- हर month के लिए provider-side spend cap set करें। | |
| +- Free या cheap model को default रखें; premium rules सिर्फ़ complex work के लिए रखें। | |
| +- Task-type specific routing use करें ताकि GPT/Claude हर छोटी request पर न जाए। | |
| +- Local models को fallback में रखकर cloud overage कम करें। | |
| + | |
| +### Suggested budgets | |
| +| Profile | Monthly strategy | | |
| +|---|---| | |
| +| Solo hobby | Free-tier default + one premium audit model | | |
| +| Freelancer | Speed preset for iteration + Sonnet for client-critical reviews | | |
| +| Small team | Enterprise preset + provider spend caps + weekly dashboard review | | |
| + | |
| +## 6. Quota Exhaustion — क्या होगा? | |
| + | |
| +जब provider 402/429 दे, v4.7 का flow दो रास्ते देता है: | |
| +1. **ask_new_key** → pipeline pause, user से नई key माँगना। | |
| +2. **local_model** → task mapping के हिसाब से local model पर continue करना। | |
| + | |
| +### Recommended walkthrough | |
| +- A model card quota bar low दिखाती है। | |
| +- Run के दौरान provider limit hit होती है। | |
| +- Status में clear message आता है। | |
| +- User या तो key replace करता है या local fallback पर continue करता है। | |
| + | |
| +### What to document for teams | |
| +- कौन-से tasks पर cloud-only quality चाहिए। | |
| +- कौन-से tasks local fallback tolerate कर सकते हैं। | |
| +- किस provider का spend alert कौन monitor करेगा। | |
| + | |
| +## 7. Security & Privacy | |
| + | |
| +- API keys **Fernet (AES-128 + HMAC-SHA256)** से encrypted-at-rest रहती हैं। | |
| +- Master key disk पर store नहीं होती; session context में use होकर disappear हो जाती है। | |
| +- Secret values logs में mask रहते हैं। | |
| +- Atomic writes और restrictive permissions accidental leakage risk कम करते हैं। | |
| +- No vendor telemetry by DevAI Studio; billing और request flow आपके चुने provider तक सीमित रहता है। | |
| + | |
| +### Operational security checklist | |
| +- Personal and team keys अलग रखें। | |
| +- Revoked keys तुरंत replace करें। | |
| +- Shared demo environments में real production keys use न करें। | |
| +- Master key को password manager में रखें, plain text note में नहीं। | |
| + | |
| +## 8. Troubleshooting | |
| + | |
| +नीचे top issues का short version है। Full searchable knowledge base `docs/TROUBLESHOOTING_KB.md` में है। | |
| + | |
| +### समस्या #1: Invalid API key on Test Connection | |
| + | |
| +**Symptoms:** Red ❌ appears after clicking Test Connection. | |
| + | |
| +**Common causes** | |
| +- Extra spaces in the key | |
| +- Wrong provider selected | |
| +- Key revoked or expired | |
| + | |
| +**Recommended fix** | |
| +1. Regenerate the key from the provider dashboard | |
| +2. Paste it again without leading/trailing spaces | |
| +3. Confirm the provider dropdown matches the key type | |
| + | |
| +### समस्या #2: Model replies in the wrong language | |
| + | |
| +**Symptoms:** Responses ignore the language of the prompt or system instruction. | |
| + | |
| +**Common causes** | |
| +- Model preset optimized for another language | |
| +- Task prompt lacks a language instruction | |
| +- Provider-side system prompt contamination | |
| + | |
| +**Recommended fix** | |
| +1. Add an explicit language instruction to the task | |
| +2. Prefer GPT-4o or Claude Sonnet for multilingual work | |
| +3. Test the model directly in the provider console | |
| + | |
| +### समस्या #3: Fallback not triggering on 429 | |
| + | |
| +**Symptoms:** Pipeline pauses instead of moving to the chosen fallback behavior. | |
| + | |
| +**Common causes** | |
| +- Saved fallback policy is ask_new_key | |
| +- 429 body is returned as a generic error by a proxy | |
| +- Outdated custom model config | |
| + | |
| +**Recommended fix** | |
| +1. Re-open the model card and verify fallback policy | |
| +2. Retest using direct provider endpoint | |
| +3. Save the model again to refresh metadata | |
| + | |
| +### समस्या #4: Pipeline hangs during Coder stage | |
| + | |
| +**Symptoms:** Status remains on coder or reviewer for too long. | |
| + | |
| +**Common causes** | |
| +- Provider latency spike | |
| +- Very large prompt or repository | |
| +- Provider queue saturation | |
| + | |
| +**Recommended fix** | |
| +1. Retry with a smaller ZIP | |
| +2. Switch to a faster preset like Groq or Claude Haiku | |
| +3. Use Private Mode for small/local tasks | |
| + | |
| +### समस्या #5: Custom model is used even when disabled | |
| + | |
| +**Symptoms:** Router keeps picking a model after you thought it was inactive. | |
| + | |
| +**Common causes** | |
| +- always_use is enabled | |
| +- Task rules still match any task | |
| +- Priority order favors that model | |
| + | |
| +**Recommended fix** | |
| +1. Edit the model and disable always_use | |
| +2. Change task_types from any to specific categories | |
| +3. Adjust the rule priority matrix | |
| + | |
| +### समस्या #6: Base URL looks correct but requests fail | |
| + | |
| +**Symptoms:** Connection test fails with network or 404 errors. | |
| + | |
| +**Common causes** | |
| +- Provider endpoint missing /v1 | |
| +- Anthropic direct uses /messages instead of /chat/completions | |
| +- Proxy strips auth headers | |
| + | |
| +**Recommended fix** | |
| +1. Verify the endpoint in provider docs | |
| +2. Use the built-in preset instead of manual typing | |
| +3. Try a direct provider endpoint to isolate the issue | |
| + | |
| +### समस्या #7: Saved model disappears after restart | |
| + | |
| +**Symptoms:** A model is visible in-session but missing later. | |
| + | |
| +**Common causes** | |
| +- Master key changed | |
| +- Encrypted file corrupted | |
| +- Data directory permissions issue | |
| + | |
| +**Recommended fix** | |
| +1. Reuse the same master key | |
| +2. Restore data/custom_models.enc.json from backup | |
| +3. Ensure the process can write to the data folder | |
| + | |
| +### समस्या #8: Quota bar never updates | |
| + | |
| +**Symptoms:** Model card always shows unknown quota. | |
| + | |
| +**Common causes** | |
| +- Provider does not expose headers | |
| +- First request never completed successfully | |
| +- Proxy removed rate-limit headers | |
| + | |
| +**Recommended fix** | |
| +1. Run one successful generation | |
| +2. Use a direct provider endpoint if quota visibility matters | |
| +3. Treat the bar as optional and rely on provider dashboard billing | |
| + | |
| +### समस्या #9: Anthropic direct fails while OpenRouter works | |
| + | |
| +**Symptoms:** Claude via Anthropic shows HTTP errors. | |
| + | |
| +**Common causes** | |
| +- Anthropic key pasted into OpenRouter provider | |
| +- Account lacks billing | |
| +- Model name typo | |
| + | |
| +**Recommended fix** | |
| +1. Select Anthropic direct provider | |
| +2. Check billing and usage limits | |
| +3. Use a preset rather than a hand-typed model ID | |
| + | |
| +### समस्या #10: OpenRouter free tier is rate-limited | |
| + | |
| +**Symptoms:** Requests work, then suddenly slow down or fail. | |
| + | |
| +**Common causes** | |
| +- Free tier cap reached | |
| +- Burst traffic from multiple runs | |
| +- No paid balance | |
| + | |
| +**Recommended fix** | |
| +1. Wait for the reset window | |
| +2. Use a paid key or alternate provider | |
| +3. Route simple tasks to a cheaper preset | |
| + | |
| +### समस्या #11: Task Rules matrix saves unexpected priorities | |
| + | |
| +**Symptoms:** The top model in cards differs from the table order. | |
| + | |
| +**Common causes** | |
| +- Priority value duplicates | |
| +- Higher min complexity wins ties | |
| +- Model list sorted after save | |
| + | |
| +**Recommended fix** | |
| +1. Give each model a unique priority | |
| +2. Check min_complexity values | |
| +3. Refresh the panel after saving | |
| + | |
| +### समस्या #12: Local fallback quality is poor | |
| + | |
| +**Symptoms:** Fallback works but output quality drops noticeably. | |
| + | |
| +**Common causes** | |
| +- Fallback switched to small local model | |
| +- Task too complex for local model | |
| +- Prompt too large for context | |
| + | |
| +**Recommended fix** | |
| +1. Use ask_new_key for critical work | |
| +2. Trim prompt size | |
| +3. Reserve local fallback for continuation, not best quality | |
| + | |
| +### समस्या #13: Edit modal requires a new key unexpectedly | |
| + | |
| +**Symptoms:** Changing provider or model ID forces key replacement. | |
| + | |
| +**Common causes** | |
| +- Security design prevents silent target change | |
| +- Provider changed endpoints | |
| + | |
| +**Recommended fix** | |
| +1. Paste a new key when changing provider/model target | |
| +2. Keep provider/model unchanged to reuse the stored encrypted key | |
| + | |
| +### समस्या #14: Model ID preset dropdown is empty | |
| + | |
| +**Symptoms:** Provider selected but no popular models appear. | |
| + | |
| +**Common causes** | |
| +- provider_presets.json missing | |
| +- Provider not curated | |
| +- JSON failed to load | |
| + | |
| +**Recommended fix** | |
| +1. Validate data/provider_presets.json | |
| +2. Choose a curated provider preset | |
| +3. Restart the app after restoring the file | |
| + | |
| +### समस्या #15: Tour never starts | |
| + | |
| +**Symptoms:** First-run experience does not appear. | |
| + | |
| +**Common causes** | |
| +- localStorage already marks it complete | |
| +- Advanced options never opened | |
| +- CDN blocked | |
| + | |
| +**Recommended fix** | |
| +1. Use the Restart onboarding tour button in About | |
| +2. Open Advanced options once | |
| +3. Allow driver.js CDN or self-host the asset | |
| + | |
| +## 9. Advanced: Custom endpoints | |
| + | |
| +### Supported patterns | |
| +- **vLLM** — self-hosted OpenAI-compatible gateway for large models. | |
| +- **LiteLLM proxy** — multi-provider normalization layer with your own routing/billing policies. | |
| +- **LM Studio HTTP server** — local desktop endpoint for experimentation. | |
| +- **Ollama via proxy bridge** — useful when a team wants a unified OpenAI-compatible URL. | |
| + | |
| +### Endpoint checklist | |
| +- Base URL सही `/v1` prefix के साथ दें। | |
| +- Auth header behavior verify करें। | |
| +- Large context claims को manually test करें। | |
| +- 401/403 और 429 status codes proxy preserve कर रहा हो। | |
| + | |
| +### Example endpoint patterns | |
| +```text | |
| +https://api.openai.com/v1 | |
| +https://api.together.xyz/v1 | |
| +https://api.groq.com/openai/v1 | |
| +https://your-vllm-gateway.example.com/v1 | |
| +http://localhost:1234/v1 | |
| +``` | |
| + | |
| +## 10. FAQ | |
| + | |
| +### क्या मुझे हर provider के लिए अलग API key चाहिए? | |
| +हाँ। हर direct provider की अपनी key होती है। OpenRouter एक key से कई models दे सकता है। | |
| + | |
| +### क्या master key भूलने पर keys recover होंगी? | |
| +नहीं। सुरक्षा कारणों से encrypted keys दोबारा नहीं निकाली जा सकतीं; models फिर से जोड़ने पड़ेंगे। | |
| + | |
| +### क्या custom models local models को replace कर देंगे? | |
| +नहीं। यह तीसरी tier है; local models हमेशा available रहते हैं। | |
| + | |
| +### क्या मैं सिर्फ़ free models use कर सकता हूँ? | |
| +हाँ, cost-conscious preset इसी use case के लिए है। | |
| + | |
| +### क्या fallback local model हमेशा exact same answer देगा? | |
| +नहीं, पर pipeline continue रहेगी और context बचा रहेगा। | |
| + | |
| +### क्या provider presets editable हैं? | |
| +हाँ, JSON curated defaults है; आप manual values भी डाल सकते हैं। | |
| + | |
| +### क्या docs और KB offline पढ़े जा सकते हैं? | |
| +हाँ, release ZIP के docs folder में markdown files रहेंगी। | |
| + | |
| +### क्या custom endpoints supported हैं? | |
| +हाँ, अगर endpoint OpenAI-compatible है या आप custom base URL दे सकते हैं। | |
| + | |
| +### क्या billing app के अंदर होती है? | |
| +नहीं। billing provider dashboard पर होती है; app सिर्फ़ estimation दिखाता है। | |
| + | |
| +### क्या team repo में ये feature merge-safe है? | |
| +हाँ, क्योंकि storage JSON-based है और existing APIs unchanged हैं। | |
| + | |
| +### क्या कोई database migration चाहिए? | |
| +नहीं। Feature additive है और JSON-based storage use करता है। | |
| + | |
| +### क्या screenshots to code flow पर भी custom models apply होंगे? | |
| +हाँ, जहाँ routing allows और provider capable हो। | |
| + | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/docs/MIGRATION_v4.6_to_v4.7.md devai_phase4/docs/MIGRATION_v4.6_to_v4.7.md | |
| --- devai_phase4_orig/docs/MIGRATION_v4.6_to_v4.7.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/docs/MIGRATION_v4.6_to_v4.7.md 2026-07-06 10:28:32.013919928 +0000 | |
| +# DevAI Studio v4.6 → v4.7 Migration Guide | |
| + | |
| +## Table of contents | |
| +1. Scope | |
| +2. Compatibility guarantees | |
| +3. Pre-upgrade checklist | |
| +4. Deployment steps | |
| +5. Validation checklist | |
| +6. Rollback procedure | |
| +7. FAQ | |
| + | |
| +## 1. Scope | |
| +- This guide upgrades a working v4.6 deployment to v4.7 with BYOM support. | |
| +- The feature is additive and JSON-based. | |
| + | |
| +## 2. Compatibility guarantees | |
| +- All v4.6 APIs remain unchanged. | |
| +- Existing local-model and built-in cloud flows keep working. | |
| +- No database migration is required. | |
| +- No mandatory environment variables are introduced. | |
| +- Breaking changes: **zero**. | |
| + | |
| +## 3. Pre-upgrade checklist | |
| +- Keep a backup copy of the current v4.6 ZIP. | |
| +- Record the current commit/tag and release artifact name. | |
| +- Confirm `data/custom_models.enc.json` does not exist in v4.6 (expected, feature is new). | |
| +- If you have local edits, export a patch before replacing files. | |
| + | |
| +## 4. Deployment steps | |
| +1. Stop the running v4.6 app. | |
| +2. Extract the combined v4.7 package over a clean directory. | |
| +3. Preserve your existing environment file if you use one. | |
| +4. Start the app normally; no migration command is needed. | |
| +5. Open About tab and confirm the docs buttons render. | |
| +6. Open Advanced options and verify the three-dot BYOM entry point exists. | |
| + | |
| +## 5. Validation checklist | |
| +- App launches successfully. | |
| +- Existing v4.6 tasks run unchanged. | |
| +- BYOM provider presets load. | |
| +- Tour can be restarted from About. | |
| +- Troubleshooting KB opens from About. | |
| +- No data loss is observed in existing workspace exports or logs. | |
| + | |
| +## 6. Rollback procedure | |
| +1. Stop v4.7. | |
| +2. Restore the saved v4.6 ZIP into a clean directory. | |
| +3. Restore your previous environment file. | |
| +4. Delete any newly created BYOM files only if your deployment policy requires a pristine rollback: | |
| + - `data/provider_presets.json` | |
| + - `ui/onboarding_tour.py` | |
| + - `docs/BYOM_USER_GUIDE_HI.md` | |
| + - `docs/BYOM_USER_GUIDE_EN.md` | |
| + - `docs/MIGRATION_v4.6_to_v4.7.md` | |
| + - `docs/TROUBLESHOOTING_KB.md` | |
| +5. Start v4.6 and run the same smoke tests you used before the upgrade. | |
| + | |
| +## 7. FAQ | |
| +- **Do I need to convert old data?** No. | |
| +- **Do I need new env vars?** No required ones. | |
| +- **Is there any schema migration?** No. | |
| +- **Can I keep the docs folder on rollback?** Yes, if your packaging policy allows it. | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/docs/TROUBLESHOOTING_KB.md devai_phase4/docs/TROUBLESHOOTING_KB.md | |
| --- devai_phase4_orig/docs/TROUBLESHOOTING_KB.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/docs/TROUBLESHOOTING_KB.md 2026-07-06 10:28:32.013919928 +0000 | |
| +# DevAI Studio v4.7 Troubleshooting Knowledge Base | |
| + | |
| +## Table of contents | |
| +1. [Invalid API key on Test Connection](#issue-1-invalid-api-key-on-test-connection) | |
| +2. [Model replies in the wrong language](#issue-2-model-replies-in-the-wrong-language) | |
| +3. [Fallback not triggering on 429](#issue-3-fallback-not-triggering-on-429) | |
| +4. [Pipeline hangs during Coder stage](#issue-4-pipeline-hangs-during-coder-stage) | |
| +5. [Custom model is used even when disabled](#issue-5-custom-model-is-used-even-when-disabled) | |
| +6. [Base URL looks correct but requests fail](#issue-6-base-url-looks-correct-but-requests-fail) | |
| +7. [Saved model disappears after restart](#issue-7-saved-model-disappears-after-restart) | |
| +8. [Quota bar never updates](#issue-8-quota-bar-never-updates) | |
| +9. [Anthropic direct fails while OpenRouter works](#issue-9-anthropic-direct-fails-while-openrouter-works) | |
| +10. [OpenRouter free tier is rate-limited](#issue-10-openrouter-free-tier-is-rate-limited) | |
| +11. [Task Rules matrix saves unexpected priorities](#issue-11-task-rules-matrix-saves-unexpected-priorities) | |
| +12. [Local fallback quality is poor](#issue-12-local-fallback-quality-is-poor) | |
| +13. [Edit modal requires a new key unexpectedly](#issue-13-edit-modal-requires-a-new-key-unexpectedly) | |
| +14. [Model ID preset dropdown is empty](#issue-14-model-id-preset-dropdown-is-empty) | |
| +15. [Tour never starts](#issue-15-tour-never-starts) | |
| +16. [Tour restarts every session](#issue-16-tour-restarts-every-session) | |
| +17. [Security note mentions AES-128 but audit expects Fernet](#issue-17-security-note-mentions-aes-128-but-audit-expects-fernet) | |
| +18. [Provider preset cost seems too low](#issue-18-provider-preset-cost-seems-too-low) | |
| +19. [Migration from v4.6 loses nothing but docs are missing](#issue-19-migration-from-v4.6-loses-nothing-but-docs-are-missing) | |
| +20. [Troubleshooting search via Ctrl+F is hard](#issue-20-troubleshooting-search-via-ctrl+f-is-hard) | |
| +21. [Custom endpoint with LM Studio returns 404](#issue-21-custom-endpoint-with-lm-studio-returns-404) | |
| +22. [vLLM proxy rejects large context requests](#issue-22-vllm-proxy-rejects-large-context-requests) | |
| +23. [Self-hosted proxy masks 401 as 500](#issue-23-self-hosted-proxy-masks-401-as-500) | |
| +24. [API key copy/paste includes newline](#issue-24-api-key-copypaste-includes-newline) | |
| +25. [Budget control expectations are too high](#issue-25-budget-control-expectations-are-too-high) | |
| +26. [JSON file merge conflict on team repo](#issue-26-json-file-merge-conflict-on-team-repo) | |
| +27. [Rules mismatch because task is misclassified](#issue-27-rules-mismatch-because-task-is-misclassified) | |
| +28. [About tab links open a blank page](#issue-28-about-tab-links-open-a-blank-page) | |
| +29. [Demo video is present but silent](#issue-29-demo-video-is-present-but-silent) | |
| +30. [Gradio update changes DOM selectors](#issue-30-gradio-update-changes-dom-selectors) | |
| +31. [Quota exhaustion pauses without resume context](#issue-31-quota-exhaustion-pauses-without-resume-context) | |
| +32. [Enterprise reviewer asks for rollback plan](#issue-32-enterprise-reviewer-asks-for-rollback-plan) | |
| + | |
| +## How to use this document | |
| +- Use the table of contents for anchor links. | |
| +- Use Ctrl+F with the exact symptom phrase shown in bold. | |
| +- Cross-check the About tab docs links if a deployment strips local file routing. | |
| + | |
| +<a id="issue-1-invalid-api-key-on-test-connection"></a> | |
| +### Issue #1: Invalid API key on Test Connection | |
| + | |
| +**Symptoms:** Red ❌ appears after clicking Test Connection. | |
| + | |
| +**Common causes** | |
| +- Extra spaces in the key | |
| +- Wrong provider selected | |
| +- Key revoked or expired | |
| + | |
| +**Recommended fix** | |
| +1. Regenerate the key from the provider dashboard | |
| +2. Paste it again without leading/trailing spaces | |
| +3. Confirm the provider dropdown matches the key type | |
| + | |
| +<a id="issue-2-model-replies-in-the-wrong-language"></a> | |
| +### Issue #2: Model replies in the wrong language | |
| + | |
| +**Symptoms:** Responses ignore the language of the prompt or system instruction. | |
| + | |
| +**Common causes** | |
| +- Model preset optimized for another language | |
| +- Task prompt lacks a language instruction | |
| +- Provider-side system prompt contamination | |
| + | |
| +**Recommended fix** | |
| +1. Add an explicit language instruction to the task | |
| +2. Prefer GPT-4o or Claude Sonnet for multilingual work | |
| +3. Test the model directly in the provider console | |
| + | |
| +<a id="issue-3-fallback-not-triggering-on-429"></a> | |
| +### Issue #3: Fallback not triggering on 429 | |
| + | |
| +**Symptoms:** Pipeline pauses instead of moving to the chosen fallback behavior. | |
| + | |
| +**Common causes** | |
| +- Saved fallback policy is ask_new_key | |
| +- 429 body is returned as a generic error by a proxy | |
| +- Outdated custom model config | |
| + | |
| +**Recommended fix** | |
| +1. Re-open the model card and verify fallback policy | |
| +2. Retest using direct provider endpoint | |
| +3. Save the model again to refresh metadata | |
| + | |
| +<a id="issue-4-pipeline-hangs-during-coder-stage"></a> | |
| +### Issue #4: Pipeline hangs during Coder stage | |
| + | |
| +**Symptoms:** Status remains on coder or reviewer for too long. | |
| + | |
| +**Common causes** | |
| +- Provider latency spike | |
| +- Very large prompt or repository | |
| +- Provider queue saturation | |
| + | |
| +**Recommended fix** | |
| +1. Retry with a smaller ZIP | |
| +2. Switch to a faster preset like Groq or Claude Haiku | |
| +3. Use Private Mode for small/local tasks | |
| + | |
| +<a id="issue-5-custom-model-is-used-even-when-disabled"></a> | |
| +### Issue #5: Custom model is used even when disabled | |
| + | |
| +**Symptoms:** Router keeps picking a model after you thought it was inactive. | |
| + | |
| +**Common causes** | |
| +- always_use is enabled | |
| +- Task rules still match any task | |
| +- Priority order favors that model | |
| + | |
| +**Recommended fix** | |
| +1. Edit the model and disable always_use | |
| +2. Change task_types from any to specific categories | |
| +3. Adjust the rule priority matrix | |
| + | |
| +<a id="issue-6-base-url-looks-correct-but-requests-fail"></a> | |
| +### Issue #6: Base URL looks correct but requests fail | |
| + | |
| +**Symptoms:** Connection test fails with network or 404 errors. | |
| + | |
| +**Common causes** | |
| +- Provider endpoint missing /v1 | |
| +- Anthropic direct uses /messages instead of /chat/completions | |
| +- Proxy strips auth headers | |
| + | |
| +**Recommended fix** | |
| +1. Verify the endpoint in provider docs | |
| +2. Use the built-in preset instead of manual typing | |
| +3. Try a direct provider endpoint to isolate the issue | |
| + | |
| +<a id="issue-7-saved-model-disappears-after-restart"></a> | |
| +### Issue #7: Saved model disappears after restart | |
| + | |
| +**Symptoms:** A model is visible in-session but missing later. | |
| + | |
| +**Common causes** | |
| +- Master key changed | |
| +- Encrypted file corrupted | |
| +- Data directory permissions issue | |
| + | |
| +**Recommended fix** | |
| +1. Reuse the same master key | |
| +2. Restore data/custom_models.enc.json from backup | |
| +3. Ensure the process can write to the data folder | |
| + | |
| +<a id="issue-8-quota-bar-never-updates"></a> | |
| +### Issue #8: Quota bar never updates | |
| + | |
| +**Symptoms:** Model card always shows unknown quota. | |
| + | |
| +**Common causes** | |
| +- Provider does not expose headers | |
| +- First request never completed successfully | |
| +- Proxy removed rate-limit headers | |
| + | |
| +**Recommended fix** | |
| +1. Run one successful generation | |
| +2. Use a direct provider endpoint if quota visibility matters | |
| +3. Treat the bar as optional and rely on provider dashboard billing | |
| + | |
| +<a id="issue-9-anthropic-direct-fails-while-openrouter-works"></a> | |
| +### Issue #9: Anthropic direct fails while OpenRouter works | |
| + | |
| +**Symptoms:** Claude via Anthropic shows HTTP errors. | |
| + | |
| +**Common causes** | |
| +- Anthropic key pasted into OpenRouter provider | |
| +- Account lacks billing | |
| +- Model name typo | |
| + | |
| +**Recommended fix** | |
| +1. Select Anthropic direct provider | |
| +2. Check billing and usage limits | |
| +3. Use a preset rather than a hand-typed model ID | |
| + | |
| +<a id="issue-10-openrouter-free-tier-is-rate-limited"></a> | |
| +### Issue #10: OpenRouter free tier is rate-limited | |
| + | |
| +**Symptoms:** Requests work, then suddenly slow down or fail. | |
| + | |
| +**Common causes** | |
| +- Free tier cap reached | |
| +- Burst traffic from multiple runs | |
| +- No paid balance | |
| + | |
| +**Recommended fix** | |
| +1. Wait for the reset window | |
| +2. Use a paid key or alternate provider | |
| +3. Route simple tasks to a cheaper preset | |
| + | |
| +<a id="issue-11-task-rules-matrix-saves-unexpected-priorities"></a> | |
| +### Issue #11: Task Rules matrix saves unexpected priorities | |
| + | |
| +**Symptoms:** The top model in cards differs from the table order. | |
| + | |
| +**Common causes** | |
| +- Priority value duplicates | |
| +- Higher min complexity wins ties | |
| +- Model list sorted after save | |
| + | |
| +**Recommended fix** | |
| +1. Give each model a unique priority | |
| +2. Check min_complexity values | |
| +3. Refresh the panel after saving | |
| + | |
| +<a id="issue-12-local-fallback-quality-is-poor"></a> | |
| +### Issue #12: Local fallback quality is poor | |
| + | |
| +**Symptoms:** Fallback works but output quality drops noticeably. | |
| + | |
| +**Common causes** | |
| +- Fallback switched to small local model | |
| +- Task too complex for local model | |
| +- Prompt too large for context | |
| + | |
| +**Recommended fix** | |
| +1. Use ask_new_key for critical work | |
| +2. Trim prompt size | |
| +3. Reserve local fallback for continuation, not best quality | |
| + | |
| +<a id="issue-13-edit-modal-requires-a-new-key-unexpectedly"></a> | |
| +### Issue #13: Edit modal requires a new key unexpectedly | |
| + | |
| +**Symptoms:** Changing provider or model ID forces key replacement. | |
| + | |
| +**Common causes** | |
| +- Security design prevents silent target change | |
| +- Provider changed endpoints | |
| + | |
| +**Recommended fix** | |
| +1. Paste a new key when changing provider/model target | |
| +2. Keep provider/model unchanged to reuse the stored encrypted key | |
| + | |
| +<a id="issue-14-model-id-preset-dropdown-is-empty"></a> | |
| +### Issue #14: Model ID preset dropdown is empty | |
| + | |
| +**Symptoms:** Provider selected but no popular models appear. | |
| + | |
| +**Common causes** | |
| +- provider_presets.json missing | |
| +- Provider not curated | |
| +- JSON failed to load | |
| + | |
| +**Recommended fix** | |
| +1. Validate data/provider_presets.json | |
| +2. Choose a curated provider preset | |
| +3. Restart the app after restoring the file | |
| + | |
| +<a id="issue-15-tour-never-starts"></a> | |
| +### Issue #15: Tour never starts | |
| + | |
| +**Symptoms:** First-run experience does not appear. | |
| + | |
| +**Common causes** | |
| +- localStorage already marks it complete | |
| +- Advanced options never opened | |
| +- CDN blocked | |
| + | |
| +**Recommended fix** | |
| +1. Use the Restart onboarding tour button in About | |
| +2. Open Advanced options once | |
| +3. Allow driver.js CDN or self-host the asset | |
| + | |
| +<a id="issue-16-tour-restarts-every-session"></a> | |
| +### Issue #16: Tour restarts every session | |
| + | |
| +**Symptoms:** Users see the tour repeatedly. | |
| + | |
| +**Common causes** | |
| +- localStorage blocked in browser | |
| +- Incognito session | |
| +- Browser privacy extension | |
| + | |
| +**Recommended fix** | |
| +1. Use a standard browser profile | |
| +2. Disable aggressive storage cleaners for the app origin | |
| +3. Treat it as a browser setting rather than an app bug | |
| + | |
| +<a id="issue-17-security-note-mentions-aes-128-but-audit-expects-fernet"></a> | |
| +### Issue #17: Security note mentions AES-128 but audit expects Fernet | |
| + | |
| +**Symptoms:** Documentation wording causes confusion. | |
| + | |
| +**Common causes** | |
| +- Fernet uses AES-128-CBC plus HMAC-SHA256 | |
| +- Reader expects a lower-level cipher description | |
| + | |
| +**Recommended fix** | |
| +1. Document the exact primitive and wrapper name together | |
| +2. Keep the wording consistent across guides and release notes | |
| + | |
| +<a id="issue-18-provider-preset-cost-seems-too-low"></a> | |
| +### Issue #18: Provider preset cost seems too low | |
| + | |
| +**Symptoms:** Estimated bug-fix cost differs from dashboard billing. | |
| + | |
| +**Common causes** | |
| +- Estimate assumes 2K input and 500 output tokens | |
| +- Provider bills cached tokens or additional overhead | |
| +- Round-off in UI | |
| + | |
| +**Recommended fix** | |
| +1. Treat it as a rough planning estimate | |
| +2. Check exact bill in provider console | |
| +3. Adjust your internal budgeting spreadsheet | |
| + | |
| +<a id="issue-19-migration-from-v4.6-loses-nothing-but-docs-are-missing"></a> | |
| +### Issue #19: Migration from v4.6 loses nothing but docs are missing | |
| + | |
| +**Symptoms:** App works, but new guides are absent. | |
| + | |
| +**Common causes** | |
| +- Phase 4 files not deployed | |
| +- Incomplete ZIP extraction | |
| + | |
| +**Recommended fix** | |
| +1. Confirm docs/ folder exists in deployment package | |
| +2. Redeploy using the combined Phase 1-4 archive | |
| + | |
| +<a id="issue-20-troubleshooting-search-via-ctrl+f-is-hard"></a> | |
| +### Issue #20: Troubleshooting search via Ctrl+F is hard | |
| + | |
| +**Symptoms:** Finding issues in KB takes too long. | |
| + | |
| +**Common causes** | |
| +- Heading text inconsistent | |
| +- No anchor-friendly titles | |
| + | |
| +**Recommended fix** | |
| +1. Use the TOC links first | |
| +2. Keep issue titles short and unique | |
| +3. Search the exact symptom phrase in quotes | |
| + | |
| +<a id="issue-21-custom-endpoint-with-lm-studio-returns-404"></a> | |
| +### Issue #21: Custom endpoint with LM Studio returns 404 | |
| + | |
| +**Symptoms:** Local LM Studio server responds but chat route fails. | |
| + | |
| +**Common causes** | |
| +- Wrong port | |
| +- Different API path | |
| +- Server not started in OpenAI-compatible mode | |
| + | |
| +**Recommended fix** | |
| +1. Verify server URL in browser | |
| +2. Use the documented /v1 endpoint | |
| +3. Enable OpenAI compatibility in LM Studio settings | |
| + | |
| +<a id="issue-22-vllm-proxy-rejects-large-context-requests"></a> | |
| +### Issue #22: vLLM proxy rejects large context requests | |
| + | |
| +**Symptoms:** Long prompts fail despite large advertised context. | |
| + | |
| +**Common causes** | |
| +- Server max model len lower than preset value | |
| +- Proxy truncation | |
| +- Model served with smaller rope scaling | |
| + | |
| +**Recommended fix** | |
| +1. Set a realistic context window in your infra | |
| +2. Use a smaller chunking strategy | |
| +3. Test maximum prompt size manually | |
| + | |
| +<a id="issue-23-self-hosted-proxy-masks-401-as-500"></a> | |
| +### Issue #23: Self-hosted proxy masks 401 as 500 | |
| + | |
| +**Symptoms:** App shows generic error while creds are wrong. | |
| + | |
| +**Common causes** | |
| +- Reverse proxy rewrites status code | |
| +- Custom middleware | |
| + | |
| +**Recommended fix** | |
| +1. Inspect proxy logs | |
| +2. Prefer direct provider URL when debugging auth | |
| +3. Update middleware to preserve upstream status | |
| + | |
| +<a id="issue-24-api-key-copypaste-includes-newline"></a> | |
| +### Issue #24: API key copy/paste includes newline | |
| + | |
| +**Symptoms:** Invisible characters break auth. | |
| + | |
| +**Common causes** | |
| +- Clipboard copied from terminal with newline | |
| +- Password manager inserted formatting | |
| + | |
| +**Recommended fix** | |
| +1. Paste into a plain-text editor first | |
| +2. Re-copy from provider dashboard | |
| + | |
| +<a id="issue-25-budget-control-expectations-are-too-high"></a> | |
| +### Issue #25: Budget control expectations are too high | |
| + | |
| +**Symptoms:** User expects hard spend caps inside the app. | |
| + | |
| +**Common causes** | |
| +- Feature only estimates cost; billing lives with provider | |
| +- No provider budget API configured | |
| + | |
| +**Recommended fix** | |
| +1. Use provider-side spend limits | |
| +2. Treat app estimate as advisory | |
| + | |
| +<a id="issue-26-json-file-merge-conflict-on-team-repo"></a> | |
| +### Issue #26: JSON file merge conflict on team repo | |
| + | |
| +**Symptoms:** Two branches modify provider_presets.json differently. | |
| + | |
| +**Common causes** | |
| +- Manual edits to the same preset list | |
| +- Different ordering | |
| + | |
| +**Recommended fix** | |
| +1. Sort presets by provider name | |
| +2. Review both additions before merge | |
| + | |
| +<a id="issue-27-rules-mismatch-because-task-is-misclassified"></a> | |
| +### Issue #27: Rules mismatch because task is misclassified | |
| + | |
| +**Symptoms:** Router picks a model for feature instead of refactor. | |
| + | |
| +**Common causes** | |
| +- Classifier confidence low | |
| +- Prompt mixes multiple intents | |
| + | |
| +**Recommended fix** | |
| +1. Rewrite the task to emphasize the primary intent | |
| +2. Use always_use temporarily for critical flows | |
| + | |
| +<a id="issue-28-about-tab-links-open-a-blank-page"></a> | |
| +### Issue #28: About tab links open a blank page | |
| + | |
| +**Symptoms:** Clicking docs buttons does not show files. | |
| + | |
| +**Common causes** | |
| +- Deployment blocks local file serving | |
| +- Reverse proxy strips /file route | |
| + | |
| +**Recommended fix** | |
| +1. Expose the docs directory in deployment config | |
| +2. Fall back to packaging docs in release ZIP | |
| + | |
| +<a id="issue-29-demo-video-is-present-but-silent"></a> | |
| +### Issue #29: Demo video is present but silent | |
| + | |
| +**Symptoms:** Stakeholder expects narration. | |
| + | |
| +**Common causes** | |
| +- Video is a storyboard walkthrough rather than a recorded voiceover | |
| + | |
| +**Recommended fix** | |
| +1. Use the screenshots plus release notes as the spoken script | |
| +2. Record narration later if needed | |
| + | |
| +<a id="issue-30-gradio-update-changes-dom-selectors"></a> | |
| +### Issue #30: Gradio update changes DOM selectors | |
| + | |
| +**Symptoms:** Tour highlights break after dependency upgrades. | |
| + | |
| +**Common causes** | |
| +- Button or accordion DOM changed | |
| +- driver.js selector stale | |
| + | |
| +**Recommended fix** | |
| +1. Revalidate selectors after any Gradio upgrade | |
| +2. Keep tour hooks tied to explicit elem_id values | |
| + | |
| +<a id="issue-31-quota-exhaustion-pauses-without-resume-context"></a> | |
| +### Issue #31: Quota exhaustion pauses without resume context | |
| + | |
| +**Symptoms:** User adds a new key and loses track of partial progress. | |
| + | |
| +**Common causes** | |
| +- Completed work context not surfaced in current UX | |
| + | |
| +**Recommended fix** | |
| +1. Persist task summary in status panel | |
| +2. Re-run with the same prompt after key update and compare output | |
| + | |
| +<a id="issue-32-enterprise-reviewer-asks-for-rollback-plan"></a> | |
| +### Issue #32: Enterprise reviewer asks for rollback plan | |
| + | |
| +**Symptoms:** Team needs a low-risk revert path. | |
| + | |
| +**Common causes** | |
| +- Change review process requires a documented rollback | |
| + | |
| +**Recommended fix** | |
| +1. Use the migration guide rollback steps | |
| +2. Keep the v4.6 ZIP backup alongside the v4.7 release package | |
| + | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/release_notes_v4.7.md devai_phase4/release_notes_v4.7.md | |
| --- devai_phase4_orig/release_notes_v4.7.md 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/release_notes_v4.7.md 2026-07-06 10:28:32.013919928 +0000 | |
| +# DevAI Studio v4.7 Release Notes | |
| + | |
| +## Highlights | |
| +- Bring Your Own Model (BYOM) is now production-ready. | |
| +- Curated provider presets remove the need to memorize base URLs and model IDs. | |
| +- First-run onboarding tour explains the three-dot workflow. | |
| +- Full Hindi and English user guides are bundled in the release. | |
| +- Migration remains zero-breaking and zero-schema-change. | |
| + | |
| +## Included artifacts | |
| +- Combined Phase 1 + 2 + 3 + 4 source tree | |
| +- `CHANGELOG_v4.7.md` | |
| +- `PHASE4_DIFF.patch` | |
| +- `screenshots/` with 12+ walkthrough images | |
| +- `demo/devai_studio_v4.7_phase4_demo.mp4` | |
| +- `docs/` with user guides, migration guide and troubleshooting KB | |
| + | |
| +## Upgrade risk | |
| +Low. All changes are additive. Existing v4.6 APIs remain unchanged. | |
| Binary files devai_phase4_orig/screenshots/09_provider_presets_overview.png and devai_phase4/screenshots/09_provider_presets_overview.png differ | |
| Binary files devai_phase4_orig/screenshots/10_cost_estimator.png and devai_phase4/screenshots/10_cost_estimator.png differ | |
| Binary files devai_phase4_orig/screenshots/11_example_rule_sets.png and devai_phase4/screenshots/11_example_rule_sets.png differ | |
| Binary files devai_phase4_orig/screenshots/12_onboarding_tour.png and devai_phase4/screenshots/12_onboarding_tour.png differ | |
| Binary files devai_phase4_orig/screenshots/13_docs_hub_about_tab.png and devai_phase4/screenshots/13_docs_hub_about_tab.png differ | |
| Binary files devai_phase4_orig/screenshots/14_quota_exhaustion_storyboard.png and devai_phase4/screenshots/14_quota_exhaustion_storyboard.png differ | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/tests/test_phase4_docs_presets.py devai_phase4/tests/test_phase4_docs_presets.py | |
| --- devai_phase4_orig/tests/test_phase4_docs_presets.py 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/tests/test_phase4_docs_presets.py 2026-07-06 10:26:42.073919928 +0000 | |
| +from pathlib import Path | |
| +import json | |
| + | |
| +ROOT = Path(__file__).resolve().parent.parent | |
| + | |
| + | |
| +def test_provider_presets_catalog_exists(): | |
| + data = json.loads((ROOT / "data/provider_presets.json").read_text(encoding="utf-8")) | |
| + assert len(data["presets"]) >= 6 | |
| + assert len(data["example_rule_sets"]) >= 4 | |
| + | |
| + | |
| +def test_guides_exist_and_share_same_core_sections(): | |
| + hi = (ROOT / "docs/BYOM_USER_GUIDE_HI.md").read_text(encoding="utf-8") | |
| + en = (ROOT / "docs/BYOM_USER_GUIDE_EN.md").read_text(encoding="utf-8") | |
| + for marker in ["1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10."]: | |
| + assert marker in hi | |
| + assert marker in en | |
| + | |
| + | |
| +def test_onboarding_and_ui_hooks_present(): | |
| + tour = (ROOT / "ui/onboarding_tour.py").read_text(encoding="utf-8") | |
| + panel = (ROOT / "ui/custom_models_panel.py").read_text(encoding="utf-8") | |
| + assert "devai_tour_completed_v4.7" in tour | |
| + assert "add-model-btn" in panel | |
| + assert "fallback-radio" in panel | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/ui/custom_models_panel.py devai_phase4/ui/custom_models_panel.py | |
| --- devai_phase4_orig/ui/custom_models_panel.py 2026-07-06 10:20:00.089919928 +0000 | |
| +++ devai_phase4/ui/custom_models_panel.py 2026-07-06 10:28:42.293919928 +0000 | |
| from __future__ import annotations | |
| import html | |
| +import json | |
| import tempfile | |
| from pathlib import Path | |
| -from typing import Any, List, Optional | |
| +from typing import Any, Dict, List, Optional | |
| import gradio as gr | |
| "number", "bool", "str", | |
| ] | |
| +PRESETS_PATH = Path(__file__).resolve().parent.parent / "data" / "provider_presets.json" | |
| + | |
| + | |
| +def _load_presets() -> Dict[str, Any]: | |
| + try: | |
| + return json.loads(PRESETS_PATH.read_text(encoding="utf-8")) | |
| + except Exception: | |
| + return {"presets": [], "example_rule_sets": []} | |
| + | |
| + | |
| +PRESET_DATA = _load_presets() | |
| +PROVIDER_PRESETS = {item.get("provider"): item for item in PRESET_DATA.get("presets", []) if item.get("provider")} | |
| +RULE_SET_PRESETS = {item.get("name"): item for item in PRESET_DATA.get("example_rule_sets", []) if item.get("name")} | |
| +RULE_SET_CHOICES = list(RULE_SET_PRESETS.keys()) | |
| + | |
| + | |
| +def _provider_meta(provider: str) -> Dict[str, Any]: | |
| + return PROVIDER_PRESETS.get(provider, {}) | |
| + | |
| + | |
| +def _provider_summary_html(provider: str) -> str: | |
| + meta = _provider_meta(provider) | |
| + desc = html.escape(str(meta.get("description") or "OpenAI-compatible endpoint")) | |
| + signup = str(meta.get("signup_url") or "") | |
| + docs = str(meta.get("docs_url") or "") | |
| + base_url = str((SUPPORTED_PROVIDERS.get(provider) or {}).get("base_url") or "Custom / user supplied") | |
| + links = [] | |
| + if signup: | |
| + links.append(f'<a href="{html.escape(signup)}" target="_blank">Signup</a>') | |
| + if docs: | |
| + links.append(f'<a href="{html.escape(docs)}" target="_blank">Docs</a>') | |
| + return ( | |
| + '<div class="devai-inline-status ok" style="margin-bottom:12px;">' | |
| + f'<b>{html.escape(str(meta.get("display_name") or provider.title()))}</b><br>{desc}<br>' | |
| + f'<span style="font-size:12px;">Base URL: <code>{html.escape(base_url)}</code></span>' | |
| + + (f'<br><span style="font-size:12px;">{" · ".join(links)}</span>' if links else '') | |
| + + '</div>' | |
| + ) | |
| + | |
| + | |
| +def _popular_choices(provider: str) -> List[str]: | |
| + return [str(item.get("display_name")) for item in _provider_meta(provider).get("popular_models", []) if item.get("display_name")] | |
| + | |
| + | |
| +def _find_popular_model(provider: str, label: str) -> Optional[dict]: | |
| + for item in _provider_meta(provider).get("popular_models", []): | |
| + if str(item.get("display_name")) == str(label): | |
| + return item | |
| + return None | |
| + | |
| + | |
| +def _cost_hint_html(model: Optional[dict], provider: Optional[str] = None) -> str: | |
| + if not model: | |
| + return '<div class="devai-model-sub">Select a popular model to auto-fill model_id, endpoint and a rough cost hint.</div>' | |
| + cost = dict(model.get("approx_cost_per_1k_tokens") or {}) | |
| + input_cost = float(cost.get("input", 0) or 0) | |
| + output_cost = float(cost.get("output", 0) or 0) | |
| + typical = (input_cost * 2.0) + (output_cost * 0.5) | |
| + ctx = model.get("context_window") | |
| + best_for = ", ".join(model.get("best_for") or ["any"]) | |
| + notes = model.get("notes") | |
| + parts = [f'≈ ${typical:.2f} per typical bug fix (2K in / 500 out tokens)', f'Best for: {html.escape(best_for)}'] | |
| + if ctx: | |
| + parts.append(f'Context: {int(ctx):,} tokens') | |
| + if notes: | |
| + parts.append(html.escape(str(notes))) | |
| + return '<div class="devai-inline-status ok">' + '<br>'.join(parts) + '</div>' | |
| + | |
| + | |
| +def _rule_set_defaults(rule_name: str, current_model_id: str = "", current_label: str = ""): | |
| + preset = RULE_SET_PRESETS.get(rule_name) or {} | |
| + rules = list(preset.get("rules") or []) | |
| + selected = rules[0] if rules else {} | |
| + needle_id = str(current_model_id or "").lower() | |
| + needle_label = str(current_label or "").lower() | |
| + for rule in rules: | |
| + target = str(rule.get("model") or "").lower() | |
| + if needle_id and needle_id in target: | |
| + selected = rule | |
| + break | |
| + if needle_label and needle_label.split(' (')[0] in target: | |
| + selected = rule | |
| + break | |
| + fallback = "local_model" if rule_name == "Privacy-hybrid" else "ask_new_key" | |
| + return list(selected.get("task_types") or ["any"]), int(selected.get("min_complexity", 0) or 0), bool(selected.get("always_use")), fallback | |
| + | |
| + | |
| CUSTOM_MODELS_CSS = """ | |
| <style> | |
| .devai-custom-models-root { position: relative; } | |
| def _empty_state() -> str: | |
| return ( | |
| - '<div class="devai-empty-state">' | |
| + '<div id="devai-model-list-anchor" class="devai-empty-state devai-model-card">' | |
| '<div class="devai-empty-illu">🧠✨</div>' | |
| '<div style="font-weight:700;font-size:16px;">No custom models yet</div>' | |
| '<div style="font-size:13px;color:#6b7280;margin-top:6px;">Get started by adding your first model.</div>' | |
| f' <div class="devai-quota-bar"><div class="devai-quota-fill {cls}" style="width:{pct:.1f}%;"></div></div>' | |
| '</div>' | |
| ) | |
| - return "".join(parts) | |
| + return '<div id="devai-model-list-anchor">' + ''.join(parts) + '</div>' | |
| def _rules_table(models: List[dict]) -> List[List[Any]]: | |
| with gr.Group(visible=False, elem_classes=["devai-modal-overlay"], elem_id="devai-cm-menu") as menu_group: | |
| gr.HTML('<div class="devai-modal-title">🎨 Custom AI Models</div>') | |
| gr.HTML('<div class="devai-modal-subtitle">अपने personal API keys से कोई भी OpenAI-compatible मॉडल जोड़ें</div>') | |
| - add_new_btn = gr.Button("➕ अपना AI मॉडल जोड़ें", variant="primary") | |
| + add_new_btn = gr.Button("➕ अपना AI मॉडल जोड़ें", variant="primary", elem_id="add-model-btn") | |
| models_display = gr.HTML(value=_empty_state()) | |
| with gr.Row(): | |
| edit_rules_btn = gr.Button("⚙️ Task Rules", size="sm") | |
| with gr.Group(visible=False, elem_classes=["devai-modal-overlay"], elem_id="devai-cm-add-modal") as add_modal: | |
| gr.HTML('<div class="devai-modal-title">➕ नया AI Model जोड़ें</div>') | |
| - gr.HTML('<div class="devai-modal-subtitle">यह model तभी use होगा जब आप rules में specify करेंगे</div>') | |
| + gr.HTML('<div class="devai-modal-subtitle">Provider preset, popular model और rule-set starter के साथ 60-second setup</div>') | |
| + add_provider_help = gr.HTML(_provider_summary_html("openrouter")) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| add_name = gr.Textbox(label="Model Name (आपका पहचानने के लिए)", placeholder="e.g., My Claude 3.5 for security audits", max_lines=1) | |
| add_provider = gr.Dropdown(label="Provider", choices=list(SUPPORTED_PROVIDERS.keys()), value="openrouter", info="OpenRouter सबसे flexible है (100+ models)") | |
| - add_base_url = gr.Textbox(label="Base URL (सिर्फ़ 'custom' provider के लिए)", placeholder="https://your-endpoint.com/v1", visible=False, max_lines=1) | |
| + add_popular_model = gr.Dropdown(label="Popular models", choices=_popular_choices("openrouter"), value=None, info="Curated presets — model_id याद रखने की ज़रूरत नहीं") | |
| + add_base_url = gr.Textbox(label="Base URL (सिर्फ़ 'custom' provider के लिए)", placeholder="https://your-endpoint.com/v1", visible=False, max_lines=1, value="https://openrouter.ai/api/v1") | |
| add_model_id = gr.Textbox(label="Model ID (provider के docs से copy करें)", placeholder="anthropic/claude-3.5-sonnet", max_lines=1) | |
| add_api_key = gr.Textbox(label="🔑 API Key", placeholder="sk-or-v1-...", type="password", max_lines=1, info="Encrypted at rest with your master key. कभी logs में नहीं दिखेगी।") | |
| + add_cost_hint = gr.HTML(_cost_hint_html(None, "openrouter")) | |
| with gr.Column(scale=1): | |
| - gr.HTML("<div style='font-weight:700;color:#6d28d9;margin-bottom:8px;'>📌 यह मॉडल कब use हो?</div>") | |
| - add_task_types = gr.CheckboxGroup(label="Task types", choices=TASK_CHOICES, value=["any"]) | |
| - add_complexity = gr.Slider(label="Minimum complexity (0=कोई भी, 10=बहुत जटिल)", minimum=0, maximum=10, value=0, step=1, info="0 रखें अगर हर task पर use करना है") | |
| - add_always_use = gr.Checkbox(label="⚡ हमेशा use करें (override सारे rules)", value=False) | |
| - add_fallback = gr.Radio(choices=[("नई API key माँगो (pause pipeline)", "ask_new_key"), ("Local model पर switch करो (task-mapping के अनुसार)", "local_model")], value="ask_new_key", label="📉 जब API limit ख़त्म हो") | |
| + with gr.Group(elem_id="task-rules-section"): | |
| + gr.HTML("<div style='font-weight:700;color:#6d28d9;margin-bottom:8px;'>📌 यह मॉडल कब use हो?</div>") | |
| + add_rule_set = gr.Dropdown(label="Load Example Rule Set", choices=RULE_SET_CHOICES, value=None, info="One click से starter routing rules भरें") | |
| + add_task_types = gr.CheckboxGroup(label="Task types", choices=TASK_CHOICES, value=["any"]) | |
| + add_complexity = gr.Slider(label="Minimum complexity (0=कोई भी, 10=बहुत जटिल)", minimum=0, maximum=10, value=0, step=1, info="0 रखें अगर हर task पर use करना है") | |
| + add_always_use = gr.Checkbox(label="⚡ हमेशा use करें (override सारे rules)", value=False) | |
| + add_fallback = gr.Radio(choices=[("नई API key माँगो (pause pipeline)", "ask_new_key"), ("Local model पर switch करो (task-mapping के अनुसार)", "local_model")], value="ask_new_key", label="📉 जब API limit ख़त्म हो", elem_id="fallback-radio") | |
| add_status = gr.HTML("") | |
| with gr.Row(): | |
| add_test_btn = gr.Button("🔌 Test Connection", variant="secondary") | |
| False, | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| - "", "openrouter", gr.update(value="", visible=False), "", "", | |
| + "", "openrouter", _provider_summary_html("openrouter"), gr.update(choices=_popular_choices("openrouter"), value=None), | |
| + gr.update(value=(SUPPORTED_PROVIDERS.get("openrouter") or {}).get("base_url") or "", visible=False), | |
| + "", "", _cost_hint_html(None, "openrouter"), None, | |
| ["any"], 0, False, "ask_new_key", "", | |
| ) | |
| + def handle_provider_change(provider: str): | |
| + base = (SUPPORTED_PROVIDERS.get(provider) or {}).get("base_url") or "" | |
| + return ( | |
| + _provider_summary_html(provider), | |
| + gr.update(choices=_popular_choices(provider), value=None), | |
| + gr.update(value=base, visible=(provider == "custom")), | |
| + "", | |
| + _cost_hint_html(None, provider), | |
| + ) | |
| + | |
| def toggle_base_url_visibility(provider: str): | |
| - return gr.update(visible=(provider == "custom")) | |
| + base = (SUPPORTED_PROVIDERS.get(provider) or {}).get("base_url") or "" | |
| + return gr.update(value=base, visible=(provider == "custom")) | |
| + | |
| + def apply_popular_model(provider: str, popular_label: str, current_name: str): | |
| + meta = _find_popular_model(provider, popular_label or "") | |
| + if not meta: | |
| + return current_name, "", gr.update(value=(SUPPORTED_PROVIDERS.get(provider) or {}).get("base_url") or "", visible=(provider == "custom")), _cost_hint_html(None, provider) | |
| + suggested_name = (current_name or "").strip() or str(meta.get("display_name") or "") | |
| + base = (SUPPORTED_PROVIDERS.get(provider) or {}).get("base_url") or "" | |
| + return suggested_name, str(meta.get("model_id") or ""), gr.update(value=base, visible=(provider == "custom")), _cost_hint_html(meta, provider) | |
| + | |
| + def apply_rule_set(rule_name: str, popular_label: str, model_id: str): | |
| + if not rule_name: | |
| + return ["any"], 0, False, "ask_new_key", "" | |
| + tasks, complexity, always_use, fallback = _rule_set_defaults(rule_name, model_id, popular_label) | |
| + return tasks, complexity, always_use, fallback, _status_html(f"Loaded rule set: {rule_name}", ok=True) | |
| def _build_rules(task_types, complexity, always_use, fallback, priority=None): | |
| tasks = list(task_types or []) or ["any"] | |
| ) | |
| add_new_btn.click( | |
| fn=show_add_modal, | |
| - outputs=[menu_open_state, menu_group, add_modal, add_name, add_provider, add_base_url, add_model_id, add_api_key, add_task_types, add_complexity, add_always_use, add_fallback, add_status], | |
| + outputs=[menu_open_state, menu_group, add_modal, add_name, add_provider, add_provider_help, add_popular_model, add_base_url, add_model_id, add_api_key, add_cost_hint, add_rule_set, add_task_types, add_complexity, add_always_use, add_fallback, add_status], | |
| ) | |
| - add_provider.change(fn=toggle_base_url_visibility, inputs=[add_provider], outputs=[add_base_url]) | |
| + add_provider.change(fn=handle_provider_change, inputs=[add_provider], outputs=[add_provider_help, add_popular_model, add_base_url, add_model_id, add_cost_hint]) | |
| + add_popular_model.change(fn=apply_popular_model, inputs=[add_provider, add_popular_model, add_name], outputs=[add_name, add_model_id, add_base_url, add_cost_hint]) | |
| + add_rule_set.change(fn=apply_rule_set, inputs=[add_rule_set, add_popular_model, add_model_id], outputs=[add_task_types, add_complexity, add_always_use, add_fallback, add_status]) | |
| add_test_btn.click(fn=test_connection_handler, inputs=[add_name, add_provider, add_model_id, add_api_key, add_base_url, master_key_state], outputs=[add_status]) | |
| add_save_btn.click( | |
| fn=save_model_handler, | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/ui/gradio_ui.py devai_phase4/ui/gradio_ui.py | |
| --- devai_phase4_orig/ui/gradio_ui.py 2026-07-06 10:20:00.089919928 +0000 | |
| +++ devai_phase4/ui/gradio_ui.py 2026-07-06 10:26:42.069919928 +0000 | |
| preview_project_contents, | |
| ) | |
| from ui.custom_models_panel import render_custom_models_panel | |
| +from ui.onboarding_tour import render_tour | |
| try: | |
| from core.graph_mapper import build_graph, export_cytoscape_json | |
| system_info_fn() -> dict | |
| """ | |
| info = system_info_fn() or {} | |
| + docs_root = Path(__file__).resolve().parent.parent / "docs" | |
| model_choices = list(info.get("router_models") or []) | |
| key_status = info.get("key_status", {}) | |
| router_default = info.get("router_default") or (model_choices[0] if model_choices else AUTO_MODEL_OPTION) | |
| file_types=[".zip"], | |
| file_count="single", | |
| ) | |
| - with gr.Accordion("Advanced options", open=False): | |
| + with gr.Accordion("Advanced options", open=False, elem_id="devai-advanced-options"): | |
| enable_jury = gr.Checkbox( | |
| label="Enable multi-model Jury vote (slower, uses all 4 models)", | |
| value=False, | |
| custom_panel = render_custom_models_panel( | |
| master_key_state=master_key_state | |
| ) | |
| + render_tour(show_restart_button=False) | |
| master_api_hidden = gr.Textbox( | |
| value="", | |
| elem_id="devai-master-api-hidden", | |
| + pretty | |
| + "\n\n**Stack:** Python · Gradio · OpenRouter free-tier · Piston sandbox" | |
| ) | |
| + gr.Markdown("### 📚 BYOM docs, migration and help") | |
| + gr.HTML( | |
| + f""" | |
| + <div style='display:flex;flex-wrap:wrap;gap:12px;margin:8px 0 16px;'> | |
| + <a class='devai-doc-btn' href='/file={docs_root / "BYOM_USER_GUIDE_HI.md"}' target='_blank' style='padding:10px 16px;border-radius:999px;background:#f3e8ff;color:#6d28d9;text-decoration:none;font-weight:600;border:1px solid #ddd6fe;'>📖 User Guide (HI)</a> | |
| + <a class='devai-doc-btn' href='/file={docs_root / "BYOM_USER_GUIDE_EN.md"}' target='_blank' style='padding:10px 16px;border-radius:999px;background:#f3e8ff;color:#6d28d9;text-decoration:none;font-weight:600;border:1px solid #ddd6fe;'>📘 User Guide (EN)</a> | |
| + <a class='devai-doc-btn' href='/file={docs_root / "MIGRATION_v4.6_to_v4.7.md"}' target='_blank' style='padding:10px 16px;border-radius:999px;background:#f3e8ff;color:#6d28d9;text-decoration:none;font-weight:600;border:1px solid #ddd6fe;'>🚚 Migration Guide</a> | |
| + <a class='devai-doc-btn' href='/file={docs_root / "TROUBLESHOOTING_KB.md"}' target='_blank' style='padding:10px 16px;border-radius:999px;background:#fef2f2;color:#be123c;text-decoration:none;font-weight:600;border:1px solid #fecaca;'>🐛 Troubleshooting</a> | |
| + </div> | |
| + """ | |
| + ) | |
| + render_tour(show_restart_button=True) | |
| return demo | |
| diff -ruN '--exclude=__pycache__' '--exclude=*.pyc' devai_phase4_orig/ui/onboarding_tour.py devai_phase4/ui/onboarding_tour.py | |
| --- devai_phase4_orig/ui/onboarding_tour.py 1970-01-01 00:00:00.000000000 +0000 | |
| +++ devai_phase4/ui/onboarding_tour.py 2026-07-06 10:26:42.069919928 +0000 | |
| +"""First-run onboarding tour for BYOM feature using driver.js.""" | |
| +from __future__ import annotations | |
| + | |
| +import gradio as gr | |
| + | |
| +TOUR_JS = """ | |
| +<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/driver.js@1.3.6/dist/driver.css" /> | |
| +<script src="https://cdn.jsdelivr.net/npm/driver.js@1.3.6/dist/driver.js.iife.js"></script> | |
| +<script> | |
| +(() => { | |
| + if (window.__devaiTourBootstrapped) return; | |
| + window.__devaiTourBootstrapped = true; | |
| + const TOUR_KEY = 'devai_tour_completed_v4.7'; | |
| + const waitFor = (selector, timeout=10000) => new Promise((resolve) => { | |
| + const start = Date.now(); | |
| + const tick = () => { | |
| + const el = document.querySelector(selector); | |
| + if (el) return resolve(el); | |
| + if (Date.now() - start > timeout) return resolve(null); | |
| + setTimeout(tick, 200); | |
| + }; | |
| + tick(); | |
| + }); | |
| + const visible = (el) => !!el && el.offsetParent !== null; | |
| + async function prepTour() { | |
| + const three = await waitFor('.devai-three-dot-btn'); | |
| + if (!three) return false; | |
| + if (!visible(three)) return false; | |
| + three.click(); | |
| + await new Promise(r => setTimeout(r, 500)); | |
| + const addBtn = await waitFor('#add-model-btn'); | |
| + if (addBtn && visible(addBtn)) addBtn.click(); | |
| + await new Promise(r => setTimeout(r, 500)); | |
| + return true; | |
| + } | |
| + window.startDevAITour = async function(force=false) { | |
| + if (!force && localStorage.getItem(TOUR_KEY)) return; | |
| + if (!window.driver || !window.driver.js) return; | |
| + const ok = await prepTour(); | |
| + if (!ok) return; | |
| + const driverObj = window.driver.js.driver({ | |
| + showProgress: true, | |
| + allowClose: true, | |
| + nextBtnText: 'आगे →', | |
| + prevBtnText: '← पीछे', | |
| + doneBtnText: 'Done ✓', | |
| + onDestroyed: () => localStorage.setItem(TOUR_KEY, 'true'), | |
| + steps: [ | |
| + { element: '.devai-three-dot-btn', popover: { title: '✨ नया: Custom AI Models', description: 'यहाँ से अपने personal API keys के साथ Claude, GPT, Gemini या कोई भी OpenAI-compatible model जोड़ें।' } }, | |
| + { element: '#add-model-btn', popover: { title: 'Model जोड़ना', description: 'Provider preset चुनें, popular model चुनें, API key डालें और DevAI Studio बाकी fields auto-fill कर देगा।' } }, | |
| + { element: '#task-rules-section', popover: { title: 'Task Rules ⚙️', description: 'यह model कब use हो? हर task पर, सिर्फ़ security audits पर, या complexity threshold के बाद — सब यहाँ तय होता है।' } }, | |
| + { element: '#fallback-radio', popover: { title: 'Fallback Policy 📉', description: 'Quota खत्म हो जाए तो नई key माँगनी है या local model पर continue करना है — यह भी आप control करते हैं।' } }, | |
| + { element: '#devai-model-list-anchor', popover: { title: 'Model Cards', description: 'Saved models, quota hints और routing priority यहाँ दिखेगी। यहीं से edit/update भी कर सकते हैं।' } }, | |
| + ], | |
| + }); | |
| + driverObj.drive(); | |
| + }; | |
| + const boot = () => { | |
| + if (localStorage.getItem(TOUR_KEY)) return; | |
| + let started = false; | |
| + const tick = () => { | |
| + if (started) return; | |
| + const three = document.querySelector('.devai-three-dot-btn'); | |
| + if (visible(three)) { | |
| + started = true; | |
| + setTimeout(() => window.startDevAITour(false), 1200); | |
| + } else { | |
| + setTimeout(tick, 700); | |
| + } | |
| + }; | |
| + tick(); | |
| + }; | |
| + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); | |
| + else boot(); | |
| +})(); | |
| +</script> | |
| +""" | |
| + | |
| + | |
| +def render_tour(show_restart_button: bool = True): | |
| + gr.HTML(TOUR_JS) | |
| + if show_restart_button: | |
| + restart_btn = gr.Button('🔄 Restart onboarding tour', size='sm') | |
| + restart_btn.click(fn=None, js="() => { localStorage.removeItem('devai_tour_completed_v4.7'); window.startDevAITour(true); }") | |
| + return restart_btn | |
| + return None | |