From 9a848489e33d518d8bdcc29400be8e28c68fb2e9 Mon Sep 17 00:00:00 2001 From: duanfuxiang Date: Wed, 20 Aug 2025 22:08:04 +0800 Subject: [PATCH] release version update --- CHANGELOG.yaml | 3 + manifest.json | 3 +- package.json | 13 +- pnpm-lock.yaml | 286 ++++++++------ src/components/modals/ApiKeyModal.tsx | 246 ++++++++++++ src/components/modals/ProUpgradeModal.tsx | 183 +++++++++ src/constants.ts | 4 +- src/core/llm/openai-compatible.ts | 17 +- src/hooks/use-infio.ts | 294 +++++++++++++++ src/settings/SettingTab.tsx | 25 ++ .../components/PluginInfoSettings.tsx | 354 ++++++++++++++++++ .../components/ProviderModelsPicker.tsx | 98 +++-- src/utils/icon.d.ts | 2 + src/utils/icon.ts | 22 ++ src/utils/provider-urls.ts | 2 +- 15 files changed, 1404 insertions(+), 148 deletions(-) create mode 100644 src/components/modals/ApiKeyModal.tsx create mode 100644 src/components/modals/ProUpgradeModal.tsx create mode 100644 src/hooks/use-infio.ts create mode 100644 src/settings/components/PluginInfoSettings.tsx create mode 100644 src/utils/icon.d.ts create mode 100644 src/utils/icon.ts diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 2aa7fe9..4340206 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -1,4 +1,7 @@ releases: + - version: "0.8.0" + features: + - "add infio pro" - version: "0.7.6" features: - "update mcp settings file watcher" diff --git a/manifest.json b/manifest.json index 7915b85..6f0b650 100644 --- a/manifest.json +++ b/manifest.json @@ -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 } + diff --git a/package.json b/package.json index f153d1d..63f102c 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3bed62c..8ab4523 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/src/components/modals/ApiKeyModal.tsx b/src/components/modals/ApiKeyModal.tsx new file mode 100644 index 0000000..a024a3c --- /dev/null +++ b/src/components/modals/ApiKeyModal.tsx @@ -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 = ({ 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 ( +
+
+

配置 API Key

+
+ +
+
+ {/*
🔑
*/} +

请先在 Infio Provider 设置中配置 Infio API Key

+

您可以按照以下步骤获取和配置 API Key:

+ +
+
+
1
+
+

获取 API Key

+

访问 Infio 平台获取您的 API Key

+ +
+
+ +
+
2
+
+

确保已升级为 Pro 会员

+

升级到 Pro 会员以享受更多高级功能和模型访问权限

+ +
+
+ +
+
3
+
+

配置 Infio API Key

+

在插件设置中的 Infio Provider 部分配置您的 Infio API Key

+ +
+
+
+
+
+ +
+ +
+ + +
+ ) +} + +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( + this.close()} + app={this.app} + /> + ) + } + + onClose(): void { + const { contentEl, modalEl } = this + modalEl.removeClass('mod-api-key') + this.root?.unmount() + this.root = null + contentEl.empty() + } +} diff --git a/src/components/modals/ProUpgradeModal.tsx b/src/components/modals/ProUpgradeModal.tsx new file mode 100644 index 0000000..1b03a7d --- /dev/null +++ b/src/components/modals/ProUpgradeModal.tsx @@ -0,0 +1,183 @@ +import { App, Modal } from 'obsidian' +import { createRoot, Root } from 'react-dom/client' + +interface ProUpgradeModalContentProps { + onClose: () => void +} + +const ProUpgradeModalContent: React.FC = ({ onClose }) => { + const handleUpgradeClick = () => { + window.open('https://platform.infio.com/billing', '_blank') + } + + return ( +
+
+

升级到 Pro 会员

+
+ +
+
+
+

您的账户不是Pro会员,无法升级到Pro版本。

+

请先升级到Pro,享受更多高级功能:

+
    +
  • ✨ 全新的UI界面
  • +
  • 🚀 在线市场使用权限
  • +
  • 💎 专注任务模型访问权限
  • +
  • 🎯 专业技术支持
  • +
+
+
+ +
+ + +
+ + +
+ ) +} + +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( + this.close()} + /> + ) + } + + onClose(): void { + const { contentEl, modalEl } = this + modalEl.removeClass('mod-pro-upgrade') + this.root?.unmount() + this.root = null + contentEl.empty() + } +} diff --git a/src/constants.ts b/src/constants.ts index 55dfb60..db9e1b8 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -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 diff --git a/src/core/llm/openai-compatible.ts b/src/core/llm/openai-compatible.ts index c31b038..54e435d 100644 --- a/src/core/llm/openai-compatible.ts +++ b/src/core/llm/openai-compatible.ts @@ -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 { + private getExtraParams(isStreaming: boolean, modelName: string): Record { const extraParams: Record = {} // 阿里云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) } } diff --git a/src/hooks/use-infio.ts b/src/hooks/use-infio.ts new file mode 100644 index 0000000..796f7ed --- /dev/null +++ b/src/hooks/use-infio.ts @@ -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 => { + 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 => { + 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 => { + 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 => { + 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 => { + 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 => { + 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 + }; + } +} diff --git a/src/settings/SettingTab.tsx b/src/settings/SettingTab.tsx index b32ece2..9a64655 100644 --- a/src/settings/SettingTab.tsx +++ b/src/settings/SettingTab.tsx @@ -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( + + ); + } + private renderComponent(containerEl: HTMLElement, component: React.ReactNode) { const div = containerEl.createDiv("div"); const root = createRoot(div); diff --git a/src/settings/components/PluginInfoSettings.tsx b/src/settings/components/PluginInfoSettings.tsx new file mode 100644 index 0000000..c207a99 --- /dev/null +++ b/src/settings/components/PluginInfoSettings.tsx @@ -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 ( +
+ {/* 插件头部区域 */} +
+
+
+ Infio Logo +
+
+

Infio

+
+ + {isPro ? 'Pro' : 'community'} + + v{pluginVersion} + +
+
+
+
+ + {/* 链接容器 */} + + + +
+ ); +} diff --git a/src/settings/components/ProviderModelsPicker.tsx b/src/settings/components/ProviderModelsPicker.tsx index 49c8afd..d8401fb 100644 --- a/src/settings/components/ProviderModelsPicker.tsx +++ b/src/settings/components/ProviderModelsPicker.tsx @@ -343,13 +343,31 @@ export const ComboBoxComponent: React.FC = ({ - -
+ + { + e.preventDefault(); + // 延迟聚焦到搜索输入框 + setTimeout(() => { + const input = e.currentTarget.querySelector('input'); + input?.focus(); + }, 0); + }} + onCloseAutoFocus={(e) => e.preventDefault()} + > +
{ + // 防止点击内容区域时关闭 Popover + e.stopPropagation(); + }} + >
= ({ 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 = ({ {filteredOptions.length > 0 ? (
{filteredOptions.map((option, index) => ( - -
(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' : ''}`} - > - -
-
+
(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' : ''}`} + > + +
))}
) : null}
- + +
@@ -457,6 +486,7 @@ export const ComboBoxComponent: React.FC = ({ display: flex; align-items: center; gap: 12px; + position: relative; } .infio-llm-setting-provider-label, @@ -545,15 +575,30 @@ export const ComboBoxComponent: React.FC = ({ 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 = ({ } .infio-llm-setting-options-list { - max-height: 200px; + max-height: 240px; overflow-y: auto; + overscroll-behavior: contain; } .infio-llm-setting-combobox-option { diff --git a/src/utils/icon.d.ts b/src/utils/icon.d.ts new file mode 100644 index 0000000..39f2ccc --- /dev/null +++ b/src/utils/icon.d.ts @@ -0,0 +1,2 @@ +export declare function getInfioLogoSimpleSvg(): string; +export declare function getInfioLogoSvg(): string; diff --git a/src/utils/icon.ts b/src/utils/icon.ts new file mode 100644 index 0000000..b1709da --- /dev/null +++ b/src/utils/icon.ts @@ -0,0 +1,22 @@ +/** + * Utility functions for creating Obsidian-compatible icons + */ + + + +/** + * Generate a simplified monochrome version for smaller sizes + */ +export function getInfioLogoSimpleSvg(): string { + return ` + +`; +} + +export function getInfioLogoSvg(): string { + return ` + + +` +} + diff --git a/src/utils/provider-urls.ts b/src/utils/provider-urls.ts index 82e4bbf..74d5ef1 100644 --- a/src/utils/provider-urls.ts +++ b/src/utils/provider-urls.ts @@ -2,7 +2,7 @@ import { ApiProvider } from '../types/llm/model'; // Provider API Key获取地址映射 export const providerApiUrls: Record = { - [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',