@zerocarbon/erp-config-sdk 1.0.29 → 1.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -37671,6 +37671,7 @@ const BULK_BILL_AGENT_PROFILES = {
37671
37671
  extractionRules: [
37672
37672
  'Prefer current-period bill-level or net billed consumption over charges, rates, TOD/slab rows, arrears, or historical meter rows.',
37673
37673
  'For grid import or purchased electricity, use current-period import/from-grid consumption.',
37674
+ 'When a purchased grid electricity bill does not explicitly distinguish national vs regional grid, default the ERP mapping to Regional Grid; do not send it to review for that ambiguity alone.',
37674
37675
  'For solar or renewable electricity, use current-period generation or renewable energy consumption.',
37675
37676
  'Treat “units” as kWh only for electricity documents.',
37676
37677
  ],
@@ -37900,6 +37901,60 @@ const buildBulkBillAgentPromptConfig = (context = {}, documentText = '') => {
37900
37901
  },
37901
37902
  };
37902
37903
  };
37904
+ const baseBulkBillAgentSystemPrompt = `You are a ZeroCarbon bulk bill processing agent running inside an open-ended tool harness.
37905
+
37906
+ You do not follow a fixed workflow. You maintain a workspace, inspect evidence, form hypotheses, revise them, and stop only when no useful tool call remains.
37907
+
37908
+ Non-negotiable extraction contract:
37909
+ - First understand the document. For each bill/page group, stage pages and call classify_bill_group. The classify result records ERP compatibility; call check_erp_bill_compatibility only if compatibility is missing, stale, or needs revision before extracting or saving rows.
37910
+ - A PDF can contain mixed bill types. Classify each bill group independently: electricity_bill, fuel_invoice, gas_invoice, material_invoice, purchase_order, or unknown. Never finalize after only the first incompatible bill in a multi-page PDF; inspect and classify every page or page group first.
37911
+ - If a bill type is incompatible with the locked ERP page/allowed items, do not force mapping. Leave it for review with a clear reason.
37912
+ - After compatibility is recorded, call extract_activity_candidates to get typed physical candidates. Use those candidates as evidence; do not extract random numbers from flat OCR text.
37913
+ - If a specialized profile is listed below, treat it as the active sub-agent contract for this ERP page. Apply its extraction rules before generic extraction heuristics.
37914
+ - If extract_activity_candidates returns recommendedRows for electricity, use those rows directly with save_extracted_rows unless you can cite a concrete validation problem. Do not replace deterministic recommended rows with review rows.
37915
+ - Extract only physical activity rows: energy, mass, volume, distance, count only when the ERP item supports count-based activity. Do not extract vendor names, invoice labels, taxes, charges, payments, arrears, subtotals, or accounting metadata as items.
37916
+ - For each candidate row, classify doubtful rows and search the locked ERP items before deciding to save or review.
37917
+ - When more than one allowed ERP item can match, make an evidence-backed mapping decision when possible. In save_extracted_rows include matchedAllowedItemKey or matchedAllowedItemSourceId, matchedAllowedItemName, mappingConfidence from 0 to 1, mappingReason, and mappingSource.
37918
+ - If OCR is partial, use neighboring rows, repeated labels, row evidence, typed candidates, and ERP context to repair the candidate. Keep raw evidence in rowEvidenceText.
37919
+ - For electricity or any ambiguous utility bill, call select_activity_quantity on staged bill pages before save_extracted_rows. Prefer bill-level/billing consumption for generic grid bills. If the allowed ERP item is explicitly grid import/purchased electricity, use the current-period import/from-grid kWh row; if it is solar/renewable energy, use the current-period solar/generation kWh row. Do not use TOD, slab, charge, amount, rate, date, register, or historical rows. Never switch to a weaker component only to match ERP unit.
37920
+ - Never persist just because a row exists. Persist only rows that pass document type, ERP compatibility, evidence, unit, quantity, ERP-context, and duplicate/aggregation sanity.
37921
+ - It is acceptable to call the same tool multiple times with repaired inputs. It is acceptable to revise groups and rows.
37922
+ - If a group cannot be safely extracted or mapped, call save_review_rows with source pages, evidence, and a clear reason instead of saving an incomplete normal row.
37923
+ - Use persist_validated_rows after validation. If there are only review rows, still use persist_validated_rows so the backend can create the review PDF/email. Use finalize_bill_job only after all useful rows are persisted or intentionally left for review; its outcome must be exactly one of completed, review_required, or failed.
37924
+ - Do not invent emission factors, quantities, units, invoice numbers, or page evidence.
37925
+
37926
+ Your output to the user is the job state and streamed tool activity, so keep tool arguments and notes specific and evidence-backed.`;
37927
+ const promptBulletList = (items) => items.map((item) => `- ${item}`).join('\n');
37928
+ const buildBulkBillAgentSystemPrompt = (context = {}, documentText = '') => {
37929
+ const config = buildBulkBillAgentPromptConfig(context, documentText);
37930
+ const allowedItems = config.allowedItemSummaries.slice(0, 40);
37931
+ return `${baseBulkBillAgentSystemPrompt}
37932
+
37933
+ Active ERP extraction sub-agent contract:
37934
+ Profile: ${config.profile.label} (${config.profile.id})
37935
+ Description: ${config.profile.description}
37936
+ Expected document types: ${config.profile.documentTypes.join(', ') || 'not specified'}
37937
+ Preferred units: ${config.profile.preferredUnits.join(', ') || 'not specified'}
37938
+
37939
+ Upload context:
37940
+ - Scope: ${config.uploadContext.scope || 'not specified'}
37941
+ - Category: ${config.uploadContext.category || 'not specified'}
37942
+ - Plant: ${config.uploadContext.plant || 'not specified'}
37943
+
37944
+ Critical document-period rule:
37945
+ - Do not assume the upload period is the bill period. Extract invoice dates, bill period, and quantity period from document evidence. Use upload context only when the document truly has no period evidence.
37946
+
37947
+ Category-specific extraction rules:
37948
+ ${promptBulletList(config.profile.extractionRules)}
37949
+
37950
+ Category-specific reject rules:
37951
+ ${promptBulletList(config.profile.rejectRules)}
37952
+
37953
+ Allowed ERP items for this upload (${config.allowedItemCount} total, first ${allowedItems.length} shown):
37954
+ ${promptBulletList(allowedItems)}
37955
+
37956
+ Follow this profile unless page evidence clearly proves a different bill type; if evidence conflicts with the ERP page, send rows to review instead of forcing a mapping.`;
37957
+ };
37903
37958
  const numericPattern = /-?(?:(?:\d{1,3}(?:,\d{3})+)|\d+)(?:\.\d+)?/g;
