The trial check refused 20 hand-picked domains by exact match, so trial
spam walked around it with any other throwaway provider, any subdomain
of a listed one, or a punycode spelling.
Refuse the community disposable-email-domains list (~9.2k domains, CC0),
installed as its official PyPI package and pinned in uv.lock, plus the
three hand-picked domains it lacks. Match every parent domain short of
the TLD, as upstream requires, and look up the punycode form, since
EmailStr hands the route Unicode. Purchases and resends are unaffected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KrM98FAv8YT3boAVJpf6PW
Comments, docstrings and .env.example notes that cited moved or
deleted plan files now cite their new homes under docs/.
The three llama.cpp checksums in fetch-llamacpp.mjs and a URL-format
example in the backend config are marked `pragma: allowlist secret`.
Touching those files puts them in front of detect-secrets, and both
are false positives.
Co-authored-by: Cursor <cursoragent@cursor.com>
A trial is handed to an email address, not to an installation, so the email now opens with an install link built from NEXT_FRONTEND_URL. Deployments without a portal keep the original steps rather than printing a dead link.
Trial length moves to 30 days so the week before the first plugin ships does not eat half of it. The number is read from LICENSE_TRIAL_DAYS everywhere, including the subject line and the pricing copy, which previously hardcoded 14.
LICENSE_MAIL_TRANSPORT selects how mail leaves the process (null, console, smtp), never which vendor delivers it: every provider exposes SMTP, so changing company means editing the connection strings and leaving this alone.
Reconcile the observability module refactor (god-files split into
core/signals/setup/domains) with 86 upstream commits that kept evolving the
now-deleted otel.py / metrics.py / bootstrap.py.
Ported upstream's net-new telemetry into the new layout instead of dropping it:
- drift-sweep + per-workspace drift-check spans and git-remote
connect/push/sweep spans + counters -> domains/knowledge_store
- video render/admission/segment/verify metrics -> domains/media
- OTEL_EXPORTER_OTLP_LOGS_ENDPOINT added to core.config.is_configured
(log export itself already lived in setup/providers)
Re-swept upstream call-sites that referenced the deleted modules onto domain
imports (remote facade + push task, deliverables sandbox, artifact
verification, drift monitor) and updated the two upstream tests that patched
the old module attributes. Deleted otel.py/metrics.py/bootstrap.py and the
stale test_otel.py.
Verified: 4688 tests collect with zero import errors; observability, sandbox,
artifacts, and knowledge-store-remote unit suites pass. The drift-monitor
integration test needs a live Postgres and is unaffected by this merge.
Drop build_llm_callback_handler from the chat orchestrators and anonymous
route, delete POSTHOG_AI_PRIVACY_MODE, and default LANGSMITH_TRACING off
(dev-only). The anonymous tier gains OtelSpanMiddleware so its LLM calls still
emit gen_ai.* to LGTM. PostHog now carries product analytics only.
Uncomment the DAYTONA_* env passthrough on the backend service and add
DAYTONA_SNAPSHOT_ID, so a deployment that sets SANDBOX_PROVIDER=daytona
actually forwards the key, URL, target, and snapshot into the container.
Document the snapshot name in the compose .env.example.
- Added `SANDBOX_OPERATION_TIMEOUT_SECONDS` to configuration for controlling sandbox operation timeouts.
- Updated various components to utilize the new timeout setting, ensuring consistent timeout behavior across different sandbox providers.
- Refactored execution logic in the sandbox tools to improve error handling and cleanup processes.
- Enhanced tests to validate the new timeout functionality and ensure proper execution flow.
- Updated backend-tests.yml to include OpenSandbox integration for running tests in a sandbox environment.
- Modified docker-build.yml to support building and testing the sandbox image.
- Enhanced docker-compose files to manage sandbox image creation and configuration.
- Added PDF generation skills and scripts for the sandbox, including quality checks and rendering capabilities.
- Updated the .env.example file to include new sandbox settings for code execution, including SANDBOX_ENABLED, SANDBOX_PROVIDER, and session management parameters.
- Modified docker-compose files to reflect the new sandbox environment variables, allowing for easier configuration of cloud execution options.
The video presentation agent built its Kokoro pipeline with a literal
lang_code="a" and took its voice from a hand-rolled provider map that only
ever returned American English. Slides generated from Japanese or Chinese
source content were therefore narrated by an English voice reading text it
could not pronounce.
The podcast pipeline already solved this: a voice catalog with per-language
rosters, a BCP-47 tag normaliser, and a TTS port whose Kokoro adapter maps the
tag to the right pipeline and caches one pipeline per language. The video path
simply sat outside that infrastructure. Route it through the same port instead
of duplicating a second, English-only implementation.
The language now comes from the model that writes the slides, which is the
only component that knows what language it wrote in. An absent or unusable tag
falls back to a new VIDEO_PRESENTATION_DEFAULT_LANGUAGE and finally to English,
so a bad value degrades instead of failing the render.
app/services/kokoro_tts_service.py is removed: routing through the port left it
without a caller, and it also pulled kokoro and torch into the agent's import
chain at module scope.
- Added PostHog configuration options to .env.example files for both Docker and Surfsense backend.
- Introduced PostHog dependency in pyproject.toml.
- Implemented analytics middleware to capture various events across the application, including user authentication, automation runs, and API requests.
- Enhanced existing routes and services to emit analytics events, providing insights into user interactions and system performance.
- Ensured graceful shutdown of analytics clients in worker processes and application lifecycles.
Comments load over a signed /api/comment/list XHR that TikTok serves to
anonymous sessions once the comments panel is opened (unlike profile-video and
general-search feeds), so this is a reliable verb. Given video URLs it returns
CommentItems (text, author, likes, reply counts; replies carry repliesToId),
deduped per video, capped, and degraded to an ErrorItem for empty/withheld
videos or a bad_url ErrorItem for non-video inputs.
Generalizes the browser capture over a pluggable interaction step so the
comments flow (open panel, scroll the panel to paginate) reuses the same
warm+capture scaffolding as listing/user-search. Billed per comment on a new
TIKTOK_COMMENT meter (TIKTOK_MICROS_PER_COMMENT, matching the per-comment
market), surfaced on the chat subagent alongside tiktok.scrape/user_search.
Video/general search is login-walled for anonymous sessions, but the Users
tab (/api/search/user) returns public account records without a redirect, so
this exposes the one reliably-unblocked search path. A keyword yields
TikTokProfileItems (name, followers, bio, verification), deduped per query,
capped, and degraded to an ErrorItem when a query is empty/withheld.
Reuses the browser capture (generalized over XHR markers + extractor) and the
shared profile item shape. Billed per account on a new TIKTOK_USER meter
(TIKTOK_MICROS_PER_USER), surfaced on the chat subagent alongside tiktok.scrape.
- Adjusted Google Maps and YouTube micro pricing in the .env.example file for better cost management.
- Introduced new environment variables for captcha solving and stealth browser hardening to improve scraping resilience.
- Removed outdated smoke test for scraper API endpoints to streamline testing.
- Enhanced anonymous chat agent's system prompt to clarify capabilities and suggest account creation for advanced features.
- Updated Reddit fetch logic to prioritize new session handling and improve resilience against IP-related issues.
- Added compacting functionality for scraper results to optimize data handling and presentation.
- Improved workspace and document management tools with clearer descriptions and enhanced functionality.
- Introduced new UI components for agent setup guidance in the web application.
Add per-item, per-platform billing for the platform-native connectors (Reddit, Google Search, Google Maps places/reviews, YouTube videos/comments) through the capability gate/charge seam. Rates are config-driven with a shared wallet-credit module (wallet_credit) and a dedicated PlatformScrapeCreditService; agent and REST capability runs now record cost_micros. Google Maps scrape dual-meters places and attached reviews.
Remove the main-agent scrape_webpage tool now that the web.crawl capability covers single-page (maxCrawlDepth=0) and site crawling. The main agent now reaches crawling via task(web_crawler, ...). Update prompts, tool catalog, receipts, skills, proprietary docs, and tests; drop the obsolete chat-turn crawl fold path.
Co-authored-by: Cursor <cursoragent@cursor.com>
MCP consolidation:
- Route all MCP-capable connectors (Slack, Jira, Linear, ClickUp, Airtable,
Notion, Confluence, interim Gmail/Calendar, custom MCP) through a single
`mcp_discovery` subagent. Drive/OneDrive/Dropbox stay native to enrich the KB.
- Deprecate Discord/Teams/Luma: no viable official MCP server.
Google-only web search:
- Remove the main-agent `web_search` tool and the SearXNG platform service;
all public web search now flows through the `google_search` subagent via task().
- Deprecate the Tavily/SearXNG/Linkup/Baidu search connectors (HTTP 410 on
create, "Deprecated" badge); guide heavy users to the custom MCP connector.
- Remove web search from anonymous chat (pure Q&A).
- Tear SearXNG out of docker compose + install scripts; drop tavily-python
and linkup-sdk deps and their config/env vars.
Fix:
- metrics._package_version() now swallows any metadata lookup failure. A
malformed editable-install distribution with no `Version` field raised
KeyError deep in importlib.metadata, and since it runs on every
record_subagent_invoke_duration call it was crashing every task()
delegation. Verified end-to-end against live GPT-5.4.
Co-authored-by: Cursor <cursoragent@cursor.com>