diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..60d24188 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,17 @@ +[target.x86_64-pc-windows-msvc] +rustflags = [ + "-C", + "target-feature=+crt-static", + "-C", + "link-args=/DEFAULTLIB:ucrt.lib /DEFAULTLIB:libvcruntime.lib libcmt.lib", + "-C", + "link-args=/NODEFAULTLIB:libvcruntimed.lib /NODEFAULTLIB:vcruntime.lib /NODEFAULTLIB:vcruntimed.lib", + "-C", + "link-args=/NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcrtd.lib", + "-C", + "link-args=/NODEFAULTLIB:libucrt.lib /NODEFAULTLIB:libucrtd.lib /NODEFAULTLIB:ucrtd.lib", + +] + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "link-arg=-Wl,--allow-multiple-definition"] diff --git a/.github/scripts/purge.sh b/.github/scripts/purge.sh index bd533328..134d67ba 100755 --- a/.github/scripts/purge.sh +++ b/.github/scripts/purge.sh @@ -7,7 +7,7 @@ if [ -z "$CN_API_KEY" ]; then fi # Extract the current version from Cargo.toml -current_version=$(sed -n 's/^version = "\(.*\)"/\1/p' examples/apps/screenpipe-app-tauri/src-tauri/Cargo.toml | head -n 1) +current_version=$(sed -n 's/^version = "\(.*\)"/\1/p' screenpipe-app-tauri/src-tauri/Cargo.toml | head -n 1) # Get the version to purge up to from the first argument purge_up_to=${1:-$current_version} diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 3ed08cb8..0bf15d9d 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -132,15 +132,16 @@ jobs: fail-on-alert: true alert-comment-cc-users: "@louis030195" - - name: Analyze STT benchmarks - uses: benchmark-action/github-action-benchmark@v1 - with: - name: STT Benchmarks - tool: "cargo" - output-file-path: ./cache/stt/stt_output.txt - github-token: ${{ secrets.GH_PAGES_TOKEN }} - auto-push: true - alert-threshold: "200%" - comment-on-alert: true - fail-on-alert: true - alert-comment-cc-users: "@louis030195" + # todo broken + # - name: Analyze STT benchmarks + # uses: benchmark-action/github-action-benchmark@v1 + # with: + # name: STT Benchmarks + # tool: "cargo" + # output-file-path: ./cache/stt/stt_output.txt + # github-token: ${{ secrets.GH_PAGES_TOKEN }} + # auto-push: true + # alert-threshold: "200%" + # comment-on-alert: true + # fail-on-alert: true + # alert-comment-cc-users: "@louis030195" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2a3635c..92913b22 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,8 @@ on: jobs: test-ubuntu: runs-on: ubuntu-latest + env: + RUSTFLAGS: "-C link-arg=-Wl,--allow-multiple-definition" steps: - uses: actions/checkout@v3 - uses: actions/cache@v3 @@ -27,6 +29,7 @@ jobs: with: profile: minimal toolchain: stable + override: true - name: Install dependencies run: | @@ -64,10 +67,7 @@ jobs: - name: Run pre_build.js on shell: bash run: bun ./scripts/pre_build.js - working-directory: ./examples/apps/screenpipe-app-tauri - - # - name: Run tests - # run: cargo test + working-directory: ./screenpipe-app-tauri - name: Copy test image shell: bash @@ -102,7 +102,7 @@ jobs: env: SKIP_SCREENPIPE_SETUP: true # avoid trying to copy screenpipe binaries, not yet built (next step) run: bun ./scripts/pre_build.js - working-directory: ./examples/apps/screenpipe-app-tauri + working-directory: ./screenpipe-app-tauri - name: Copy test image shell: bash diff --git a/.github/workflows/perf-long-running-end-to-end.yml b/.github/workflows/perf-long-running-end-to-end.yml index 81d2a15a..534e7deb 100644 --- a/.github/workflows/perf-long-running-end-to-end.yml +++ b/.github/workflows/perf-long-running-end-to-end.yml @@ -79,13 +79,13 @@ jobs: EOF - name: Upload memory usage data - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: memory-usage-data path: memory_usage.csv - name: Upload memory usage graph - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: memory-usage-graph path: memory_usage_graph.png @@ -101,7 +101,7 @@ jobs: sqlite3 ~/.screenpipe/db.sqlite "SELECT COUNT(*) FROM audio_transcriptions;" - name: Upload screenpipe data - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: screenpipe-data path: | diff --git a/.github/workflows/publish-app.yml b/.github/workflows/publish-app.yml index eac0b1f6..2e3bc938 100644 --- a/.github/workflows/publish-app.yml +++ b/.github/workflows/publish-app.yml @@ -35,4 +35,4 @@ jobs: with: command: release publish ${{ secrets.CN_APP_SLUG }} --framework tauri api-key: ${{ secrets.CN_API_KEY }} - path: ./examples/apps/screenpipe-app-tauri/src-tauri + path: ./screenpipe-app-tauri/src-tauri diff --git a/.github/workflows/release-app.yml b/.github/workflows/release-app.yml index 57a62f3b..dac9a04b 100644 --- a/.github/workflows/release-app.yml +++ b/.github/workflows/release-app.yml @@ -7,9 +7,9 @@ name: Release App on: - # push: - # tags: - # - "v*" + push: + tags: + - "v*" workflow_dispatch: jobs: @@ -40,9 +40,9 @@ jobs: args: "--target x86_64-apple-darwin --features metal" target: x86_64-apple-darwin - platform: "ubuntu-22.04" # Ubuntu x86_64 - args: "" # TODO CUDA + args: "" # TODO CUDA, mkl - platform: "windows-latest" # Windows x86_64 - args: "--target x86_64-pc-windows-msvc" # TODO CUDA? --features "openblas" + args: "--target x86_64-pc-windows-msvc" # TODO CUDA, mkl? --features "openblas" pre-build-args: "" # --openblas # windows arm: https://github.com/ahqsoftwares/tauri-ahq-store/blob/2fbc2103c222662b3c6ee0cd71fcde664824f0ef/.github/workflows/publish.yml#L136 @@ -86,10 +86,10 @@ jobs: uses: actions/cache@v4 with: path: | - examples/apps/screenpipe-app-tauri/src-tauri/openblas - examples/apps/screenpipe-app-tauri/src-tauri/clblast - examples/apps/screenpipe-app-tauri/src-tauri/ffmpeg - examples/apps/screenpipe-app-tauri/src-tauri/tesseract-* + screenpipe-app-tauri/src-tauri/openblas + screenpipe-app-tauri/src-tauri/clblast + screenpipe-app-tauri/src-tauri/ffmpeg + screenpipe-app-tauri/src-tauri/tesseract-* key: ${{ matrix.platform }}-${{ matrix.args }}-pre-build - uses: actions/cache@v3 @@ -117,7 +117,7 @@ jobs: - name: Install frontend dependencies shell: bash - working-directory: ./examples/apps/screenpipe-app-tauri + working-directory: ./screenpipe-app-tauri run: | ls . bun install @@ -130,13 +130,13 @@ jobs: run: | bun ./scripts/pre_build.js ${{ matrix.pre-build-args }} ls -R . - working-directory: ./examples/apps/screenpipe-app-tauri + working-directory: ./screenpipe-app-tauri - name: Verify Tesseract Installation if: matrix.platform == 'windows-latest' shell: pwsh run: | - $env:PATH += ";${{ github.workspace }}\examples\apps\screenpipe-app-tauri\src-tauri\tesseract" + $env:PATH += ";${{ github.workspace }}\screenpipe-app-tauri\src-tauri\tesseract" tesseract --version if ($LASTEXITCODE -ne 0) { Write-Error "Tesseract is not properly installed or not in PATH" @@ -161,7 +161,34 @@ jobs: - name: Run pre_build.js on ${{ matrix.platform }} shell: bash run: bun ./scripts/pre_build.js ${{ matrix.pre-build-args }} - working-directory: ./examples/apps/screenpipe-app-tauri + working-directory: ./screenpipe-app-tauri + + - name: Identify esaxx usage (Windows) + if: matrix.platform == 'windows-latest' + run: | + cargo tree > cargo_tree_output.txt + findstr /i "esaxx" cargo_tree_output.txt + continue-on-error: true + + - name: Install vcpkg + if: matrix.platform == 'windows-latest' + uses: lukka/run-vcpkg@v11 + with: + vcpkgGitCommitId: "5b1214315250939257ef5d62ecdcbca18cf4fb1c" + + # - name: Install ONNX Runtime + # if: matrix.platform == 'windows-latest' + # run: vcpkg install onnxruntime:x64-windows + + - name: Set up MSVC + if: matrix.platform == 'windows-latest' + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install LLVM and Clang + if: matrix.platform == 'windows-latest' + uses: KyleMayes/install-llvm-action@v2 + with: + version: "10.0" - name: Build uses: tauri-apps/tauri-action@v0 @@ -180,6 +207,7 @@ jobs: APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} # https://tauri.app/v1/guides/distribution/sign-macos CI: true + # RUSTFLAGS: "-C link-arg=-Wl,--allow-multiple-definition" with: tagName: app-v__VERSION__ # the action automatically replaces __VERSION__ with the app version. releaseName: "App v__VERSION__" @@ -187,7 +215,7 @@ jobs: releaseDraft: true prerelease: true args: ${{ matrix.args }} - projectPath: "./examples/apps/screenpipe-app-tauri" + projectPath: "./screenpipe-app-tauri" tauriScript: bunx tauri -v - name: Upload Assets to CrabNebula Cloud @@ -195,7 +223,7 @@ jobs: with: command: release upload ${{ secrets.CN_APP_SLUG }} --framework tauri api-key: ${{ secrets.CN_API_KEY }} - path: ./examples/apps/screenpipe-app-tauri/src-tauri + path: ./screenpipe-app-tauri/src-tauri # basically wait for macos manual add sset #publish: diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 3fe6d949..5bdfde98 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -123,7 +123,7 @@ jobs: gh pr create --base main --head update-formula-${{ matrix.target }}-${{ github.sha }} --title "Update Homebrew formula for ${{ matrix.target }}" --body "Automated PR to update Homebrew formula for ${{ matrix.target }}" - name: Upload Artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: screenpipe-macos-${{ matrix.target }} path: screenpipe-*.tar.gz @@ -172,7 +172,7 @@ jobs: # tar -czvf screenpipe-linux.tar.gz screenpipe-linux # - name: Upload Artifact - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: screenpipe-linux # path: screenpipe-linux.tar.gz @@ -243,7 +243,7 @@ jobs: echo "Set version to: $VERSION" - name: Download macOS Artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: artifacts diff --git a/.gitignore b/.gitignore index 9935641a..b29f710d 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,7 @@ examples/typescript/vercel-ai-chatbot/package-lock.json tauri_key_louis.key pnpm-lock.yaml -.DS_Store \ No newline at end of file +.DS_Store + +# Ignore onnxruntime-win-x64-gpu libraries +onnxruntime-win-x64-gpu*/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9df30c7b..b60c4ac6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,6 +53,22 @@ We follow [this](https://doc.rust-lang.org/cargo/guide/project-layout.html) fold ## Additional Notes +### AI system prompt + +i use cursor with this prompt to help me with the code: + +``` +Rules: +- Coding: always use lower case for logging stuff or UI +- Coding: Rust: always use anyhow error, tokio instead of std stuff, avoid mutex if you can, prefer channels, write code easy to read for humans, fast for machines +- Coding: when i ask to give me the full code it means FULL, no fucking // rest of the code comments GIVE ME THE FULL CODE +- Coding: if it seems like you lack some context about a niche lib just ask me to provide the source code and i will (instead of providing a bad answer) +- Coding: NextJS: make sure to use tailwind, typescript, shadcn, lucide, magicui, and framer-motion to make UIs amazing +- Coding: Make sure to escape html thing like quotes etc properly. Only when necessary +- Coding: When writing react or html code make sure to use thing like ' instead of ". Only when necessary (e.g inside quote themselves) +``` + + ### Principles - **User fanatic: focus on building what people want and making users happy.** @@ -97,6 +113,43 @@ You can add env var to `.vscode/settings.json`: } ``` +This is @louis030195 whole `.vscode/settings.json` file: + +```json +{ + "rust-analyzer.server.extraEnv": { + "PKG_CONFIG_ALLOW_SYSTEM_LIBS": "1", + "PKG_CONFIG_ALLOW_SYSTEM_CFLAGS": "1", + "PKG_CONFIG_PATH": "/opt/homebrew/lib/pkgconfig:/opt/homebrew/share/pkgconfig", + "PATH": "/usr/bin:/opt/homebrew/bin:${env:PATH}", + "DYLD_LIBRARY_PATH": "${workspaceFolder}/screenpipe-vision/lib:${env:DYLD_LIBRARY_PATH}" + }, + "rust-analyzer.cargo.extraEnv": { + "PKG_CONFIG_ALLOW_SYSTEM_LIBS": "1", + "PKG_CONFIG_ALLOW_SYSTEM_CFLAGS": "1", + "PKG_CONFIG_PATH": "/opt/homebrew/lib/pkgconfig:/opt/homebrew/share/pkgconfig", + "PATH": "/usr/bin:/opt/homebrew/bin:${env:PATH}", + "DYLD_LIBRARY_PATH": "${workspaceFolder}/screenpipe-vision/lib:${env:DYLD_LIBRARY_PATH}" + }, + // add env to integrated terminal + "terminal.integrated.env.osx": { + "DYLD_LIBRARY_PATH": "${workspaceFolder}/screenpipe-vision/lib:${env:DYLD_LIBRARY_PATH}", + "SCREENPIPE_APP_DEV": "true", + }, + "rust-analyzer.cargo.features": [ + "pipes" + ], + "rust-analyzer.cargo.runBuildScripts": true, + "rust-analyzer.checkOnSave.command": "clippy", + "rust-analyzer.checkOnSave.extraArgs": [ + "--features", + "pipes" + ], + "rust-analyzer.cargo.allFeatures": false, + "rust-analyzer.cargo.noDefaultFeatures": false +} +``` + ## Other hacks diff --git a/Cargo.toml b/Cargo.toml index 0356053b..36a65c2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,13 +7,13 @@ members = [ "screenpipe-integrations", ] exclude = [ - "examples/apps/screenpipe-app-tauri/src-tauri", + "screenpipe-app-tauri/src-tauri", ] resolver = "2" [workspace.package] -version = "0.1.78" +version = "0.1.84" authors = ["louis030195 "] description = "" repository = "https://github.com/mediar-ai/screenpipe" @@ -33,10 +33,13 @@ hf-hub = "0.3.0" crossbeam = "0.8.4" image = "0.25" reqwest = { version = "0.11", features = ["blocking", "multipart", "json"] } - -# dev criterion = { version = "0.5.1", features = ["async_tokio"] } +vcpkg = "0.2" +[workspace.metadata.vcpkg] +git = "https://github.com/microsoft/vcpkg" +rev = "2023.04.15" +dynamic = true diff --git a/Formula/screenpipe.rb b/Formula/screenpipe.rb index 97f2c278..b108416a 100644 --- a/Formula/screenpipe.rb +++ b/Formula/screenpipe.rb @@ -1,16 +1,16 @@ class Screenpipe < Formula desc "Library to build personalized AI powered by what you've seen, said, or heard." homepage "https://github.com/mediar-ai/screenpipe" - url "https://github.com/mediar-ai/screenpipe/releases/download/v0.1.78/screenpipe-0.1.78-aarch64-apple-darwin.tar.gz" - version "0.1.78" + url "https://github.com/mediar-ai/screenpipe/releases/download/v0.1.85/screenpipe-0.1.85-aarch64-apple-darwin.tar.gz" + version "0.1.85" on_macos do if Hardware::CPU.arm? url "https://github.com/mediar-ai/screenpipe/releases/download/v#{version}/screenpipe-#{version}-aarch64-apple-darwin.tar.gz" - sha256 "0adf737c627524d3a5f7c1f726103ef143e7ba0c65fe610ac8f9ba8442ed7937" # arm64 + sha256 "d41406d867674b21103ec089bf34d77e0476de6ac22e22a6da72adb42dc5fec8" # arm64 else url "https://github.com/mediar-ai/screenpipe/releases/download/v#{version}/screenpipe-#{version}-x86_64-apple-darwin.tar.gz" - sha256 "68db5c35ebf77a62bdb75cad79029141be948f56cdbe36abb79e92351b36d622" # x86_64 + sha256 "ef2ca50886b92c2ff995a9f3d0f7e6391d832940bd68f130c85fedd2680712a1" # x86_64 end end diff --git a/README.md b/README.md index 85a215b8..bc39fc6d 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,9 @@ There are multiple ways to install screenpipe: - as a Rust or WASM library (documentation WIP) - as a business - check [use cases](https://github.com/mediar-ai/screenpipe?tab=readme-ov-file#use-cases) and [DM louis](https://www.linkedin.com/in/louis030195/) -PS: we invest 80% of the paid app revenue in [bounties](https://github.com/mediar-ai/screenpipe/issues?q=is:open+is:issue+label:%22%F0%9F%92%8E+Bounty%22), send PR, make money! +we invest 80% of the paid app revenue in [bounties](https://github.com/mediar-ai/screenpipe/issues?q=is:open+is:issue+label:%22%F0%9F%92%8E+Bounty%22), send PR, make money! + +think of screenpipe like a DAO, but without crypto This is the instructions to install the command line interface. @@ -109,11 +111,8 @@ brew install screenpipe ```bash screenpipe ``` -we just released experimental apple native OCR, to use it: -```bash -screenpipe --ocr-engine apple-native -``` -or if you don't want audio to be recorded + +if you don't want audio to be recorded ```bash screenpipe --disable-audio ``` @@ -125,14 +124,15 @@ if you want to run screenpipe in debug mode to show more logs in terminal: ```bash screenpipe --debug ``` -by default screenpipe is using whisper-tiny that runs LOCALLY to get better quality or lower compute you can use cloud model (we use Deepgram) via cloud api: +by default screenpipe is using Silero-VAD to identify speech and non-speech tokens to improve audio transcription, bu you can use WebRTC if needed by passing the following command: ```bash -screenpipe -audio-transcription-engine deepgram +screenpipe --vad-engine webrtc ``` -by default screenpipe is using a local model for screen capture OCR processing to use the cloud (through unstructured.io) for better performance use this flag: +by default screenpipe is using whisper-large that runs LOCALLY to get better quality or lower compute you can use cloud model (we use Deepgram) via cloud api: ```bash -screenpipe --ocr-engine unstructured +screenpipe --audio-transcription-engine deepgram ``` + friend wearable integration, in order to link your wearable you need to pass user ID from friend app: ```bash screenpipe --friend-wearable-uid AC...........................F3 @@ -193,6 +193,8 @@ Then run it > This is experimental support for Windows build. This assumes you already have the CUDA Toolkit installed and the CUDA_PATH set to my CUDA v12.6 folder. > Replace `V:\projects` and `V:\packages` with your own folders. +If this does not work for you, please [open an issue](https://github.com/mediar-ai/screenpipe/issues/new?assignees=&labels=dislike&template=dislike.yml&title=windows+install+screenpipe+didnt+work) or get the pre-built [desktop app](https://screenpi.pe) + - Install chocolatey - Install git - Install CUDA Toolkit (if using NVIDIA and building with cuda) @@ -212,7 +214,7 @@ Then run it ```batch choco install pkgconfiglite rust cd V:\projects -git clone https://github.com/louis030195/screen-pipe +git clone https://github.com/mediar-ai/screenpipe cd V:\packages git clone https://github.com/microsoft/vcpkg.git cd vcpkg @@ -345,9 +347,8 @@ npm run dev You can use terminal commands to query and view your data as shown below. Also, we recommend Tableplus.com to view the database, it has a free tier. -Here's a pseudo code to illustrate how to use screenpipe, after a meeting for example (automatically with our webhooks): +Here's a pseudo code to illustrate how to use screenpipe, to summarize meetings: ```js - // 1h ago const startDate = "" // 10m ago @@ -363,10 +364,9 @@ const summary = fetchOllama("{results} create a summary from these transcription // add the meeting summary to your notes addToNotion(summary) // or your favourite note taking app - ``` -Or thousands of other usages of all your screen & mic data! +Or thousands of other usages of all your screen & mic data! [Check examples](https://github.com/mediar-ai/screenpipe/tree/main/examples/typescript), screenpipes makes it easy to write plugins in JS for example that runs directly in the Rust code through Deno engine.
@@ -438,6 +438,9 @@ curl "http://localhost:3030/search?q=QUERY_HERE&limit=10&offset=20" # 6. Search with no query (should return all results) curl "http://localhost:3030/search?limit=5&offset=0" +# Display first frame from 30m to 25m ago (macos, translate to your OS with AI) +curl "http://localhost:3030/search?limit=1&offset=0&content_type=ocr&include_frames=true&start_time=$(date -u -v-220M +%Y-%m-%dT%H:%M:%SZ)&end_time=$(date -u -v-120M +%Y-%m-%dT%H:%M:%SZ)" | jq -r '.data[0].content.frame' | base64 --decode > /tmp/frame.png && open /tmp/frame.png + # filter by app (wll only return OCR results) curl "http://localhost:3030/search?app_name=cursor" ``` @@ -446,7 +449,8 @@ curl "http://localhost:3030/search?app_name=cursor" Keep in mind that it's still experimental.

