@dizzlkheinz/ynab-mcpb 0.12.1
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/.chunkhound.json +11 -0
- package/.code/agents/0427d95e-edca-431f-a214-5e53264e29c4/error.txt +8 -0
- package/.code/agents/0d675174-d1e1-41c3-9975-4c2e275819a9/error.txt +3 -0
- package/.code/agents/0d8c5afd-4787-422b-abf8-2e5943fc7e67/error.txt +3 -0
- package/.code/agents/0ec34a70-ed5d-4b9e-bee4-bb0e4cccbc4b/error.txt +1 -0
- package/.code/agents/0ef51a21-1ab1-49d7-9561-0eaa43875ebc/error.txt +12 -0
- package/.code/agents/15db95d7-abad-4b4d-9c3b-8446089cb61d/error.txt +1 -0
- package/.code/agents/19ab9acb-f675-4ff0-902a-09a5476f8149/error.txt +1 -0
- package/.code/agents/1ef7e12d-f6ff-4897-8a9b-152d523d898e/error.txt +5 -0
- package/.code/agents/2465/exec-call_lroN9KKzJVWC7t5423DK1nT9.txt +1453 -0
- package/.code/agents/28edb6fe-95a9-41a0-ae69-aa0100d26c0c/error.txt +8 -0
- package/.code/agents/2ae40cf5-b4bf-42e2-92bf-7ea350a7755e/error.txt +9 -0
- package/.code/agents/2bfc4e1f-ac4b-45a5-b6df-bf89d4dbb54c/error.txt +1 -0
- package/.code/agents/2e2e1134-eff0-49be-ba25-8e2c3468a564/error.txt +5 -0
- package/.code/agents/3/exec-call_203OC4TNVkLxW7z2HCVEQ1cM.txt +81 -0
- package/.code/agents/3/exec-call_SS5T0XSiXB4LSNzUKTl75wkh.txt +610 -0
- package/.code/agents/3322c003-ce5e-48e3-a342-f5049c5bf9a2/error.txt +1 -0
- package/.code/agents/391e9b08-1ebc-468c-9bcd-6d0cc3193b37/error.txt +1 -0
- package/.code/agents/3ab0aa84-b7bb-4054-afa3-40b8fd7d3be0/error.txt +1 -0
- package/.code/agents/3bed368d-50fe-477e-aee3-a6707eaa1ab9/error.txt +3 -0
- package/.code/agents/3e40b925-db12-442f-8d7a-a25fc69a6672/error.txt +8 -0
- package/.code/agents/414d5776-cf58-41f3-9328-a6daed503a50/error.txt +5 -0
- package/.code/agents/42687751-4565-4610-b240-67835b17d861/error.txt +1 -0
- package/.code/agents/46b98876-1a39-43c9-9e2f-507ca6d47335/error.txt +9 -0
- package/.code/agents/4a7d9491-b26f-43dd-850d-2ecdc49b5d1b/error.txt +1 -0
- package/.code/agents/4e60f00a-1b3e-447f-87f3-7faf9deddec3/error.txt +13 -0
- package/.code/agents/5138fc1c-4d49-4b74-a7da-ccdb3a8e44e7/error.txt +14 -0
- package/.code/agents/521cff39-a7a3-42e5-a557-134f0f7daaa0/error.txt +5 -0
- package/.code/agents/53302dc5-3857-4413-9a47-9e0f64a51dc4/error.txt +5 -0
- package/.code/agents/567c7c2e-6a6f-4761-a08d-d36deeb2e0ac/error.txt +5 -0
- package/.code/agents/57b00845-80dc-47c9-953c-3028d16275d6/error.txt +3 -0
- package/.code/agents/593d9005-c2a5-48fd-8813-ece0d3f2de96/error.txt +1 -0
- package/.code/agents/5a112e66-0e1a-42f9-877c-53af56ea3551/error.txt +1 -0
- package/.code/agents/5b05e8ed-7788-4738-b7ee-9faa8180f992/error.txt +5 -0
- package/.code/agents/5f888d6f-d7ca-4ac8-be23-9ea1bf753951/error.txt +5 -0
- package/.code/agents/607db3ab-e4b0-435b-b497-93e9aa525549/error.txt +8 -0
- package/.code/agents/67dcb2a2-900f-4c78-b3fc-80b5213e0ddf/error.txt +8 -0
- package/.code/agents/69ad848c-4e98-49b3-b16c-0094ac2d1759/error.txt +5 -0
- package/.code/agents/6c9cfc5f-0d0b-445c-b121-9f60082c4f70/error.txt +1 -0
- package/.code/agents/6f6f8f77-4ab0-4f6e-9f30-40e8be0bd8f5/error.txt +1 -0
- package/.code/agents/72a7cde4-fa8a-4024-9038-27faa550539b/error.txt +1 -0
- package/.code/agents/7b48335c-8247-43aa-9949-5f820ba8e199/error.txt +1 -0
- package/.code/agents/80944249-bea9-4ac5-87de-a666c4df306e/error.txt +1 -0
- package/.code/agents/826099df-1b66-4186-a915-7eb59f9db19d/error.txt +5 -0
- package/.code/agents/8291d158-18a8-4a92-b799-4e9a4d9cce88/error.txt +1 -0
- package/.code/agents/82fb71a3-20fb-4341-804a-a2fc900f95bc/error.txt +1 -0
- package/.code/agents/855790ea-54ee-43e4-8209-a66994e37590/error.txt +1 -0
- package/.code/agents/88ce3a2e-04f2-42be-9062-bf97aa798da0/error.txt +3 -0
- package/.code/agents/9a17e398-b6ed-4218-bb55-bc64a8d38ce8/error.txt +8 -0
- package/.code/agents/9a4f4bfc-a2a6-4f40-a896-9335b41a7ed1/error.txt +1 -0
- package/.code/agents/9b633e55-ef84-47d6-94bb-fd3dd172ad97/error.txt +1 -0
- package/.code/agents/9b81f3ab-c72b-4a81-9a8f-28a49ddba84a/error.txt +8 -0
- package/.code/agents/a35daf29-b2d1-4aef-9b42-dad63a76bd47/error.txt +3 -0
- package/.code/agents/a81990cc-69ee-44d2-b907-17403c9bc5d7/error.txt +5 -0
- package/.code/agents/ab56260a-4a83-4ad4-9410-f88a23d6520a/error.txt +1 -0
- package/.code/agents/ad722c31-2d1d-45f7-bae2-3f02ca455b60/error.txt +1 -0
- package/.code/agents/b62e8690-3324-4b97-9309-731bee79416b/error.txt +5 -0
- package/.code/agents/baf60a3a-752b-4ad8-99d6-df32423ed2eb/error.txt +1 -0
- package/.code/agents/be049042-7dcb-4ac8-9beb-c8f1aea67742/error.txt +14 -0
- package/.code/agents/bed1dcb4-bfce-4a9f-8594-0f994962aafd/error.txt +1 -0
- package/.code/agents/c324a6cf-e935-4ede-9529-b3ebc18e8d6b/error.txt +5 -0
- package/.code/agents/c37c06ff-dfe3-43f2-9bbc-3ec73ec8f41d/error.txt +5 -0
- package/.code/agents/c8cd6671-433a-456b-9f88-e51cb2df6bfc/error.txt +11 -0
- package/.code/agents/ca2ccb67-2f24-428e-b27d-9365beadd140/error.txt +1 -0
- package/.code/agents/cf08c0c8-e7f0-423e-93ba-547e8e818340/error.txt +8 -0
- package/.code/agents/d579c74f-874b-40a4-9d56-ced1eb6a701d/error.txt +1 -0
- package/.code/agents/df412c98-7378-4deb-8e1e-76c416931181/error.txt +3 -0
- package/.code/agents/e5134eb3-2af4-45b0-8998-051cb4afdb45/error.txt +3 -0
- package/.code/agents/e6308471-aa45-4e9e-9496-2e9404164d97/error.txt +8 -0
- package/.code/agents/e7bd8bc7-23fb-4f46-98dc-b0dcf11b75a1/error.txt +1 -0
- package/.code/agents/e92bec35-378d-4fe1-8ac0-6e1bb3c86911/error.txt +5 -0
- package/.code/agents/ed918fbf-2dc4-4aa2-bfc5-04b65d9471ea/error.txt +1 -0
- package/.code/agents/ef1d756f-b272-48fc-8729-f05c494674f7/error.txt +1 -0
- package/.code/agents/ef359853-0249-4e41-a804-c0fc459fe456/error.txt +1 -0
- package/.code/agents/effc7b4a-4b90-40a0-8c86-a7a99d2d5fd2/error.txt +1 -0
- package/.code/agents/fa15f8d5-8359-4a8b-83a3-2f2056b3ff40/error.txt +3 -0
- package/.code/agents/fbef4193-eadf-4c8a-83ff-4878a6310f25/error.txt +8 -0
- package/.code/agents/fd0a4b4a-fda4-4964-a6d6-2b8a2da387c6/error.txt +1 -0
- package/.dxtignore +57 -0
- package/.env.example +44 -0
- package/.gemini/settings.json +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- package/.github/ISSUE_TEMPLATE/release_checklist.md +31 -0
- package/.github/pull_request_template.md +41 -0
- package/.github/workflows/ci-tests.yml +41 -0
- package/.github/workflows/claude-code-review.yml +57 -0
- package/.github/workflows/claude.yml +50 -0
- package/.github/workflows/full-integration.yml +22 -0
- package/.github/workflows/pr-description-check.yml +88 -0
- package/.github/workflows/publish.yml +33 -0
- package/.github/workflows/release.yml +89 -0
- package/.mcpbignore +58 -0
- package/.prettierignore +10 -0
- package/.prettierrc.json +10 -0
- package/ADOS-2-Module-1-Complete-Manual.md +757 -0
- package/AGENTS.md +36 -0
- package/CHANGELOG.md +187 -0
- package/CLAUDE.md +414 -0
- package/CODEREVIEW_RESPONSE.md +128 -0
- package/LICENSE +17 -0
- package/NUL +1 -0
- package/README.md +222 -0
- package/SCHEMA_IMPROVEMENT_SUMMARY.md +120 -0
- package/TESTING_NOTES.md +217 -0
- package/WARP.md +245 -0
- package/accountactivity-merged.csv +149 -0
- package/bin/ynab-mcp-server.cjs +4 -0
- package/bin/ynab-mcp-server.js +8 -0
- package/bundle-analysis.html +13110 -0
- package/dist/bundle/index.cjs +124 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +85 -0
- package/dist/server/YNABMCPServer.d.ts +264 -0
- package/dist/server/YNABMCPServer.js +845 -0
- package/dist/server/budgetResolver.d.ts +15 -0
- package/dist/server/budgetResolver.js +99 -0
- package/dist/server/cacheManager.d.ts +74 -0
- package/dist/server/cacheManager.js +306 -0
- package/dist/server/config.d.ts +3 -0
- package/dist/server/config.js +19 -0
- package/dist/server/deltaCache.d.ts +61 -0
- package/dist/server/deltaCache.js +206 -0
- package/dist/server/deltaCache.merge.d.ts +9 -0
- package/dist/server/deltaCache.merge.js +111 -0
- package/dist/server/diagnostics.d.ts +90 -0
- package/dist/server/diagnostics.js +163 -0
- package/dist/server/errorHandler.d.ts +69 -0
- package/dist/server/errorHandler.js +524 -0
- package/dist/server/prompts.d.ts +31 -0
- package/dist/server/prompts.js +205 -0
- package/dist/server/rateLimiter.d.ts +27 -0
- package/dist/server/rateLimiter.js +82 -0
- package/dist/server/requestLogger.d.ts +62 -0
- package/dist/server/requestLogger.js +190 -0
- package/dist/server/resources.d.ts +39 -0
- package/dist/server/resources.js +85 -0
- package/dist/server/responseFormatter.d.ts +14 -0
- package/dist/server/responseFormatter.js +42 -0
- package/dist/server/securityMiddleware.d.ts +87 -0
- package/dist/server/securityMiddleware.js +117 -0
- package/dist/server/serverKnowledgeStore.d.ts +11 -0
- package/dist/server/serverKnowledgeStore.js +42 -0
- package/dist/server/toolRegistry.d.ts +85 -0
- package/dist/server/toolRegistry.js +272 -0
- package/dist/tools/__tests__/deltaTestUtils.d.ts +18 -0
- package/dist/tools/__tests__/deltaTestUtils.js +26 -0
- package/dist/tools/accountTools.d.ts +37 -0
- package/dist/tools/accountTools.js +175 -0
- package/dist/tools/budgetTools.d.ts +10 -0
- package/dist/tools/budgetTools.js +68 -0
- package/dist/tools/categoryTools.d.ts +27 -0
- package/dist/tools/categoryTools.js +232 -0
- package/dist/tools/compareTransactions/formatter.d.ts +71 -0
- package/dist/tools/compareTransactions/formatter.js +97 -0
- package/dist/tools/compareTransactions/index.d.ts +30 -0
- package/dist/tools/compareTransactions/index.js +160 -0
- package/dist/tools/compareTransactions/matcher.d.ts +12 -0
- package/dist/tools/compareTransactions/matcher.js +140 -0
- package/dist/tools/compareTransactions/parser.d.ts +14 -0
- package/dist/tools/compareTransactions/parser.js +430 -0
- package/dist/tools/compareTransactions/types.d.ts +27 -0
- package/dist/tools/compareTransactions/types.js +1 -0
- package/dist/tools/compareTransactions.d.ts +1 -0
- package/dist/tools/compareTransactions.js +1 -0
- package/dist/tools/deltaFetcher.d.ts +22 -0
- package/dist/tools/deltaFetcher.js +137 -0
- package/dist/tools/deltaSupport.d.ts +20 -0
- package/dist/tools/deltaSupport.js +176 -0
- package/dist/tools/exportTransactions.d.ts +17 -0
- package/dist/tools/exportTransactions.js +191 -0
- package/dist/tools/monthTools.d.ts +16 -0
- package/dist/tools/monthTools.js +107 -0
- package/dist/tools/payeeTools.d.ts +17 -0
- package/dist/tools/payeeTools.js +82 -0
- package/dist/tools/reconcileAdapter.d.ts +25 -0
- package/dist/tools/reconcileAdapter.js +167 -0
- package/dist/tools/reconciliation/analyzer.d.ts +3 -0
- package/dist/tools/reconciliation/analyzer.js +567 -0
- package/dist/tools/reconciliation/executor.d.ts +94 -0
- package/dist/tools/reconciliation/executor.js +611 -0
- package/dist/tools/reconciliation/index.d.ts +54 -0
- package/dist/tools/reconciliation/index.js +249 -0
- package/dist/tools/reconciliation/matcher.d.ts +3 -0
- package/dist/tools/reconciliation/matcher.js +160 -0
- package/dist/tools/reconciliation/payeeNormalizer.d.ts +6 -0
- package/dist/tools/reconciliation/payeeNormalizer.js +77 -0
- package/dist/tools/reconciliation/recommendationEngine.d.ts +2 -0
- package/dist/tools/reconciliation/recommendationEngine.js +273 -0
- package/dist/tools/reconciliation/reportFormatter.d.ts +13 -0
- package/dist/tools/reconciliation/reportFormatter.js +214 -0
- package/dist/tools/reconciliation/types.d.ts +172 -0
- package/dist/tools/reconciliation/types.js +7 -0
- package/dist/tools/schemas/outputs/accountOutputs.d.ts +58 -0
- package/dist/tools/schemas/outputs/accountOutputs.js +24 -0
- package/dist/tools/schemas/outputs/budgetOutputs.d.ts +48 -0
- package/dist/tools/schemas/outputs/budgetOutputs.js +15 -0
- package/dist/tools/schemas/outputs/categoryOutputs.d.ts +93 -0
- package/dist/tools/schemas/outputs/categoryOutputs.js +37 -0
- package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +269 -0
- package/dist/tools/schemas/outputs/comparisonOutputs.js +181 -0
- package/dist/tools/schemas/outputs/index.d.ts +14 -0
- package/dist/tools/schemas/outputs/index.js +14 -0
- package/dist/tools/schemas/outputs/monthOutputs.d.ts +122 -0
- package/dist/tools/schemas/outputs/monthOutputs.js +51 -0
- package/dist/tools/schemas/outputs/payeeOutputs.d.ts +34 -0
- package/dist/tools/schemas/outputs/payeeOutputs.js +16 -0
- package/dist/tools/schemas/outputs/reconciliationOutputs.d.ts +1275 -0
- package/dist/tools/schemas/outputs/reconciliationOutputs.js +377 -0
- package/dist/tools/schemas/outputs/transactionMutationOutputs.d.ts +717 -0
- package/dist/tools/schemas/outputs/transactionMutationOutputs.js +260 -0
- package/dist/tools/schemas/outputs/transactionOutputs.d.ts +98 -0
- package/dist/tools/schemas/outputs/transactionOutputs.js +49 -0
- package/dist/tools/schemas/outputs/utilityOutputs.d.ts +219 -0
- package/dist/tools/schemas/outputs/utilityOutputs.js +120 -0
- package/dist/tools/schemas/shared/commonOutputs.d.ts +24 -0
- package/dist/tools/schemas/shared/commonOutputs.js +27 -0
- package/dist/tools/toolCategories.d.ts +32 -0
- package/dist/tools/toolCategories.js +32 -0
- package/dist/tools/transactionTools.d.ts +315 -0
- package/dist/tools/transactionTools.js +1722 -0
- package/dist/tools/utilityTools.d.ts +10 -0
- package/dist/tools/utilityTools.js +56 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.js +16 -0
- package/dist/types/toolAnnotations.d.ts +7 -0
- package/dist/types/toolAnnotations.js +1 -0
- package/dist/utils/amountUtils.d.ts +3 -0
- package/dist/utils/amountUtils.js +10 -0
- package/dist/utils/dateUtils.d.ts +9 -0
- package/dist/utils/dateUtils.js +43 -0
- package/dist/utils/money.d.ts +21 -0
- package/dist/utils/money.js +51 -0
- package/docs/README.md +72 -0
- package/docs/assets/examples/reconciliation-with-recommendations.json +68 -0
- package/docs/assets/schemas/reconciliation-v2.json +338 -0
- package/docs/getting-started/CONFIGURATION.md +175 -0
- package/docs/getting-started/INSTALLATION.md +333 -0
- package/docs/getting-started/QUICKSTART.md +282 -0
- package/docs/guides/ARCHITECTURE.md +650 -0
- package/docs/guides/DEPLOYMENT.md +189 -0
- package/docs/guides/INTEGRATION_TESTING.md +730 -0
- package/docs/guides/TESTING.md +591 -0
- package/docs/reconciliation-flow.md +83 -0
- package/docs/reference/API.md +1450 -0
- package/docs/reference/EXAMPLES.md +946 -0
- package/docs/reference/TOOLS.md +348 -0
- package/docs/reference/TROUBLESHOOTING.md +481 -0
- package/esbuild.config.mjs +68 -0
- package/eslint.config.js +49 -0
- package/fix-types.sh +17 -0
- package/meta.json +12550 -0
- package/package.json +105 -0
- package/package.json.tmp +105 -0
- package/scripts/analyze-bundle.mjs +41 -0
- package/scripts/create-pr-description.js +203 -0
- package/scripts/generate-mcpb.ps1 +96 -0
- package/scripts/run-domain-integration-tests.js +33 -0
- package/scripts/run-generate-mcpb.js +29 -0
- package/scripts/run-throttled-integration-tests.js +116 -0
- package/scripts/test-delta-params.mjs +140 -0
- package/scripts/test-recommendations.ts +53 -0
- package/scripts/tmpTransaction.ts +48 -0
- package/scripts/validate-env.js +122 -0
- package/scripts/verify-build.js +105 -0
- package/scripts/watch-and-restart.ps1 +50 -0
- package/src/__tests__/comprehensive.integration.test.ts +1196 -0
- package/src/__tests__/delta.performance.test.ts +80 -0
- package/src/__tests__/performance.test.ts +725 -0
- package/src/__tests__/setup.ts +449 -0
- package/src/__tests__/testRunner.ts +444 -0
- package/src/__tests__/testUtils.ts +563 -0
- package/src/__tests__/workflows.e2e.test.ts +1675 -0
- package/src/index.ts +124 -0
- package/src/server/.gitkeep +1 -0
- package/src/server/YNABMCPServer.ts +1188 -0
- package/src/server/__tests__/YNABMCPServer.integration.test.ts +903 -0
- package/src/server/__tests__/YNABMCPServer.test.ts +894 -0
- package/src/server/__tests__/budgetResolver.test.ts +425 -0
- package/src/server/__tests__/cacheManager.test.ts +880 -0
- package/src/server/__tests__/config.test.ts +166 -0
- package/src/server/__tests__/deltaCache.merge.test.ts +724 -0
- package/src/server/__tests__/deltaCache.swr.test.ts +168 -0
- package/src/server/__tests__/deltaCache.test.ts +774 -0
- package/src/server/__tests__/diagnostics.test.ts +823 -0
- package/src/server/__tests__/errorHandler.integration.test.ts +466 -0
- package/src/server/__tests__/errorHandler.test.ts +416 -0
- package/src/server/__tests__/prompts.test.ts +354 -0
- package/src/server/__tests__/rateLimiter.test.ts +314 -0
- package/src/server/__tests__/requestLogger.test.ts +408 -0
- package/src/server/__tests__/resources.test.ts +299 -0
- package/src/server/__tests__/security.integration.test.ts +426 -0
- package/src/server/__tests__/securityMiddleware.test.ts +449 -0
- package/src/server/__tests__/server-startup.integration.test.ts +477 -0
- package/src/server/__tests__/serverKnowledgeStore.test.ts +174 -0
- package/src/server/__tests__/toolRegistry.test.ts +855 -0
- package/src/server/budgetResolver.ts +235 -0
- package/src/server/cacheManager.ts +503 -0
- package/src/server/config.ts +41 -0
- package/src/server/deltaCache.merge.ts +149 -0
- package/src/server/deltaCache.ts +341 -0
- package/src/server/diagnostics.ts +338 -0
- package/src/server/errorHandler.ts +756 -0
- package/src/server/prompts.ts +291 -0
- package/src/server/rateLimiter.ts +156 -0
- package/src/server/requestLogger.ts +344 -0
- package/src/server/resources.ts +168 -0
- package/src/server/responseFormatter.ts +51 -0
- package/src/server/securityMiddleware.ts +236 -0
- package/src/server/serverKnowledgeStore.ts +91 -0
- package/src/server/toolRegistry.ts +489 -0
- package/src/tools/.gitkeep +1 -0
- package/src/tools/__tests__/accountTools.delta.integration.test.ts +128 -0
- package/src/tools/__tests__/accountTools.integration.test.ts +117 -0
- package/src/tools/__tests__/accountTools.test.ts +653 -0
- package/src/tools/__tests__/budgetTools.delta.integration.test.ts +90 -0
- package/src/tools/__tests__/budgetTools.integration.test.ts +134 -0
- package/src/tools/__tests__/budgetTools.test.ts +423 -0
- package/src/tools/__tests__/categoryTools.delta.integration.test.ts +80 -0
- package/src/tools/__tests__/categoryTools.integration.test.ts +295 -0
- package/src/tools/__tests__/categoryTools.test.ts +622 -0
- package/src/tools/__tests__/compareTransactions/formatter.test.ts +486 -0
- package/src/tools/__tests__/compareTransactions/index.test.ts +383 -0
- package/src/tools/__tests__/compareTransactions/matcher.test.ts +410 -0
- package/src/tools/__tests__/compareTransactions/parser.test.ts +764 -0
- package/src/tools/__tests__/compareTransactions.test.ts +342 -0
- package/src/tools/__tests__/compareTransactions.window.test.ts +147 -0
- package/src/tools/__tests__/deltaFetcher.scheduled.integration.test.ts +76 -0
- package/src/tools/__tests__/deltaFetcher.test.ts +270 -0
- package/src/tools/__tests__/deltaSupport.test.ts +188 -0
- package/src/tools/__tests__/deltaTestUtils.ts +46 -0
- package/src/tools/__tests__/exportTransactions.test.ts +213 -0
- package/src/tools/__tests__/monthTools.delta.integration.test.ts +80 -0
- package/src/tools/__tests__/monthTools.integration.test.ts +174 -0
- package/src/tools/__tests__/monthTools.test.ts +523 -0
- package/src/tools/__tests__/payeeTools.delta.integration.test.ts +80 -0
- package/src/tools/__tests__/payeeTools.integration.test.ts +150 -0
- package/src/tools/__tests__/payeeTools.test.ts +445 -0
- package/src/tools/__tests__/transactionTools.integration.test.ts +762 -0
- package/src/tools/__tests__/transactionTools.test.ts +3521 -0
- package/src/tools/__tests__/utilityTools.integration.test.ts +128 -0
- package/src/tools/__tests__/utilityTools.test.ts +205 -0
- package/src/tools/accountTools.ts +283 -0
- package/src/tools/budgetTools.ts +112 -0
- package/src/tools/categoryTools.ts +366 -0
- package/src/tools/compareTransactions/formatter.ts +163 -0
- package/src/tools/compareTransactions/index.ts +228 -0
- package/src/tools/compareTransactions/matcher.ts +240 -0
- package/src/tools/compareTransactions/parser.ts +557 -0
- package/src/tools/compareTransactions/types.ts +60 -0
- package/src/tools/compareTransactions.ts +3 -0
- package/src/tools/deltaFetcher.ts +278 -0
- package/src/tools/deltaSupport.ts +293 -0
- package/src/tools/exportTransactions.ts +273 -0
- package/src/tools/monthTools.ts +164 -0
- package/src/tools/payeeTools.ts +140 -0
- package/src/tools/reconcileAdapter.ts +312 -0
- package/src/tools/reconciliation/__tests__/adapter.causes.test.ts +122 -0
- package/src/tools/reconciliation/__tests__/adapter.test.ts +234 -0
- package/src/tools/reconciliation/__tests__/analyzer.test.ts +406 -0
- package/src/tools/reconciliation/__tests__/executor.integration.test.ts +366 -0
- package/src/tools/reconciliation/__tests__/executor.test.ts +779 -0
- package/src/tools/reconciliation/__tests__/matcher.test.ts +650 -0
- package/src/tools/reconciliation/__tests__/payeeNormalizer.test.ts +278 -0
- package/src/tools/reconciliation/__tests__/recommendationEngine.integration.test.ts +658 -0
- package/src/tools/reconciliation/__tests__/recommendationEngine.test.ts +1000 -0
- package/src/tools/reconciliation/__tests__/reconciliation.delta.integration.test.ts +151 -0
- package/src/tools/reconciliation/__tests__/reportFormatter.test.ts +573 -0
- package/src/tools/reconciliation/__tests__/scenarios/adapterCurrency.scenario.test.ts +78 -0
- package/src/tools/reconciliation/__tests__/scenarios/extremes.scenario.test.ts +47 -0
- package/src/tools/reconciliation/__tests__/scenarios/repeatAmount.scenario.test.ts +61 -0
- package/src/tools/reconciliation/__tests__/schemaUrl.test.ts +49 -0
- package/src/tools/reconciliation/analyzer.ts +824 -0
- package/src/tools/reconciliation/executor.ts +880 -0
- package/src/tools/reconciliation/index.ts +400 -0
- package/src/tools/reconciliation/matcher.ts +269 -0
- package/src/tools/reconciliation/payeeNormalizer.ts +167 -0
- package/src/tools/reconciliation/recommendationEngine.ts +506 -0
- package/src/tools/reconciliation/reportFormatter.ts +363 -0
- package/src/tools/reconciliation/types.ts +314 -0
- package/src/tools/schemas/outputs/__tests__/accountOutputs.test.ts +424 -0
- package/src/tools/schemas/outputs/__tests__/budgetOutputs.test.ts +310 -0
- package/src/tools/schemas/outputs/__tests__/categoryOutputs.test.ts +448 -0
- package/src/tools/schemas/outputs/__tests__/comparisonOutputs.test.ts +519 -0
- package/src/tools/schemas/outputs/__tests__/dateValidation.test.ts +155 -0
- package/src/tools/schemas/outputs/__tests__/discrepancyDirection.test.ts +288 -0
- package/src/tools/schemas/outputs/__tests__/monthOutputs.test.ts +478 -0
- package/src/tools/schemas/outputs/__tests__/payeeOutputs.test.ts +370 -0
- package/src/tools/schemas/outputs/__tests__/reconciliationOutputs.test.ts +401 -0
- package/src/tools/schemas/outputs/__tests__/transactionMutationSchemas.test.ts +213 -0
- package/src/tools/schemas/outputs/__tests__/transactionOutputs.test.ts +474 -0
- package/src/tools/schemas/outputs/__tests__/utilityOutputs.test.ts +333 -0
- package/src/tools/schemas/outputs/accountOutputs.ts +137 -0
- package/src/tools/schemas/outputs/budgetOutputs.ts +86 -0
- package/src/tools/schemas/outputs/categoryOutputs.ts +194 -0
- package/src/tools/schemas/outputs/comparisonOutputs.ts +600 -0
- package/src/tools/schemas/outputs/index.ts +270 -0
- package/src/tools/schemas/outputs/monthOutputs.ts +243 -0
- package/src/tools/schemas/outputs/payeeOutputs.ts +105 -0
- package/src/tools/schemas/outputs/reconciliationOutputs.ts +796 -0
- package/src/tools/schemas/outputs/transactionMutationOutputs.ts +758 -0
- package/src/tools/schemas/outputs/transactionOutputs.ts +243 -0
- package/src/tools/schemas/outputs/utilityOutputs.ts +411 -0
- package/src/tools/schemas/shared/commonOutputs.ts +140 -0
- package/src/tools/toolCategories.ts +140 -0
- package/src/tools/transactionTools.ts +2509 -0
- package/src/tools/utilityTools.ts +90 -0
- package/src/types/.gitkeep +1 -0
- package/src/types/__tests__/index.test.ts +52 -0
- package/src/types/index.ts +67 -0
- package/src/types/integration-tests.d.ts +35 -0
- package/src/types/toolAnnotations.ts +44 -0
- package/src/utils/__tests__/dateUtils.test.ts +170 -0
- package/src/utils/__tests__/money.test.ts +189 -0
- package/src/utils/amountUtils.ts +32 -0
- package/src/utils/dateUtils.ts +108 -0
- package/src/utils/money.ts +123 -0
- package/test-csv-sample.csv +28 -0
- package/test-exports/sample_bank_statement.csv +7 -0
- package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_09-04-53.json +23 -0
- package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_10-37-42.json +23 -0
- package/test-exports/ynab_account_e9ddc2a6_minimal_4items_2025-11-19_09-02-09.json +44 -0
- package/test-exports/ynab_account_e9ddc2a6_minimal_6items_2025-11-19_10-37-52.json +58 -0
- package/test-exports/ynab_since_2025-11-01_account_4c18e9f0_minimal_14items_2025-11-16_10-07-10.json +115 -0
- package/test-reconcile-autodetect.js +40 -0
- package/test-reconcile-tool.js +152 -0
- package/test-reconcile-with-csv.cjs +89 -0
- package/test-statement.csv +8 -0
- package/test_debug.js +47 -0
- package/test_simple.mjs +16 -0
- package/tsconfig.json +31 -0
- package/tsconfig.prod.json +18 -0
- package/vitest-reporters/split-json-reporter.ts +211 -0
- package/vitest.config.ts +96 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable report formatting for reconciliation results
|
|
3
|
+
* Implements Phase 3 of dual-channel output improvements
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
ReconciliationAnalysis,
|
|
8
|
+
TransactionMatch,
|
|
9
|
+
BankTransaction,
|
|
10
|
+
YNABTransaction,
|
|
11
|
+
ReconciliationInsight,
|
|
12
|
+
BalanceInfo,
|
|
13
|
+
} from './types.js';
|
|
14
|
+
import type { LegacyReconciliationResult } from './executor.js';
|
|
15
|
+
import type { MoneyValue } from '../../utils/money.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Options for report formatting
|
|
19
|
+
*/
|
|
20
|
+
export interface ReportFormatterOptions {
|
|
21
|
+
accountName?: string | undefined;
|
|
22
|
+
accountId?: string | undefined;
|
|
23
|
+
currencyCode?: string | undefined;
|
|
24
|
+
includeDetailedMatches?: boolean | undefined;
|
|
25
|
+
maxUnmatchedToShow?: number | undefined;
|
|
26
|
+
maxInsightsToShow?: number | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Format the main human-readable reconciliation report
|
|
31
|
+
*/
|
|
32
|
+
export function formatHumanReadableReport(
|
|
33
|
+
analysis: ReconciliationAnalysis,
|
|
34
|
+
options: ReportFormatterOptions = {},
|
|
35
|
+
execution?: LegacyReconciliationResult,
|
|
36
|
+
): string {
|
|
37
|
+
const accountLabel = options.accountName ?? 'Account';
|
|
38
|
+
const sections: string[] = [];
|
|
39
|
+
|
|
40
|
+
// Header
|
|
41
|
+
sections.push(formatHeader(accountLabel, analysis));
|
|
42
|
+
|
|
43
|
+
// Balance check section
|
|
44
|
+
sections.push(formatBalanceSection(analysis.balance_info, analysis.summary));
|
|
45
|
+
|
|
46
|
+
// Transaction analysis section
|
|
47
|
+
sections.push(formatTransactionAnalysisSection(analysis, options));
|
|
48
|
+
|
|
49
|
+
// Insights section (if any)
|
|
50
|
+
if (analysis.insights.length > 0) {
|
|
51
|
+
sections.push(formatInsightsSection(analysis.insights, options.maxInsightsToShow));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Execution summary (if any)
|
|
55
|
+
if (execution) {
|
|
56
|
+
sections.push(formatExecutionSection(execution));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Recommendations/Next steps
|
|
60
|
+
sections.push(formatRecommendationsSection(analysis, execution));
|
|
61
|
+
|
|
62
|
+
return sections.join('\n\n');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Format the report header
|
|
67
|
+
*/
|
|
68
|
+
function formatHeader(accountName: string, analysis: ReconciliationAnalysis): string {
|
|
69
|
+
const lines: string[] = [];
|
|
70
|
+
lines.push(`📊 ${accountName} Reconciliation Report`);
|
|
71
|
+
lines.push('═'.repeat(60));
|
|
72
|
+
lines.push(`Statement Period: ${analysis.summary.statement_date_range}`);
|
|
73
|
+
return lines.join('\n');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Format the balance check section
|
|
78
|
+
*/
|
|
79
|
+
function formatBalanceSection(
|
|
80
|
+
balanceInfo: BalanceInfo,
|
|
81
|
+
summary: ReconciliationAnalysis['summary'],
|
|
82
|
+
): string {
|
|
83
|
+
const lines: string[] = [];
|
|
84
|
+
lines.push('BALANCE CHECK');
|
|
85
|
+
lines.push('═'.repeat(60));
|
|
86
|
+
|
|
87
|
+
// Current balances
|
|
88
|
+
lines.push(`✓ YNAB Cleared Balance: ${summary.current_cleared_balance.value_display}`);
|
|
89
|
+
lines.push(`✓ Statement Balance: ${summary.target_statement_balance.value_display}`);
|
|
90
|
+
lines.push('');
|
|
91
|
+
|
|
92
|
+
// Discrepancy status
|
|
93
|
+
const discrepancyMilli = balanceInfo.discrepancy.value_milliunits;
|
|
94
|
+
if (discrepancyMilli === 0) {
|
|
95
|
+
lines.push('✅ BALANCES MATCH PERFECTLY');
|
|
96
|
+
} else {
|
|
97
|
+
const direction = discrepancyMilli > 0 ? 'ynab_higher' : 'bank_higher';
|
|
98
|
+
const directionLabel =
|
|
99
|
+
direction === 'ynab_higher'
|
|
100
|
+
? 'YNAB shows MORE than statement'
|
|
101
|
+
: 'Statement shows MORE than YNAB';
|
|
102
|
+
|
|
103
|
+
lines.push(`❌ DISCREPANCY: ${balanceInfo.discrepancy.value_display}`);
|
|
104
|
+
lines.push(` Direction: ${directionLabel}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return lines.join('\n');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Format the transaction analysis section
|
|
112
|
+
*/
|
|
113
|
+
function formatTransactionAnalysisSection(
|
|
114
|
+
analysis: ReconciliationAnalysis,
|
|
115
|
+
options: ReportFormatterOptions,
|
|
116
|
+
): string {
|
|
117
|
+
const lines: string[] = [];
|
|
118
|
+
lines.push('TRANSACTION ANALYSIS');
|
|
119
|
+
lines.push('═'.repeat(60));
|
|
120
|
+
|
|
121
|
+
const summary = analysis.summary;
|
|
122
|
+
lines.push(
|
|
123
|
+
`✓ Automatically matched: ${summary.auto_matched} of ${summary.bank_transactions_count} transactions`,
|
|
124
|
+
);
|
|
125
|
+
lines.push(`✓ Suggested matches: ${summary.suggested_matches}`);
|
|
126
|
+
lines.push(`✓ Unmatched bank: ${summary.unmatched_bank}`);
|
|
127
|
+
lines.push(`✓ Unmatched YNAB: ${summary.unmatched_ynab}`);
|
|
128
|
+
|
|
129
|
+
// Show unmatched bank transactions (if any)
|
|
130
|
+
if (analysis.unmatched_bank.length > 0) {
|
|
131
|
+
lines.push('');
|
|
132
|
+
lines.push('❌ UNMATCHED BANK TRANSACTIONS:');
|
|
133
|
+
const maxToShow = options.maxUnmatchedToShow ?? 5;
|
|
134
|
+
const toShow = analysis.unmatched_bank.slice(0, maxToShow);
|
|
135
|
+
|
|
136
|
+
for (const txn of toShow) {
|
|
137
|
+
lines.push(formatBankTransactionLine(txn));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (analysis.unmatched_bank.length > maxToShow) {
|
|
141
|
+
lines.push(` ... and ${analysis.unmatched_bank.length - maxToShow} more`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Show suggested matches (if any)
|
|
146
|
+
if (analysis.suggested_matches.length > 0) {
|
|
147
|
+
lines.push('');
|
|
148
|
+
lines.push('💡 SUGGESTED MATCHES:');
|
|
149
|
+
const maxToShow = options.maxUnmatchedToShow ?? 3;
|
|
150
|
+
const toShow = analysis.suggested_matches.slice(0, maxToShow);
|
|
151
|
+
|
|
152
|
+
for (const match of toShow) {
|
|
153
|
+
lines.push(formatSuggestedMatchLine(match));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (analysis.suggested_matches.length > maxToShow) {
|
|
157
|
+
lines.push(` ... and ${analysis.suggested_matches.length - maxToShow} more suggestions`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return lines.join('\n');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Format a bank transaction line
|
|
166
|
+
*/
|
|
167
|
+
function formatBankTransactionLine(txn: BankTransaction): string {
|
|
168
|
+
const amountStr = formatAmount(txn.amount);
|
|
169
|
+
return ` ${txn.date} - ${txn.payee.substring(0, 40).padEnd(40)} ${amountStr}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Format a suggested match line
|
|
174
|
+
*/
|
|
175
|
+
function formatSuggestedMatchLine(match: TransactionMatch): string {
|
|
176
|
+
const bankTxn = match.bank_transaction;
|
|
177
|
+
const amountStr = formatAmount(bankTxn.amount);
|
|
178
|
+
const confidenceStr = `${match.confidence_score}%`;
|
|
179
|
+
return ` ${bankTxn.date} - ${bankTxn.payee.substring(0, 35).padEnd(35)} ${amountStr} (${confidenceStr} confidence)`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Format an amount for display
|
|
184
|
+
*/
|
|
185
|
+
function formatAmount(amount: number): string {
|
|
186
|
+
const sign = amount >= 0 ? '+' : '-';
|
|
187
|
+
const absAmount = Math.abs(amount);
|
|
188
|
+
return `${sign}$${absAmount.toFixed(2)}`.padStart(10);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Format the insights section
|
|
193
|
+
*/
|
|
194
|
+
function formatInsightsSection(insights: ReconciliationInsight[], maxToShow: number = 3): string {
|
|
195
|
+
const lines: string[] = [];
|
|
196
|
+
lines.push('KEY INSIGHTS');
|
|
197
|
+
lines.push('═'.repeat(60));
|
|
198
|
+
|
|
199
|
+
const toShow = insights.slice(0, maxToShow);
|
|
200
|
+
for (const insight of toShow) {
|
|
201
|
+
const severityIcon = getSeverityIcon(insight.severity);
|
|
202
|
+
lines.push(`${severityIcon} ${insight.title}`);
|
|
203
|
+
lines.push(` ${insight.description}`);
|
|
204
|
+
|
|
205
|
+
// Show evidence summary if available
|
|
206
|
+
if (insight.evidence && Object.keys(insight.evidence).length > 0) {
|
|
207
|
+
const evidenceSummary = formatEvidenceSummary(insight.evidence);
|
|
208
|
+
if (evidenceSummary) {
|
|
209
|
+
lines.push(` Evidence: ${evidenceSummary}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
lines.push('');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (insights.length > maxToShow) {
|
|
217
|
+
lines.push(`... and ${insights.length - maxToShow} more insights (see structured output)`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return lines.join('\n').trimEnd();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get emoji icon for severity level
|
|
225
|
+
*/
|
|
226
|
+
function getSeverityIcon(severity: string): string {
|
|
227
|
+
switch (severity) {
|
|
228
|
+
case 'critical':
|
|
229
|
+
return '🚨';
|
|
230
|
+
case 'warning':
|
|
231
|
+
return '⚠️';
|
|
232
|
+
case 'info':
|
|
233
|
+
return 'ℹ️';
|
|
234
|
+
default:
|
|
235
|
+
return '•';
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Format evidence summary from insight evidence object
|
|
241
|
+
*/
|
|
242
|
+
function formatEvidenceSummary(evidence: Record<string, unknown>): string | null {
|
|
243
|
+
// Handle common evidence patterns
|
|
244
|
+
if ('transaction_count' in evidence) {
|
|
245
|
+
return `${evidence['transaction_count']} transactions`;
|
|
246
|
+
}
|
|
247
|
+
if ('amount' in evidence && typeof evidence['amount'] === 'object') {
|
|
248
|
+
const amount = evidence['amount'] as MoneyValue;
|
|
249
|
+
return amount.value_display;
|
|
250
|
+
}
|
|
251
|
+
if ('transaction_ids' in evidence && Array.isArray(evidence['transaction_ids'])) {
|
|
252
|
+
return `${evidence['transaction_ids'].length} transactions involved`;
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Format the execution section
|
|
259
|
+
*/
|
|
260
|
+
function formatExecutionSection(execution: LegacyReconciliationResult): string {
|
|
261
|
+
const lines: string[] = [];
|
|
262
|
+
lines.push('EXECUTION SUMMARY');
|
|
263
|
+
lines.push('═'.repeat(60));
|
|
264
|
+
|
|
265
|
+
const summary = execution.summary;
|
|
266
|
+
lines.push(`• Transactions created: ${summary.transactions_created}`);
|
|
267
|
+
lines.push(`• Transactions updated: ${summary.transactions_updated}`);
|
|
268
|
+
lines.push(`• Date adjustments: ${summary.dates_adjusted}`);
|
|
269
|
+
|
|
270
|
+
// Show top recommendations if any
|
|
271
|
+
if (execution.recommendations.length > 0) {
|
|
272
|
+
lines.push('');
|
|
273
|
+
lines.push('Recommendations:');
|
|
274
|
+
const maxRecs = 3;
|
|
275
|
+
const toShow = execution.recommendations.slice(0, maxRecs);
|
|
276
|
+
for (const rec of toShow) {
|
|
277
|
+
lines.push(` • ${rec}`);
|
|
278
|
+
}
|
|
279
|
+
if (execution.recommendations.length > maxRecs) {
|
|
280
|
+
lines.push(` ... and ${execution.recommendations.length - maxRecs} more`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
lines.push('');
|
|
285
|
+
if (summary.dry_run) {
|
|
286
|
+
lines.push('⚠️ Dry run only — no YNAB changes were applied.');
|
|
287
|
+
} else {
|
|
288
|
+
lines.push('✅ Changes applied to YNAB. Review structured output for action details.');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return lines.join('\n');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Format the recommendations/next steps section
|
|
296
|
+
*/
|
|
297
|
+
function formatRecommendationsSection(
|
|
298
|
+
analysis: ReconciliationAnalysis,
|
|
299
|
+
execution?: LegacyReconciliationResult,
|
|
300
|
+
): string {
|
|
301
|
+
const lines: string[] = [];
|
|
302
|
+
lines.push('RECOMMENDED ACTIONS');
|
|
303
|
+
lines.push('═'.repeat(60));
|
|
304
|
+
|
|
305
|
+
// If we have execution results, recommendations are already shown
|
|
306
|
+
if (execution && !execution.summary.dry_run) {
|
|
307
|
+
lines.push('All recommended actions have been applied.');
|
|
308
|
+
return lines.join('\n');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Show next steps from analysis
|
|
312
|
+
if (analysis.next_steps.length > 0) {
|
|
313
|
+
for (const step of analysis.next_steps) {
|
|
314
|
+
lines.push(`• ${step}`);
|
|
315
|
+
}
|
|
316
|
+
} else {
|
|
317
|
+
lines.push('• No specific actions recommended.');
|
|
318
|
+
lines.push('• Review the structured output for detailed match information.');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return lines.join('\n');
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Format a balance section (helper for backward compatibility)
|
|
326
|
+
*/
|
|
327
|
+
export function formatBalanceInfo(balance: BalanceInfo): string {
|
|
328
|
+
const lines: string[] = [];
|
|
329
|
+
lines.push(`Current Cleared: ${balance.current_cleared.value_display}`);
|
|
330
|
+
lines.push(`Current Total: ${balance.current_total.value_display}`);
|
|
331
|
+
lines.push(`Target Statement: ${balance.target_statement.value_display}`);
|
|
332
|
+
lines.push(`Discrepancy: ${balance.discrepancy.value_display}`);
|
|
333
|
+
return lines.join('\n');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Format transaction list (helper for detailed reports)
|
|
338
|
+
*/
|
|
339
|
+
export function formatTransactionList(
|
|
340
|
+
transactions: BankTransaction[] | YNABTransaction[],
|
|
341
|
+
maxItems: number = 10,
|
|
342
|
+
): string {
|
|
343
|
+
const lines: string[] = [];
|
|
344
|
+
const toShow = transactions.slice(0, maxItems);
|
|
345
|
+
|
|
346
|
+
for (const txn of toShow) {
|
|
347
|
+
if ('payee' in txn) {
|
|
348
|
+
// Bank transaction
|
|
349
|
+
lines.push(formatBankTransactionLine(txn));
|
|
350
|
+
} else {
|
|
351
|
+
// YNAB transaction
|
|
352
|
+
const amount = txn.amount / 1000; // Convert milliunits to dollars
|
|
353
|
+
const payee = txn.payee_name ?? 'Unknown';
|
|
354
|
+
lines.push(` ${txn.date} - ${payee.substring(0, 40).padEnd(40)} ${formatAmount(amount)}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (transactions.length > maxItems) {
|
|
359
|
+
lines.push(` ... and ${transactions.length - maxItems} more`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return lines.join('\n');
|
|
363
|
+
}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the reconciliation tool
|
|
3
|
+
* Based on the 2025-10-31 reconciliation redesign specification
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { MoneyValue } from '../../utils/money.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Matching confidence levels
|
|
10
|
+
*/
|
|
11
|
+
export type MatchConfidence = 'high' | 'medium' | 'low' | 'none';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Bank transaction parsed from CSV
|
|
15
|
+
*/
|
|
16
|
+
export interface BankTransaction {
|
|
17
|
+
/** Generated UUID for tracking */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Transaction date in YYYY-MM-DD format */
|
|
20
|
+
date: string;
|
|
21
|
+
/** Amount in dollars */
|
|
22
|
+
amount: number;
|
|
23
|
+
/** Payee/merchant name */
|
|
24
|
+
payee: string;
|
|
25
|
+
/** Optional memo/description */
|
|
26
|
+
memo?: string;
|
|
27
|
+
/** Original CSV row number for debugging */
|
|
28
|
+
original_csv_row: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* YNAB transaction (simplified from API)
|
|
33
|
+
*/
|
|
34
|
+
export interface YNABTransaction {
|
|
35
|
+
id: string;
|
|
36
|
+
date: string;
|
|
37
|
+
/** Amount in milliunits */
|
|
38
|
+
amount: number;
|
|
39
|
+
payee_name: string | null;
|
|
40
|
+
category_name: string | null;
|
|
41
|
+
cleared: 'cleared' | 'uncleared' | 'reconciled';
|
|
42
|
+
approved: boolean;
|
|
43
|
+
memo?: string | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Match candidate with confidence score
|
|
48
|
+
*/
|
|
49
|
+
export interface MatchCandidate {
|
|
50
|
+
ynab_transaction: YNABTransaction;
|
|
51
|
+
confidence: number;
|
|
52
|
+
match_reason: string;
|
|
53
|
+
explanation: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Transaction match result
|
|
58
|
+
*/
|
|
59
|
+
export interface TransactionMatch {
|
|
60
|
+
bank_transaction: BankTransaction;
|
|
61
|
+
/** Best matched YNAB transaction (if any) */
|
|
62
|
+
ynab_transaction?: YNABTransaction;
|
|
63
|
+
/** Alternative candidates for suggested matches */
|
|
64
|
+
candidates?: MatchCandidate[];
|
|
65
|
+
/** Confidence level */
|
|
66
|
+
confidence: MatchConfidence;
|
|
67
|
+
/** Confidence score 0-100 */
|
|
68
|
+
confidence_score: number;
|
|
69
|
+
/** Reason for the match */
|
|
70
|
+
match_reason: string;
|
|
71
|
+
/** Top confidence from candidates */
|
|
72
|
+
top_confidence?: number;
|
|
73
|
+
/** Action hint for user */
|
|
74
|
+
action_hint?: string;
|
|
75
|
+
/** Recommendation text */
|
|
76
|
+
recommendation?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Balance information with structured monetary values
|
|
81
|
+
*/
|
|
82
|
+
export interface BalanceInfo {
|
|
83
|
+
current_cleared: MoneyValue;
|
|
84
|
+
current_uncleared: MoneyValue;
|
|
85
|
+
current_total: MoneyValue;
|
|
86
|
+
target_statement: MoneyValue;
|
|
87
|
+
discrepancy: MoneyValue;
|
|
88
|
+
on_track: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Reconciliation summary statistics with structured monetary values
|
|
93
|
+
*/
|
|
94
|
+
export interface ReconciliationSummary {
|
|
95
|
+
statement_date_range: string;
|
|
96
|
+
bank_transactions_count: number;
|
|
97
|
+
ynab_transactions_count: number;
|
|
98
|
+
auto_matched: number;
|
|
99
|
+
suggested_matches: number;
|
|
100
|
+
unmatched_bank: number;
|
|
101
|
+
unmatched_ynab: number;
|
|
102
|
+
current_cleared_balance: MoneyValue;
|
|
103
|
+
target_statement_balance: MoneyValue;
|
|
104
|
+
discrepancy: MoneyValue;
|
|
105
|
+
discrepancy_explanation: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Insight severity levels
|
|
110
|
+
*/
|
|
111
|
+
export type InsightSeverity = 'info' | 'warning' | 'critical';
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Insight types for reconciliation analysis
|
|
115
|
+
*/
|
|
116
|
+
export type InsightKind = 'repeat_amount' | 'near_match' | 'anomaly';
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Reconciliation insight - highlights important findings that help explain discrepancies
|
|
120
|
+
*/
|
|
121
|
+
export interface ReconciliationInsight {
|
|
122
|
+
id: string;
|
|
123
|
+
type: InsightKind;
|
|
124
|
+
severity: InsightSeverity;
|
|
125
|
+
title: string;
|
|
126
|
+
description: string;
|
|
127
|
+
evidence?: Record<string, unknown>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Analysis phase result
|
|
132
|
+
*/
|
|
133
|
+
export interface ReconciliationAnalysis {
|
|
134
|
+
success: true;
|
|
135
|
+
phase: 'analysis';
|
|
136
|
+
summary: ReconciliationSummary;
|
|
137
|
+
auto_matches: TransactionMatch[];
|
|
138
|
+
suggested_matches: TransactionMatch[];
|
|
139
|
+
unmatched_bank: BankTransaction[];
|
|
140
|
+
unmatched_ynab: YNABTransaction[];
|
|
141
|
+
balance_info: BalanceInfo;
|
|
142
|
+
next_steps: string[];
|
|
143
|
+
insights: ReconciliationInsight[];
|
|
144
|
+
recommendations?: ActionableRecommendation[];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Reconciliation action types
|
|
149
|
+
*/
|
|
150
|
+
export type ReconciliationActionType = 'match' | 'add' | 'unclear' | 'delete' | 'ignore';
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Reconciliation action
|
|
154
|
+
*/
|
|
155
|
+
export interface ReconciliationAction {
|
|
156
|
+
type: ReconciliationActionType;
|
|
157
|
+
bank_txn_id?: string;
|
|
158
|
+
ynab_txn_id?: string;
|
|
159
|
+
mark_cleared?: boolean;
|
|
160
|
+
create_as_cleared?: boolean;
|
|
161
|
+
reason?: string;
|
|
162
|
+
metadata?: Record<string, unknown>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Matching algorithm configuration
|
|
167
|
+
*/
|
|
168
|
+
export interface MatchingConfig {
|
|
169
|
+
/** Date tolerance in days */
|
|
170
|
+
dateToleranceDays: number;
|
|
171
|
+
/** Amount tolerance in cents */
|
|
172
|
+
amountToleranceCents: number;
|
|
173
|
+
/** Description similarity threshold (0-1) */
|
|
174
|
+
descriptionSimilarityThreshold: number;
|
|
175
|
+
/** Confidence threshold for auto-matching (0-100) */
|
|
176
|
+
autoMatchThreshold: number;
|
|
177
|
+
/** Confidence threshold for suggestions (0-100) */
|
|
178
|
+
suggestionThreshold: number;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Default matching configuration (not type-only for use in code)
|
|
183
|
+
*/
|
|
184
|
+
export const DEFAULT_MATCHING_CONFIG = {
|
|
185
|
+
dateToleranceDays: 2,
|
|
186
|
+
amountToleranceCents: 1,
|
|
187
|
+
descriptionSimilarityThreshold: 0.8,
|
|
188
|
+
autoMatchThreshold: 90,
|
|
189
|
+
suggestionThreshold: 60,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Parsed CSV data from compareTransactions
|
|
194
|
+
*/
|
|
195
|
+
export interface ParsedCSVData {
|
|
196
|
+
transactions: BankTransaction[];
|
|
197
|
+
format_detected: string;
|
|
198
|
+
delimiter: string;
|
|
199
|
+
total_rows: number;
|
|
200
|
+
valid_rows: number;
|
|
201
|
+
errors: string[];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Priority levels for actionable recommendations
|
|
206
|
+
*/
|
|
207
|
+
export type RecommendationPriority = 'high' | 'medium' | 'low';
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Base fields common to all recommendation types
|
|
211
|
+
*/
|
|
212
|
+
export interface BaseRecommendation {
|
|
213
|
+
/** Unique identifier for this recommendation */
|
|
214
|
+
id: string;
|
|
215
|
+
/** Priority level for execution */
|
|
216
|
+
priority: RecommendationPriority;
|
|
217
|
+
/** Confidence score 0-1 (higher = more confident) */
|
|
218
|
+
confidence: number;
|
|
219
|
+
/** Human-readable message describing the recommendation */
|
|
220
|
+
message: string;
|
|
221
|
+
/** Explanation of why this recommendation was generated */
|
|
222
|
+
reason: string;
|
|
223
|
+
/** Estimated impact on reconciliation balance */
|
|
224
|
+
estimated_impact: MoneyValue;
|
|
225
|
+
/** YNAB account ID this recommendation applies to */
|
|
226
|
+
account_id: string;
|
|
227
|
+
/** Optional link to the insight that generated this recommendation */
|
|
228
|
+
source_insight_id?: string;
|
|
229
|
+
/** Additional metadata (version, timestamps, etc.) */
|
|
230
|
+
metadata?: Record<string, unknown>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Recommendation to create a new YNAB transaction
|
|
235
|
+
*/
|
|
236
|
+
export interface CreateTransactionRecommendation extends BaseRecommendation {
|
|
237
|
+
action_type: 'create_transaction';
|
|
238
|
+
parameters: {
|
|
239
|
+
account_id: string;
|
|
240
|
+
date: string;
|
|
241
|
+
amount: number;
|
|
242
|
+
payee_name: string;
|
|
243
|
+
memo?: string;
|
|
244
|
+
cleared: 'cleared' | 'uncleared';
|
|
245
|
+
approved: boolean;
|
|
246
|
+
category_id?: string;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Recommendation to update a transaction's cleared status
|
|
252
|
+
*/
|
|
253
|
+
export interface UpdateClearedRecommendation extends BaseRecommendation {
|
|
254
|
+
action_type: 'update_cleared';
|
|
255
|
+
parameters: {
|
|
256
|
+
transaction_id: string;
|
|
257
|
+
cleared: 'cleared' | 'uncleared' | 'reconciled';
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Recommendation to review potential duplicate transactions
|
|
263
|
+
*/
|
|
264
|
+
export interface ReviewDuplicateRecommendation extends BaseRecommendation {
|
|
265
|
+
action_type: 'review_duplicate';
|
|
266
|
+
parameters: {
|
|
267
|
+
candidate_ids: string[];
|
|
268
|
+
bank_transaction?: BankTransaction;
|
|
269
|
+
suggested_match_id?: string;
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Related transaction reference for manual review
|
|
275
|
+
*/
|
|
276
|
+
export interface RelatedTransaction {
|
|
277
|
+
source: 'bank' | 'ynab';
|
|
278
|
+
id: string;
|
|
279
|
+
description: string;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Recommendation requiring manual investigation
|
|
284
|
+
*/
|
|
285
|
+
export interface ManualReviewRecommendation extends BaseRecommendation {
|
|
286
|
+
action_type: 'manual_review';
|
|
287
|
+
parameters: {
|
|
288
|
+
issue_type: 'complex_match' | 'large_discrepancy' | 'unknown';
|
|
289
|
+
related_transactions?: RelatedTransaction[];
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Union type of all possible recommendation types (discriminated by action_type)
|
|
295
|
+
*/
|
|
296
|
+
export type ActionableRecommendation =
|
|
297
|
+
| CreateTransactionRecommendation
|
|
298
|
+
| UpdateClearedRecommendation
|
|
299
|
+
| ReviewDuplicateRecommendation
|
|
300
|
+
| ManualReviewRecommendation;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Context passed to recommendation engine for generating recommendations
|
|
304
|
+
*/
|
|
305
|
+
export interface RecommendationContext {
|
|
306
|
+
/** Account ID for the recommendations */
|
|
307
|
+
account_id: string;
|
|
308
|
+
/** Budget ID (reserved for future category suggestions) */
|
|
309
|
+
budget_id: string;
|
|
310
|
+
/** The reconciliation analysis results */
|
|
311
|
+
analysis: ReconciliationAnalysis;
|
|
312
|
+
/** Matching configuration used during analysis */
|
|
313
|
+
matching_config: MatchingConfig;
|
|
314
|
+
}
|