/** * Agent 0 – Pre-Flight Global Context Extractor * * Scans the initial segment of a contract to extract structural * definitions, governing law, and parties. */ const { callLLM } = require('./aiClient'); const Contract = require('../models/Contract'); const PRE_FLIGHT_SYSTEM_PROMPT = ` Role: Elite Enterprise Legal Ontologist & Ingestion Preprocessor. Task: Analyze the initial segments of the attached legal contract and build a deterministic Global Context JSON block. This contract may be of any type: employment agreement, real estate contract, freelance agreement, SaaS contract, NDA, etc. Extract party names generically (even if they are buyer/seller, employer/employee, licensor/licensee, etc.). You must strictly output a valid JSON object matching the schema below. Do NOT append introductory conversational text, markdown formatting blocks, or trailing commentary. Required Schema: { "metadata": { "documentType": "String (e.g., 'Employment Agreement', 'Real Estate Contract', 'Non-Disclosure Agreement', 'Service Agreement')", "governingLaw": "String (e.g., 'Republic of India / State of Karnataka')", "executionDate": "String (ISO 8601 Date or YYYY-MM-DD)", "employerName": "String (Party 1 / Company / Employer / Buyer / Licensor — whichever applies)", "employeeDesignation": "String (Party 2's role or designation — whichever applies)", "employeeAddress": "String (The physical city/state/country of Party 2 / Employee / Seller / Licensee)", "companyAddress": "String (The physical city/state/country of Party 1 / Company / Employer / Buyer)" } } `; /** * Run the pre-flight LLM extraction pass on the first 12,000 characters of the raw text. * * @param {string} rawText * @returns {Promise} */ async function runAgentPreFlight(rawText) { // Extract initial slice (first 20,000 characters) where recitals live const sampleText = (rawText || '').substring(0, 20000).trim(); // If the contract is completely blank, return empty structured fallback if (!sampleText) { return { metadata: { governingLaw: null, employerName: null, employeeDesignation: null, employeeAddress: null, companyAddress: null, } }; } try { const resp = await callLLM({ systemPrompt: PRE_FLIGHT_SYSTEM_PROMPT, userContent: sampleText, jsonMode: true, temperature: 0.1, maxTokens: 1000, }); // Tail scan for governing law if missing if (!resp?.metadata?.governingLaw && rawText.length > 20000) { const tailText = rawText.slice(-5000).trim(); if (tailText) { const tailResp = await callLLM({ systemPrompt: PRE_FLIGHT_SYSTEM_PROMPT, userContent: tailText, jsonMode: true, temperature: 0.1, maxTokens: 1000, }); if (tailResp?.metadata?.governingLaw) { if (!resp.metadata) resp.metadata = {}; resp.metadata.governingLaw = tailResp.metadata.governingLaw; } } } // Ensure safe structured defaults in case of incomplete/partial object returns return { metadata: { documentType: resp?.metadata?.documentType || null, governingLaw: resp?.metadata?.governingLaw || null, executionDate: resp?.metadata?.executionDate || null, employerName: resp?.metadata?.employerName || null, employeeDesignation: resp?.metadata?.employeeDesignation || null, employeeAddress: resp?.metadata?.employeeAddress || null, companyAddress: resp?.metadata?.companyAddress || null, } }; } catch (err) { console.error('⚠️ Pre-Flight LLM extraction failed. Returning safe defaults.', err.message); return { metadata: { documentType: null, governingLaw: null, employerName: null, employeeDesignation: null, employeeAddress: null, companyAddress: null, } }; } } /** * Extract and save global context for a specific contract. * * @param {string} contractId */ async function extractGlobalContextForContract(contractId) { const contract = await Contract.findById(contractId); if (!contract) { throw new Error(`Contract ${contractId} not found.`); } console.log(`🧠 [Pre-Flight Agent] Running global context extraction for: ${contract.originalFileName}`); const globalContext = await runAgentPreFlight(contract.rawText); // Persist to MongoDB await Contract.findByIdAndUpdate(contractId, { globalContext, 'agentMetadata.preFlightExtractedAt': new Date(), 'agentMetadata.isPreFlightComplete': true, }); console.log(`✅ [Pre-Flight Agent] Global context persisted for contract ${contractId}`); } module.exports = { runAgentPreFlight, extractGlobalContextForContract };