Cursor style input (#790)

This commit is contained in:
Logan Yang 2024-11-08 14:41:05 -08:00 committed by GitHub
parent 8fa2060a6c
commit 92aaa86f8e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 1144 additions and 122 deletions

View file

@ -3,7 +3,7 @@
"name": "Copilot",
"version": "2.7.1",
"minAppVersion": "0.15.0",
"description": "A ChatGPT Copilot in Obsidian.",
"description": "An AI Copilot in Obsidian.",
"author": "Logan Yang",
"authorUrl": "https://twitter.com/logancyang",
"fundingUrl": {

773
package-lock.json generated
View file

@ -18,6 +18,8 @@
"@langchain/google-genai": "^0.1.2",
"@langchain/groq": "^0.1.2",
"@orama/orama": "^3.0.0-rc-2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-tooltip": "^1.1.3",
"@tabler/icons-react": "^2.14.0",
"axios": "^1.3.4",
"cohere-ai": "^7.13.0",
@ -27,6 +29,7 @@
"koa": "^2.14.2",
"koa-proxies": "^0.12.3",
"langchain": "^0.3.2",
"lucide-react": "^0.454.0",
"next-i18next": "^13.2.2",
"prop-types": "^15.8.1",
"react": "^18.2.0",
@ -2464,6 +2467,40 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@floating-ui/core": {
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz",
"integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==",
"dependencies": {
"@floating-ui/utils": "^0.2.8"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.12",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz",
"integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.8"
}
},
"node_modules/@floating-ui/react-dom": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
"integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
"dependencies": {
"@floating-ui/dom": "^1.0.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig=="
},
"node_modules/@google/generative-ai": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.7.1.tgz",
@ -4001,6 +4038,592 @@
"node": ">= 16.0.0"
}
},
"node_modules/@radix-ui/primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
"integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA=="
},
"node_modules/@radix-ui/react-arrow": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
"integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==",
"dependencies": {
"@radix-ui/react-primitive": "2.0.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
"integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-slot": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
"integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-context": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
"integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-direction": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
"integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dismissable-layer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz",
"integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-escape-keydown": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dropdown-menu": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz",
"integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-menu": "2.1.2",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-guards": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz",
"integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-scope": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz",
"integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-id": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
"integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-menu": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz",
"integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-dismissable-layer": "1.1.1",
"@radix-ui/react-focus-guards": "1.1.1",
"@radix-ui/react-focus-scope": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-popper": "1.2.0",
"@radix-ui/react-portal": "1.1.2",
"@radix-ui/react-presence": "1.1.1",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-roving-focus": "1.1.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"aria-hidden": "^1.1.1",
"react-remove-scroll": "2.6.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popper": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
"integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==",
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
"@radix-ui/react-arrow": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0",
"@radix-ui/react-use-rect": "1.1.0",
"@radix-ui/react-use-size": "1.1.0",
"@radix-ui/rect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-portal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz",
"integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==",
"dependencies": {
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-presence": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
"integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-primitive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
"integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
"dependencies": {
"@radix-ui/react-slot": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
"integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tooltip": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.3.tgz",
"integrity": "sha512-Z4w1FIS0BqVFI2c1jZvb/uDVJijJjJ2ZMuPV81oVgTZ7g3BZxobplnMVvXtFWgtozdvYJ+MFWtwkM5S2HnAong==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-dismissable-layer": "1.1.1",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-popper": "1.2.0",
"@radix-ui/react-portal": "1.1.2",
"@radix-ui/react-presence": "1.1.1",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0",
"@radix-ui/react-visually-hidden": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
"integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz",
"integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-escape-keydown": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
"integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
"integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
"integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==",
"dependencies": {
"@radix-ui/rect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-size": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
"integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-visually-hidden": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz",
"integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==",
"dependencies": {
"@radix-ui/react-primitive": "2.0.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -5566,7 +6189,7 @@
"version": "18.0.11",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz",
"integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==",
"dev": true,
"devOptional": true,
"dependencies": {
"@types/react": "*"
}
@ -6051,6 +6674,17 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/aria-hidden": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz",
"integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/aria-query": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
@ -7222,6 +7856,11 @@
"dev": true,
"optional": true
},
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
},
"node_modules/devlop": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
@ -8386,6 +9025,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-nonce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
"engines": {
"node": ">=6"
}
},
"node_modules/get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@ -9104,6 +9751,14 @@
"node": ">= 0.4"
}
},
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
@ -11596,6 +12251,14 @@
"yallist": "^3.0.2"
}
},
"node_modules/lucide-react": {
"version": "0.454.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.454.0.tgz",
"integrity": "sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
}
},
"node_modules/lz-string": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
@ -13554,6 +14217,73 @@
"@types/unist": "*"
}
},
"node_modules/react-remove-scroll": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
"integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==",
"dependencies": {
"react-remove-scroll-bar": "^2.3.6",
"react-style-singleton": "^2.2.1",
"tslib": "^2.1.0",
"use-callback-ref": "^1.3.0",
"use-sidecar": "^1.1.2"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-remove-scroll-bar": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
"integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
"dependencies": {
"react-style-singleton": "^2.2.1",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-style-singleton": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
"integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==",
"dependencies": {
"get-nonce": "^1.0.0",
"invariant": "^2.2.4",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-syntax-highlighter": {
"version": "15.5.0",
"resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz",
@ -14829,6 +15559,47 @@
"requires-port": "^1.0.0"
}
},
"node_modules/use-callback-ref": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz",
"integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-sidecar": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
"integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",

View file

@ -69,6 +69,8 @@
"@langchain/google-genai": "^0.1.2",
"@langchain/groq": "^0.1.2",
"@orama/orama": "^3.0.0-rc-2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-tooltip": "^1.1.3",
"@tabler/icons-react": "^2.14.0",
"axios": "^1.3.4",
"cohere-ai": "^7.13.0",
@ -78,6 +80,7 @@
"koa": "^2.14.2",
"koa-proxies": "^0.12.3",
"langchain": "^0.3.2",
"lucide-react": "^0.454.0",
"next-i18next": "^13.2.2",
"prop-types": "^15.8.1",
"react": "^18.2.0",

View file

@ -1,7 +1,6 @@
import ChainManager from "@/LLMProviders/chainManager";
import { useAIState } from "@/aiState";
import { updateChatMemory } from "@/chatUtils";
import ChatControls from "@/components/ChatComponents/ChatControls";
import ChatInput from "@/components/ChatComponents/ChatInput";
import ChatMessages from "@/components/ChatComponents/ChatMessages";
import {
@ -546,7 +545,16 @@ ${chatContent}`;
}}
/>
<div className="bottom-container">
<ChatControls
<ChatInput
inputMessage={inputMessage}
setInputMessage={setInputMessage}
handleSendMessage={handleSendMessage}
isGenerating={loading}
onStopGenerating={() => handleStopGenerating(ABORT_REASON.USER_STOPPED)}
app={app}
settings={settings}
navigateHistory={navigateHistory}
chatIsVisible={chatIsVisible}
currentModelKey={currentModelKey}
setCurrentModelKey={setModelKey}
currentChain={currentChain}
@ -562,25 +570,10 @@ ${chatContent}`;
}}
onSaveAsNote={() => handleSaveAsNote(true)}
onRefreshVaultContext={refreshVaultContext}
onFindSimilarNotes={(content, activeFilePath) =>
plugin.findSimilarNotes(content, activeFilePath)
}
addMessage={addMessage}
settings={settings}
vault={app.vault}
vault_qa_strategy={plugin.settings.indexVaultToVectorStore}
debug={debug}
/>
<ChatInput
inputMessage={inputMessage}
setInputMessage={setInputMessage}
handleSendMessage={handleSendMessage}
isGenerating={loading}
onStopGenerating={() => handleStopGenerating(ABORT_REASON.USER_STOPPED)}
app={app}
settings={settings}
navigateHistory={navigateHistory}
chatIsVisible={chatIsVisible}
addMessage={addMessage}
vault={app.vault}
/>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { CustomModel, SetChainOptions } from "@/aiParams";
import { SetChainOptions } from "@/aiParams";
import { CopilotPlusModal } from "@/components/CopilotPlusModal";
import { VAULT_VECTOR_STORE_STRATEGY } from "@/constants";
import { CustomError } from "@/error";
@ -10,6 +10,8 @@ import React, { useEffect, useState } from "react";
import { ChainType } from "@/chainFactory";
import { RefreshIcon, SaveAsNoteIcon, UseActiveNoteAsContextIcon } from "@/components/Icons";
import { stringToChainType } from "@/utils";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { ChevronDown } from "lucide-react";
interface ChatControlsProps {
currentModelKey: string;
@ -19,7 +21,6 @@ interface ChatControlsProps {
onNewChat: (openNote: boolean) => void;
onSaveAsNote: () => void;
onRefreshVaultContext: () => void;
onFindSimilarNotes: (content: string, activeFilePath: string) => Promise<any>;
addMessage: (message: ChatMessage) => void;
settings: CopilotSettings;
vault: Vault;
@ -35,7 +36,6 @@ const ChatControls: React.FC<ChatControlsProps> = ({
onNewChat,
onSaveAsNote,
onRefreshVaultContext,
onFindSimilarNotes,
addMessage,
settings,
vault,
@ -44,15 +44,8 @@ const ChatControls: React.FC<ChatControlsProps> = ({
}) => {
const [selectedChain, setSelectedChain] = useState<ChainType>(currentChain);
const getModelKey = (model: CustomModel) => `${model.name}|${model.provider}`;
const handleModelChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
const selectedModelKey = event.target.value;
setCurrentModelKey(selectedModelKey);
};
const handleChainChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
const newChain = stringToChainType(event.target.value);
const handleChainChange = async ({ value }: { value: string }) => {
const newChain = stringToChainType(value);
setSelectedChain(newChain);
if (newChain === ChainType.COPILOT_PLUS_CHAIN) {
@ -113,25 +106,6 @@ const ChatControls: React.FC<ChatControlsProps> = ({
return (
<div className="chat-icons-container">
<div className="chat-icon-selection-tooltip">
<div className="select-wrapper">
<select
id="aiModelSelect"
className="chat-icon-selection model-select"
value={currentModelKey}
onChange={handleModelChange}
>
{settings.activeModels
.filter((model) => model.enabled)
.map((model) => (
<option key={getModelKey(model)} value={getModelKey(model)}>
{model.name}
</option>
))}
</select>
<span className="tooltip-text">Model Selection</span>
</div>
</div>
<button className="chat-icon-button clickable-icon" onClick={() => onNewChat(false)}>
<RefreshIcon className="icon-scaler" />
<span className="tooltip-text">
@ -144,21 +118,6 @@ const ChatControls: React.FC<ChatControlsProps> = ({
<SaveAsNoteIcon className="icon-scaler" />
<span className="tooltip-text">Save as Note</span>
</button>
<div className="chat-icon-selection-tooltip">
<div className="select-wrapper">
<select
id="aiChainSelect"
className="chat-icon-selection"
value={currentChain}
onChange={handleChainChange}
>
<option value="llm_chain">Chat</option>
<option value="vault_qa">Vault QA (Basic)</option>
<option value="copilot_plus">Copilot Plus (Alpha)</option>
</select>
<span className="tooltip-text">Mode Selection</span>
</div>
</div>
{selectedChain === "vault_qa" && (
<>
<button className="chat-icon-button clickable-icon" onClick={onRefreshVaultContext}>
@ -178,6 +137,30 @@ const ChatControls: React.FC<ChatControlsProps> = ({
</button> */}
</>
)}
<div className="chat-icon-selection-tooltip">
<DropdownMenu.Root>
<DropdownMenu.Trigger className="chain-select-button">
{currentChain === "llm_chain" && "Chat Mode"}
{currentChain === "vault_qa" && "Vault QA Mode (Basic)"}
{currentChain === "copilot_plus" && "Copilot Plus Mode (Alpha)"}
<ChevronDown size={10} />
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="chain-select-content">
<DropdownMenu.Item onSelect={() => handleChainChange({ value: "llm_chain" })}>
Chat Mode
</DropdownMenu.Item>
<DropdownMenu.Item onSelect={() => handleChainChange({ value: "vault_qa" })}>
Vault QA Mode (Basic)
</DropdownMenu.Item>
<DropdownMenu.Item onSelect={() => handleChainChange({ value: "copilot_plus" })}>
Copilot Plus Mode (Alpha)
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
</div>
</div>
);
};

View file

@ -1,10 +1,16 @@
import { CustomModel, SetChainOptions } from "@/aiParams";
import { ChainType } from "@/chainFactory";
import { ListPromptModal } from "@/components/ListPromptModal";
import { NoteTitleModal } from "@/components/NoteTitleModal";
import { CustomPromptProcessor } from "@/customPromptProcessor";
import { CopilotSettings } from "@/settings/SettingsPage";
import { IconPlayerStopFilled, IconSend } from "@tabler/icons-react";
import { App, TFile } from "obsidian";
import { ChatMessage } from "@/sharedState";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import * as Tooltip from "@radix-ui/react-tooltip";
import { ChevronUp, Command, CornerDownLeft, StopCircle } from "lucide-react";
import { App, Platform, TFile, Vault } from "obsidian";
import React, { useEffect, useRef, useState } from "react";
import ChatControls from "./ChatControls";
interface ChatInputProps {
inputMessage: string;
@ -16,8 +22,21 @@ interface ChatInputProps {
app: App;
settings: CopilotSettings;
navigateHistory: (direction: "up" | "down") => string;
currentModelKey: string;
setCurrentModelKey: (modelKey: string) => void;
currentChain: ChainType;
setCurrentChain: (chain: ChainType, options?: SetChainOptions) => void;
onNewChat: (openNote: boolean) => void;
onSaveAsNote: () => void;
onRefreshVaultContext: () => void;
addMessage: (message: ChatMessage) => void;
vault: Vault;
vault_qa_strategy: string;
debug?: boolean;
}
const getModelKey = (model: CustomModel) => `${model.name}|${model.provider}`;
const ChatInput: React.FC<ChatInputProps> = ({
inputMessage,
setInputMessage,
@ -28,10 +47,22 @@ const ChatInput: React.FC<ChatInputProps> = ({
settings,
navigateHistory,
chatIsVisible,
currentModelKey,
setCurrentModelKey,
currentChain,
setCurrentChain,
onNewChat,
onSaveAsNote,
onRefreshVaultContext,
addMessage,
vault,
vault_qa_strategy,
debug,
}) => {
const [shouldFocus, setShouldFocus] = useState(false);
const [historyIndex, setHistoryIndex] = useState(-1);
const [tempInput, setTempInput] = useState("");
const [isModelDropdownOpen, setIsModelDropdownOpen] = useState(false);
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
@ -166,6 +197,21 @@ const ChatInput: React.FC<ChatInputProps> = ({
return (
<div className="chat-input-container" ref={containerRef}>
<ChatControls
currentModelKey={currentModelKey}
setCurrentModelKey={setCurrentModelKey}
currentChain={currentChain}
setCurrentChain={setCurrentChain}
onNewChat={onNewChat}
onSaveAsNote={onSaveAsNote}
onRefreshVaultContext={onRefreshVaultContext}
settings={settings}
vault_qa_strategy={vault_qa_strategy}
debug={debug}
addMessage={addMessage}
vault={vault}
/>
<textarea
ref={textAreaRef}
className="chat-input-textarea"
@ -174,12 +220,69 @@ const ChatInput: React.FC<ChatInputProps> = ({
onChange={handleInputChange}
onKeyDown={handleKeyDown}
/>
<button
onClick={isGenerating ? onStopGenerating : handleSendMessage}
aria-label={isGenerating ? "Stop generating" : "Send message"}
>
{isGenerating ? <IconPlayerStopFilled size={18} /> : <IconSend size={18} />}
</button>
<div className="chat-input-controls">
<DropdownMenu.Root open={isModelDropdownOpen} onOpenChange={setIsModelDropdownOpen}>
<DropdownMenu.Trigger className="model-select-button">
{settings.activeModels.find((model) => getModelKey(model) === currentModelKey)?.name ||
"Select Model"}
<ChevronUp size={10} />
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="model-select-content">
{settings.activeModels
.filter((model) => model.enabled)
.map((model) => (
<DropdownMenu.Item
key={getModelKey(model)}
onSelect={() => setCurrentModelKey(getModelKey(model))}
>
{model.name}
</DropdownMenu.Item>
))}
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
<div className="chat-input-buttons">
{isGenerating && (
<Tooltip.Provider delayDuration={0}>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button onClick={() => onStopGenerating()} className="submit-button cancel">
<StopCircle />
</button>
</Tooltip.Trigger>
</Tooltip.Root>
</Tooltip.Provider>
)}
<Tooltip.Provider delayDuration={0}>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button onClick={handleSendMessage} className="submit-button">
<CornerDownLeft size={16} />
<span>chat</span>
</button>
</Tooltip.Trigger>
</Tooltip.Root>
{currentChain === "copilot_plus" && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button onClick={handleSendMessage} className="submit-button vault">
<div className="button-content">
{Platform.isMacOS && <Command size={12} />}
<CornerDownLeft size={16} />
<span>vault</span>
</div>
</button>
</Tooltip.Trigger>
</Tooltip.Root>
)}
</Tooltip.Provider>
</div>
</div>
</div>
);
};

View file

@ -65,8 +65,8 @@ If your plugin does not need CSS, delete this file.
}
.copilot-setting-item-control::placeholder {
color: gray; /* Set the color you want for the placeholder text */
opacity: 0.5; /* Adjust for lighter appearance */
color: gray;
opacity: 0.5;
}
.copilot-setting-item-control[type="range"] {
@ -78,7 +78,7 @@ If your plugin does not need CSS, delete this file.
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden; /* Fix overflow and can't scroll up */
overflow: hidden;
}
.bottom-container {
@ -93,25 +93,24 @@ If your plugin does not need CSS, delete this file.
.chat-icons-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 8px 8px 0;
order: 1;
gap: 8px;
padding: 0 0 4px;
gap: 4px;
flex-wrap: wrap;
justify-content: flex-end;
}
.icon-scaler {
transform: scale(1.6);
transform: scale(0.5);
}
.tooltip-text {
max-width: 400px;
visibility: hidden;
opacity: 0;
background-color: #333;
color: #fff;
background-color: var(--background-secondary);
color: var(--text-normal);
text-align: center;
border-radius: 5px;
padding: 5px;
@ -122,6 +121,8 @@ If your plugin does not need CSS, delete this file.
margin-bottom: 4px;
transform: translateX(-50%);
transition: opacity 0.3s;
font-size: var(--font-ui-smaller);
white-space: nowrap;
}
.select-wrapper {
@ -135,56 +136,222 @@ If your plugin does not need CSS, delete this file.
opacity: 1 !important;
}
.chat-icon-button.clickable-icon {
display: flex !important;
justify-content: center !important;
align-items: center !important;
width: 22px !important;
height: 22px !important;
cursor: pointer !important;
position: relative !important;
.chat-icon-button.clickable-icon,
.chat-icon-selection,
.model-select-button,
.submit-button,
.chain-select-button {
display: flex;
align-items: center;
gap: 2px;
padding: 0;
background: none !important;
border: none !important;
box-shadow: none !important;
color: var(--text-muted);
font-size: 10px;
cursor: pointer;
opacity: 0.5;
transition: opacity 0.2s ease;
}
.chat-icon-selection {
color: var(--inline-title-color);
.chat-icon-button.clickable-icon:hover,
.chat-icon-selection:hover,
.model-select-button:hover,
.submit-button:hover,
.chain-select-button:hover {
background: none !important;
color: var(--text-normal);
opacity: 1;
}
@keyframes flash {
0%,
100% {
opacity: 0.5;
}
50% {
opacity: 1;
}
}
.submit-button.cancel {
opacity: 0.5;
padding: 4px;
border-radius: 4px;
animation: flash 2s infinite;
}
.submit-button.cancel:hover {
opacity: 1;
}
.chat-input-container {
display: flex;
padding: 8px;
box-sizing: border-box;
flex-grow: 1;
flex-direction: column;
width: 100%;
order: 2;
position: relative;
background: var(--background-secondary-alt);
border-radius: 4px;
padding: 4px;
gap: 2px;
}
.chat-input-container textarea {
.chat-input-textarea {
width: 100%;
margin-right: 0;
margin-bottom: 8px;
min-height: 44px;
resize: none;
overflow: auto;
min-height: 60px;
max-height: 200px;
box-sizing: border-box;
border: 1px solid gray;
border-radius: 10px;
padding: 15px 60px 15px 15px;
padding: 2px 12px;
background: var(--background-secondary-alt);
border: none;
border-radius: 4px;
color: var(--text-normal);
font-size: 13px;
}
.chat-input-container textarea::placeholder {
color: var(--inline-title-color);
.chat-input-textarea::placeholder {
color: var(--text-muted);
opacity: 0.5;
}
.chat-input-container button {
.chat-input-textarea:focus {
outline: none;
border: none;
box-shadow: none;
}
.chat-input-controls {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 4px;
}
.chat-input-buttons {
display: flex;
gap: 8px;
}
.model-select-content {
min-width: 120px;
background: var(--background-secondary);
border: 1px solid var(--background-modifier-border);
border-radius: 4px;
padding: 4px;
font-size: 10px;
transform: translateX(18px);
}
.model-select-content [role="menuitem"] {
padding: 6px 12px;
cursor: pointer;
border-radius: 2px;
font-size: 10px;
color: var(--text-normal);
margin: 2px 0;
}
.model-select-content [role="menuitem"]:hover {
background: var(--background-modifier-hover);
}
.submit-button svg,
.model-select-button svg,
.chain-select-button svg {
width: 10px;
height: 10px;
}
.chain-select-button:hover {
opacity: 1;
background: var(--background-modifier-hover);
}
.chain-select-content {
min-width: 120px;
background: var(--background-secondary);
border: 1px solid var(--background-modifier-border);
border-radius: 4px;
padding: 4px;
font-size: 10px;
transform: translateX(-18px);
}
.chain-select-content [role="menuitem"] {
padding: 6px 12px;
cursor: pointer;
border-radius: 2px;
font-size: 10px;
color: var(--text-normal);
margin: 2px 0;
}
.chain-select-content [role="menuitem"]:hover {
background: var(--background-modifier-hover);
}
/* Make the chevron icon smaller */
.chain-select-button svg {
width: 12px;
height: 12px;
}
.chain-select-button span {
opacity: 1;
}
/* Tooltip Styles */
.tooltip-text {
max-width: 400px;
visibility: hidden;
opacity: 0;
background-color: var(--background-secondary);
color: var(--text-normal);
text-align: center;
border-radius: 5px;
padding: 5px;
position: absolute;
right: 22px;
bottom: 31px;
padding: 8px;
margin: 0;
z-index: 1;
bottom: 100%;
left: 50%;
margin-bottom: 4px;
transform: translateX(-50%);
transition: opacity 0.3s;
font-size: var(--font-ui-smaller);
white-space: nowrap;
}
/* Button and Tooltip Container */
.chat-icon-button {
position: relative;
}
/* Show tooltip on hover */
.chat-icon-button:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
/* Ensure tooltips are visible for all icon buttons */
.chat-icon-button.clickable-icon .tooltip-text {
visibility: hidden;
opacity: 0;
}
.chat-icon-button.clickable-icon:hover .tooltip-text {
visibility: visible !important;
opacity: 1 !important;
}
.submit-button svg,
.model-select-button svg,
.chain-select-button svg {
width: 12px;
height: 12px;
}
.chat-icon-button.clickable-icon:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
.chat-messages {
@ -327,19 +494,20 @@ If your plugin does not need CSS, delete this file.
display: flex;
gap: 4px;
align-items: center;
height: 24px;
height: 20px;
margin-left: auto;
}
.chat-message-buttons button {
width: 24px;
height: 24px;
width: 20px;
height: 20px;
padding: 0;
font-size: 12px;
display: flex;
justify-content: center;
align-items: center;
background-color: transparent;
opacity: 0.5;
border: none;
cursor: pointer;
color: var(--text-muted);
@ -348,11 +516,12 @@ If your plugin does not need CSS, delete this file.
.chat-message-buttons button:hover {
color: var(--text-normal);
opacity: 1;
}
.chat-message-buttons button svg {
width: 16px;
height: 16px;
width: 14px;
height: 14px;
}
.user-message {