diff --git a/src/programs/error-tracking-upload-source-maps/prompt.ts b/src/programs/error-tracking-upload-source-maps/prompt.ts index 311e6cf67..4ee603688 100644 --- a/src/programs/error-tracking-upload-source-maps/prompt.ts +++ b/src/programs/error-tracking-upload-source-maps/prompt.ts @@ -148,7 +148,7 @@ STEP 1 — Get a personal API key from the user. (skill: "Get a personal API key STEP 5: { id: "api-key", - prompt: "Paste your PostHog personal API key below. Don't have one yet? Create one here:\\n\\n${apiKeyUrl}", + prompt: "Uploading source maps needs a PostHog personal API key. Source maps let PostHog show your original code in error stack traces, not minified code.\\n\\nCreate a key with the right permissions here:\\n${apiKeyUrl}\\n\\nThen paste it below.", kind: "text", sensitive: true } diff --git a/src/tui/__tests__/__snapshots__/frames/wizard-ask-sensitive-120x40.txt b/src/tui/__tests__/__snapshots__/frames/wizard-ask-sensitive-120x40.txt new file mode 100644 index 000000000..1e8b940fe --- /dev/null +++ b/src/tui/__tests__/__snapshots__/frames/wizard-ask-sensitive-120x40.txt @@ -0,0 +1,31 @@ + PostHog Wizard v0.0.0-test Feedback: wizard@posthog.com + + Cost (running): $0.00 · no agent turns yet Ctrl+T to hide + + + + + + + + + ╭──────────────────────────────────────────────────────────────────────╮ + │ │ + │ ◆ error-tracking │ + │ │ + │ Uploading source maps needs a PostHog personal API key. Source │ + │ maps let PostHog show your original code in error stack traces, │ + │ not minified code. │ + │ │ + │ Create a key with the right permissions here: │ + │ https://us.posthog.com/source-maps-key │ + │ │ + │ Then paste it below. │ + │ │ + │ Type your answer │ + │ │ + │ Hidden as you type. The AI agent never sees it. ENTER submit │ + │ │ + │ ESC skip │ + │ │ + ╰──────────────────────────────────────────────────────────────────────╯ diff --git a/src/tui/__tests__/__snapshots__/frames/wizard-ask-sensitive-80x28.txt b/src/tui/__tests__/__snapshots__/frames/wizard-ask-sensitive-80x28.txt new file mode 100644 index 000000000..0660fd27d --- /dev/null +++ b/src/tui/__tests__/__snapshots__/frames/wizard-ask-sensitive-80x28.txt @@ -0,0 +1,25 @@ + PostHog Wizard v0.0.0-test Feedback: wizard@posthog.com + + Cost (running): $0.00 · no agent turns yet Ctrl+T to hide + + + ╭──────────────────────────────────────────────────────────────────────╮ + │ │ + │ ◆ error-tracking │ + │ │ + │ Uploading source maps needs a PostHog personal API key. Source │ + │ maps let PostHog show your original code in error stack traces, │ + │ not minified code. │ + │ │ + │ Create a key with the right permissions here: │ + │ https://us.posthog.com/source-maps-key │ + │ │ + │ Then paste it below. │ + │ │ + │ Type your answer │ + │ │ + │ Hidden as you type. The AI agent never sees it. ENTER submit │ + │ │ + │ ESC skip │ + │ │ + ╰──────────────────────────────────────────────────────────────────────╯ diff --git a/src/tui/__tests__/frames.test.tsx b/src/tui/__tests__/frames.test.tsx index e9a9f5650..753ef9469 100644 --- a/src/tui/__tests__/frames.test.tsx +++ b/src/tui/__tests__/frames.test.tsx @@ -703,6 +703,35 @@ describe('feature-flags-intro with an unsupported framework version', () => { }); }); +describe('wizard-ask with a sensitive text question', () => { + it.each(SIZES)(`at $columns x $rows`, async (size) => { + const store = makeStore(Program.PostHogIntegration); + void store.requestQuestion({ + id: 'q1', + source: 'error-tracking', + questions: [ + { + id: 'api-key', + prompt: + 'Uploading source maps needs a PostHog personal API key. Source maps let PostHog show your original code in error stack traces, not minified code.\n\nCreate a key with the right permissions here:\nhttps://us.posthog.com/source-maps-key\n\nThen paste it below.', + kind: 'text', + sensitive: true, + }, + ], + }); + expect(store.currentScreen).toBe(Overlay.WizardAsk); + const { frame } = await renderScreen( + store, + screenShell(store, makeServices(store)), + size, + ); + expect(frame).toContain('The AI agent never sees it.'); + await expect(frame).toMatchFileSnapshot( + `__snapshots__/frames/wizard-ask-sensitive-${size.columns}x${size.rows}.txt`, + ); + }); +}); + function snapshotPath(screen: ScreenName, size: TerminalSize): string { return `__snapshots__/frames/${screen}-${size.columns}x${size.rows}.txt`; } diff --git a/src/tui/screens/WizardAskScreen.tsx b/src/tui/screens/WizardAskScreen.tsx index 355759737..f3551250d 100644 --- a/src/tui/screens/WizardAskScreen.tsx +++ b/src/tui/screens/WizardAskScreen.tsx @@ -361,7 +361,8 @@ const QuestionInput = ({ question, onSubmit }: QuestionInputProps) => { } case 'text': { - const Input = shouldMaskAnswer(question) ? PasswordInput : TextInput; + const masked = shouldMaskAnswer(question); + const Input = masked ? PasswordInput : TextInput; return ( // `width="100%"` on both the column and the hint row anchors them to // the modal's content width — without it, Ink/Yoga shrinks the column @@ -372,7 +373,17 @@ const QuestionInput = ({ question, onSubmit }: QuestionInputProps) => { placeholder="Type your answer" onSubmit={(value) => onSubmit(value)} /> - + + {/* A sensitive answer is vaulted; the agent only gets a secretRef. */} + {masked && ( + + Hidden as you type. The AI agent never sees it. + + )} ENTER submit