char-slop/ai-dots
ai dotfiles
git clone https://git.t4t.associates/char-slop/ai-dots
766a1e1
main
1/** 2* Shared settings.json loading utilities. 3* 4* Reads global (~/.pi/agent/settings.json) and project (.pi/settings.json) 5* settings, merging them so the closest-to-cwd wins. 6*/ 7 8import { getAgentDir } from "@earendil-works/pi-coding-agent" ; 9import * as fs from "node:fs" ; 10import * as path from "node:path" ; 11 12type SettingsObject = Record < string , unknown >; 13 14function isSettingsObject ( value :unknown ) :value isSettingsObject { 15return typeof value === "object" && value !== null && ! Array . isArray ( value ); 16} 17 18function mergeInto ( target :SettingsObject , source :SettingsObject ) :void { 19for ( const [ key , value ] of Object . entries ( source )) { 20const existing = target [ key ]; 21if ( isSettingsObject ( existing ) && isSettingsObject ( value )) { 22mergeInto ( existing , value ); 23} else { 24target [ key ] = value ; 25} 26} 27} 28 29/** 30* Read and merge settings from global + all project-level settings.json files. 31* Project settings are walked up from `cwd` and applied farthest-first, 32* so the closest `.pi/settings.json` wins over more distant ones. 33*/ 34export function loadSettings ( cwd :string ) :Record < string , unknown > { 35const merged :SettingsObject = {}; 36 37function mergeFrom ( raw :string ) { 38try { 39const settings = JSON . parse ( raw ); 40if ( isSettingsObject ( settings )) { 41mergeInto ( merged , settings ); 42} 43} catch { 44/* ignore */ 45} 46} 47 48// Global settings 49try { 50mergeFrom ( fs . readFileSync ( path . join ( getAgentDir (), "settings.json" ), "utf-8" )); 51} catch { 52/* ignore */ 53} 54 55// Project settings (walk up from cwd, collect all, apply farthest-first so closest wins) 56const projectPaths :string [] = []; 57let dir = cwd ; 58while ( true ) { 59projectPaths . push ( path . join ( dir , ".pi" , "settings.json" )); 60const parent = path . dirname ( dir ); 61if ( parent === dir ) break ; 62dir = parent ; 63} 64for ( let i = projectPaths . length - 1 ; i >= 0 ; i -- ) { 65try { 66mergeFrom ( fs . readFileSync ( projectPaths [ i ], "utf-8" )); 67} catch { 68/* ignore */ 69} 70} 71 72return merged ; 73}