-https://github.com/user-attachments/assets/edb503d4-6531-4527-9b05-0397fd8b5976 +![0910244](https://github.com/user-attachments/assets/6025ef71-43b9-4151-a34c-155c30236a57) + ## Use cases: @@ -482,6 +486,8 @@ https://github.com/user-attachments/assets/edb503d4-6531-4527-9b05-0397fd8b5976 Alpha: runs on my computer `Macbook pro m3 32 GB ram` and a $400 Windows laptop, 24/7. +Uses 600 MB, 10% CPU. + - [ ] Integrations - [x] ollama - [x] openai diff --git a/examples/apps/screenpipe-app-tauri/bun.lockb b/examples/apps/screenpipe-app-tauri/bun.lockb deleted file mode 100755 index c8da4572..00000000 Binary files a/examples/apps/screenpipe-app-tauri/bun.lockb and /dev/null differ diff --git a/examples/apps/screenpipe-app-tauri/components/pipe-store.tsx b/examples/apps/screenpipe-app-tauri/components/pipe-store.tsx deleted file mode 100644 index 0834de7c..00000000 --- a/examples/apps/screenpipe-app-tauri/components/pipe-store.tsx +++ /dev/null @@ -1,392 +0,0 @@ -import React, { useState } from "react"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog"; -import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { Separator } from "@/components/ui/separator"; -import { Card } from "@/components/ui/card"; -import { MemoizedReactMarkdown } from "@/components/markdown"; -import { usePipes, Pipe } from "@/lib/hooks/use-pipes"; -import { CodeBlock } from "@/components/ui/codeblock"; -import remarkGfm from "remark-gfm"; -import remarkMath from "remark-math"; -import { Skeleton } from "./ui/skeleton"; -import { PrettyLink } from "@/components/pretty-link"; -import { MeetingSummarizer } from "./meeting-summarized"; -import { useSettings } from "@/lib/hooks/use-settings"; -import { open } from "@tauri-apps/plugin-shell"; -import { invoke } from "@tauri-apps/api/core"; -import { toast } from "./ui/use-toast"; -import { Input } from "./ui/input"; -import { Plus } from "lucide-react"; -import { FeatureRequestLink } from "./feature-request-link"; -const formatDate = (dateString: string) => { - const date = new Date(dateString); - return date.toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - }); -}; - -const PipeDialog: React.FC = () => { - const [newRepoUrl, setNewRepoUrl] = useState(""); - const { pipes, loading, error, addCustomPipe } = usePipes([ - // "https://github.com/different-ai/file-organizer-2000", - "https://github.com/mediar-ai/screenpipe/tree/main/examples/typescript/pipe-tagging-activity", - ]); - const [selectedPipe, setSelectedPipe] = useState(null); - const { settings, updateSettings } = useSettings(); - - const handleAddOwnPipe = async () => { - if (newRepoUrl) { - try { - toast({ - title: "Adding custom pipe", - description: "Please wait...", - }); - await addCustomPipe(newRepoUrl); - setNewRepoUrl(""); - toast({ - title: "Custom pipe added", - description: - "Your pipe has been successfully added. Screenpipe will restart with the new pipe.", - }); - } catch (error) { - console.error("Failed to add custom pipe:", error); - toast({ - title: "Error adding custom pipe", - description: "Please check the URL and try again.", - variant: "destructive", - }); - } - } - }; - - const formatUpdatedTime = (date: string) => { - const now = new Date(); - const updated = new Date(date); - const diffTime = Math.abs(now.getTime() - updated.getTime()); - const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); - return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`; - }; - - const handleInstall = async (pipe: Pipe) => { - // if its file organizer, just open the github url in new tab - if (pipe.repository.includes("file-organizer")) { - console.log("opening file organizer", pipe.repository); - open(pipe.repository); - return; - } - - try { - toast({ - title: "Installing pipe", - description: "This may take a few moments...", - }); - - // Update installed pipes in settings - const updatedInstalledPipes = [...settings.installedPipes, pipe]; - console.log("updated installed pipes", updatedInstalledPipes); - await updateSettings({ installedPipes: updatedInstalledPipes }); - - // Kill existing screenpipe processes - await invoke("kill_all_sreenpipes"); - - // Spawn new screenpipe process with the pipe - await invoke("spawn_screenpipe"); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - - toast({ - title: "Pipe installed successfully", - description: "Screenpipe has been restarted with the new pipe.", - }); - - setSelectedPipe({ ...pipe }); - } catch (error) { - console.error("Failed to install pipe:", error); - toast({ - title: "Error installing pipe", - description: "Please try again or check the logs for more information.", - variant: "destructive", - }); - } - }; - - const handleUninstall = async (pipe: Pipe) => { - try { - toast({ - title: "Uninstalling pipe", - description: "This may take a few moments...", - }); - - // Update installed pipes in settings - const updatedInstalledPipes = settings.installedPipes.filter( - (p) => p.name !== pipe.name - ); - console.log("updated installed pipes", updatedInstalledPipes); - await updateSettings({ installedPipes: updatedInstalledPipes }); - - // restart screenpipe with no pipe - await invoke("kill_all_sreenpipes"); - await invoke("spawn_screenpipe"); - await new Promise((resolve) => setTimeout(resolve, 1000)); - - toast({ - title: "Pipe uninstalled successfully", - description: "Screenpipe has been restarted without the pipe.", - }); - - setSelectedPipe({ ...pipe }); - } catch (error) { - console.error("Failed to uninstall pipe:", error); - toast({ - title: "Error uninstalling pipe", - description: "Please try again or check the logs for more information.", - variant: "destructive", - }); - } - }; - - const renderPipeContent = () => { - if (!selectedPipe) { - return ( -
-

