Update dependencies, enhance AI integration, and improve email content
Some checks failed
Deploy / deploy (push) Failing after 1h35m43s
Some checks failed
Deploy / deploy (push) Failing after 1h35m43s
- Added @google/genai dependency for enhanced AI capabilities. - Updated CI workflow to include new environment variables for AI integration. - Refactored AI client to support multiple providers and improved key management. - Enhanced email templates for better user engagement and clarity. - Updated error handling in AI-related functions to provide clearer feedback. - Made various improvements to the application structure and code clarity.
This commit is contained in:
@@ -26,7 +26,9 @@ jobs:
|
|||||||
IYZICO_API_KEY=${{ secrets.IYZICO_API_KEY }}
|
IYZICO_API_KEY=${{ secrets.IYZICO_API_KEY }}
|
||||||
IYZICO_SECRET_KEY=${{ secrets.IYZICO_SECRET_KEY }}
|
IYZICO_SECRET_KEY=${{ secrets.IYZICO_SECRET_KEY }}
|
||||||
IYZICO_BASE_URL=${{ secrets.IYZICO_BASE_URL }}
|
IYZICO_BASE_URL=${{ secrets.IYZICO_BASE_URL }}
|
||||||
|
AI_SAGLAYICI=${{ secrets.AI_SAGLAYICI }}
|
||||||
ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}
|
ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
|
GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
- name: Build & deploy
|
- name: Build & deploy
|
||||||
|
|||||||
BIN
data/app.db
BIN
data/app.db
Binary file not shown.
@@ -15,6 +15,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/sdk": "^0.112.4",
|
"@anthropic-ai/sdk": "^0.112.4",
|
||||||
"@cds/city": "^1.1.0",
|
"@cds/city": "^1.1.0",
|
||||||
|
"@google/genai": "^2.15.0",
|
||||||
"@libsql/client": "^0.17.4",
|
"@libsql/client": "^0.17.4",
|
||||||
"@number-flow/react": "^0.6.2",
|
"@number-flow/react": "^0.6.2",
|
||||||
"@react-pdf/renderer": "^4.5.1",
|
"@react-pdf/renderer": "^4.5.1",
|
||||||
|
|||||||
286
pnpm-lock.yaml
generated
286
pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
|||||||
'@cds/city':
|
'@cds/city':
|
||||||
specifier: ^1.1.0
|
specifier: ^1.1.0
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
|
'@google/genai':
|
||||||
|
specifier: ^2.15.0
|
||||||
|
version: 2.15.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))
|
||||||
'@libsql/client':
|
'@libsql/client':
|
||||||
specifier: ^0.17.4
|
specifier: ^0.17.4
|
||||||
version: 0.17.4
|
version: 0.17.4
|
||||||
@@ -920,6 +923,15 @@ packages:
|
|||||||
'@floating-ui/utils@0.2.12':
|
'@floating-ui/utils@0.2.12':
|
||||||
resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
|
resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
|
||||||
|
|
||||||
|
'@google/genai@2.15.0':
|
||||||
|
resolution: {integrity: sha512-Q41TvqwBQ9NcmWdh6qxY5qrpg+0FaVHD7febQoH007pykxzco4ohScBUP4BBBy+Q8j5D8euIBSRIBDfWuNVCKA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@modelcontextprotocol/sdk': ^1.25.2
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@modelcontextprotocol/sdk':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@hono/node-server@1.19.14':
|
'@hono/node-server@1.19.14':
|
||||||
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
||||||
engines: {node: '>=18.14.1'}
|
engines: {node: '>=18.14.1'}
|
||||||
@@ -1291,6 +1303,33 @@ packages:
|
|||||||
'@postman/tunnel-agent@0.6.8':
|
'@postman/tunnel-agent@0.6.8':
|
||||||
resolution: {integrity: sha512-2U42SmZW5G+suEcS++zB94sBWNO4qD4bvETGFRFDTqSpYl5ksfjcPqzYpgQgXgUmb6dfz+fAGbkcRamounGm0w==}
|
resolution: {integrity: sha512-2U42SmZW5G+suEcS++zB94sBWNO4qD4bvETGFRFDTqSpYl5ksfjcPqzYpgQgXgUmb6dfz+fAGbkcRamounGm0w==}
|
||||||
|
|
||||||
|
'@protobufjs/aspromise@1.1.2':
|
||||||
|
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
||||||
|
|
||||||
|
'@protobufjs/base64@1.1.2':
|
||||||
|
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
||||||
|
|
||||||
|
'@protobufjs/codegen@2.0.5':
|
||||||
|
resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
|
||||||
|
|
||||||
|
'@protobufjs/eventemitter@1.1.1':
|
||||||
|
resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==}
|
||||||
|
|
||||||
|
'@protobufjs/fetch@1.1.1':
|
||||||
|
resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==}
|
||||||
|
|
||||||
|
'@protobufjs/float@1.0.2':
|
||||||
|
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
||||||
|
|
||||||
|
'@protobufjs/path@1.1.2':
|
||||||
|
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
||||||
|
|
||||||
|
'@protobufjs/pool@1.1.0':
|
||||||
|
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
||||||
|
|
||||||
|
'@protobufjs/utf8@1.1.2':
|
||||||
|
resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==}
|
||||||
|
|
||||||
'@radix-ui/number@1.1.2':
|
'@radix-ui/number@1.1.2':
|
||||||
resolution: {integrity: sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==}
|
resolution: {integrity: sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==}
|
||||||
|
|
||||||
@@ -2305,6 +2344,9 @@ packages:
|
|||||||
'@types/react@19.2.17':
|
'@types/react@19.2.17':
|
||||||
resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==}
|
resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==}
|
||||||
|
|
||||||
|
'@types/retry@0.12.0':
|
||||||
|
resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
|
||||||
|
|
||||||
'@types/trusted-types@2.0.7':
|
'@types/trusted-types@2.0.7':
|
||||||
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||||
|
|
||||||
@@ -2742,6 +2784,9 @@ packages:
|
|||||||
bidi-js@1.0.3:
|
bidi-js@1.0.3:
|
||||||
resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
|
resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
|
||||||
|
|
||||||
|
bignumber.js@9.3.1:
|
||||||
|
resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
|
||||||
|
|
||||||
bindings@1.5.0:
|
bindings@1.5.0:
|
||||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
||||||
|
|
||||||
@@ -2777,6 +2822,9 @@ packages:
|
|||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1:
|
||||||
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
@@ -3129,6 +3177,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
|
data-uri-to-buffer@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
|
||||||
data-view-buffer@1.0.2:
|
data-view-buffer@1.0.2:
|
||||||
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
|
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3372,6 +3424,9 @@ packages:
|
|||||||
ecc-jsbn@0.1.2:
|
ecc-jsbn@0.1.2:
|
||||||
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
|
|
||||||
@@ -3689,6 +3744,10 @@ packages:
|
|||||||
picomatch:
|
picomatch:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
fetch-blob@3.2.0:
|
||||||
|
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||||
|
engines: {node: ^12.20 || >= 14.13}
|
||||||
|
|
||||||
fflate@0.8.3:
|
fflate@0.8.3:
|
||||||
resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==}
|
resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==}
|
||||||
|
|
||||||
@@ -3736,6 +3795,10 @@ packages:
|
|||||||
forever-agent@0.6.1:
|
forever-agent@0.6.1:
|
||||||
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
|
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
|
||||||
|
|
||||||
|
formdata-polyfill@4.0.10:
|
||||||
|
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
|
||||||
forwarded@0.2.0:
|
forwarded@0.2.0:
|
||||||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@@ -3783,6 +3846,14 @@ packages:
|
|||||||
fuzzysort@3.1.0:
|
fuzzysort@3.1.0:
|
||||||
resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==}
|
resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==}
|
||||||
|
|
||||||
|
gaxios@7.3.0:
|
||||||
|
resolution: {integrity: sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
gcp-metadata@8.1.2:
|
||||||
|
resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
generator-function@2.0.1:
|
generator-function@2.0.1:
|
||||||
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
|
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3852,6 +3923,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
|
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
google-auth-library@10.9.1:
|
||||||
|
resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
google-logging-utils@1.1.3:
|
||||||
|
resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
gopd@1.2.0:
|
gopd@1.2.0:
|
||||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3928,6 +4007,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==}
|
resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
|
https-proxy-agent@7.0.6:
|
||||||
|
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||||
|
engines: {node: '>= 14'}
|
||||||
|
|
||||||
human-signals@2.1.0:
|
human-signals@2.1.0:
|
||||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||||
engines: {node: '>=10.17.0'}
|
engines: {node: '>=10.17.0'}
|
||||||
@@ -4242,6 +4325,9 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
json-bigint@1.0.0:
|
||||||
|
resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
|
||||||
|
|
||||||
json-buffer@3.0.1:
|
json-buffer@3.0.1:
|
||||||
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
||||||
|
|
||||||
@@ -4293,6 +4379,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
|
||||||
|
jwa@2.0.1:
|
||||||
|
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
|
||||||
|
|
||||||
|
jws@4.0.1:
|
||||||
|
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
|
||||||
|
|
||||||
katex@0.16.47:
|
katex@0.16.47:
|
||||||
resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==}
|
resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -4444,6 +4536,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
|
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
long@5.3.2:
|
||||||
|
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
|
||||||
|
|
||||||
longest-streak@3.1.0:
|
longest-streak@3.1.0:
|
||||||
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
||||||
|
|
||||||
@@ -4759,10 +4854,19 @@ packages:
|
|||||||
resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==}
|
resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
node-domexception@1.0.0:
|
||||||
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
|
engines: {node: '>=10.5.0'}
|
||||||
|
deprecated: Use your platform's native DOMException instead
|
||||||
|
|
||||||
node-exports-info@1.6.2:
|
node-exports-info@1.6.2:
|
||||||
resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==}
|
resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
node-fetch@3.3.2:
|
||||||
|
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
|
||||||
node-releases@2.0.51:
|
node-releases@2.0.51:
|
||||||
resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==}
|
resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -4877,6 +4981,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
p-retry@4.6.2:
|
||||||
|
resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
p-try@2.2.0:
|
p-try@2.2.0:
|
||||||
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -5025,6 +5133,10 @@ packages:
|
|||||||
property-information@7.2.0:
|
property-information@7.2.0:
|
||||||
resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==}
|
resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==}
|
||||||
|
|
||||||
|
protobufjs@7.6.5:
|
||||||
|
resolution: {integrity: sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
proxy-addr@2.0.7:
|
proxy-addr@2.0.7:
|
||||||
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@@ -5213,6 +5325,10 @@ packages:
|
|||||||
restructure@3.0.2:
|
restructure@3.0.2:
|
||||||
resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
|
resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
|
||||||
|
|
||||||
|
retry@0.13.1:
|
||||||
|
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
reusify@1.1.0:
|
reusify@1.1.0:
|
||||||
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
||||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||||
@@ -5776,6 +5892,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==}
|
resolution: {integrity: sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
web-streams-polyfill@3.3.3:
|
||||||
|
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
which-boxed-primitive@1.1.1:
|
which-boxed-primitive@1.1.1:
|
||||||
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
|
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -6465,6 +6585,19 @@ snapshots:
|
|||||||
|
|
||||||
'@floating-ui/utils@0.2.12': {}
|
'@floating-ui/utils@0.2.12': {}
|
||||||
|
|
||||||
|
'@google/genai@2.15.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))':
|
||||||
|
dependencies:
|
||||||
|
google-auth-library: 10.9.1
|
||||||
|
p-retry: 4.6.2
|
||||||
|
protobufjs: 7.6.5
|
||||||
|
ws: 8.21.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bufferutil
|
||||||
|
- supports-color
|
||||||
|
- utf-8-validate
|
||||||
|
|
||||||
'@hono/node-server@1.19.14(hono@4.12.31)':
|
'@hono/node-server@1.19.14(hono@4.12.31)':
|
||||||
dependencies:
|
dependencies:
|
||||||
hono: 4.12.31
|
hono: 4.12.31
|
||||||
@@ -6693,6 +6826,29 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)':
|
||||||
|
dependencies:
|
||||||
|
'@hono/node-server': 1.19.14(hono@4.12.31)
|
||||||
|
ajv: 8.20.0
|
||||||
|
ajv-formats: 3.0.1(ajv@8.20.0)
|
||||||
|
content-type: 1.0.5
|
||||||
|
cors: 2.8.6
|
||||||
|
cross-spawn: 7.0.6
|
||||||
|
eventsource: 3.0.7
|
||||||
|
eventsource-parser: 3.1.0
|
||||||
|
express: 5.2.1
|
||||||
|
express-rate-limit: 8.6.0(express@5.2.1)
|
||||||
|
hono: 4.12.31
|
||||||
|
jose: 6.2.3
|
||||||
|
json-schema-typed: 8.0.2
|
||||||
|
pkce-challenge: 5.0.1
|
||||||
|
raw-body: 3.0.2
|
||||||
|
zod: 4.4.3
|
||||||
|
zod-to-json-schema: 3.25.2(zod@4.4.3)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
|
'@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emnapi/core': 1.10.0
|
'@emnapi/core': 1.10.0
|
||||||
@@ -6780,6 +6936,26 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
'@protobufjs/aspromise@1.1.2': {}
|
||||||
|
|
||||||
|
'@protobufjs/base64@1.1.2': {}
|
||||||
|
|
||||||
|
'@protobufjs/codegen@2.0.5': {}
|
||||||
|
|
||||||
|
'@protobufjs/eventemitter@1.1.1': {}
|
||||||
|
|
||||||
|
'@protobufjs/fetch@1.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@protobufjs/aspromise': 1.1.2
|
||||||
|
|
||||||
|
'@protobufjs/float@1.0.2': {}
|
||||||
|
|
||||||
|
'@protobufjs/path@1.1.2': {}
|
||||||
|
|
||||||
|
'@protobufjs/pool@1.1.0': {}
|
||||||
|
|
||||||
|
'@protobufjs/utf8@1.1.2': {}
|
||||||
|
|
||||||
'@radix-ui/number@1.1.2': {}
|
'@radix-ui/number@1.1.2': {}
|
||||||
|
|
||||||
'@radix-ui/primitive@1.1.6': {}
|
'@radix-ui/primitive@1.1.6': {}
|
||||||
@@ -7926,6 +8102,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
csstype: 3.2.3
|
csstype: 3.2.3
|
||||||
|
|
||||||
|
'@types/retry@0.12.0': {}
|
||||||
|
|
||||||
'@types/trusted-types@2.0.7':
|
'@types/trusted-types@2.0.7':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -8323,6 +8501,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
require-from-string: 2.0.2
|
require-from-string: 2.0.2
|
||||||
|
|
||||||
|
bignumber.js@9.3.1: {}
|
||||||
|
|
||||||
bindings@1.5.0:
|
bindings@1.5.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
file-uri-to-path: 1.0.0
|
file-uri-to-path: 1.0.0
|
||||||
@@ -8378,6 +8558,8 @@ snapshots:
|
|||||||
node-releases: 2.0.51
|
node-releases: 2.0.51
|
||||||
update-browserslist-db: 1.2.3(browserslist@4.28.6)
|
update-browserslist-db: 1.2.3(browserslist@4.28.6)
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
@@ -8728,6 +8910,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus: 1.0.0
|
assert-plus: 1.0.0
|
||||||
|
|
||||||
|
data-uri-to-buffer@4.0.1: {}
|
||||||
|
|
||||||
data-view-buffer@1.0.2:
|
data-view-buffer@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
@@ -8864,6 +9048,10 @@ snapshots:
|
|||||||
jsbn: 0.1.1
|
jsbn: 0.1.1
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
|
|
||||||
electron-to-chromium@1.5.394: {}
|
electron-to-chromium@1.5.394: {}
|
||||||
@@ -9429,6 +9617,11 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
picomatch: 4.0.5
|
picomatch: 4.0.5
|
||||||
|
|
||||||
|
fetch-blob@3.2.0:
|
||||||
|
dependencies:
|
||||||
|
node-domexception: 1.0.0
|
||||||
|
web-streams-polyfill: 3.3.3
|
||||||
|
|
||||||
fflate@0.8.3: {}
|
fflate@0.8.3: {}
|
||||||
|
|
||||||
figures@6.1.0:
|
figures@6.1.0:
|
||||||
@@ -9490,6 +9683,10 @@ snapshots:
|
|||||||
|
|
||||||
forever-agent@0.6.1: {}
|
forever-agent@0.6.1: {}
|
||||||
|
|
||||||
|
formdata-polyfill@4.0.10:
|
||||||
|
dependencies:
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
|
||||||
forwarded@0.2.0: {}
|
forwarded@0.2.0: {}
|
||||||
|
|
||||||
framer-motion@12.42.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
framer-motion@12.42.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||||
@@ -9532,6 +9729,22 @@ snapshots:
|
|||||||
|
|
||||||
fuzzysort@3.1.0: {}
|
fuzzysort@3.1.0: {}
|
||||||
|
|
||||||
|
gaxios@7.3.0:
|
||||||
|
dependencies:
|
||||||
|
extend: 3.0.2
|
||||||
|
https-proxy-agent: 7.0.6
|
||||||
|
node-fetch: 3.3.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
gcp-metadata@8.1.2:
|
||||||
|
dependencies:
|
||||||
|
gaxios: 7.3.0
|
||||||
|
google-logging-utils: 1.1.3
|
||||||
|
json-bigint: 1.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
generator-function@2.0.1: {}
|
generator-function@2.0.1: {}
|
||||||
|
|
||||||
gensync@1.0.0-beta.2: {}
|
gensync@1.0.0-beta.2: {}
|
||||||
@@ -9600,6 +9813,19 @@ snapshots:
|
|||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
|
|
||||||
|
google-auth-library@10.9.1:
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
gaxios: 7.3.0
|
||||||
|
gcp-metadata: 8.1.2
|
||||||
|
google-logging-utils: 1.1.3
|
||||||
|
jws: 4.0.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
google-logging-utils@1.1.3: {}
|
||||||
|
|
||||||
gopd@1.2.0: {}
|
gopd@1.2.0: {}
|
||||||
|
|
||||||
graceful-fs@4.2.11: {}
|
graceful-fs@4.2.11: {}
|
||||||
@@ -9698,6 +9924,13 @@ snapshots:
|
|||||||
jsprim: 2.0.2
|
jsprim: 2.0.2
|
||||||
sshpk: 1.18.0
|
sshpk: 1.18.0
|
||||||
|
|
||||||
|
https-proxy-agent@7.0.6:
|
||||||
|
dependencies:
|
||||||
|
agent-base: 7.1.4
|
||||||
|
debug: 4.4.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
human-signals@2.1.0: {}
|
human-signals@2.1.0: {}
|
||||||
|
|
||||||
human-signals@8.0.1: {}
|
human-signals@8.0.1: {}
|
||||||
@@ -9963,6 +10196,10 @@ snapshots:
|
|||||||
|
|
||||||
jsesc@3.1.0: {}
|
jsesc@3.1.0: {}
|
||||||
|
|
||||||
|
json-bigint@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
bignumber.js: 9.3.1
|
||||||
|
|
||||||
json-buffer@3.0.1: {}
|
json-buffer@3.0.1: {}
|
||||||
|
|
||||||
json-parse-even-better-errors@2.3.1: {}
|
json-parse-even-better-errors@2.3.1: {}
|
||||||
@@ -10012,6 +10249,17 @@ snapshots:
|
|||||||
object.assign: 4.1.7
|
object.assign: 4.1.7
|
||||||
object.values: 1.2.1
|
object.values: 1.2.1
|
||||||
|
|
||||||
|
jwa@2.0.1:
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time: 1.0.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
jws@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
jwa: 2.0.1
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
katex@0.16.47:
|
katex@0.16.47:
|
||||||
dependencies:
|
dependencies:
|
||||||
commander: 8.3.0
|
commander: 8.3.0
|
||||||
@@ -10136,6 +10384,8 @@ snapshots:
|
|||||||
chalk: 5.6.2
|
chalk: 5.6.2
|
||||||
is-unicode-supported: 1.3.0
|
is-unicode-supported: 1.3.0
|
||||||
|
|
||||||
|
long@5.3.2: {}
|
||||||
|
|
||||||
longest-streak@3.1.0: {}
|
longest-streak@3.1.0: {}
|
||||||
|
|
||||||
loose-envify@1.4.0:
|
loose-envify@1.4.0:
|
||||||
@@ -10643,6 +10893,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
semver: 7.8.5
|
semver: 7.8.5
|
||||||
|
|
||||||
|
node-domexception@1.0.0: {}
|
||||||
|
|
||||||
node-exports-info@1.6.2:
|
node-exports-info@1.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
array.prototype.flatmap: 1.3.3
|
array.prototype.flatmap: 1.3.3
|
||||||
@@ -10650,6 +10902,12 @@ snapshots:
|
|||||||
object.entries: 1.1.9
|
object.entries: 1.1.9
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
|
|
||||||
|
node-fetch@3.3.2:
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer: 4.0.1
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
formdata-polyfill: 4.0.10
|
||||||
|
|
||||||
node-releases@2.0.51: {}
|
node-releases@2.0.51: {}
|
||||||
|
|
||||||
normalize-svg-path@1.1.0:
|
normalize-svg-path@1.1.0:
|
||||||
@@ -10797,6 +11055,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-limit: 3.1.0
|
p-limit: 3.1.0
|
||||||
|
|
||||||
|
p-retry@4.6.2:
|
||||||
|
dependencies:
|
||||||
|
'@types/retry': 0.12.0
|
||||||
|
retry: 0.13.1
|
||||||
|
|
||||||
p-try@2.2.0: {}
|
p-try@2.2.0: {}
|
||||||
|
|
||||||
package-manager-detector@1.8.0: {}
|
package-manager-detector@1.8.0: {}
|
||||||
@@ -10957,6 +11220,20 @@ snapshots:
|
|||||||
|
|
||||||
property-information@7.2.0: {}
|
property-information@7.2.0: {}
|
||||||
|
|
||||||
|
protobufjs@7.6.5:
|
||||||
|
dependencies:
|
||||||
|
'@protobufjs/aspromise': 1.1.2
|
||||||
|
'@protobufjs/base64': 1.1.2
|
||||||
|
'@protobufjs/codegen': 2.0.5
|
||||||
|
'@protobufjs/eventemitter': 1.1.1
|
||||||
|
'@protobufjs/fetch': 1.1.1
|
||||||
|
'@protobufjs/float': 1.0.2
|
||||||
|
'@protobufjs/path': 1.1.2
|
||||||
|
'@protobufjs/pool': 1.1.0
|
||||||
|
'@protobufjs/utf8': 1.1.2
|
||||||
|
'@types/node': 20.19.43
|
||||||
|
long: 5.3.2
|
||||||
|
|
||||||
proxy-addr@2.0.7:
|
proxy-addr@2.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
forwarded: 0.2.0
|
forwarded: 0.2.0
|
||||||
@@ -11242,6 +11519,8 @@ snapshots:
|
|||||||
|
|
||||||
restructure@3.0.2: {}
|
restructure@3.0.2: {}
|
||||||
|
|
||||||
|
retry@0.13.1: {}
|
||||||
|
|
||||||
reusify@1.1.0: {}
|
reusify@1.1.0: {}
|
||||||
|
|
||||||
robust-predicates@3.0.3: {}
|
robust-predicates@3.0.3: {}
|
||||||
@@ -11977,6 +12256,8 @@ snapshots:
|
|||||||
string_decoder: 1.3.0
|
string_decoder: 1.3.0
|
||||||
util-deprecate: 1.0.2
|
util-deprecate: 1.0.2
|
||||||
|
|
||||||
|
web-streams-polyfill@3.3.3: {}
|
||||||
|
|
||||||
which-boxed-primitive@1.1.1:
|
which-boxed-primitive@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-bigint: 1.1.0
|
is-bigint: 1.1.0
|
||||||
@@ -12053,6 +12334,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
|
|
||||||
|
zod-to-json-schema@3.25.2(zod@4.4.3):
|
||||||
|
dependencies:
|
||||||
|
zod: 4.4.3
|
||||||
|
optional: true
|
||||||
|
|
||||||
zod-validation-error@4.0.2(zod@4.4.3):
|
zod-validation-error@4.0.2(zod@4.4.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
zod: 4.4.3
|
zod: 4.4.3
|
||||||
|
|||||||
BIN
public/kolay-tercih-mark.png
Normal file
BIN
public/kolay-tercih-mark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
@@ -3,7 +3,8 @@ import type { NextRequest } from "next/server";
|
|||||||
import { getSession } from "@/lib/session";
|
import { getSession } from "@/lib/session";
|
||||||
import { appDb, schema } from "@/lib/appdb";
|
import { appDb, schema } from "@/lib/appdb";
|
||||||
import { spendCreditForMessage, grantCredits } from "@/lib/credits";
|
import { spendCreditForMessage, grantCredits } from "@/lib/credits";
|
||||||
import { getAnthropic, SOHBET_MODEL, SORUMLULUK_REDDI } from "@/lib/ai/client";
|
import { anahtarVar, SORUMLULUK_REDDI } from "@/lib/ai/client";
|
||||||
|
import { sohbetAkisi } from "@/lib/ai/cagri";
|
||||||
import { listeOzetiCikar, type RaporSonuc } from "@/lib/ai/rapor";
|
import { listeOzetiCikar, type RaporSonuc } from "@/lib/ai/rapor";
|
||||||
import type { RaporParams } from "@/lib/rapor-havuzu";
|
import type { RaporParams } from "@/lib/rapor-havuzu";
|
||||||
import { secimOzeti } from "@/lib/sihirbaz";
|
import { secimOzeti } from "@/lib/sihirbaz";
|
||||||
@@ -183,15 +184,11 @@ export async function POST(request: NextRequest) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Dev'de API key yoksa danışman mock cevap stream'ler (prod'da asla)
|
// Dev'de API key yoksa danışman mock cevap stream'ler (prod'da asla)
|
||||||
if (
|
if (process.env.NODE_ENV !== "production" && !anahtarVar()) {
|
||||||
process.env.NODE_ENV !== "production" &&
|
|
||||||
!process.env.ANTHROPIC_API_KEY &&
|
|
||||||
!process.env.ANTHROPIC_AUTH_TOKEN
|
|
||||||
) {
|
|
||||||
const mockEncoder = new TextEncoder();
|
const mockEncoder = new TextEncoder();
|
||||||
const mockUserId = session.user.id;
|
const mockUserId = session.user.id;
|
||||||
const cevap =
|
const cevap =
|
||||||
`(Dev mock — ANTHROPIC_API_KEY tanımlı değil.) Sorunu aldım: "${mesaj.slice(0, 120)}". ` +
|
`(Dev mock — Yapay Zeka anahtarı tanımlı değil.) Sorunu aldım: "${mesaj.slice(0, 120)}". ` +
|
||||||
`Gerçek danışman burada listen ve seçimlerin bağlamında yanıt verecek. ` +
|
`Gerçek danışman burada listen ve seçimlerin bağlamında yanıt verecek. ` +
|
||||||
`${SORUMLULUK_REDDI}`;
|
`${SORUMLULUK_REDDI}`;
|
||||||
const mockReadable = new ReadableStream({
|
const mockReadable = new ReadableStream({
|
||||||
@@ -219,17 +216,14 @@ export async function POST(request: NextRequest) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let client;
|
if (!anahtarVar()) {
|
||||||
try {
|
|
||||||
client = getAnthropic();
|
|
||||||
} catch {
|
|
||||||
await grantCredits({
|
await grantCredits({
|
||||||
userId: session.user.id,
|
userId: session.user.id,
|
||||||
delta: 1,
|
delta: 1,
|
||||||
reason: "refund",
|
reason: "refund",
|
||||||
refId: kullaniciMesajId,
|
refId: kullaniciMesajId,
|
||||||
});
|
});
|
||||||
console.error("[soru] Yapay Zeka istemcisi kurulamadı (anahtar eksik olabilir)");
|
console.error("[soru] Yapay Zeka anahtarı tanımlı değil");
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{
|
{
|
||||||
error:
|
error:
|
||||||
@@ -250,36 +244,20 @@ export async function POST(request: NextRequest) {
|
|||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
const userId = session.user.id;
|
const userId = session.user.id;
|
||||||
|
|
||||||
let stream;
|
|
||||||
try {
|
|
||||||
stream = client.messages.stream({
|
|
||||||
model: SOHBET_MODEL,
|
|
||||||
max_tokens: 1024,
|
|
||||||
system,
|
|
||||||
messages: mesajlar,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
await grantCredits({ userId, delta: 1, reason: "refund", refId: kullaniciMesajId });
|
|
||||||
return Response.json({ error: "Yapay Zeka'ya ulaşılamadı." }, { status: 502 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const readable = new ReadableStream({
|
const readable = new ReadableStream({
|
||||||
async start(controller) {
|
async start(controller) {
|
||||||
let tamamlandi = false;
|
let tamamlandi = false;
|
||||||
try {
|
try {
|
||||||
for await (const event of stream) {
|
// Sağlayıcıya bağlanma hatası da ilk parçada burada yakalanır
|
||||||
if (
|
let metin = "";
|
||||||
event.type === "content_block_delta" &&
|
for await (const parca of sohbetAkisi({
|
||||||
event.delta.type === "text_delta"
|
system,
|
||||||
) {
|
mesajlar,
|
||||||
controller.enqueue(encoder.encode(event.delta.text));
|
maxTokens: 1024,
|
||||||
}
|
})) {
|
||||||
|
metin += parca;
|
||||||
|
controller.enqueue(encoder.encode(parca));
|
||||||
}
|
}
|
||||||
const final = await stream.finalMessage();
|
|
||||||
const metin = final.content
|
|
||||||
.filter((b) => b.type === "text")
|
|
||||||
.map((b) => b.text)
|
|
||||||
.join("");
|
|
||||||
await appDb.insert(schema.chatMessages).values({
|
await appDb.insert(schema.chatMessages).values({
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
userId,
|
userId,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function aiHataMesaji(err: unknown): string {
|
|||||||
if (err instanceof RaporUretimHatasi) return err.message;
|
if (err instanceof RaporUretimHatasi) return err.message;
|
||||||
if (err instanceof Error && err.message === "AI_KEY_MISSING") {
|
if (err instanceof Error && err.message === "AI_KEY_MISSING") {
|
||||||
// Yapılandırma detayı log'a; kullanıcıya altyapı sızdırmayan mesaj
|
// Yapılandırma detayı log'a; kullanıcıya altyapı sızdırmayan mesaj
|
||||||
console.error("[liste] ANTHROPIC_API_KEY eksik — üretim başlatılamadı");
|
console.error("[liste] Yapay Zeka anahtarı eksik — üretim başlatılamadı");
|
||||||
return "Liste üretimi şu anda başlatılamıyor. Birazdan tekrar dener misin? Harcanan kredin otomatik iade edilir.";
|
return "Liste üretimi şu anda başlatılamıyor. Birazdan tekrar dener misin? Harcanan kredin otomatik iade edilir.";
|
||||||
}
|
}
|
||||||
console.error("[liste] üretim hatası:", err);
|
console.error("[liste] üretim hatası:", err);
|
||||||
|
|||||||
158
src/lib/ai/cagri.ts
Normal file
158
src/lib/ai/cagri.ts
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";
|
||||||
|
import { ThinkingLevel } from "@google/genai";
|
||||||
|
import {
|
||||||
|
getAnthropic,
|
||||||
|
getGemini,
|
||||||
|
raporModeli,
|
||||||
|
saglayici,
|
||||||
|
sohbetModeli,
|
||||||
|
} from "./client";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sağlayıcıdan bağımsız AI çağrı katmanı. Anthropic ve Gemini'nin SDK'ları
|
||||||
|
* yapılandırılmış çıktı ve stream için farklı şekiller kullanıyor; rapor ve
|
||||||
|
* sohbet kodu bu farkı görmesin diye tek arayüz burada toplanıyor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gemini JSON Schema'nın yalnızca bir alt kümesini destekliyor; zod'un ürettiği
|
||||||
|
* $schema ve additionalProperties alanları isteği reddettiriyor, ayıklanıyor.
|
||||||
|
*/
|
||||||
|
function geminiSemasi(sema: z.ZodType): unknown {
|
||||||
|
const temizle = (dugum: unknown): unknown => {
|
||||||
|
if (Array.isArray(dugum)) return dugum.map(temizle);
|
||||||
|
if (dugum && typeof dugum === "object") {
|
||||||
|
const cikti: Record<string, unknown> = {};
|
||||||
|
for (const [k, v] of Object.entries(dugum as Record<string, unknown>)) {
|
||||||
|
if (k === "$schema" || k === "additionalProperties") continue;
|
||||||
|
cikti[k] = temizle(v);
|
||||||
|
}
|
||||||
|
return cikti;
|
||||||
|
}
|
||||||
|
return dugum;
|
||||||
|
};
|
||||||
|
return temizle(z.toJSONSchema(sema));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gemini ücretsiz katmanı yoğunlukta 503/429 döndürüyor; bu geçici hatalarda
|
||||||
|
* artan bekleme ile yeniden dene. Kalıcı hatalar (400, 403) olduğu gibi fırlar.
|
||||||
|
*/
|
||||||
|
const GECICI_KODLAR = new Set([429, 500, 502, 503, 504]);
|
||||||
|
|
||||||
|
async function geciciHatadaTekrarla<T>(
|
||||||
|
islem: () => Promise<T>,
|
||||||
|
denemeSayisi = 3,
|
||||||
|
): Promise<T> {
|
||||||
|
let sonHata: unknown;
|
||||||
|
for (let i = 0; i < denemeSayisi; i++) {
|
||||||
|
try {
|
||||||
|
return await islem();
|
||||||
|
} catch (hata) {
|
||||||
|
const kod = (hata as { status?: number })?.status;
|
||||||
|
if (kod == null || !GECICI_KODLAR.has(kod) || i === denemeSayisi - 1) {
|
||||||
|
throw hata;
|
||||||
|
}
|
||||||
|
sonHata = hata;
|
||||||
|
await new Promise((r) => setTimeout(r, 2000 * 2 ** i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw sonHata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Şemaya uyan tek seferlik çıktı üretir. Şemaya uymayan yanıtta null döner
|
||||||
|
* (çağıran taraf yeniden dener).
|
||||||
|
*/
|
||||||
|
export async function yapilandirilmisUret<T extends z.ZodType>(opts: {
|
||||||
|
system: string;
|
||||||
|
kullanici: string;
|
||||||
|
sema: T;
|
||||||
|
maxTokens: number;
|
||||||
|
}): Promise<z.infer<T> | null> {
|
||||||
|
if (saglayici() === "gemini") {
|
||||||
|
const yanit = await geciciHatadaTekrarla(() =>
|
||||||
|
getGemini().models.generateContent({
|
||||||
|
model: raporModeli(),
|
||||||
|
contents: opts.kullanici,
|
||||||
|
config: {
|
||||||
|
systemInstruction: opts.system,
|
||||||
|
maxOutputTokens: opts.maxTokens,
|
||||||
|
responseMimeType: "application/json",
|
||||||
|
responseJsonSchema: geminiSemasi(opts.sema),
|
||||||
|
thinkingConfig: { thinkingLevel: ThinkingLevel.HIGH },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const metin = yanit.text;
|
||||||
|
if (!metin) return null;
|
||||||
|
try {
|
||||||
|
const parsed = opts.sema.safeParse(JSON.parse(metin));
|
||||||
|
return parsed.success ? parsed.data : null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const yanit = await getAnthropic().messages.parse({
|
||||||
|
model: raporModeli(),
|
||||||
|
max_tokens: opts.maxTokens,
|
||||||
|
thinking: { type: "adaptive" },
|
||||||
|
system: opts.system,
|
||||||
|
messages: [{ role: "user", content: opts.kullanici }],
|
||||||
|
output_config: { format: zodOutputFormat(opts.sema) },
|
||||||
|
});
|
||||||
|
return yanit.parsed_output ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SohbetMesaji = { role: "user" | "assistant"; content: string };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sohbet yanıtını parça parça üretir. Sağlayıcıya bakmaksızın düz metin
|
||||||
|
* parçaları yield eder; çağıran taraf hem stream'ler hem biriktirip kaydeder.
|
||||||
|
*/
|
||||||
|
export async function* sohbetAkisi(opts: {
|
||||||
|
system: string;
|
||||||
|
mesajlar: SohbetMesaji[];
|
||||||
|
maxTokens: number;
|
||||||
|
}): AsyncGenerator<string> {
|
||||||
|
if (saglayici() === "gemini") {
|
||||||
|
const akis = await geciciHatadaTekrarla(() =>
|
||||||
|
getGemini().models.generateContentStream({
|
||||||
|
model: sohbetModeli(),
|
||||||
|
contents: opts.mesajlar.map((m) => ({
|
||||||
|
// Gemini "assistant" yerine "model" rolünü kullanır
|
||||||
|
role: m.role === "assistant" ? "model" : "user",
|
||||||
|
parts: [{ text: m.content }],
|
||||||
|
})),
|
||||||
|
config: {
|
||||||
|
systemInstruction: opts.system,
|
||||||
|
maxOutputTokens: opts.maxTokens,
|
||||||
|
// Sohbet kısa ve hızlı olmalı; uzun düşünme adayı bekletiyor
|
||||||
|
thinkingConfig: { thinkingLevel: ThinkingLevel.LOW },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
for await (const parca of akis) {
|
||||||
|
const metin = parca.text;
|
||||||
|
if (metin) yield metin;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const akis = getAnthropic().messages.stream({
|
||||||
|
model: sohbetModeli(),
|
||||||
|
max_tokens: opts.maxTokens,
|
||||||
|
system: opts.system,
|
||||||
|
messages: opts.mesajlar,
|
||||||
|
});
|
||||||
|
for await (const olay of akis) {
|
||||||
|
if (
|
||||||
|
olay.type === "content_block_delta" &&
|
||||||
|
olay.delta.type === "text_delta"
|
||||||
|
) {
|
||||||
|
yield olay.delta.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,44 @@
|
|||||||
import Anthropic from "@anthropic-ai/sdk";
|
import Anthropic from "@anthropic-ai/sdk";
|
||||||
|
import { GoogleGenAI } from "@google/genai";
|
||||||
|
|
||||||
// Model seçimi (bilinçli): rapor tek seferlik ve yüksek değerli -> Opus 4.8;
|
export type Saglayici = "anthropic" | "gemini";
|
||||||
|
|
||||||
|
/** AI_SAGLAYICI env'i ile seçilir; tanımsızsa hangi anahtar varsa o kullanılır. */
|
||||||
|
export function saglayici(): Saglayici {
|
||||||
|
const secim = process.env.AI_SAGLAYICI?.trim().toLowerCase();
|
||||||
|
if (secim === "gemini" || secim === "anthropic") return secim;
|
||||||
|
return process.env.GEMINI_API_KEY ? "gemini" : "anthropic";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Seçili sağlayıcının anahtarı tanımlı mı (mock moduna düşülecek mi)? */
|
||||||
|
export function anahtarVar(): boolean {
|
||||||
|
return saglayici() === "gemini"
|
||||||
|
? Boolean(process.env.GEMINI_API_KEY)
|
||||||
|
: Boolean(process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Model seçimi (bilinçli):
|
||||||
|
// Anthropic — rapor tek seferlik ve yüksek değerli -> Opus 4.8;
|
||||||
// sohbet kredi başına marj hassas -> Haiku 4.5 (kullanıcı kararı, 22 Tem 2026).
|
// sohbet kredi başına marj hassas -> Haiku 4.5 (kullanıcı kararı, 22 Tem 2026).
|
||||||
export const RAPOR_MODEL = "claude-opus-4-8";
|
// Gemini — ücretsiz katmanda yalnızca Flash ailesi açık (Pro'da kota 0),
|
||||||
export const SOHBET_MODEL = "claude-haiku-4-5";
|
// bu yüzden rapor ve sohbet aynı modeli kullanır; ayrım thinking seviyesinde.
|
||||||
|
const MODELLER: Record<Saglayici, { rapor: string; sohbet: string }> = {
|
||||||
|
anthropic: { rapor: "claude-opus-4-8", sohbet: "claude-haiku-4-5" },
|
||||||
|
gemini: { rapor: "gemini-3.6-flash", sohbet: "gemini-3.6-flash" },
|
||||||
|
};
|
||||||
|
|
||||||
const globalForAi = globalThis as unknown as { __anthropic?: Anthropic };
|
export function raporModeli(): string {
|
||||||
|
return MODELLER[saglayici()].rapor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sohbetModeli(): string {
|
||||||
|
return MODELLER[saglayici()].sohbet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const globalForAi = globalThis as unknown as {
|
||||||
|
__anthropic?: Anthropic;
|
||||||
|
__gemini?: GoogleGenAI;
|
||||||
|
};
|
||||||
|
|
||||||
export function getAnthropic(): Anthropic {
|
export function getAnthropic(): Anthropic {
|
||||||
if (!process.env.ANTHROPIC_API_KEY && !process.env.ANTHROPIC_AUTH_TOKEN) {
|
if (!process.env.ANTHROPIC_API_KEY && !process.env.ANTHROPIC_AUTH_TOKEN) {
|
||||||
@@ -17,5 +50,16 @@ export function getAnthropic(): Anthropic {
|
|||||||
return globalForAi.__anthropic;
|
return globalForAi.__anthropic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGemini(): GoogleGenAI {
|
||||||
|
const apiKey = process.env.GEMINI_API_KEY;
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new Error("AI_KEY_MISSING");
|
||||||
|
}
|
||||||
|
if (!globalForAi.__gemini) {
|
||||||
|
globalForAi.__gemini = new GoogleGenAI({ apiKey });
|
||||||
|
}
|
||||||
|
return globalForAi.__gemini;
|
||||||
|
}
|
||||||
|
|
||||||
export const SORUMLULUK_REDDI =
|
export const SORUMLULUK_REDDI =
|
||||||
"KolayTercih bir karar destek aracıdır; öneriler resmî YÖK Atlas verisine dayanır ancak yerleşme garantisi verilmez. Nihai tercih sorumluluğu adaya aittir.";
|
"KolayTercih bir karar destek aracıdır; öneriler resmî YÖK Atlas verisine dayanır ancak yerleşme garantisi verilmez. Nihai tercih sorumluluğu adaya aittir.";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";
|
import { anahtarVar } from "./client";
|
||||||
import { getAnthropic, RAPOR_MODEL } from "./client";
|
import { yapilandirilmisUret } from "./cagri";
|
||||||
import {
|
import {
|
||||||
havuzOlustur,
|
havuzOlustur,
|
||||||
havuzuKompaktJson,
|
havuzuKompaktJson,
|
||||||
@@ -88,11 +88,7 @@ function programBilgisi(p: AdayProgram): RaporSonuc["programlar"][string] {
|
|||||||
// gerçek Yapay Zeka olmadan uçtan uca test edilebilsin diye. Prod'da asla çalışmaz.
|
// gerçek Yapay Zeka olmadan uçtan uca test edilebilsin diye. Prod'da asla çalışmaz.
|
||||||
|
|
||||||
function mockAktif(): boolean {
|
function mockAktif(): boolean {
|
||||||
return (
|
return process.env.NODE_ENV !== "production" && !anahtarVar();
|
||||||
process.env.NODE_ENV !== "production" &&
|
|
||||||
!process.env.ANTHROPIC_API_KEY &&
|
|
||||||
!process.env.ANTHROPIC_AUTH_TOKEN
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mockRapor(
|
function mockRapor(
|
||||||
@@ -140,7 +136,7 @@ function mockRapor(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
tercihler,
|
tercihler,
|
||||||
genelDegerlendirme: `(Dev mock — ANTHROPIC_API_KEY tanımlı değil, bu rapor gerçek Yapay Zeka çıktısı değildir.) ${params.sira.toLocaleString(
|
genelDegerlendirme: `(Dev mock — Yapay Zeka anahtarı tanımlı değil, bu rapor gerçek Yapay Zeka çıktısı değildir.) ${params.sira.toLocaleString(
|
||||||
"tr-TR",
|
"tr-TR",
|
||||||
)}. sıra için hayal/dengeli/garanti dağılımlı 24 tercihlik örnek liste kuruldu.${
|
)}. sıra için hayal/dengeli/garanti dağılımlı 24 tercihlik örnek liste kuruldu.${
|
||||||
revizyonNotu ? ` Revizyon isteğin not alındı: "${revizyonNotu}".` : ""
|
revizyonNotu ? ` Revizyon isteğin not alındı: "${revizyonNotu}".` : ""
|
||||||
@@ -189,7 +185,6 @@ export async function raporUret(
|
|||||||
return mockRapor(havuz, params, revizyonNotu);
|
return mockRapor(havuz, params, revizyonNotu);
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = getAnthropic();
|
|
||||||
const havuzJson = havuzuKompaktJson(havuz);
|
const havuzJson = havuzuKompaktJson(havuz);
|
||||||
const kullaniciMesaji = [
|
const kullaniciMesaji = [
|
||||||
`Aday bilgisi: başarı sıralaması ${params.sira.toLocaleString("tr-TR")}, puan türü ${turLabel(params.tur)}.`,
|
`Aday bilgisi: başarı sıralaması ${params.sira.toLocaleString("tr-TR")}, puan türü ${turLabel(params.tur)}.`,
|
||||||
@@ -215,24 +210,16 @@ export async function raporUret(
|
|||||||
let sonuc: z.infer<typeof RaporSchema> | null = null;
|
let sonuc: z.infer<typeof RaporSchema> | null = null;
|
||||||
let sonHata = "";
|
let sonHata = "";
|
||||||
for (let deneme = 0; deneme < 2; deneme++) {
|
for (let deneme = 0; deneme < 2; deneme++) {
|
||||||
const response = await client.messages.parse({
|
const parsed = await yapilandirilmisUret({
|
||||||
model: RAPOR_MODEL,
|
|
||||||
max_tokens: 16000,
|
|
||||||
thinking: { type: "adaptive" },
|
|
||||||
system: SISTEM,
|
system: SISTEM,
|
||||||
messages: [
|
kullanici:
|
||||||
{
|
deneme === 0
|
||||||
role: "user",
|
? kullaniciMesaji
|
||||||
content:
|
: `${kullaniciMesaji}\n\nÖNCEKİ DENEMENDE HATA VARDI: ${sonHata} Kurallara tam uy.`,
|
||||||
deneme === 0
|
sema: RaporSchema,
|
||||||
? kullaniciMesaji
|
maxTokens: 16000,
|
||||||
: `${kullaniciMesaji}\n\nÖNCEKİ DENEMENDE HATA VARDI: ${sonHata} Kurallara tam uy.`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
output_config: { format: zodOutputFormat(RaporSchema) },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const parsed = response.parsed_output;
|
|
||||||
if (!parsed) {
|
if (!parsed) {
|
||||||
sonHata = "Çıktı şemaya uymadı.";
|
sonHata = "Çıktı şemaya uymadı.";
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
*
|
*
|
||||||
* Kurallar: mail istemcileri harici CSS, <style> kuralı, flexbox ve SVG
|
* Kurallar: mail istemcileri harici CSS, <style> kuralı, flexbox ve SVG
|
||||||
* desteğini güvenilir biçimde sunmaz — bu yüzden düzen tablo tabanlı ve tüm
|
* desteğini güvenilir biçimde sunmaz — bu yüzden düzen tablo tabanlı ve tüm
|
||||||
* stiller satır içi. Logo işareti de SVG yerine renkli hücrelerle yeniden
|
* stiller satır içi. Logo işareti sitedeki SVG'nin raster kopyası olan
|
||||||
* çizilir (Outlook masaüstü border-radius'u yok sayar; kareler köşeli görünür,
|
* `/kolay-tercih-mark.png` ile gösterilir (SVG'yi Gmail/Outlook engeller).
|
||||||
* kabul edilebilir bozulma).
|
* Web fontları (Bricolage Grotesque, Cal Sans) <link> ile progresif olarak
|
||||||
|
* yüklenir; desteklemeyen istemciler sistem yazı tipine düşer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { SITE_URL } from "./seo";
|
||||||
|
|
||||||
const MAVI = "#3b82f6";
|
const MAVI = "#3b82f6";
|
||||||
const SEFTALI = "#fdc7a7";
|
|
||||||
const TURUNCU = "#ff5a00";
|
|
||||||
const LACIVERT = "#0f172b";
|
const LACIVERT = "#0f172b";
|
||||||
const GRI = "#475569";
|
const GRI = "#475569";
|
||||||
const KENAR = "#e2e8f0";
|
const KENAR = "#e2e8f0";
|
||||||
@@ -18,6 +19,10 @@ const ZEMIN = "#f8fafc";
|
|||||||
|
|
||||||
const YAZI_TIPI =
|
const YAZI_TIPI =
|
||||||
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
|
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
|
||||||
|
/** Sitedeki başlıklar Cal Sans (--font-heading); destekleyen istemcide o görünür. */
|
||||||
|
const BASLIK_TIPI = `'Cal Sans', ${YAZI_TIPI}`;
|
||||||
|
/** Sitedeki kelime markası Bricolage Grotesque (font-bricolage). */
|
||||||
|
const MARKA_TIPI = `'Bricolage Grotesque', ${YAZI_TIPI}`;
|
||||||
|
|
||||||
export type EpostaIcerik = {
|
export type EpostaIcerik = {
|
||||||
subject: string;
|
subject: string;
|
||||||
@@ -34,33 +39,15 @@ function kacir(deger: string): string {
|
|||||||
.replace(/"/g, """);
|
.replace(/"/g, """);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Logo işareti: üç yuvarlak kare + KolayTercih kelime markası. */
|
/** Logo: sitedeki işaretin raster kopyası + KolayTercih kelime markası. */
|
||||||
function baslik(): string {
|
function baslik(): string {
|
||||||
return `
|
return `
|
||||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding-right:8px;">
|
<td style="padding-right:6px;">
|
||||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
<img src="${SITE_URL}/kolay-tercih-mark.png" width="36" height="36" alt="" style="display:block;width:36px;height:36px;border:0;">
|
||||||
<tr>
|
|
||||||
<td width="19" height="19" style="width:19px;height:19px;background-color:${MAVI};border-radius:5px;font-size:0;line-height:0;"> </td>
|
|
||||||
<td width="4" style="width:4px;font-size:0;line-height:0;"> </td>
|
|
||||||
<td>
|
|
||||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td width="18" height="18" style="width:18px;height:18px;background-color:${SEFTALI};border-radius:5px;font-size:0;line-height:0;"> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td height="4" style="height:4px;font-size:0;line-height:0;"> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="18" height="18" style="width:18px;height:18px;background-color:${TURUNCU};border-radius:5px;font-size:0;line-height:0;"> </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
</td>
|
||||||
<td style="font-family:${YAZI_TIPI};font-size:20px;letter-spacing:-0.5px;color:${LACIVERT};">
|
<td style="font-family:${MARKA_TIPI};font-size:22px;letter-spacing:-0.05em;color:${LACIVERT};">
|
||||||
<span style="font-weight:300;">Kolay</span><span style="font-weight:600;">Tercih</span>
|
<span style="font-weight:300;">Kolay</span><span style="font-weight:600;">Tercih</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -84,7 +71,9 @@ function kabuk({
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<meta name="color-scheme" content="light">
|
<meta name="color-scheme" content="light">
|
||||||
<title>KolayTercih</title>
|
<title>Merhaba, giriş bağlantını gönderdik</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,300;12..96,600&family=Cal+Sans&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body style="margin:0;padding:0;background-color:${ZEMIN};">
|
<body style="margin:0;padding:0;background-color:${ZEMIN};">
|
||||||
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;font-size:1px;line-height:1px;">${onizleme}</div>
|
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;font-size:1px;line-height:1px;">${onizleme}</div>
|
||||||
@@ -129,8 +118,8 @@ function buton(url: string, etiket: string): string {
|
|||||||
export function magicLinkEpostasi(url: string): EpostaIcerik {
|
export function magicLinkEpostasi(url: string): EpostaIcerik {
|
||||||
const guvenliUrl = kacir(url);
|
const guvenliUrl = kacir(url);
|
||||||
const govde = `
|
const govde = `
|
||||||
<h1 style="margin:0 0 12px;font-family:${YAZI_TIPI};font-size:22px;line-height:1.35;font-weight:700;color:${LACIVERT};">
|
<h1 style="margin:0 0 12px;font-family:${BASLIK_TIPI};font-size:22px;line-height:1.35;font-weight:700;color:${LACIVERT};">
|
||||||
Giriş bağlantın hazır
|
Merhaba, giriş bağlantını gönderdik
|
||||||
</h1>
|
</h1>
|
||||||
<p style="margin:0 0 24px;">
|
<p style="margin:0 0 24px;">
|
||||||
Aşağıdaki butona tıklayarak KolayTercih hesabına giriş yapabilirsin.
|
Aşağıdaki butona tıklayarak KolayTercih hesabına giriş yapabilirsin.
|
||||||
@@ -148,13 +137,13 @@ export function magicLinkEpostasi(url: string): EpostaIcerik {
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subject: "KolayTercih giriş bağlantın",
|
subject: "Merhaba, giriş bağlantını gönderdik",
|
||||||
html: kabuk({
|
html: kabuk({
|
||||||
onizleme: "Giriş bağlantın 5 dakika geçerli.",
|
onizleme: "Giriş bağlantın 5 dakika geçerli.",
|
||||||
govde,
|
govde,
|
||||||
}),
|
}),
|
||||||
text: [
|
text: [
|
||||||
"KolayTercih giriş bağlantın",
|
"Merhaba, giriş bağlantını gönderdik",
|
||||||
"",
|
"",
|
||||||
"Hesabına giriş yapmak için bu adresi tarayıcında aç:",
|
"Hesabına giriş yapmak için bu adresi tarayıcında aç:",
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ export async function olusturulanListeSayisi(): Promise<number> {
|
|||||||
export async function anlikZiyaretci(): Promise<number | null> {
|
export async function anlikZiyaretci(): Promise<number | null> {
|
||||||
if (!HOST || !API_KEY || !STATS_SITE_ID) return null;
|
if (!HOST || !API_KEY || !STATS_SITE_ID) return null;
|
||||||
|
|
||||||
|
// `Date.now()`den önce şart: prerender sırasında saat okumak yasak, istek
|
||||||
|
// anına bağlanmamız gerekiyor. Kardeş fonksiyondaki `connection()` bunu
|
||||||
|
// karşılamıyor — ikisi `Promise.all` ile paralel koşuyor.
|
||||||
|
await connection();
|
||||||
|
|
||||||
const onceki = bellek.canli;
|
const onceki = bellek.canli;
|
||||||
if (onceki && Date.now() - onceki.zaman < CANLI_TTL_MS) return onceki.deger;
|
if (onceki && Date.now() - onceki.zaman < CANLI_TTL_MS) return onceki.deger;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user