@claritylabs/cl-sdk 3.0.32 → 3.1.0

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
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
33
  ADMITTED_STATUSES: () => ADMITTED_STATUSES,
34
34
  AGENT_TOOLS: () => AGENT_TOOLS,
35
35
  APPLICATION_CLASSIFY_PROMPT: () => APPLICATION_CLASSIFY_PROMPT,
@@ -40,13 +40,21 @@ __export(index_exports, {
40
40
  AgenticExecutionModeSchema: () => AgenticExecutionModeSchema,
41
41
  AnswerParsingResultSchema: () => AnswerParsingResultSchema,
42
42
  ApplicationClassifyResultSchema: () => ApplicationClassifyResultSchema,
43
+ ApplicationContextProposalSchema: () => ApplicationContextProposalSchema,
43
44
  ApplicationEmailReviewSchema: () => ApplicationEmailReviewSchema,
44
45
  ApplicationFieldSchema: () => ApplicationFieldSchema,
46
+ ApplicationPacketAnswerSchema: () => ApplicationPacketAnswerSchema,
47
+ ApplicationPacketSchema: () => ApplicationPacketSchema,
45
48
  ApplicationQualityArtifactSchema: () => ApplicationQualityArtifactSchema,
46
49
  ApplicationQualityIssueSchema: () => ApplicationQualityIssueSchema,
47
50
  ApplicationQualityReportSchema: () => ApplicationQualityReportSchema,
48
51
  ApplicationQualityRoundSchema: () => ApplicationQualityRoundSchema,
52
+ ApplicationQuestionConditionSchema: () => ApplicationQuestionConditionSchema,
53
+ ApplicationQuestionGraphSchema: () => ApplicationQuestionGraphSchema,
54
+ ApplicationQuestionNodeSchema: () => ApplicationQuestionNodeSchema,
55
+ ApplicationRepeatSchema: () => ApplicationRepeatSchema,
49
56
  ApplicationStateSchema: () => ApplicationStateSchema,
57
+ ApplicationTemplateSchema: () => ApplicationTemplateSchema,
50
58
  AttachmentInterpretationSchema: () => AttachmentInterpretationSchema,
51
59
  AuditTypeSchema: () => AuditTypeSchema,
52
60
  AutoFillMatchSchema: () => AutoFillMatchSchema,
@@ -261,9 +269,11 @@ __export(index_exports, {
261
269
  VerifyResultSchema: () => VerifyResultSchema,
262
270
  WatercraftDeclarationsSchema: () => WatercraftDeclarationsSchema,
263
271
  WorkersCompDeclarationsSchema: () => WorkersCompDeclarationsSchema,
272
+ applyApplicationAnswers: () => applyApplicationAnswers,
264
273
  buildAcroFormMappingPrompt: () => buildAcroFormMappingPrompt,
265
274
  buildAgentSystemPrompt: () => buildAgentSystemPrompt,
266
275
  buildAnswerParsingPrompt: () => buildAnswerParsingPrompt,
276
+ buildApplicationPacket: () => buildApplicationPacket,
267
277
  buildAutoFillPrompt: () => buildAutoFillPrompt,
268
278
  buildBatchEmailGenerationPrompt: () => buildBatchEmailGenerationPrompt,
269
279
  buildClassifyMessagePrompt: () => buildClassifyMessagePrompt,
@@ -290,6 +300,7 @@ __export(index_exports, {
290
300
  buildPdfProviderOptions: () => buildPdfProviderOptions,
291
301
  buildQueryClassifyPrompt: () => buildQueryClassifyPrompt,
292
302
  buildQuestionBatchPrompt: () => buildQuestionBatchPrompt,
303
+ buildQuestionGraphFromFields: () => buildQuestionGraphFromFields,
293
304
  buildQuotesPoliciesPrompt: () => buildQuotesPoliciesPrompt,
294
305
  buildReasonPrompt: () => buildReasonPrompt,
295
306
  buildReplyIntentClassificationPrompt: () => buildReplyIntentClassificationPrompt,
@@ -305,6 +316,7 @@ __export(index_exports, {
305
316
  collectPceEvidenceSources: () => collectPceEvidenceSources,
306
317
  compareSourceEvidence: () => compareSourceEvidence,
307
318
  createApplicationPipeline: () => createApplicationPipeline,
319
+ createApplicationRun: () => createApplicationRun,
308
320
  createExtractor: () => createExtractor,
309
321
  createPceAgent: () => createPceAgent,
310
322
  createPipelineContext: () => createPipelineContext,
@@ -312,12 +324,16 @@ __export(index_exports, {
312
324
  evaluateCaseProposals: () => evaluateCaseProposals,
313
325
  evidenceContainsQuote: () => evidenceContainsQuote,
314
326
  extractPageRange: () => extractPageRange,
327
+ extractQuestionGraphFromFields: () => extractQuestionGraphFromFields,
315
328
  fillAcroForm: () => fillAcroForm,
329
+ flattenQuestionGraph: () => flattenQuestionGraph,
316
330
  generateNextMessage: () => generateNextMessage,
317
331
  getAcroFormFields: () => getAcroFormFields,
332
+ getActiveApplicationFields: () => getActiveApplicationFields,
318
333
  getDoclingPageRangeText: () => getDoclingPageRangeText,
319
334
  getExtractor: () => getExtractor,
320
335
  getFileIdentifier: () => getFileIdentifier,
336
+ getNextApplicationQuestions: () => getNextApplicationQuestions,
321
337
  getPdfPageCount: () => getPdfPageCount,
322
338
  getTemplate: () => getTemplate,
323
339
  isDoclingExtractionInput: () => isDoclingExtractionInput,
@@ -325,6 +341,7 @@ __export(index_exports, {
325
341
  mergeOperationalProfile: () => mergeOperationalProfile,
326
342
  mergeQuestionAnswers: () => mergeQuestionAnswers,
327
343
  mergeSourceSpans: () => mergeSourceSpans,
344
+ normalizeApplicationQuestionGraph: () => normalizeApplicationQuestionGraph,
328
345
  normalizeDoclingDocument: () => normalizeDoclingDocument,
329
346
  normalizeDocumentSourceTreePaths: () => normalizeDocumentSourceTreePaths,
330
347
  normalizeForMatch: () => normalizeForMatch,
@@ -334,7 +351,9 @@ __export(index_exports, {
334
351
  pLimit: () => pLimit,
335
352
  pdfInputToBase64: () => pdfInputToBase64,
336
353
  pdfInputToBytes: () => pdfInputToBytes,
354
+ planNextApplicationQuestions: () => planNextApplicationQuestions,
337
355
  processReply: () => processReply,
356
+ proposeContextWrites: () => proposeContextWrites,
338
357
  resolveModelBudget: () => resolveModelBudget,
339
358
  safeGenerateObject: () => safeGenerateObject,
340
359
  sanitizeNulls: () => sanitizeNulls,
@@ -347,12 +366,13 @@ __export(index_exports, {
347
366
  stableStringify: () => stableStringify,
348
367
  stripFences: () => stripFences,
349
368
  toStrictSchema: () => toStrictSchema,
369
+ validateApplicationPacket: () => validateApplicationPacket,
350
370
  validateEvidence: () => validateEvidence,
351
371
  validatePceItems: () => validatePceItems,
352
372
  validateQuotedEvidence: () => validateQuotedEvidence,
353
373
  withRetry: () => withRetry
354
374
  });
355
- module.exports = __toCommonJS(index_exports);
375
+ module.exports = __toCommonJS(src_exports);
356
376
 
357
377
  // src/core/retry.ts
358
378
  var MAX_RETRIES = 5;
@@ -3337,6 +3357,14 @@ function valueFromNode(node, value, confidence = "medium") {
3337
3357
  sourceSpanIds: node.sourceSpanIds
3338
3358
  };
3339
3359
  }
3360
+ function valueFromNodes(nodes, value, confidence = "medium", normalizedValue) {
3361
+ return {
3362
+ value,
3363
+ ...normalizedValue ? { normalizedValue } : {},
3364
+ confidence,
3365
+ ...sourceIds(nodes)
3366
+ };
3367
+ }
3340
3368
  function firstMatch(nodes, patterns) {
3341
3369
  for (const node of nodes) {
3342
3370
  const text = nodeText(node);
@@ -3413,8 +3441,65 @@ function cleanNamedInsured(value) {
3413
3441
  }
3414
3442
  return clean;
3415
3443
  }
3444
+ var PARTY_LABEL_PATTERNS = {
3445
+ namedInsured: /^(?:item\s*\d+[.)]?\s*)?(?:named insured(?:\s+and\s+address)?|insured name)$/i,
3446
+ insurer: /^(?:carrier|insurer|security)$/i,
3447
+ broker: /^(?:broker(?:\s+of\s+record)?|producer|agent)$/i
3448
+ };
3449
+ function partyLabelKind(value) {
3450
+ const clean = cleanValue(value.replace(/^\s*column\s+\d+\s*:\s*/i, ""));
3451
+ if (!clean) return void 0;
3452
+ if (PARTY_LABEL_PATTERNS.namedInsured.test(clean)) return "namedInsured";
3453
+ if (PARTY_LABEL_PATTERNS.insurer.test(clean)) return "insurer";
3454
+ if (PARTY_LABEL_PATTERNS.broker.test(clean)) return "broker";
3455
+ return void 0;
3456
+ }
3457
+ function isRejectedPartyValue(value) {
3458
+ const clean = normalizeWhitespace3(value);
3459
+ return /^(?:and address|of record|insurer|carrier|security|broker|producer|agent|the|a|an|is|are|was|were|agrees?|means?|includes?|shall|will)\b/i.test(clean);
3460
+ }
3461
+ function identityWithoutAddress(value) {
3462
+ const clean = cleanValue(value.replace(/\b(?:phone|tel|telephone|email|e-mail)\b.*$/i, "").replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b.*$/i, ""));
3463
+ if (!clean) return void 0;
3464
+ const beforeStreet = clean.match(/^(.+?)\s+\d{1,6}\s+[A-Za-z0-9.'-]+(?:\s+[A-Za-z0-9.'-]+){0,5}\s+(?:street|st\.?|avenue|ave\.?|road|rd\.?|drive|dr\.?|lane|ln\.?|boulevard|blvd\.?|suite|ste\.?|floor|fl\.?|way|court|ct\.?)\b/i)?.[1];
3465
+ const beforeCityState = clean.match(/^(.+?)\s+[A-Z][A-Za-z.'-]+(?:\s+[A-Z][A-Za-z.'-]+)*,\s*[A-Z]{2}\s+\d{5}(?:-\d{4})?\b/)?.[1];
3466
+ return cleanValue(beforeStreet ?? beforeCityState ?? clean);
3467
+ }
3468
+ function cleanPartyIdentity(value, clean) {
3469
+ const raw = cleanValue(value);
3470
+ if (!raw || isRejectedPartyValue(raw)) return void 0;
3471
+ const identity = identityWithoutAddress(raw);
3472
+ const cleaned = identity ? clean(identity) : void 0;
3473
+ if (!cleaned || isRejectedPartyValue(cleaned)) return void 0;
3474
+ return {
3475
+ value: cleaned,
3476
+ ...cleaned !== raw ? { normalizedValue: cleaned } : {}
3477
+ };
3478
+ }
3479
+ function partyFromTableRows(nodes, wanted, clean) {
3480
+ const children = childMap(nodes);
3481
+ for (const row of compactFactNodes(nodes).filter((node) => node.kind === "table_row")) {
3482
+ const cells = cellRows(row, children);
3483
+ for (const [index, cell] of cells.entries()) {
3484
+ const labelKind = partyLabelKind(cell.value) ?? partyLabelKind(cell.label);
3485
+ if (labelKind !== wanted) continue;
3486
+ const valueCell = cells.slice(index + 1).find((candidate) => !partyLabelKind(candidate.value) && !partyLabelKind(candidate.label));
3487
+ if (!valueCell) continue;
3488
+ const cleaned = cleanPartyIdentity(valueCell.value, clean);
3489
+ if (cleaned) return valueFromNodes([row, valueCell.node], cleaned.value, "high", cleaned.normalizedValue);
3490
+ }
3491
+ const parts = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row)).split(/\s+\|\s+|\t/).map(cleanValue).filter((part) => Boolean(part));
3492
+ for (const [index, part] of parts.entries()) {
3493
+ const labelKind = partyLabelKind(part);
3494
+ if (labelKind !== wanted) continue;
3495
+ const cleaned = cleanPartyIdentity(parts[index + 1] ?? "", clean);
3496
+ if (cleaned) return valueFromNodes([row], cleaned.value, "high", cleaned.normalizedValue);
3497
+ }
3498
+ }
3499
+ return void 0;
3500
+ }
3416
3501
  function namedInsuredFromNodes(nodes) {
3417
- return firstCleanMatch(nodes, [
3502
+ return partyFromTableRows(nodes, "namedInsured", cleanNamedInsured) ?? firstCleanMatch(nodes, [
3418
3503
  /\b(?:named insured|insured name)\s*:?\s*(.+?)(?=\s+(?:insurance amount|benefit amount|policy number|policy date|owner|beneficiary|premium|coverage|risk classification|date this)\b|[|;\n]|$)/i,
3419
3504
  /\b(?:insured persons?|insured person)\s*:\s*(.+?)(?=\s+(?:insurance amount|benefit amount|policy number|policy date|owner|beneficiary|premium|coverage|risk classification|date this)\b|[|;\n]|$)/i,
3420
3505
  /\b(?:applicant|policyholder)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i
@@ -3423,12 +3508,19 @@ function namedInsuredFromNodes(nodes) {
3423
3508
  function cleanInsurer(value) {
3424
3509
  const clean = cleanValue(value);
3425
3510
  if (!clean || clean.length > 140) return void 0;
3426
- if (/^(mean|means|we|us|our)\b/i.test(clean)) return void 0;
3511
+ if (/^(mean|means|we|us|our|the|a|an|agrees?|shall|will)\b/i.test(clean)) return void 0;
3427
3512
  if (/\b(table of contents|policy wording|provided solely|convenience)\b/i.test(clean)) return void 0;
3428
3513
  const known = clean.match(/\b(Sun Life Assurance Company of Canada|Manulife|The Manufacturers Life Insurance Company)\b/i)?.[1];
3429
3514
  return known ?? clean;
3430
3515
  }
3431
3516
  function insurerFromNodes(nodes) {
3517
+ const tableValue = partyFromTableRows(nodes, "insurer", cleanInsurer);
3518
+ if (tableValue) return tableValue;
3519
+ for (const node of compactFactNodes(nodes)) {
3520
+ const text = nodeText(node);
3521
+ const value = cleanInsurer(text.match(/\b([A-Z][A-Za-z&.,' -]{2,120}?(?:Insurance|Assurance|Indemnity|Casualty|Underwriting|Mutual|Risk|Reinsurance)\s+Company(?:\s+of\s+[A-Z][A-Za-z .'-]+)?)\s*\(\s*the\s+["']?Insurer["']?\s*\)/i)?.[1] ?? "");
3522
+ if (value) return valueFromNode(node, value, "high");
3523
+ }
3432
3524
  return firstCleanMatch(nodes, [
3433
3525
  /\bunderwritten by\s+([^|;\n.]{3,160})/i,
3434
3526
  /\b(?:insurer|carrier|company|security)\s*:?\s*([^|;\n]{3,120})/i,
@@ -3474,6 +3566,19 @@ function coverageNameFromRow(text) {
3474
3566
  );
3475
3567
  return cleanCoverageLabel(first);
3476
3568
  }
3569
+ function isDeclarationLimitLabel(value) {
3570
+ const label = normalizeLabel(value);
3571
+ return /\bitem\s*\d+[.)]?\s*limits?\s+of\s+liability\b/.test(label) || /^limits?\s+of\s+liability$/.test(label) || /^policy\s+limits?$/.test(label);
3572
+ }
3573
+ function declarationCoverageNameFromRow(row, children) {
3574
+ const cells = cellRows(row, children);
3575
+ const candidates = [
3576
+ row.title,
3577
+ ...cells.flatMap((cell) => [cell.label, cell.value])
3578
+ ];
3579
+ if (!candidates.some(isDeclarationLimitLabel)) return void 0;
3580
+ return candidates.some((candidate) => /\blimits?\s+of\s+liability\b/i.test(candidate ?? "")) ? "Limits of Liability" : "Policy Limits";
3581
+ }
3477
3582
  function limitFromText(text) {
3478
3583
  return moneyValue(
3479
3584
  text.match(/\b(?:limit|liability|aggregate|occurrence|claim)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?|\$?\d[\d,]*\s*(?:each|per|aggregate)[^|;]*)/i)?.[1] ?? text.match(/(\$\s?\d[\d,]*(?:\.\d{2})?)(?=.*\b(limit|aggregate|occurrence|claim|liability)\b)/i)?.[1]
@@ -3493,7 +3598,12 @@ function premiumFromNodes(nodes) {
3493
3598
  return void 0;
3494
3599
  }
3495
3600
  function moneyAmount(value) {
3496
- const match = value?.match(/\$?\s*([0-9][0-9,]*(?:\.\d+)?)/);
3601
+ const clean = cleanValue(value);
3602
+ if (!clean) return void 0;
3603
+ const currency = clean.match(/\$\s*([0-9][0-9,]*(?:\.\d+)?)/);
3604
+ const percent = clean.match(/\b([0-9][0-9,]*(?:\.\d+)?)\s*%/);
3605
+ const explicitNumeric = !/\bitem\s*\d+\b/i.test(clean) && /\b(?:limit|aggregate|claim|occurrence|loss|retention|deductible|sir|premium|amount)\b/i.test(clean) ? clean.match(/\b([0-9][0-9,]*(?:\.\d+)?)\b/) : void 0;
3606
+ const match = currency ?? percent ?? explicitNumeric;
3497
3607
  if (!match) return void 0;
3498
3608
  const amount = Number(match[1].replace(/,/g, ""));
3499
3609
  return Number.isFinite(amount) ? amount : void 0;
@@ -3539,6 +3649,10 @@ function isValueCell(label, value) {
3539
3649
  }
3540
3650
  return /\b(limit|aggregate|retention|deductible|sir|retroactive|premium|amount)\b/.test(normalizedLabel) || moneyAmount(value) !== void 0 || /\b(full prior acts|none|included|not included|as stated)\b/.test(normalizedValue);
3541
3651
  }
3652
+ function isCoverageTermLabel(value) {
3653
+ const label = normalizeLabel(value);
3654
+ return /\b(limit|aggregate|retention|deductible|sir|retroactive|premium|amount|sub[-\s]?limit)\b/.test(label);
3655
+ }
3542
3656
  function isNameCell(label, value) {
3543
3657
  const normalizedLabel = normalizeLabel(label);
3544
3658
  const normalizedValue = normalizeLabel(value);
@@ -3640,6 +3754,16 @@ function termFromCell(params) {
3640
3754
  function termsFromRow(row, children) {
3641
3755
  const cells = cellRows(row, children);
3642
3756
  if (cells.length > 0) {
3757
+ const pairedTerms = [];
3758
+ for (const [index, cell] of cells.entries()) {
3759
+ const next = cells[index + 1];
3760
+ if (!next) continue;
3761
+ if (!isCoverageTermLabel(cell.value)) continue;
3762
+ if (isCoverageTermLabel(next.value) && moneyAmount(next.value) === void 0) continue;
3763
+ const term = termFromCell({ row, cell: next.node, label: cell.value, value: next.value });
3764
+ if (term) pairedTerms.push(term);
3765
+ }
3766
+ if (pairedTerms.length > 0) return pairedTerms;
3643
3767
  return cells.filter((cell) => isValueCell(cell.label, cell.value)).map((cell) => termFromCell({ row, cell: cell.node, label: cell.label, value: cell.value })).filter((term) => Boolean(term));
3644
3768
  }
3645
3769
  const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
@@ -3666,6 +3790,8 @@ function termsFromRow(row, children) {
3666
3790
  return terms;
3667
3791
  }
3668
3792
  function nameFromRow(row, children) {
3793
+ const declarationName = declarationCoverageNameFromRow(row, children);
3794
+ if (declarationName) return declarationName;
3669
3795
  const cells = cellRows(row, children);
3670
3796
  const named = cells.find((cell) => isNameCell(cell.label, cell.value));
3671
3797
  if (named) return cleanValue(named.value);
@@ -3843,7 +3969,7 @@ function buildParties(profile) {
3843
3969
  if (profile.namedInsured) {
3844
3970
  parties.push({
3845
3971
  role: "named_insured",
3846
- name: profile.namedInsured.value,
3972
+ name: profile.namedInsured.normalizedValue ?? profile.namedInsured.value,
3847
3973
  sourceNodeIds: profile.namedInsured.sourceNodeIds,
3848
3974
  sourceSpanIds: profile.namedInsured.sourceSpanIds
3849
3975
  });
@@ -3851,7 +3977,7 @@ function buildParties(profile) {
3851
3977
  if (profile.insurer) {
3852
3978
  parties.push({
3853
3979
  role: "insurer",
3854
- name: profile.insurer.value,
3980
+ name: profile.insurer.normalizedValue ?? profile.insurer.value,
3855
3981
  sourceNodeIds: profile.insurer.sourceNodeIds,
3856
3982
  sourceSpanIds: profile.insurer.sourceSpanIds
3857
3983
  });
@@ -3859,7 +3985,7 @@ function buildParties(profile) {
3859
3985
  if (profile.broker) {
3860
3986
  parties.push({
3861
3987
  role: "broker",
3862
- name: profile.broker.value,
3988
+ name: profile.broker.normalizedValue ?? profile.broker.value,
3863
3989
  sourceNodeIds: profile.broker.sourceNodeIds,
3864
3990
  sourceSpanIds: profile.broker.sourceSpanIds
3865
3991
  });
@@ -11296,9 +11422,19 @@ function sourceTreeToOutline(sourceTree) {
11296
11422
  });
11297
11423
  return (byParent.get(root?.id) ?? []).map(visit);
11298
11424
  }
11425
+ var NORMALIZED_COMPATIBILITY_FIELDS = /* @__PURE__ */ new Set([
11426
+ "policyNumber",
11427
+ "namedInsured",
11428
+ "insurer",
11429
+ "broker"
11430
+ ]);
11299
11431
  function valueOf(profile, key) {
11300
11432
  const value = profile[key];
11301
- return value && typeof value === "object" && !Array.isArray(value) && "value" in value ? String(value.value) : void 0;
11433
+ if (!value || typeof value !== "object" || Array.isArray(value) || !("value" in value)) return void 0;
11434
+ if (NORMALIZED_COMPATIBILITY_FIELDS.has(key) && "normalizedValue" in value && typeof value.normalizedValue === "string" && value.normalizedValue.trim()) {
11435
+ return value.normalizedValue;
11436
+ }
11437
+ return String(value.value);
11302
11438
  }
11303
11439
  function materializeDocument(params) {
11304
11440
  const profile = params.operationalProfile;
@@ -12896,6 +13032,55 @@ var ApplicationFieldSchema = import_zod42.z.object({
12896
13032
  acroFormName: import_zod42.z.string().optional().describe("Native PDF AcroForm field name when available"),
12897
13033
  validationStatus: import_zod42.z.enum(["valid", "needs_review", "unsupported", "missing"]).optional()
12898
13034
  });
13035
+ var ApplicationQuestionConditionSchema = import_zod42.z.object({
13036
+ dependsOn: import_zod42.z.string(),
13037
+ operator: import_zod42.z.enum(["equals", "not_equals", "in", "not_in", "exists"]).optional(),
13038
+ value: import_zod42.z.string().optional(),
13039
+ whenValue: import_zod42.z.string().optional(),
13040
+ values: import_zod42.z.array(import_zod42.z.string()).optional()
13041
+ });
13042
+ var ApplicationRepeatSchema = import_zod42.z.object({
13043
+ min: import_zod42.z.number().int().nonnegative().optional(),
13044
+ max: import_zod42.z.number().int().positive().optional(),
13045
+ label: import_zod42.z.string().optional()
13046
+ });
13047
+ var ApplicationQuestionNodeSchema = import_zod42.z.lazy(
13048
+ () => import_zod42.z.object({
13049
+ id: import_zod42.z.string(),
13050
+ nodeType: import_zod42.z.enum(["group", "question", "repeat_group", "table"]),
13051
+ fieldId: import_zod42.z.string().optional(),
13052
+ fieldPath: import_zod42.z.string().optional(),
13053
+ parentId: import_zod42.z.string().optional(),
13054
+ order: import_zod42.z.number().int().nonnegative().optional(),
13055
+ label: import_zod42.z.string(),
13056
+ section: import_zod42.z.string().optional(),
13057
+ fieldType: FieldTypeSchema.optional(),
13058
+ required: import_zod42.z.boolean().optional(),
13059
+ prompt: import_zod42.z.string().optional(),
13060
+ options: import_zod42.z.array(import_zod42.z.string()).optional(),
13061
+ columns: import_zod42.z.array(import_zod42.z.string()).optional(),
13062
+ condition: ApplicationQuestionConditionSchema.optional(),
13063
+ repeat: ApplicationRepeatSchema.optional(),
13064
+ children: import_zod42.z.array(ApplicationQuestionNodeSchema).optional()
13065
+ })
13066
+ );
13067
+ var ApplicationQuestionGraphSchema = import_zod42.z.object({
13068
+ id: import_zod42.z.string(),
13069
+ version: import_zod42.z.string(),
13070
+ title: import_zod42.z.string().optional(),
13071
+ applicationType: import_zod42.z.string().nullable().optional(),
13072
+ source: import_zod42.z.enum(["pdf", "manual", "imported", "generated"]).default("generated"),
13073
+ rootNodeIds: import_zod42.z.array(import_zod42.z.string()).optional(),
13074
+ nodes: import_zod42.z.array(ApplicationQuestionNodeSchema)
13075
+ });
13076
+ var ApplicationTemplateSchema = import_zod42.z.object({
13077
+ id: import_zod42.z.string(),
13078
+ version: import_zod42.z.string(),
13079
+ title: import_zod42.z.string(),
13080
+ applicationType: import_zod42.z.string().nullable().optional(),
13081
+ questionGraph: ApplicationQuestionGraphSchema,
13082
+ fields: import_zod42.z.array(ApplicationFieldSchema).optional()
13083
+ });
12899
13084
  var ApplicationClassifyResultSchema = import_zod42.z.object({
12900
13085
  isApplication: import_zod42.z.boolean(),
12901
13086
  confidence: import_zod42.z.number().min(0).max(1),
@@ -12993,16 +13178,67 @@ var ApplicationQualityReportSchema = import_zod42.z.object({
12993
13178
  emailReview: ApplicationEmailReviewSchema.optional(),
12994
13179
  qualityGateStatus: QualityGateStatusSchema
12995
13180
  });
13181
+ var ApplicationContextProposalSchema = import_zod42.z.object({
13182
+ id: import_zod42.z.string(),
13183
+ fieldId: import_zod42.z.string().optional(),
13184
+ key: import_zod42.z.string(),
13185
+ value: import_zod42.z.string(),
13186
+ category: import_zod42.z.string(),
13187
+ source: import_zod42.z.enum(["application", "user", "lookup", "policy", "email", "chat", "imessage", "mcp"]),
13188
+ confidence: import_zod42.z.enum(["confirmed", "high", "medium", "low"]),
13189
+ sourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional(),
13190
+ userSourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional()
13191
+ });
13192
+ var ApplicationPacketAnswerSchema = import_zod42.z.object({
13193
+ fieldId: import_zod42.z.string(),
13194
+ label: import_zod42.z.string(),
13195
+ section: import_zod42.z.string(),
13196
+ value: import_zod42.z.string(),
13197
+ source: import_zod42.z.string(),
13198
+ confidence: import_zod42.z.enum(["confirmed", "high", "medium", "low"]).optional(),
13199
+ sourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional(),
13200
+ userSourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional()
13201
+ });
13202
+ var ApplicationPacketSchema = import_zod42.z.object({
13203
+ id: import_zod42.z.string(),
13204
+ applicationId: import_zod42.z.string(),
13205
+ title: import_zod42.z.string(),
13206
+ status: import_zod42.z.enum(["draft", "broker_ready", "submitted"]),
13207
+ answers: import_zod42.z.array(ApplicationPacketAnswerSchema),
13208
+ missingFieldIds: import_zod42.z.array(import_zod42.z.string()),
13209
+ qualityReport: ApplicationQualityReportSchema,
13210
+ submissionNotes: import_zod42.z.string().optional(),
13211
+ createdAt: import_zod42.z.number()
13212
+ });
12996
13213
  var ApplicationStateSchema = import_zod42.z.object({
12997
13214
  id: import_zod42.z.string(),
12998
13215
  pdfBase64: import_zod42.z.string().optional().describe("Original PDF, omitted after extraction"),
13216
+ templateId: import_zod42.z.string().optional(),
13217
+ templateVersion: import_zod42.z.string().optional(),
13218
+ templateSnapshot: ApplicationTemplateSchema.optional(),
12999
13219
  title: import_zod42.z.string().optional(),
13000
13220
  applicationType: import_zod42.z.string().nullable().optional(),
13221
+ questionGraph: ApplicationQuestionGraphSchema.optional(),
13001
13222
  fields: import_zod42.z.array(ApplicationFieldSchema),
13002
13223
  batches: import_zod42.z.array(import_zod42.z.array(import_zod42.z.string())).optional(),
13003
13224
  currentBatchIndex: import_zod42.z.number().default(0),
13225
+ contextProposals: import_zod42.z.array(ApplicationContextProposalSchema).optional(),
13226
+ packet: ApplicationPacketSchema.optional(),
13004
13227
  qualityReport: ApplicationQualityReportSchema.optional(),
13005
- status: import_zod42.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
13228
+ status: import_zod42.z.enum([
13229
+ "classifying",
13230
+ "extracting",
13231
+ "auto_filling",
13232
+ "batching",
13233
+ "collecting",
13234
+ "confirming",
13235
+ "mapping",
13236
+ "broker_review",
13237
+ "packet_ready",
13238
+ "submitted",
13239
+ "cancelled",
13240
+ "complete"
13241
+ ]),
13006
13242
  createdAt: import_zod42.z.number(),
13007
13243
  updatedAt: import_zod42.z.number()
13008
13244
  });
@@ -13701,7 +13937,7 @@ function planReplyActions(input) {
13701
13937
  parseAnswers: input.intent.hasAnswers && hasCurrentFields,
13702
13938
  runLookup: hasLookupRequests && input.hasDocumentStore,
13703
13939
  answerQuestion: Boolean(input.intent.questionText) && (input.intent.primaryIntent === "question" || input.intent.primaryIntent === "mixed"),
13704
- advanceBatch: hasCurrentFields && input.currentBatchFields.every((field) => !isUnfilled(field)),
13940
+ advanceBatch: hasCurrentFields && input.currentBatchFields.every((field) => !isUnfilled(field)) || !hasCurrentFields && nextBatchNeedsAnswers,
13705
13941
  generateNextEmail: nextBatchNeedsAnswers
13706
13942
  };
13707
13943
  }
@@ -13740,12 +13976,287 @@ function isHighValueLookupField(field) {
13740
13976
  ].some((term) => text.includes(term));
13741
13977
  }
13742
13978
 
13979
+ // src/application/question-graph.ts
13980
+ function buildQuestionGraphFromFields(fields, options) {
13981
+ const sectionNodes = /* @__PURE__ */ new Map();
13982
+ const nodes = [];
13983
+ for (const [index, field] of fields.entries()) {
13984
+ const sectionId = stableNodeId(["section", field.section]);
13985
+ let sectionNode = sectionNodes.get(sectionId);
13986
+ if (!sectionNode) {
13987
+ sectionNode = {
13988
+ id: sectionId,
13989
+ nodeType: "group",
13990
+ label: field.section,
13991
+ order: sectionNodes.size,
13992
+ children: []
13993
+ };
13994
+ sectionNodes.set(sectionId, sectionNode);
13995
+ nodes.push(sectionNode);
13996
+ }
13997
+ const child = {
13998
+ id: field.fieldAnchorId ?? stableNodeId(["field", field.section, field.id || field.label]),
13999
+ nodeType: field.fieldType === "table" ? "table" : "question",
14000
+ fieldId: field.id,
14001
+ fieldPath: `${field.section}.${field.id}`,
14002
+ parentId: sectionId,
14003
+ order: index,
14004
+ label: field.label,
14005
+ section: field.section,
14006
+ fieldType: field.fieldType,
14007
+ required: field.required,
14008
+ options: field.options,
14009
+ columns: field.columns,
14010
+ condition: field.condition ? {
14011
+ dependsOn: field.condition.dependsOn,
14012
+ operator: "equals",
14013
+ value: field.condition.whenValue,
14014
+ whenValue: field.condition.whenValue
14015
+ } : void 0
14016
+ };
14017
+ sectionNode.children = [...sectionNode.children ?? [], child];
14018
+ }
14019
+ return normalizeApplicationQuestionGraph({
14020
+ id: options.id,
14021
+ version: options.version ?? "v1",
14022
+ title: options.title,
14023
+ applicationType: options.applicationType,
14024
+ source: options.source ?? "generated",
14025
+ rootNodeIds: nodes.map((node) => node.id),
14026
+ nodes
14027
+ });
14028
+ }
14029
+ function normalizeApplicationQuestionGraph(graph) {
14030
+ const normalizedNodes = graph.nodes.map((node, index) => normalizeNode(node, void 0, index)).sort(compareNodes);
14031
+ return {
14032
+ ...graph,
14033
+ rootNodeIds: graph.rootNodeIds?.length ? graph.rootNodeIds : normalizedNodes.map((node) => node.id),
14034
+ nodes: normalizedNodes
14035
+ };
14036
+ }
14037
+ function flattenQuestionGraph(graph) {
14038
+ const fields = [];
14039
+ for (const node of graph.nodes.sort(compareNodes)) {
14040
+ collectFields(node, fields);
14041
+ }
14042
+ return fields;
14043
+ }
14044
+ function getActiveApplicationFields(state) {
14045
+ const valueByFieldId = new Map(
14046
+ state.fields.filter((field) => field.value !== void 0 && field.value.trim() !== "").map((field) => [field.id, field.value ?? ""])
14047
+ );
14048
+ const graphConditions = /* @__PURE__ */ new Map();
14049
+ for (const node of state.questionGraph?.nodes ?? []) {
14050
+ collectNodeConditions(node, graphConditions);
14051
+ }
14052
+ return state.fields.filter((field) => {
14053
+ const graphCondition = graphConditions.get(field.id);
14054
+ return isConditionSatisfied(field.condition, valueByFieldId) && isQuestionConditionSatisfied(graphCondition, valueByFieldId);
14055
+ });
14056
+ }
14057
+ function getNextApplicationQuestions(state, limit = 8) {
14058
+ const activeUnfilled = getActiveApplicationFields(state).filter((field) => !field.value);
14059
+ if (activeUnfilled.length === 0) return [];
14060
+ const currentBatchIds = state.batches?.[state.currentBatchIndex] ?? [];
14061
+ const currentBatchFields = activeUnfilled.filter((field) => currentBatchIds.includes(field.id));
14062
+ return (currentBatchFields.length > 0 ? currentBatchFields : activeUnfilled).slice(0, limit);
14063
+ }
14064
+ function normalizeNode(node, parentId, index) {
14065
+ const children = node.children?.map((child, childIndex) => normalizeNode(child, node.id, childIndex));
14066
+ return {
14067
+ ...node,
14068
+ parentId: node.parentId ?? parentId,
14069
+ order: node.order ?? index,
14070
+ fieldPath: node.fieldPath ?? (node.fieldId ? [node.section, node.fieldId].filter(Boolean).join(".") : void 0),
14071
+ children
14072
+ };
14073
+ }
14074
+ function collectFields(node, fields) {
14075
+ if ((node.nodeType === "question" || node.nodeType === "table") && node.fieldId) {
14076
+ fields.push({
14077
+ id: node.fieldId,
14078
+ label: node.label,
14079
+ section: node.section ?? "General",
14080
+ fieldType: node.fieldType ?? (node.nodeType === "table" ? "table" : "text"),
14081
+ required: node.required ?? false,
14082
+ options: node.options,
14083
+ columns: node.columns,
14084
+ condition: node.condition ? {
14085
+ dependsOn: node.condition.dependsOn,
14086
+ whenValue: node.condition.value ?? node.condition.whenValue ?? ""
14087
+ } : void 0,
14088
+ fieldAnchorId: node.id
14089
+ });
14090
+ }
14091
+ for (const child of node.children ?? []) {
14092
+ collectFields(child, fields);
14093
+ }
14094
+ }
14095
+ function collectNodeConditions(node, conditions) {
14096
+ if (node.fieldId && node.condition) {
14097
+ conditions.set(node.fieldId, node.condition);
14098
+ }
14099
+ for (const child of node.children ?? []) {
14100
+ collectNodeConditions(child, conditions);
14101
+ }
14102
+ }
14103
+ function isConditionSatisfied(condition, valueByFieldId) {
14104
+ if (!condition) return true;
14105
+ const current = valueByFieldId.get(condition.dependsOn);
14106
+ return normalizeValue(current) === normalizeValue(condition.whenValue);
14107
+ }
14108
+ function isQuestionConditionSatisfied(condition, valueByFieldId) {
14109
+ if (!condition) return true;
14110
+ const current = valueByFieldId.get(condition.dependsOn);
14111
+ const expected = condition.value ?? condition.whenValue;
14112
+ const values = condition.values ?? (expected !== void 0 ? [expected] : []);
14113
+ switch (condition.operator) {
14114
+ case "exists":
14115
+ return current !== void 0 && current.trim() !== "";
14116
+ case "not_equals":
14117
+ return normalizeValue(current) !== normalizeValue(expected);
14118
+ case "in":
14119
+ return values.map(normalizeValue).includes(normalizeValue(current));
14120
+ case "not_in":
14121
+ return !values.map(normalizeValue).includes(normalizeValue(current));
14122
+ case "equals":
14123
+ default:
14124
+ return normalizeValue(current) === normalizeValue(expected);
14125
+ }
14126
+ }
14127
+ function compareNodes(a, b) {
14128
+ return (a.order ?? 0) - (b.order ?? 0) || a.id.localeCompare(b.id);
14129
+ }
14130
+ function normalizeValue(value) {
14131
+ return (value ?? "").trim().toLowerCase();
14132
+ }
14133
+ function stableNodeId(parts) {
14134
+ return parts.join(":").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "node";
14135
+ }
14136
+
14137
+ // src/application/intake.ts
14138
+ function extractQuestionGraphFromFields(fields, options) {
14139
+ return buildQuestionGraphFromFields(fields, options);
14140
+ }
14141
+ function createApplicationRun(params) {
14142
+ const now = params.now ?? Date.now();
14143
+ const graph = normalizeApplicationQuestionGraph(params.template.questionGraph);
14144
+ const fields = params.template.fields?.length ? params.template.fields : flattenQuestionGraph(graph);
14145
+ return {
14146
+ id: params.applicationId,
14147
+ templateId: params.template.id,
14148
+ templateVersion: params.template.version,
14149
+ templateSnapshot: params.template,
14150
+ title: params.template.title,
14151
+ applicationType: params.template.applicationType,
14152
+ questionGraph: graph,
14153
+ fields,
14154
+ currentBatchIndex: 0,
14155
+ status: "collecting",
14156
+ createdAt: now,
14157
+ updatedAt: now
14158
+ };
14159
+ }
14160
+ function planNextApplicationQuestions(state, limit) {
14161
+ const fields = getNextApplicationQuestions(state, limit);
14162
+ return {
14163
+ status: fields.length === 0 ? "complete" : "needs_answers",
14164
+ fieldIds: fields.map((field) => field.id),
14165
+ fields
14166
+ };
14167
+ }
14168
+ function applyApplicationAnswers(state, answers, now = Date.now()) {
14169
+ const answerByFieldId = new Map(answers.map((answer) => [answer.fieldId, answer]));
14170
+ const fields = state.fields.map((field) => {
14171
+ const answer = answerByFieldId.get(field.id);
14172
+ if (!answer) return field;
14173
+ return {
14174
+ ...field,
14175
+ value: answer.value,
14176
+ source: answer.source ?? "user",
14177
+ confidence: answer.confidence ?? "confirmed",
14178
+ sourceSpanIds: answer.sourceSpanIds ?? field.sourceSpanIds,
14179
+ userSourceSpanIds: answer.userSourceSpanIds ?? field.userSourceSpanIds,
14180
+ validationStatus: "valid"
14181
+ };
14182
+ });
14183
+ const nextState = {
14184
+ ...state,
14185
+ fields,
14186
+ updatedAt: now
14187
+ };
14188
+ const nextQuestions = planNextApplicationQuestions(nextState);
14189
+ return {
14190
+ ...nextState,
14191
+ status: nextQuestions.status === "complete" ? "confirming" : nextState.status,
14192
+ qualityReport: buildApplicationQualityReport(nextState)
14193
+ };
14194
+ }
14195
+ function proposeContextWrites(state) {
14196
+ return getActiveApplicationFields(state).filter((field) => field.value && field.confidence && field.confidence !== "low").map((field) => ({
14197
+ id: `${state.id}:${field.id}:context`,
14198
+ fieldId: field.id,
14199
+ key: stableContextKey(field),
14200
+ value: field.value ?? "",
14201
+ category: field.section,
14202
+ source: field.source?.startsWith("lookup:") ? "lookup" : "application",
14203
+ confidence: field.confidence ?? "medium",
14204
+ sourceSpanIds: field.sourceSpanIds,
14205
+ userSourceSpanIds: field.userSourceSpanIds
14206
+ }));
14207
+ }
14208
+ function buildApplicationPacket(state, options = {}) {
14209
+ const qualityReport = buildApplicationQualityReport(state);
14210
+ const activeFields = getActiveApplicationFields(state);
14211
+ const answers = activeFields.filter((field) => field.value).map((field) => ({
14212
+ fieldId: field.id,
14213
+ label: field.label,
14214
+ section: field.section,
14215
+ value: field.value ?? "",
14216
+ source: field.source ?? "unknown",
14217
+ confidence: field.confidence,
14218
+ sourceSpanIds: field.sourceSpanIds,
14219
+ userSourceSpanIds: field.userSourceSpanIds
14220
+ }));
14221
+ const missingFieldIds = activeFields.filter((field) => field.required && !field.value).map((field) => field.id);
14222
+ return {
14223
+ id: `${state.id}:packet`,
14224
+ applicationId: state.id,
14225
+ title: state.title ?? state.applicationType ?? "Insurance Application",
14226
+ status: qualityReport.qualityGateStatus === "failed" || missingFieldIds.length > 0 ? "draft" : "broker_ready",
14227
+ answers,
14228
+ missingFieldIds,
14229
+ qualityReport,
14230
+ submissionNotes: options.submissionNotes,
14231
+ createdAt: options.now ?? Date.now()
14232
+ };
14233
+ }
14234
+ function validateApplicationPacket(packet) {
14235
+ const issues = [...packet.qualityReport.issues];
14236
+ if (packet.missingFieldIds.length > 0) {
14237
+ issues.push({
14238
+ code: "packet_missing_required_answers",
14239
+ severity: "blocking",
14240
+ message: "Packet still has required unanswered application fields."
14241
+ });
14242
+ }
14243
+ return {
14244
+ ...packet.qualityReport,
14245
+ issues,
14246
+ qualityGateStatus: issues.some((issue) => issue.severity === "blocking") ? "failed" : packet.qualityReport.qualityGateStatus
14247
+ };
14248
+ }
14249
+ function stableContextKey(field) {
14250
+ return `${field.section}.${field.label}`.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
14251
+ }
14252
+
13743
14253
  // src/application/coordinator.ts
13744
14254
  function createApplicationPipeline(config) {
13745
14255
  const {
13746
14256
  generateText,
13747
14257
  generateObject,
13748
14258
  applicationStore,
14259
+ templateStore,
13749
14260
  documentStore,
13750
14261
  memoryStore,
13751
14262
  backfillProvider,
@@ -13782,11 +14293,18 @@ function createApplicationPipeline(config) {
13782
14293
  const applicationProviderOptions = input.sourceSpans?.length ? { ...providerOptions, sourceSpans: input.sourceSpans } : providerOptions;
13783
14294
  const id = input.applicationId ?? `app-${Date.now()}`;
13784
14295
  const now = Date.now();
14296
+ if (input.template) {
14297
+ await templateStore?.saveTemplate(input.template);
14298
+ }
13785
14299
  let state = {
13786
14300
  id,
14301
+ templateId: input.template?.id,
14302
+ templateVersion: input.template?.version,
14303
+ templateSnapshot: input.template,
13787
14304
  pdfBase64: void 0,
13788
14305
  title: void 0,
13789
14306
  applicationType: null,
14307
+ questionGraph: input.questionGraph ?? input.template?.questionGraph,
13790
14308
  fields: [],
13791
14309
  qualityReport: void 0,
13792
14310
  batches: void 0,
@@ -13846,6 +14364,12 @@ function createApplicationPipeline(config) {
13846
14364
  return { state, tokenUsage: totalUsage, reviewReport: state.qualityReport };
13847
14365
  }
13848
14366
  state.fields = fields;
14367
+ state.questionGraph = input.questionGraph ?? input.template?.questionGraph ?? buildQuestionGraphFromFields(fields, {
14368
+ id: `${id}:graph`,
14369
+ title: classifyResult.applicationType ?? void 0,
14370
+ applicationType: classifyResult.applicationType,
14371
+ source: "pdf"
14372
+ });
13849
14373
  state.title = classifyResult.applicationType ?? void 0;
13850
14374
  state.status = "auto_filling";
13851
14375
  state.updatedAt = Date.now();
@@ -13866,8 +14390,10 @@ function createApplicationPipeline(config) {
13866
14390
  if (field && !field.value && pa.relevance > 0.8) {
13867
14391
  field.value = pa.value;
13868
14392
  field.source = `backfill: ${pa.source}`;
13869
- field.confidence = "high";
13870
- field.validationStatus = "needs_review";
14393
+ field.confidence = pa.confidence ?? "high";
14394
+ field.validationStatus = pa.sourceSpanIds?.length ? "valid" : "needs_review";
14395
+ field.sourceSpanIds = pa.sourceSpanIds;
14396
+ field.userSourceSpanIds = pa.userSourceSpanIds;
13871
14397
  }
13872
14398
  }
13873
14399
  } catch (e) {
@@ -13917,7 +14443,18 @@ function createApplicationPipeline(config) {
13917
14443
  try {
13918
14444
  const searchPromises = workflowPlan.documentSearchFields.map(
13919
14445
  (f) => limit(async () => {
13920
- await memoryStore.search(f.label, { limit: 3 });
14446
+ const chunks = await memoryStore.search(`${f.section} ${f.label}`, { limit: 3 });
14447
+ const match = selectMemoryBackfillMatch(f, chunks);
14448
+ if (match) {
14449
+ const field = state.fields.find((candidate) => candidate.id === f.id);
14450
+ if (field && !field.value) {
14451
+ field.value = match.value;
14452
+ field.source = match.source;
14453
+ field.confidence = match.confidence;
14454
+ field.validationStatus = match.sourceSpanIds.length > 0 ? "valid" : "needs_review";
14455
+ field.sourceSpanIds = match.sourceSpanIds.length > 0 ? match.sourceSpanIds : void 0;
14456
+ }
14457
+ }
13921
14458
  })
13922
14459
  );
13923
14460
  await Promise.all(searchPromises);
@@ -13937,7 +14474,7 @@ function createApplicationPipeline(config) {
13937
14474
  hasDocumentStore: false,
13938
14475
  hasMemoryStore: false
13939
14476
  });
13940
- const unfilledFields = workflowPlan.unfilledFields;
14477
+ const unfilledFields = getActiveApplicationFields(state).filter((field) => !field.value);
13941
14478
  if (workflowPlan.runBatching) {
13942
14479
  onProgress?.(`Batching ${unfilledFields.length} remaining questions...`);
13943
14480
  state.status = "batching";
@@ -13959,6 +14496,7 @@ function createApplicationPipeline(config) {
13959
14496
  } else {
13960
14497
  state.status = "confirming";
13961
14498
  }
14499
+ state.contextProposals = proposeContextWrites(state);
13962
14500
  state.qualityReport = buildApplicationQualityReport(state);
13963
14501
  state.updatedAt = Date.now();
13964
14502
  await applicationStore?.save(state);
@@ -13986,7 +14524,8 @@ function createApplicationPipeline(config) {
13986
14524
  throw new Error(`Application ${applicationId} not found`);
13987
14525
  }
13988
14526
  const currentBatchFieldIds = state.batches?.[state.currentBatchIndex] ?? [];
13989
- const currentBatchFields = state.fields.filter(
14527
+ const activeFields = getActiveApplicationFields(state);
14528
+ const currentBatchFields = activeFields.filter(
13990
14529
  (f) => currentBatchFieldIds.includes(f.id)
13991
14530
  );
13992
14531
  onProgress?.("Classifying reply...");
@@ -14109,14 +14648,16 @@ Provide a brief, helpful explanation (2-3 sentences). End with "Just reply with
14109
14648
  responseText = `I wasn't able to generate an explanation for your question. Could you rephrase it, or just provide the answer directly?`;
14110
14649
  }
14111
14650
  }
14112
- const currentBatchComplete = currentBatchFieldIds.every(
14651
+ const activeCurrentBatchFieldIds = currentBatchFields.map((field) => field.id);
14652
+ const currentBatchComplete = activeCurrentBatchFieldIds.every(
14113
14653
  (fid) => state.fields.find((f) => f.id === fid)?.value
14114
14654
  );
14115
14655
  let nextBatchIndex;
14116
14656
  let nextBatchFields;
14117
14657
  if (state.batches) {
14118
14658
  for (let index = state.currentBatchIndex + 1; index < state.batches.length; index++) {
14119
- const candidateFields = state.fields.filter((f) => state.batches[index].includes(f.id));
14659
+ const activeCandidateFields = getActiveApplicationFields(state);
14660
+ const candidateFields = activeCandidateFields.filter((f) => state.batches[index].includes(f.id));
14120
14661
  if (candidateFields.some((f) => !f.value)) {
14121
14662
  nextBatchIndex = index;
14122
14663
  nextBatchFields = candidateFields;
@@ -14172,7 +14713,8 @@ ${emailText}`;
14172
14713
  }
14173
14714
  }
14174
14715
  state.updatedAt = Date.now();
14175
- state.qualityReport = state.qualityReport ?? buildApplicationQualityReport(state);
14716
+ state.contextProposals = proposeContextWrites(state);
14717
+ state.qualityReport = buildApplicationQualityReport(state);
14176
14718
  await applicationStore?.save(state);
14177
14719
  if (shouldFailQualityGate(qualityGate, state.qualityReport.qualityGateStatus)) {
14178
14720
  throw new Error("Application quality gate failed. See state.qualityReport for blocking issues.");
@@ -14192,7 +14734,7 @@ ${emailText}`;
14192
14734
  if (!state) throw new Error(`Application ${applicationId} not found`);
14193
14735
  if (!state.batches?.length) throw new Error("No batches available");
14194
14736
  const batchFieldIds = state.batches[state.currentBatchIndex];
14195
- const batchFields = state.fields.filter((f) => batchFieldIds.includes(f.id));
14737
+ const batchFields = getActiveApplicationFields(state).filter((f) => batchFieldIds.includes(f.id));
14196
14738
  const filledCount = state.fields.filter((f) => f.value).length;
14197
14739
  const { text, usage } = await generateBatchEmail(
14198
14740
  batchFields,
@@ -14240,13 +14782,86 @@ ${fieldSummary}`,
14240
14782
  trackUsage(usage);
14241
14783
  return { text, tokenUsage: totalUsage };
14242
14784
  }
14785
+ async function createApplicationRun2(input) {
14786
+ const state = createApplicationRun(input);
14787
+ await applicationStore?.save(state);
14788
+ return state;
14789
+ }
14790
+ async function planNextQuestions(applicationId, limit2) {
14791
+ const state = await applicationStore?.get(applicationId);
14792
+ if (!state) throw new Error(`Application ${applicationId} not found`);
14793
+ return planNextApplicationQuestions(state, limit2);
14794
+ }
14795
+ async function proposeContextWrites2(applicationId) {
14796
+ const state = await applicationStore?.get(applicationId);
14797
+ if (!state) throw new Error(`Application ${applicationId} not found`);
14798
+ const proposals = proposeContextWrites(state);
14799
+ await applicationStore?.save({
14800
+ ...state,
14801
+ contextProposals: proposals,
14802
+ updatedAt: Date.now()
14803
+ });
14804
+ return { proposals };
14805
+ }
14806
+ async function buildApplicationPacket2(input) {
14807
+ const state = await applicationStore?.get(input.applicationId);
14808
+ if (!state) throw new Error(`Application ${input.applicationId} not found`);
14809
+ const packet = buildApplicationPacket(state, {
14810
+ submissionNotes: input.submissionNotes,
14811
+ now: input.now
14812
+ });
14813
+ const reviewReport = validateApplicationPacket(packet);
14814
+ await applicationStore?.save({
14815
+ ...state,
14816
+ packet: { ...packet, qualityReport: reviewReport },
14817
+ status: reviewReport.qualityGateStatus === "failed" ? "broker_review" : "packet_ready",
14818
+ qualityReport: reviewReport,
14819
+ updatedAt: Date.now()
14820
+ });
14821
+ return { packet: { ...packet, qualityReport: reviewReport }, reviewReport };
14822
+ }
14243
14823
  return {
14244
14824
  processApplication,
14245
14825
  processReply: processReply2,
14246
14826
  generateCurrentBatchEmail,
14247
- getConfirmationSummary
14827
+ getConfirmationSummary,
14828
+ createApplicationRun: createApplicationRun2,
14829
+ planNextQuestions,
14830
+ proposeContextWrites: proposeContextWrites2,
14831
+ buildApplicationPacket: buildApplicationPacket2
14248
14832
  };
14249
14833
  }
14834
+ function selectMemoryBackfillMatch(field, chunks) {
14835
+ for (const chunk of chunks) {
14836
+ const value = chunk.metadata.value ?? chunk.metadata.answer ?? chunk.metadata.fieldValue;
14837
+ if (!value) continue;
14838
+ const metadataFieldId = chunk.metadata.fieldId ?? chunk.metadata.applicationFieldId;
14839
+ const metadataLabel = chunk.metadata.fieldLabel?.toLowerCase();
14840
+ const labelMatches = metadataLabel === field.label.toLowerCase();
14841
+ if (metadataFieldId && metadataFieldId !== field.id && !labelMatches) continue;
14842
+ return {
14843
+ value,
14844
+ source: chunk.metadata.source ?? `memory: ${chunk.documentId}`,
14845
+ confidence: metadataFieldId === field.id || labelMatches ? "high" : "medium",
14846
+ sourceSpanIds: parseSourceSpanIds(chunk.metadata.sourceSpanIds)
14847
+ };
14848
+ }
14849
+ return null;
14850
+ }
14851
+ function parseSourceSpanIds(value) {
14852
+ if (!value) return [];
14853
+ const trimmed = value.trim();
14854
+ if (!trimmed) return [];
14855
+ if (trimmed.startsWith("[")) {
14856
+ try {
14857
+ const parsed = JSON.parse(trimmed);
14858
+ return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
14859
+ } catch {
14860
+ return [];
14861
+ }
14862
+ }
14863
+ return trimmed.split(",").map((item) => item.trim()).filter(Boolean);
14864
+ }
14250
14865
 
14251
14866
  // src/prompts/application/confirmation.ts
14252
14867
  function buildConfirmationSummaryPrompt(fields, applicationTitle) {
@@ -16327,13 +16942,21 @@ var AGENT_TOOLS = [
16327
16942
  AgenticExecutionModeSchema,
16328
16943
  AnswerParsingResultSchema,
16329
16944
  ApplicationClassifyResultSchema,
16945
+ ApplicationContextProposalSchema,
16330
16946
  ApplicationEmailReviewSchema,
16331
16947
  ApplicationFieldSchema,
16948
+ ApplicationPacketAnswerSchema,
16949
+ ApplicationPacketSchema,
16332
16950
  ApplicationQualityArtifactSchema,
16333
16951
  ApplicationQualityIssueSchema,
16334
16952
  ApplicationQualityReportSchema,
16335
16953
  ApplicationQualityRoundSchema,
16954
+ ApplicationQuestionConditionSchema,
16955
+ ApplicationQuestionGraphSchema,
16956
+ ApplicationQuestionNodeSchema,
16957
+ ApplicationRepeatSchema,
16336
16958
  ApplicationStateSchema,
16959
+ ApplicationTemplateSchema,
16337
16960
  AttachmentInterpretationSchema,
16338
16961
  AuditTypeSchema,
16339
16962
  AutoFillMatchSchema,
@@ -16548,9 +17171,11 @@ var AGENT_TOOLS = [
16548
17171
  VerifyResultSchema,
16549
17172
  WatercraftDeclarationsSchema,
16550
17173
  WorkersCompDeclarationsSchema,
17174
+ applyApplicationAnswers,
16551
17175
  buildAcroFormMappingPrompt,
16552
17176
  buildAgentSystemPrompt,
16553
17177
  buildAnswerParsingPrompt,
17178
+ buildApplicationPacket,
16554
17179
  buildAutoFillPrompt,
16555
17180
  buildBatchEmailGenerationPrompt,
16556
17181
  buildClassifyMessagePrompt,
@@ -16577,6 +17202,7 @@ var AGENT_TOOLS = [
16577
17202
  buildPdfProviderOptions,
16578
17203
  buildQueryClassifyPrompt,
16579
17204
  buildQuestionBatchPrompt,
17205
+ buildQuestionGraphFromFields,
16580
17206
  buildQuotesPoliciesPrompt,
16581
17207
  buildReasonPrompt,
16582
17208
  buildReplyIntentClassificationPrompt,
@@ -16592,6 +17218,7 @@ var AGENT_TOOLS = [
16592
17218
  collectPceEvidenceSources,
16593
17219
  compareSourceEvidence,
16594
17220
  createApplicationPipeline,
17221
+ createApplicationRun,
16595
17222
  createExtractor,
16596
17223
  createPceAgent,
16597
17224
  createPipelineContext,
@@ -16599,12 +17226,16 @@ var AGENT_TOOLS = [
16599
17226
  evaluateCaseProposals,
16600
17227
  evidenceContainsQuote,
16601
17228
  extractPageRange,
17229
+ extractQuestionGraphFromFields,
16602
17230
  fillAcroForm,
17231
+ flattenQuestionGraph,
16603
17232
  generateNextMessage,
16604
17233
  getAcroFormFields,
17234
+ getActiveApplicationFields,
16605
17235
  getDoclingPageRangeText,
16606
17236
  getExtractor,
16607
17237
  getFileIdentifier,
17238
+ getNextApplicationQuestions,
16608
17239
  getPdfPageCount,
16609
17240
  getTemplate,
16610
17241
  isDoclingExtractionInput,
@@ -16612,6 +17243,7 @@ var AGENT_TOOLS = [
16612
17243
  mergeOperationalProfile,
16613
17244
  mergeQuestionAnswers,
16614
17245
  mergeSourceSpans,
17246
+ normalizeApplicationQuestionGraph,
16615
17247
  normalizeDoclingDocument,
16616
17248
  normalizeDocumentSourceTreePaths,
16617
17249
  normalizeForMatch,
@@ -16621,7 +17253,9 @@ var AGENT_TOOLS = [
16621
17253
  pLimit,
16622
17254
  pdfInputToBase64,
16623
17255
  pdfInputToBytes,
17256
+ planNextApplicationQuestions,
16624
17257
  processReply,
17258
+ proposeContextWrites,
16625
17259
  resolveModelBudget,
16626
17260
  safeGenerateObject,
16627
17261
  sanitizeNulls,
@@ -16634,6 +17268,7 @@ var AGENT_TOOLS = [
16634
17268
  stableStringify,
16635
17269
  stripFences,
16636
17270
  toStrictSchema,
17271
+ validateApplicationPacket,
16637
17272
  validateEvidence,
16638
17273
  validatePceItems,
16639
17274
  validateQuotedEvidence,