mike-backend / backend /scripts /bootstrap-builtin-column-modules.mjs
bardd's picture
Deploy Mike backend-only Space
06671aa verified
Raw History Blame Contribute Delete
6.65 kB
#!/usr/bin/env node
/**
* One-time bootstrap: import frontend builtin registry into backend canonical modules.
* Not the workflow export script — see export-builtin-workflows.mjs.
*/
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import {
parseFrontendInventory,
stableStringify,
} from "./lib/parseFrontendBuiltinWorkflows.mjs";
const __dirname = dirname(fileURLToPath(import.meta.url));
const BACKEND = join(__dirname, "..");
const COLUMNS_DIR = join(BACKEND, "src/prompts/tabular/builtin-columns");
const GOLDEN_PATH = join(
BACKEND,
"tests/golden/builtin-workflows-frontend-bootstrap.json",
);
const TABULAR_WORKFLOW_IDS = [
"builtin-coc-dd",
"builtin-commercial-agreement",
"builtin-credit-agreement",
"builtin-ediscovery",
"builtin-supply-agreement",
"builtin-spa",
"builtin-nda",
"builtin-commercial-lease",
"builtin-lpa",
"builtin-shareholder-agreement",
"builtin-employment-agreement",
"builtin-zamil-proposal-radar",
"builtin-zamil-subcontractor-radar",
"builtin-zamil-peb-commercial-terms-radar",
];
function toExportName(workflowId) {
return workflowId
.replace(/^builtin-/, "")
.replace(/-/g, "_")
.toUpperCase();
}
function escapeTemplateLiteral(value) {
return value
.replace(/\\/g, "\\\\")
.replace(/`/g, "\\`")
.replace(/\$\{/g, "\\${");
}
function serializeColumn(col) {
const lines = [
" {",
` index: ${col.index},`,
` name: ${JSON.stringify(col.name)},`,
];
if (col.format !== undefined) {
lines.push(` format: ${JSON.stringify(col.format)},`);
}
if (col.tags !== undefined) {
lines.push(
` tags: ${JSON.stringify(col.tags)},`,
);
}
lines.push(
` prompt: ${JSON.stringify(col.prompt)},`,
" },",
);
return lines.join("\n");
}
function writeColumnModule(workflowId, columns) {
const exportName = `${toExportName(workflowId)}_COLUMNS`;
const fileName = `${workflowId}.ts`;
const body = `/** Tabular built-in columns for ${workflowId} — canonical backend source. */\nimport type { BuiltinColumnConfig } from "./types";\n\nexport const ${exportName}: BuiltinColumnConfig[] = [\n${columns.map(serializeColumn).join("\n")}\n];\n`;
const fullPath = join(COLUMNS_DIR, fileName);
writeFileSync(fullPath, body, "utf8");
return { fileName, exportName };
}
function writeMetadataModule(workflows) {
const entries = workflows.map((wf) => {
const fields = [
` id: ${JSON.stringify(wf.id)},`,
` title: ${JSON.stringify(wf.title)},`,
` type: ${JSON.stringify(wf.type)},`,
` practice: ${JSON.stringify(wf.practice ?? null)},`,
];
if ("playbook_id" in wf) {
fields.push(
` playbook_id: ${JSON.stringify(wf.playbook_id ?? null)},`,
);
}
if (wf.prompt_md) {
fields.push(
` prompt_md: \`${escapeTemplateLiteral(wf.prompt_md)}\`,`,
);
} else {
fields.push(" prompt_md: null,");
}
return ` {\n${fields.join("\n")}\n }`;
});
const body = `/** Canonical built-in workflow metadata imported from frontend bootstrap inventory. */\nimport type { BuiltinWorkflowMetadata } from "./types";\n\nexport const BUILTIN_WORKFLOW_METADATA: BuiltinWorkflowMetadata[] = [\n${entries.join(",\n")}\n];\n`;
writeFileSync(join(COLUMNS_DIR, "metadata.ts"), body, "utf8");
}
function writeIndex(exportsList) {
const imports = exportsList
.map(({ fileName, exportName }) => {
const base = fileName.replace(/\.ts$/, "");
return `import { ${exportName} } from "./${base}";`;
})
.join("\n");
const mapEntries = exportsList
.map(({ fileName, exportName }) => {
const id = fileName.replace(/\.ts$/, "");
return ` "${id}": ${exportName},`;
})
.join("\n");
const body = `${imports}
import { BUILTIN_WORKFLOW_METADATA } from "./metadata";
export { BUILTIN_WORKFLOW_METADATA } from "./metadata";
export * from "./types";
export const BUILTIN_TABULAR_COLUMNS = {
${mapEntries}
} as const;
`;
writeFileSync(join(COLUMNS_DIR, "index.ts"), body, "utf8");
}
function writeTypes() {
const body = `export type BuiltinColumnFormat =
| "text"
| "bulleted_list"
| "number"
| "currency"
| "yes_no"
| "date"
| "tag"
| "percentage"
| "monetary_amount";
export interface BuiltinColumnConfig {
index: number;
name: string;
prompt: string;
format?: BuiltinColumnFormat;
tags?: string[];
}
export interface BuiltinWorkflowMetadata {
id: string;
title: string;
type: "assistant" | "tabular" | "playbook";
practice: string | null;
playbook_id?: string | null;
prompt_md: string | null;
}
export interface BuiltinWorkflowExport {
id: string;
user_id: null;
is_system: true;
created_at: "";
title: string;
type: "assistant" | "tabular" | "playbook";
practice: string | null;
playbook_id?: string | null;
prompt_md: string | null;
columns_config: BuiltinColumnConfig[] | null;
}
`;
writeFileSync(join(COLUMNS_DIR, "types.ts"), body, "utf8");
}
const inventory = parseFrontendInventory();
mkdirSync(COLUMNS_DIR, { recursive: true });
writeTypes();
const columnExports = [];
for (const workflowId of TABULAR_WORKFLOW_IDS) {
const wf = inventory.workflows.find((w) => w.id === workflowId);
if (!wf?.columns_config) {
throw new Error(`Missing tabular columns for ${workflowId}`);
}
columnExports.push(writeColumnModule(workflowId, wf.columns_config));
}
writeMetadataModule(inventory.workflows);
writeIndex(columnExports);
const golden = {
orderedIds: inventory.orderedIds,
totalWorkflowCount: inventory.totalWorkflowCount,
perWorkflowColumnCount: inventory.perWorkflowColumnCount,
totalColumnPromptCount: inventory.totalColumnPromptCount,
sha256: inventory.sha256,
workflows: inventory.workflows,
};
writeFileSync(GOLDEN_PATH, stableStringify(golden), "utf8");
console.log(
`bootstrap: ${inventory.totalWorkflowCount} workflows, ${inventory.totalColumnPromptCount} column prompts`,
);
console.log(`bootstrap sha256: ${inventory.sha256}`);
console.log(`wrote golden: ${GOLDEN_PATH}`);