Resolve CutOS models path outside root home
This commit is contained in:
+37
-1
@@ -14,7 +14,18 @@ let operationId = 0;
|
|||||||
|
|
||||||
function resolvePiModelsConfigFile(env = process.env) {
|
function resolvePiModelsConfigFile(env = process.env) {
|
||||||
const configured = String(env.PI_MODELS_CONFIG || '').trim();
|
const configured = String(env.PI_MODELS_CONFIG || '').trim();
|
||||||
return configured ? path.resolve(configured) : path.join(os.homedir(), '.pi', 'agent', 'models.json');
|
if (configured) return path.resolve(configured);
|
||||||
|
|
||||||
|
const candidates = [];
|
||||||
|
if (process.getuid && process.getuid() === 0) {
|
||||||
|
candidates.push('/home/sts/.pi/agent/models.json');
|
||||||
|
}
|
||||||
|
candidates.push(path.join(os.homedir(), '.pi', 'agent', 'models.json'));
|
||||||
|
candidates.push('/root/.pi/agent/models.json');
|
||||||
|
|
||||||
|
return candidates.find((candidate) => {
|
||||||
|
try { return fs.existsSync(path.dirname(candidate)) || fs.existsSync(candidate); } catch (_) { return false; }
|
||||||
|
}) || candidates[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeBaseUrl(baseUrl) {
|
function normalizeBaseUrl(baseUrl) {
|
||||||
@@ -75,16 +86,41 @@ function readConfig(configFile) {
|
|||||||
|
|
||||||
function writeConfigAtomic(configFile, config) {
|
function writeConfigAtomic(configFile, config) {
|
||||||
const dir = path.dirname(configFile);
|
const dir = path.dirname(configFile);
|
||||||
|
const owner = resolveOwnerForPath(dir);
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
chownIfPossible(dir, owner);
|
||||||
const tempFile = path.join(dir, `.${path.basename(configFile)}.${process.pid}.${Date.now()}.tmp`);
|
const tempFile = path.join(dir, `.${path.basename(configFile)}.${process.pid}.${Date.now()}.tmp`);
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(tempFile, `${JSON.stringify(config, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
fs.writeFileSync(tempFile, `${JSON.stringify(config, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
||||||
fs.renameSync(tempFile, configFile);
|
fs.renameSync(tempFile, configFile);
|
||||||
|
chownIfPossible(configFile, owner);
|
||||||
} finally {
|
} finally {
|
||||||
try { fs.unlinkSync(tempFile); } catch (_) {}
|
try { fs.unlinkSync(tempFile); } catch (_) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveOwnerForPath(targetPath) {
|
||||||
|
let current = targetPath;
|
||||||
|
while (current && current !== path.dirname(current)) {
|
||||||
|
try {
|
||||||
|
const stat = fs.statSync(current);
|
||||||
|
return { uid: stat.uid, gid: stat.gid };
|
||||||
|
} catch (_) {
|
||||||
|
current = path.dirname(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function chownIfPossible(targetPath, owner) {
|
||||||
|
if (!owner || !(process.getuid && process.getuid() === 0)) return;
|
||||||
|
try {
|
||||||
|
fs.chownSync(targetPath, owner.uid, owner.gid);
|
||||||
|
} catch (error) {
|
||||||
|
log.warn('pi-provider', `chown failed for ${targetPath}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function sameModels(left, right) {
|
function sameModels(left, right) {
|
||||||
const ids = (models) => (models || []).map((model) => model.id).sort();
|
const ids = (models) => (models || []).map((model) => model.id).sort();
|
||||||
return JSON.stringify(ids(left)) === JSON.stringify(ids(right));
|
return JSON.stringify(ids(left)) === JSON.stringify(ids(right));
|
||||||
|
|||||||
Reference in New Issue
Block a user