diff --git a/README.md b/README.md index 8ebcb01..929c58c 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,10 @@ public/env-ob.json Used for obfuscated environment configuration. +Because this is a static browser application, `API_KEY` must be a publishable +Pollinations key beginning with `pk_`. Never place an `sk_` secret key in this +file or any other client-side asset. + If modifying environment handling, see: ``` diff --git a/src/pages/SimpleCite.tsx b/src/pages/SimpleCite.tsx index ff93ab7..27449af 100644 --- a/src/pages/SimpleCite.tsx +++ b/src/pages/SimpleCite.tsx @@ -2,7 +2,11 @@ import { createSignal, Show, onMount, For } from 'solid-js'; import type { Component } from 'solid-js'; import { db } from '../db'; import type { Citation } from '../db'; -import { getPollinationsApiKey, POLLINATIONS_TEXT_ENDPOINT } from '../utils/env'; +import { + getPollinationsApiKey, + POLLINATIONS_TEXT_ENDPOINT, + POLLINATIONS_TEXT_MODEL, +} from '../utils/env'; import styles from './SimpleCite.module.css'; type Guideline = 'apa7' | 'mla9' | 'ieee' | 'chicago17'; @@ -743,12 +747,17 @@ const fetchMetadataViaAi = async ( if (!apiKey) { throw new Error('Missing API key'); } + const query = new URLSearchParams({ + model: POLLINATIONS_TEXT_MODEL, + json: 'true', + }); const llm = await fetch( - `${POLLINATIONS_TEXT_ENDPOINT}/${encodeURIComponent(prompt)}=gemini-fast?key=${ - apiKey - }`, + `${POLLINATIONS_TEXT_ENDPOINT}/${encodeURIComponent(prompt)}?${query}`, { - headers: { Accept: 'text/plain' }, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${apiKey}`, + }, }, ); if (!llm.ok) { @@ -1684,4 +1693,3 @@ const SimpleCite: Component = () => { export default SimpleCite; - diff --git a/src/pages/SimpleSuite.tsx b/src/pages/SimpleSuite.tsx index b564dce..111f039 100644 --- a/src/pages/SimpleSuite.tsx +++ b/src/pages/SimpleSuite.tsx @@ -4,7 +4,11 @@ import { Editor } from 'mini-canvas-editor'; import 'mini-canvas-editor/css/editor.css'; import { db } from '../db'; import type { Drawing } from '../db'; -import { getPollinationsApiKey, POLLINATIONS_TEXT_ENDPOINT } from '../utils/env'; +import { + getPollinationsApiKey, + POLLINATIONS_TEXT_ENDPOINT, + POLLINATIONS_TEXT_MODEL, +} from '../utils/env'; import styles from './SimpleSuite.module.css'; export type SuiteTab = 'text' | 'files' | 'human' | 'draw'; @@ -303,12 +307,19 @@ ${localPass}`; if (!apiKey) { throw new Error('Missing API key'); } + const query = new URLSearchParams({ model: POLLINATIONS_TEXT_MODEL }); const response = await fetch( - `${POLLINATIONS_TEXT_ENDPOINT}/${encoded}=gemini-fast?key=${apiKey}`, + `${POLLINATIONS_TEXT_ENDPOINT}/${encoded}?${query}`, { - headers: { Accept: 'text/plain' }, + headers: { + Accept: 'text/plain', + Authorization: `Bearer ${apiKey}`, + }, }, ); + if (!response.ok) { + throw new Error(`Pollinations request failed (${response.status})`); + } const result = await response.text(); let trimmed = result.trim(); @@ -905,4 +916,3 @@ export const SimpleSuite: Component = (props) => { export default SimpleSuite; - diff --git a/src/utils/env.ts b/src/utils/env.ts index 04f9630..9e5c475 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -7,6 +7,7 @@ declare global { } export const POLLINATIONS_TEXT_ENDPOINT = 'https://gen.pollinations.ai/text'; +export const POLLINATIONS_TEXT_MODEL = 'gemini-fast'; let envCache: Promise> | null = null; @@ -34,7 +35,11 @@ export const getPollinationsApiKey = async () => { try { const env = await loadEnv(); const apiKey = env.API_KEY; - return typeof apiKey === 'string' ? apiKey : ''; + if (typeof apiKey === 'string' && apiKey.startsWith('pk_')) { + return apiKey; + } + console.warn('Pollinations API key must be a browser-safe publishable key'); + return ''; } catch (error) { console.warn('Failed to load API key', error); return '';