release version update

This commit is contained in:
duanfuxiang 2025-08-20 22:08:04 +08:00
parent 80e72394a9
commit 9a848489e3
15 changed files with 1404 additions and 148 deletions

View File

@ -1,4 +1,7 @@
releases:
- version: "0.8.0"
features:
- "add infio pro"
- version: "0.7.6"
features:
- "update mcp settings file watcher"

View File

@ -1,10 +1,11 @@
{
"id": "infio-copilot",
"name": "Infio Copilot",
"version": "0.7.6",
"version": "0.8.0",
"minAppVersion": "0.15.0",
"description": "A Cursor-inspired AI assistant for notes that offers smart autocomplete and interactive chat with your selected notes",
"author": "Felix.D",
"authorUrl": "https://github.com/infiolab",
"isDesktopOnly": true
}

View File

@ -1,6 +1,6 @@
{
"name": "obsidian-infio-copilot",
"version": "0.7.6",
"version": "0.8.0",
"description": "A Cursor-inspired AI assistant that offers smart autocomplete and interactive chat with your selected notes",
"main": "main.js",
"scripts": {
@ -55,16 +55,15 @@
},
"dependencies": {
"@anthropic-ai/sdk": "^0.27.3",
"codemirror": "^6.0.1",
"@codemirror/basic-setup": "^0.20.0",
"@codemirror/commands": "^6.7.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-markdown": "^6.3.2",
"@codemirror/language": "^6.11.2",
"@codemirror/merge": "^6.10.0",
"@codemirror/state": "^6.5.2",
"@codemirror/theme-one-dark": "^6.1.2",
"@codemirror/view": "^6.35.0",
"@codemirror/basic-setup": "^0.20.0",
"@codemirror/lang-markdown": "^6.3.2",
"@codemirror/merge": "^6.10.0",
"@codemirror/language": "^6.11.2",
"@electric-sql/pglite": "0.2.14",
"@google/genai": "^1.2.0",
"@google/generative-ai": "^0.21.0",
@ -86,6 +85,7 @@
"axios": "^1.8.3",
"chokidar": "^4.0.3",
"clsx": "^2.1.1",
"codemirror": "^6.0.1",
"delay": "^6.0.0",
"diff": "^7.0.0",
"diff-match-patch": "^1.0.5",
@ -101,6 +101,7 @@
"js-tiktoken": "^1.0.15",
"js-yaml": "^4.1.0",
"json5": "^2.2.3",
"jszip": "^3.10.1",
"langchain": "^0.3.15",
"lexical": "^0.17.1",
"lodash": "^4.17.21",

286
pnpm-lock.yaml generated
View File

@ -153,6 +153,9 @@ importers:
json5:
specifier: ^2.2.3
version: 2.2.3
jszip:
specifier: ^3.10.1
version: 3.10.1
langchain:
specifier: ^0.3.15
version: 0.3.29(@langchain/core@0.3.40(openai@4.104.0(ws@8.18.3)(zod@3.24.2)))(axios@1.10.0)(handlebars@4.7.8)(openai@4.104.0(ws@8.18.3)(zod@3.24.2))(ws@8.18.3)
@ -702,8 +705,8 @@ packages:
cpu: [ppc64]
os: [aix]
'@esbuild/aix-ppc64@0.25.7':
resolution: {integrity: sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==}
'@esbuild/aix-ppc64@0.25.9':
resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@ -726,8 +729,8 @@ packages:
cpu: [arm64]
os: [android]
'@esbuild/android-arm64@0.25.7':
resolution: {integrity: sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==}
'@esbuild/android-arm64@0.25.9':
resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@ -750,8 +753,8 @@ packages:
cpu: [arm]
os: [android]
'@esbuild/android-arm@0.25.7':
resolution: {integrity: sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==}
'@esbuild/android-arm@0.25.9':
resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@ -774,8 +777,8 @@ packages:
cpu: [x64]
os: [android]
'@esbuild/android-x64@0.25.7':
resolution: {integrity: sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==}
'@esbuild/android-x64@0.25.9':
resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@ -798,8 +801,8 @@ packages:
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-arm64@0.25.7':
resolution: {integrity: sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==}
'@esbuild/darwin-arm64@0.25.9':
resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@ -822,8 +825,8 @@ packages:
cpu: [x64]
os: [darwin]
'@esbuild/darwin-x64@0.25.7':
resolution: {integrity: sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==}
'@esbuild/darwin-x64@0.25.9':
resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@ -846,8 +849,8 @@ packages:
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-arm64@0.25.7':
resolution: {integrity: sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==}
'@esbuild/freebsd-arm64@0.25.9':
resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@ -870,8 +873,8 @@ packages:
cpu: [x64]
os: [freebsd]
'@esbuild/freebsd-x64@0.25.7':
resolution: {integrity: sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==}
'@esbuild/freebsd-x64@0.25.9':
resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@ -894,8 +897,8 @@ packages:
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm64@0.25.7':
resolution: {integrity: sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==}
'@esbuild/linux-arm64@0.25.9':
resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@ -918,8 +921,8 @@ packages:
cpu: [arm]
os: [linux]
'@esbuild/linux-arm@0.25.7':
resolution: {integrity: sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==}
'@esbuild/linux-arm@0.25.9':
resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@ -942,8 +945,8 @@ packages:
cpu: [ia32]
os: [linux]
'@esbuild/linux-ia32@0.25.7':
resolution: {integrity: sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==}
'@esbuild/linux-ia32@0.25.9':
resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@ -966,8 +969,8 @@ packages:
cpu: [loong64]
os: [linux]
'@esbuild/linux-loong64@0.25.7':
resolution: {integrity: sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==}
'@esbuild/linux-loong64@0.25.9':
resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@ -990,8 +993,8 @@ packages:
cpu: [mips64el]
os: [linux]
'@esbuild/linux-mips64el@0.25.7':
resolution: {integrity: sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==}
'@esbuild/linux-mips64el@0.25.9':
resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@ -1014,8 +1017,8 @@ packages:
cpu: [ppc64]
os: [linux]
'@esbuild/linux-ppc64@0.25.7':
resolution: {integrity: sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==}
'@esbuild/linux-ppc64@0.25.9':
resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@ -1038,8 +1041,8 @@ packages:
cpu: [riscv64]
os: [linux]
'@esbuild/linux-riscv64@0.25.7':
resolution: {integrity: sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==}
'@esbuild/linux-riscv64@0.25.9':
resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@ -1062,8 +1065,8 @@ packages:
cpu: [s390x]
os: [linux]
'@esbuild/linux-s390x@0.25.7':
resolution: {integrity: sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==}
'@esbuild/linux-s390x@0.25.9':
resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@ -1086,14 +1089,14 @@ packages:
cpu: [x64]
os: [linux]
'@esbuild/linux-x64@0.25.7':
resolution: {integrity: sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==}
'@esbuild/linux-x64@0.25.9':
resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-arm64@0.25.7':
resolution: {integrity: sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==}
'@esbuild/netbsd-arm64@0.25.9':
resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
@ -1116,14 +1119,14 @@ packages:
cpu: [x64]
os: [netbsd]
'@esbuild/netbsd-x64@0.25.7':
resolution: {integrity: sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==}
'@esbuild/netbsd-x64@0.25.9':
resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.25.7':
resolution: {integrity: sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==}
'@esbuild/openbsd-arm64@0.25.9':
resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@ -1146,14 +1149,14 @@ packages:
cpu: [x64]
os: [openbsd]
'@esbuild/openbsd-x64@0.25.7':
resolution: {integrity: sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==}
'@esbuild/openbsd-x64@0.25.9':
resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openharmony-arm64@0.25.7':
resolution: {integrity: sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==}
'@esbuild/openharmony-arm64@0.25.9':
resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
@ -1176,8 +1179,8 @@ packages:
cpu: [x64]
os: [sunos]
'@esbuild/sunos-x64@0.25.7':
resolution: {integrity: sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==}
'@esbuild/sunos-x64@0.25.9':
resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@ -1200,8 +1203,8 @@ packages:
cpu: [arm64]
os: [win32]
'@esbuild/win32-arm64@0.25.7':
resolution: {integrity: sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==}
'@esbuild/win32-arm64@0.25.9':
resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@ -1224,8 +1227,8 @@ packages:
cpu: [ia32]
os: [win32]
'@esbuild/win32-ia32@0.25.7':
resolution: {integrity: sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==}
'@esbuild/win32-ia32@0.25.9':
resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@ -1248,8 +1251,8 @@ packages:
cpu: [x64]
os: [win32]
'@esbuild/win32-x64@0.25.7':
resolution: {integrity: sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==}
'@esbuild/win32-x64@0.25.9':
resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@ -3218,6 +3221,9 @@ packages:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
cors@2.8.5:
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
engines: {node: '>= 0.10'}
@ -3784,8 +3790,8 @@ packages:
engines: {node: '>=12'}
hasBin: true
esbuild@0.25.7:
resolution: {integrity: sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==}
esbuild@0.25.9:
resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==}
engines: {node: '>=18'}
hasBin: true
@ -4588,6 +4594,9 @@ packages:
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
engines: {node: '>= 0.4'}
isarray@1.0.0:
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
isarray@2.0.5:
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
@ -4837,6 +4846,9 @@ packages:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
jwa@2.0.1:
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
@ -4977,6 +4989,9 @@ packages:
lie@3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@ -5615,6 +5630,9 @@ packages:
package-manager-detector@1.3.0:
resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
papaparse@5.5.3:
resolution: {integrity: sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==}
@ -5769,6 +5787,9 @@ packages:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
@ -5922,6 +5943,9 @@ packages:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
@ -6042,6 +6066,9 @@ packages:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@ -6102,6 +6129,9 @@ packages:
resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
engines: {node: '>= 0.4'}
setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
@ -6256,6 +6286,9 @@ packages:
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
engines: {node: '>= 0.4'}
string_decoder@1.1.1:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
@ -7260,7 +7293,7 @@ snapshots:
'@esbuild/aix-ppc64@0.19.12':
optional: true
'@esbuild/aix-ppc64@0.25.7':
'@esbuild/aix-ppc64@0.25.9':
optional: true
'@esbuild/android-arm64@0.17.3':
@ -7272,7 +7305,7 @@ snapshots:
'@esbuild/android-arm64@0.19.12':
optional: true
'@esbuild/android-arm64@0.25.7':
'@esbuild/android-arm64@0.25.9':
optional: true
'@esbuild/android-arm@0.17.3':
@ -7284,7 +7317,7 @@ snapshots:
'@esbuild/android-arm@0.19.12':
optional: true
'@esbuild/android-arm@0.25.7':
'@esbuild/android-arm@0.25.9':
optional: true
'@esbuild/android-x64@0.17.3':
@ -7296,7 +7329,7 @@ snapshots:
'@esbuild/android-x64@0.19.12':
optional: true
'@esbuild/android-x64@0.25.7':
'@esbuild/android-x64@0.25.9':
optional: true
'@esbuild/darwin-arm64@0.17.3':
@ -7308,7 +7341,7 @@ snapshots:
'@esbuild/darwin-arm64@0.19.12':
optional: true
'@esbuild/darwin-arm64@0.25.7':
'@esbuild/darwin-arm64@0.25.9':
optional: true
'@esbuild/darwin-x64@0.17.3':
@ -7320,7 +7353,7 @@ snapshots:
'@esbuild/darwin-x64@0.19.12':
optional: true
'@esbuild/darwin-x64@0.25.7':
'@esbuild/darwin-x64@0.25.9':
optional: true
'@esbuild/freebsd-arm64@0.17.3':
@ -7332,7 +7365,7 @@ snapshots:
'@esbuild/freebsd-arm64@0.19.12':
optional: true
'@esbuild/freebsd-arm64@0.25.7':
'@esbuild/freebsd-arm64@0.25.9':
optional: true
'@esbuild/freebsd-x64@0.17.3':
@ -7344,7 +7377,7 @@ snapshots:
'@esbuild/freebsd-x64@0.19.12':
optional: true
'@esbuild/freebsd-x64@0.25.7':
'@esbuild/freebsd-x64@0.25.9':
optional: true
'@esbuild/linux-arm64@0.17.3':
@ -7356,7 +7389,7 @@ snapshots:
'@esbuild/linux-arm64@0.19.12':
optional: true
'@esbuild/linux-arm64@0.25.7':
'@esbuild/linux-arm64@0.25.9':
optional: true
'@esbuild/linux-arm@0.17.3':
@ -7368,7 +7401,7 @@ snapshots:
'@esbuild/linux-arm@0.19.12':
optional: true
'@esbuild/linux-arm@0.25.7':
'@esbuild/linux-arm@0.25.9':
optional: true
'@esbuild/linux-ia32@0.17.3':
@ -7380,7 +7413,7 @@ snapshots:
'@esbuild/linux-ia32@0.19.12':
optional: true
'@esbuild/linux-ia32@0.25.7':
'@esbuild/linux-ia32@0.25.9':
optional: true
'@esbuild/linux-loong64@0.17.3':
@ -7392,7 +7425,7 @@ snapshots:
'@esbuild/linux-loong64@0.19.12':
optional: true
'@esbuild/linux-loong64@0.25.7':
'@esbuild/linux-loong64@0.25.9':
optional: true
'@esbuild/linux-mips64el@0.17.3':
@ -7404,7 +7437,7 @@ snapshots:
'@esbuild/linux-mips64el@0.19.12':
optional: true
'@esbuild/linux-mips64el@0.25.7':
'@esbuild/linux-mips64el@0.25.9':
optional: true
'@esbuild/linux-ppc64@0.17.3':
@ -7416,7 +7449,7 @@ snapshots:
'@esbuild/linux-ppc64@0.19.12':
optional: true
'@esbuild/linux-ppc64@0.25.7':
'@esbuild/linux-ppc64@0.25.9':
optional: true
'@esbuild/linux-riscv64@0.17.3':
@ -7428,7 +7461,7 @@ snapshots:
'@esbuild/linux-riscv64@0.19.12':
optional: true
'@esbuild/linux-riscv64@0.25.7':
'@esbuild/linux-riscv64@0.25.9':
optional: true
'@esbuild/linux-s390x@0.17.3':
@ -7440,7 +7473,7 @@ snapshots:
'@esbuild/linux-s390x@0.19.12':
optional: true
'@esbuild/linux-s390x@0.25.7':
'@esbuild/linux-s390x@0.25.9':
optional: true
'@esbuild/linux-x64@0.17.3':
@ -7452,10 +7485,10 @@ snapshots:
'@esbuild/linux-x64@0.19.12':
optional: true
'@esbuild/linux-x64@0.25.7':
'@esbuild/linux-x64@0.25.9':
optional: true
'@esbuild/netbsd-arm64@0.25.7':
'@esbuild/netbsd-arm64@0.25.9':
optional: true
'@esbuild/netbsd-x64@0.17.3':
@ -7467,10 +7500,10 @@ snapshots:
'@esbuild/netbsd-x64@0.19.12':
optional: true
'@esbuild/netbsd-x64@0.25.7':
'@esbuild/netbsd-x64@0.25.9':
optional: true
'@esbuild/openbsd-arm64@0.25.7':
'@esbuild/openbsd-arm64@0.25.9':
optional: true
'@esbuild/openbsd-x64@0.17.3':
@ -7482,10 +7515,10 @@ snapshots:
'@esbuild/openbsd-x64@0.19.12':
optional: true
'@esbuild/openbsd-x64@0.25.7':
'@esbuild/openbsd-x64@0.25.9':
optional: true
'@esbuild/openharmony-arm64@0.25.7':
'@esbuild/openharmony-arm64@0.25.9':
optional: true
'@esbuild/sunos-x64@0.17.3':
@ -7497,7 +7530,7 @@ snapshots:
'@esbuild/sunos-x64@0.19.12':
optional: true
'@esbuild/sunos-x64@0.25.7':
'@esbuild/sunos-x64@0.25.9':
optional: true
'@esbuild/win32-arm64@0.17.3':
@ -7509,7 +7542,7 @@ snapshots:
'@esbuild/win32-arm64@0.19.12':
optional: true
'@esbuild/win32-arm64@0.25.7':
'@esbuild/win32-arm64@0.25.9':
optional: true
'@esbuild/win32-ia32@0.17.3':
@ -7521,7 +7554,7 @@ snapshots:
'@esbuild/win32-ia32@0.19.12':
optional: true
'@esbuild/win32-ia32@0.25.7':
'@esbuild/win32-ia32@0.25.9':
optional: true
'@esbuild/win32-x64@0.17.3':
@ -7533,7 +7566,7 @@ snapshots:
'@esbuild/win32-x64@0.19.12':
optional: true
'@esbuild/win32-x64@0.25.7':
'@esbuild/win32-x64@0.25.9':
optional: true
'@eslint-community/eslint-utils@4.7.0(eslint@8.57.1)':
@ -9894,6 +9927,8 @@ snapshots:
cookie@0.7.2: {}
core-util-is@1.0.3: {}
cors@2.8.5:
dependencies:
object-assign: 4.1.1
@ -10428,7 +10463,7 @@ snapshots:
esbuild-plugin-inline-worker@0.1.1:
dependencies:
esbuild: 0.25.7
esbuild: 0.25.9
find-cache-dir: 3.3.2
esbuild-register@3.6.0(esbuild@0.19.12):
@ -10514,34 +10549,34 @@ snapshots:
'@esbuild/win32-ia32': 0.19.12
'@esbuild/win32-x64': 0.19.12
esbuild@0.25.7:
esbuild@0.25.9:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.7
'@esbuild/android-arm': 0.25.7
'@esbuild/android-arm64': 0.25.7
'@esbuild/android-x64': 0.25.7
'@esbuild/darwin-arm64': 0.25.7
'@esbuild/darwin-x64': 0.25.7
'@esbuild/freebsd-arm64': 0.25.7
'@esbuild/freebsd-x64': 0.25.7
'@esbuild/linux-arm': 0.25.7
'@esbuild/linux-arm64': 0.25.7
'@esbuild/linux-ia32': 0.25.7
'@esbuild/linux-loong64': 0.25.7
'@esbuild/linux-mips64el': 0.25.7
'@esbuild/linux-ppc64': 0.25.7
'@esbuild/linux-riscv64': 0.25.7
'@esbuild/linux-s390x': 0.25.7
'@esbuild/linux-x64': 0.25.7
'@esbuild/netbsd-arm64': 0.25.7
'@esbuild/netbsd-x64': 0.25.7
'@esbuild/openbsd-arm64': 0.25.7
'@esbuild/openbsd-x64': 0.25.7
'@esbuild/openharmony-arm64': 0.25.7
'@esbuild/sunos-x64': 0.25.7
'@esbuild/win32-arm64': 0.25.7
'@esbuild/win32-ia32': 0.25.7
'@esbuild/win32-x64': 0.25.7
'@esbuild/aix-ppc64': 0.25.9
'@esbuild/android-arm': 0.25.9
'@esbuild/android-arm64': 0.25.9
'@esbuild/android-x64': 0.25.9
'@esbuild/darwin-arm64': 0.25.9
'@esbuild/darwin-x64': 0.25.9
'@esbuild/freebsd-arm64': 0.25.9
'@esbuild/freebsd-x64': 0.25.9
'@esbuild/linux-arm': 0.25.9
'@esbuild/linux-arm64': 0.25.9
'@esbuild/linux-ia32': 0.25.9
'@esbuild/linux-loong64': 0.25.9
'@esbuild/linux-mips64el': 0.25.9
'@esbuild/linux-ppc64': 0.25.9
'@esbuild/linux-riscv64': 0.25.9
'@esbuild/linux-s390x': 0.25.9
'@esbuild/linux-x64': 0.25.9
'@esbuild/netbsd-arm64': 0.25.9
'@esbuild/netbsd-x64': 0.25.9
'@esbuild/openbsd-arm64': 0.25.9
'@esbuild/openbsd-x64': 0.25.9
'@esbuild/openharmony-arm64': 0.25.9
'@esbuild/sunos-x64': 0.25.9
'@esbuild/win32-arm64': 0.25.9
'@esbuild/win32-ia32': 0.25.9
'@esbuild/win32-x64': 0.25.9
escalade@3.2.0: {}
@ -11493,6 +11528,8 @@ snapshots:
call-bound: 1.0.4
get-intrinsic: 1.3.0
isarray@1.0.0: {}
isarray@2.0.5: {}
isexe@2.0.0: {}
@ -11962,6 +11999,13 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
jszip@3.10.1:
dependencies:
lie: 3.3.0
pako: 1.0.11
readable-stream: 2.3.8
setimmediate: 1.0.5
jwa@2.0.1:
dependencies:
buffer-equal-constant-time: 1.0.1
@ -12062,6 +12106,10 @@ snapshots:
dependencies:
immediate: 3.0.6
lie@3.3.0:
dependencies:
immediate: 3.0.6
lines-and-columns@1.2.4: {}
local-pkg@1.1.1:
@ -12847,6 +12895,8 @@ snapshots:
package-manager-detector@1.3.0: {}
pako@1.0.11: {}
papaparse@5.5.3: {}
parent-module@1.0.1:
@ -13001,6 +13051,8 @@ snapshots:
prismjs@1.30.0: {}
process-nextick-args@2.0.1: {}
process@0.11.10: {}
prompts@2.4.2:
@ -13242,6 +13294,16 @@ snapshots:
dependencies:
loose-envify: 1.4.0
readable-stream@2.3.8:
dependencies:
core-util-is: 1.0.3
inherits: 2.0.4
isarray: 1.0.0
process-nextick-args: 2.0.1
safe-buffer: 5.1.2
string_decoder: 1.1.1
util-deprecate: 1.0.2
readable-stream@3.6.2:
dependencies:
inherits: 2.0.4
@ -13402,6 +13464,8 @@ snapshots:
has-symbols: 1.1.0
isarray: 2.0.5
safe-buffer@5.1.2: {}
safe-buffer@5.2.1: {}
safe-push-apply@1.0.0:
@ -13484,6 +13548,8 @@ snapshots:
es-errors: 1.3.0
es-object-atoms: 1.1.1
setimmediate@1.0.5: {}
setprototypeof@1.2.0: {}
shallowequal@1.1.0: {}
@ -13710,6 +13776,10 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
string_decoder@1.1.1:
dependencies:
safe-buffer: 5.1.2
string_decoder@1.3.0:
dependencies:
safe-buffer: 5.2.1

View File

@ -0,0 +1,246 @@
import { App, Modal } from 'obsidian'
import { createRoot, Root } from 'react-dom/client'
import { INFIO_PLATFORM_URL } from '../../constants'
interface ApiKeyModalContentProps {
onClose: () => void
app: App
}
const ApiKeyModalContent: React.FC<ApiKeyModalContentProps> = ({ onClose, app }) => {
const handleGetApiKeyClick = () => {
window.open(`${INFIO_PLATFORM_URL}/api-keys`, '_blank')
}
const handleUpgradeProClick = () => {
window.open(`${INFIO_PLATFORM_URL}/billing`, '_blank')
}
const handleOpenSettingsClick = () => {
onClose()
// 打开设置面板到 Infio Provider 选项卡
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const setting = (app as any).setting
setting.open()
setting.openTabById('infio-copilot')
}
return (
<div className="api-key-modal-content">
<div className="api-key-modal-header">
<h2> API Key</h2>
</div>
<div className="api-key-modal-body">
<div className="api-key-message">
{/* <div className="api-key-icon">🔑</div> */}
<p> Infio Provider Infio API Key</p>
<p> API Key</p>
<div className="api-key-steps">
<div className="api-key-step">
<div className="step-number">1</div>
<div className="step-content">
<h4> API Key</h4>
<p>访 Infio API Key</p>
<button className="step-action-btn" onClick={handleGetApiKeyClick}>
API Key
</button>
</div>
</div>
<div className="api-key-step">
<div className="step-number">2</div>
<div className="step-content">
<h4> Pro </h4>
<p> Pro 访</p>
<button className="step-action-btn" onClick={handleUpgradeProClick}>
Pro
</button>
</div>
</div>
<div className="api-key-step">
<div className="step-number">3</div>
<div className="step-content">
<h4> Infio API Key</h4>
<p> Infio Provider Infio API Key</p>
<button className="step-action-btn" onClick={handleOpenSettingsClick}>
</button>
</div>
</div>
</div>
</div>
</div>
<div className="api-key-modal-footer">
<button className="api-key-btn-close" onClick={onClose}>
</button>
</div>
<style>
{`
.api-key-modal-content {
padding: 0;
}
.api-key-modal-header {
padding: 20px 24px 16px;
border-bottom: 1px solid var(--background-modifier-border);
}
.api-key-modal-header h2 {
margin: 0;
font-size: 20px;
font-weight: 600;
color: var(--text-normal);
}
.api-key-modal-body {
padding: 24px;
}
.api-key-message {
text-align: center;
}
.api-key-icon {
font-size: 48px;
margin-bottom: 16px;
}
.api-key-message p {
font-size: 16px;
line-height: 1.5;
color: var(--text-normal);
margin: 0 0 16px 0;
}
.api-key-steps {
margin: 24px 0;
text-align: left;
}
.api-key-step {
display: flex;
gap: 16px;
margin-bottom: 20px;
padding: 16px;
background: var(--background-secondary);
border-radius: var(--radius-m);
border-left: 3px solid var(--interactive-accent);
}
.step-number {
width: 32px;
height: 32px;
background: var(--interactive-accent);
color: var(--text-on-accent);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 16px;
flex-shrink: 0;
}
.step-content {
flex: 1;
}
.step-content h4 {
margin: 0 0 8px 0;
font-size: 16px;
font-weight: 600;
color: var(--text-normal);
}
.step-content p {
margin: 0 0 12px 0;
font-size: 14px;
color: var(--text-muted);
line-height: 1.4;
}
.step-action-btn {
padding: 8px 16px;
border: 1px solid var(--interactive-accent);
background: transparent;
color: var(--interactive-accent);
border-radius: var(--radius-s);
cursor: pointer;
font-size: 13px;
font-weight: 500;
transition: all 0.2s ease;
}
.step-action-btn:hover {
background: var(--interactive-accent);
color: var(--text-on-accent);
}
.api-key-modal-footer {
padding: 16px 24px 24px;
display: flex;
justify-content: center;
}
.api-key-btn-close {
padding: 10px 24px;
border: 1px solid var(--background-modifier-border);
background: var(--background-secondary);
color: var(--text-normal);
border-radius: var(--radius-s);
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
}
.api-key-btn-close:hover {
background: var(--background-modifier-hover);
}
`}
</style>
</div>
)
}
export class ApiKeyModal extends Modal {
private root: Root | null = null
constructor(app: App) {
super(app)
}
onOpen(): void {
const { contentEl, modalEl } = this
// 添加特定的CSS类
modalEl.addClass('mod-api-key')
// 设置模态框样式
modalEl.style.width = '520px'
modalEl.style.maxWidth = '90vw'
this.root = createRoot(contentEl)
this.root.render(
<ApiKeyModalContent
onClose={() => this.close()}
app={this.app}
/>
)
}
onClose(): void {
const { contentEl, modalEl } = this
modalEl.removeClass('mod-api-key')
this.root?.unmount()
this.root = null
contentEl.empty()
}
}

View File

@ -0,0 +1,183 @@
import { App, Modal } from 'obsidian'
import { createRoot, Root } from 'react-dom/client'
interface ProUpgradeModalContentProps {
onClose: () => void
}
const ProUpgradeModalContent: React.FC<ProUpgradeModalContentProps> = ({ onClose }) => {
const handleUpgradeClick = () => {
window.open('https://platform.infio.com/billing', '_blank')
}
return (
<div className="pro-upgrade-modal-content">
<div className="pro-upgrade-modal-header">
<h2> Pro </h2>
</div>
<div className="pro-upgrade-modal-body">
<div className="pro-upgrade-message">
<div className="pro-upgrade-icon"></div>
<p>Pro会员Pro版本</p>
<p>Pro</p>
<ul className="pro-upgrade-features">
<li> UI界面</li>
<li>🚀 线使</li>
<li>💎 访</li>
<li>🎯 </li>
</ul>
</div>
</div>
<div className="pro-upgrade-modal-footer">
<button className="pro-upgrade-btn-cancel" onClick={onClose}>
</button>
<button className="pro-upgrade-btn-upgrade" onClick={handleUpgradeClick}>
Pro
</button>
</div>
<style>
{`
.pro-upgrade-modal-content {
padding: 0;
}
.pro-upgrade-modal-header {
padding: 20px 24px 16px;
border-bottom: 1px solid var(--background-modifier-border);
}
.pro-upgrade-modal-header h2 {
margin: 0;
font-size: 20px;
font-weight: 600;
color: var(--text-normal);
}
.pro-upgrade-modal-body {
padding: 24px;
}
.pro-upgrade-message {
text-align: center;
}
.pro-upgrade-icon {
font-size: 48px;
margin-bottom: 16px;
}
.pro-upgrade-message p {
font-size: 16px;
line-height: 1.5;
color: var(--text-normal);
margin: 0 0 16px 0;
}
.pro-upgrade-features {
list-style: none;
padding: 0;
margin: 20px 0;
text-align: left;
background: var(--background-secondary);
border-radius: var(--radius-m);
padding: 16px 20px;
}
.pro-upgrade-features li {
padding: 8px 0;
font-size: 14px;
color: var(--text-normal);
display: flex;
align-items: center;
}
.pro-upgrade-modal-footer {
padding: 16px 24px 24px;
display: flex;
gap: 12px;
justify-content: flex-end;
}
.pro-upgrade-btn-cancel {
padding: 10px 20px;
border: 1px solid var(--background-modifier-border);
background: var(--background-secondary);
color: var(--text-normal);
border-radius: var(--radius-s);
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
}
.pro-upgrade-btn-cancel:hover {
background: var(--background-modifier-hover);
}
.pro-upgrade-btn-upgrade {
padding: 10px 20px;
border: none;
background: linear-gradient(135deg, var(--interactive-accent), var(--interactive-accent-hover));
color: var(--text-on-accent);
border-radius: var(--radius-s);
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.pro-upgrade-btn-upgrade:hover {
background: linear-gradient(135deg, var(--interactive-accent-hover), var(--interactive-accent));
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.pro-upgrade-btn-upgrade:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
`}
</style>
</div>
)
}
export class ProUpgradeModal extends Modal {
private root: Root | null = null
constructor(app: App) {
super(app)
}
onOpen(): void {
const { contentEl, modalEl } = this
// 添加特定的CSS类
modalEl.addClass('mod-pro-upgrade')
// 设置模态框样式
modalEl.style.width = '480px'
modalEl.style.maxWidth = '90vw'
this.root = createRoot(contentEl)
this.root.render(
<ProUpgradeModalContent
onClose={() => this.close()}
/>
)
}
onClose(): void {
const { contentEl, modalEl } = this
modalEl.removeClass('mod-pro-upgrade')
this.root?.unmount()
this.root = null
contentEl.empty()
}
}

View File

@ -22,7 +22,9 @@ export const GROK_BASE_URL = 'https://api.x.ai/v1'
export const SILICONFLOW_BASE_URL = 'https://api.siliconflow.cn/v1'
export const ALIBABA_QWEN_BASE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1'
export const MOONSHOT_BASE_URL = 'https://api.moonshot.cn/v1'
export const INFIO_BASE_URL = 'https://api.infio.app'
// export const INFIO_BASE_URL = 'https://api.infio.app'
export const INFIO_PLATFORM_URL = 'https://platform.infio.app'
export const INFIO_BASE_URL = 'http://192.168.31.211:4000'
export const JINA_BASE_URL = 'https://r.jina.ai'
export const SERPER_BASE_URL = 'https://serpapi.com/search'
// Pricing in dollars per million tokens

View File

@ -1,6 +1,6 @@
import OpenAI from 'openai'
import { ALIBABA_QWEN_BASE_URL, MOONSHOT_BASE_URL } from '../../constants'
import { ALIBABA_QWEN_BASE_URL, INFIO_BASE_URL, MOONSHOT_BASE_URL } from '../../constants'
import { LLMModel } from '../../types/llm/model'
import {
LLMOptions,
@ -51,16 +51,23 @@ export class OpenAICompatibleProvider implements BaseLLMProvider {
private isAlibabaQwen(): boolean {
return this.baseURL === ALIBABA_QWEN_BASE_URL ||
this.baseURL?.includes('dashscope.aliyuncs.com')
}
}
private isGemini(modelName: string): boolean {
return this.baseURL === INFIO_BASE_URL && modelName.includes('gemini')
}
// 获取提供商特定的额外参数
private getExtraParams(isStreaming: boolean): Record<string, unknown> {
private getExtraParams(isStreaming: boolean, modelName: string): Record<string, unknown> {
const extraParams: Record<string, unknown> = {}
// 阿里云Qwen API需要在非流式调用中设置 enable_thinking: false
if (this.isAlibabaQwen() && !isStreaming) {
extraParams.enable_thinking = false
}
}
if (this.isGemini(modelName)) {
extraParams.reasoning_effort = 'low';
}
return extraParams
}
@ -91,7 +98,7 @@ export class OpenAICompatibleProvider implements BaseLLMProvider {
)
}
const extraParams = this.getExtraParams(true) // 流式调用
const extraParams = this.getExtraParams(true, model.modelId) // 流式调用
return this.adapter.streamResponse(this.client as OpenAI, request, options, extraParams)
}
}

