Repository navigation
[unified_analytics] Fix Cursor agent check, default agent & add isBot - #2687
Conversation
… tighten Cursor agent detection - Default `agent` in `Analytics` and `Analytics.development` to `AiAgent.detectAgentName(Platform.environment)` when omitted, while keeping `Analytics.fake` hermetic. - Tighten `AiAgent.cursor` detection in `AiAgent.detectAgentName` to check `CURSOR_AGENT` and `CURSOR_EXTENSION_HOST_ROLE=agent-exec` instead of `TERM_PROGRAM=cursor` or arbitrary `CURSOR_*` environment variables (such as `CURSOR_TRACE_ID` in human-opened Cursor IDE terminals). - Add `Analytics.isBot(Map<String, String> environment)` unifying CI and bot environment checks across `flutter_tools` and `dartdev`. Fixes #2670 Fixes #2671
PR HealthCoverage ✔️
This check for test coverage is informational (issues shown here will not fail the PR). This check can be disabled by tagging the PR with License Headers ✔️
All source files should start with a license header. Unrelated files missing license headers
This check can be disabled by tagging the PR with Breaking changes ✔️
This check can be disabled by tagging the PR with Unused Dependencies ✔️
For details on how to fix these, see dependency_validator. This check can be disabled by tagging the PR with
API leaks
|
| Package | Leaked API symbol | Leaking sources |
|---|---|---|
| unified_analytics | Condition | survey_handler.dart::Survey::conditionList survey_handler.dart::Survey::new::conditionList |
| unified_analytics | PersistedSurvey | survey_handler.dart::SurveyHandler::fetchPersistedSurveys |
| unified_analytics | GAClient | analytics.dart::Analytics::fake::gaClient analytics.dart::AnalyticsImpl::new::gaClient |
| unified_analytics | UserProperty | analytics.dart::FakeAnalytics::userProperty |
This check can be disabled by tagging the PR with skip-leaking-check.
Changelog Entry ✔️
| Package | Changed Files |
|---|
Changes to files need to be accounted for in their respective changelogs.
This check can be disabled by tagging the PR with skip-changelog-check (for example, for non-user-visible changes when the package version is already at -wip).
There was a problem hiding this comment.
Code Review
This pull request defaults the agent parameter in Analytics to the detected agent name, refines the detection of the Cursor agent, and introduces Analytics.isBot to identify CI and bot environments. Feedback suggests improving the DartDoc for isBot to align with style guidelines, and handling the TRAVIS and CONTINUOUS_INTEGRATION environment variables case-insensitively along with corresponding test updates.
Default `agent` to `AiAgent.detectAgentName(environment)` in `Analytics.fake` (where `environment` defaults to `const {}`) so unit tests remain hermetic by default while supporting environment-driven `ai_agent` testing.
…tter#194530) Remove `AzureDetector` (`http://169.254.169.254/metadata/instance`) and persistent `is-bot` caching (`PersistentToolState.isRunningOnBot` / `setIsRunningOnBot`) from `BotDetector`, relying strictly on deterministic CI environment variables. - **Remove IMDS probe and disk cache (`bot_detector.dart`, `persistent_tool_state.dart`)**: Eliminates the link-local HTTP probe on tool startup, prevents cloud developer workstations on Azure/GCE/AWS from being permanently misclassified as bots in `.flutter_tool_state`, and removes unused `httpClientFactory` and `persistentToolState` parameters from `BotDetector`. - **Tighten `BOT` and `CI` environment checks (`bot_detector.dart`)**: Treat `BOT=false` and `BOT=0` as explicit non-bot overrides, require `CI` to be non-empty and not `'false'` or `'0'`, accept `BOT=true` or `BOT=1`, and check `AZURE_HTTP_USER_AGENT` alongside `TF_BUILD` (matching `dartdev`). - **Async getter retention**: `Future<bool> get isRunningOnBot` is intentionally kept async (`Future<bool>`) in this PR to avoid churn across the 12 production `await` sites and `FakeBotDetector` in tests; once `package:unified_analytics` rolls with `Analytics.isBot(Map<String, String> environment)` (tracked in dart-lang/tools#2672 / dart-lang/tools#2687), a follow-up PR for flutter#194405 can delegate directly or simplify callers if desired. Part of flutter#194405
Roll `tools_rev` to c1471db9c0fead64394eab4834d0fb640403b42a and replace `dartdev`'s duplicate `_isRunningOnBot` implementation with `Analytics.isBot` from `package:unified_analytics`, which ignores falsy `CI` and `BOT` environment values (`false`, `0`, empty). Rolling `package:unified_analytics` also defaults `Analytics.agent` to `AiAgent.detectAgentName(Platform.environment)` for SDK tools such as `analysis_server` and `dtd` when `agent` is omitted, and tightens `AiAgent.cursor` detection. tools (https://github.com/dart-lang/tools/compare/350bde5..c1471db): c1471db9 Fri Oct 16 09:35:21 2026 -0700 Kevin Moore [unified_analytics] Fix Cursor agent check, default agent & add isBot (dart-lang/tools#2687) 2d0d09a1 Fri Oct 16 15:37:59 2026 +0000 Phil Quitslund [unified_analytics] Prepare for 8.1.0 release (dart-lang/tools#2684) 7ea42bf6 Thu Oct 15 11:13:58 2026 -0700 Kallen Tu Add Event.migrateEvent for the dart migrate tool. (dart-lang/tools#2682) 4eaf46ba Wed Oct 14 18:18:45 2026 +0000 Kevin Moore [markdown] Fix LinkParser edge cases and BlockParser retreat loop (dart-lang/tools#2631) 03f7124a Wed Oct 14 11:15:00 2026 -0700 Kevin Moore [markdown] Add tool/update_spec_tests.dart and sync GFM 0.29.0.gfm.13 spec stats (dart-lang/tools#2666) e0c90075 Tue Oct 13 16:16:23 2026 -0700 Morgan :) [code_builder] publish 4.13.0 (dart-lang/tools#2663) Fixes #64594 Fixes #64591 TEST=pkg/dartdev/test/analytics_test.dart Change-Id: I71026772917d60df2ef144cc5527be9002f087f6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/565421 Commit-Queue: Kevin Moore <[email protected]> Reviewed-by: Keerti Parthasarathy <[email protected]>
…tter#194530) Remove `AzureDetector` (`http://169.254.169.254/metadata/instance`) and persistent `is-bot` caching (`PersistentToolState.isRunningOnBot` / `setIsRunningOnBot`) from `BotDetector`, relying strictly on deterministic CI environment variables. - **Remove IMDS probe and disk cache (`bot_detector.dart`, `persistent_tool_state.dart`)**: Eliminates the link-local HTTP probe on tool startup, prevents cloud developer workstations on Azure/GCE/AWS from being permanently misclassified as bots in `.flutter_tool_state`, and removes unused `httpClientFactory` and `persistentToolState` parameters from `BotDetector`. - **Tighten `BOT` and `CI` environment checks (`bot_detector.dart`)**: Treat `BOT=false` and `BOT=0` as explicit non-bot overrides, require `CI` to be non-empty and not `'false'` or `'0'`, accept `BOT=true` or `BOT=1`, and check `AZURE_HTTP_USER_AGENT` alongside `TF_BUILD` (matching `dartdev`). - **Async getter retention**: `Future<bool> get isRunningOnBot` is intentionally kept async (`Future<bool>`) in this PR to avoid churn across the 12 production `await` sites and `FakeBotDetector` in tests; once `package:unified_analytics` rolls with `Analytics.isBot(Map<String, String> environment)` (tracked in dart-lang/tools#2672 / dart-lang/tools#2687), a follow-up PR for flutter#194405 can delegate directly or simplify callers if desired. Part of flutter#194405
Tighten Cursor AI agent detection, default
agentin productionAnalyticsfactories, and add a sharedAnalytics.isBothelper for CI/bot environment detection.AiAgent.cursordetection (lib/src/enums.dart): CheckCURSOR_AGENT(non-empty and not'0'/'false') andCURSOR_EXTENSION_HOST_ROLE == 'agent-exec'instead ofTERM_PROGRAM == 'cursor'or anyCURSOR_*prefix (which false-matchedCURSOR_TRACE_IDin human-opened Cursor IDE terminals).agentinAnalyticsandAnalytics.development(lib/src/analytics.dart): DefaultagenttoAiAgent.detectAgentName(Platform.environment)when omitted so all Dash tools automatically reportai_agentwithout per-caller plumbing.Analytics.fakeleavesagentas passed (nullby default) so unit tests remain hermetic when run inside an AI agent.Analytics.isBot(Map<String, String> environment)(lib/src/analytics.dart): Unifies the CI/bot environment variable checks fromflutter_tools(BotDetector) anddartdev(isBot), respecting explicit non-bot overrides (BOT=false,BOT=0,FLUTTER_HOST,FLUTTER_ANALYTICS_LOG_FILE) and rejecting falsyCI=false/CI=0/empty values. Scoped as a static method onAnalyticsto avoid colliding withpkg/dartdev's top-levelisBot. (is_botuser property registration is deferred to Step 2 of [unified_analytics] Add shared isBot helper and is_bot user property #2672 pending PDD review.)Fixes #2670
Fixes #2671
Part of #2672