diff --git a/scripts/verify-s03.sh b/scripts/verify-s03.sh index ce326b63b..14ae2dd50 100755 --- a/scripts/verify-s03.sh +++ b/scripts/verify-s03.sh @@ -88,6 +88,7 @@ tmp4=$(mktemp) env -i HOME="$HOME" PATH="$PATH" \ ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" \ BRAVE_API_KEY="test-brave" \ + BRAVE_ANSWERS_KEY="test-answers" \ CONTEXT7_API_KEY="test-ctx7" \ JINA_API_KEY="test-jina" \ node dist/loader.js < /dev/null > "$tmp4" 2>&1 @@ -111,8 +112,8 @@ echo "--- loadStoredEnvKeys hydration ---" # ---------------------------------------------------------------- # Check 5 — Structural: env var names compiled into dist/wizard.js # ---------------------------------------------------------------- -if grep -q "BRAVE_API_KEY" dist/wizard.js && grep -q "CONTEXT7_API_KEY" dist/wizard.js && grep -q "JINA_API_KEY" dist/wizard.js; then - pass "5 — dist/wizard.js contains all three optional key env var names" +if grep -q "BRAVE_API_KEY" dist/wizard.js && grep -q "BRAVE_ANSWERS_KEY" dist/wizard.js && grep -q "CONTEXT7_API_KEY" dist/wizard.js && grep -q "JINA_API_KEY" dist/wizard.js; then + pass "5 — dist/wizard.js contains all four optional key env var names" else fail "5 — dist/wizard.js missing one or more optional key env var names" fi diff --git a/src/tests/app-smoke.test.ts b/src/tests/app-smoke.test.ts index 8ad147b91..5c82c7b67 100644 --- a/src/tests/app-smoke.test.ts +++ b/src/tests/app-smoke.test.ts @@ -162,14 +162,17 @@ test("loadStoredEnvKeys hydrates process.env from auth.json", async () => { const authPath = join(tmp, "auth.json"); writeFileSync(authPath, JSON.stringify({ brave: { type: "api_key", key: "test-brave-key" }, + brave_answers: { type: "api_key", key: "test-answers-key" }, context7: { type: "api_key", key: "test-ctx7-key" }, })); // Clear any existing env vars const origBrave = process.env.BRAVE_API_KEY; + const origBraveAnswers = process.env.BRAVE_ANSWERS_KEY; const origCtx7 = process.env.CONTEXT7_API_KEY; const origJina = process.env.JINA_API_KEY; delete process.env.BRAVE_API_KEY; + delete process.env.BRAVE_ANSWERS_KEY; delete process.env.CONTEXT7_API_KEY; delete process.env.JINA_API_KEY; @@ -178,11 +181,13 @@ test("loadStoredEnvKeys hydrates process.env from auth.json", async () => { loadStoredEnvKeys(auth); assert.equal(process.env.BRAVE_API_KEY, "test-brave-key", "BRAVE_API_KEY hydrated"); + assert.equal(process.env.BRAVE_ANSWERS_KEY, "test-answers-key", "BRAVE_ANSWERS_KEY hydrated"); assert.equal(process.env.CONTEXT7_API_KEY, "test-ctx7-key", "CONTEXT7_API_KEY hydrated"); assert.equal(process.env.JINA_API_KEY, undefined, "JINA_API_KEY not set (not in auth)"); } finally { // Restore original env if (origBrave) process.env.BRAVE_API_KEY = origBrave; else delete process.env.BRAVE_API_KEY; + if (origBraveAnswers) process.env.BRAVE_ANSWERS_KEY = origBraveAnswers; else delete process.env.BRAVE_ANSWERS_KEY; if (origCtx7) process.env.CONTEXT7_API_KEY = origCtx7; else delete process.env.CONTEXT7_API_KEY; if (origJina) process.env.JINA_API_KEY = origJina; else delete process.env.JINA_API_KEY; rmSync(tmp, { recursive: true, force: true }); @@ -322,6 +327,7 @@ test("gsd launches and loads extensions without errors", async () => { env: { ...process.env, BRAVE_API_KEY: "test", + BRAVE_ANSWERS_KEY: "test", CONTEXT7_API_KEY: "test", JINA_API_KEY: "test", }, diff --git a/src/wizard.ts b/src/wizard.ts index 998f7a037..589ba9e68 100644 --- a/src/wizard.ts +++ b/src/wizard.ts @@ -60,6 +60,7 @@ async function promptMasked(question: string): Promise { export function loadStoredEnvKeys(authStorage: AuthStorage): void { const providers: Array<[string, string]> = [ ['brave', 'BRAVE_API_KEY'], + ['brave_answers', 'BRAVE_ANSWERS_KEY'], ['context7', 'CONTEXT7_API_KEY'], ['jina', 'JINA_API_KEY'], ] @@ -87,15 +88,17 @@ export function loadStoredEnvKeys(authStorage: AuthStorage): void { */ export async function runWizardIfNeeded(authStorage: AuthStorage): Promise { const needsBrave = !authStorage.has('brave') && !process.env.BRAVE_API_KEY + const needsBraveAnswers = !authStorage.has('brave_answers') && !process.env.BRAVE_ANSWERS_KEY const needsContext7 = !authStorage.has('context7') && !process.env.CONTEXT7_API_KEY const needsJina = !authStorage.has('jina') && !process.env.JINA_API_KEY - if (!needsBrave && !needsContext7 && !needsJina) { + if (!needsBrave && !needsBraveAnswers && !needsContext7 && !needsJina) { return } const missing = [ needsBrave && 'Brave Search', + needsBraveAnswers && 'Brave Answers', needsContext7 && 'Context7', needsJina && 'Jina', ] @@ -115,13 +118,21 @@ export async function runWizardIfNeeded(authStorage: AuthStorage): Promise process.stdout.write('[gsd] Press Enter to skip any key you want to set up later.\n\n') if (needsBrave) { - const key = await promptMasked('Brave Search API key (optional): ') + const key = await promptMasked('Brave Search API key (optional, for web search + LLM context): ') if (key) { authStorage.set('brave', { type: 'api_key', key }) process.env.BRAVE_API_KEY = key } } + if (needsBraveAnswers) { + const key = await promptMasked('Brave Answers API key (optional, for AI-generated answers): ') + if (key) { + authStorage.set('brave_answers', { type: 'api_key', key }) + process.env.BRAVE_ANSWERS_KEY = key + } + } + if (needsContext7) { const key = await promptMasked('Context7 API key (optional): ') if (key) {