294
src/hooks/use-infio.ts Normal file
View File

@ -0,0 +1,294 @@
/* eslint-disable no-console, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */
import JSZip from "jszip";
import { App, Notice, Plugin, requestUrl } from "obsidian";
import { INFIO_BASE_URL } from "../constants";
// 扩展App类型以包含plugins属性
type AppWithPlugins = App & {
plugins: {
reloadPlugin: (id: string) => void;
};
};
// 类型保护函数
function hasPluginsProperty(app: App): app is AppWithPlugins {
return 'plugins' in app &&
app.plugins !== undefined &&
typeof app.plugins === 'object' &&
'reloadPlugin' in app.plugins &&
typeof app.plugins.reloadPlugin === 'function';
}
// API响应类型定义
export type UserPlanResponse = {
plan: string;
status: string;
dl_zip?: string;
[key: string]: unknown;
};
export type UpgradeResult = {
success: boolean;
message: string;
};
export const fetchUserPlan = async (apiKey: string): Promise<UserPlanResponse> => {
const response = await requestUrl({
url: `${INFIO_BASE_URL}/subscription/status`,
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return response.json;
}
/**
* Pro用户
*/
export const checkIsProUser = async (apiKey: string): Promise<boolean> => {
try {
if (!apiKey) {
return false;
}
const userPlan = await fetchUserPlan(apiKey);
return userPlan.plan?.toLowerCase().startsWith('pro') || false;
} catch (error) {
// eslint-disable-next-line no-console
console.error('检查Pro用户状态失败:', error);
return false;
}
}
/**
*
*/
const cleanupTempDirectory = async (adapter: Plugin['app']['vault']['adapter'], tempDir: string): Promise<void> => {
try {
// 检查目录是否存在
if (await adapter.exists(tempDir)) {
console.log(`清理临时目录: ${tempDir}`);
// 删除临时目录及其所有内容
await adapter.rmdir(tempDir, true);
console.log(`临时目录清理完成: ${tempDir}`);
}
} catch (error) {
console.log("清理临时目录失败:", error);
// 不抛出错误,因为这不是关键操作
}
};
/**
* ZIP文件到临时目录
*/
const downloadAndExtractToTemp = async (
adapter: Plugin['app']['vault']['adapter'],
tempDir: string,
downloadUrl: string
): Promise<void> => {
console.log(`开始下载文件: ${downloadUrl}`);
// 下载ZIP文件
let zipResponse;
try {
zipResponse = await requestUrl({
url: downloadUrl,
method: "GET",
});
console.log("文件下载完成,状态:", zipResponse.status);
} catch (error) {
console.log("下载失败:", error);
throw new Error("网络连接失败无法下载Pro版本文件");
}
if (!zipResponse.arrayBuffer) {
console.log("响应格式无效缺少arrayBuffer");
throw new Error("下载的文件格式无效");
}
console.log("正在解压文件到临时目录...");
console.log(`开始解压文件到临时目录: ${tempDir}`);
// 解压ZIP文件
let zipData: JSZip;
try {
const zip = new JSZip();
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
zipData = await zip.loadAsync(zipResponse.arrayBuffer);
console.log("ZIP文件解析成功");
} catch (error) {
console.log("ZIP文件解析失败:", error);
throw new Error("文件解压失败,可能文件已损坏");
}
// 创建临时目录
try {
if (!(await adapter.exists(tempDir))) {
await adapter.mkdir(tempDir);
console.log(`临时目录创建成功: ${tempDir}`);
} else {
console.log(`临时目录已存在: ${tempDir}`);
}
} catch (error) {
console.log("创建临时目录失败:", error);
throw new Error("无法创建临时目录");
}
// 解压所有文件到临时目录
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const files = Object.keys(zipData.files);
console.log(files);
console.log(`ZIP文件中包含 ${files.length} 个条目`);
let extractedCount = 0;
for (const filename of files) {
const file = zipData.files[filename];
// 跳过目录
if (file?.dir) {
console.log(`跳过目录: ${filename}`);
continue;
}
console.log(`正在解压文件: ${filename}`);
// 获取文件内容
const content = await file?.async("text");
if (!content) {
console.log(`跳过空文件: ${filename}`);
continue;
}
// 提取文件名(去掉路径前缀)
const pathParts = filename.split('/');
const actualFileName = pathParts[pathParts.length - 1];
// 直接写入到临时目录根目录,不创建子目录
const tempFilePath = `${tempDir}/${actualFileName}`;
// 写入文件到临时目录
await adapter.write(tempFilePath, content);
extractedCount++;
console.log(`文件解压完成: ${actualFileName} (${extractedCount}/${files.filter(f => !zipData.files[f].dir).length})`);
}
console.log(`所有文件解压完成,共解压 ${extractedCount} 个文件`);
} catch (error) {
console.log("文件解压过程中出错:", error);
throw new Error("文件解压过程中出现错误");
}
};
/**
*
*/
const copyFilesFromTemp = async (
adapter: Plugin['app']['vault']['adapter'],
tempDir: string,
pluginDir: string
): Promise<void> => {
console.log("正在更新插件文件...");
console.log(`开始从临时目录复制文件到插件目录: ${tempDir} -> ${pluginDir}`);
// 需要复制的关键文件
const filesToCopy = ['main.js', 'styles.css', 'manifest.json'];
// 检查必需文件是否存在
const mainJsPath = `${tempDir}/main.js`;
if (!(await adapter.exists(mainJsPath))) {
console.log("关键文件缺失: main.js");
throw new Error("升级文件不完整,缺少关键组件");
}
// 复制文件
let copiedCount = 0;
for (const filename of filesToCopy) {
const tempFilePath = `${tempDir}/${filename}`;
const pluginFilePath = `${pluginDir}/${filename}`;
try {
if (await adapter.exists(tempFilePath)) {
const content = await adapter.read(tempFilePath);
await adapter.write(pluginFilePath, content);
copiedCount++;
} else if (filename !== 'main.js') {
console.log(`可选文件不存在,跳过: ${filename}`);
}
} catch (error) {
throw new Error(`文件更新失败: ${filename}`);
}
}
console.log(`文件复制完成,共复制 ${copiedCount} 个文件`);
};
/**
* Pro版本
*/
export const upgradeToProVersion = async (
plugin: Plugin,
dl_zip: string
): Promise<UpgradeResult> => {
const tempDir = '.infio_download_cache';
const adapter = plugin.app.vault.adapter;
try {
// 获取插件目录
const pluginDir = plugin.manifest.dir;
if (!pluginDir) {
console.log("插件目录未找到");
throw new Error("无法找到插件目录");
}
new Notice("正在加载...");
await cleanupTempDirectory(adapter, tempDir);
await downloadAndExtractToTemp(
adapter,
tempDir,
dl_zip
);
await copyFilesFromTemp(adapter, tempDir, pluginDir);
new Notice("加载完成成功升级为Pro");
await cleanupTempDirectory(adapter, tempDir);
setTimeout(() => {
console.log(`重载插件: ${plugin.manifest.id}`);
if (hasPluginsProperty(plugin.app)) {
plugin.app.plugins.reloadPlugin(plugin.manifest.id);
}
}, 1000);
return {
success: true,
message: "加载完成成功升级为Pro"
};
} catch (error) {
console.log("错误详情:", error);
// 发生错误时也要清理临时目录
await cleanupTempDirectory(adapter, tempDir);
const errorMessage = error instanceof Error ? error.message : "升级过程中出现未知错误";
console.log(`最终错误信息: ${errorMessage}`);
new Notice(`加载失败: ${errorMessage}`);
return {
success: false,
message: errorMessage
};
}
}

View File

@ -18,6 +18,7 @@ import { findFilesMatchingPatterns } from '../utils/glob-utils';
import BasicAutoCompleteSettings from './components/BasicAutoCompleteSettings';
// import DangerZoneSettings from './components/DangerZoneSettings';
import CustomProviderSettings from './components/ModelProviderSettings';
import PluginInfoSettings from './components/PluginInfoSettings';
import PostprocessingSettings from './components/PostprocessingSettings';
import PreprocessingSettings from './components/PreprocessingSettings';
import PrivacySettings from './components/PrivacySettings';
@ -27,6 +28,7 @@ export class InfioSettingTab extends PluginSettingTab {
plugin: InfioPlugin;
private autoCompleteContainer: HTMLElement | null = null;
private modelsContainer: HTMLElement | null = null;
private pluginInfoContainer: HTMLElement | null = null;
constructor(app: App, plugin: InfioPlugin) {
super(app, plugin)
@ -36,6 +38,7 @@ export class InfioSettingTab extends PluginSettingTab {
display(): void {
const { containerEl } = this
containerEl.empty()
this.renderPluginInfoSection(containerEl)
this.renderModelsSection(containerEl)
this.renderModelParametersSection(containerEl)
this.renderFilesSearchSection(containerEl)
@ -242,6 +245,12 @@ export class InfioSettingTab extends PluginSettingTab {
);
}
renderPluginInfoSection(containerEl: HTMLElement): void {
const pluginInfoDiv = containerEl.createDiv("plugin-info-section");
this.pluginInfoContainer = pluginInfoDiv;
this.renderPluginInfoContent(pluginInfoDiv);
}
renderModelsSection(containerEl: HTMLElement): void {
const modelsDiv = containerEl.createDiv("models-section");
this.modelsContainer = modelsDiv;
@ -725,6 +734,22 @@ export class InfioSettingTab extends PluginSettingTab {
// }
}
private renderPluginInfoContent(containerEl: HTMLElement): void {
const div = containerEl.createDiv("div");
const root = createRoot(div);
root.render(
<PluginInfoSettings
pluginVersion={this.plugin.manifest.version}
// pluginName={this.plugin.manifest.name}
author={this.plugin.manifest.author}
authorUrl={this.plugin.manifest.authorUrl}
// description={this.plugin.manifest.description}
plugin={this.plugin}
settings={this.plugin.settings}
/>
);
}
private renderComponent(containerEl: HTMLElement, component: React.ReactNode) {
const div = containerEl.createDiv("div");
const root = createRoot(div);

View File

@ -0,0 +1,354 @@
import { Notice, Plugin } from 'obsidian';
import * as React from 'react';
import { ApiKeyModal } from '../../components/modals/ApiKeyModal';
import { ProUpgradeModal } from '../../components/modals/ProUpgradeModal';
import { fetchUserPlan, upgradeToProVersion } from '../../hooks/use-infio';
import type { InfioSettings } from '../../types/settings';
import { getInfioLogoSvg } from '../../utils/icon';
type PluginInfoSettingsProps = {
pluginVersion: string;
author: string;
authorUrl: string;
plugin?: Plugin;
settings?: InfioSettings;
};
export default function PluginInfoSettings({
pluginVersion,
author,
authorUrl,
plugin,
settings
}: PluginInfoSettingsProps) {
const isPro = false; // this is must be false
const [isUpgrading, setIsUpgrading] = React.useState(false);
// Convert SVG string to data URL for proper display
const logoDataUrl = `data:image/svg+xml;base64,${btoa(getInfioLogoSvg())}`;
// 处理升级按钮点击
const handleUpgrade = async () => {
if (!plugin) {
new Notice('无法获取插件实例');
return;
}
if (!settings?.infioProvider?.apiKey) {
if (plugin?.app) {
new ApiKeyModal(plugin.app).open();
} else {
new Notice('请先在Infio Provider设置中配置 Infio API Key');
}
return;
}
setIsUpgrading(true);
try {
// 检查是否为Pro用户
const userPlan = await fetchUserPlan(settings.infioProvider.apiKey);
const isProUser = userPlan.plan?.toLowerCase().startsWith('pro') || false;
if (!isProUser) {
if (plugin?.app) {
new ProUpgradeModal(plugin.app).open();
} else {
new Notice('您的账户不是Pro用户无法升级到Pro版本, 请先升级到Pro');
}
return;
}
// 执行升级
const result = await upgradeToProVersion(plugin, userPlan.dl_zip || '');
if (result.success) {
// 升级成功的提示已经在upgradeToProVersion中处理了
} else {
new Notice(`加载失败: ${result.message}`);
}
} catch (error) {
// eslint-disable-next-line no-console
console.error('升级过程中发生错误:', error);
} finally {
setIsUpgrading(false);
}
};
return (
<div className="plugin-info-container">
{/* 插件头部区域 */}
<div className="plugin-header">
<div className="plugin-brand">
<div className="plugin-logo-wrapper">
<img src={logoDataUrl} alt="Infio Logo" className="plugin-logo" />
</div>
<div className="plugin-title-info">
<h1 className="plugin-name">Infio</h1>
<div className="plugin-badges">
<span className={`version-type-badge ${isPro ? 'pro' : 'community'}`}>
{isPro ? 'Pro' : 'community'}
</span>
<span className="version-number">v{pluginVersion}</span>
<button
className="upgrade-button"
onClick={handleUpgrade}
disabled={isUpgrading}
>
{isUpgrading ? '加载中...' : '升级到Pro'}
</button>
</div>
</div>
</div>
</div>
{/* 链接容器 */}
<div className="plugin-links">
{author && authorUrl && (
<a
href={authorUrl}
target="_blank"
rel="noopener noreferrer"
className="plugin-link"
>
<span className="plugin-link-icon">👤</span>
<span>{author}</span>
</a>
)}
<a
href="https://github.com/infiolab/infio-copilot"
target="_blank"
rel="noopener noreferrer"
className="plugin-link"
>
<span className="plugin-link-icon">📖</span>
<span>GitHub</span>
</a>
<a
href="https://infio.app/docs"
target="_blank"
rel="noopener noreferrer"
className="plugin-link"
>
<span className="plugin-link-icon">📚</span>
<span>Documentation</span>
</a>
<a
href="https://github.com/infiolab/obsidian-infio-copilot/issues"
target="_blank"
rel="noopener noreferrer"
className="plugin-link"
>
<span className="plugin-link-icon">💬</span>
<span>Feedback</span>
</a>
</div>
<style>
{`
/* 插件信息容器样式 */
.plugin-info-container {
background: var(--background-primary);
border: 1px solid var(--background-modifier-border);
border-radius: var(--radius-l);
padding: var(--size-4-6);
margin-bottom: var(--size-4-8);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
transition: box-shadow 0.2s ease;
}
.plugin-info-container:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
/* 插件头部区域 */
.plugin-header {
margin-bottom: var(--size-4-6);
}
/* 品牌区域 */
.plugin-brand {
display: flex;
align-items: center;
gap: var(--size-4-3);
}
/* Logo包装器 */
.plugin-logo-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
border-radius: var(--radius-m);
padding: var(--size-2-2);
}
/* 插件logo */
.plugin-logo {
width: 60px;
height: 60px;
flex-shrink: 0;
}
/* 标题信息区域 */
.plugin-title-info {
display: flex;
flex-direction: column;
gap: var(--size-2-2);
}
/* 插件名称 */
.plugin-name {
font-size: 1.75rem;
font-weight: 700;
color: var(--text-normal);
margin: 0;
line-height: 1.2;
letter-spacing: -0.01em;
}
/* 徽章容器 */
.plugin-badges {
display: flex;
align-items: center;
gap: var(--size-2-3);
}
/* 版本类型标识 */
.version-type-badge {
padding: var(--size-2-1) var(--size-2-3);
border-radius: var(--radius-s);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
white-space: nowrap;
}
.version-type-badge.pro {
background: linear-gradient(135deg, var(--interactive-accent), var(--interactive-accent-hover));
color: var(--text-on-accent);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.version-type-badge.community {
background: var(--background-modifier-border);
color: var(--text-muted);
font-weight: 600;
}
/* 版本号 */
.version-number {
color: var(--text-muted);
font-size: var(--font-ui-medium);
font-weight: 500;
background: var(--background-secondary);
padding: var(--size-2-1) var(--size-2-2);
border-radius: var(--radius-s);
border: 1px solid var(--background-modifier-border);
}
/* 升级按钮 */
.upgrade-button {
background: linear-gradient(135deg, var(--interactive-accent), var(--interactive-accent-hover));
color: var(--text-on-accent);
border: none;
padding: var(--size-2-1) var(--size-2-3);
border-radius: var(--radius-s);
font-size: var(--font-ui-small);
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.upgrade-button:hover:not(:disabled) {
background: linear-gradient(135deg, var(--interactive-accent-hover), var(--interactive-accent));
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.upgrade-button:active:not(:disabled) {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.upgrade-button:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* 链接容器 */
.plugin-links {
display: flex;
gap: var(--size-4-2);
flex-wrap: wrap;
}
/* 链接样式 */
.plugin-link {
color: var(--text-accent);
text-decoration: none;
font-size: var(--font-ui-small);
padding: var(--size-2-1) var(--size-2-3);
border: 1px solid var(--background-modifier-border);
border-radius: var(--radius-s);
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: var(--size-2-1);
}
.plugin-link:hover {
background: var(--background-modifier-hover);
border-color: var(--background-modifier-border-hover);
}
/* 响应式设计 */
@media (max-width: 768px) {
.plugin-title-row {
flex-direction: column;
align-items: flex-start;
gap: var(--size-2-3);
}
.plugin-logo {
width: 32px;
height: 32px;
}
.plugin-name {
font-size: 1.5rem;
}
.plugin-badges {
justify-content: center;
}
.plugin-links {
grid-template-columns: 1fr;
gap: var(--size-2-2);
}
.plugin-link {
justify-content: center;
padding: var(--size-2-3);
}
}
/* 深色模式适配 */
.theme-dark .plugin-info-container {
background: var(--background-primary-alt);
border-color: var(--background-modifier-border-hover);
}
`}
</style>
</div>
);
}

View File

@ -343,13 +343,31 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
</svg>
</button>
</Popover.Trigger>
<Popover.Content
side="bottom"
align="start"
sideOffset={4}
className="infio-llm-setting-combobox-dropdown"
>
<div ref={listRef}>
<Popover.Portal>
<Popover.Content
side="bottom"
align="start"
sideOffset={4}
className="infio-model-picker-dropdown"
avoidCollisions={true}
collisionPadding={8}
onOpenAutoFocus={(e) => {
e.preventDefault();
// 延迟聚焦到搜索输入框
setTimeout(() => {
const input = e.currentTarget.querySelector('input');
input?.focus();
}, 0);
}}
onCloseAutoFocus={(e) => e.preventDefault()}
>
<div
ref={listRef}
onMouseDown={(e) => {
// 防止点击内容区域时关闭 Popover
e.stopPropagation();
}}
>
<div className="infio-llm-setting-search-container">
<input
type="text"
@ -360,6 +378,14 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
setSearchTerm(e.target.value);
setSelectedIndex(0);
}}
onMouseDown={(e) => {
// 防止点击输入框时关闭 Popover
e.stopPropagation();
}}
onFocus={(e) => {
// 防止聚焦时关闭 Popover
e.stopPropagation();
}}
onKeyDown={(e) => {
switch (e.key) {
case "ArrowDown":
@ -399,25 +425,28 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
{filteredOptions.length > 0 ? (
<div className="infio-llm-setting-options-list">
{filteredOptions.map((option, index) => (
<Popover.Close key={option.id} asChild>
<div
ref={(el) => (itemRefs.current[index] = el)}
onMouseEnter={() => setSelectedIndex(index)}
onClick={() => {
handleModelSelect(modelProvider, option.id, option.isCustom);
setSearchTerm("");
setIsOpen(false);
}}
className={`infio-llm-setting-combobox-option ${index === selectedIndex ? 'is-selected' : ''}`}
>
<HighlightedText segments={option.html} />
</div>
</Popover.Close>
<div
key={option.id}
ref={(el) => (itemRefs.current[index] = el)}
onMouseEnter={() => setSelectedIndex(index)}
onMouseDown={(e) => {
// 防止事件冒泡
e.preventDefault();
e.stopPropagation();
handleModelSelect(modelProvider, option.id, option.isCustom);
setSearchTerm("");
setIsOpen(false);
}}
className={`infio-llm-setting-combobox-option ${index === selectedIndex ? 'is-selected' : ''}`}
>
<HighlightedText segments={option.html} />
</div>
))}
</div>
) : null}
</div>
</Popover.Content>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
</div>
</div>
@ -457,6 +486,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
display: flex;
align-items: center;
gap: 12px;
position: relative;
}
.infio-llm-setting-provider-label,
@ -545,15 +575,30 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
transform: rotate(180deg);
}
.infio-llm-setting-combobox-dropdown {
.infio-model-picker-dropdown {
background: var(--background-primary);
border: 1px solid var(--background-modifier-border);
border-radius: 6px;
box-shadow: var(--shadow-s);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
padding: 6px;
min-width: 300px;
max-width: 500px;
z-index: 1000;
z-index: 10000;
max-height: 300px;
overflow: hidden;
transform-origin: var(--radix-popover-content-transform-origin);
animation: popover-in 0.15s ease-out;
}
@keyframes popover-in {
from {
opacity: 0;
transform: scale(0.95) translateY(-5px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.infio-llm-setting-search-container {
@ -578,8 +623,9 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
}
.infio-llm-setting-options-list {
max-height: 200px;
max-height: 240px;
overflow-y: auto;
overscroll-behavior: contain;
}
.infio-llm-setting-combobox-option {

2
src/utils/icon.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
export declare function getInfioLogoSimpleSvg(): string;
export declare function getInfioLogoSvg(): string;

22
src/utils/icon.ts Normal file
View File

@ -0,0 +1,22 @@
/**
* Utility functions for creating Obsidian-compatible icons
*/
/**
* Generate a simplified monochrome version for smaller sizes
*/
export function getInfioLogoSimpleSvg(): string {
return `<svg viewBox="0 0 233 179" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M231.342 93.98L229.862 92.43H219.602L223.192 0.45L208.392 0L205.622 65.43C146.022 62.19 86.2922 62.19 26.7022 65.41L24.9722 0.45L10.1722 0.9L12.6722 92.43H2.16217L0.752167 93.9C-0.797833 110.13 0.0921667 126.58 3.01217 142.79H13.8422L14.0222 144.06C14.6922 163.4 30.1222 178.74 49.9222 178.74C69.7222 178.74 94.7822 177.82 116.042 177.82C137.302 177.82 162.602 178.74 181.992 178.74C201.382 178.74 217.182 163.45 217.892 144.13L218.052 142.79H229.072C231.982 126.6 232.882 110.18 231.332 93.98H231.342ZM73.1122 151.99C55.8422 151.99 42.8622 138.21 42.8622 122.21C42.8622 106.21 55.8522 92.43 73.1122 92.43C90.3722 92.43 102.732 106.37 102.732 122.37C102.732 138.37 90.3822 151.99 73.1122 151.99ZM159.622 151.99C142.352 151.99 129.372 138.21 129.372 122.21C129.372 106.21 142.362 92.43 159.622 92.43C176.882 92.43 189.242 106.37 189.242 122.37C189.242 138.37 176.892 151.99 159.622 151.99Z" style="fill:currentColor;fill-rule:nonzero"/>
</svg>`;
}
export function getInfioLogoSvg(): string {
return `<svg width="233" height="233" viewBox="0 0 233 233" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M231.342 93.98L229.862 92.43H219.602L223.192 0.45L208.392 0L205.622 65.43C146.022 62.19 86.2922 62.19 26.7022 65.41L24.9722 0.45L10.1722 0.9L12.6722 92.43H2.16217L0.752167 93.9C-0.797833 110.13 0.0921667 126.58 3.01217 142.79H13.8422L14.0222 144.06C14.6922 163.4 30.1222 178.74 49.9222 178.74C69.7222 178.74 94.7822 177.82 116.042 177.82C137.302 177.82 162.602 178.74 181.992 178.74C201.382 178.74 217.182 163.45 217.892 144.13L218.052 142.79H229.072C231.982 126.6 232.882 110.18 231.332 93.98H231.342ZM73.1122 151.99C55.8422 151.99 42.8622 138.21 42.8622 122.21C42.8622 106.21 55.8522 92.43 73.1122 92.43C90.3722 92.43 102.732 106.37 102.732 122.37C102.732 138.37 90.3822 151.99 73.1122 151.99ZM159.622 151.99C142.352 151.99 129.372 138.21 129.372 122.21C129.372 106.21 142.362 92.43 159.622 92.43C176.882 92.43 189.242 106.37 189.242 122.37C189.242 138.37 176.892 151.99 159.622 151.99Z" fill="#808080"/>
</svg>
`
}

View File

@ -2,7 +2,7 @@ import { ApiProvider } from '../types/llm/model';
// Provider API Key获取地址映射
export const providerApiUrls: Record<ApiProvider, string> = {
[ApiProvider.Infio]: 'https://platform.infio.app/home',
[ApiProvider.Infio]: 'https://platform.infio.app/api-keys',
[ApiProvider.OpenRouter]: 'https://openrouter.ai/settings/keys',
[ApiProvider.SiliconFlow]: 'https://cloud.siliconflow.cn/account/ak',
[ApiProvider.AlibabaQwen]: 'https://help.aliyun.com/zh/dashscope/developer-reference/activate-dashscope-and-create-an-api-key',