Files
PaperClipAI/server/src/config-file.ts
T
DottaandPaperclip 8f822bfcf7 fix(cloud): persist configuration and load release-image packages (#18335)
Land the approved Cloud configuration and release-image package stack.

Includes the separately reviewed adapter settings (#18335), external adapters (#18333), bundled plugins (#18336), startup configuration (#18339), and migration/package checks (#18341).

Includes the final image-owned loader and linked-dependency inventory corrections.

Verified stack head: 462716170d.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 19:21:33 +00:00

61 lines
2.1 KiB
TypeScript

import fs from "node:fs";
import {
DEPLOYMENT_MODES,
findPaperclipConfigKeyWarnings,
paperclipConfigSchema,
type PaperclipConfig,
type DeploymentMode,
} from "@paperclipai/shared";
import { ZodError } from "zod";
import { resolvePaperclipConfigPath } from "./paths.js";
import { isCloudManagedInstance } from "./services/cloud-instance.js";
import { getCloudRuntimeConfigSnapshot, toPaperclipConfig } from "./services/cloud-runtime-config-snapshot.js";
function formatConfigValidationError(error: ZodError): string {
return error.issues
.map((issue) => {
const issuePath = issue.path.length > 0 ? issue.path.join(".") : "<root>";
return `${issuePath}: ${issue.message}`;
})
.join("; ");
}
export function readConfigFile(): PaperclipConfig | null {
if (isCloudManagedInstance()) return toPaperclipConfig(getCloudRuntimeConfigSnapshot().config);
const configPath = resolvePaperclipConfigPath();
if (!fs.existsSync(configPath)) return null;
let raw: unknown;
try {
raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
} catch (error) {
const reason = error instanceof Error ? error.message : String(error);
throw new Error(`Invalid Paperclip config at ${configPath}: failed to read or parse JSON: ${reason}`);
}
try {
const config = paperclipConfigSchema.parse(raw);
for (const warning of findPaperclipConfigKeyWarnings(config)) {
console.warn(
`Unknown config key ${warning.path}; did you mean ${warning.suggestion}? It will be preserved.`,
);
}
return config;
} catch (error) {
if (error instanceof ZodError) {
throw new Error(`Invalid Paperclip config at ${configPath}: ${formatConfigValidationError(error)}`);
}
throw error;
}
}
/** Resolve the same deployment mode without loading config.ts's dotenv/startup side effects. */
export function resolveDeploymentMode(fileConfig = readConfigFile()): DeploymentMode {
const fromEnv = process.env.PAPERCLIP_DEPLOYMENT_MODE;
return fromEnv && DEPLOYMENT_MODES.includes(fromEnv as DeploymentMode)
? fromEnv as DeploymentMode
: fileConfig?.server.deploymentMode ?? "local_trusted";
}