From 6bc04a43ad4d3867c0ec886225a256ef950e2678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Beteg=C3=B3n?= Date: Wed, 8 Apr 2026 11:28:39 +0200 Subject: [PATCH 1/3] refactor(init): use renderInlineMarkdown for spinner messages Pipe spinner messages through the markdown rendering pipeline so file names, commands, and project names display as styled inline code in the terminal. Truncation happens on the plain markdown source before rendering, keeping truncateForTerminal simple. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/lib/init/wizard-runner.ts | 19 ++++++++++--------- test/lib/init/wizard-runner.test.ts | 29 ++++++++++++++++------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/lib/init/wizard-runner.ts b/src/lib/init/wizard-runner.ts index 5ef660a53..289a4b432 100644 --- a/src/lib/init/wizard-runner.ts +++ b/src/lib/init/wizard-runner.ts @@ -25,6 +25,7 @@ import { CLI_VERSION } from "../constants.js"; import { getAuthToken } from "../db/auth.js"; import { WizardError } from "../errors.js"; import { terminalLink } from "../formatters/colors.js"; +import { renderInlineMarkdown } from "../formatters/markdown.js"; import { resolveOrCreateTeam } from "../resolve-team.js"; import { slugify } from "../utils.js"; import { @@ -112,7 +113,7 @@ export function describeLocalOp(payload: LocalOpPayload): string { const first = patches[0]; if (patches.length === 1 && first) { const verb = patchActionVerb(first.action); - return `${verb} ${basename(first.path)}...`; + return `${verb} \`${basename(first.path)}\`...`; } const counts = patchActionCounts(patches); return `Applying ${patches.length} file changes (${counts})...`; @@ -121,14 +122,14 @@ export function describeLocalOp(payload: LocalOpPayload): string { const cmds = payload.params.commands; const first = cmds[0]; if (cmds.length === 1 && first) { - return `Running ${first}...`; + return `Running \`${first}\`...`; } - return `Running ${cmds.length} commands (${first ?? "..."}, ...)...`; + return `Running ${cmds.length} commands (\`${first ?? "..."}\`, ...)...`; } case "list-dir": return "Listing directory..."; case "create-sentry-project": - return `Creating project "${payload.params.name}" (${payload.params.platform})...`; + return `Creating project \`${payload.params.name}\` (${payload.params.platform})...`; case "detect-sentry": return "Checking for existing Sentry setup..."; default: @@ -144,12 +145,12 @@ function describeFilePaths(verb: string, paths: string[]): string { return `${verb} files...`; } if (paths.length === 1) { - return `${verb} ${basename(first)}...`; + return `${verb} \`${basename(first)}\`...`; } if (paths.length === 2 && second) { - return `${verb} ${basename(first)}, ${basename(second)}...`; + return `${verb} \`${basename(first)}\`, \`${basename(second)}\`...`; } - return `${verb} ${paths.length} files (${basename(first)}${second ? `, ${basename(second)}` : ""}, ...)...`; + return `${verb} ${paths.length} files (\`${basename(first)}\`${second ? `, \`${basename(second)}\`` : ""}, ...)...`; } /** Map a patch action to a user-facing verb. */ @@ -189,12 +190,12 @@ async function handleSuspendedStep( if (payload.type === "local-op") { const message = describeLocalOp(payload); - spin.message(truncateForTerminal(message)); + spin.message(renderInlineMarkdown(truncateForTerminal(message))); const localResult = await handleLocalOp(payload, options); if (localResult.message) { - spin.stop(localResult.message); + spin.stop(renderInlineMarkdown(localResult.message)); spin.start("Processing..."); } diff --git a/test/lib/init/wizard-runner.test.ts b/test/lib/init/wizard-runner.test.ts index 3f64564c8..b14f2ce17 100644 --- a/test/lib/init/wizard-runner.test.ts +++ b/test/lib/init/wizard-runner.test.ts @@ -628,8 +628,11 @@ describe("runWizard", { timeout: TEST_TIMEOUT_MS }, () => { ) as string[] | undefined; expect(call).toBeDefined(); const msg = call?.[0] ?? ""; - expect(msg.length).toBeLessThanOrEqual(36); - expect(msg.endsWith("…")).toBe(true); + // The rendered message contains ANSI codes, so check visible content + // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping ANSI escape sequences + const plain = msg.replace(/\x1b\[[^m]*m/g, ""); + expect(plain.length).toBeLessThanOrEqual(36); + expect(plain.endsWith("…")).toBe(true); } finally { Object.defineProperty(process.stdout, "columns", { value: origColumns, @@ -939,7 +942,7 @@ describe("describeLocalOp", () => { params: { paths: ["src/settings.py"] }, }) ); - expect(msg).toBe("Reading settings.py..."); + expect(msg).toBe("Reading `settings.py`..."); }); test("two files shows both basenames", () => { @@ -949,7 +952,7 @@ describe("describeLocalOp", () => { params: { paths: ["src/settings.py", "src/urls.py"] }, }) ); - expect(msg).toBe("Reading settings.py, urls.py..."); + expect(msg).toBe("Reading `settings.py`, `urls.py`..."); }); test("three+ files shows count and first two basenames", () => { @@ -961,7 +964,7 @@ describe("describeLocalOp", () => { }, }) ); - expect(msg).toBe("Reading 4 files (one.py, two.py, ...)..."); + expect(msg).toBe("Reading 4 files (`one.py`, `two.py`, ...)..."); }); test("empty paths array", () => { @@ -980,7 +983,7 @@ describe("describeLocalOp", () => { params: { paths: ["requirements.txt"] }, }) ); - expect(msg).toBe("Checking requirements.txt..."); + expect(msg).toBe("Checking `requirements.txt`..."); }); test("multiple files shows count", () => { @@ -990,7 +993,7 @@ describe("describeLocalOp", () => { params: { paths: ["a.py", "b.py", "c.py"] }, }) ); - expect(msg).toBe("Checking 3 files (a.py, b.py, ...)..."); + expect(msg).toBe("Checking 3 files (`a.py`, `b.py`, ...)..."); }); }); @@ -1004,7 +1007,7 @@ describe("describeLocalOp", () => { }, }) ); - expect(msg).toBe("Creating sentry.py..."); + expect(msg).toBe("Creating `sentry.py`..."); }); test("single modify shows verb and basename", () => { @@ -1016,7 +1019,7 @@ describe("describeLocalOp", () => { }, }) ); - expect(msg).toBe("Modifying settings.py..."); + expect(msg).toBe("Modifying `settings.py`..."); }); test("single delete shows verb and basename", () => { @@ -1028,7 +1031,7 @@ describe("describeLocalOp", () => { }, }) ); - expect(msg).toBe("Deleting old.js..."); + expect(msg).toBe("Deleting `old.js`..."); }); test("multiple patches shows count and breakdown", () => { @@ -1056,7 +1059,7 @@ describe("describeLocalOp", () => { params: { commands: ["pip install sentry-sdk"] }, }) ); - expect(msg).toBe("Running pip install sentry-sdk..."); + expect(msg).toBe("Running `pip install sentry-sdk`..."); }); test("multiple commands shows count and first", () => { @@ -1068,7 +1071,7 @@ describe("describeLocalOp", () => { }, }) ); - expect(msg).toBe("Running 2 commands (pip install sentry-sdk, ...)..."); + expect(msg).toBe("Running 2 commands (`pip install sentry-sdk`, ...)..."); }); }); @@ -1089,7 +1092,7 @@ describe("describeLocalOp", () => { params: { name: "my-app", platform: "python-django" }, }) ); - expect(msg).toBe('Creating project "my-app" (python-django)...'); + expect(msg).toBe("Creating project `my-app` (python-django)..."); }); }); }); From 7c94eb84e1ec55c9c7ce1991efc11f052f6e1a27 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 8 Apr 2026 09:29:10 +0000 Subject: [PATCH 2/3] chore: regenerate skill files and command docs --- docs/src/content/docs/commands/dashboard.md | 2 +- docs/src/content/docs/commands/event.md | 2 +- docs/src/content/docs/commands/issue.md | 4 ++-- docs/src/content/docs/commands/log.md | 2 +- docs/src/content/docs/commands/span.md | 2 +- docs/src/content/docs/commands/trace.md | 4 ++-- plugins/sentry-cli/skills/sentry-cli/references/dashboard.md | 2 +- plugins/sentry-cli/skills/sentry-cli/references/event.md | 2 +- plugins/sentry-cli/skills/sentry-cli/references/issue.md | 4 ++-- plugins/sentry-cli/skills/sentry-cli/references/log.md | 2 +- plugins/sentry-cli/skills/sentry-cli/references/span.md | 2 +- plugins/sentry-cli/skills/sentry-cli/references/trace.md | 4 ++-- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/src/content/docs/commands/dashboard.md b/docs/src/content/docs/commands/dashboard.md index 51ce630e0..d40c7e971 100644 --- a/docs/src/content/docs/commands/dashboard.md +++ b/docs/src/content/docs/commands/dashboard.md @@ -43,7 +43,7 @@ View a dashboard | `-w, --web` | Open in browser | | `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | | `-r, --refresh ` | Auto-refresh interval in seconds (default: 60, min: 10) | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" | ### `sentry dashboard create ` diff --git a/docs/src/content/docs/commands/event.md b/docs/src/content/docs/commands/event.md index 34d1e0465..87ca42361 100644 --- a/docs/src/content/docs/commands/event.md +++ b/docs/src/content/docs/commands/event.md @@ -42,7 +42,7 @@ List events for an issue | `-n, --limit ` | Number of events (1-1000) (default: "25") | | `-q, --query ` | Search query (Sentry search syntax) | | `--full` | Include full event body (stacktraces) | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "7d") | | `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | | `-c, --cursor ` | Navigate pages: "next", "prev", "first" (or raw cursor string) | diff --git a/docs/src/content/docs/commands/issue.md b/docs/src/content/docs/commands/issue.md index 7b5fb9d32..1eb4503c9 100644 --- a/docs/src/content/docs/commands/issue.md +++ b/docs/src/content/docs/commands/issue.md @@ -24,7 +24,7 @@ List issues in a project | `-q, --query ` | Search query (Sentry search syntax) | | `-n, --limit ` | Maximum number of issues to list (default: "25") | | `-s, --sort ` | Sort by: date, new, freq, user (default: "date") | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "90d") | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "90d") | | `-c, --cursor ` | Pagination cursor (use "next" for next page, "prev" for previous) | | `--compact` | Single-line rows for compact output (auto-detects if omitted) | | `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | @@ -46,7 +46,7 @@ List events for a specific issue | `-n, --limit ` | Number of events (1-1000) (default: "25") | | `-q, --query ` | Search query (Sentry search syntax) | | `--full` | Include full event body (stacktraces) | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "7d") | | `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | | `-c, --cursor ` | Navigate pages: "next", "prev", "first" (or raw cursor string) | diff --git a/docs/src/content/docs/commands/log.md b/docs/src/content/docs/commands/log.md index dcbd6b470..bb6c82343 100644 --- a/docs/src/content/docs/commands/log.md +++ b/docs/src/content/docs/commands/log.md @@ -24,7 +24,7 @@ List logs from a project | `-n, --limit ` | Number of log entries (1-1000) (default: "100") | | `-q, --query ` | Filter query (Sentry search syntax) | | `-f, --follow ` | Stream logs (optionally specify poll interval in seconds) | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" | | `-s, --sort ` | Sort order: "newest" (default) or "oldest" (default: "newest") | | `--fresh` | Bypass cache, re-detect projects, and fetch fresh data | diff --git a/docs/src/content/docs/commands/span.md b/docs/src/content/docs/commands/span.md index 053367ccb..85bfef5da 100644 --- a/docs/src/content/docs/commands/span.md +++ b/docs/src/content/docs/commands/span.md @@ -24,7 +24,7 @@ List spans in a project or trace | `-n, --limit ` | Number of spans (<=1000) (default: "25") | | `-q, --query ` | Filter spans (e.g., "op:db", "duration:>100ms", "project:backend") | | `-s, --sort ` | Sort order: date, duration (default: "date") | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "7d") | | `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | | `-c, --cursor ` | Navigate pages: "next", "prev", "first" (or raw cursor string) | diff --git a/docs/src/content/docs/commands/trace.md b/docs/src/content/docs/commands/trace.md index b5d8c1e07..162168b85 100644 --- a/docs/src/content/docs/commands/trace.md +++ b/docs/src/content/docs/commands/trace.md @@ -24,7 +24,7 @@ List recent traces in a project | `-n, --limit ` | Number of traces (1-1000) (default: "25") | | `-q, --query ` | Search query (Sentry search syntax) | | `-s, --sort ` | Sort by: date, duration (default: "date") | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "7d") | | `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | | `-c, --cursor ` | Navigate pages: "next", "prev", "first" (or raw cursor string) | @@ -61,7 +61,7 @@ View logs associated with a trace | Option | Description | |--------|-------------| | `-w, --web` | Open trace in browser | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "14d") | +| `-t, --period ` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "14d") | | `-n, --limit ` | Number of log entries (<=1000) (default: "100") | | `-q, --query ` | Additional filter query (Sentry search syntax) | | `-s, --sort ` | Sort order: "newest" (default) or "oldest" (default: "newest") | diff --git a/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md b/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md index e79d10e67..2469f6584 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md @@ -42,7 +42,7 @@ View a dashboard - `-w, --web - Open in browser` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` - `-r, --refresh - Auto-refresh interval in seconds (default: 60, min: 10)` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07"` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08"` **Examples:** diff --git a/plugins/sentry-cli/skills/sentry-cli/references/event.md b/plugins/sentry-cli/skills/sentry-cli/references/event.md index 0ea3ae478..85f9a8c54 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/event.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/event.md @@ -28,7 +28,7 @@ List events for an issue - `-n, --limit - Number of events (1-1000) - (default: "25")` - `-q, --query - Search query (Sentry search syntax)` - `--full - Include full event body (stacktraces)` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" - (default: "7d")` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` - `-c, --cursor - Navigate pages: "next", "prev", "first" (or raw cursor string)` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/issue.md b/plugins/sentry-cli/skills/sentry-cli/references/issue.md index 5625eb535..a335718bc 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/issue.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/issue.md @@ -19,7 +19,7 @@ List issues in a project - `-q, --query - Search query (Sentry search syntax)` - `-n, --limit - Maximum number of issues to list - (default: "25")` - `-s, --sort - Sort by: date, new, freq, user - (default: "date")` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "90d")` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" - (default: "90d")` - `-c, --cursor - Pagination cursor (use "next" for next page, "prev" for previous)` - `--compact - Single-line rows for compact output (auto-detects if omitted)` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` @@ -78,7 +78,7 @@ List events for a specific issue - `-n, --limit - Number of events (1-1000) - (default: "25")` - `-q, --query - Search query (Sentry search syntax)` - `--full - Include full event body (stacktraces)` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" - (default: "7d")` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` - `-c, --cursor - Navigate pages: "next", "prev", "first" (or raw cursor string)` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/log.md b/plugins/sentry-cli/skills/sentry-cli/references/log.md index c1674729e..dd2604b52 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/log.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/log.md @@ -19,7 +19,7 @@ List logs from a project - `-n, --limit - Number of log entries (1-1000) - (default: "100")` - `-q, --query - Filter query (Sentry search syntax)` - `-f, --follow - Stream logs (optionally specify poll interval in seconds)` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07"` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08"` - `-s, --sort - Sort order: "newest" (default) or "oldest" - (default: "newest")` - `--fresh - Bypass cache, re-detect projects, and fetch fresh data` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/span.md b/plugins/sentry-cli/skills/sentry-cli/references/span.md index 100e62e04..d7892ad94 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/span.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/span.md @@ -19,7 +19,7 @@ List spans in a project or trace - `-n, --limit - Number of spans (<=1000) - (default: "25")` - `-q, --query - Filter spans (e.g., "op:db", "duration:>100ms", "project:backend")` - `-s, --sort - Sort order: date, duration - (default: "date")` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" - (default: "7d")` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` - `-c, --cursor - Navigate pages: "next", "prev", "first" (or raw cursor string)` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/trace.md b/plugins/sentry-cli/skills/sentry-cli/references/trace.md index 20e20bf7b..1fb9244f2 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/trace.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/trace.md @@ -19,7 +19,7 @@ List recent traces in a project - `-n, --limit - Number of traces (1-1000) - (default: "25")` - `-q, --query - Search query (Sentry search syntax)` - `-s, --sort - Sort by: date, duration - (default: "date")` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" - (default: "7d")` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` - `-c, --cursor - Navigate pages: "next", "prev", "first" (or raw cursor string)` @@ -78,7 +78,7 @@ View logs associated with a trace **Flags:** - `-w, --web - Open trace in browser` -- `-t, --period - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "14d")` +- `-t, --period - Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" - (default: "14d")` - `-n, --limit - Number of log entries (<=1000) - (default: "100")` - `-q, --query - Additional filter query (Sentry search syntax)` - `-s, --sort - Sort order: "newest" (default) or "oldest" - (default: "newest")` From b1af2dd78ddb7d6f7a1c3ad78c7178ee4852ad92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Beteg=C3=B3n?= Date: Wed, 8 Apr 2026 12:02:36 +0200 Subject: [PATCH 3/3] fix: use safeCodeSpan and handle truncated backticks Address review feedback: - Use safeCodeSpan() to safely wrap values in backtick code spans, handling values that may contain backticks, pipes, or newlines. - Strip unmatched trailing backtick after truncation so renderInlineMarkdown doesn't produce a literal ` character. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/lib/init/wizard-runner.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/lib/init/wizard-runner.ts b/src/lib/init/wizard-runner.ts index 289a4b432..ed08a977b 100644 --- a/src/lib/init/wizard-runner.ts +++ b/src/lib/init/wizard-runner.ts @@ -25,7 +25,7 @@ import { CLI_VERSION } from "../constants.js"; import { getAuthToken } from "../db/auth.js"; import { WizardError } from "../errors.js"; import { terminalLink } from "../formatters/colors.js"; -import { renderInlineMarkdown } from "../formatters/markdown.js"; +import { renderInlineMarkdown, safeCodeSpan } from "../formatters/markdown.js"; import { resolveOrCreateTeam } from "../resolve-team.js"; import { slugify } from "../utils.js"; import { @@ -90,7 +90,16 @@ function truncateForTerminal(message: string): string { if (message.length <= maxWidth) { return message; } - return `${message.slice(0, maxWidth - 1)}…`; + let truncated = message.slice(0, maxWidth - 1); + // If truncation split a backtick code span, drop the unmatched backtick + // so renderInlineMarkdown doesn't produce a literal ` character. + const backtickCount = truncated.split("`").length - 1; + if (backtickCount % 2 !== 0) { + const lastBacktick = truncated.lastIndexOf("`"); + truncated = + truncated.slice(0, lastBacktick) + truncated.slice(lastBacktick + 1); + } + return `${truncated}…`; } /** @@ -113,7 +122,7 @@ export function describeLocalOp(payload: LocalOpPayload): string { const first = patches[0]; if (patches.length === 1 && first) { const verb = patchActionVerb(first.action); - return `${verb} \`${basename(first.path)}\`...`; + return `${verb} ${safeCodeSpan(basename(first.path))}...`; } const counts = patchActionCounts(patches); return `Applying ${patches.length} file changes (${counts})...`; @@ -122,14 +131,14 @@ export function describeLocalOp(payload: LocalOpPayload): string { const cmds = payload.params.commands; const first = cmds[0]; if (cmds.length === 1 && first) { - return `Running \`${first}\`...`; + return `Running ${safeCodeSpan(first)}...`; } - return `Running ${cmds.length} commands (\`${first ?? "..."}\`, ...)...`; + return `Running ${cmds.length} commands (${safeCodeSpan(first ?? "...")}, ...)...`; } case "list-dir": return "Listing directory..."; case "create-sentry-project": - return `Creating project \`${payload.params.name}\` (${payload.params.platform})...`; + return `Creating project ${safeCodeSpan(payload.params.name)} (${payload.params.platform})...`; case "detect-sentry": return "Checking for existing Sentry setup..."; default: @@ -145,12 +154,12 @@ function describeFilePaths(verb: string, paths: string[]): string { return `${verb} files...`; } if (paths.length === 1) { - return `${verb} \`${basename(first)}\`...`; + return `${verb} ${safeCodeSpan(basename(first))}...`; } if (paths.length === 2 && second) { - return `${verb} \`${basename(first)}\`, \`${basename(second)}\`...`; + return `${verb} ${safeCodeSpan(basename(first))}, ${safeCodeSpan(basename(second))}...`; } - return `${verb} ${paths.length} files (\`${basename(first)}\`${second ? `, \`${basename(second)}\`` : ""}, ...)...`; + return `${verb} ${paths.length} files (${safeCodeSpan(basename(first))}${second ? `, ${safeCodeSpan(basename(second))}` : ""}, ...)...`; } /** Map a patch action to a user-facing verb. */