diff --git a/docs/README.md b/docs/README.md index 2a08f5b..394051c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,6 +14,7 @@ Operational, architectural, and UX-design notes for the local-AI IDE initiative | [../deploy/nginx/README-ia-enso.md](../deploy/nginx/README-ia-enso.md) | Proxy HTTPS `ia.enso.4nkweb.com` → Ollama / AnythingLLM (Bearer, script SSH, dépannage) | | [../extensions/anythingllm-workspaces/README.md](../extensions/anythingllm-workspaces/README.md) | Extension VS Code / Cursor : lister les workspaces AnythingLLM (API) et ouvrir l’UI | | [features/anythingllm-vscode-extension.md](./features/anythingllm-vscode-extension.md) | Fiche évolution : extension AnythingLLM, impacts, modalités | +| [fixKnowledge/anythingllm-extension-403-api-key.md](./fixKnowledge/anythingllm-extension-403-api-key.md) | 403 API AnythingLLM : clé nginx Ollama vs clé UI API Keys | | [features/ia-enso-nginx-proxy-ollama-anythingllm.md](./features/ia-enso-nginx-proxy-ollama-anythingllm.md) | Fiche évolution : objectifs, impacts, modalités du reverse proxy ia.enso | | [anythingllm-workspaces.md](./anythingllm-workspaces.md) | One AnythingLLM workspace per project; sync pipeline | | [ux-navigation-model.md](./ux-navigation-model.md) | Beyond file explorer: intentions, graph, palette, risks, expert mode | diff --git a/docs/fixKnowledge/anythingllm-extension-403-api-key.md b/docs/fixKnowledge/anythingllm-extension-403-api-key.md new file mode 100644 index 0000000..0b6b6f0 --- /dev/null +++ b/docs/fixKnowledge/anythingllm-extension-403-api-key.md @@ -0,0 +1,43 @@ +# AnythingLLM extension — 403 « No valid api key found » + +**Author:** 4NK + +## Symptôme + +Commande **AnythingLLM: List workspaces** → erreur du type : + +`AnythingLLM API 403: {"error":"No valid api key found."}` + +## Cause + +Le middleware amont `validApiKey` lit `Authorization`, extrait le jeton après `Bearer `, puis appelle `ApiKey.get({ secret })` sur la base AnythingLLM. Toute valeur absente de cette base produit la même réponse 403. + +## Root cause fréquente + +Confusion entre : + +- le **secret Bearer nginx** utilisé pour `https://ia.enso.4nkweb.com/ollama/…` (documenté dans `deploy/nginx/README-ia-enso.md`) ; +- une **clé API AnythingLLM** créée dans l’UI : **Settings → API Keys**. + +Ce sont deux mécanismes indépendants. Le secret nginx n’est **pas** enregistré comme clé API dans AnythingLLM. + +## Correctifs côté utilisateur + +1. Ouvrir l’UI AnythingLLM (`anythingllm.baseUrl`). +2. **Settings → API Keys** : créer une clé si besoin, copier le secret affiché. +3. Coller ce secret dans `anythingllm.apiKey` (réglages **Utilisateur** de l’éditeur). + +## Correctifs côté code / doc + +- README de l’extension : rappel explicite nginx vs clé AnythingLLM. +- Client : normalisation `normalizeApiSecret` — si l’utilisateur a collé `Bearer `, le préfixe est retiré avant l’envoi (évite un jeton parsé comme `Bearer` par erreur). + +## Modalités d’analyse + +- Vérifier la réponse HTTP brute (403 + corps JSON). +- Comparer la valeur configurée avec l’origine (fichier map nginx vs écran API Keys). +- Tester avec `curl` : `curl -sS -H "Authorization: Bearer " "/api/v1/workspaces"`. + +## Modalités de déploiement + +Redéployer / réinstaller l’extension après modification du client (`npm run compile` ou nouveau `.vsix`). Aucun changement nginx requis pour ce diagnostic. diff --git a/extensions/anythingllm-workspaces/README.md b/extensions/anythingllm-workspaces/README.md index 6a2050f..f05c475 100644 --- a/extensions/anythingllm-workspaces/README.md +++ b/extensions/anythingllm-workspaces/README.md @@ -7,12 +7,14 @@ Minimal extension to call the **AnythingLLM developer API** and open a workspace - AnythingLLM reachable at your public base URL (e.g. `https://ia.enso.4nkweb.com/anythingllm`). - An **API key** created in AnythingLLM: **Settings → API Keys**. +**Do not** use the **nginx Bearer secret** for `/ollama/` (see `deploy/nginx/README-ia-enso.md`). That value is only for the Ollama reverse proxy. AnythingLLM validates API keys against its **own** database; a wrong secret yields `403` with `{"error":"No valid api key found."}`. + ## Configuration | Setting | Description | |--------|-------------| | `anythingllm.baseUrl` | Base URL without trailing slash (default matches `deploy/nginx/README-ia-enso.md`). | -| `anythingllm.apiKey` | Bearer token for `GET /api/v1/workspaces`. Use **User** settings to avoid committing secrets. | +| `anythingllm.apiKey` | Secret from AnythingLLM **Settings → API Keys** (optional leading `Bearer ` is stripped). Use **User** settings to avoid committing secrets. | ## Commands diff --git a/extensions/anythingllm-workspaces/package.json b/extensions/anythingllm-workspaces/package.json index 048b10b..c2b0c76 100644 --- a/extensions/anythingllm-workspaces/package.json +++ b/extensions/anythingllm-workspaces/package.json @@ -2,7 +2,7 @@ "name": "anythingllm-workspaces", "displayName": "AnythingLLM Workspaces (ia.enso)", "description": "List AnythingLLM workspaces via your proxied instance (e.g. ia.enso.4nkweb.com/anythingllm).", - "version": "0.1.0", + "version": "0.1.1", "publisher": "4nk", "license": "MIT", "engines": { diff --git a/extensions/anythingllm-workspaces/src/anythingllmClient.ts b/extensions/anythingllm-workspaces/src/anythingllmClient.ts index fceb734..f95601d 100644 --- a/extensions/anythingllm-workspaces/src/anythingllmClient.ts +++ b/extensions/anythingllm-workspaces/src/anythingllmClient.ts @@ -49,12 +49,18 @@ const parseListWorkspaces = (payload: unknown): readonly AnythingWorkspace[] => return workspaces; }; +const normalizeApiSecret = (raw: string): string => { + const trimmed = raw.trim(); + const bearerPrefix = /^Bearer\s+/i; + return bearerPrefix.test(trimmed) ? trimmed.replace(bearerPrefix, "").trim() : trimmed; +}; + export const listWorkspaces = async ( baseUrl: string, apiKey: string, ): Promise => { const normalized = normalizeAnythingLlmBaseUrl(baseUrl); - const key = apiKey.trim(); + const key = normalizeApiSecret(apiKey); if (key.length === 0) { throw new Error("anythingllm.apiKey is empty"); }