Skip to content

Commit 9439f97

Browse files
authored
feat: Adjust copy and make simpler (#65)
1 parent e8da4d2 commit 9439f97

6 files changed

Lines changed: 260 additions & 239 deletions

File tree

packages/spark/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@clack/prompts": "1.3.0",
2525
"@inquirer/search": "4.1.8",
2626
"@tanstack/react-query": "5.100.9",
27+
"chalk": "^5.6.2",
2728
"clipboardy": "^5.3.1",
2829
"ignore": "^7.0.5",
2930
"ink": "7.0.2",

packages/spark/src/clack-copy.ts

Lines changed: 57 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { BraintrustCliContext } from "./braintrust-cli";
2+
import chalk from "chalk";
23

34
const BRAINTRUST_CLI_CONTEXT_FALLBACKS = {
45
profile: "no profile",
@@ -18,9 +19,7 @@ export const CLACK_WIZARD_COPY = {
1819
},
1920

2021
gitRepository: {
21-
outsideRepoWarning:
22-
"Warning: You are running this wizard inside a folder that is not a git repository. The wizard may edit files.",
23-
continueOutsideRepoQuestion: "Continue without a git repository?",
22+
outsideRepoWarning: `${chalk.yellow.bold("Warning:")} You are running this wizard inside a folder that is not a git repository. The wizard may edit files. ${chalk.bold("Continue without a git repository?")}`,
2423
continueOutsideRepoChoices: {
2524
yes: {
2625
label: "Yes",
@@ -50,10 +49,16 @@ export const CLACK_WIZARD_COPY = {
5049
readonly verificationCode: string;
5150
}) =>
5251
[
53-
`Sign in: ${args.loginLink}`,
52+
chalk.bold(
53+
"Sign in to continue the setup. Your browser should have opened automatically.",
54+
),
5455
"",
55-
"If your browser didn't open automatically, open the link above to sign in.",
5656
`Verification code: ${args.verificationCode}`,
57+
"",
58+
chalk.dim(
59+
"If your browser didn't open automatically, open the link below to sign in:\n",
60+
),
61+
chalk.dim(args.loginLink),
5762
].join("\n"),
5863
waitingForBrowser: "Waiting for you to sign in via the browser...",
5964
browserSetupComplete: (args: {
@@ -88,18 +93,16 @@ export const CLACK_WIZARD_COPY = {
8893
},
8994
installing: "Installing Braintrust CLI...",
9095
updating: "Updating Braintrust CLI...",
91-
checkingContext: "Checking Braintrust CLI context...",
92-
configuringContext: "Configuring Braintrust CLI context...",
96+
checkingContext: "Checking Braintrust CLI login state...",
97+
configuringContext: "Configuring Braintrust CLI login state...",
9398
updateFailed: (message: string) =>
9499
`Could not update Braintrust CLI: ${message}`,
95100
installFailed: (message: string) =>
96101
`Could not install Braintrust CLI: ${message}`,
97102
configureFailed: (message: string) =>
98103
`Could not configure Braintrust CLI: ${message}`,
99104
installedButNotFound:
100-
"Braintrust CLI was installed, but the wizard could not find `bt` in PATH or the default install location. Open a new shell and run `bt status` to verify it.",
101-
statusFailed: (message: string) =>
102-
`Could not inspect Braintrust CLI status; leaving existing CLI context unchanged. ${message}`,
105+
"Braintrust CLI was installed, but the wizard could not find `bt` in PATH or the default install location. Install the CLI manually:\nhttps://www.braintrust.dev/docs/reference/cli/quickstart",
103106
switchContextQuestion: (args: {
104107
readonly currentContext: BraintrustCliContext;
105108
readonly targetContext: BraintrustCliContext;
@@ -137,10 +140,9 @@ export const CLACK_WIZARD_COPY = {
137140
},
138141
},
139142
builtIn: {
140-
determiningAvailable: "Scanning for available coding agents...",
143+
determiningAvailable: "Searching for available coding agents...",
141144
running: (label: string) => `Running ${label}...`,
142-
proceedQuestion:
143-
"This setup wizard will now invoke a coding agent with full permissions. Proceed?",
145+
proceedQuestion: `This setup wizard will now invoke a coding agent ${chalk.bold("with full permissions")}. Proceed?`,
144146
proceedChoices: {
145147
yes: {
146148
label: "Confirm",
@@ -176,92 +178,80 @@ export const CLACK_WIZARD_COPY = {
176178
complete: "Instrumentation complete.",
177179
toolFinished: (toolLabel: string) => `${toolLabel} finished.`,
178180
},
179-
localToken: {
180-
title: "Local application token",
181-
notice:
182-
"The wizard will now create .env.braintrust and .braintrust.json files that are used to authenticate your application to Braintrust. They will be used for local testing.",
183-
existingNotice:
184-
"A local Braintrust token file already exists. The wizard can replace local token files with the API key for this Braintrust project.",
185-
replaceQuestion: "Replace local Braintrust token files?",
186-
replaceChoices: {
187-
yes: {
188-
label: "Yes (recommended)",
189-
hint: "Use this project key",
190-
},
191-
no: {
192-
label: "No",
193-
hint: "Keep existing file",
194-
},
195-
},
196-
outsideGitRepo: (apiKey: string) =>
197-
`BRAINTRUST_API_KEY=${apiKey}\nNot in a git repo — set this in your environment manually.`,
198-
keptTokenFiles: () =>
199-
"Kept existing local Braintrust token files unchanged.",
200-
gitignoreNote: (args: {
201-
readonly added: boolean;
202-
readonly alreadyCovered: boolean;
203-
}) => {
204-
if (args.added) {
205-
return "Updated .gitignore for local Braintrust token files.";
206-
}
207-
if (args.alreadyCovered) {
208-
return undefined;
209-
}
210-
return ".gitignore unchanged.";
211-
},
212-
},
213181
manual: {
214-
title: "Manual instrumentation",
215-
note: (docsLink: string) =>
182+
completedQuestion: (docsLink: string) =>
216183
[
217-
"Follow the Braintrust instrumentation docs for your project.",
184+
"Follow the Braintrust instrumentation docs for your project:",
185+
chalk.cyanBright(docsLink),
218186
"",
219-
docsLink,
187+
chalk.bold(
188+
"Did you complete setting up Braintrust by following the docs?\n",
189+
),
220190
].join("\n"),
221-
completedQuestion: "Braintrust instrumentation completed?",
222191
completedChoices: {
223192
confirm: {
224-
label: "confirm",
225-
hint: "Continue setup",
193+
label: "Confirm",
194+
hint: "Press Enter to continue",
226195
},
227196
},
228197
},
229198
ownAgent: {
230199
deliveryQuestion:
231-
"How should Braintrust Setup deliver the instrumentation prompt?",
200+
"How do you want to receive the prompt for your coding agent?",
232201
copyToClipboard: "Copy to clipboard",
233202
printToTerminal: "Print to terminal",
234203
copiedToClipboard: "Copied instrumentation prompt to clipboard.",
235204
clipboardFailed: (message: string) =>
236205
`Could not copy the instrumentation prompt to the clipboard: ${message}`,
237206
completedQuestion:
238-
"Give the above prompt to your coding agent and proceed when the agent has completed the task.",
207+
"Paste the above prompt into your coding agent. Press enter and proceed when the agent has completed the task.",
239208
completedChoices: {
240209
confirm: {
241210
label: "Confirm and proceed",
242-
hint: "Continue setup",
211+
hint: "Press Enter to continue",
243212
},
244213
},
245214
},
246215
},
247216

248217
logs: {
249-
projectLogsUrl: (url: string) => `Check your Braintrust logs: ${url}`,
218+
checkQuestion: (url: string) =>
219+
[
220+
"Your application should now be instrumented with Braintrust tracing.",
221+
"",
222+
chalk.bold(
223+
"Please run your app locally now, and invoke AI functionality to confirm whether AI calls are logged and traced.",
224+
),
225+
"",
226+
`If everything is set up correctly, traces will appear in your Braintrust logs:\n${chalk.cyanBright(url)}`,
227+
"",
228+
chalk.dim(
229+
`If traces are not showing up, visit the troubleshooting guide:\nhttps://www.braintrust.dev/docs/kb/troubleshooting-guides\n`,
230+
),
231+
].join("\n"),
232+
checked: "I've confirmed my application is sending traces.",
233+
hint: "Press Enter to continue",
250234
},
251235

252236
productionToken: {
253-
title: "Production token",
254-
noteWithEnvFile: (envFilePath: string) =>
255-
`The local Braintrust token files contain a BRAINTRUST_API_KEY token. Add that token to your deployment platform's environment variables so tracing works in production.\n\nEnv file: ${envFilePath}`,
256-
noteWithoutEnvFile:
257-
"Add the BRAINTRUST_API_KEY token to your deployment platform's environment variables so tracing works in production.",
258-
question: "Have you added BRAINTRUST_API_KEY to your deployment platform?",
259-
understood: "Understood",
237+
question: `Production Setup: Add the ${chalk.cyanBright("BRAINTRUST_API_KEY")} token from your local ${chalk.bold("./.env.braintrust")} file to your production environment as environment variable.\n`,
238+
confirmed: `I have added ${chalk.bold("BRAINTRUST_API_KEY")} to my production env.`,
239+
hint: "Press Enter to continue",
260240
},
261241

262242
outro: {
263-
complete: (docsUrl: string) =>
264-
["Setup complete.", "", `Docs: ${docsUrl}`].join("\n"),
243+
complete: [
244+
chalk.dim("Braintrust setup complete."),
245+
"",
246+
"You can now use Braintrust in production.",
247+
"",
248+
"If you encountered any issues during setup, please open an issue at https://github.com/braintrustdata/spark/issues/new.",
249+
"",
250+
chalk.dim("- Contact support: https://www.braintrust.dev/contact"),
251+
chalk.dim(
252+
"- Further documentation: https://www.braintrust.dev/docs/instrument",
253+
),
254+
].join("\n"),
265255
},
266256
} as const;
267257

packages/spark/src/clack-wizard.ts

Lines changed: 32 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,11 @@ import {
3131
type CodingToolRunResult,
3232
type CodingToolStatus,
3333
} from "./coding-tools";
34-
import {
35-
braintrustTokenFilesExist,
36-
ensureEnvBraintrustIgnored,
37-
isGitRepo,
38-
writeEnvBraintrust,
39-
} from "./git";
34+
import { isGitRepo, writeEnvBraintrust } from "./git";
4035
import { allocateResultFile, readResultFile } from "./instrument";
4136
import type { WizardOptions } from "./options";
4237
import { renderPrompt } from "./prompt";
4338
import { ClackToolRenderer } from "./tool-ui";
44-
import { terminalHyperlink } from "./wizard-utils";
4539

4640
const COPY = CLACK_WIZARD_COPY;
4741
const WIZARD_CANCEL_MESSAGE = COPY.shared.cancelMessage;
@@ -196,9 +190,8 @@ export async function runClackWizard(deps: WizardDeps): Promise<WizardResult> {
196190
clack.intro(COPY.welcome.intro);
197191

198192
if (!(await isGitRepo(deps.cwd))) {
199-
clack.log.warn(COPY.gitRepository.outsideRepoWarning);
200193
const continueOutsideGit = await selectBoolean({
201-
message: COPY.gitRepository.continueOutsideRepoQuestion,
194+
message: COPY.gitRepository.outsideRepoWarning,
202195
choices: COPY.gitRepository.continueOutsideRepoChoices,
203196
yesFirst: false,
204197
});
@@ -219,7 +212,7 @@ export async function runClackWizard(deps: WizardDeps): Promise<WizardResult> {
219212
authMode: (await hasBraintrustAccount()) ? "signin" : "signup",
220213
});
221214

222-
const envFilePath = await writeLocalEnvBraintrust(deps, session.apiKey);
215+
await writeLocalEnvBraintrust(deps, session.apiKey);
223216

224217
const setupSpinner = new WizardStepSpinner();
225218
let codingToolStatuses: readonly CodingToolStatus[];
@@ -286,11 +279,11 @@ export async function runClackWizard(deps: WizardDeps): Promise<WizardResult> {
286279
}
287280

288281
const projectLogsUrl = `${deps.options.appUrl}/app/${encodeURIComponent(session.orgName)}/p/${encodeURIComponent(session.projectName)}/logs`;
289-
clack.log.info(COPY.logs.projectLogsUrl(projectLogsUrl));
282+
await confirmTraceLogs(projectLogsUrl);
290283

291-
await confirmProductionApiKey(envFilePath);
284+
await confirmProductionApiKey();
292285

293-
clack.outro(COPY.outro.complete(COPY.shared.instrumentationDocsUrl));
286+
clack.outro(COPY.outro.complete);
294287

295288
return {
296289
orgName: session.orgName,
@@ -460,11 +453,8 @@ async function handleBraintrustCliSetup(
460453
spinner.update(COPY.braintrustCli.checkingContext);
461454
try {
462455
currentContext = await deps.braintrustCli.status(commandPath);
463-
} catch (error) {
456+
} catch {
464457
spinner.clear();
465-
clack.log.warn(
466-
COPY.braintrustCli.statusFailed(summarizeBraintrustCliError(error)),
467-
);
468458
return;
469459
}
470460

@@ -604,55 +594,17 @@ function warnNoUsableCodingTools(statuses: readonly CodingToolStatus[]): void {
604594
async function writeLocalEnvBraintrust(
605595
deps: WizardDeps,
606596
apiKey: string,
607-
): Promise<string | undefined> {
608-
const targetDirectory = deps.cwd;
609-
if (await braintrustTokenFilesExist(targetDirectory)) {
610-
clack.note(
611-
COPY.instrumentation.localToken.existingNotice,
612-
COPY.instrumentation.localToken.title,
613-
);
614-
const shouldReplace = await selectBoolean({
615-
message: COPY.instrumentation.localToken.replaceQuestion,
616-
choices: COPY.instrumentation.localToken.replaceChoices,
617-
yesFirst: true,
618-
});
619-
if (!shouldReplace) {
620-
const gitignoreResult = await ensureEnvBraintrustIgnored(targetDirectory);
621-
const gitignoreNote = COPY.instrumentation.localToken.gitignoreNote({
622-
added: gitignoreResult.addedToGitignore,
623-
alreadyCovered: gitignoreResult.alreadyCovered,
624-
});
625-
clack.log.info(COPY.instrumentation.localToken.keptTokenFiles());
626-
if (gitignoreNote) clack.log.info(gitignoreNote);
627-
return undefined;
628-
}
629-
} else {
630-
clack.note(
631-
COPY.instrumentation.localToken.notice,
632-
COPY.instrumentation.localToken.title,
633-
);
634-
}
635-
636-
const result = await writeEnvBraintrust(targetDirectory, apiKey);
637-
const envFilePath = relative(targetDirectory, result.envFilePath);
638-
const gitignoreNote = COPY.instrumentation.localToken.gitignoreNote({
639-
added: result.addedToGitignore,
640-
alreadyCovered: result.alreadyCovered,
641-
});
642-
if (gitignoreNote) clack.log.info(gitignoreNote);
643-
return envFilePath;
597+
): Promise<string> {
598+
const result = await writeEnvBraintrust(deps.cwd, apiKey);
599+
return relative(deps.cwd, result.envFilePath);
644600
}
645601

646602
async function confirmManualInstrumentation(): Promise<void> {
647-
clack.note(
648-
COPY.instrumentation.manual.note(
649-
terminalHyperlink(COPY.shared.instrumentationDocsUrl),
650-
),
651-
COPY.instrumentation.manual.title,
652-
);
653603
unwrap(
654604
await clack.select<"confirm">({
655-
message: COPY.instrumentation.manual.completedQuestion,
605+
message: COPY.instrumentation.manual.completedQuestion(
606+
COPY.shared.instrumentationDocsUrl,
607+
),
656608
options: [
657609
{
658610
label: COPY.instrumentation.manual.completedChoices.confirm.label,
@@ -722,22 +674,30 @@ function printInstrumentationPrompt(promptText: string): void {
722674
process.stdout.write(`\n${promptText}\n\n`);
723675
}
724676

725-
async function confirmProductionApiKey(
726-
envFilePath: string | undefined,
727-
): Promise<void> {
728-
clack.note(
729-
envFilePath
730-
? COPY.productionToken.noteWithEnvFile(envFilePath)
731-
: COPY.productionToken.noteWithoutEnvFile,
732-
COPY.productionToken.title,
677+
async function confirmTraceLogs(projectLogsUrl: string): Promise<void> {
678+
unwrap(
679+
await clack.select<"checked">({
680+
message: COPY.logs.checkQuestion(projectLogsUrl),
681+
options: [
682+
{
683+
label: COPY.logs.checked,
684+
value: "checked",
685+
hint: COPY.logs.hint,
686+
},
687+
],
688+
}),
733689
);
690+
}
691+
692+
async function confirmProductionApiKey(): Promise<void> {
734693
unwrap(
735-
await clack.select<"understood">({
694+
await clack.select<"confirmed">({
736695
message: COPY.productionToken.question,
737696
options: [
738697
{
739-
label: COPY.productionToken.understood,
740-
value: "understood",
698+
label: COPY.productionToken.confirmed,
699+
value: "confirmed",
700+
hint: COPY.productionToken.hint,
741701
},
742702
],
743703
}),

packages/spark/src/git.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export async function isGitRepo(cwd: string): Promise<boolean> {
4545
const ENV_FILENAME = ".env.braintrust";
4646
const BRAINTRUST_JSON_FILENAME = ".braintrust.json";
4747
const GENERATED_FILE_COMMENT =
48-
"This file was generated by the Braintrust CLI wizard. This file contains sensitive information. Do not commit this file to version control! The file can be safely deleted after confirming your application sends traces.";
48+
"This file was generated by the Braintrust wizard. This file contains sensitive information. Do not commit this file to version control! The file can be safely deleted after confirming your application sends traces.";
4949
const LOCAL_TOKEN_FILENAMES = [ENV_FILENAME, BRAINTRUST_JSON_FILENAME] as const;
5050

5151
export function envBraintrustPath(directory: string): string {

0 commit comments

Comments
 (0)