no pipe selected

- -
- ); - } - - const isInstalled = - settings.installedPipes.find((p) => p.name === selectedPipe.name) !== - undefined; - - return ( - <> -

{selectedPipe.name}

-
-
-

downloads: {selectedPipe.downloads}

-

version: {selectedPipe.version}

-

- by:{" "} - - {selectedPipe.author} - -

-

- repository:{" "} - - link - -

-

- last update:{" "} - - {formatDate(selectedPipe.lastUpdate)} - -

-
-
-

{selectedPipe.description}

-
- {isInstalled ? ( - - ) : ( - - )} - - -
- - -
-

About this pipe

- {children}

; - }, - code({ node, className, children, ...props }) { - const content = String(children).replace(/\n$/, ""); - const match = /language-(\w+)/.exec(className || ""); - - if (!match) { - return ( - - {content} - - ); - } - - return ( - - ); - }, - img({ src, alt }) { - return ( - /* eslint-disable @next/next/no-img-element */ - {alt} { - const target = e.target as HTMLImageElement; - target.onerror = null; - target.src = "path/to/fallback/image.png"; // Replace with your fallback image - }} - /> - ); - }, - }} - > - {selectedPipe.fullDescription.replace(/Â/g, "")} -
-
- - ); - }; - - return ( - - - - - - - Pipe Store - - Screenpipe's store is a collection of app, scripts, prompts - that are available to install. -
- It will process, annotate, help you search, or automate in your - screenpipe's data. -
- - Check out more examples on GitHub - -
- - {selectedPipe && } -
-
-
- {pipes.length === 0 && - Array(5) - .fill(0) - .map((_, index) => ( -
- -
- ))} - {pipes.map((pipe: Pipe) => ( - setSelectedPipe(pipe)} - > -
-
-

{pipe.name}

-

by {pipe.author}

-
-
- - - - {pipe.downloads} -
-
-

{pipe.description}

-

- updated {formatUpdatedTime(pipe.lastUpdate)} -

-
- ))} - - setNewRepoUrl(e.target.value)} - /> - - -
-
- {renderPipeContent()} -
-
-
-
- ); -}; - -export default PipeDialog; diff --git a/examples/apps/screenpipe-app-tauri/components/settings.tsx b/examples/apps/screenpipe-app-tauri/components/settings.tsx deleted file mode 100644 index 25fc049e..00000000 --- a/examples/apps/screenpipe-app-tauri/components/settings.tsx +++ /dev/null @@ -1,368 +0,0 @@ -"use client"; -import React from "react"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog"; -import { Button } from "@/components/ui/button"; -import { Switch } from "@/components/ui/switch"; -import { useSettings } from "@/lib/hooks/use-settings"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; -import { Badge } from "@/components/ui/badge"; -import { MemoizedReactMarkdown } from "./markdown"; -import { Separator } from "@/components/ui/separator"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Textarea } from "./ui/textarea"; - -import { platform } from "@tauri-apps/plugin-os"; -import { Eye, EyeOff, RefreshCw } from "lucide-react"; -import { RecordingSettings } from "./recording-settings"; - -export function Settings({ className }: { className?: string }) { - const { settings, updateSettings, resetSetting } = useSettings(); - const [localSettings, setLocalSettings] = React.useState(settings); - const [currentPlatform, setCurrentPlatform] = React.useState(""); - const [showApiKey, setShowApiKey] = React.useState(false); - - const handleApiKeyChange = (e: React.ChangeEvent) => { - const newValue = e.target.value; - setLocalSettings((prev) => ({ ...prev, openaiApiKey: newValue })); - updateSettings({ openaiApiKey: newValue }); - }; - - const handleOllamaToggle = (checked: boolean) => { - setLocalSettings((prev) => ({ ...prev, useOllama: checked })); - updateSettings({ useOllama: checked }); - }; - - const handleOllamaUrlChange = (e: React.ChangeEvent) => { - const newValue = e.target.value; - setLocalSettings((prev) => ({ ...prev, ollamaUrl: newValue })); - updateSettings({ ollamaUrl: newValue }); - }; - - const handleModelChange = (e: React.ChangeEvent) => { - const newValue = e.target.value; - setLocalSettings((prev) => ({ ...prev, aiModel: newValue })); - updateSettings({ aiModel: newValue }); - }; - - const handleCustomPromptChange = ( - e: React.ChangeEvent - ) => { - const newValue = e.target.value; - setLocalSettings((prev) => ({ ...prev, customPrompt: newValue })); - updateSettings({ customPrompt: newValue }); - }; - - const handleResetCustomPrompt = () => { - resetSetting("customPrompt"); - }; - - React.useEffect(() => { - setLocalSettings(settings); - setCurrentPlatform(platform()); - }, [settings]); - - return ( - { - if (!open) { - location.reload(); // ! HACK to properly refresh stuff (tood beter) - } - }} - > - - - - - - settings - - choose your AI provider, enter necessary credentials, and more. - - {localSettings.useOllama ? ( -

- you are now using ollama 🦙 -

- ) : ( -

- you are now using openai 🤖 -

- )} -
-
- - - - - - - general ai settings - - -
-
- - -
-

- {localSettings.useOllama - ? "recommended: mistral-nemo for ollama (we only support models supporting tools like llama3.1, mistral-nemo, etc.)" - : "recommended: gpt-4o for openai"} -

-
- -
-
-
- - - - - - - -

Reset to default prompt

-
-
-
-
-