nastech-app 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/i18n-translator.md +119 -0
- package/.claude/settings.json +8 -0
- package/.eas/workflows/ota.yaml +9 -0
- package/.eas/workflows/preview.yaml +12 -0
- package/.easignore +12 -0
- package/.github/workflows/eas-build.yml +24 -0
- package/CHANGELOG.md +117 -0
- package/CLAUDE.md +413 -0
- package/GoogleService-Info.plist +30 -0
- package/LICENSE +21 -0
- package/NasTechapp.md +383 -0
- package/README.md +75 -0
- package/Stores.md +85 -0
- package/TERMS.md +83 -0
- package/app.config.js +153 -0
- package/babel.config.js +28 -0
- package/deploy/nastech-app.yaml +51 -0
- package/docs/marketing/README-creators.md +73 -0
- package/eas-build-post-install.sh +11 -0
- package/eas-build-pre-install.sh +27 -0
- package/eas.json +78 -0
- package/google-services.json +67 -0
- package/index.ts +3 -0
- package/logo.png +0 -0
- package/metro.config.js +54 -0
- package/nativewind-env.d.ts +1 -0
- package/package.json +233 -0
- package/patches/.keep +0 -0
- package/plugins/withEinkCompatibility.js +156 -0
- package/public/.well-known/apple-app-site-association +22 -0
- package/public/.well-known/assetlinks.json +12 -0
- package/public/canvaskit.wasm +0 -0
- package/public/favicon-active.ico +0 -0
- package/release-dev.sh +7 -0
- package/release-production.sh +3 -0
- package/release.cjs +160 -0
- package/sources/-session/SessionView.tsx +944 -0
- package/sources/-session/sessionOverlayNav.ts +34 -0
- package/sources/app/(app)/_layout.tsx +321 -0
- package/sources/app/(app)/artifacts/[id].tsx +279 -0
- package/sources/app/(app)/artifacts/edit/[id].tsx +318 -0
- package/sources/app/(app)/artifacts/index.tsx +264 -0
- package/sources/app/(app)/artifacts/new.tsx +219 -0
- package/sources/app/(app)/changelog.tsx +113 -0
- package/sources/app/(app)/dev/colors.tsx +197 -0
- package/sources/app/(app)/dev/device-info.tsx +183 -0
- package/sources/app/(app)/dev/expo-constants.tsx +394 -0
- package/sources/app/(app)/dev/index.tsx +400 -0
- package/sources/app/(app)/dev/input-styles.tsx +1951 -0
- package/sources/app/(app)/dev/inverted-list.tsx +295 -0
- package/sources/app/(app)/dev/list-demo.tsx +125 -0
- package/sources/app/(app)/dev/logs.tsx +160 -0
- package/sources/app/(app)/dev/messages-demo-data.ts +479 -0
- package/sources/app/(app)/dev/messages-demo.tsx +45 -0
- package/sources/app/(app)/dev/modal-demo.tsx +211 -0
- package/sources/app/(app)/dev/multi-text-input.tsx +224 -0
- package/sources/app/(app)/dev/purchases.tsx +228 -0
- package/sources/app/(app)/dev/qr-test.tsx +168 -0
- package/sources/app/(app)/dev/session-composer.tsx +812 -0
- package/sources/app/(app)/dev/shimmer-demo.tsx +275 -0
- package/sources/app/(app)/dev/tests.tsx +203 -0
- package/sources/app/(app)/dev/tools2.tsx +556 -0
- package/sources/app/(app)/dev/typography.tsx +177 -0
- package/sources/app/(app)/dev/unistyles-demo.tsx +376 -0
- package/sources/app/(app)/friends/index.tsx +167 -0
- package/sources/app/(app)/friends/search.tsx +232 -0
- package/sources/app/(app)/inbox/index.tsx +124 -0
- package/sources/app/(app)/index.tsx +264 -0
- package/sources/app/(app)/machine/[id].tsx +646 -0
- package/sources/app/(app)/new/index.tsx +1611 -0
- package/sources/app/(app)/restore/index.tsx +167 -0
- package/sources/app/(app)/restore/manual.tsx +138 -0
- package/sources/app/(app)/server.tsx +234 -0
- package/sources/app/(app)/session/[id]/file.tsx +527 -0
- package/sources/app/(app)/session/[id]/files.tsx +442 -0
- package/sources/app/(app)/session/[id]/info.tsx +655 -0
- package/sources/app/(app)/session/[id]/message/[messageId].tsx +125 -0
- package/sources/app/(app)/session/[id].tsx +10 -0
- package/sources/app/(app)/session/recent.tsx +270 -0
- package/sources/app/(app)/settings/account.tsx +600 -0
- package/sources/app/(app)/settings/agents.tsx +180 -0
- package/sources/app/(app)/settings/appearance.tsx +259 -0
- package/sources/app/(app)/settings/connect/claude.tsx +178 -0
- package/sources/app/(app)/settings/features.tsx +177 -0
- package/sources/app/(app)/settings/index.tsx +3 -0
- package/sources/app/(app)/settings/language.tsx +106 -0
- package/sources/app/(app)/settings/usage.tsx +11 -0
- package/sources/app/(app)/settings/voice/language.tsx +114 -0
- package/sources/app/(app)/settings/voice.tsx +274 -0
- package/sources/app/(app)/terminal/connect.tsx +241 -0
- package/sources/app/(app)/terminal/index.tsx +184 -0
- package/sources/app/(app)/text-selection.tsx +149 -0
- package/sources/app/(app)/user/[id].tsx +314 -0
- package/sources/app/+html.tsx +39 -0
- package/sources/app/_layout.tsx +402 -0
- package/sources/assets/animations/game.json +1 -0
- package/sources/assets/animations/owl.json +1 -0
- package/sources/assets/animations/popcorn.json +1 -0
- package/sources/assets/animations/robot.json +1 -0
- package/sources/assets/animations/sparkles.json +1 -0
- package/sources/assets/animations/stone.json +1 -0
- package/sources/assets/fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/sources/assets/fonts/IBMPlexMono-Italic.ttf +0 -0
- package/sources/assets/fonts/IBMPlexMono-Regular.ttf +0 -0
- package/sources/assets/fonts/IBMPlexMono-SemiBold.ttf +0 -0
- package/sources/assets/fonts/IBMPlexSans-Italic.ttf +0 -0
- package/sources/assets/fonts/IBMPlexSans-Regular.ttf +0 -0
- package/sources/assets/fonts/IBMPlexSans-SemiBold.ttf +0 -0
- package/sources/assets/fonts/SpaceMono-Regular.ttf +0 -0
- package/sources/assets/images/brutalist/Abstract-1.png +0 -0
- package/sources/assets/images/brutalist/Abstract-10.png +0 -0
- package/sources/assets/images/brutalist/Abstract-100.png +0 -0
- package/sources/assets/images/brutalist/Abstract-101.png +0 -0
- package/sources/assets/images/brutalist/Abstract-102.png +0 -0
- package/sources/assets/images/brutalist/Abstract-103.png +0 -0
- package/sources/assets/images/brutalist/Abstract-104.png +0 -0
- package/sources/assets/images/brutalist/Abstract-105.png +0 -0
- package/sources/assets/images/brutalist/Abstract-106.png +0 -0
- package/sources/assets/images/brutalist/Abstract-107.png +0 -0
- package/sources/assets/images/brutalist/Abstract-108.png +0 -0
- package/sources/assets/images/brutalist/Abstract-109.png +0 -0
- package/sources/assets/images/brutalist/Abstract-11.png +0 -0
- package/sources/assets/images/brutalist/Abstract-110.png +0 -0
- package/sources/assets/images/brutalist/Abstract-111.png +0 -0
- package/sources/assets/images/brutalist/Abstract-112.png +0 -0
- package/sources/assets/images/brutalist/Abstract-113.png +0 -0
- package/sources/assets/images/brutalist/Abstract-114.png +0 -0
- package/sources/assets/images/brutalist/Abstract-115.png +0 -0
- package/sources/assets/images/brutalist/Abstract-116.png +0 -0
- package/sources/assets/images/brutalist/Abstract-117.png +0 -0
- package/sources/assets/images/brutalist/Abstract-118.png +0 -0
- package/sources/assets/images/brutalist/Abstract-119.png +0 -0
- package/sources/assets/images/brutalist/Abstract-12.png +0 -0
- package/sources/assets/images/brutalist/Abstract-120.png +0 -0
- package/sources/assets/images/brutalist/Abstract-121.png +0 -0
- package/sources/assets/images/brutalist/Abstract-122.png +0 -0
- package/sources/assets/images/brutalist/Abstract-123.png +0 -0
- package/sources/assets/images/brutalist/Abstract-124.png +0 -0
- package/sources/assets/images/brutalist/Abstract-125.png +0 -0
- package/sources/assets/images/brutalist/Abstract-126.png +0 -0
- package/sources/assets/images/brutalist/Abstract-127.png +0 -0
- package/sources/assets/images/brutalist/Abstract-128.png +0 -0
- package/sources/assets/images/brutalist/Abstract-129.png +0 -0
- package/sources/assets/images/brutalist/Abstract-13.png +0 -0
- package/sources/assets/images/brutalist/Abstract-130.png +0 -0
- package/sources/assets/images/brutalist/Abstract-131.png +0 -0
- package/sources/assets/images/brutalist/Abstract-132.png +0 -0
- package/sources/assets/images/brutalist/Abstract-133.png +0 -0
- package/sources/assets/images/brutalist/Abstract-134.png +0 -0
- package/sources/assets/images/brutalist/Abstract-135.png +0 -0
- package/sources/assets/images/brutalist/Abstract-136.png +0 -0
- package/sources/assets/images/brutalist/Abstract-137.png +0 -0
- package/sources/assets/images/brutalist/Abstract-138.png +0 -0
- package/sources/assets/images/brutalist/Abstract-139.png +0 -0
- package/sources/assets/images/brutalist/Abstract-14.png +0 -0
- package/sources/assets/images/brutalist/Abstract-140.png +0 -0
- package/sources/assets/images/brutalist/Abstract-141.png +0 -0
- package/sources/assets/images/brutalist/Abstract-142.png +0 -0
- package/sources/assets/images/brutalist/Abstract-143.png +0 -0
- package/sources/assets/images/brutalist/Abstract-144.png +0 -0
- package/sources/assets/images/brutalist/Abstract-145.png +0 -0
- package/sources/assets/images/brutalist/Abstract-146.png +0 -0
- package/sources/assets/images/brutalist/Abstract-147.png +0 -0
- package/sources/assets/images/brutalist/Abstract-148.png +0 -0
- package/sources/assets/images/brutalist/Abstract-149.png +0 -0
- package/sources/assets/images/brutalist/Abstract-15.png +0 -0
- package/sources/assets/images/brutalist/Abstract-150.png +0 -0
- package/sources/assets/images/brutalist/Abstract-151.png +0 -0
- package/sources/assets/images/brutalist/Abstract-152.png +0 -0
- package/sources/assets/images/brutalist/Abstract-153.png +0 -0
- package/sources/assets/images/brutalist/Abstract-154.png +0 -0
- package/sources/assets/images/brutalist/Abstract-155.png +0 -0
- package/sources/assets/images/brutalist/Abstract-156.png +0 -0
- package/sources/assets/images/brutalist/Abstract-157.png +0 -0
- package/sources/assets/images/brutalist/Abstract-158.png +0 -0
- package/sources/assets/images/brutalist/Abstract-159.png +0 -0
- package/sources/assets/images/brutalist/Abstract-16.png +0 -0
- package/sources/assets/images/brutalist/Abstract-160.png +0 -0
- package/sources/assets/images/brutalist/Abstract-161.png +0 -0
- package/sources/assets/images/brutalist/Abstract-162.png +0 -0
- package/sources/assets/images/brutalist/Abstract-163.png +0 -0
- package/sources/assets/images/brutalist/Abstract-164.png +0 -0
- package/sources/assets/images/brutalist/Abstract-165.png +0 -0
- package/sources/assets/images/brutalist/Abstract-166.png +0 -0
- package/sources/assets/images/brutalist/Abstract-167.png +0 -0
- package/sources/assets/images/brutalist/Abstract-168.png +0 -0
- package/sources/assets/images/brutalist/Abstract-169.png +0 -0
- package/sources/assets/images/brutalist/Abstract-17.png +0 -0
- package/sources/assets/images/brutalist/Abstract-170.png +0 -0
- package/sources/assets/images/brutalist/Abstract-171.png +0 -0
- package/sources/assets/images/brutalist/Abstract-172.png +0 -0
- package/sources/assets/images/brutalist/Abstract-173.png +0 -0
- package/sources/assets/images/brutalist/Abstract-174.png +0 -0
- package/sources/assets/images/brutalist/Abstract-175.png +0 -0
- package/sources/assets/images/brutalist/Abstract-176.png +0 -0
- package/sources/assets/images/brutalist/Abstract-177.png +0 -0
- package/sources/assets/images/brutalist/Abstract-178.png +0 -0
- package/sources/assets/images/brutalist/Abstract-179.png +0 -0
- package/sources/assets/images/brutalist/Abstract-18.png +0 -0
- package/sources/assets/images/brutalist/Abstract-180.png +0 -0
- package/sources/assets/images/brutalist/Abstract-181.png +0 -0
- package/sources/assets/images/brutalist/Abstract-182.png +0 -0
- package/sources/assets/images/brutalist/Abstract-183.png +0 -0
- package/sources/assets/images/brutalist/Abstract-184.png +0 -0
- package/sources/assets/images/brutalist/Abstract-185.png +0 -0
- package/sources/assets/images/brutalist/Abstract-186.png +0 -0
- package/sources/assets/images/brutalist/Abstract-187.png +0 -0
- package/sources/assets/images/brutalist/Abstract-188.png +0 -0
- package/sources/assets/images/brutalist/Abstract-189.png +0 -0
- package/sources/assets/images/brutalist/Abstract-19.png +0 -0
- package/sources/assets/images/brutalist/Abstract-190.png +0 -0
- package/sources/assets/images/brutalist/Abstract-191.png +0 -0
- package/sources/assets/images/brutalist/Abstract-192.png +0 -0
- package/sources/assets/images/brutalist/Abstract-193.png +0 -0
- package/sources/assets/images/brutalist/Abstract-194.png +0 -0
- package/sources/assets/images/brutalist/Abstract-195.png +0 -0
- package/sources/assets/images/brutalist/Abstract-196.png +0 -0
- package/sources/assets/images/brutalist/Abstract-197.png +0 -0
- package/sources/assets/images/brutalist/Abstract-198.png +0 -0
- package/sources/assets/images/brutalist/Abstract-199.png +0 -0
- package/sources/assets/images/brutalist/Abstract-2.png +0 -0
- package/sources/assets/images/brutalist/Abstract-20.png +0 -0
- package/sources/assets/images/brutalist/Abstract-200.png +0 -0
- package/sources/assets/images/brutalist/Abstract-201.png +0 -0
- package/sources/assets/images/brutalist/Abstract-202.png +0 -0
- package/sources/assets/images/brutalist/Abstract-203.png +0 -0
- package/sources/assets/images/brutalist/Abstract-204.png +0 -0
- package/sources/assets/images/brutalist/Abstract-205.png +0 -0
- package/sources/assets/images/brutalist/Abstract-206.png +0 -0
- package/sources/assets/images/brutalist/Abstract-207.png +0 -0
- package/sources/assets/images/brutalist/Abstract-208.png +0 -0
- package/sources/assets/images/brutalist/Abstract-209.png +0 -0
- package/sources/assets/images/brutalist/Abstract-21.png +0 -0
- package/sources/assets/images/brutalist/Abstract-210.png +0 -0
- package/sources/assets/images/brutalist/Abstract-211.png +0 -0
- package/sources/assets/images/brutalist/Abstract-212.png +0 -0
- package/sources/assets/images/brutalist/Abstract-213.png +0 -0
- package/sources/assets/images/brutalist/Abstract-214.png +0 -0
- package/sources/assets/images/brutalist/Abstract-215.png +0 -0
- package/sources/assets/images/brutalist/Abstract-216.png +0 -0
- package/sources/assets/images/brutalist/Abstract-217.png +0 -0
- package/sources/assets/images/brutalist/Abstract-218.png +0 -0
- package/sources/assets/images/brutalist/Abstract-219.png +0 -0
- package/sources/assets/images/brutalist/Abstract-22.png +0 -0
- package/sources/assets/images/brutalist/Abstract-220.png +0 -0
- package/sources/assets/images/brutalist/Abstract-221.png +0 -0
- package/sources/assets/images/brutalist/Abstract-222.png +0 -0
- package/sources/assets/images/brutalist/Abstract-223.png +0 -0
- package/sources/assets/images/brutalist/Abstract-224.png +0 -0
- package/sources/assets/images/brutalist/Abstract-225.png +0 -0
- package/sources/assets/images/brutalist/Abstract-226.png +0 -0
- package/sources/assets/images/brutalist/Abstract-227.png +0 -0
- package/sources/assets/images/brutalist/Abstract-228.png +0 -0
- package/sources/assets/images/brutalist/Abstract-229.png +0 -0
- package/sources/assets/images/brutalist/Abstract-23.png +0 -0
- package/sources/assets/images/brutalist/Abstract-230.png +0 -0
- package/sources/assets/images/brutalist/Abstract-231.png +0 -0
- package/sources/assets/images/brutalist/Abstract-232.png +0 -0
- package/sources/assets/images/brutalist/Abstract-233.png +0 -0
- package/sources/assets/images/brutalist/Abstract-234.png +0 -0
- package/sources/assets/images/brutalist/Abstract-235.png +0 -0
- package/sources/assets/images/brutalist/Abstract-236.png +0 -0
- package/sources/assets/images/brutalist/Abstract-237.png +0 -0
- package/sources/assets/images/brutalist/Abstract-238.png +0 -0
- package/sources/assets/images/brutalist/Abstract-239.png +0 -0
- package/sources/assets/images/brutalist/Abstract-24.png +0 -0
- package/sources/assets/images/brutalist/Abstract-240.png +0 -0
- package/sources/assets/images/brutalist/Abstract-241.png +0 -0
- package/sources/assets/images/brutalist/Abstract-242.png +0 -0
- package/sources/assets/images/brutalist/Abstract-243.png +0 -0
- package/sources/assets/images/brutalist/Abstract-244.png +0 -0
- package/sources/assets/images/brutalist/Abstract-245.png +0 -0
- package/sources/assets/images/brutalist/Abstract-246.png +0 -0
- package/sources/assets/images/brutalist/Abstract-247.png +0 -0
- package/sources/assets/images/brutalist/Abstract-248.png +0 -0
- package/sources/assets/images/brutalist/Abstract-249.png +0 -0
- package/sources/assets/images/brutalist/Abstract-25.png +0 -0
- package/sources/assets/images/brutalist/Abstract-250.png +0 -0
- package/sources/assets/images/brutalist/Abstract-251.png +0 -0
- package/sources/assets/images/brutalist/Abstract-252.png +0 -0
- package/sources/assets/images/brutalist/Abstract-253.png +0 -0
- package/sources/assets/images/brutalist/Abstract-254.png +0 -0
- package/sources/assets/images/brutalist/Abstract-255.png +0 -0
- package/sources/assets/images/brutalist/Abstract-256.png +0 -0
- package/sources/assets/images/brutalist/Abstract-257.png +0 -0
- package/sources/assets/images/brutalist/Abstract-258.png +0 -0
- package/sources/assets/images/brutalist/Abstract-259.png +0 -0
- package/sources/assets/images/brutalist/Abstract-26.png +0 -0
- package/sources/assets/images/brutalist/Abstract-260.png +0 -0
- package/sources/assets/images/brutalist/Abstract-261.png +0 -0
- package/sources/assets/images/brutalist/Abstract-262.png +0 -0
- package/sources/assets/images/brutalist/Abstract-27.png +0 -0
- package/sources/assets/images/brutalist/Abstract-28.png +0 -0
- package/sources/assets/images/brutalist/Abstract-29.png +0 -0
- package/sources/assets/images/brutalist/Abstract-3.png +0 -0
- package/sources/assets/images/brutalist/Abstract-30.png +0 -0
- package/sources/assets/images/brutalist/Abstract-31.png +0 -0
- package/sources/assets/images/brutalist/Abstract-32.png +0 -0
- package/sources/assets/images/brutalist/Abstract-33.png +0 -0
- package/sources/assets/images/brutalist/Abstract-34.png +0 -0
- package/sources/assets/images/brutalist/Abstract-35.png +0 -0
- package/sources/assets/images/brutalist/Abstract-36.png +0 -0
- package/sources/assets/images/brutalist/Abstract-37.png +0 -0
- package/sources/assets/images/brutalist/Abstract-38.png +0 -0
- package/sources/assets/images/brutalist/Abstract-39.png +0 -0
- package/sources/assets/images/brutalist/Abstract-4.png +0 -0
- package/sources/assets/images/brutalist/Abstract-40.png +0 -0
- package/sources/assets/images/brutalist/Abstract-41.png +0 -0
- package/sources/assets/images/brutalist/Abstract-42.png +0 -0
- package/sources/assets/images/brutalist/Abstract-43.png +0 -0
- package/sources/assets/images/brutalist/Abstract-44.png +0 -0
- package/sources/assets/images/brutalist/Abstract-45.png +0 -0
- package/sources/assets/images/brutalist/Abstract-46.png +0 -0
- package/sources/assets/images/brutalist/Abstract-47.png +0 -0
- package/sources/assets/images/brutalist/Abstract-48.png +0 -0
- package/sources/assets/images/brutalist/Abstract-49.png +0 -0
- package/sources/assets/images/brutalist/Abstract-5.png +0 -0
- package/sources/assets/images/brutalist/Abstract-50.png +0 -0
- package/sources/assets/images/brutalist/Abstract-51.png +0 -0
- package/sources/assets/images/brutalist/Abstract-52.png +0 -0
- package/sources/assets/images/brutalist/Abstract-53.png +0 -0
- package/sources/assets/images/brutalist/Abstract-54.png +0 -0
- package/sources/assets/images/brutalist/Abstract-55.png +0 -0
- package/sources/assets/images/brutalist/Abstract-56.png +0 -0
- package/sources/assets/images/brutalist/Abstract-57.png +0 -0
- package/sources/assets/images/brutalist/Abstract-58.png +0 -0
- package/sources/assets/images/brutalist/Abstract-59.png +0 -0
- package/sources/assets/images/brutalist/Abstract-6.png +0 -0
- package/sources/assets/images/brutalist/Abstract-60.png +0 -0
- package/sources/assets/images/brutalist/Abstract-61.png +0 -0
- package/sources/assets/images/brutalist/Abstract-62.png +0 -0
- package/sources/assets/images/brutalist/Abstract-63.png +0 -0
- package/sources/assets/images/brutalist/Abstract-64.png +0 -0
- package/sources/assets/images/brutalist/Abstract-65.png +0 -0
- package/sources/assets/images/brutalist/Abstract-66.png +0 -0
- package/sources/assets/images/brutalist/Abstract-67.png +0 -0
- package/sources/assets/images/brutalist/Abstract-68.png +0 -0
- package/sources/assets/images/brutalist/Abstract-69.png +0 -0
- package/sources/assets/images/brutalist/Abstract-7.png +0 -0
- package/sources/assets/images/brutalist/Abstract-70.png +0 -0
- package/sources/assets/images/brutalist/Abstract-71.png +0 -0
- package/sources/assets/images/brutalist/Abstract-72.png +0 -0
- package/sources/assets/images/brutalist/Abstract-73.png +0 -0
- package/sources/assets/images/brutalist/Abstract-74.png +0 -0
- package/sources/assets/images/brutalist/Abstract-75.png +0 -0
- package/sources/assets/images/brutalist/Abstract-76.png +0 -0
- package/sources/assets/images/brutalist/Abstract-77.png +0 -0
- package/sources/assets/images/brutalist/Abstract-78.png +0 -0
- package/sources/assets/images/brutalist/Abstract-79.png +0 -0
- package/sources/assets/images/brutalist/Abstract-8.png +0 -0
- package/sources/assets/images/brutalist/Abstract-80.png +0 -0
- package/sources/assets/images/brutalist/Abstract-81.png +0 -0
- package/sources/assets/images/brutalist/Abstract-82.png +0 -0
- package/sources/assets/images/brutalist/Abstract-83.png +0 -0
- package/sources/assets/images/brutalist/Abstract-84.png +0 -0
- package/sources/assets/images/brutalist/Abstract-85.png +0 -0
- package/sources/assets/images/brutalist/Abstract-86.png +0 -0
- package/sources/assets/images/brutalist/Abstract-87.png +0 -0
- package/sources/assets/images/brutalist/Abstract-88.png +0 -0
- package/sources/assets/images/brutalist/Abstract-89.png +0 -0
- package/sources/assets/images/brutalist/Abstract-9.png +0 -0
- package/sources/assets/images/brutalist/Abstract-90.png +0 -0
- package/sources/assets/images/brutalist/Abstract-91.png +0 -0
- package/sources/assets/images/brutalist/Abstract-92.png +0 -0
- package/sources/assets/images/brutalist/Abstract-93.png +0 -0
- package/sources/assets/images/brutalist/Abstract-94.png +0 -0
- package/sources/assets/images/brutalist/Abstract-95.png +0 -0
- package/sources/assets/images/brutalist/Abstract-96.png +0 -0
- package/sources/assets/images/brutalist/Abstract-97.png +0 -0
- package/sources/assets/images/brutalist/Abstract-98.png +0 -0
- package/sources/assets/images/brutalist/Abstract-99.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-1.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-10.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-11.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-12.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-13.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-14.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-15.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-16.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-17.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-18.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-19.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-2.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-20.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-21.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-22.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-23.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-24.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-25.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-26.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-27.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-28.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-29.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-3.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-30.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-31.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-32.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-33.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-34.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-35.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-36.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-37.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-38.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-39.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-4.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-40.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-5.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-6.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-7.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-8.png +0 -0
- package/sources/assets/images/brutalist/Bauhaus-9.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-1.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-10.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-100.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-101.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-102.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-103.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-104.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-105.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-106.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-107.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-108.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-109.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-11.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-110.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-111.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-112.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-113.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-114.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-115.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-116.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-117.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-118.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-12.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-13.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-14.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-15.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-16.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-17.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-18.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-19.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-2.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-20.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-21.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-22.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-23.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-24.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-25.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-26.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-27.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-28.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-29.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-3.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-30.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-31.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-32.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-33.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-34.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-35.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-36.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-37.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-38.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-39.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-4.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-40.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-41.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-42.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-43.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-44.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-45.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-46.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-47.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-48.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-49.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-5.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-50.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-51.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-52.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-53.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-54.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-55.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-56.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-57.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-58.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-59.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-6.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-60.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-61.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-62.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-63.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-64.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-65.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-66.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-67.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-68.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-69.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-7.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-70.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-71.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-72.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-73.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-74.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-75.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-76.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-77.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-78.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-79.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-8.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-80.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-81.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-82.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-83.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-84.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-85.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-86.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-87.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-88.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-89.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-9.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-90.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-91.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-92.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-93.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-94.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-95.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-96.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-97.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-98.png +0 -0
- package/sources/assets/images/brutalist/Brutalism-99.png +0 -0
- package/sources/assets/images/favicon-active.png +0 -0
- package/sources/assets/images/favicon.png +0 -0
- package/sources/assets/images/gradients/01.png +0 -0
- package/sources/assets/images/gradients/02.png +0 -0
- package/sources/assets/images/gradients/03.png +0 -0
- package/sources/assets/images/gradients/04.png +0 -0
- package/sources/assets/images/gradients/05.png +0 -0
- package/sources/assets/images/gradients/06.png +0 -0
- package/sources/assets/images/gradients/07.png +0 -0
- package/sources/assets/images/gradients/08.png +0 -0
- package/sources/assets/images/gradients/09.png +0 -0
- package/sources/assets/images/gradients/10.png +0 -0
- package/sources/assets/images/gradients/100.png +0 -0
- package/sources/assets/images/gradients/11.png +0 -0
- package/sources/assets/images/gradients/12.png +0 -0
- package/sources/assets/images/gradients/13.png +0 -0
- package/sources/assets/images/gradients/14.png +0 -0
- package/sources/assets/images/gradients/15.png +0 -0
- package/sources/assets/images/gradients/16.png +0 -0
- package/sources/assets/images/gradients/17.png +0 -0
- package/sources/assets/images/gradients/18.png +0 -0
- package/sources/assets/images/gradients/19.png +0 -0
- package/sources/assets/images/gradients/20.png +0 -0
- package/sources/assets/images/gradients/21.png +0 -0
- package/sources/assets/images/gradients/22.png +0 -0
- package/sources/assets/images/gradients/23.png +0 -0
- package/sources/assets/images/gradients/24.png +0 -0
- package/sources/assets/images/gradients/25.png +0 -0
- package/sources/assets/images/gradients/26.png +0 -0
- package/sources/assets/images/gradients/27.png +0 -0
- package/sources/assets/images/gradients/28.png +0 -0
- package/sources/assets/images/gradients/29.png +0 -0
- package/sources/assets/images/gradients/30.png +0 -0
- package/sources/assets/images/gradients/31.png +0 -0
- package/sources/assets/images/gradients/32.png +0 -0
- package/sources/assets/images/gradients/33.png +0 -0
- package/sources/assets/images/gradients/34.png +0 -0
- package/sources/assets/images/gradients/35.png +0 -0
- package/sources/assets/images/gradients/36.png +0 -0
- package/sources/assets/images/gradients/37.png +0 -0
- package/sources/assets/images/gradients/38.png +0 -0
- package/sources/assets/images/gradients/39.png +0 -0
- package/sources/assets/images/gradients/40.png +0 -0
- package/sources/assets/images/gradients/41.png +0 -0
- package/sources/assets/images/gradients/42.png +0 -0
- package/sources/assets/images/gradients/43.png +0 -0
- package/sources/assets/images/gradients/44.png +0 -0
- package/sources/assets/images/gradients/45.png +0 -0
- package/sources/assets/images/gradients/46.png +0 -0
- package/sources/assets/images/gradients/47.png +0 -0
- package/sources/assets/images/gradients/48.png +0 -0
- package/sources/assets/images/gradients/49.png +0 -0
- package/sources/assets/images/gradients/50.png +0 -0
- package/sources/assets/images/gradients/51.png +0 -0
- package/sources/assets/images/gradients/52.png +0 -0
- package/sources/assets/images/gradients/53.png +0 -0
- package/sources/assets/images/gradients/54.png +0 -0
- package/sources/assets/images/gradients/55.png +0 -0
- package/sources/assets/images/gradients/56.png +0 -0
- package/sources/assets/images/gradients/57.png +0 -0
- package/sources/assets/images/gradients/58.png +0 -0
- package/sources/assets/images/gradients/59.png +0 -0
- package/sources/assets/images/gradients/60.png +0 -0
- package/sources/assets/images/gradients/61.png +0 -0
- package/sources/assets/images/gradients/62.png +0 -0
- package/sources/assets/images/gradients/63.png +0 -0
- package/sources/assets/images/gradients/64.png +0 -0
- package/sources/assets/images/gradients/65.png +0 -0
- package/sources/assets/images/gradients/66.png +0 -0
- package/sources/assets/images/gradients/67.png +0 -0
- package/sources/assets/images/gradients/68.png +0 -0
- package/sources/assets/images/gradients/69.png +0 -0
- package/sources/assets/images/gradients/70.png +0 -0
- package/sources/assets/images/gradients/71.png +0 -0
- package/sources/assets/images/gradients/72.png +0 -0
- package/sources/assets/images/gradients/73.png +0 -0
- package/sources/assets/images/gradients/74.png +0 -0
- package/sources/assets/images/gradients/75.png +0 -0
- package/sources/assets/images/gradients/76.png +0 -0
- package/sources/assets/images/gradients/77.png +0 -0
- package/sources/assets/images/gradients/78.png +0 -0
- package/sources/assets/images/gradients/79.png +0 -0
- package/sources/assets/images/gradients/80.png +0 -0
- package/sources/assets/images/gradients/81.png +0 -0
- package/sources/assets/images/gradients/82.png +0 -0
- package/sources/assets/images/gradients/83.png +0 -0
- package/sources/assets/images/gradients/84.png +0 -0
- package/sources/assets/images/gradients/85.png +0 -0
- package/sources/assets/images/gradients/86.png +0 -0
- package/sources/assets/images/gradients/87.png +0 -0
- package/sources/assets/images/gradients/88.png +0 -0
- package/sources/assets/images/gradients/89.png +0 -0
- package/sources/assets/images/gradients/90.png +0 -0
- package/sources/assets/images/gradients/91.png +0 -0
- package/sources/assets/images/gradients/92.png +0 -0
- package/sources/assets/images/gradients/93.png +0 -0
- package/sources/assets/images/gradients/94.png +0 -0
- package/sources/assets/images/gradients/95.png +0 -0
- package/sources/assets/images/gradients/96.png +0 -0
- package/sources/assets/images/gradients/97.png +0 -0
- package/sources/assets/images/gradients/98.png +0 -0
- package/sources/assets/images/gradients/99.png +0 -0
- package/sources/assets/images/icon-adaptive.png +0 -0
- package/sources/assets/images/icon-claude.png +0 -0
- package/sources/assets/images/icon-claude@2x.png +0 -0
- package/sources/assets/images/icon-claude@3x.png +0 -0
- package/sources/assets/images/icon-gemini.png +0 -0
- package/sources/assets/images/icon-gemini@2x.png +0 -0
- package/sources/assets/images/icon-gemini@3x.png +0 -0
- package/sources/assets/images/icon-gpt.png +0 -0
- package/sources/assets/images/icon-gpt@2x.png +0 -0
- package/sources/assets/images/icon-gpt@3x.png +0 -0
- package/sources/assets/images/icon-monochrome.png +0 -0
- package/sources/assets/images/icon-notification.png +0 -0
- package/sources/assets/images/icon-openclaw.png +0 -0
- package/sources/assets/images/icon-openclaw@2x.png +0 -0
- package/sources/assets/images/icon-openclaw@3x.png +0 -0
- package/sources/assets/images/icon-tauri.png +0 -0
- package/sources/assets/images/icon-voice-white.png +0 -0
- package/sources/assets/images/icon-voice.png +0 -0
- package/sources/assets/images/icon-voice@2x.png +0 -0
- package/sources/assets/images/icon-voice@3x.png +0 -0
- package/sources/assets/images/icon.png +0 -0
- package/sources/assets/images/logo-black.png +0 -0
- package/sources/assets/images/logo-white.png +0 -0
- package/sources/assets/images/logotype-dark.png +0 -0
- package/sources/assets/images/logotype-dark@2x.png +0 -0
- package/sources/assets/images/logotype-dark@3x.png +0 -0
- package/sources/assets/images/logotype-light.png +0 -0
- package/sources/assets/images/logotype-light@2x.png +0 -0
- package/sources/assets/images/logotype-light@3x.png +0 -0
- package/sources/assets/images/logotype.png +0 -0
- package/sources/assets/images/logotype@2x.png +0 -0
- package/sources/assets/images/logotype@3x.png +0 -0
- package/sources/assets/images/splash-android-dark.png +0 -0
- package/sources/assets/images/splash-android-light.png +0 -0
- package/sources/assets/images/transparent.png +0 -0
- package/sources/assets/images/zen-icon.png +0 -0
- package/sources/auth/AuthContext.tsx +100 -0
- package/sources/auth/authAccountApprove.ts +2 -0
- package/sources/auth/authApprove.ts +2 -0
- package/sources/auth/authChallenge.ts +8 -0
- package/sources/auth/authGetToken.ts +4 -0
- package/sources/auth/authQRStart.ts +17 -0
- package/sources/auth/authQRWait.ts +13 -0
- package/sources/auth/secretKeyBackup.spec.ts +465 -0
- package/sources/auth/secretKeyBackup.ts +179 -0
- package/sources/auth/tokenStorage.ts +27 -0
- package/sources/changelog/changelog.json +60 -0
- package/sources/changelog/index.ts +3 -0
- package/sources/changelog/parser.ts +23 -0
- package/sources/changelog/storage.ts +17 -0
- package/sources/changelog/types.ts +10 -0
- package/sources/components/ActiveSessionsGroupCompact.tsx +567 -0
- package/sources/components/AgentContentView.ios.tsx +70 -0
- package/sources/components/AgentContentView.tsx +48 -0
- package/sources/components/AgentInput.tsx +1468 -0
- package/sources/components/AgentInputAttachmentStrip.tsx +122 -0
- package/sources/components/AgentInputAutocomplete.tsx +96 -0
- package/sources/components/AgentInputSuggestionView.tsx +106 -0
- package/sources/components/AllFilesDiffView.tsx +515 -0
- package/sources/components/Avatar.tsx +149 -0
- package/sources/components/AvatarBrutalist.tsx +501 -0
- package/sources/components/AvatarGradient.tsx +147 -0
- package/sources/components/AvatarSkia.tsx +111 -0
- package/sources/components/AvatarSkia.web.tsx +113 -0
- package/sources/components/ChatFooter.tsx +50 -0
- package/sources/components/ChatHeaderView.tsx +180 -0
- package/sources/components/ChatList.tsx +283 -0
- package/sources/components/CodeEditor.tsx +22 -0
- package/sources/components/CodeEditor.web.tsx +180 -0
- package/sources/components/CodeView.tsx +33 -0
- package/sources/components/CommandPalette/CommandPalette.tsx +72 -0
- package/sources/components/CommandPalette/CommandPaletteInput.tsx +65 -0
- package/sources/components/CommandPalette/CommandPaletteItem.tsx +141 -0
- package/sources/components/CommandPalette/CommandPaletteModal.tsx +148 -0
- package/sources/components/CommandPalette/CommandPaletteProvider.tsx +141 -0
- package/sources/components/CommandPalette/CommandPaletteResults.tsx +129 -0
- package/sources/components/CommandPalette/index.ts +3 -0
- package/sources/components/CommandPalette/types.ts +15 -0
- package/sources/components/CommandPalette/useCommandPalette.ts +107 -0
- package/sources/components/CommandView.tsx +135 -0
- package/sources/components/CompactGitStatus.tsx +88 -0
- package/sources/components/ConnectButton.tsx +117 -0
- package/sources/components/Deferred.tsx +18 -0
- package/sources/components/DuplicateSheet.tsx +295 -0
- package/sources/components/EmptyMainScreen.tsx +171 -0
- package/sources/components/EmptyMessages.tsx +123 -0
- package/sources/components/EmptySessionsTablet.tsx +111 -0
- package/sources/components/ExternalLink.tsx +22 -0
- package/sources/components/FAB.tsx +53 -0
- package/sources/components/FABWide.tsx +59 -0
- package/sources/components/FeedItemCard.tsx +98 -0
- package/sources/components/FileIcon.tsx +63 -0
- package/sources/components/FileViewPanel.tsx +673 -0
- package/sources/components/FilesSidebar.tsx +739 -0
- package/sources/components/FloatingOverlay.tsx +48 -0
- package/sources/components/GitStatusBadge.tsx +82 -0
- package/sources/components/HeaderLogo.tsx +28 -0
- package/sources/components/HomeHeader.tsx +243 -0
- package/sources/components/HorizontalScrollView.tsx +88 -0
- package/sources/components/InboxView.tsx +260 -0
- package/sources/components/InlineFileDiff.tsx +277 -0
- package/sources/components/Item.tsx +315 -0
- package/sources/components/ItemGroup.tsx +147 -0
- package/sources/components/ItemList.tsx +102 -0
- package/sources/components/MainView.tsx +324 -0
- package/sources/components/MessageView.tsx +299 -0
- package/sources/components/MultiTextInput.tsx +285 -0
- package/sources/components/MultiTextInput.web.tsx +220 -0
- package/sources/components/OAuthView.tsx +374 -0
- package/sources/components/PermissionModeSelector.tsx +68 -0
- package/sources/components/PlaceholderContainerView.tsx +47 -0
- package/sources/components/PlusPlus.tsx +34 -0
- package/sources/components/PlusPlus.web.tsx +34 -0
- package/sources/components/ProjectGitStatus.tsx +102 -0
- package/sources/components/RoundButton.tsx +130 -0
- package/sources/components/SearchableListSelector.tsx +675 -0
- package/sources/components/SessionActionsNativeMenu.android.tsx +58 -0
- package/sources/components/SessionActionsNativeMenu.ios.tsx +55 -0
- package/sources/components/SessionActionsNativeMenu.tsx +20 -0
- package/sources/components/SessionActionsNativeMenu.web.tsx +13 -0
- package/sources/components/SessionActionsPopover.tsx +240 -0
- package/sources/components/SessionsList.tsx +471 -0
- package/sources/components/SessionsListWrapper.tsx +72 -0
- package/sources/components/SettingsView.tsx +470 -0
- package/sources/components/SettingsViewWrapper.tsx +21 -0
- package/sources/components/Shaker.tsx +42 -0
- package/sources/components/Shaker.web.tsx +46 -0
- package/sources/components/ShimmerView.tsx +106 -0
- package/sources/components/SidebarNavigator.tsx +218 -0
- package/sources/components/SidebarView.tsx +104 -0
- package/sources/components/SimpleSyntaxHighlighter.tsx +322 -0
- package/sources/components/StatusBarProvider.tsx +12 -0
- package/sources/components/StatusDot.tsx +49 -0
- package/sources/components/StyledText.tsx +35 -0
- package/sources/components/Switch.tsx +20 -0
- package/sources/components/TabBar.tsx +140 -0
- package/sources/components/ToolGroupView.tsx +101 -0
- package/sources/components/TransitionStack.tsx +14 -0
- package/sources/components/UpdateBanner.tsx +74 -0
- package/sources/components/UserCard.tsx +41 -0
- package/sources/components/UserSearchResult.tsx +129 -0
- package/sources/components/VoiceAssistantStatusBar.tsx +260 -0
- package/sources/components/VoiceBars.tsx +95 -0
- package/sources/components/autocomplete/applySuggestion.test.ts +194 -0
- package/sources/components/autocomplete/applySuggestion.ts +61 -0
- package/sources/components/autocomplete/findActiveWord.test.ts +365 -0
- package/sources/components/autocomplete/findActiveWord.ts +207 -0
- package/sources/components/autocomplete/suggestions.ts +79 -0
- package/sources/components/autocomplete/useActiveSuggestions.ts +130 -0
- package/sources/components/autocomplete/useActiveWord.ts +19 -0
- package/sources/components/diff/DiffView.tsx +188 -0
- package/sources/components/diff/PierreDiffView.tsx +253 -0
- package/sources/components/diff/calculateDiff.ts +317 -0
- package/sources/components/entityColor.ts +51 -0
- package/sources/components/haptics.ts +9 -0
- package/sources/components/haptics.web.ts +7 -0
- package/sources/components/layout.ts +44 -0
- package/sources/components/markdown/MarkdownView.tsx +670 -0
- package/sources/components/markdown/MermaidRenderer.tsx +233 -0
- package/sources/components/markdown/linkUtils.test.ts +17 -0
- package/sources/components/markdown/linkUtils.ts +5 -0
- package/sources/components/markdown/parseMarkdown.test.ts +64 -0
- package/sources/components/markdown/parseMarkdown.ts +46 -0
- package/sources/components/markdown/parseMarkdownBlock.test.ts +108 -0
- package/sources/components/markdown/parseMarkdownBlock.ts +200 -0
- package/sources/components/markdown/parseMarkdownSpans.ts +88 -0
- package/sources/components/modelModeOptions.test.ts +114 -0
- package/sources/components/modelModeOptions.ts +257 -0
- package/sources/components/navigation/Header.tsx +252 -0
- package/sources/components/parseLocalCommandMessage.spec.ts +96 -0
- package/sources/components/parseLocalCommandMessage.ts +97 -0
- package/sources/components/qr/QRCode.tsx +178 -0
- package/sources/components/qr/QRCode.web.tsx +229 -0
- package/sources/components/qr/index.ts +2 -0
- package/sources/components/qr/qrMatrix.ts +48 -0
- package/sources/components/tools/PermissionFooter.tsx +527 -0
- package/sources/components/tools/ToolDiffView.tsx +60 -0
- package/sources/components/tools/ToolError.tsx +49 -0
- package/sources/components/tools/ToolFullView.tsx +193 -0
- package/sources/components/tools/ToolHeader.tsx +93 -0
- package/sources/components/tools/ToolSectionView.tsx +42 -0
- package/sources/components/tools/ToolStatusIndicator.tsx +36 -0
- package/sources/components/tools/ToolView.tsx +340 -0
- package/sources/components/tools/knownTools.tsx +957 -0
- package/sources/components/tools/views/AskUserQuestionView.tsx +357 -0
- package/sources/components/tools/views/BashView.tsx +47 -0
- package/sources/components/tools/views/BashViewFull.tsx +81 -0
- package/sources/components/tools/views/CodexBashView.tsx +126 -0
- package/sources/components/tools/views/CodexDiffView.tsx +79 -0
- package/sources/components/tools/views/CodexPatchView.tsx +186 -0
- package/sources/components/tools/views/EditView.tsx +33 -0
- package/sources/components/tools/views/EditViewFull.tsx +38 -0
- package/sources/components/tools/views/ExitPlanToolView.tsx +21 -0
- package/sources/components/tools/views/FileView.tsx +118 -0
- package/sources/components/tools/views/GeminiEditView.tsx +75 -0
- package/sources/components/tools/views/GeminiExecuteView.tsx +92 -0
- package/sources/components/tools/views/MCPToolView.tsx +31 -0
- package/sources/components/tools/views/MultiEditView.tsx +41 -0
- package/sources/components/tools/views/MultiEditViewFull.tsx +84 -0
- package/sources/components/tools/views/TaskView.tsx +129 -0
- package/sources/components/tools/views/TodoView.tsx +90 -0
- package/sources/components/tools/views/WriteView.tsx +29 -0
- package/sources/components/tools/views/_all.tsx +88 -0
- package/sources/components/usage/UsageBar.tsx +80 -0
- package/sources/components/usage/UsageChart.tsx +164 -0
- package/sources/components/usage/UsagePanel.tsx +283 -0
- package/sources/components/web/FaviconPermissionIndicator.tsx +44 -0
- package/sources/config.ts +3 -0
- package/sources/constants/Languages.ts +116 -0
- package/sources/constants/Typography.ts +116 -0
- package/sources/dev/testRunner.ts +277 -0
- package/sources/docs/autocomplete-text-manipulation.md +224 -0
- package/sources/encryption/aes.appspec.ts +25 -0
- package/sources/encryption/aes.ts +21 -0
- package/sources/encryption/aes.web.test.ts +73 -0
- package/sources/encryption/aes.web.ts +79 -0
- package/sources/encryption/base64.appspec.ts +240 -0
- package/sources/encryption/base64.native.ts +12 -0
- package/sources/encryption/base64.ts +46 -0
- package/sources/encryption/blob.test.ts +120 -0
- package/sources/encryption/blob.ts +58 -0
- package/sources/encryption/deriveKey.appspec.ts +72 -0
- package/sources/encryption/deriveKey.ts +46 -0
- package/sources/encryption/hex.ts +17 -0
- package/sources/encryption/hmac_sha512.appspec.ts +40 -0
- package/sources/encryption/hmac_sha512.ts +42 -0
- package/sources/encryption/libsodium.lib.ts +2 -0
- package/sources/encryption/libsodium.lib.web.ts +2 -0
- package/sources/encryption/libsodium.ts +58 -0
- package/sources/encryption/text.test.ts +61 -0
- package/sources/encryption/text.ts +11 -0
- package/sources/hooks/useAsyncCommand.ts +25 -0
- package/sources/hooks/useAttachmentImage.ts +134 -0
- package/sources/hooks/useAutocomplete.ts +69 -0
- package/sources/hooks/useAutocompleteSession.ts +53 -0
- package/sources/hooks/useChangelog.ts +45 -0
- package/sources/hooks/useCheckCameraPermissions.ts +25 -0
- package/sources/hooks/useConnectAccount.ts +107 -0
- package/sources/hooks/useConnectTerminal.ts +112 -0
- package/sources/hooks/useDemoMessages.ts +48 -0
- package/sources/hooks/useDraft.ts +120 -0
- package/sources/hooks/useElapsedTime.ts +36 -0
- package/sources/hooks/useGetPath.ts +13 -0
- package/sources/hooks/useGitStatusFiles.ts +45 -0
- package/sources/hooks/useGlobalKeyboard.ts +29 -0
- package/sources/hooks/useGroupedMessages.ts +149 -0
- package/sources/hooks/useImagePicker.ts +135 -0
- package/sources/hooks/useInboxHasContent.ts +19 -0
- package/sources/hooks/useMultiClick.ts +56 -0
- package/sources/hooks/useNasTechAction.ts +45 -0
- package/sources/hooks/useNativeUpdate.ts +10 -0
- package/sources/hooks/useNavigateToSession.ts +20 -0
- package/sources/hooks/useNewSessionDraft.ts +70 -0
- package/sources/hooks/usePrefetchFileContents.ts +162 -0
- package/sources/hooks/useSearch.ts +120 -0
- package/sources/hooks/useSessionQuickActions.ts +325 -0
- package/sources/hooks/useTauriDrag.ts +76 -0
- package/sources/hooks/useTauriZoom.ts +67 -0
- package/sources/hooks/useUpdates.ts +84 -0
- package/sources/hooks/useVisibleSessionListViewData.ts +65 -0
- package/sources/hooks/useWorktreeCleanup.ts +69 -0
- package/sources/log.ts +108 -0
- package/sources/modal/ModalManager.ts +203 -0
- package/sources/modal/ModalProvider.tsx +103 -0
- package/sources/modal/components/BaseModal.tsx +122 -0
- package/sources/modal/components/CustomModal.tsx +42 -0
- package/sources/modal/components/WebAlertModal.tsx +139 -0
- package/sources/modal/components/WebPromptModal.tsx +185 -0
- package/sources/modal/index.ts +3 -0
- package/sources/modal/types.ts +79 -0
- package/sources/nastech-wire/index.ts +10 -0
- package/sources/nastech-wire/legacyProtocol.ts +27 -0
- package/sources/nastech-wire/messageMeta.ts +14 -0
- package/sources/nastech-wire/messages.ts +113 -0
- package/sources/nastech-wire/sessionProtocol.ts +134 -0
- package/sources/nastech-wire/voice.ts +34 -0
- package/sources/polyfills/screenOrientation.ts +33 -0
- package/sources/realtime/RealtimeProvider.tsx +20 -0
- package/sources/realtime/RealtimeProvider.web.tsx +15 -0
- package/sources/realtime/RealtimeSession.ts +200 -0
- package/sources/realtime/RealtimeVoiceSession.tsx +211 -0
- package/sources/realtime/RealtimeVoiceSession.web.tsx +209 -0
- package/sources/realtime/hooks/contextFormatters.ts +127 -0
- package/sources/realtime/hooks/voiceHooks.ts +232 -0
- package/sources/realtime/realtimeClientTools.ts +94 -0
- package/sources/realtime/types.ts +19 -0
- package/sources/realtime/voiceConfig.ts +31 -0
- package/sources/realtime/voiceExperiment.ts +91 -0
- package/sources/realtime/voiceSystemPrompt.ts +75 -0
- package/sources/scripts/compareTranslations.ts +217 -0
- package/sources/scripts/parseChangelog.ts +87 -0
- package/sources/sync/__testdata__/trace_0.json +3986 -0
- package/sources/sync/__testdata__/trace_1.json +1391 -0
- package/sources/sync/__testdata__/trace_2.json +182 -0
- package/sources/sync/agentDefaults.ts +108 -0
- package/sources/sync/apiArtifacts.ts +143 -0
- package/sources/sync/apiAttachments.ts +217 -0
- package/sources/sync/apiFeed.ts +60 -0
- package/sources/sync/apiFriends.ts +217 -0
- package/sources/sync/apiGithub.spec.ts +97 -0
- package/sources/sync/apiGithub.ts +103 -0
- package/sources/sync/apiKv.ts +270 -0
- package/sources/sync/apiPush.ts +83 -0
- package/sources/sync/apiServices.ts +64 -0
- package/sources/sync/apiSocket.ts +290 -0
- package/sources/sync/apiTypes.spec.ts +23 -0
- package/sources/sync/apiTypes.ts +213 -0
- package/sources/sync/apiUsage.ts +130 -0
- package/sources/sync/apiVoice.ts +57 -0
- package/sources/sync/appConfig.ts +95 -0
- package/sources/sync/artifactTypes.ts +85 -0
- package/sources/sync/attachmentTypes.ts +28 -0
- package/sources/sync/encryption/artifactEncryption.ts +83 -0
- package/sources/sync/encryption/encryption.ts +220 -0
- package/sources/sync/encryption/encryptionCache.ts +248 -0
- package/sources/sync/encryption/encryptor.appspec.ts +409 -0
- package/sources/sync/encryption/encryptor.ts +126 -0
- package/sources/sync/encryption/machineEncryption.ts +122 -0
- package/sources/sync/encryption/sessionEncryption.ts +207 -0
- package/sources/sync/feedTypes.ts +43 -0
- package/sources/sync/friendTypes.ts +92 -0
- package/sources/sync/git-parsers/LineParser.ts +62 -0
- package/sources/sync/git-parsers/parseBranch.ts +97 -0
- package/sources/sync/git-parsers/parseDiff.ts +180 -0
- package/sources/sync/git-parsers/parseStatus.ts +162 -0
- package/sources/sync/git-parsers/parseStatusV2.ts +307 -0
- package/sources/sync/gitStatusFiles.ts +185 -0
- package/sources/sync/gitStatusSync.ts +282 -0
- package/sources/sync/localSettings.ts +67 -0
- package/sources/sync/messageMeta.test.ts +87 -0
- package/sources/sync/messageMeta.ts +36 -0
- package/sources/sync/modeHacks.test.ts +29 -0
- package/sources/sync/modeHacks.ts +22 -0
- package/sources/sync/nastechApi.ts +124 -0
- package/sources/sync/ops.ts +776 -0
- package/sources/sync/persistence.ts +322 -0
- package/sources/sync/profile.ts +95 -0
- package/sources/sync/projectFiles.ts +54 -0
- package/sources/sync/prompt/systemPrompt.ts +20 -0
- package/sources/sync/purchases.ts +67 -0
- package/sources/sync/pushRegistration.ts +229 -0
- package/sources/sync/reducer/activityUpdateAccumulator.test.ts +492 -0
- package/sources/sync/reducer/activityUpdateAccumulator.ts +96 -0
- package/sources/sync/reducer/messageToEvent.ts +85 -0
- package/sources/sync/reducer/phase0-skipping.spec.ts +206 -0
- package/sources/sync/reducer/reducer.spec.ts +3169 -0
- package/sources/sync/reducer/reducer.ts +1214 -0
- package/sources/sync/reducer/reducerTracer.spec.ts +502 -0
- package/sources/sync/reducer/reducerTracer.ts +310 -0
- package/sources/sync/revenueCat/index.ts +21 -0
- package/sources/sync/revenueCat/revenueCat.ts +215 -0
- package/sources/sync/revenueCat/revenueCat.web.ts +238 -0
- package/sources/sync/revenueCat/types.ts +82 -0
- package/sources/sync/serverConfig.ts +72 -0
- package/sources/sync/settings.spec.ts +456 -0
- package/sources/sync/settings.ts +186 -0
- package/sources/sync/storage.ts +1653 -0
- package/sources/sync/storageTypes.spec.ts +24 -0
- package/sources/sync/storageTypes.ts +215 -0
- package/sources/sync/suggestionCommands.ts +149 -0
- package/sources/sync/suggestionFile.ts +206 -0
- package/sources/sync/sync.ts +2555 -0
- package/sources/sync/typesMessage.ts +69 -0
- package/sources/sync/typesMessageMeta.test.ts +14 -0
- package/sources/sync/typesMessageMeta.ts +17 -0
- package/sources/sync/typesRaw.spec.ts +2010 -0
- package/sources/sync/typesRaw.ts +1183 -0
- package/sources/sync/uploadFormFile.ts +29 -0
- package/sources/sync/uploadFormFile.web.ts +14 -0
- package/sources/sync/webTabTitle.ts +58 -0
- package/sources/text/README.md +223 -0
- package/sources/text/_all.ts +104 -0
- package/sources/text/_default.ts +1015 -0
- package/sources/text/index.ts +215 -0
- package/sources/text/translations/ca.ts +993 -0
- package/sources/text/translations/en.ts +1009 -0
- package/sources/text/translations/es.ts +995 -0
- package/sources/text/translations/it.ts +992 -0
- package/sources/text/translations/ja.ts +993 -0
- package/sources/text/translations/pl.ts +1024 -0
- package/sources/text/translations/pt.ts +992 -0
- package/sources/text/translations/ru.ts +1023 -0
- package/sources/text/translations/zh-Hans.ts +992 -0
- package/sources/text/translations/zh-Hant.ts +991 -0
- package/sources/theme.css +72 -0
- package/sources/theme.dark.json +31 -0
- package/sources/theme.figma.json +457 -0
- package/sources/theme.gen.ts +10 -0
- package/sources/theme.light.json +31 -0
- package/sources/theme.ts +452 -0
- package/sources/track/index.ts +171 -0
- package/sources/track/tracking.ts +12 -0
- package/sources/track/useTrackScreens.ts +10 -0
- package/sources/types/react-native-webrtc-web-shim.d.ts +6 -0
- package/sources/unistyles.ts +97 -0
- package/sources/utils/codexUnifiedDiff.spec.ts +43 -0
- package/sources/utils/codexUnifiedDiff.ts +70 -0
- package/sources/utils/consoleLogging.ts +145 -0
- package/sources/utils/copySessionMetadataToClipboard.ts +53 -0
- package/sources/utils/debounce.test.ts +646 -0
- package/sources/utils/debounce.ts +122 -0
- package/sources/utils/deviceCalculations.test.ts +318 -0
- package/sources/utils/deviceCalculations.ts +87 -0
- package/sources/utils/errors.ts +10 -0
- package/sources/utils/formatPermissionParams.ts +23 -0
- package/sources/utils/isTauri.ts +7 -0
- package/sources/utils/loadSkia.ts +3 -0
- package/sources/utils/loadSkia.web.ts +5 -0
- package/sources/utils/lock.ts +40 -0
- package/sources/utils/machineUtils.ts +6 -0
- package/sources/utils/messageUtils.ts +254 -0
- package/sources/utils/microphonePermissions.ts +109 -0
- package/sources/utils/notificationRouting.test.ts +51 -0
- package/sources/utils/notificationRouting.ts +81 -0
- package/sources/utils/oauth.ts +143 -0
- package/sources/utils/openExternalUrl.ts +19 -0
- package/sources/utils/parseToken.ts +23 -0
- package/sources/utils/pasteImages.web.ts +81 -0
- package/sources/utils/pathUtils.spec.ts +226 -0
- package/sources/utils/pathUtils.ts +75 -0
- package/sources/utils/platform.ts +19 -0
- package/sources/utils/readFileBytes.ts +11 -0
- package/sources/utils/readFileBytes.web.ts +12 -0
- package/sources/utils/requestReview.ts +135 -0
- package/sources/utils/responsive.ts +87 -0
- package/sources/utils/resumeCommand.test.ts +78 -0
- package/sources/utils/resumeCommand.ts +70 -0
- package/sources/utils/sessionFileLinks.test.ts +112 -0
- package/sources/utils/sessionFileLinks.ts +388 -0
- package/sources/utils/sessionUtils.ts +226 -0
- package/sources/utils/stringUtils.ts +41 -0
- package/sources/utils/sync.ts +164 -0
- package/sources/utils/thumbhash.ts +17 -0
- package/sources/utils/thumbhash.web.ts +85 -0
- package/sources/utils/time.ts +41 -0
- package/sources/utils/toSnakeCase.test.ts +182 -0
- package/sources/utils/toSnakeCase.ts +40 -0
- package/sources/utils/toolCommand.test.ts +23 -0
- package/sources/utils/toolCommand.ts +35 -0
- package/sources/utils/toolComparison.test.ts +101 -0
- package/sources/utils/toolComparison.ts +73 -0
- package/sources/utils/toolErrorParser.test.ts +126 -0
- package/sources/utils/toolErrorParser.ts +102 -0
- package/sources/utils/trimIdent.ts +27 -0
- package/sources/utils/truncateForLogs.ts +37 -0
- package/sources/utils/versionUtils.test.ts +58 -0
- package/sources/utils/versionUtils.ts +69 -0
- package/sources/utils/web/faviconGenerator.ts +39 -0
- package/sources/utils/worktree.ts +192 -0
- package/sources/wire/index.ts +97 -0
- package/src-tauri/Cargo.lock +5978 -0
- package/src-tauri/Cargo.toml +27 -0
- package/src-tauri/build.rs +3 -0
- package/src-tauri/capabilities/default.json +27 -0
- package/src-tauri/deny.toml +53 -0
- package/src-tauri/entitlements.plist +24 -0
- package/src-tauri/icons/128x128.png +0 -0
- package/src-tauri/icons/128x128@2x.png +0 -0
- package/src-tauri/icons/32x32.png +0 -0
- package/src-tauri/icons/64x64.png +0 -0
- package/src-tauri/icons/Square107x107Logo.png +0 -0
- package/src-tauri/icons/Square142x142Logo.png +0 -0
- package/src-tauri/icons/Square150x150Logo.png +0 -0
- package/src-tauri/icons/Square284x284Logo.png +0 -0
- package/src-tauri/icons/Square30x30Logo.png +0 -0
- package/src-tauri/icons/Square310x310Logo.png +0 -0
- package/src-tauri/icons/Square44x44Logo.png +0 -0
- package/src-tauri/icons/Square71x71Logo.png +0 -0
- package/src-tauri/icons/Square89x89Logo.png +0 -0
- package/src-tauri/icons/StoreLogo.png +0 -0
- package/src-tauri/icons/icon.icns +0 -0
- package/src-tauri/icons/icon.ico +0 -0
- package/src-tauri/icons/icon.png +0 -0
- package/src-tauri/src/lib.rs +18 -0
- package/src-tauri/src/main.rs +6 -0
- package/src-tauri/tauri.conf.json +51 -0
- package/src-tauri/tauri.dev.conf.json +20 -0
- package/src-tauri/tauri.preview.conf.json +20 -0
- package/tsconfig.json +45 -0
- package/vitest.config.ts +26 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { describe, it, expect } from '@/dev/testRunner';
|
|
2
|
+
import { SecretBoxEncryption, BoxEncryption, AES256Encryption } from './encryptor';
|
|
3
|
+
import { getRandomBytes } from 'expo-crypto';
|
|
4
|
+
|
|
5
|
+
describe('SecretBoxEncryption', () => {
|
|
6
|
+
it('should encrypt and decrypt single Uint8Array', async () => {
|
|
7
|
+
const secretKey = getRandomBytes(32);
|
|
8
|
+
const encryptor = new SecretBoxEncryption(secretKey);
|
|
9
|
+
|
|
10
|
+
const originalData = new TextEncoder().encode('Hello, World!');
|
|
11
|
+
const encrypted = await encryptor.encrypt([originalData]);
|
|
12
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
13
|
+
|
|
14
|
+
expect(decrypted.length).toBe(1);
|
|
15
|
+
expect(decrypted[0]).toEqual(originalData);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should encrypt and decrypt multiple Uint8Arrays', async () => {
|
|
19
|
+
const secretKey = getRandomBytes(32);
|
|
20
|
+
const encryptor = new SecretBoxEncryption(secretKey);
|
|
21
|
+
|
|
22
|
+
const data1 = new TextEncoder().encode('First message');
|
|
23
|
+
const data2 = new TextEncoder().encode('Second message');
|
|
24
|
+
const data3 = new TextEncoder().encode('Third message');
|
|
25
|
+
|
|
26
|
+
const encrypted = await encryptor.encrypt([data1, data2, data3]);
|
|
27
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
28
|
+
|
|
29
|
+
expect(decrypted.length).toBe(3);
|
|
30
|
+
expect(decrypted[0]).toEqual(data1);
|
|
31
|
+
expect(decrypted[1]).toEqual(data2);
|
|
32
|
+
expect(decrypted[2]).toEqual(data3);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should handle empty arrays', async () => {
|
|
36
|
+
const secretKey = getRandomBytes(32);
|
|
37
|
+
const encryptor = new SecretBoxEncryption(secretKey);
|
|
38
|
+
|
|
39
|
+
const encrypted = await encryptor.encrypt([]);
|
|
40
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
41
|
+
|
|
42
|
+
expect(encrypted.length).toBe(0);
|
|
43
|
+
expect(decrypted.length).toBe(0);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should produce different ciphertext for same plaintext (due to random nonce)', async () => {
|
|
47
|
+
const secretKey = getRandomBytes(32);
|
|
48
|
+
const encryptor = new SecretBoxEncryption(secretKey);
|
|
49
|
+
|
|
50
|
+
const originalData = new TextEncoder().encode('Same message');
|
|
51
|
+
const encrypted1 = await encryptor.encrypt([originalData]);
|
|
52
|
+
const encrypted2 = await encryptor.encrypt([originalData]);
|
|
53
|
+
|
|
54
|
+
// Ciphertexts should be different due to random nonce
|
|
55
|
+
expect(encrypted1[0]).not.toEqual(encrypted2[0]);
|
|
56
|
+
|
|
57
|
+
// But both should decrypt to the same plaintext
|
|
58
|
+
const decrypted1 = await encryptor.decrypt(encrypted1);
|
|
59
|
+
const decrypted2 = await encryptor.decrypt(encrypted2);
|
|
60
|
+
|
|
61
|
+
expect(decrypted1[0]).toEqual(originalData);
|
|
62
|
+
expect(decrypted2[0]).toEqual(originalData);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should fail decryption with wrong key', async () => {
|
|
66
|
+
const secretKey1 = getRandomBytes(32);
|
|
67
|
+
const secretKey2 = getRandomBytes(32);
|
|
68
|
+
|
|
69
|
+
const encryptor1 = new SecretBoxEncryption(secretKey1);
|
|
70
|
+
const encryptor2 = new SecretBoxEncryption(secretKey2);
|
|
71
|
+
|
|
72
|
+
const originalData = new TextEncoder().encode('Secret message');
|
|
73
|
+
const encrypted = await encryptor1.encrypt([originalData]);
|
|
74
|
+
const decrypted = await encryptor2.decrypt(encrypted);
|
|
75
|
+
|
|
76
|
+
expect(decrypted[0]).toBe(null);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle moderate size data', async () => {
|
|
80
|
+
const secretKey = getRandomBytes(32);
|
|
81
|
+
const encryptor = new SecretBoxEncryption(secretKey);
|
|
82
|
+
|
|
83
|
+
// Create a moderate array (10KB instead of 1MB)
|
|
84
|
+
const largeData = new Uint8Array(10 * 1024);
|
|
85
|
+
for (let i = 0; i < largeData.length; i++) {
|
|
86
|
+
largeData[i] = i % 256;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const encrypted = await encryptor.encrypt([largeData]);
|
|
90
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
91
|
+
|
|
92
|
+
expect(decrypted.length).toBe(1);
|
|
93
|
+
expect(decrypted[0]).toEqual(largeData);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should handle 500 individual items separately', async () => {
|
|
97
|
+
const secretKey = getRandomBytes(32);
|
|
98
|
+
const encryptor = new SecretBoxEncryption(secretKey);
|
|
99
|
+
|
|
100
|
+
// Create 500 individual items
|
|
101
|
+
const originalItems = [];
|
|
102
|
+
for (let i = 0; i < 500; i++) {
|
|
103
|
+
originalItems.push(new TextEncoder().encode(`Item ${i}: This is test data for item number ${i}`));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Encrypt each item individually
|
|
107
|
+
const encryptedItems = [];
|
|
108
|
+
for (const item of originalItems) {
|
|
109
|
+
const encrypted = await encryptor.encrypt([item]);
|
|
110
|
+
encryptedItems.push(encrypted[0]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Decrypt each item individually
|
|
114
|
+
const decryptedItems = [];
|
|
115
|
+
for (const encryptedItem of encryptedItems) {
|
|
116
|
+
const decrypted = await encryptor.decrypt([encryptedItem]);
|
|
117
|
+
decryptedItems.push(decrypted[0]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Verify all items match
|
|
121
|
+
expect(decryptedItems.length).toBe(500);
|
|
122
|
+
for (let i = 0; i < 500; i++) {
|
|
123
|
+
expect(decryptedItems[i]).toEqual(originalItems[i]);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('BoxEncryption', () => {
|
|
129
|
+
it('should encrypt and decrypt single Uint8Array', async () => {
|
|
130
|
+
const seed = getRandomBytes(32);
|
|
131
|
+
const encryptor = new BoxEncryption(seed);
|
|
132
|
+
|
|
133
|
+
const originalData = new TextEncoder().encode('Hello, Box!');
|
|
134
|
+
const encrypted = await encryptor.encrypt([originalData]);
|
|
135
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
136
|
+
|
|
137
|
+
expect(decrypted.length).toBe(1);
|
|
138
|
+
expect(decrypted[0]).toEqual(originalData);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should encrypt and decrypt multiple Uint8Arrays', async () => {
|
|
142
|
+
const seed = getRandomBytes(32);
|
|
143
|
+
const encryptor = new BoxEncryption(seed);
|
|
144
|
+
|
|
145
|
+
const data1 = new TextEncoder().encode('Box message 1');
|
|
146
|
+
const data2 = new TextEncoder().encode('Box message 2');
|
|
147
|
+
const data3 = new TextEncoder().encode('Box message 3');
|
|
148
|
+
|
|
149
|
+
const encrypted = await encryptor.encrypt([data1, data2, data3]);
|
|
150
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
151
|
+
|
|
152
|
+
expect(decrypted.length).toBe(3);
|
|
153
|
+
expect(decrypted[0]).toEqual(data1);
|
|
154
|
+
expect(decrypted[1]).toEqual(data2);
|
|
155
|
+
expect(decrypted[2]).toEqual(data3);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should handle empty arrays', async () => {
|
|
159
|
+
const seed = getRandomBytes(32);
|
|
160
|
+
const encryptor = new BoxEncryption(seed);
|
|
161
|
+
|
|
162
|
+
const encrypted = await encryptor.encrypt([]);
|
|
163
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
164
|
+
|
|
165
|
+
expect(encrypted.length).toBe(0);
|
|
166
|
+
expect(decrypted.length).toBe(0);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should generate consistent public key from seed', async () => {
|
|
170
|
+
const seed = getRandomBytes(32);
|
|
171
|
+
const encryptor1 = new BoxEncryption(seed);
|
|
172
|
+
const encryptor2 = new BoxEncryption(seed);
|
|
173
|
+
|
|
174
|
+
// Both instances with same secret key should generate same public key
|
|
175
|
+
// We can't directly access the public key, but we can verify
|
|
176
|
+
// that data encrypted by one can be decrypted by the other
|
|
177
|
+
const originalData = new TextEncoder().encode('Test consistency');
|
|
178
|
+
const encrypted = await encryptor1.encrypt([originalData]);
|
|
179
|
+
const decrypted = await encryptor2.decrypt(encrypted);
|
|
180
|
+
|
|
181
|
+
expect(decrypted[0]).toEqual(originalData);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should produce different ciphertext for same plaintext (ephemeral keys)', async () => {
|
|
185
|
+
const seed = getRandomBytes(32);
|
|
186
|
+
const encryptor = new BoxEncryption(seed);
|
|
187
|
+
|
|
188
|
+
const originalData = new TextEncoder().encode('Same box message');
|
|
189
|
+
const encrypted1 = await encryptor.encrypt([originalData]);
|
|
190
|
+
const encrypted2 = await encryptor.encrypt([originalData]);
|
|
191
|
+
|
|
192
|
+
// Ciphertexts should be different due to ephemeral keys
|
|
193
|
+
expect(encrypted1[0]).not.toEqual(encrypted2[0]);
|
|
194
|
+
|
|
195
|
+
// But both should decrypt to the same plaintext
|
|
196
|
+
const decrypted1 = await encryptor.decrypt(encrypted1);
|
|
197
|
+
const decrypted2 = await encryptor.decrypt(encrypted2);
|
|
198
|
+
|
|
199
|
+
expect(decrypted1[0]).toEqual(originalData);
|
|
200
|
+
expect(decrypted2[0]).toEqual(originalData);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should fail decryption with wrong key', async () => {
|
|
204
|
+
const seed1 = getRandomBytes(32);
|
|
205
|
+
const seed2 = getRandomBytes(32);
|
|
206
|
+
|
|
207
|
+
const encryptor1 = new BoxEncryption(seed1);
|
|
208
|
+
const encryptor2 = new BoxEncryption(seed2);
|
|
209
|
+
|
|
210
|
+
const originalData = new TextEncoder().encode('Secret box message');
|
|
211
|
+
const encrypted = await encryptor1.encrypt([originalData]);
|
|
212
|
+
const decrypted = await encryptor2.decrypt(encrypted);
|
|
213
|
+
|
|
214
|
+
expect(decrypted[0]).toBe(null);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should handle moderate size data', async () => {
|
|
218
|
+
const seed = getRandomBytes(32);
|
|
219
|
+
const encryptor = new BoxEncryption(seed);
|
|
220
|
+
|
|
221
|
+
// Create a moderate array (10KB instead of 1MB)
|
|
222
|
+
const largeData = new Uint8Array(10 * 1024);
|
|
223
|
+
for (let i = 0; i < largeData.length; i++) {
|
|
224
|
+
largeData[i] = (i * 3) % 256;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const encrypted = await encryptor.encrypt([largeData]);
|
|
228
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
229
|
+
|
|
230
|
+
expect(decrypted.length).toBe(1);
|
|
231
|
+
expect(decrypted[0]).toEqual(largeData);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should handle mixed data sizes in batch', async () => {
|
|
235
|
+
const seed = getRandomBytes(32);
|
|
236
|
+
const encryptor = new BoxEncryption(seed);
|
|
237
|
+
|
|
238
|
+
const small = new TextEncoder().encode('Small');
|
|
239
|
+
const medium = new Uint8Array(512);
|
|
240
|
+
for (let i = 0; i < medium.length; i++) {
|
|
241
|
+
medium[i] = i % 256;
|
|
242
|
+
}
|
|
243
|
+
const large = new Uint8Array(5 * 1024); // 5KB instead of 100KB
|
|
244
|
+
for (let i = 0; i < large.length; i++) {
|
|
245
|
+
large[i] = (i * 7) % 256;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const encrypted = await encryptor.encrypt([small, medium, large]);
|
|
249
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
250
|
+
|
|
251
|
+
expect(decrypted.length).toBe(3);
|
|
252
|
+
expect(decrypted[0]).toEqual(small);
|
|
253
|
+
expect(decrypted[1]).toEqual(medium);
|
|
254
|
+
expect(decrypted[2]).toEqual(large);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('should handle 500 individual items separately', async () => {
|
|
258
|
+
const seed = getRandomBytes(32);
|
|
259
|
+
const encryptor = new BoxEncryption(seed);
|
|
260
|
+
|
|
261
|
+
// Create 500 individual items
|
|
262
|
+
const originalItems = [];
|
|
263
|
+
for (let i = 0; i < 500; i++) {
|
|
264
|
+
originalItems.push(new TextEncoder().encode(`Box Item ${i}: This is test data for box encryption item ${i}`));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Encrypt each item individually
|
|
268
|
+
const encryptedItems = [];
|
|
269
|
+
for (const item of originalItems) {
|
|
270
|
+
const encrypted = await encryptor.encrypt([item]);
|
|
271
|
+
encryptedItems.push(encrypted[0]);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Decrypt each item individually
|
|
275
|
+
const decryptedItems = [];
|
|
276
|
+
for (const encryptedItem of encryptedItems) {
|
|
277
|
+
const decrypted = await encryptor.decrypt([encryptedItem]);
|
|
278
|
+
decryptedItems.push(decrypted[0]);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Verify all items match
|
|
282
|
+
expect(decryptedItems.length).toBe(500);
|
|
283
|
+
for (let i = 0; i < 500; i++) {
|
|
284
|
+
expect(decryptedItems[i]).toEqual(originalItems[i]);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
describe('AES256Encryption', () => {
|
|
290
|
+
it('should encrypt and decrypt single Uint8Array', async () => {
|
|
291
|
+
const secretKey = getRandomBytes(32);
|
|
292
|
+
const encryptor = new AES256Encryption(secretKey);
|
|
293
|
+
|
|
294
|
+
const encrypted = await encryptor.encrypt(['Hello, AES!']);
|
|
295
|
+
const decrypted = await encryptor.decrypt(encrypted);
|
|
296
|
+
|
|
297
|
+
expect(decrypted.length).toBe(1);
|
|
298
|
+
expect(decrypted[0]).toEqual('Hello, AES!');
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// it('should encrypt and decrypt multiple Uint8Arrays', async () => {
|
|
302
|
+
// const secretKey = getRandomBytes(32);
|
|
303
|
+
// const encryptor = new AES256Encryption(secretKey);
|
|
304
|
+
|
|
305
|
+
// const data1 = new TextEncoder().encode('AES message 1');
|
|
306
|
+
// const data2 = new TextEncoder().encode('AES message 2');
|
|
307
|
+
// const data3 = new TextEncoder().encode('AES message 3');
|
|
308
|
+
|
|
309
|
+
// const encrypted = await encryptor.encrypt([data1, data2, data3]);
|
|
310
|
+
// const decrypted = await encryptor.decrypt(encrypted);
|
|
311
|
+
|
|
312
|
+
// expect(decrypted.length).toBe(3);
|
|
313
|
+
// expect(decrypted[0]).toEqual(data1);
|
|
314
|
+
// expect(decrypted[1]).toEqual(data2);
|
|
315
|
+
// expect(decrypted[2]).toEqual(data3);
|
|
316
|
+
// });
|
|
317
|
+
|
|
318
|
+
// it('should handle empty arrays', async () => {
|
|
319
|
+
// const secretKey = getRandomBytes(32);
|
|
320
|
+
// const encryptor = new AES256Encryption(secretKey);
|
|
321
|
+
|
|
322
|
+
// const encrypted = await encryptor.encrypt([]);
|
|
323
|
+
// const decrypted = await encryptor.decrypt(encrypted);
|
|
324
|
+
|
|
325
|
+
// expect(encrypted.length).toBe(0);
|
|
326
|
+
// expect(decrypted.length).toBe(0);
|
|
327
|
+
// });
|
|
328
|
+
|
|
329
|
+
// it('should produce different ciphertext for same plaintext (due to random IV)', async () => {
|
|
330
|
+
// const secretKey = getRandomBytes(32);
|
|
331
|
+
// const encryptor = new AES256Encryption(secretKey);
|
|
332
|
+
|
|
333
|
+
// const originalData = new TextEncoder().encode('Same AES message');
|
|
334
|
+
// const encrypted1 = await encryptor.encrypt([originalData]);
|
|
335
|
+
// const encrypted2 = await encryptor.encrypt([originalData]);
|
|
336
|
+
|
|
337
|
+
// // Ciphertexts should be different due to random IV
|
|
338
|
+
// expect(encrypted1[0]).not.toEqual(encrypted2[0]);
|
|
339
|
+
|
|
340
|
+
// // But both should decrypt to the same plaintext
|
|
341
|
+
// const decrypted1 = await encryptor.decrypt(encrypted1);
|
|
342
|
+
// const decrypted2 = await encryptor.decrypt(encrypted2);
|
|
343
|
+
|
|
344
|
+
// expect(decrypted1[0]).toEqual(originalData);
|
|
345
|
+
// expect(decrypted2[0]).toEqual(originalData);
|
|
346
|
+
// });
|
|
347
|
+
|
|
348
|
+
// it('should fail decryption with wrong key', async () => {
|
|
349
|
+
// const secretKey1 = getRandomBytes(32);
|
|
350
|
+
// const secretKey2 = getRandomBytes(32);
|
|
351
|
+
|
|
352
|
+
// const encryptor1 = new AES256Encryption(secretKey1);
|
|
353
|
+
// const encryptor2 = new AES256Encryption(secretKey2);
|
|
354
|
+
|
|
355
|
+
// const originalData = new TextEncoder().encode('Secret AES message');
|
|
356
|
+
// const encrypted = await encryptor1.encrypt([originalData]);
|
|
357
|
+
// const decrypted = await encryptor2.decrypt(encrypted);
|
|
358
|
+
|
|
359
|
+
// expect(decrypted[0]).toBe(null);
|
|
360
|
+
// });
|
|
361
|
+
|
|
362
|
+
// it('should handle moderate size data', async () => {
|
|
363
|
+
// const secretKey = getRandomBytes(32);
|
|
364
|
+
// const encryptor = new AES256Encryption(secretKey);
|
|
365
|
+
|
|
366
|
+
// // Create a moderate array (10KB)
|
|
367
|
+
// const largeData = new Uint8Array(10 * 1024);
|
|
368
|
+
// for (let i = 0; i < largeData.length; i++) {
|
|
369
|
+
// largeData[i] = (i * 5) % 100;
|
|
370
|
+
// }
|
|
371
|
+
|
|
372
|
+
// const encrypted = await encryptor.encrypt([largeData]);
|
|
373
|
+
// const decrypted = await encryptor.decrypt(encrypted);
|
|
374
|
+
|
|
375
|
+
// expect(decrypted.length).toBe(1);
|
|
376
|
+
// expect(decrypted[0]).toEqual(largeData);
|
|
377
|
+
// });
|
|
378
|
+
|
|
379
|
+
// it('should handle 500 individual items separately', async () => {
|
|
380
|
+
// const secretKey = getRandomBytes(32);
|
|
381
|
+
// const encryptor = new AES256Encryption(secretKey);
|
|
382
|
+
|
|
383
|
+
// // Create 500 individual items
|
|
384
|
+
// const originalItems = [];
|
|
385
|
+
// for (let i = 0; i < 500; i++) {
|
|
386
|
+
// originalItems.push(new TextEncoder().encode(`AES Item ${i}: This is test data for AES encryption item ${i}`));
|
|
387
|
+
// }
|
|
388
|
+
|
|
389
|
+
// // Encrypt each item individually
|
|
390
|
+
// const encryptedItems = [];
|
|
391
|
+
// for (const item of originalItems) {
|
|
392
|
+
// const encrypted = await encryptor.encrypt([item]);
|
|
393
|
+
// encryptedItems.push(encrypted[0]);
|
|
394
|
+
// }
|
|
395
|
+
|
|
396
|
+
// // Decrypt each item individually
|
|
397
|
+
// const decryptedItems = [];
|
|
398
|
+
// for (const encryptedItem of encryptedItems) {
|
|
399
|
+
// const decrypted = await encryptor.decrypt([encryptedItem]);
|
|
400
|
+
// decryptedItems.push(decrypted[0]);
|
|
401
|
+
// }
|
|
402
|
+
|
|
403
|
+
// // Verify all items match
|
|
404
|
+
// expect(decryptedItems.length).toBe(500);
|
|
405
|
+
// for (let i = 0; i < 500; i++) {
|
|
406
|
+
// expect(decryptedItems[i]).toEqual(originalItems[i]);
|
|
407
|
+
// }
|
|
408
|
+
// });
|
|
409
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { decryptBox, decryptSecretBox, encryptBox, encryptSecretBox } from "@/encryption/libsodium";
|
|
2
|
+
import { encodeBase64, decodeBase64 } from "@/encryption/base64";
|
|
3
|
+
import sodium from '@/encryption/libsodium.lib';
|
|
4
|
+
import { decodeUTF8, encodeUTF8 } from "@/encryption/text";
|
|
5
|
+
import { decryptAESGCMString, encryptAESGCMString } from "@/encryption/aes";
|
|
6
|
+
|
|
7
|
+
//
|
|
8
|
+
// IMPORTANT: Right now there is a bug in the AES implementation and it works only with a normal strings converted to Uint8Array.
|
|
9
|
+
// Any abnormal string might break encoding and decoding utf8.
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
export interface Encryptor {
|
|
13
|
+
encrypt(data: any[]): Promise<Uint8Array[]>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Decryptor {
|
|
17
|
+
decrypt(data: Uint8Array[]): Promise<(any | null)[]>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class SecretBoxEncryption implements Encryptor, Decryptor {
|
|
21
|
+
private readonly secretKey: Uint8Array;
|
|
22
|
+
|
|
23
|
+
constructor(secretKey: Uint8Array) {
|
|
24
|
+
this.secretKey = secretKey;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async decrypt(data: Uint8Array[]): Promise<(any | null)[]> {
|
|
28
|
+
// Process as batch, not Promise.all - more efficient
|
|
29
|
+
const results: (any | null)[] = [];
|
|
30
|
+
for (const item of data) {
|
|
31
|
+
results.push(decryptSecretBox(item, this.secretKey));
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async encrypt(data: any[]): Promise<Uint8Array[]> {
|
|
37
|
+
// Process as batch, not Promise.all - more efficient
|
|
38
|
+
const results: Uint8Array[] = [];
|
|
39
|
+
for (const item of data) {
|
|
40
|
+
results.push(encryptSecretBox(item, this.secretKey));
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class BoxEncryption implements Encryptor, Decryptor {
|
|
47
|
+
private readonly privateKey: Uint8Array;
|
|
48
|
+
private readonly publicKey: Uint8Array;
|
|
49
|
+
|
|
50
|
+
constructor(seed: Uint8Array) {
|
|
51
|
+
// Use the seed to generate a proper keypair
|
|
52
|
+
const keypair = sodium.crypto_box_seed_keypair(seed);
|
|
53
|
+
this.privateKey = keypair.privateKey;
|
|
54
|
+
this.publicKey = keypair.publicKey;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async encrypt(data: any[]): Promise<Uint8Array[]> {
|
|
58
|
+
// Process as batch, not Promise.all - more efficient
|
|
59
|
+
const results: Uint8Array[] = [];
|
|
60
|
+
for (const item of data) {
|
|
61
|
+
results.push(encryptBox(encodeUTF8(JSON.stringify(item)), this.publicKey));
|
|
62
|
+
}
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async decrypt(data: Uint8Array[]): Promise<(any | null)[]> {
|
|
67
|
+
// Process as batch, not Promise.all - more efficient
|
|
68
|
+
const results: (any | null)[] = [];
|
|
69
|
+
for (const item of data) {
|
|
70
|
+
let decrypted = decryptBox(item, this.privateKey);
|
|
71
|
+
if (!decrypted) {
|
|
72
|
+
results.push(null);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
results.push(JSON.parse(decodeUTF8(decrypted)));
|
|
76
|
+
}
|
|
77
|
+
return results;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class AES256Encryption implements Encryptor, Decryptor {
|
|
82
|
+
private readonly secretKey: Uint8Array;
|
|
83
|
+
private readonly secretKeyB64: string;
|
|
84
|
+
|
|
85
|
+
constructor(secretKey: Uint8Array) {
|
|
86
|
+
this.secretKey = secretKey;
|
|
87
|
+
this.secretKeyB64 = encodeBase64(secretKey);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async encrypt(data: any[]): Promise<Uint8Array[]> {
|
|
91
|
+
// Process as batch, not Promise.all - more efficient
|
|
92
|
+
const results: Uint8Array[] = [];
|
|
93
|
+
for (const item of data) {
|
|
94
|
+
// Serialize to JSON string first
|
|
95
|
+
const encrypted = decodeBase64(await encryptAESGCMString(JSON.stringify(item), this.secretKeyB64));
|
|
96
|
+
let output = new Uint8Array(encrypted.length + 1);
|
|
97
|
+
output[0] = 0;
|
|
98
|
+
output.set(encrypted, 1);
|
|
99
|
+
results.push(output);
|
|
100
|
+
}
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async decrypt(data: Uint8Array[]): Promise<(any | null)[]> {
|
|
105
|
+
// Decrypt items concurrently. The previous implementation used a
|
|
106
|
+
// sequential for-await loop, which serialised every AES-GCM call on
|
|
107
|
+
// the JS thread. For a 1000-message session that meant ~1000
|
|
108
|
+
// serialised crypto operations before the UI could display anything.
|
|
109
|
+
// Promise.all schedules them on the microtask queue, allowing the
|
|
110
|
+
// crypto subtle backend (and any native bridge work) to interleave.
|
|
111
|
+
return Promise.all(data.map(async (item) => {
|
|
112
|
+
try {
|
|
113
|
+
if (item[0] !== 0) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const decryptedString = await decryptAESGCMString(encodeBase64(item.slice(1)), this.secretKeyB64);
|
|
117
|
+
if (!decryptedString) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return JSON.parse(decryptedString);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { decodeBase64, encodeBase64 } from '@/encryption/base64';
|
|
2
|
+
import { MachineMetadata, MachineMetadataSchema } from '../storageTypes';
|
|
3
|
+
import { EncryptionCache } from './encryptionCache';
|
|
4
|
+
import { Decryptor, Encryptor } from './encryptor';
|
|
5
|
+
|
|
6
|
+
export class MachineEncryption {
|
|
7
|
+
private machineId: string;
|
|
8
|
+
private encryptor: Encryptor & Decryptor;
|
|
9
|
+
private cache: EncryptionCache;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
machineId: string,
|
|
13
|
+
encryptor: Encryptor & Decryptor,
|
|
14
|
+
cache: EncryptionCache
|
|
15
|
+
) {
|
|
16
|
+
this.machineId = machineId;
|
|
17
|
+
this.encryptor = encryptor;
|
|
18
|
+
this.cache = cache;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Encrypt machine metadata
|
|
23
|
+
*/
|
|
24
|
+
async encryptMetadata(metadata: MachineMetadata): Promise<string> {
|
|
25
|
+
const encrypted = await this.encryptor.encrypt([metadata]);
|
|
26
|
+
return encodeBase64(encrypted[0], 'base64');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Decrypt machine metadata with caching
|
|
31
|
+
*/
|
|
32
|
+
async decryptMetadata(version: number, encrypted: string): Promise<MachineMetadata | null> {
|
|
33
|
+
// Check cache first
|
|
34
|
+
const cached = this.cache.getCachedMachineMetadata(this.machineId, version);
|
|
35
|
+
if (cached) {
|
|
36
|
+
return cached;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Decrypt if not cached
|
|
40
|
+
try {
|
|
41
|
+
const encryptedData = decodeBase64(encrypted, 'base64');
|
|
42
|
+
const decrypted = await this.encryptor.decrypt([encryptedData]);
|
|
43
|
+
if (!decrypted[0]) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const parsed = MachineMetadataSchema.safeParse(decrypted[0]);
|
|
48
|
+
if (!parsed.success) {
|
|
49
|
+
console.error('Failed to parse machine metadata:', parsed.error);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Cache the result
|
|
54
|
+
this.cache.setCachedMachineMetadata(this.machineId, version, parsed.data);
|
|
55
|
+
return parsed.data;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Failed to decrypt machine metadata:', error);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Encrypt daemon state
|
|
64
|
+
*/
|
|
65
|
+
async encryptDaemonState(state: any): Promise<string> {
|
|
66
|
+
const encrypted = await this.encryptor.encrypt([state]);
|
|
67
|
+
return encodeBase64(encrypted[0], 'base64');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Decrypt daemon state with caching
|
|
72
|
+
*/
|
|
73
|
+
async decryptDaemonState(version: number, encrypted: string | null | undefined): Promise<any | null> {
|
|
74
|
+
if (!encrypted) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check cache first
|
|
79
|
+
const cached = this.cache.getCachedDaemonState(this.machineId, version);
|
|
80
|
+
if (cached !== undefined) {
|
|
81
|
+
return cached;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Decrypt if not cached
|
|
85
|
+
try {
|
|
86
|
+
const encryptedData = decodeBase64(encrypted, 'base64');
|
|
87
|
+
const decrypted = await this.encryptor.decrypt([encryptedData]);
|
|
88
|
+
const result = decrypted[0] || null;
|
|
89
|
+
|
|
90
|
+
// Cache the result (including null values)
|
|
91
|
+
this.cache.setCachedDaemonState(this.machineId, version, result);
|
|
92
|
+
return result;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Failed to decrypt daemon state:', error);
|
|
95
|
+
// Cache null result to avoid repeated decryption attempts
|
|
96
|
+
this.cache.setCachedDaemonState(this.machineId, version, null);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Encrypt raw data using machine-specific encryption
|
|
103
|
+
*/
|
|
104
|
+
async encryptRaw(data: any): Promise<string> {
|
|
105
|
+
const encrypted = await this.encryptor.encrypt([data]);
|
|
106
|
+
return encodeBase64(encrypted[0], 'base64');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Decrypt raw data using machine-specific encryption
|
|
111
|
+
*/
|
|
112
|
+
async decryptRaw(encrypted: string): Promise<any | null> {
|
|
113
|
+
try {
|
|
114
|
+
const encryptedData = decodeBase64(encrypted, 'base64');
|
|
115
|
+
const decrypted = await this.encryptor.decrypt([encryptedData]);
|
|
116
|
+
return decrypted[0] || null;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('Failed to decrypt raw data:', error);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|