(
entry: CustomProviderEntry,
opts?: { setDefault?: boolean; defaultModel?: string },
)
| 28 | * touching disk. |
| 29 | */ |
| 30 | export async function addProviderToConfig( |
| 31 | entry: CustomProviderEntry, |
| 32 | opts?: { setDefault?: boolean; defaultModel?: string }, |
| 33 | ): Promise<AddProviderResult> { |
| 34 | return withLock(QODEX_CONFIG_FILE + '.lock', async () => { |
| 35 | let raw = ''; |
| 36 | try { |
| 37 | raw = await fs.readFile(QODEX_CONFIG_FILE, 'utf-8'); |
| 38 | } catch (e: any) { |
| 39 | // Only a missing file means "no config yet — start fresh". Any other read |
| 40 | // error (permission denied, IO failure) must NOT be swallowed: doing so |
| 41 | // would merge into an empty object and overwrite the file, dropping every |
| 42 | // previously-configured provider. Surface it before the merge-and-write. |
| 43 | if (e?.code !== 'ENOENT') { |
| 44 | throw new Error( |
| 45 | `Could not read ${QODEX_CONFIG_FILE} (${e?.message ?? e}). ` + |
| 46 | `Refusing to overwrite it to avoid dropping existing providers. Fix the file/permissions, then retry.`, |
| 47 | ); |
| 48 | } |
| 49 | raw = ''; // no config yet — start fresh |
| 50 | } |
| 51 | |
| 52 | let parsed: any = {}; |
| 53 | if (raw.trim()) { |
| 54 | try { |
| 55 | parsed = yaml.load(raw) ?? {}; |
| 56 | } catch (e: any) { |
| 57 | throw new Error(`Could not parse ${QODEX_CONFIG_FILE}: ${e?.message ?? e}. Fix the YAML or move it aside, then retry.`); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | const merged = mergeCustomProvider(parsed, entry, opts); |
| 62 | const out = yaml.dump(merged, { lineWidth: 100, noRefs: true }); |
| 63 | |
| 64 | // Ensure the directory exists (first-run case). |
| 65 | const dir = QODEX_CONFIG_FILE.slice(0, QODEX_CONFIG_FILE.lastIndexOf('/')); |
| 66 | await fs.mkdir(dir, { recursive: true }); |
| 67 | await writeFileAtomic(QODEX_CONFIG_FILE, out); |
| 68 | |
| 69 | return { configPath: QODEX_CONFIG_FILE, name: entry.name, setDefault: !!opts?.setDefault }; |
| 70 | }); |
| 71 | } |
no test coverage detected