Conversation
e5604a9 to
7e369c5
Compare
7e369c5 to
bbb47ef
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate findings must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds fallback AI-agent detection to CLI analytics using @vercel/detect-agent, while preserving declared agent metadata.
Changes:
- Adds and locks the detection dependency.
- Detects, sanitizes, and reports agent names through sensitive analytics fields.
- Adds detection and analytics integration tests.
Review findings include two critical issues in analytics gating and test fixtures, four moderate issues involving send eligibility and name handling, and one documentation nit.
File summaries
| File | Description |
|---|---|
pnpm-lock.yaml |
Locks the new detection dependency. |
packages/cli-kit/src/public/node/analytics.ts |
Provides analytics skip-check behavior. |
packages/cli-kit/src/public/node/analytics.test.ts |
Tests analytics integration and opt-out behavior. |
packages/cli-kit/src/private/node/context/agent.ts |
Implements agent detection, mapping, and sanitization. |
packages/cli-kit/src/private/node/context/agent.test.ts |
Tests detection behavior and normalization. |
packages/cli-kit/src/private/node/analytics.ts |
Integrates detected variables into analytics payloads. |
packages/cli-kit/package.json |
Adds the detection dependency. |
Review details
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
packages/cli-kit/src/private/node/analytics.ts:136
env_shopify_variablesis only delivered in the Monorail payload, but this gate treatsalwaysLogMetricsas sufficient to run detection. With analytics disabled and only the metrics override enabled,monorailAnalyticsSkipped()remains true, sosendAnalyticsEventdrops the Monorail payload and the detected values are discarded after the detection work. Gate this enrichment on Monorail delivery instead; the related test should not require detection for a metrics-only send.
packages/cli-kit/src/private/node/context/agent.ts:33- The lookup happens after replacing
|, so an arbitraryAI_AGENTvalue can collide with a canonical detector name. With the pinned detector names,AI_AGENT=claude|codebecomesclaude_codeand is then remapped toclaude-code, falsely attributing it to the Shopify toolkit instead of preserving the sanitized custom name. Apply the known-agent mapping torawDetectedNamebefore sanitizing the fallback.
const detectedName = rawDetectedName.replaceAll('|', '_').trim()
return {
SHOPIFY_CLI_AGENT_INFO: `n:${toolkitAgentNamesByDetectedName[detectedName] ?? detectedName}`,
- Files reviewed: 6/7 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
57b1197 to
2665e2c
Compare
Detect the agent running the CLI with @vercel/detect-agent and report it as n:<name> inside SHOPIFY_CLI_AGENT_INFO, the packed format the Shopify AI toolkit already uses, so a detected name resolves through the same field as a declared one. Detection only fills the gap. It is skipped when a producer declared SHOPIFY_CLI_AGENT_INFO or SHOPIFY_CLI_AGENT_IDS, because writing INFO ourselves would clobber their whole packed value, not just the name. SHOPIFY_CLI_AGENT_DETECTED marks a name as derived rather than declared. Assisted-By: devx/105d6a35-ec6d-462e-9e36-a9fde4ec06fc Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2665e2c to
140c363
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationspackages/cli-kit/dist/private/node/context/agent.d.tsexport declare function detectedAgentEnvironmentVariables(env?: NodeJS.ProcessEnv): Promise<NodeJS.ProcessEnv>;
Existing type declarationsWe found no diffs with existing type declarations |
WHY are these changes introduced?
CLI analytics can't distinguish AI-agent runs from human or scripted ones. The AI toolkit has agents declare themselves through
SHOPIFY_CLI_AGENT_INFO/SHOPIFY_CLI_AGENT_IDS; agents outside it stay invisible.https://github.com/shop/issues-develop/issues/23864
WHAT is this pull request doing?
Detect the agent with
@vercel/detect-agentand report it through the existing sensitiveenv_shopify_variablesfield, so there's no Monorail schema change. Detected names reuse the packed format producers already send —SHOPIFY_CLI_AGENT_INFO="n:<name>"— so theagentcolumn resolves identically whether declared or detected. Onlyn:is set; detection can't resolve version, provider or model.Decisions worth review:
SHOPIFY_CLI_AGENT_INFOourselves would clobber the producer's whole packed value, not just the name.SHOPIFY_CLI_AGENT_DETECTED=truemarks a derived name. It's deliberately off the allowlist, which filters before the merge, so only the CLI can set it.|becomes_in detected names — it separates tags with no escape sequence, so one could otherwise fabricate tags likev:.determineAgent()measures 15µs worst case, against an event that does a network POST.How to manually test your changes?
bin/dev.jsruns the bundle, sopnpm nx bundle --skip-nx-cachefirst. Detected, nothing declared:env -u SHOPIFY_CLI_AGENT_INFO -u SHOPIFY_CLI_AGENT_IDS AI_AGENT=codex SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS=1 node packages/cli/bin/dev.js version --verbose | grep env_shopify_variablesDeclared, which detection must leave untouched and unmarked; declared (
cursor) and detected (codex) differ so you can see which won:Checklist
patchfor bug fixes ·minorfor new features ·majorfor breaking changes) and added a changeset withpnpm changeset add🤖 Generated with Claude Code