hazo_collab_forms 3.1.7 → 5.0.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/CHANGE_LOG.md +201 -0
- package/README.md +3 -0
- package/dist/components/clarification/clarification_item_body.d.ts +19 -1
- package/dist/components/clarification/clarification_item_body.d.ts.map +1 -1
- package/dist/components/clarification/clarification_item_body.js +114 -6
- package/dist/components/clarification/clarification_item_body.js.map +1 -1
- package/dist/components/clarification/clarification_thread.js +1 -1
- package/dist/components/clarification/clarification_thread.js.map +1 -1
- package/dist/components/clarification/index.d.ts +2 -0
- package/dist/components/clarification/index.d.ts.map +1 -1
- package/dist/components/clarification/index.js +1 -0
- package/dist/components/clarification/index.js.map +1 -1
- package/dist/components/clarification/resolution_status_strip.d.ts +18 -0
- package/dist/components/clarification/resolution_status_strip.d.ts.map +1 -0
- package/dist/components/clarification/resolution_status_strip.js +20 -0
- package/dist/components/clarification/resolution_status_strip.js.map +1 -0
- package/dist/components/hazo_fb_form/context.d.ts +1 -1
- package/dist/components/hazo_fb_form/context.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/hazo_fb_form.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/hazo_fb_form.js +330 -113
- package/dist/components/hazo_fb_form/hazo_fb_form.js.map +1 -1
- package/dist/components/hazo_fb_form/hooks/use_fb_form_state.d.ts +3 -3
- package/dist/components/hazo_fb_form/hooks/use_fb_form_state.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/hooks/use_fb_form_state.js +339 -46
- package/dist/components/hazo_fb_form/hooks/use_fb_form_state.js.map +1 -1
- package/dist/components/hazo_fb_form/hooks/use_llm_run.d.ts +3 -1
- package/dist/components/hazo_fb_form/hooks/use_llm_run.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/hooks/use_llm_run.js +89 -11
- package/dist/components/hazo_fb_form/hooks/use_llm_run.js.map +1 -1
- package/dist/components/hazo_fb_form/shared/agent_stepper.js +1 -1
- package/dist/components/hazo_fb_form/shared/agent_stepper.js.map +1 -1
- package/dist/components/hazo_fb_form/shared/file_status_accordion.d.ts +9 -0
- package/dist/components/hazo_fb_form/shared/file_status_accordion.d.ts.map +1 -0
- package/dist/components/hazo_fb_form/shared/file_status_accordion.js +39 -0
- package/dist/components/hazo_fb_form/shared/file_status_accordion.js.map +1 -0
- package/dist/components/hazo_fb_form/shared/format.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/shared/format.js +8 -3
- package/dist/components/hazo_fb_form/shared/format.js.map +1 -1
- package/dist/components/hazo_fb_form/shared/send_back_item_card.d.ts +7 -1
- package/dist/components/hazo_fb_form/shared/send_back_item_card.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/shared/send_back_item_card.js +6 -3
- package/dist/components/hazo_fb_form/shared/send_back_item_card.js.map +1 -1
- package/dist/components/hazo_fb_form/types.d.ts +3 -1
- package/dist/components/hazo_fb_form/types.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/views/back_office_view.js +1 -1
- package/dist/components/hazo_fb_form/views/back_office_view.js.map +1 -1
- package/dist/components/hazo_fb_form/views/clarifications_view.js +2 -2
- package/dist/components/hazo_fb_form/views/clarifications_view.js.map +1 -1
- package/dist/components/hazo_fb_form/views/front_office_view.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/views/front_office_view.js +62 -41
- package/dist/components/hazo_fb_form/views/front_office_view.js.map +1 -1
- package/dist/components/hazo_fb_form/views/interim_view.js +3 -3
- package/dist/components/hazo_fb_form/views/interim_view.js.map +1 -1
- package/dist/components/hazo_fb_form/views/review_queue_view.d.ts.map +1 -1
- package/dist/components/hazo_fb_form/views/review_queue_view.js +22 -9
- package/dist/components/hazo_fb_form/views/review_queue_view.js.map +1 -1
- package/dist/components/hazo_validation_rule_editor/components/rule_editor.d.ts.map +1 -1
- package/dist/components/hazo_validation_rule_editor/components/rule_editor.js +32 -3
- package/dist/components/hazo_validation_rule_editor/components/rule_editor.js.map +1 -1
- package/dist/components/hazo_validation_rule_editor/components/variable_chain_input.d.ts +20 -0
- package/dist/components/hazo_validation_rule_editor/components/variable_chain_input.d.ts.map +1 -0
- package/dist/components/hazo_validation_rule_editor/components/variable_chain_input.js +34 -0
- package/dist/components/hazo_validation_rule_editor/components/variable_chain_input.js.map +1 -0
- package/dist/components/hazo_validation_rule_editor/context.d.ts +3 -2
- package/dist/components/hazo_validation_rule_editor/context.d.ts.map +1 -1
- package/dist/components/hazo_validation_rule_editor/context.js +15 -3
- package/dist/components/hazo_validation_rule_editor/context.js.map +1 -1
- package/dist/components/hazo_validation_rule_editor/types.d.ts +7 -1
- package/dist/components/hazo_validation_rule_editor/types.d.ts.map +1 -1
- package/dist/components/hazo_validation_rule_editor/validation_rule_editor.d.ts +1 -1
- package/dist/components/hazo_validation_rule_editor/validation_rule_editor.d.ts.map +1 -1
- package/dist/components/hazo_validation_rule_editor/validation_rule_editor.js +2 -2
- package/dist/components/hazo_validation_rule_editor/validation_rule_editor.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/shared/document_type_editor.d.ts +31 -0
- package/dist/components/shared/document_type_editor.d.ts.map +1 -0
- package/dist/components/shared/document_type_editor.js +60 -0
- package/dist/components/shared/document_type_editor.js.map +1 -0
- package/dist/components/shared/file_bar/file_bar.d.ts +7 -1
- package/dist/components/shared/file_bar/file_bar.d.ts.map +1 -1
- package/dist/components/shared/file_bar/file_bar.js +5 -3
- package/dist/components/shared/file_bar/file_bar.js.map +1 -1
- package/dist/components/shared/file_bar/file_bar_validation_dialog.js +4 -4
- package/dist/components/shared/file_bar/file_bar_validation_dialog.js.map +1 -1
- package/dist/components/shared/file_status_icon.d.ts +23 -0
- package/dist/components/shared/file_status_icon.d.ts.map +1 -0
- package/dist/components/shared/file_status_icon.js +38 -0
- package/dist/components/shared/file_status_icon.js.map +1 -0
- package/dist/components/shared/json_data_panel/json_data_panel.d.ts +1 -1
- package/dist/components/shared/json_data_panel/json_data_panel.d.ts.map +1 -1
- package/dist/components/shared/json_data_panel/json_data_panel.js +27 -2
- package/dist/components/shared/json_data_panel/json_data_panel.js.map +1 -1
- package/dist/components/shared/rule_result_card.d.ts.map +1 -1
- package/dist/components/shared/rule_result_card.js +5 -4
- package/dist/components/shared/rule_result_card.js.map +1 -1
- package/dist/components/thread_form/components/add_question_dialog.d.ts +12 -0
- package/dist/components/thread_form/components/add_question_dialog.d.ts.map +1 -0
- package/dist/components/thread_form/components/add_question_dialog.js +36 -0
- package/dist/components/thread_form/components/add_question_dialog.js.map +1 -0
- package/dist/components/thread_form/components/agent_compose_dialog.d.ts +30 -0
- package/dist/components/thread_form/components/agent_compose_dialog.d.ts.map +1 -0
- package/dist/components/thread_form/components/agent_compose_dialog.js +45 -0
- package/dist/components/thread_form/components/agent_compose_dialog.js.map +1 -0
- package/dist/components/thread_form/components/clarification.d.ts +14 -0
- package/dist/components/thread_form/components/clarification.d.ts.map +1 -0
- package/dist/components/thread_form/components/clarification.js +12 -0
- package/dist/components/thread_form/components/clarification.js.map +1 -0
- package/dist/components/thread_form/components/collected_data_view.d.ts +15 -0
- package/dist/components/thread_form/components/collected_data_view.d.ts.map +1 -0
- package/dist/components/thread_form/components/collected_data_view.js +121 -0
- package/dist/components/thread_form/components/collected_data_view.js.map +1 -0
- package/dist/components/thread_form/components/coverage_card.d.ts +11 -0
- package/dist/components/thread_form/components/coverage_card.d.ts.map +1 -0
- package/dist/components/thread_form/components/coverage_card.js +60 -0
- package/dist/components/thread_form/components/coverage_card.js.map +1 -0
- package/dist/components/thread_form/components/file_bar.d.ts +93 -0
- package/dist/components/thread_form/components/file_bar.d.ts.map +1 -0
- package/dist/components/thread_form/components/file_bar.js +251 -0
- package/dist/components/thread_form/components/file_bar.js.map +1 -0
- package/dist/components/thread_form/components/file_info_dialog.d.ts +15 -0
- package/dist/components/thread_form/components/file_info_dialog.d.ts.map +1 -0
- package/dist/components/thread_form/components/file_info_dialog.js +64 -0
- package/dist/components/thread_form/components/file_info_dialog.js.map +1 -0
- package/dist/components/thread_form/components/issue_group_tree.d.ts +20 -0
- package/dist/components/thread_form/components/issue_group_tree.d.ts.map +1 -0
- package/dist/components/thread_form/components/issue_group_tree.js +164 -0
- package/dist/components/thread_form/components/issue_group_tree.js.map +1 -0
- package/dist/components/thread_form/components/pdf_side_panel.d.ts +20 -0
- package/dist/components/thread_form/components/pdf_side_panel.d.ts.map +1 -0
- package/dist/components/thread_form/components/pdf_side_panel.js +63 -0
- package/dist/components/thread_form/components/pdf_side_panel.js.map +1 -0
- package/dist/components/thread_form/components/rule_decision_row.d.ts +31 -0
- package/dist/components/thread_form/components/rule_decision_row.d.ts.map +1 -0
- package/dist/components/thread_form/components/rule_decision_row.js +20 -0
- package/dist/components/thread_form/components/rule_decision_row.js.map +1 -0
- package/dist/components/thread_form/components/send_back_message.d.ts +32 -0
- package/dist/components/thread_form/components/send_back_message.d.ts.map +1 -0
- package/dist/components/thread_form/components/send_back_message.js +82 -0
- package/dist/components/thread_form/components/send_back_message.js.map +1 -0
- package/dist/components/thread_form/components/shared.d.ts +54 -0
- package/dist/components/thread_form/components/shared.d.ts.map +1 -0
- package/dist/components/thread_form/components/shared.js +136 -0
- package/dist/components/thread_form/components/shared.js.map +1 -0
- package/dist/components/thread_form/components/task_card.d.ts +90 -0
- package/dist/components/thread_form/components/task_card.d.ts.map +1 -0
- package/dist/components/thread_form/components/task_card.js +63 -0
- package/dist/components/thread_form/components/task_card.js.map +1 -0
- package/dist/components/thread_form/components/text_doc_check.d.ts +15 -0
- package/dist/components/thread_form/components/text_doc_check.d.ts.map +1 -0
- package/dist/components/thread_form/components/text_doc_check.js +16 -0
- package/dist/components/thread_form/components/text_doc_check.js.map +1 -0
- package/dist/components/thread_form/components/text_extraction.d.ts +14 -0
- package/dist/components/thread_form/components/text_extraction.d.ts.map +1 -0
- package/dist/components/thread_form/components/text_extraction.js +16 -0
- package/dist/components/thread_form/components/text_extraction.js.map +1 -0
- package/dist/components/thread_form/components/thread_composer.d.ts +15 -0
- package/dist/components/thread_form/components/thread_composer.d.ts.map +1 -0
- package/dist/components/thread_form/components/thread_composer.js +93 -0
- package/dist/components/thread_form/components/thread_composer.js.map +1 -0
- package/dist/components/thread_form/components/thread_timeline.d.ts +65 -0
- package/dist/components/thread_form/components/thread_timeline.d.ts.map +1 -0
- package/dist/components/thread_form/components/thread_timeline.js +225 -0
- package/dist/components/thread_form/components/thread_timeline.js.map +1 -0
- package/dist/components/thread_form/hooks/use_file_pipeline.d.ts +126 -0
- package/dist/components/thread_form/hooks/use_file_pipeline.d.ts.map +1 -0
- package/dist/components/thread_form/hooks/use_file_pipeline.js +760 -0
- package/dist/components/thread_form/hooks/use_file_pipeline.js.map +1 -0
- package/dist/components/thread_form/hooks/use_thread_form.d.ts +36 -0
- package/dist/components/thread_form/hooks/use_thread_form.d.ts.map +1 -0
- package/dist/components/thread_form/hooks/use_thread_form.js +126 -0
- package/dist/components/thread_form/hooks/use_thread_form.js.map +1 -0
- package/dist/components/thread_form/index.d.ts +33 -0
- package/dist/components/thread_form/index.d.ts.map +1 -0
- package/dist/components/thread_form/index.js +30 -0
- package/dist/components/thread_form/index.js.map +1 -0
- package/dist/components/thread_form/sample_data.d.ts +8 -0
- package/dist/components/thread_form/sample_data.d.ts.map +1 -0
- package/dist/components/thread_form/sample_data.js +658 -0
- package/dist/components/thread_form/sample_data.js.map +1 -0
- package/dist/components/thread_form/thread_form.d.ts +7 -0
- package/dist/components/thread_form/thread_form.d.ts.map +1 -0
- package/dist/components/thread_form/thread_form.js +1385 -0
- package/dist/components/thread_form/thread_form.js.map +1 -0
- package/dist/components/thread_form/types.d.ts +402 -0
- package/dist/components/thread_form/types.d.ts.map +1 -0
- package/dist/components/thread_form/types.js +23 -0
- package/dist/components/thread_form/types.js.map +1 -0
- package/dist/components/thread_form/utils/file_decision_state.d.ts +22 -0
- package/dist/components/thread_form/utils/file_decision_state.d.ts.map +1 -0
- package/dist/components/thread_form/utils/file_decision_state.js +37 -0
- package/dist/components/thread_form/utils/file_decision_state.js.map +1 -0
- package/dist/components/thread_form/utils/merge_send_back.d.ts +13 -0
- package/dist/components/thread_form/utils/merge_send_back.d.ts.map +1 -0
- package/dist/components/thread_form/utils/merge_send_back.js +23 -0
- package/dist/components/thread_form/utils/merge_send_back.js.map +1 -0
- package/dist/lib/autofill_handler.d.ts.map +1 -1
- package/dist/lib/autofill_handler.js +5 -44
- package/dist/lib/autofill_handler.js.map +1 -1
- package/dist/lib/classification_handler.d.ts +105 -0
- package/dist/lib/classification_handler.d.ts.map +1 -0
- package/dist/lib/classification_handler.js +342 -0
- package/dist/lib/classification_handler.js.map +1 -0
- package/dist/lib/content_gate_handler.d.ts +37 -0
- package/dist/lib/content_gate_handler.d.ts.map +1 -0
- package/dist/lib/content_gate_handler.js +126 -0
- package/dist/lib/content_gate_handler.js.map +1 -0
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +5 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/periodic_coverage_runner.d.ts +24 -0
- package/dist/lib/periodic_coverage_runner.d.ts.map +1 -0
- package/dist/lib/periodic_coverage_runner.js +121 -0
- package/dist/lib/periodic_coverage_runner.js.map +1 -0
- package/dist/lib/resolution_handler.d.ts +150 -0
- package/dist/lib/resolution_handler.d.ts.map +1 -0
- package/dist/lib/resolution_handler.js +597 -0
- package/dist/lib/resolution_handler.js.map +1 -0
- package/dist/lib/resolve_variable.d.ts +25 -0
- package/dist/lib/resolve_variable.d.ts.map +1 -0
- package/dist/lib/resolve_variable.js +77 -0
- package/dist/lib/resolve_variable.js.map +1 -0
- package/dist/lib/validation_handler.d.ts +27 -3
- package/dist/lib/validation_handler.d.ts.map +1 -1
- package/dist/lib/validation_handler.js +338 -288
- package/dist/lib/validation_handler.js.map +1 -1
- package/dist/types/clarification.d.ts +54 -0
- package/dist/types/clarification.d.ts.map +1 -1
- package/dist/types/fb_form_data.d.ts +273 -123
- package/dist/types/fb_form_data.d.ts.map +1 -1
- package/dist/types/fb_form_data.js +44 -58
- package/dist/types/fb_form_data.js.map +1 -1
- package/dist/types/fb_form_data_v1.d.ts +250 -0
- package/dist/types/fb_form_data_v1.d.ts.map +1 -0
- package/dist/types/fb_form_data_v1.js +117 -0
- package/dist/types/fb_form_data_v1.js.map +1 -0
- package/dist/types/fb_form_instance.d.ts +1 -1
- package/dist/types/fb_form_instance.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/validation.d.ts +134 -12
- package/dist/types/validation.d.ts.map +1 -1
- package/dist/utils/expectation_extractor.d.ts +31 -0
- package/dist/utils/expectation_extractor.d.ts.map +1 -0
- package/dist/utils/expectation_extractor.js +142 -0
- package/dist/utils/expectation_extractor.js.map +1 -0
- package/dist/utils/fb_data_adapter.d.ts +7 -2
- package/dist/utils/fb_data_adapter.d.ts.map +1 -1
- package/dist/utils/fb_data_adapter.js +58 -7
- package/dist/utils/fb_data_adapter.js.map +1 -1
- package/dist/utils/fb_data_adapter_v2.d.ts +17 -0
- package/dist/utils/fb_data_adapter_v2.d.ts.map +1 -0
- package/dist/utils/fb_data_adapter_v2.js +483 -0
- package/dist/utils/fb_data_adapter_v2.js.map +1 -0
- package/dist/utils/fb_data_helpers.d.ts +1 -1
- package/dist/utils/fb_data_helpers.d.ts.map +1 -1
- package/dist/utils/fb_data_mutations.d.ts +1 -1
- package/dist/utils/fb_data_mutations.d.ts.map +1 -1
- package/dist/utils/fb_data_mutations_v2.d.ts +46 -0
- package/dist/utils/fb_data_mutations_v2.d.ts.map +1 -0
- package/dist/utils/fb_data_mutations_v2.js +341 -0
- package/dist/utils/fb_data_mutations_v2.js.map +1 -0
- package/dist/utils/fb_data_queries.d.ts +81 -0
- package/dist/utils/fb_data_queries.d.ts.map +1 -0
- package/dist/utils/fb_data_queries.js +354 -0
- package/dist/utils/fb_data_queries.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/issue_bucketing.d.ts +36 -0
- package/dist/utils/issue_bucketing.d.ts.map +1 -0
- package/dist/utils/issue_bucketing.js +107 -0
- package/dist/utils/issue_bucketing.js.map +1 -0
- package/dist/utils/validation_result.d.ts +32 -0
- package/dist/utils/validation_result.d.ts.map +1 -0
- package/dist/utils/validation_result.js +55 -0
- package/dist/utils/validation_result.js.map +1 -0
- package/package.json +16 -4
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregate-level resolver for clarification responses.
|
|
3
|
+
*
|
|
4
|
+
* Step 1 (deterministic, mandatory): sum_match math + date-range check
|
|
5
|
+
* Step 2 (LLM commentary, best-effort): per-file plain-English notes
|
|
6
|
+
*
|
|
7
|
+
* Step 1 is the source of truth. Step 2 enriches with qualitative commentary
|
|
8
|
+
* but never overrides the verdict — if the LLM step fails, file_notes is empty
|
|
9
|
+
* and the deterministic summary still flows through.
|
|
10
|
+
*/
|
|
11
|
+
import 'server-only';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Helpers
|
|
14
|
+
// ============================================================================
|
|
15
|
+
const DEFAULT_TOLERANCE = 0.05;
|
|
16
|
+
/**
|
|
17
|
+
* Document types accepted as evidence for a sum_match (receipt-style proof
|
|
18
|
+
* of payment). Files outside this list are flagged as off-topic and excluded
|
|
19
|
+
* from the sum. 'unknown' is included so the resolver doesn't punish files
|
|
20
|
+
* the classifier wasn't confident about.
|
|
21
|
+
*/
|
|
22
|
+
const SUM_MATCH_ACCEPTED_TYPES = new Set([
|
|
23
|
+
'invoice',
|
|
24
|
+
'receipt',
|
|
25
|
+
'tax_invoice',
|
|
26
|
+
'bill',
|
|
27
|
+
'unknown',
|
|
28
|
+
]);
|
|
29
|
+
function is_acceptable_for_sum_match(document_type) {
|
|
30
|
+
if (!document_type)
|
|
31
|
+
return true; // missing classification — give benefit of doubt
|
|
32
|
+
return SUM_MATCH_ACCEPTED_TYPES.has(document_type);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Phrases that, when present in `document_nature`, guarantee the file is NOT
|
|
36
|
+
* a receipt for repairs/maintenance even if `document_type` came back as a
|
|
37
|
+
* generic 'invoice'. This is a deterministic safety net — the LLM relevance
|
|
38
|
+
* check should also catch these, but we don't depend on its compliance.
|
|
39
|
+
*
|
|
40
|
+
* Match is case-insensitive substring against document_nature.
|
|
41
|
+
*/
|
|
42
|
+
const SUM_MATCH_NATURE_DENYLIST = [
|
|
43
|
+
{ phrase: 'settlement adjustment', label: 'settlement adjustment statement' },
|
|
44
|
+
{ phrase: 'purchaser settlement', label: 'purchaser settlement sheet' },
|
|
45
|
+
{ phrase: 'settlement statement', label: 'settlement statement' },
|
|
46
|
+
{ phrase: 'council rates', label: 'council rates notice' },
|
|
47
|
+
{ phrase: 'strata levy', label: 'strata levy invoice' },
|
|
48
|
+
{ phrase: 'body corporate', label: 'body corporate fee notice' },
|
|
49
|
+
{ phrase: 'insurance schedule', label: 'insurance policy schedule' },
|
|
50
|
+
{ phrase: 'certificate of currency', label: 'insurance certificate of currency' },
|
|
51
|
+
{ phrase: 'depreciation schedule', label: 'depreciation schedule' },
|
|
52
|
+
{ phrase: 'property valuation', label: 'property valuation' },
|
|
53
|
+
{ phrase: 'conveyancing', label: 'conveyancing service invoice' },
|
|
54
|
+
{ phrase: 'property purchase', label: 'property purchase document' },
|
|
55
|
+
{ phrase: 'property management fee', label: 'property management fee invoice' },
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* Deterministic content check — returns the matched denylist label when the
|
|
59
|
+
* file's document_nature contains any denied phrase, otherwise null. Lets us
|
|
60
|
+
* flag a file as off-topic without waiting on (or trusting) the LLM verdict.
|
|
61
|
+
*/
|
|
62
|
+
function nature_denylist_match(document_nature) {
|
|
63
|
+
if (!document_nature)
|
|
64
|
+
return null;
|
|
65
|
+
const haystack = document_nature.toLowerCase();
|
|
66
|
+
for (const entry of SUM_MATCH_NATURE_DENYLIST) {
|
|
67
|
+
if (haystack.includes(entry.phrase))
|
|
68
|
+
return entry.label;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
function format_doc_type(t) {
|
|
73
|
+
if (!t)
|
|
74
|
+
return 'document';
|
|
75
|
+
return t.replace(/_/g, ' ');
|
|
76
|
+
}
|
|
77
|
+
function format_currency(amount, currency) {
|
|
78
|
+
const sign = amount < 0 ? '-' : '';
|
|
79
|
+
const abs = Math.abs(amount);
|
|
80
|
+
const symbol = currency_symbol(currency);
|
|
81
|
+
return `${sign}${symbol}${abs.toFixed(2)}`;
|
|
82
|
+
}
|
|
83
|
+
function currency_symbol(currency) {
|
|
84
|
+
switch (currency.toUpperCase()) {
|
|
85
|
+
case 'USD': return '$';
|
|
86
|
+
case 'AUD': return 'A$';
|
|
87
|
+
case 'NZD': return 'NZ$';
|
|
88
|
+
case 'CAD': return 'C$';
|
|
89
|
+
case 'GBP': return '£';
|
|
90
|
+
case 'EUR': return '€';
|
|
91
|
+
case 'JPY': return '¥';
|
|
92
|
+
default: return `${currency} `;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function date_in_range(date_str, range) {
|
|
96
|
+
if (!date_str)
|
|
97
|
+
return false;
|
|
98
|
+
return date_str >= range.from && date_str <= range.to;
|
|
99
|
+
}
|
|
100
|
+
async function run_with_timeout(promise, ms) {
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
const timer = setTimeout(() => reject(new Error('commentary_timeout')), ms);
|
|
103
|
+
promise.then((v) => { clearTimeout(timer); resolve(v); }, (e) => { clearTimeout(timer); reject(e); });
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function run_deterministic(input, tolerance, relevance) {
|
|
107
|
+
if (input.expectation.kind !== 'sum_match') {
|
|
108
|
+
// Future kinds not yet implemented — pass through with informational summary.
|
|
109
|
+
return {
|
|
110
|
+
passed: true,
|
|
111
|
+
delta: 0,
|
|
112
|
+
sum_actual: 0,
|
|
113
|
+
sum_expected: 0,
|
|
114
|
+
summary: `No deterministic resolver registered for kind '${input.expectation.kind}'.`,
|
|
115
|
+
details: [],
|
|
116
|
+
file_relevance: {},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const sum_expected = input.expectation.amount;
|
|
120
|
+
const currency = input.expectation.currency;
|
|
121
|
+
const date_range = input.expectation.date_range;
|
|
122
|
+
// Per-file relevance map — combines type filter + LLM relevance into one
|
|
123
|
+
// record consumed by the caller (so each file's pill reflects the verdict).
|
|
124
|
+
const file_relevance = {};
|
|
125
|
+
// Filtering happens in two passes:
|
|
126
|
+
// 1. Type filter (cheap, deterministic) — bank_statement etc. always
|
|
127
|
+
// excluded regardless of relevance.
|
|
128
|
+
// 2. Relevance filter (LLM) — wrong-property invoices flagged as mismatch
|
|
129
|
+
// land here. Defaults to 'matches' when the LLM didn't speak.
|
|
130
|
+
const relevant = [];
|
|
131
|
+
const off_topic_type = [];
|
|
132
|
+
const mismatched = [];
|
|
133
|
+
const unclear = [];
|
|
134
|
+
for (const file of input.response_files) {
|
|
135
|
+
if (!is_acceptable_for_sum_match(file.document_type)) {
|
|
136
|
+
off_topic_type.push({
|
|
137
|
+
file_id: file.file_id,
|
|
138
|
+
name: file.file_name ?? file.file_id,
|
|
139
|
+
document_type: file.document_type,
|
|
140
|
+
});
|
|
141
|
+
file_relevance[file.file_id] = {
|
|
142
|
+
verdict: 'off_topic',
|
|
143
|
+
reason: `looks like a ${format_doc_type(file.document_type)}, not a receipt`,
|
|
144
|
+
};
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// Content denylist — when document_type is a generic 'invoice' but the
|
|
148
|
+
// document_nature reveals it's actually a settlement adjustment, council
|
|
149
|
+
// rates notice, etc., reject deterministically. Catches the case where
|
|
150
|
+
// the LLM relevance check is too lenient.
|
|
151
|
+
const nature_match = nature_denylist_match(file.document_nature);
|
|
152
|
+
if (nature_match) {
|
|
153
|
+
off_topic_type.push({
|
|
154
|
+
file_id: file.file_id,
|
|
155
|
+
name: file.file_name ?? file.file_id,
|
|
156
|
+
document_type: nature_match,
|
|
157
|
+
});
|
|
158
|
+
file_relevance[file.file_id] = {
|
|
159
|
+
verdict: 'off_topic',
|
|
160
|
+
reason: `looks like a ${nature_match}, not a receipt for the requested expense`,
|
|
161
|
+
};
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const r = relevance[file.file_id];
|
|
165
|
+
if (r?.verdict === 'mismatch') {
|
|
166
|
+
mismatched.push({ file_id: file.file_id, name: file.file_name ?? file.file_id, reason: r.reason });
|
|
167
|
+
file_relevance[file.file_id] = { verdict: 'mismatch', reason: r.reason };
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (r?.verdict === 'unclear') {
|
|
171
|
+
unclear.push({ file_id: file.file_id, name: file.file_name ?? file.file_id, reason: r.reason });
|
|
172
|
+
file_relevance[file.file_id] = { verdict: 'unclear', reason: r.reason };
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
file_relevance[file.file_id] = {
|
|
176
|
+
verdict: 'matches',
|
|
177
|
+
reason: r?.reason ?? 'matches the expected expense',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
relevant.push(file);
|
|
181
|
+
}
|
|
182
|
+
let sum_actual = 0;
|
|
183
|
+
const date_violations = [];
|
|
184
|
+
const missing_totals = [];
|
|
185
|
+
for (const file of relevant) {
|
|
186
|
+
const fields = file.extracted_fields;
|
|
187
|
+
if (!fields || typeof fields.total !== 'number') {
|
|
188
|
+
missing_totals.push({ file_id: file.file_id, name: file.file_name ?? file.file_id });
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
sum_actual += fields.total;
|
|
192
|
+
if (date_range && fields.date && !date_in_range(fields.date, date_range)) {
|
|
193
|
+
date_violations.push({ file_id: file.file_id, name: file.file_name ?? file.file_id, date: fields.date });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const delta = +(sum_actual - sum_expected).toFixed(2);
|
|
197
|
+
const within_tolerance = Math.abs(delta) <= tolerance;
|
|
198
|
+
const passed = within_tolerance &&
|
|
199
|
+
date_violations.length === 0 &&
|
|
200
|
+
missing_totals.length === 0 &&
|
|
201
|
+
off_topic_type.length === 0 &&
|
|
202
|
+
mismatched.length === 0 &&
|
|
203
|
+
unclear.length === 0;
|
|
204
|
+
const expected_str = format_currency(sum_expected, currency);
|
|
205
|
+
const actual_str = format_currency(sum_actual, currency);
|
|
206
|
+
// Build structured bullet list. Sum status comes first, then each excluded
|
|
207
|
+
// file gets its own bullet so the client can see exactly which file is the
|
|
208
|
+
// problem.
|
|
209
|
+
const details = [];
|
|
210
|
+
if (passed) {
|
|
211
|
+
details.push({
|
|
212
|
+
kind: 'sum',
|
|
213
|
+
severity: 'success',
|
|
214
|
+
message: `Receipts add up to ${expected_str} — matches the expected total.`,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
else if (within_tolerance) {
|
|
218
|
+
details.push({
|
|
219
|
+
kind: 'sum',
|
|
220
|
+
severity: 'success',
|
|
221
|
+
message: `Sum matches ${expected_str}.`,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const short = delta < 0;
|
|
226
|
+
const gap = format_currency(Math.abs(delta), currency);
|
|
227
|
+
const message = short
|
|
228
|
+
? `So far we've received receipts totalling ${actual_str}, but the expected total is ${expected_str}. Please provide additional receipt(s) covering the remaining ${gap}.`
|
|
229
|
+
: `Receipts uploaded so far total ${actual_str}, which exceeds the expected ${expected_str} by ${gap}. Please confirm whether all of these belong to the requested expense.`;
|
|
230
|
+
details.push({
|
|
231
|
+
kind: 'sum',
|
|
232
|
+
severity: 'warning',
|
|
233
|
+
message,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
for (const o of off_topic_type) {
|
|
237
|
+
details.push({
|
|
238
|
+
kind: 'off_topic',
|
|
239
|
+
severity: 'warning',
|
|
240
|
+
message: `looks like a ${format_doc_type(o.document_type)}, not a receipt — not counted toward the total`,
|
|
241
|
+
file_id: o.file_id,
|
|
242
|
+
file_name: o.name,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
for (const m of mismatched) {
|
|
246
|
+
details.push({
|
|
247
|
+
kind: 'mismatch',
|
|
248
|
+
severity: 'warning',
|
|
249
|
+
message: m.reason,
|
|
250
|
+
file_id: m.file_id,
|
|
251
|
+
file_name: m.name,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
for (const u of unclear) {
|
|
255
|
+
details.push({
|
|
256
|
+
kind: 'unclear',
|
|
257
|
+
severity: 'info',
|
|
258
|
+
message: u.reason,
|
|
259
|
+
file_id: u.file_id,
|
|
260
|
+
file_name: u.name,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
for (const d of date_violations) {
|
|
264
|
+
details.push({
|
|
265
|
+
kind: 'date_violation',
|
|
266
|
+
severity: 'warning',
|
|
267
|
+
message: `dated ${d.date}, outside the expected range`,
|
|
268
|
+
file_id: d.file_id,
|
|
269
|
+
file_name: d.name,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
for (const m of missing_totals) {
|
|
273
|
+
details.push({
|
|
274
|
+
kind: 'missing_total',
|
|
275
|
+
severity: 'info',
|
|
276
|
+
message: `couldn't read a total from this file — please confirm it's the right one`,
|
|
277
|
+
file_id: m.file_id,
|
|
278
|
+
file_name: m.name,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
// Plain-string summary kept for fallback rendering / logs.
|
|
282
|
+
const all_excluded = relevant.length === 0 && (off_topic_type.length > 0 || mismatched.length > 0);
|
|
283
|
+
let summary;
|
|
284
|
+
if (passed) {
|
|
285
|
+
summary = `Receipts add up to ${expected_str} — matches the expected total.`;
|
|
286
|
+
}
|
|
287
|
+
else if (all_excluded) {
|
|
288
|
+
summary = `None of the uploaded files look like receipts for the expected expense.`;
|
|
289
|
+
}
|
|
290
|
+
else if (!within_tolerance) {
|
|
291
|
+
const short = delta < 0;
|
|
292
|
+
const gap = format_currency(Math.abs(delta), currency);
|
|
293
|
+
summary = short
|
|
294
|
+
? `Receipts so far total ${actual_str} of the expected ${expected_str} — short by ${gap}.`
|
|
295
|
+
: `Receipts so far total ${actual_str}, which exceeds the expected ${expected_str} by ${gap}.`;
|
|
296
|
+
}
|
|
297
|
+
else if (date_violations.length > 0) {
|
|
298
|
+
summary = `Sum matches ${expected_str} but some receipts are outside the expected date range.`;
|
|
299
|
+
}
|
|
300
|
+
else if (missing_totals.length > 0) {
|
|
301
|
+
summary = `Could not read totals from one or more files.`;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
summary = `Receipts add up to ${actual_str}, expected ${expected_str}.`;
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
passed,
|
|
308
|
+
delta,
|
|
309
|
+
sum_actual: +sum_actual.toFixed(2),
|
|
310
|
+
sum_expected,
|
|
311
|
+
summary,
|
|
312
|
+
details,
|
|
313
|
+
file_relevance,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
// ============================================================================
|
|
317
|
+
// Public entrypoint
|
|
318
|
+
// ============================================================================
|
|
319
|
+
/**
|
|
320
|
+
* Run the two-step resolver.
|
|
321
|
+
*
|
|
322
|
+
* Step 1 — LLM commentary + relevance (best-effort, optional)
|
|
323
|
+
* Step 2 — deterministic math, gated by relevance verdicts
|
|
324
|
+
*
|
|
325
|
+
* Commentary runs first so its per-file relevance can influence which files
|
|
326
|
+
* count toward the sum. When the LLM is unavailable or fails, relevance is
|
|
327
|
+
* empty and the deterministic step runs with type-filter only — preserving
|
|
328
|
+
* the prior behaviour as a graceful fallback.
|
|
329
|
+
*/
|
|
330
|
+
export async function run_resolution(input, options = {}) {
|
|
331
|
+
const tolerance = options.tolerance ?? DEFAULT_TOLERANCE;
|
|
332
|
+
const commentary_timeout_ms = options.commentary_timeout_ms ?? 5000;
|
|
333
|
+
const on_error = options.on_error ?? ((err, ctx) => console.error(`[resolution] ${ctx}:`, err));
|
|
334
|
+
let file_notes = {};
|
|
335
|
+
let relevance = {};
|
|
336
|
+
if (options.commentary_fn) {
|
|
337
|
+
// Pre-deterministic estimate so commentary can reason about the gap.
|
|
338
|
+
// Excludes mismatch logic (relevance isn't known yet) — close enough.
|
|
339
|
+
const preview = preview_sum(input);
|
|
340
|
+
try {
|
|
341
|
+
const commentary = await run_with_timeout(options.commentary_fn({
|
|
342
|
+
expectation: input.expectation,
|
|
343
|
+
files: input.response_files,
|
|
344
|
+
verdict: {
|
|
345
|
+
sum_actual: preview.sum_actual,
|
|
346
|
+
sum_expected: preview.sum_expected,
|
|
347
|
+
delta: preview.delta,
|
|
348
|
+
},
|
|
349
|
+
}), commentary_timeout_ms);
|
|
350
|
+
if (commentary) {
|
|
351
|
+
file_notes = commentary.file_notes ?? {};
|
|
352
|
+
relevance = commentary.relevance ?? {};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (err) {
|
|
356
|
+
on_error(err, 'commentary step failed (continuing with deterministic verdict)');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const verdict = run_deterministic(input, tolerance, relevance);
|
|
360
|
+
return {
|
|
361
|
+
passed: verdict.passed,
|
|
362
|
+
delta: verdict.delta,
|
|
363
|
+
sum_actual: verdict.sum_actual,
|
|
364
|
+
sum_expected: verdict.sum_expected,
|
|
365
|
+
file_notes,
|
|
366
|
+
file_relevance: verdict.file_relevance,
|
|
367
|
+
summary: verdict.summary,
|
|
368
|
+
details: verdict.details,
|
|
369
|
+
ran_at: new Date().toISOString(),
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Best-effort sum used by the commentary step. Excludes type-incompatible
|
|
374
|
+
* files (bank statements etc.) but includes all others — relevance is decided
|
|
375
|
+
* downstream of this number.
|
|
376
|
+
*/
|
|
377
|
+
function preview_sum(input) {
|
|
378
|
+
const sum_expected = input.expectation.kind === 'sum_match' ? input.expectation.amount : 0;
|
|
379
|
+
let sum_actual = 0;
|
|
380
|
+
for (const file of input.response_files) {
|
|
381
|
+
if (!is_acceptable_for_sum_match(file.document_type))
|
|
382
|
+
continue;
|
|
383
|
+
if (nature_denylist_match(file.document_nature))
|
|
384
|
+
continue;
|
|
385
|
+
const t = file.extracted_fields?.total;
|
|
386
|
+
if (typeof t === 'number')
|
|
387
|
+
sum_actual += t;
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
sum_actual: +sum_actual.toFixed(2),
|
|
391
|
+
sum_expected,
|
|
392
|
+
delta: +(sum_actual - sum_expected).toFixed(2),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Creates a POST route handler that wraps run_resolution. Mirrors the factory
|
|
397
|
+
* pattern used by validation_handler / classification_handler / autofill_handler.
|
|
398
|
+
*/
|
|
399
|
+
export function create_resolution_route(options = {}) {
|
|
400
|
+
const on_error = options.on_error ?? ((err, ctx) => console.error(`[resolution] ${ctx}:`, err));
|
|
401
|
+
return async function POST(request) {
|
|
402
|
+
try {
|
|
403
|
+
const body = await request.json();
|
|
404
|
+
if (!body || !body.expectation) {
|
|
405
|
+
return Response.json({ success: false, error: 'expectation is required' }, { status: 400 });
|
|
406
|
+
}
|
|
407
|
+
if (!Array.isArray(body.response_files)) {
|
|
408
|
+
return Response.json({ success: false, error: 'response_files must be an array' }, { status: 400 });
|
|
409
|
+
}
|
|
410
|
+
const check = await run_resolution({ expectation: body.expectation, response_files: body.response_files }, options);
|
|
411
|
+
return Response.json({ success: true, check });
|
|
412
|
+
}
|
|
413
|
+
catch (err) {
|
|
414
|
+
on_error(err, 'unhandled error');
|
|
415
|
+
return Response.json({ success: false, error: err instanceof Error ? err.message : 'Unknown error' }, { status: 500 });
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Build a commentary_fn that calls hazo_llm_api with the resolve_clarification_relevance
|
|
421
|
+
* prompt, attaching every inspectable response file inline. Wire this into
|
|
422
|
+
* `create_resolution_route({ commentary_fn: create_llm_commentary_fn(...) })`.
|
|
423
|
+
*
|
|
424
|
+
* The returned function is best-effort: any failure (LLM error, JSON parse
|
|
425
|
+
* fail, missing prompt) returns `null` so the resolver falls back to the
|
|
426
|
+
* deterministic-only verdict.
|
|
427
|
+
*/
|
|
428
|
+
export function create_llm_commentary_fn(options) {
|
|
429
|
+
const on_error = options.on_error ?? ((err, ctx) => console.error(`[resolution-commentary] ${ctx}:`, err));
|
|
430
|
+
// Lazy-loaded module reference + init guard, copied from classification_handler.
|
|
431
|
+
let llm_api_module = null;
|
|
432
|
+
let init_promise = null;
|
|
433
|
+
async function get_llm_api() {
|
|
434
|
+
if (!llm_api_module) {
|
|
435
|
+
const module_id = 'hazo_llm_api/server';
|
|
436
|
+
llm_api_module = await import(/* webpackIgnore: true */ module_id);
|
|
437
|
+
}
|
|
438
|
+
return llm_api_module;
|
|
439
|
+
}
|
|
440
|
+
async function ensure_initialized() {
|
|
441
|
+
const api = await get_llm_api();
|
|
442
|
+
if (!api.is_initialized()) {
|
|
443
|
+
if (!init_promise) {
|
|
444
|
+
const init_config = options.hazo_connect_adapter
|
|
445
|
+
? { hazo_connect_adapter: options.hazo_connect_adapter }
|
|
446
|
+
: { sqlite_path: options.sqlite_path };
|
|
447
|
+
init_promise = api.initialize_llm_api(init_config).then(() => { });
|
|
448
|
+
}
|
|
449
|
+
await init_promise;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return async function commentary_fn(input) {
|
|
453
|
+
try {
|
|
454
|
+
await ensure_initialized();
|
|
455
|
+
const api = await get_llm_api();
|
|
456
|
+
// Fetch the prompt text from hazo_prompts.
|
|
457
|
+
const connect = api.get_hazo_connect?.() ?? null;
|
|
458
|
+
if (!connect) {
|
|
459
|
+
on_error(new Error('hazo_connect not available'), 'prompt lookup');
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
const lookup = await connect.get_by_area_key(options.prompt_area, options.prompt_key);
|
|
463
|
+
const db_prompt = lookup.success ? lookup.data?.prompt_text_full : undefined;
|
|
464
|
+
if (!db_prompt) {
|
|
465
|
+
on_error(new Error(`prompt ${options.prompt_area}/${options.prompt_key} missing`), 'prompt lookup');
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
// Render variables.
|
|
469
|
+
const exp = input.expectation;
|
|
470
|
+
const ctx = exp.kind === 'sum_match' ? exp.context : undefined;
|
|
471
|
+
const description = exp.kind === 'sum_match' ? exp.description : undefined;
|
|
472
|
+
const expected_amount = exp.kind === 'sum_match'
|
|
473
|
+
? format_currency(exp.amount, exp.currency)
|
|
474
|
+
: 'n/a';
|
|
475
|
+
const expected_date_range = exp.kind === 'sum_match' && exp.date_range
|
|
476
|
+
? `${exp.date_range.from} to ${exp.date_range.to}`
|
|
477
|
+
: 'n/a';
|
|
478
|
+
const files_summary = input.files
|
|
479
|
+
.map(f => {
|
|
480
|
+
const lines = [`file_id: ${f.file_id}`, `filename: ${f.file_name ?? '(unnamed)'}`];
|
|
481
|
+
if (f.document_type)
|
|
482
|
+
lines.push(`classified as: ${f.document_type}`);
|
|
483
|
+
if (f.document_nature)
|
|
484
|
+
lines.push(`document_nature: ${f.document_nature}`);
|
|
485
|
+
const ef = f.extracted_fields;
|
|
486
|
+
if (ef) {
|
|
487
|
+
const parts = [];
|
|
488
|
+
if (typeof ef.total === 'number')
|
|
489
|
+
parts.push(`total=${ef.total}`);
|
|
490
|
+
if (ef.date)
|
|
491
|
+
parts.push(`date=${ef.date}`);
|
|
492
|
+
if (ef.vendor)
|
|
493
|
+
parts.push(`vendor=${ef.vendor}`);
|
|
494
|
+
if (ef.property_address)
|
|
495
|
+
parts.push(`property_address=${ef.property_address}`);
|
|
496
|
+
if (parts.length > 0)
|
|
497
|
+
lines.push(`extracted: ${parts.join(', ')}`);
|
|
498
|
+
}
|
|
499
|
+
return lines.join('\n');
|
|
500
|
+
})
|
|
501
|
+
.join('\n\n');
|
|
502
|
+
const prompt_text = substitute(db_prompt, {
|
|
503
|
+
expectation_description: description ?? '(no description provided)',
|
|
504
|
+
expected_amount,
|
|
505
|
+
expected_date_range,
|
|
506
|
+
property_address: ctx?.property_address ?? 'n/a',
|
|
507
|
+
vendor_hint: ctx?.vendor_hint ?? 'n/a',
|
|
508
|
+
expense_label: ctx?.expense_label ?? 'n/a',
|
|
509
|
+
files_summary: files_summary || '(no files)',
|
|
510
|
+
});
|
|
511
|
+
// Attach file contents. The first inspectable file becomes the primary
|
|
512
|
+
// document; the rest go in additional_documents. Files without b64 are
|
|
513
|
+
// skipped — the prompt's files_summary still references them by id.
|
|
514
|
+
const inspectable = input.files.filter(f => !!f.file_b64 && !!f.mime_type);
|
|
515
|
+
if (inspectable.length === 0) {
|
|
516
|
+
on_error(new Error('no inspectable files (b64 missing)'), 'attachment build');
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
const [primary, ...rest] = inspectable;
|
|
520
|
+
const response = await api.hazo_llm_document_text({
|
|
521
|
+
prompt: prompt_text,
|
|
522
|
+
document_b64: primary.file_b64,
|
|
523
|
+
document_mime_type: primary.mime_type,
|
|
524
|
+
...(rest.length > 0
|
|
525
|
+
? {
|
|
526
|
+
additional_documents: rest.map(f => ({
|
|
527
|
+
mime_type: f.mime_type,
|
|
528
|
+
data: f.file_b64,
|
|
529
|
+
})),
|
|
530
|
+
}
|
|
531
|
+
: {}),
|
|
532
|
+
});
|
|
533
|
+
if (!response.success || !response.text) {
|
|
534
|
+
on_error(response.error ?? new Error('LLM call failed'), 'llm call');
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
// Parse JSON, tolerating fenced code blocks the LLM sometimes adds.
|
|
538
|
+
const parsed = parse_commentary_json(response.text);
|
|
539
|
+
if (!parsed) {
|
|
540
|
+
on_error(new Error('JSON parse failed'), 'response parsing');
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
return parsed;
|
|
544
|
+
}
|
|
545
|
+
catch (err) {
|
|
546
|
+
on_error(err, 'commentary_fn');
|
|
547
|
+
return null;
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
function substitute(prompt, vars) {
|
|
552
|
+
return prompt.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
553
|
+
}
|
|
554
|
+
function parse_commentary_json(text) {
|
|
555
|
+
const cleaned = text.trim();
|
|
556
|
+
const candidates = [cleaned];
|
|
557
|
+
const fence = cleaned.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
558
|
+
if (fence)
|
|
559
|
+
candidates.push(fence[1].trim());
|
|
560
|
+
const obj = cleaned.match(/\{[\s\S]*\}/);
|
|
561
|
+
if (obj)
|
|
562
|
+
candidates.push(obj[0]);
|
|
563
|
+
for (const candidate of candidates) {
|
|
564
|
+
try {
|
|
565
|
+
const parsed = JSON.parse(candidate);
|
|
566
|
+
if (parsed && typeof parsed === 'object') {
|
|
567
|
+
const file_notes = (parsed.file_notes && typeof parsed.file_notes === 'object')
|
|
568
|
+
? parsed.file_notes
|
|
569
|
+
: {};
|
|
570
|
+
const relevance = (parsed.relevance && typeof parsed.relevance === 'object')
|
|
571
|
+
? sanitize_relevance(parsed.relevance)
|
|
572
|
+
: {};
|
|
573
|
+
const overall_note = typeof parsed.overall_note === 'string' ? parsed.overall_note : undefined;
|
|
574
|
+
return { file_notes, relevance, overall_note };
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
catch {
|
|
578
|
+
// Try the next candidate.
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
function sanitize_relevance(raw) {
|
|
584
|
+
const out = {};
|
|
585
|
+
for (const [file_id, value] of Object.entries(raw)) {
|
|
586
|
+
if (!value || typeof value !== 'object')
|
|
587
|
+
continue;
|
|
588
|
+
const v = value;
|
|
589
|
+
const verdict = v.verdict;
|
|
590
|
+
const reason = typeof v.reason === 'string' ? v.reason : '';
|
|
591
|
+
if (verdict === 'matches' || verdict === 'mismatch' || verdict === 'unclear') {
|
|
592
|
+
out[file_id] = { verdict, reason };
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return out;
|
|
596
|
+
}
|
|
597
|
+
//# sourceMappingURL=resolution_handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution_handler.js","sourceRoot":"","sources":["../../src/lib/resolution_handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve variable references (e.g. `@tenant_start_date`, `@Beginning_Of_Tax_Year`)
|
|
3
|
+
* against the active form data and session-level constants.
|
|
4
|
+
*
|
|
5
|
+
* Variable syntax: `@<name>`. Resolution order:
|
|
6
|
+
* 1. Session vars (by key name) — tax-year boundaries, client name, etc.
|
|
7
|
+
* 2. Form-field values — looked up by `question_field_id` in `FbFormData.data[]`.
|
|
8
|
+
*
|
|
9
|
+
* Empty-string and whitespace-only values are treated as null so a chain like
|
|
10
|
+
* ['@tenant_start_date', '@Beginning_Of_Tax_Year']
|
|
11
|
+
* falls through to the fallback when the user has not yet entered a tenant date.
|
|
12
|
+
*/
|
|
13
|
+
import type { VariableChain } from '../types/validation.js';
|
|
14
|
+
import type { FbFormData } from '../types/fb_form_data.js';
|
|
15
|
+
/** Session-level constants (tax year boundaries, client name, etc.). */
|
|
16
|
+
export type SessionVars = Record<string, string | null | undefined>;
|
|
17
|
+
export interface ResolveContext {
|
|
18
|
+
form_data: FbFormData | null;
|
|
19
|
+
session: SessionVars;
|
|
20
|
+
}
|
|
21
|
+
/** Resolve a single variable reference. Returns the value or null if unresolved/empty. */
|
|
22
|
+
export declare function resolve_variable(ref: string, ctx: ResolveContext): string | null;
|
|
23
|
+
/** Walk the chain. Return the first non-empty resolved value, or null if none resolve. */
|
|
24
|
+
export declare function resolve_variable_chain(chain: VariableChain, ctx: ResolveContext): string | null;
|
|
25
|
+
//# sourceMappingURL=resolve_variable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve_variable.d.ts","sourceRoot":"","sources":["../../src/lib/resolve_variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,0BAA0B,CAAC;AAE1E,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAehF;AAED,0FAA0F;AAC1F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAM/F"}
|