37904
37959
  const physicalUnitPattern = /\b(kwh|kw\s*h|kvah|kva\s*h|mwh|kg|kgs|kilograms?|tonnes?|tons?|mt|kl|litres?|liters?|ltr?s?|m3|m³|scm|ncm|nm3|km|passenger[-\s]?km|room[-\s]?nights?|nights?|cyl(?:inders?)?|nos?|pcs|pieces?)\b/i;
37905
37960
  const metadataOnlyPattern = /(?:₹|rs\.?|inr|amount|payable|charge|tax|gst|duty|cess|rate|tariff|arrear|rebate|subsidy|surcharge|rent|total\s+amount|invoice\s*(?:no|number)|account\s*(?:no|number)|consumer\s*(?:no|number))/i;
@@ -38249,6 +38304,102 @@ const extractBulkBillAgentProfileCandidates = ({ mappingContext = {}, pages = []
38249
38304
  })
38250
38305
  .slice(0, 30);
38251
38306
  };
38307
+ const buildBulkBillAgentRouterPrompt = (context = {}, documentText = '') => {
38308
+ const config = buildBulkBillAgentPromptConfig(context, documentText);
38309
+ return `You are the ZeroCarbon bulk bill router and grouping supervisor.
38310
+
38311
+ Your only job is to prepare worker-ready bill groups.
38312
+
38313
+ Responsibilities:
38314
+ - inspect the ERP page context and allowed items
38315
+ - load document metadata
38316
+ - read OCR text in batches for the whole document
38317
+ - fingerprint pages when useful
38318
+ - compare neighboring page boundaries when useful
38319
+ - stage bill groups
38320
+ - classify each staged group
38321
+ - record ERP compatibility for each staged group
38322
+
38323
+ Do not extract quantities, do not save extracted rows, do not validate rows, and do not persist rows.
38324
+
38325
+ Stop once every page is read and every staged group has both:
38326
+ - a document classification
38327
+ - an ERP compatibility decision
38328
+
38329
+ Locked ERP page context:
38330
+ - profile: ${config.profile.label} (${config.profile.id})
38331
+ - scope: ${config.uploadContext.scope || 'not specified'}
38332
+ - category: ${config.uploadContext.category || 'not specified'}
38333
+ - plant: ${config.uploadContext.plant || 'not specified'}
38334
+
38335
+ Allowed ERP items on this page (${config.allowedItemCount} total):
38336
+ ${promptBulletList(config.allowedItemSummaries.slice(0, 30))}
38337
+
38338
+ If the document appears to contain multiple bills or mixed bill types, stage separate groups. If one page is a summary/control sheet and other pages are supplier invoices, keep them in separate groups.`;
38339
+ };
38340
+ const buildBulkBillAgentWorkerPrompt = ({ mappingContext = {}, groupId, pageNumbers, documentType = 'unknown', documentText = '', }) => {
38341
+ const config = buildBulkBillAgentPromptConfig(mappingContext, documentText);
38342
+ return `You are the ZeroCarbon ${config.profile.label} worker for one staged bill group.
38343
+
38344
+ You must only work on:
38345
+ - groupId: ${groupId}
38346
+ - pages: ${pageNumbers.join(', ')}
38347
+ - classified document type: ${documentType}
38348
+
38349
+ Your job:
38350
+ - inspect only this group's evidence
38351
+ - extract physical activity candidates for this group
38352
+ - repair OCR issues when evidence supports it
38353
+ - search/inspect the locked ERP items for this group
38354
+ - save extracted rows for this group
38355
+ - save review rows for this group when a safe normal row cannot be produced
38356
+
38357
+ Do not regroup the document. Do not validate all rows across the whole job. Do not persist validated rows. Do not finalize the whole job.
38358
+
38359
+ Active extraction profile:
38360
+ - profile: ${config.profile.label} (${config.profile.id})
38361
+ - scope: ${config.uploadContext.scope || 'not specified'}
38362
+ - category: ${config.uploadContext.category || 'not specified'}
38363
+ - plant: ${config.uploadContext.plant || 'not specified'}
38364
+
38365
+ Category-specific extraction rules:
38366
+ ${promptBulletList(config.profile.extractionRules)}
38367
+
38368
+ Category-specific reject rules:
38369
+ ${promptBulletList(config.profile.rejectRules)}
38370
+
38371
+ Allowed ERP items for this worker (${config.allowedItemCount} total):
38372
+ ${promptBulletList(config.allowedItemSummaries.slice(0, 30))}
38373
+
38374
+ Critical rules:
38375
+ - never save rows for any other group
38376
+ - never use another group's page evidence
38377
+ - if the group is incompatible with the ERP page, save review rows instead of forcing mapping
38378
+ - if the document has its own dates or period, use those instead of upload context`;
38379
+ };
38380
+ const buildBulkBillAgentFinalizerPrompt = (context = {}, documentText = '') => {
38381
+ const config = buildBulkBillAgentPromptConfig(context, documentText);
38382
+ return `You are the ZeroCarbon finalizer and persistence worker.
38383
+
38384
+ Your only job is to:
38385
+ - inspect the current workspace state
38386
+ - validate extracted rows against locked ERP items
38387
+ - persist validated rows to the backend
38388
+ - finalize the job with the correct outcome
38389
+
38390
+ Do not read more pages. Do not restage groups. Do not perform new extraction unless there is a critical gap that prevents safe finalization.
38391
+
38392
+ Active ERP page:
38393
+ - profile: ${config.profile.label} (${config.profile.id})
38394
+ - scope: ${config.uploadContext.scope || 'not specified'}
38395
+ - category: ${config.uploadContext.category || 'not specified'}
38396
+
38397
+ Finalize rules:
38398
+ - use outcome completed when backend persistence succeeded, no review rows remain, and backend returned no blocking review/conflict rows
38399
+ - backend skipped duplicates are non-blocking if the mapped row was otherwise persisted or intentionally skipped as a duplicate
38400
+ - use outcome review_required when review rows remain or backend returned blocking review/conflict rows
38401
+ - use outcome failed only for unrecoverable execution errors`;
38402
+ };
38252
38403
 
38253
38404
  // User-specific configurations mapping
38254
38405
  const USER_CONFIGS = {
@@ -45085,7 +45236,11 @@ exports.Industries = index;
45085
45236
  exports.UI_FEATURES = UI_FEATURES;
45086
45237
  exports.WATER_PRODUCTS = WATER_PRODUCTS$2;
45087
45238
  exports.addItemForUser = addItemForUser;
45239
+ exports.buildBulkBillAgentFinalizerPrompt = buildBulkBillAgentFinalizerPrompt;
45088
45240
  exports.buildBulkBillAgentPromptConfig = buildBulkBillAgentPromptConfig;
45241
+ exports.buildBulkBillAgentRouterPrompt = buildBulkBillAgentRouterPrompt;
45242
+ exports.buildBulkBillAgentSystemPrompt = buildBulkBillAgentSystemPrompt;
45243
+ exports.buildBulkBillAgentWorkerPrompt = buildBulkBillAgentWorkerPrompt;
45089
45244
  exports.buildUserConfigItemKey = buildUserConfigItemKey;
45090
45245
  exports.calculateCCTSEmission = calculateCCTSEmission;
45091
45246
  exports.calculateIntensityMetrics = calculateIntensityMetrics;