- 24 Apr, 2026 24 commits
-
-
Stefy Lanza (nextime / spora ) authored
fix: use importlib.util.find_spec instead of import aisbf to avoid __init__.py crash on missing providers.json
-
Stefy Lanza (nextime / spora ) authored
fix: dynamically register all _share/ files in package_data — '**' globs in static list were silently dropped by setuptools
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
--system-site-packages only includes system-wide packages (/usr/lib/…); it does NOT include user-installed packages (~/.local/lib/…). When aisbf is installed with pip --user (or auto-detected user mode with --break-system-packages), import aisbf fails inside the venv and the server cannot start. Add _link_user_site_packages() to aisbf.sh: - Determines the user site-packages path via python3 -m site --user-site - Writes a .pth file into the venv's site-packages directory pointing there - Called on venv creation AND on every subsequent run (refresh after upgrades) Also sync aisbf/aisbf.sh (the package-bundled bootstrap copy) to match.
-
Stefy Lanza (nextime / spora ) authored
pip's data_files extraction is unreliable for user installs with --break-system-packages: files either land in the wrong prefix or are silently dropped from the wheel entirely. Fix: build_py hook in setup.py copies main.py, aisbf.sh, requirements.txt, templates/, static/, and config/ into aisbf/_share/ at wheel-build time. These are declared as package_data so pip always installs them to site-packages/aisbf/_share/ regardless of install mode. cli.py now: - Checks all sysconfig-derived paths for a complete share directory - Falls back to bootstrapping: copies the full aisbf/_share/ bundle to ~/.local/share/aisbf/ on first run if data_files were not installed - Works for both wheel installs (uses _share/) and editable installs (uses the project root directly as the bundle source) - Prints a clear error with checked paths and reinstall instructions if bootstrap also fails aisbf/_share/ is gitignored (generated at build time).
-
Stefy Lanza (nextime / spora ) authored
cli.py: - Replace hardcoded paths with sysconfig.get_path('data', scheme) covering all pip install modes (venv, posix_user, posix_prefix, posix_home, system) - Fall back to legacy hardcoded paths for extra safety - Last-resort bootstrap: copy bundled aisbf/aisbf.sh to ~/.local/share/aisbf/ when data_files were not installed by pip (known pip/wheel limitation) - Improved error message with all checked paths and reinstall instructions aisbf.sh: - Replace hardcoded /usr/share/aisbf check (wrong: setup.py installs to /usr/local/share/aisbf) with a Python sysconfig lookup that checks the actual pip data prefix across all known schemes - Derive LOG_DIR from SHARE_DIR instead of duplicating the detection logic Packaging: - Add aisbf/aisbf.sh as package_data so it is always present in the installed aisbf package regardless of data_files extraction success - Add recursive-include aisbf *.sh to MANIFEST.in for sdist - Add aisbf/aisbf.sh to setup.py data_files share/aisbf/aisbf listing -
Stefy Lanza (nextime / spora ) authored
Replace DashboardBlockingMiddleware + APIBlockingMiddleware with a single GenocidalBlockingMiddleware that blocks ALL routes (not just dashboard or API) under any of three conditions: 1. Server's own public IP resolves to Israel — detected once at startup via api.ipify.org + geolocation lookup, stored in _server_ip_blocked flag 2. Host header domain ends with .il (port stripped before check) 3. Connecting client IP resolves to Israel (per-request geolocation lookup) /blocked is always allowed through to avoid redirect loops. API/MCP routes return JSON 403; all other routes redirect to /blocked.
-
Stefy Lanza (nextime / spora ) authored
- Move geolocation.py from repo root into aisbf/ package (correct location) - Fix NameError: call geolocation.get_ip_country() with module prefix in APIBlockingMiddleware - Fix middleware execution order: register DashboardBlockingMiddleware and APIBlockingMiddleware before ProxyHeadersMiddleware so proxy headers are decoded first (last added = first executed in Starlette) - Fix typo: is_ip_genocidial -> is_ip_genocidal in aisbf/geolocation.py - Fix tests: update import path to aisbf.geolocation and use AsyncMock so httpx coroutines are properly awaitable - Add aisbf/geolocation.py and templates/blocked.html to setup.py data_files - Add trailing newlines to geolocation.py, blocked.html, and test file - Add static/i18n.js and static/i18n/*.json locale files
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
- Cache None for non-200 HTTP status codes to avoid repeated failed API calls - Move exception handling cache to except block for consistency
-
Stefy Lanza (nextime / spora ) authored
- Test invalid IP validation returns None without API call - Test caching behavior for repeated calls - Test error handling for API failures
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
fix: response cache stats missing enabled field; tor status reads from JSON config instead of Pydantic singleton
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
- 23 Apr, 2026 7 commits
-
-
Stefy Lanza (nextime / spora ) authored
When a card was added via billing page, it was only stored in the DB — never attached to the Stripe customer. This meant every charge was on an unattached PM, which Stripe processes differently. For subscription upgrades the user is actively present, so off_session=True was incorrect: it marks the charge as a Merchant-Initiated Transaction (MIT) which settles slower than Customer-Initiated (CIT). Other sites that use Stripe's frontend SDK do CITs, which is why their charges clear faster. - dashboard_add_payment_method_stripe: attach PM to Stripe customer and set as customer default immediately when the card is added - auto_charge: add off_session parameter (default True for existing auto top-up/renewal callers); document the distinction - dashboard_subscribe_tier: pass off_session=False so the upgrade charge is processed as a CIT and settles at normal speed
-
Stefy Lanza (nextime / spora ) authored
- auto_charge: verify payment_intent.status is succeeded/processing before returning success; add description/metadata params so subscription charges are labeled correctly in Stripe - pricing: redirect to ?success= after upgrade/downgrade so the persistent server-side banner shows instead of a 1.5s toast that disappears on reload - pricing GET endpoint: pass success/error query params to template context - base modal: support html:true option in open() so showConfirm can render HTML content; update showConfirm signature to accept html flag - pricing: pass html=true to showConfirm so the upgrade confirmation renders bold/colored text instead of raw tags
-
Stefy Lanza (nextime / spora ) authored
- Per-item save/delete API endpoints for providers, rotations, autoselects (admin + user) - Config hot-reload on every change without server restart - Provider list pagination (10/page) with search/filter - Searchable datalist selects for >25 providers or models - Model name autocomplete from provider's configured model list - Fix JS key-escaping bug that broke rendering with special chars in keys
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
Fix Claude CLI streaming: pass-through SSE strings, handle assistant/tool_use events, non-streaming via --output-format json
-
Stefy Lanza (nextime / spora ) authored
Bump version to 0.99.57; add Claude CLI proxy mode - Add aisbf/cli_mode.py: detect claude binary in PATH at startup - Add ClaudeCliSessionManager: per-user isolated temp config dirs with 10-minute idle cleanup and asyncio subprocess-based request proxying - Add ClaudeProviderHandler CLI methods: _get_cli_credentials, _messages_to_cli_prompt, _handle_cli_streaming_request, _handle_cli_request, _oauth_tokens_to_cli_credentials - Wire CLI mode check into _handle_request_with_model; falls through to HTTP API mode when no CLI credentials are configured - Add 'Use Claude CLI mode' checkbox in provider config (both admin and user templates): derives credentials from existing OAuth2 tokens - Add explicit CLI credentials file upload (file_type=cli_credentials); DB users: stored in user_oauth2_credentials; admin: path in providers.json - Update Claude provider warning notices to scope risk to HTTP API mode and clarify that claude -p is permitted by Claude's terms of service - Update CHANGELOG.md, DOCUMENTATION.md, README.md
-
- 22 Apr, 2026 9 commits
-
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
- Fix ReferenceError: url_for is not defined in pricing JS (was calling server-side Jinja2 helper from client-side JavaScript) - Add new POST /dashboard/subscribe/{tier_id} endpoint with smart payment logic: deducts from wallet if sufficient, otherwise charges saved Stripe card for the exact plan amount; returns clear error when neither is available - Add POST /dashboard/subscribe/free for downgrade flow - Fix plan description field names (max_requests_day → max_requests_per_day, etc.) across pricing.html and subscription.html; numbers now formatted with thousands separators - Fix pricing card layout so a single plan is centered and capped in width instead of stretching full-screen - Add is_default and is_active to get_user_tier() return dict - Add upgrade CTA banner in dashboard overview subscription section when higher plans are available - Add subscription hint banner in wallet page - Add new Usage & Quotas page (/dashboard/usage) with progress bars for daily/monthly requests, providers, rotations, autoselections, and tokens; bars warn at 75% and turn red at 90% - Add Usage link to main nav and account dropdown - Register usage.html in setup.py data_files -
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
- Add Reply-To header using sender's email for all contact submissions - Show email input in contact modal for non-logged-in users - Allow unauthenticated contact form submissions (email required) Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Stefy Lanza (nextime / spora ) authored
Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Stefy Lanza (nextime / spora ) authored
- Replace relative DOCUMENTATION.md links in README with absolute Gitea URLs (/blob/master/) - Update dashboard about page regex to rewrite both relative and absolute doc links - Bump version to 0.99.52 Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Stefy Lanza (nextime / spora ) authored
-
Stefy Lanza (nextime / spora ) authored
- Add /dashboard/profile/upload-pic/chunk endpoint: assembles chunks server-side, validates MIME type and 5 MB limit, base64-encodes and stores in DB + session - Remove profile_pic from the form POST (was limited by proxy body size limits) - Profile template: file input triggers JS chunked upload, shows progress bar and inline status; client-side pre-check for size/type before any network request Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
Stefy Lanza (nextime / spora ) authored
- Add DatabaseManager.placeholder property returning '?' (SQLite) or '%s' (MySQL) - Fix paypal_handler.py: payment_methods INSERT - Fix service.py: payment_methods INSERT for PayPal vault - Fix subscription/manager.py: all SQL in create/upgrade/downgrade/cancel_subscription - Fix subscription/renewal.py: all SQL in process_renewals/_renew_subscription/_cancel_subscription Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-