@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,524 @@
|
|
|
1
|
+
export class YNABAPIError extends Error {
|
|
2
|
+
constructor(code, message, originalError) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'YNABAPIError';
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.originalError = originalError;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export class ValidationError extends Error {
|
|
10
|
+
constructor(message, details, suggestions) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'ValidationError';
|
|
13
|
+
this.details = details;
|
|
14
|
+
this.suggestions = suggestions;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class ErrorHandler {
|
|
18
|
+
constructor(formatter) {
|
|
19
|
+
this.formatter = formatter;
|
|
20
|
+
}
|
|
21
|
+
static createFallbackFormatter() {
|
|
22
|
+
return {
|
|
23
|
+
format: (value) => JSON.stringify(value, null, 2),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
static setFormatter(formatter) {
|
|
27
|
+
ErrorHandler.defaultInstance = new ErrorHandler(formatter);
|
|
28
|
+
}
|
|
29
|
+
handleError(error, context) {
|
|
30
|
+
const errorResponse = this.createErrorResponse(error, context);
|
|
31
|
+
let formattedText;
|
|
32
|
+
try {
|
|
33
|
+
formattedText = this.formatter.format(errorResponse);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
formattedText = JSON.stringify(errorResponse, null, 2);
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: 'text',
|
|
42
|
+
text: formattedText,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
static handleError(error, context) {
|
|
48
|
+
if (!ErrorHandler.defaultInstance) {
|
|
49
|
+
ErrorHandler.defaultInstance = new ErrorHandler(ErrorHandler.createFallbackFormatter());
|
|
50
|
+
}
|
|
51
|
+
return ErrorHandler.defaultInstance.handleError(error, context);
|
|
52
|
+
}
|
|
53
|
+
createErrorResponse(error, context) {
|
|
54
|
+
if (error instanceof YNABAPIError) {
|
|
55
|
+
const sanitizedDetails = this.sanitizeErrorDetails(error.originalError);
|
|
56
|
+
return {
|
|
57
|
+
error: {
|
|
58
|
+
code: error.code,
|
|
59
|
+
message: this.getErrorMessage(error.code, context),
|
|
60
|
+
userMessage: this.getUserFriendlyMessage(error.code, context),
|
|
61
|
+
suggestions: this.getErrorSuggestions(error.code, context),
|
|
62
|
+
...(sanitizedDetails && { details: sanitizedDetails }),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (error instanceof ValidationError) {
|
|
67
|
+
const sanitizedDetails = error.details ? this.sanitizeErrorDetails(error.details) : undefined;
|
|
68
|
+
const suggestions = error.suggestions && error.suggestions.length > 0
|
|
69
|
+
? error.suggestions
|
|
70
|
+
: this.getErrorSuggestions("VALIDATION_ERROR", context);
|
|
71
|
+
return {
|
|
72
|
+
error: {
|
|
73
|
+
code: "VALIDATION_ERROR",
|
|
74
|
+
message: error.message,
|
|
75
|
+
userMessage: this.getUserFriendlyMessage("VALIDATION_ERROR", context),
|
|
76
|
+
suggestions,
|
|
77
|
+
...(sanitizedDetails && { details: sanitizedDetails }),
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const ynabApiError = this.extractYNABApiError(error);
|
|
82
|
+
if (ynabApiError) {
|
|
83
|
+
const sanitizedDetails = ynabApiError.details
|
|
84
|
+
? this.sanitizeErrorDetails(ynabApiError.details)
|
|
85
|
+
: undefined;
|
|
86
|
+
return {
|
|
87
|
+
error: {
|
|
88
|
+
code: ynabApiError.code,
|
|
89
|
+
message: this.getErrorMessage(ynabApiError.code, context),
|
|
90
|
+
userMessage: this.getUserFriendlyMessage(ynabApiError.code, context),
|
|
91
|
+
suggestions: this.getErrorSuggestions(ynabApiError.code, context),
|
|
92
|
+
...(sanitizedDetails && { details: sanitizedDetails }),
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const httpStatus = this.extractHttpStatus(error);
|
|
97
|
+
if (httpStatus !== null) {
|
|
98
|
+
const code = this.mapHttpStatusToErrorCode(httpStatus);
|
|
99
|
+
if (code) {
|
|
100
|
+
const details = this.extractHttpStatusDetails(error);
|
|
101
|
+
return {
|
|
102
|
+
error: {
|
|
103
|
+
code,
|
|
104
|
+
message: this.getErrorMessage(code, context),
|
|
105
|
+
userMessage: this.getUserFriendlyMessage(code, context),
|
|
106
|
+
suggestions: this.getErrorSuggestions(code, context),
|
|
107
|
+
...(details && { details }),
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (error instanceof Error) {
|
|
113
|
+
const detectedCode = this.detectErrorCode(error);
|
|
114
|
+
if (detectedCode) {
|
|
115
|
+
return {
|
|
116
|
+
error: {
|
|
117
|
+
code: detectedCode,
|
|
118
|
+
message: this.getErrorMessage(detectedCode, context),
|
|
119
|
+
userMessage: this.getUserFriendlyMessage(detectedCode, context),
|
|
120
|
+
suggestions: this.getErrorSuggestions(detectedCode, context),
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
126
|
+
const sanitizedDetails = this.sanitizeErrorDetails(errorMessage);
|
|
127
|
+
return {
|
|
128
|
+
error: {
|
|
129
|
+
code: "UNKNOWN_ERROR",
|
|
130
|
+
message: this.getGenericErrorMessage(context),
|
|
131
|
+
userMessage: this.getUserFriendlyGenericMessage(context),
|
|
132
|
+
suggestions: [
|
|
133
|
+
'Try the operation again',
|
|
134
|
+
'Check your internet connection',
|
|
135
|
+
'Contact support if the issue persists',
|
|
136
|
+
],
|
|
137
|
+
...(sanitizedDetails && { details: sanitizedDetails }),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
detectErrorCode(error) {
|
|
142
|
+
const message = error.message.toLowerCase();
|
|
143
|
+
if (message.includes('401') || message.includes('unauthorized')) {
|
|
144
|
+
return 401;
|
|
145
|
+
}
|
|
146
|
+
if (message.includes('403') || message.includes('forbidden')) {
|
|
147
|
+
return 403;
|
|
148
|
+
}
|
|
149
|
+
if (message.includes('404') || message.includes('not found')) {
|
|
150
|
+
return 404;
|
|
151
|
+
}
|
|
152
|
+
if (message.includes('429') || message.includes('too many requests')) {
|
|
153
|
+
return 429;
|
|
154
|
+
}
|
|
155
|
+
if (message.includes('500') || message.includes('internal server error')) {
|
|
156
|
+
return 500;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
getUserFriendlyMessage(code, context) {
|
|
161
|
+
switch (code) {
|
|
162
|
+
case 401:
|
|
163
|
+
return 'Your YNAB access token is invalid or has expired. Please check your token and try again.';
|
|
164
|
+
case 403:
|
|
165
|
+
return "You don't have permission to access this YNAB data. Please check your account permissions.";
|
|
166
|
+
case 404:
|
|
167
|
+
return this.getUserFriendlyNotFoundMessage(context);
|
|
168
|
+
case 429:
|
|
169
|
+
return "We're making too many requests to YNAB. Please wait a moment and try again.";
|
|
170
|
+
case 500:
|
|
171
|
+
return "YNAB's servers are having issues. Please try again in a few minutes.";
|
|
172
|
+
case "VALIDATION_ERROR":
|
|
173
|
+
return 'Some of the information provided is invalid. Please check your inputs and try again.';
|
|
174
|
+
case "RATE_LIMIT_EXCEEDED":
|
|
175
|
+
return 'Too many requests have been made. Please wait before trying again.';
|
|
176
|
+
default:
|
|
177
|
+
return this.getUserFriendlyGenericMessage(context);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
getErrorSuggestions(code, context) {
|
|
181
|
+
switch (code) {
|
|
182
|
+
case 401:
|
|
183
|
+
return [
|
|
184
|
+
'Go to https://app.youneedabudget.com/settings/developer to generate a new access token',
|
|
185
|
+
'Make sure you copied the entire token without any extra spaces',
|
|
186
|
+
"Check that your token hasn't expired",
|
|
187
|
+
];
|
|
188
|
+
case 403:
|
|
189
|
+
return [
|
|
190
|
+
'Verify that your YNAB account has access to the requested budget',
|
|
191
|
+
'Check if your YNAB subscription is active',
|
|
192
|
+
'Try logging into YNAB directly to confirm access',
|
|
193
|
+
];
|
|
194
|
+
case 404:
|
|
195
|
+
return this.getNotFoundSuggestions(context);
|
|
196
|
+
case 429:
|
|
197
|
+
return [
|
|
198
|
+
'Wait 1-2 minutes before trying again',
|
|
199
|
+
'Try making fewer requests at once',
|
|
200
|
+
'The system will automatically retry after a short delay',
|
|
201
|
+
];
|
|
202
|
+
case 500:
|
|
203
|
+
return [
|
|
204
|
+
"Check YNAB's status page at https://status.youneedabudget.com",
|
|
205
|
+
'Try again in a few minutes',
|
|
206
|
+
'Contact YNAB support if the issue persists',
|
|
207
|
+
];
|
|
208
|
+
case "VALIDATION_ERROR":
|
|
209
|
+
return [
|
|
210
|
+
'Double-check all required fields are filled out',
|
|
211
|
+
'Verify that amounts are in the correct format',
|
|
212
|
+
'Make sure dates are valid and in the right format',
|
|
213
|
+
];
|
|
214
|
+
default:
|
|
215
|
+
return [
|
|
216
|
+
'Try the operation again',
|
|
217
|
+
'Check your internet connection',
|
|
218
|
+
'Contact support if the issue persists',
|
|
219
|
+
];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
getUserFriendlyNotFoundMessage(context) {
|
|
223
|
+
if (context.includes('account')) {
|
|
224
|
+
return "We couldn't find the budget or account you're looking for.";
|
|
225
|
+
}
|
|
226
|
+
if (context.includes('budget')) {
|
|
227
|
+
return "We couldn't find that budget. It may have been deleted or you may not have access.";
|
|
228
|
+
}
|
|
229
|
+
if (context.includes('category')) {
|
|
230
|
+
return "We couldn't find that category. It may have been deleted or moved.";
|
|
231
|
+
}
|
|
232
|
+
if (context.includes('transaction')) {
|
|
233
|
+
return "We couldn't find that transaction. It may have been deleted or moved.";
|
|
234
|
+
}
|
|
235
|
+
if (context.includes('payee')) {
|
|
236
|
+
return "We couldn't find that payee in your budget.";
|
|
237
|
+
}
|
|
238
|
+
return "We couldn't find what you're looking for. Please check that all information is correct.";
|
|
239
|
+
}
|
|
240
|
+
getNotFoundSuggestions(context) {
|
|
241
|
+
const baseSuggestions = [
|
|
242
|
+
'Double-check that the name or ID is spelled correctly',
|
|
243
|
+
'Try refreshing your budget data',
|
|
244
|
+
"Make sure you're using the right budget",
|
|
245
|
+
];
|
|
246
|
+
if (context.includes('account')) {
|
|
247
|
+
return [...baseSuggestions, 'Check if the account was recently closed or renamed'];
|
|
248
|
+
}
|
|
249
|
+
if (context.includes('category')) {
|
|
250
|
+
return [
|
|
251
|
+
...baseSuggestions,
|
|
252
|
+
'Check if the category was deleted or moved to a different group',
|
|
253
|
+
];
|
|
254
|
+
}
|
|
255
|
+
if (context.includes('transaction')) {
|
|
256
|
+
return [
|
|
257
|
+
...baseSuggestions,
|
|
258
|
+
'Check if the transaction was deleted or is in a different account',
|
|
259
|
+
];
|
|
260
|
+
}
|
|
261
|
+
return baseSuggestions;
|
|
262
|
+
}
|
|
263
|
+
getUserFriendlyGenericMessage(context) {
|
|
264
|
+
if (context.includes('transaction')) {
|
|
265
|
+
return 'There was a problem with your transaction. Please check your information and try again.';
|
|
266
|
+
}
|
|
267
|
+
if (context.includes('budget')) {
|
|
268
|
+
return 'There was a problem accessing your budget data. Please try again.';
|
|
269
|
+
}
|
|
270
|
+
if (context.includes('account')) {
|
|
271
|
+
return 'There was a problem accessing your account information. Please try again.';
|
|
272
|
+
}
|
|
273
|
+
return 'Something went wrong. Please try again in a moment.';
|
|
274
|
+
}
|
|
275
|
+
getErrorMessage(code, context) {
|
|
276
|
+
switch (code) {
|
|
277
|
+
case 401:
|
|
278
|
+
return 'Invalid or expired YNAB access token';
|
|
279
|
+
case 403:
|
|
280
|
+
return 'Insufficient permissions to access YNAB data';
|
|
281
|
+
case 404:
|
|
282
|
+
return this.getNotFoundMessage(context);
|
|
283
|
+
case 429:
|
|
284
|
+
return 'Rate limit exceeded. Please try again later';
|
|
285
|
+
case 500:
|
|
286
|
+
return 'YNAB service is currently unavailable';
|
|
287
|
+
default:
|
|
288
|
+
return this.getGenericErrorMessage(context);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
getNotFoundMessage(context) {
|
|
292
|
+
if (context.includes('listing accounts')) {
|
|
293
|
+
return 'Failed to list accounts - budget or account not found';
|
|
294
|
+
}
|
|
295
|
+
if (context.includes('getting account')) {
|
|
296
|
+
return 'Failed to get account - budget or account not found';
|
|
297
|
+
}
|
|
298
|
+
if (context.includes('listing budgets') || context.includes('getting budget')) {
|
|
299
|
+
return 'Budget not found';
|
|
300
|
+
}
|
|
301
|
+
if (context.includes('listing categories') || context.includes('getting category')) {
|
|
302
|
+
return 'Budget or category not found';
|
|
303
|
+
}
|
|
304
|
+
if (context.includes('listing months') || context.includes('getting month')) {
|
|
305
|
+
return 'Budget or month not found';
|
|
306
|
+
}
|
|
307
|
+
if (context.includes('listing payees') || context.includes('getting payee')) {
|
|
308
|
+
return 'Budget or payee not found';
|
|
309
|
+
}
|
|
310
|
+
if (context.includes('listing transactions') || context.includes('getting transaction')) {
|
|
311
|
+
return 'Budget, account, category, or transaction not found';
|
|
312
|
+
}
|
|
313
|
+
return 'The requested resource was not found. Please verify the provided IDs are correct.';
|
|
314
|
+
}
|
|
315
|
+
getGenericErrorMessage(context) {
|
|
316
|
+
if (context.includes('listing accounts')) {
|
|
317
|
+
return 'Failed to list accounts';
|
|
318
|
+
}
|
|
319
|
+
if (context.includes('getting account')) {
|
|
320
|
+
return 'Failed to get account';
|
|
321
|
+
}
|
|
322
|
+
if (context.includes('creating account')) {
|
|
323
|
+
return 'Failed to create account';
|
|
324
|
+
}
|
|
325
|
+
if (context.includes('listing budgets')) {
|
|
326
|
+
return 'Failed to list budgets';
|
|
327
|
+
}
|
|
328
|
+
if (context.includes('getting budget')) {
|
|
329
|
+
return 'Failed to get budget';
|
|
330
|
+
}
|
|
331
|
+
if (context.includes('listing categories')) {
|
|
332
|
+
return 'Failed to list categories';
|
|
333
|
+
}
|
|
334
|
+
if (context.includes('getting category')) {
|
|
335
|
+
return 'Failed to get category';
|
|
336
|
+
}
|
|
337
|
+
if (context.includes('updating category')) {
|
|
338
|
+
return 'Failed to update category';
|
|
339
|
+
}
|
|
340
|
+
if (context.includes('listing months')) {
|
|
341
|
+
return 'Failed to list months';
|
|
342
|
+
}
|
|
343
|
+
if (context.includes('getting month')) {
|
|
344
|
+
return 'Failed to get month data';
|
|
345
|
+
}
|
|
346
|
+
if (context.includes('listing payees')) {
|
|
347
|
+
return 'Failed to list payees';
|
|
348
|
+
}
|
|
349
|
+
if (context.includes('getting payee')) {
|
|
350
|
+
return 'Failed to get payee';
|
|
351
|
+
}
|
|
352
|
+
if (context.includes('listing transactions')) {
|
|
353
|
+
return 'Failed to list transactions';
|
|
354
|
+
}
|
|
355
|
+
if (context.includes('getting transaction')) {
|
|
356
|
+
return 'Failed to get transaction';
|
|
357
|
+
}
|
|
358
|
+
if (context.includes('creating transaction')) {
|
|
359
|
+
return 'Failed to create transaction';
|
|
360
|
+
}
|
|
361
|
+
if (context.includes('updating transaction')) {
|
|
362
|
+
return 'Failed to update transaction';
|
|
363
|
+
}
|
|
364
|
+
if (context.includes('getting user')) {
|
|
365
|
+
return 'Failed to get user information';
|
|
366
|
+
}
|
|
367
|
+
return `An error occurred while ${context}`;
|
|
368
|
+
}
|
|
369
|
+
extractHttpStatus(error) {
|
|
370
|
+
if (!error || typeof error !== 'object') {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
const directStatus = error.status;
|
|
374
|
+
if (typeof directStatus === 'number' && Number.isInteger(directStatus) && directStatus > 0) {
|
|
375
|
+
return directStatus;
|
|
376
|
+
}
|
|
377
|
+
const response = error.response;
|
|
378
|
+
if (response && typeof response === 'object') {
|
|
379
|
+
const responseStatus = response.status;
|
|
380
|
+
if (typeof responseStatus === 'number' &&
|
|
381
|
+
Number.isInteger(responseStatus) &&
|
|
382
|
+
responseStatus > 0) {
|
|
383
|
+
return responseStatus;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
mapHttpStatusToErrorCode(status) {
|
|
389
|
+
switch (status) {
|
|
390
|
+
case 401:
|
|
391
|
+
case 403:
|
|
392
|
+
case 404:
|
|
393
|
+
case 429:
|
|
394
|
+
case 500:
|
|
395
|
+
return status;
|
|
396
|
+
default:
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
extractHttpStatusDetails(error) {
|
|
401
|
+
if (error && typeof error === 'object') {
|
|
402
|
+
const response = error.response;
|
|
403
|
+
if (response && typeof response === 'object') {
|
|
404
|
+
const statusText = response.statusText;
|
|
405
|
+
if (typeof statusText === 'string' && statusText.trim().length > 0) {
|
|
406
|
+
return this.sanitizeErrorDetails(statusText);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (error instanceof Error && error.message) {
|
|
411
|
+
return this.sanitizeErrorDetails(error.message);
|
|
412
|
+
}
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
extractYNABApiError(error) {
|
|
416
|
+
if (!error || typeof error !== 'object' || !('error' in error)) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
const payload = error.error;
|
|
420
|
+
if (!payload || typeof payload !== 'object') {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
const id = payload.id;
|
|
424
|
+
const name = payload.name;
|
|
425
|
+
const detail = payload.detail;
|
|
426
|
+
let code = null;
|
|
427
|
+
if (typeof id === 'string') {
|
|
428
|
+
const numeric = parseInt(id, 10);
|
|
429
|
+
if (!Number.isNaN(numeric)) {
|
|
430
|
+
code = this.mapHttpStatusToErrorCode(numeric);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (!code && typeof name === 'string') {
|
|
434
|
+
const normalized = name.toLowerCase();
|
|
435
|
+
if (normalized.includes('unauthorized')) {
|
|
436
|
+
code = 401;
|
|
437
|
+
}
|
|
438
|
+
else if (normalized.includes('forbidden')) {
|
|
439
|
+
code = 403;
|
|
440
|
+
}
|
|
441
|
+
else if (normalized.includes('not_found')) {
|
|
442
|
+
code = 404;
|
|
443
|
+
}
|
|
444
|
+
else if (normalized.includes('too_many_requests') || normalized.includes('rate_limit')) {
|
|
445
|
+
code = 429;
|
|
446
|
+
}
|
|
447
|
+
else if (normalized.includes('internal_server_error')) {
|
|
448
|
+
code = 500;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (!code) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
const details = typeof detail === 'string' ? detail : undefined;
|
|
455
|
+
const result = { code };
|
|
456
|
+
if (details !== undefined) {
|
|
457
|
+
result.details = details;
|
|
458
|
+
}
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
sanitizeErrorDetails(error) {
|
|
462
|
+
if (!error)
|
|
463
|
+
return undefined;
|
|
464
|
+
let details = '';
|
|
465
|
+
if (error instanceof Error) {
|
|
466
|
+
details = error.message;
|
|
467
|
+
}
|
|
468
|
+
else if (typeof error === 'string') {
|
|
469
|
+
details = error;
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
details = 'Unknown error details';
|
|
473
|
+
}
|
|
474
|
+
details = details
|
|
475
|
+
.replace(/token[s]?[:\s=]+([^\s,"']+)/gi, 'token=***')
|
|
476
|
+
.replace(/key[s]?[:\s=]+([^\s,"']+)/gi, 'key=***')
|
|
477
|
+
.replace(/password[s]?[:\s=]+([^\s,"']+)/gi, 'password=***')
|
|
478
|
+
.replace(/authorization[:\s=]+[^\r\n]+/gi, 'authorization=***')
|
|
479
|
+
.replace(/\bBearer\s+[A-Za-z0-9._-]+/gi, 'Bearer ***');
|
|
480
|
+
return details;
|
|
481
|
+
}
|
|
482
|
+
async withErrorHandling(operation, context) {
|
|
483
|
+
try {
|
|
484
|
+
return await operation();
|
|
485
|
+
}
|
|
486
|
+
catch (error) {
|
|
487
|
+
return this.handleError(error, context);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
static async withErrorHandling(operation, context) {
|
|
491
|
+
if (!ErrorHandler.defaultInstance) {
|
|
492
|
+
ErrorHandler.defaultInstance = new ErrorHandler(ErrorHandler.createFallbackFormatter());
|
|
493
|
+
}
|
|
494
|
+
return ErrorHandler.defaultInstance.withErrorHandling(operation, context);
|
|
495
|
+
}
|
|
496
|
+
createValidationError(message, details, suggestions) {
|
|
497
|
+
return this.handleError(new ValidationError(message, details, suggestions), 'validating parameters');
|
|
498
|
+
}
|
|
499
|
+
static createValidationError(message, details, suggestions) {
|
|
500
|
+
if (!ErrorHandler.defaultInstance) {
|
|
501
|
+
ErrorHandler.defaultInstance = new ErrorHandler(ErrorHandler.createFallbackFormatter());
|
|
502
|
+
}
|
|
503
|
+
return ErrorHandler.defaultInstance.createValidationError(message, details, suggestions);
|
|
504
|
+
}
|
|
505
|
+
createYNABError(code, context, originalError) {
|
|
506
|
+
const message = this.getErrorMessage(code, context);
|
|
507
|
+
return new YNABAPIError(code, message, originalError);
|
|
508
|
+
}
|
|
509
|
+
static createYNABError(code, context, originalError) {
|
|
510
|
+
if (!ErrorHandler.defaultInstance) {
|
|
511
|
+
ErrorHandler.defaultInstance = new ErrorHandler(ErrorHandler.createFallbackFormatter());
|
|
512
|
+
}
|
|
513
|
+
return ErrorHandler.defaultInstance.createYNABError(code, context, originalError);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
export function createErrorHandler(formatter) {
|
|
517
|
+
return new ErrorHandler(formatter);
|
|
518
|
+
}
|
|
519
|
+
export function handleToolError(error, toolName, operation) {
|
|
520
|
+
return ErrorHandler.handleError(error, `executing ${toolName} - ${operation}`);
|
|
521
|
+
}
|
|
522
|
+
export async function withToolErrorHandling(operation, toolName, operationName) {
|
|
523
|
+
return ErrorHandler.withErrorHandling(operation, `executing ${toolName} - ${operationName}`);
|
|
524
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface PromptArgument {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
required: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface PromptDefinition {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
arguments: PromptArgument[];
|
|
10
|
+
}
|
|
11
|
+
export interface PromptResponse {
|
|
12
|
+
description: string;
|
|
13
|
+
messages: {
|
|
14
|
+
role: 'user' | 'assistant';
|
|
15
|
+
content: {
|
|
16
|
+
type: 'text';
|
|
17
|
+
text: string;
|
|
18
|
+
};
|
|
19
|
+
}[];
|
|
20
|
+
}
|
|
21
|
+
export type PromptHandler = (name: string, args: Record<string, unknown> | undefined) => Promise<PromptResponse>;
|
|
22
|
+
export declare class PromptManager {
|
|
23
|
+
private promptDefinitions;
|
|
24
|
+
private promptHandlers;
|
|
25
|
+
constructor();
|
|
26
|
+
registerPrompt(definition: PromptDefinition, handler: PromptHandler): void;
|
|
27
|
+
listPrompts(): {
|
|
28
|
+
prompts: PromptDefinition[];
|
|
29
|
+
};
|
|
30
|
+
getPrompt(name: string, args: Record<string, unknown> | undefined): Promise<PromptResponse>;
|
|
31
|
+
}
|