-
-
Notifications
You must be signed in to change notification settings - Fork 10.1k
CLI: Source eval prompts from ai setup via EVAL_SETUP_PROMPT #34602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
407f451
720d018
88dffdb
fd48b03
28fea35
9412695
5a85358
741237e
5be3f0b
42f4ed9
d86161f
86ae333
9140f6c
62f2fa6
a6aaf4f
d9db8a8
01068aa
99ade86
9729a8b
14d97d2
96b782c
1557244
fd6a2b0
3b67e50
8e7c397
af1479a
b35ff84
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
|
|
||
| vi.mock('storybook/internal/common', async () => { | ||
| const actual = await vi.importActual<typeof import('storybook/internal/common')>( | ||
| 'storybook/internal/common' | ||
| ); | ||
| return { | ||
| ...actual, | ||
| cache: { set: vi.fn(), get: vi.fn(), remove: vi.fn() }, | ||
| }; | ||
| }); | ||
|
|
||
| vi.mock('storybook/internal/telemetry', () => ({ | ||
| telemetry: vi.fn(), | ||
| getSessionId: vi.fn().mockResolvedValue('session-xyz'), | ||
| snapshotPreviewFile: vi | ||
| .fn() | ||
| .mockResolvedValue({ previewPath: '/proj/.storybook/preview.ts', previewHash: 'abc' }), | ||
| isTelemetryModuleEnabled: vi.fn(() => true), | ||
| })); | ||
|
|
||
| vi.mock('storybook/internal/node-logger', () => ({ | ||
| logger: { log: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() }, | ||
| })); | ||
|
|
||
| vi.mock('../../../create-storybook/src/services/ProjectTypeService.ts', () => ({ | ||
| ProjectTypeService: class { | ||
| async detectLanguage() { | ||
| return 'ts'; | ||
| } | ||
| }, | ||
| })); | ||
|
|
||
| vi.mock('../automigrate/helpers/mainConfigFile.ts', () => ({ | ||
| getStorybookData: vi.fn().mockResolvedValue({ | ||
| versionInstalled: '10.4.0', | ||
| frameworkPackage: '@storybook/react-vite', | ||
| rendererPackage: '@storybook/react', | ||
| renderer: 'react', | ||
| builderPackage: '@storybook/builder-vite', | ||
| addons: [], | ||
| configDir: '/proj/.storybook', | ||
| storiesPaths: [], | ||
| hasCsfFactoryPreview: false, | ||
| packageManager: {}, | ||
| }), | ||
| })); | ||
|
|
||
| import { cache } from 'storybook/internal/common'; | ||
| import { | ||
| isTelemetryModuleEnabled, | ||
| snapshotPreviewFile, | ||
| telemetry, | ||
| } from 'storybook/internal/telemetry'; | ||
|
|
||
| import { aiSetup } from './index.ts'; | ||
|
|
||
| beforeEach(() => { | ||
| vi.mocked(cache.set).mockClear(); | ||
| vi.mocked(snapshotPreviewFile).mockClear(); | ||
| vi.mocked(telemetry).mockClear(); | ||
| }); | ||
|
|
||
| describe('aiSetup telemetry gating', () => { | ||
| it('records ai-setup-pending + preview snapshot when telemetry is enabled', async () => { | ||
| await aiSetup({ configDir: '/proj/.storybook', disableTelemetry: false }); | ||
|
|
||
| expect(vi.mocked(snapshotPreviewFile)).toHaveBeenCalledTimes(1); | ||
| expect(vi.mocked(cache.set)).toHaveBeenCalledWith( | ||
| 'ai-setup-pending', | ||
| expect.objectContaining({ | ||
| configDir: expect.stringContaining('.storybook'), | ||
| sessionId: 'session-xyz', | ||
| previewPath: '/proj/.storybook/preview.ts', | ||
| previewHash: 'abc', | ||
| }) | ||
| ); | ||
| expect(vi.mocked(telemetry)).toHaveBeenCalledWith('ai-setup', expect.any(Object)); | ||
| }); | ||
|
|
||
| it('skips snapshot + cache write when telemetry is disabled', async () => { | ||
| vi.mocked(isTelemetryModuleEnabled).mockReturnValueOnce(false); | ||
|
|
||
| await aiSetup({ configDir: '/proj/.storybook', disableTelemetry: true }); | ||
|
|
||
| expect(vi.mocked(snapshotPreviewFile)).not.toHaveBeenCalled(); | ||
| expect(vi.mocked(cache.set)).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('treats missing disableTelemetry as enabled (backwards compatible default)', async () => { | ||
| await aiSetup({ configDir: '/proj/.storybook' }); | ||
|
|
||
| expect(vi.mocked(snapshotPreviewFile)).toHaveBeenCalledTimes(1); | ||
| expect(vi.mocked(cache.set)).toHaveBeenCalledWith('ai-setup-pending', expect.any(Object)); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ import { cache } from 'storybook/internal/common'; | |
| import { logger } from 'storybook/internal/node-logger'; | ||
| import { | ||
| getSessionId, | ||
| isTelemetryModuleEnabled, | ||
| snapshotPreviewFile, | ||
| telemetry, | ||
| type AiSetupPendingRecord, | ||
|
|
@@ -79,7 +80,7 @@ export async function aiSetup(options: AiSetupOptions): Promise<void> { | |
| return; | ||
| } | ||
|
|
||
| const result = generateMarkdownOutput(projectInfo); | ||
| const result = await generateMarkdownOutput(projectInfo); | ||
| const markdownOutput = result.markdown; | ||
|
|
||
| await telemetry('ai-setup', { | ||
|
|
@@ -99,17 +100,21 @@ export async function aiSetup(options: AiSetupOptions): Promise<void> { | |
|
|
||
| // Snapshot the preview file baseline and cache the pending setup record. | ||
| // Subsequent CLI entry points (dev, build, doctor, etc.) read this to | ||
| // collect evidence of what the agent accomplished. | ||
| const resolvedConfigDir = resolve(projectInfo.configDir); | ||
| const previewSnapshot = await snapshotPreviewFile(resolvedConfigDir); | ||
| const sessionId = await getSessionId(); | ||
| const pendingRecord: AiSetupPendingRecord = { | ||
| timestamp: Date.now(), | ||
| sessionId, | ||
| configDir: resolvedConfigDir, | ||
| ...previewSnapshot, | ||
| }; | ||
| await cache.set('ai-setup-pending', pendingRecord); | ||
| // collect evidence of what the agent accomplished — but only via telemetry | ||
| // (the `ai-setup-evidence` event). Skip the snapshot + cache write when | ||
| // telemetry is disabled so there's nobody to read it. | ||
| if (isTelemetryModuleEnabled()) { | ||
| const resolvedConfigDir = resolve(projectInfo.configDir); | ||
| const previewSnapshot = await snapshotPreviewFile(resolvedConfigDir); | ||
| const sessionId = await getSessionId(); | ||
| const pendingRecord: AiSetupPendingRecord = { | ||
| timestamp: Date.now(), | ||
| sessionId, | ||
| configDir: resolvedConfigDir, | ||
| ...previewSnapshot, | ||
| }; | ||
| await cache.set('ai-setup-pending', pendingRecord); | ||
| } | ||
|
Comment on lines
+103
to
+117
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ValentinFunk what do you think of this? Did you plan a new API for these use cases or is this still the "canonical" way to do things? I think Kasper is doing the right thing here as we wanna avoid useless compute, but this happens earlier than when we actually can use the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm so sorry Valentin, I need to stop pinging you by accident 😭 |
||
|
|
||
| if (output) { | ||
| const outputPath = resolve(output); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: storybookjs/storybook
Length of output: 1856
Refactor mocks to use
spy: trueand move behavior setup tobeforeEach.All five module-level
vi.mock()calls (lines 3, 13, 21, 25, 33) lack the{ spy: true }option and configure mock behaviors (.mockResolvedValue(),vi.fn()) at the module scope. Per repository spy-mocking rules, add{ spy: true }to each mock declaration, move all behavior configurations into thebeforeEachblock viavi.mocked(), and keep module-level mocks pure factory functions.Example refactor pattern:
🤖 Prompt for AI Agents