donobu
Version:
Create browser automations with an LLM agent and replay them as Playwright scripts.
124 lines • 4.73 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsonUtils = void 0;
const MiscUtils_1 = require("./MiscUtils");
const path_1 = __importDefault(require("path"));
const Logger_1 = require("./Logger");
const promises_1 = __importDefault(require("fs/promises"));
class JsonUtils {
constructor() { }
static getJsonSchemaFromTypeName(typeName) {
return JSON.parse(MiscUtils_1.MiscUtils.getResourceFileAsString(path_1.default.join('generated', 'parameter-schemas.json')))[typeName];
}
static objectToJson(object) {
const getCircularReplacer = () => {
const seen = new WeakSet();
return (_key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return undefined;
}
seen.add(value);
}
return value;
};
};
return JSON.parse(JSON.stringify(object, getCircularReplacer()));
}
static readResourceAsJson(source) {
try {
const jsonString = MiscUtils_1.MiscUtils.getResourceFileAsString(source);
return JSON.parse(jsonString);
}
catch (error) {
Logger_1.appLogger.error('Failed to read resource as JSON:', error);
return null;
}
}
static jsonStringToJsonObject(jsonString) {
try {
return JSON.parse(jsonString);
}
catch (error) {
Logger_1.appLogger.error('Failed to parse JSON string to object: ', error);
return null;
}
}
/**
* Post-process the given schema to conform with OpenAI constraints
* @see https://platform.openai.com/docs/guides/structured-outputs/additionalproperties-false-must-always-be-set-in-objects
*/
static postProcessJsonSchema(schema) {
if (schema.type === 'object') {
schema.additionalProperties = false;
if (schema.properties) {
const properties = schema.properties;
schema.required = schema.required || [];
Object.entries(properties).forEach(([fieldName, fieldSchema]) => {
if (!schema.required?.includes(fieldName)) {
schema.required?.push(fieldName);
if (typeof fieldSchema.type === 'string') {
fieldSchema.type = [fieldSchema.type, 'null'];
}
else if (Array.isArray(fieldSchema.type) &&
!fieldSchema.type.includes('null')) {
fieldSchema.type.push('null');
}
}
});
}
}
// Recursively process nested schemas
if (schema.properties) {
Object.values(schema.properties).forEach((prop) => {
if (typeof prop === 'object') {
this.postProcessJsonSchema(prop);
}
});
}
if (schema.items) {
const items = Array.isArray(schema.items) ? schema.items : [schema.items];
items.forEach((item) => {
if (typeof item === 'object') {
this.postProcessJsonSchema(item);
}
});
}
}
/**
* Ensures the given file path exists. If the file does not initially exist,
* all directories to it will be created and the file will be created with a
* value of an empty JSON object (AKA {}).
*/
static async maybeInitEmptyJsonFile(filePath) {
// Ensure the directory exists
const directory = path_1.default.dirname(filePath);
await promises_1.default
.mkdir(directory, { recursive: true })
.catch((dirError) => {
// Directory already exists, continue...
if (dirError.code !== 'EEXIST') {
throw dirError;
}
});
// Try to access the file to check if it exists
try {
await promises_1.default.access(filePath);
}
catch (error) {
const fsError = error;
// File doesn't exist, create it.
if (fsError.code === 'ENOENT') {
await promises_1.default.writeFile(filePath, '{}', 'utf8');
}
else {
throw error;
}
}
}
}
exports.JsonUtils = JsonUtils;
//# sourceMappingURL=JsonUtils.js.map