diff --git a/src/lib/formatters/markdown.ts b/src/lib/formatters/markdown.ts index f2b71fdc0..cddc104a5 100644 --- a/src/lib/formatters/markdown.ts +++ b/src/lib/formatters/markdown.ts @@ -278,7 +278,6 @@ function renderCodespan(token: Tokens.Codespan): string { /** * Render a single inline token to an ANSI string. */ -// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: inline token switch is inherently branchy function renderOneInline(token: Token): string { switch (token.type) { case "strong": diff --git a/src/lib/init/wizard-runner.ts b/src/lib/init/wizard-runner.ts index 162fef049..696bbb299 100644 --- a/src/lib/init/wizard-runner.ts +++ b/src/lib/init/wizard-runner.ts @@ -12,6 +12,7 @@ import { MastraClient } from "@mastra/client-js"; import { captureException, getTraceData } from "@sentry/node-core/light"; import { formatBanner } from "../banner.js"; import { CLI_VERSION } from "../constants.js"; +import { detectAgent } from "../detect-agent.js"; import { EXIT, WizardError } from "../errors.js"; import { terminalLink } from "../formatters/colors.js"; import { @@ -328,7 +329,11 @@ async function preamble( ); } - process.stderr.write(`\n${formatBanner()}\n\n`); + // Suppress the ASCII art banner for agent-driven runs — it wastes tokens + // and adds noise to structured output without providing value to the agent. + if (!detectAgent()) { + process.stderr.write(`\n${formatBanner()}\n\n`); + } intro("sentry init"); let confirmed: boolean; diff --git a/test/lib/init/wizard-runner.test.ts b/test/lib/init/wizard-runner.test.ts index a8d9a9ddc..cc422856d 100644 --- a/test/lib/init/wizard-runner.test.ts +++ b/test/lib/init/wizard-runner.test.ts @@ -12,6 +12,8 @@ import * as clack from "@clack/prompts"; import { MastraClient } from "@mastra/client-js"; // biome-ignore lint/performance/noNamespaceImport: spyOn requires object reference import * as banner from "../../../src/lib/banner.js"; +import { ENV_VAR_AGENTS } from "../../../src/lib/detect-agent.js"; +import { setEnv } from "../../../src/lib/env.js"; import { WizardError } from "../../../src/lib/errors.js"; import { WizardCancelledError } from "../../../src/lib/init/clack-utils.js"; // biome-ignore lint/performance/noNamespaceImport: spyOn requires object reference @@ -223,6 +225,9 @@ afterEach(() => { } else { process.env.SENTRY_PLAIN_OUTPUT = savedPlainOutput; } + + // Restore the env sandbox in case any test used setEnv without try/finally. + setEnv(process.env); }); describe("runWizard", () => { @@ -278,6 +283,44 @@ describe("runWizard", () => { expect(getWorkflowSpy).not.toHaveBeenCalled(); }); + test("suppresses the ASCII art banner when an agent is detected", async () => { + setEnv({ ...process.env, CLAUDE_CODE: "1" } as NodeJS.ProcessEnv); + try { + await runWizard(makeOptions()); + } finally { + setEnv(process.env); + } + + expect(formatBannerSpy).not.toHaveBeenCalled(); + expect(stderrSpy).not.toHaveBeenCalledWith( + expect.stringContaining("BANNER") + ); + }); + + test("prints the ASCII art banner when no agent is detected", async () => { + // Strip all agent-detection env vars so detectAgent() returns undefined + // even when running inside an agent environment (e.g. OpenCode in CI). + const agentKeys = new Set([ + "AI_AGENT", + "AGENT", + "CLAUDECODE", + "CLAUDE_CODE", + ...ENV_VAR_AGENTS.keys(), + ]); + const cleanEnv = Object.fromEntries( + Object.entries(process.env).filter(([k]) => !agentKeys.has(k)) + ); + setEnv(cleanEnv as NodeJS.ProcessEnv); + try { + await runWizard(makeOptions()); + } finally { + setEnv(process.env); + } + + expect(formatBannerSpy).toHaveBeenCalled(); + expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining("BANNER")); + }); + test("dispatches tool payloads through the registry", async () => { const payload: ToolPayload = { type: "tool",