From 19ae7504b54d476ab2465bdf1adcfedc574b8207 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Wed, 10 Jun 2026 16:28:49 -0400 Subject: [PATCH] migrate to settings.json --- README.md | 25 +++++++++++++++---- index.ts | 2 +- src/firecrawl.ts | 63 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 77ffff8..0b22d06 100644 --- a/README.md +++ b/README.md @@ -79,21 +79,36 @@ Research Flow: ## Configuration -Deep Research reads Firecrawl configuration from `~/.pi/agent/settings.json`: +Deep Research reads Firecrawl configuration from pi's settings.json files, with the following resolution order (later wins): + +1. Environment variables (`FIRECRAWL_BASE_URL`, `FIRECRAWL_API_KEY`) +2. Global settings (`$agentDir/settings.json`) → `firecrawl.*` +3. Project settings (`.pi/settings.json`) → `firecrawl.*` +4. Default `http://localhost:3002` (if nothing else sets baseUrl) + +The agent directory (`$agentDir`) defaults to `~/.pi/agent` and respects the `PI_CODING_AGENT_DIR` environment variable. + +**Global settings** (`~/.pi/agent/settings.json`): ```json { "firecrawl": { "baseUrl": "http://localhost:3002", + } +} +``` + +**Project settings** (`.pi/settings.json` — overrides global): + +```json +{ + "firecrawl": { + "baseUrl": "https://firecrawl.team.internal" "apiKey": "your-api-key" } } ``` -Environment variables are also supported: -- `FIRECRAWL_BASE_URL` — overrides the Firecrawl endpoint (default: `http://localhost:3002`) -- `FIRECRAWL_API_KEY` — API key for authenticated Firecrawl instances - ### Session startup check On `session_start`, the extension checks whether the Firecrawl endpoint is reachable. If not, it shows a warning notification so you know searches will fail before you try to use it. diff --git a/index.ts b/index.ts index 274155b..b4bd1cb 100644 --- a/index.ts +++ b/index.ts @@ -585,7 +585,7 @@ export default function (pi: ExtensionAPI) { const reachable = await isFirecrawlReachable(); if (!reachable) { ctx.ui.notify( - "Deep Research: Firecrawl endpoint unreachable — searches will fail. Check FIRECRAWL_BASE_URL in settings.json or env.", + "Deep Research: Firecrawl endpoint unreachable — searches will fail. Set firecrawl.baseUrl in settings.json (global or project) or the FIRECRAWL_BASE_URL env var.", "warning", ); } diff --git a/src/firecrawl.ts b/src/firecrawl.ts index 4b14c4a..c087513 100644 --- a/src/firecrawl.ts +++ b/src/firecrawl.ts @@ -6,32 +6,53 @@ */ import * as fs from "node:fs"; import * as path from "node:path"; -import * as os from "node:os"; import type { SearchResult, EnrichedSearchResult, ContentType } from "./types"; +import { getAgentDir } from "@earendil-works/pi-coding-agent"; /* ── Config ──────────────────────────────────────────────────────── */ +/** + * Read and merge Firecrawl settings from pi's settings.json files. + * + * Resolution order (later wins): + * 1. env vars FIRECRAWL_BASE_URL / FIRECRAWL_API_KEY + * 2. global ~/.pi/agent/settings.json → firecrawl.* + * 3. project .pi/settings.json → firecrawl.* + * 4. default http://localhost:3002 (if no baseUrl configured) + */ function loadFirecrawlConfig() { - const settingsPath = path.join(os.homedir(), ".pi", "agent", "settings.json"); - try { - const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8")); - const fc = settings.firecrawl ?? {}; - return { - baseUrl: ( - fc.baseUrl ?? - process.env.FIRECRAWL_BASE_URL ?? - "http://localhost:3002" - ).replace(/\/+$/, ""), - apiKey: fc.apiKey ?? process.env.FIRECRAWL_API_KEY, - }; - } catch { - return { - baseUrl: ( - process.env.FIRECRAWL_BASE_URL ?? "http://localhost:3002" - ).replace(/\/+$/, ""), - apiKey: process.env.FIRECRAWL_API_KEY, - }; - } + // Start with env var defaults + let baseUrl = process.env.FIRECRAWL_BASE_URL ?? "http://localhost:3002"; + let apiKey = process.env.FIRECRAWL_API_KEY; + + const agentDir = getAgentDir(); + + // Helper: read a settings.json and merge its firecrawl.* keys + const tryReadSettings = (settingsPath: string): void => { + try { + const raw = JSON.parse(fs.readFileSync(settingsPath, "utf-8")); + const fc: Record = raw.firecrawl ?? {}; + if (typeof fc.baseUrl === "string" && fc.baseUrl.length > 0) { + baseUrl = fc.baseUrl; + } + if (typeof fc.apiKey === "string" && fc.apiKey.length > 0) { + apiKey = fc.apiKey; + } + } catch { + // File missing or unparseable — skip + } + }; + + // 1. Global settings + tryReadSettings(path.join(agentDir, "settings.json")); + + // 2. Project settings (override global) + tryReadSettings(path.join(process.cwd(), ".pi", "settings.json")); + + return { + baseUrl: baseUrl.replace(/\/+$/, ""), + apiKey, + }; } const { baseUrl: BASE_URL, apiKey: API_KEY } = loadFirecrawlConfig();