| author | |
| committer | |
| log | 876bbd715ae6aa8e1d663455747e17c92e0a287c |
| tree | 7881f15b09c9f4e7095776b7b2e384aa62751c9b |
| parent | ac0d1f52a087c63819b2b032ac4535d18d3c23af |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>8 files changed, 189 insertions(+), 83 deletions(-)
apps/web/src/components/PlanSidebar.tsx+6-24| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { memo, useState, useCallback, useRef, useEffect } from "react"; | |
| 1 | import { memo, useState, useCallback } from "react"; | |
| 2 | 2 | import { type TimestampFormat } from "../appSettings"; |
| 3 | 3 | import { Badge } from "./ui/badge"; |
| 4 | 4 | import { Button } from "./ui/button"; |
| ... | ... | @@ -26,6 +26,7 @@ import { |
| 26 | 26 | import { Menu, MenuItem, MenuPopup, MenuTrigger } from "./ui/menu"; |
| 27 | 27 | import { readNativeApi } from "~/nativeApi"; |
| 28 | 28 | import { toastManager } from "./ui/toast"; |
| 29 | import { useCopyToClipboard } from "~/hooks/useCopyToClipboard"; | |
| 29 | 30 | |
| 30 | 31 | function stepStatusIcon(status: string): React.ReactNode { |
| 31 | 32 | if (status === "completed") { |
| ... | ... | @@ -68,8 +69,7 @@ const PlanSidebar = memo(function PlanSidebar({ |
| 68 | 69 | }: PlanSidebarProps) { |
| 69 | 70 | const [proposedPlanExpanded, setProposedPlanExpanded] = useState(false); |
| 70 | 71 | const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false); |
| 71 | const [copied, setCopied] = useState(false); | |
| 72 | const copiedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); | |
| 72 | const { copyToClipboard, isCopied } = useCopyToClipboard(); | |
| 73 | 73 | |
| 74 | 74 | const planMarkdown = activeProposedPlan?.planMarkdown ?? null; |
| 75 | 75 | const displayedPlanMarkdown = planMarkdown ? stripDisplayedPlanMarkdown(planMarkdown) : null; |
| ... | ... | @@ -77,26 +77,8 @@ const PlanSidebar = memo(function PlanSidebar({ |
| 77 | 77 | |
| 78 | 78 | const handleCopyPlan = useCallback(() => { |
| 79 | 79 | if (!planMarkdown) return; |
| 80 | void navigator.clipboard.writeText(planMarkdown); | |
| 81 | if (copiedTimerRef.current != null) { | |
| 82 | clearTimeout(copiedTimerRef.current); | |
| 83 | } | |
| 84 | ||
| 85 | setCopied(true); | |
| 86 | copiedTimerRef.current = setTimeout(() => { | |
| 87 | setCopied(false); | |
| 88 | copiedTimerRef.current = null; | |
| 89 | }, 2000); | |
| 90 | }, [planMarkdown]); | |
| 91 | ||
| 92 | // Cleanup timeout on unmount | |
| 93 | useEffect(() => { | |
| 94 | return () => { | |
| 95 | if (copiedTimerRef.current != null) { | |
| 96 | clearTimeout(copiedTimerRef.current); | |
| 97 | } | |
| 98 | }; | |
| 99 | }, []); | |
| 80 | copyToClipboard(planMarkdown); | |
| 81 | }, [planMarkdown, copyToClipboard]); | |
| 100 | 82 | |
| 101 | 83 | const handleDownload = useCallback(() => { |
| 102 | 84 | if (!planMarkdown) return; |
| ... | ... | @@ -169,7 +151,7 @@ const PlanSidebar = memo(function PlanSidebar({ |
| 169 | 151 | </MenuTrigger> |
| 170 | 152 | <MenuPopup align="end"> |
| 171 | 153 | <MenuItem onClick={handleCopyPlan}> |
| 172 | {copied ? "Copied!" : "Copy to clipboard"} | |
| 154 | {isCopied ? "Copied!" : "Copy to clipboard"} | |
| 173 | 155 | </MenuItem> |
| 174 | 156 | <MenuItem onClick={handleDownload}>Download as markdown</MenuItem> |
| 175 | 157 | <MenuItem |
apps/web/src/components/Sidebar.tsx+19-22| ... | ... | @@ -89,17 +89,11 @@ import { |
| 89 | 89 | resolveThreadStatusPill, |
| 90 | 90 | shouldClearThreadSelectionOnMouseDown, |
| 91 | 91 | } from "./Sidebar.logic"; |
| 92 | import { useCopyToClipboard } from "~/hooks/useCopyToClipboard"; | |
| 92 | 93 | |
| 93 | 94 | const EMPTY_KEYBINDINGS: ResolvedKeybindingsConfig = []; |
| 94 | 95 | const THREAD_PREVIEW_LIMIT = 6; |
| 95 | 96 | |
| 96 | async function copyTextToClipboard(text: string): Promise<void> { | |
| 97 | if (typeof navigator === "undefined" || navigator.clipboard?.writeText === undefined) { | |
| 98 | throw new Error("Clipboard API unavailable."); | |
| 99 | } | |
| 100 | await navigator.clipboard.writeText(text); | |
| 101 | } | |
| 102 | ||
| 103 | 97 | function formatRelativeTime(iso: string): string { |
| 104 | 98 | const diff = Date.now() - new Date(iso).getTime(); |
| 105 | 99 | const minutes = Math.floor(diff / 60_000); |
| ... | ... | @@ -671,6 +665,22 @@ export default function Sidebar() { |
| 671 | 665 | ], |
| 672 | 666 | ); |
| 673 | 667 | |
| 668 | const { copyToClipboard } = useCopyToClipboard<{ threadId: ThreadId }>({ | |
| 669 | onCopy: (ctx) => { | |
| 670 | toastManager.add({ | |
| 671 | type: "success", | |
| 672 | title: "Thread ID copied", | |
| 673 | description: ctx.threadId, | |
| 674 | }); | |
| 675 | }, | |
| 676 | onError: (error) => { | |
| 677 | toastManager.add({ | |
| 678 | type: "error", | |
| 679 | title: "Failed to copy thread ID", | |
| 680 | description: error instanceof Error ? error.message : "An error occurred.", | |
| 681 | }); | |
| 682 | }, | |
| 683 | }); | |
| 674 | 684 | const handleThreadContextMenu = useCallback( |
| 675 | 685 | async (threadId: ThreadId, position: { x: number; y: number }) => { |
| 676 | 686 | const api = readNativeApi(); |
| ... | ... | @@ -699,20 +709,7 @@ export default function Sidebar() { |
| 699 | 709 | return; |
| 700 | 710 | } |
| 701 | 711 | if (clicked === "copy-thread-id") { |
| 702 | try { | |
| 703 | await copyTextToClipboard(threadId); | |
| 704 | toastManager.add({ | |
| 705 | type: "success", | |
| 706 | title: "Thread ID copied", | |
| 707 | description: threadId, | |
| 708 | }); | |
| 709 | } catch (error) { | |
| 710 | toastManager.add({ | |
| 711 | type: "error", | |
| 712 | title: "Failed to copy thread ID", | |
| 713 | description: error instanceof Error ? error.message : "An error occurred.", | |
| 714 | }); | |
| 715 | } | |
| 712 | copyToClipboard(threadId, { threadId }); | |
| 716 | 713 | return; |
| 717 | 714 | } |
| 718 | 715 | if (clicked !== "delete") return; |
| ... | ... | @@ -729,7 +726,7 @@ export default function Sidebar() { |
| 729 | 726 | } |
| 730 | 727 | await deleteThread(threadId); |
| 731 | 728 | }, |
| 732 | [appSettings.confirmThreadDelete, deleteThread, markThreadUnread, threads], | |
| 729 | [appSettings.confirmThreadDelete, copyToClipboard, deleteThread, markThreadUnread, threads], | |
| 733 | 730 | ); |
| 734 | 731 | |
| 735 | 732 | const handleMultiSelectContextMenu = useCallback( |
apps/web/src/components/chat/MessageCopyButton.tsx+11-10| ... | ... | @@ -1,19 +1,20 @@ |
| 1 | import { memo, useCallback, useState } from "react"; | |
| 1 | import { memo } from "react"; | |
| 2 | 2 | import { CopyIcon, CheckIcon } from "lucide-react"; |
| 3 | 3 | import { Button } from "../ui/button"; |
| 4 | import { useCopyToClipboard } from "~/hooks/useCopyToClipboard"; | |
| 4 | 5 | |
| 5 | 6 | export const MessageCopyButton = memo(function MessageCopyButton({ text }: { text: string }) { |
| 6 | const [copied, setCopied] = useState(false); | |
| 7 | ||
| 8 | const handleCopy = useCallback(() => { | |
| 9 | void navigator.clipboard.writeText(text); | |
| 10 | setCopied(true); | |
| 11 | setTimeout(() => setCopied(false), 2000); | |
| 12 | }, [text]); | |
| 7 | const { copyToClipboard, isCopied } = useCopyToClipboard(); | |
| 13 | 8 | |
| 14 | 9 | return ( |
| 15 | <Button type="button" size="xs" variant="outline" onClick={handleCopy} title="Copy message"> | |
| 16 | {copied ? <CheckIcon className="size-3 text-success" /> : <CopyIcon className="size-3" />} | |
| 10 | <Button | |
| 11 | type="button" | |
| 12 | size="xs" | |
| 13 | variant="outline" | |
| 14 | onClick={() => copyToClipboard(text)} | |
| 15 | title="Copy message" | |
| 16 | > | |
| 17 | {isCopied ? <CheckIcon className="size-3 text-success" /> : <CopyIcon className="size-3" />} | |
| 17 | 18 | </Button> |
| 18 | 19 | ); |
| 19 | 20 | }); |
apps/web/src/components/ui/sidebar.tsx+2-2| ... | ... | @@ -17,7 +17,7 @@ import { |
| 17 | 17 | } from "~/components/ui/sheet"; |
| 18 | 18 | import { Skeleton } from "~/components/ui/skeleton"; |
| 19 | 19 | import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip"; |
| 20 | import { useMediaQuery } from "~/hooks/useMediaQuery"; | |
| 20 | import { useIsMobile } from "~/hooks/useMediaQuery"; | |
| 21 | 21 | import { getLocalStorageItem, setLocalStorageItem } from "~/hooks/useLocalStorage"; |
| 22 | 22 | import { Schema } from "effect"; |
| 23 | 23 | |
| ... | ... | @@ -98,7 +98,7 @@ function SidebarProvider({ |
| 98 | 98 | open?: boolean; |
| 99 | 99 | onOpenChange?: (open: boolean) => void; |
| 100 | 100 | }) { |
| 101 | const isMobile = useMediaQuery("(max-width: 767px)"); | |
| 101 | const isMobile = useIsMobile(); | |
| 102 | 102 | const [openMobile, setOpenMobile] = React.useState(false); |
| 103 | 103 | |
| 104 | 104 | // This is the internal state of the sidebar. |
apps/web/src/hooks/useCopyToClipboard.ts created+66| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | import * as React from "react"; | |
| 2 | ||
| 3 | export function useCopyToClipboard<TContext = void>({ | |
| 4 | timeout = 2000, | |
| 5 | onCopy, | |
| 6 | onError, | |
| 7 | }: { | |
| 8 | timeout?: number; | |
| 9 | onCopy?: (ctx: TContext) => void; | |
| 10 | onError?: (error: Error, ctx: TContext) => void; | |
| 11 | } = {}): { copyToClipboard: (value: string, ctx: TContext) => void; isCopied: boolean } { | |
| 12 | const [isCopied, setIsCopied] = React.useState(false); | |
| 13 | const timeoutIdRef = React.useRef<NodeJS.Timeout | null>(null); | |
| 14 | const onCopyRef = React.useRef(onCopy); | |
| 15 | const onErrorRef = React.useRef(onError); | |
| 16 | const timeoutRef = React.useRef(timeout); | |
| 17 | ||
| 18 | onCopyRef.current = onCopy; | |
| 19 | onErrorRef.current = onError; | |
| 20 | timeoutRef.current = timeout; | |
| 21 | ||
| 22 | const copyToClipboard = React.useCallback((value: string, ctx: TContext): void => { | |
| 23 | if (typeof window === "undefined" || !navigator.clipboard?.writeText) { | |
| 24 | onErrorRef.current?.(new Error("Clipboard API unavailable."), ctx); | |
| 25 | return; | |
| 26 | } | |
| 27 | ||
| 28 | if (!value) return; | |
| 29 | ||
| 30 | navigator.clipboard.writeText(value).then( | |
| 31 | () => { | |
| 32 | if (timeoutIdRef.current) { | |
| 33 | clearTimeout(timeoutIdRef.current); | |
| 34 | } | |
| 35 | setIsCopied(true); | |
| 36 | ||
| 37 | onCopyRef.current?.(ctx); | |
| 38 | ||
| 39 | if (timeoutRef.current !== 0) { | |
| 40 | timeoutIdRef.current = setTimeout(() => { | |
| 41 | setIsCopied(false); | |
| 42 | timeoutIdRef.current = null; | |
| 43 | }, timeoutRef.current); | |
| 44 | } | |
| 45 | }, | |
| 46 | (error) => { | |
| 47 | if (onErrorRef.current) { | |
| 48 | onErrorRef.current(error, ctx); | |
| 49 | } else { | |
| 50 | console.error(error); | |
| 51 | } | |
| 52 | }, | |
| 53 | ); | |
| 54 | }, []); | |
| 55 | ||
| 56 | // Cleanup timeout on unmount | |
| 57 | React.useEffect(() => { | |
| 58 | return (): void => { | |
| 59 | if (timeoutIdRef.current) { | |
| 60 | clearTimeout(timeoutIdRef.current); | |
| 61 | } | |
| 62 | }; | |
| 63 | }, []); | |
| 64 | ||
| 65 | return { copyToClipboard, isCopied }; | |
| 66 | } |
apps/web/src/hooks/useMediaQuery.ts+79-19| ... | ... | @@ -1,27 +1,87 @@ |
| 1 | import { useEffect, useState } from "react"; | |
| 1 | import { useCallback, useSyncExternalStore } from "react"; | |
| 2 | 2 | |
| 3 | function getMediaQueryMatch(query: string): boolean { | |
| 4 | if (typeof window === "undefined") { | |
| 5 | return false; | |
| 3 | const BREAKPOINTS = { | |
| 4 | "2xl": 1536, | |
| 5 | "3xl": 1600, | |
| 6 | "4xl": 2000, | |
| 7 | lg: 1024, | |
| 8 | md: 768, | |
| 9 | sm: 640, | |
| 10 | xl: 1280, | |
| 11 | } as const; | |
| 12 | ||
| 13 | type Breakpoint = keyof typeof BREAKPOINTS; | |
| 14 | ||
| 15 | type BreakpointQuery = Breakpoint | `max-${Breakpoint}` | `${Breakpoint}:max-${Breakpoint}`; | |
| 16 | ||
| 17 | function resolveMin(value: Breakpoint | number): string { | |
| 18 | const px = typeof value === "number" ? value : BREAKPOINTS[value]; | |
| 19 | return `(min-width: ${px}px)`; | |
| 20 | } | |
| 21 | ||
| 22 | function resolveMax(value: Breakpoint | number): string { | |
| 23 | const px = typeof value === "number" ? value : BREAKPOINTS[value]; | |
| 24 | return `(max-width: ${px - 1}px)`; | |
| 25 | } | |
| 26 | ||
| 27 | function parseQuery(query: BreakpointQuery | MediaQueryInput | (string & {})): string { | |
| 28 | if (typeof query !== "string") { | |
| 29 | const parts: string[] = []; | |
| 30 | if (query.min != null) parts.push(resolveMin(query.min)); | |
| 31 | if (query.max != null) parts.push(resolveMax(query.max)); | |
| 32 | if (query.pointer === "coarse") parts.push("(pointer: coarse)"); | |
| 33 | if (query.pointer === "fine") parts.push("(pointer: fine)"); | |
| 34 | if (parts.length === 0) return "(min-width: 0px)"; | |
| 35 | return parts.join(" and "); | |
| 36 | } | |
| 37 | ||
| 38 | if (query.startsWith("(")) return query; | |
| 39 | ||
| 40 | const parts: string[] = []; | |
| 41 | for (const segment of query.split(":")) { | |
| 42 | if (segment.startsWith("max-")) { | |
| 43 | const bp = segment.slice(4); | |
| 44 | if (bp in BREAKPOINTS) parts.push(resolveMax(bp as Breakpoint)); | |
| 45 | } else if (segment in BREAKPOINTS) { | |
| 46 | parts.push(resolveMin(segment as Breakpoint)); | |
| 47 | } | |
| 6 | 48 | } |
| 7 | return window.matchMedia(query).matches; | |
| 49 | ||
| 50 | return parts.length > 0 ? parts.join(" and ") : query; | |
| 51 | } | |
| 52 | ||
| 53 | function getServerSnapshot(): boolean { | |
| 54 | return false; | |
| 8 | 55 | } |
| 9 | 56 | |
| 10 | export function useMediaQuery(query: string): boolean { | |
| 11 | const [matches, setMatches] = useState(() => getMediaQueryMatch(query)); | |
| 57 | export type MediaQueryInput = { | |
| 58 | min?: Breakpoint | number; | |
| 59 | max?: Breakpoint | number; | |
| 60 | /** Touch-like input (finger). Use "fine" for mouse/trackpad. */ | |
| 61 | pointer?: "coarse" | "fine"; | |
| 62 | }; | |
| 63 | ||
| 64 | export function useMediaQuery(query: BreakpointQuery | MediaQueryInput | (string & {})): boolean { | |
| 65 | const mediaQuery = parseQuery(query); | |
| 12 | 66 | |
| 13 | useEffect(() => { | |
| 14 | const mediaQueryList = window.matchMedia(query); | |
| 15 | const handleChange = () => { | |
| 16 | setMatches(mediaQueryList.matches); | |
| 17 | }; | |
| 67 | const subscribe = useCallback( | |
| 68 | (callback: () => void) => { | |
| 69 | if (typeof window === "undefined") return () => {}; | |
| 70 | const mql = window.matchMedia(mediaQuery); | |
| 71 | mql.addEventListener("change", callback); | |
| 72 | return () => mql.removeEventListener("change", callback); | |
| 73 | }, | |
| 74 | [mediaQuery], | |
| 75 | ); | |
| 18 | 76 | |
| 19 | setMatches(mediaQueryList.matches); | |
| 20 | mediaQueryList.addEventListener("change", handleChange); | |
| 21 | return () => { | |
| 22 | mediaQueryList.removeEventListener("change", handleChange); | |
| 23 | }; | |
| 24 | }, [query]); | |
| 77 | const getSnapshot = useCallback(() => { | |
| 78 | if (typeof window === "undefined") return false; | |
| 79 | return window.matchMedia(mediaQuery).matches; | |
| 80 | }, [mediaQuery]); | |
| 81 | ||
| 82 | return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); | |
| 83 | } | |
| 25 | 84 | |
| 26 | return matches; | |
| 85 | export function useIsMobile(): boolean { | |
| 86 | return useMediaQuery("max-md"); | |
| 27 | 87 | } |
apps/web/src/routes/_chat.$threadId.tsx+1-1| ... | ... | @@ -221,7 +221,7 @@ function ChatThreadRouteView() { |
| 221 | 221 | if (!shouldUseDiffSheet) { |
| 222 | 222 | return ( |
| 223 | 223 | <> |
| 224 | <SidebarInset className="h-dvh min-h-0 overflow-hidden overscroll-y-none bg-background text-foreground"> | |
| 224 | <SidebarInset className="h-dvh min-h-0 overflow-hidden overscroll-y-none bg-background text-foreground"> | |
| 225 | 225 | <ChatView key={threadId} threadId={threadId} /> |
| 226 | 226 | </SidebarInset> |
| 227 | 227 | <DiffPanelInlineSidebar |
bun.lock+5-5| ... | ... | @@ -262,13 +262,13 @@ |
| 262 | 262 | |
| 263 | 263 | "@effect/language-service": ["@effect/language-service@0.75.1", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-g9xD2tAQgRFpYC2YgpZq02VeSL5fBbFJ0B/g1o+14NuNmwtaYJc7SjiLWAA9eyhJHosNrn6h1Ye+Kx6j5mN0AA=="], |
| 264 | 264 | |
| 265 | "@effect/platform-node": ["@effect/platform-node@https://pkg.pr.new/Effect-TS/effect-smol/@effect/platform-node@8881a9b", { "dependencies": { "@effect/platform-node-shared": "https://pkg.pr.new/Effect-TS/effect-smol/@effect/platform-node-shared@8881a9b606d84a6f5eb6615279138322984f5368", "mime": "^4.1.0", "undici": "^7.20.0" }, "peerDependencies": { "effect": "^4.0.0-beta.25", "ioredis": "^5.7.0" } }, "sha512-lOVb9aLpFnbkG4dWxY8lSTXihldd6kbcFI936X5UMvHz0HAYGrxsu1a+kHt/rYjiw1gjCmmnU6pE2pwKfO9erg=="], | |
| 265 | "@effect/platform-node": ["@effect/platform-node@https://pkg.pr.new/Effect-TS/effect-smol/@effect/platform-node@8881a9b", { "dependencies": { "@effect/platform-node-shared": "https://pkg.pr.new/Effect-TS/effect-smol/@effect/platform-node-shared@8881a9b606d84a6f5eb6615279138322984f5368", "mime": "^4.1.0", "undici": "^7.20.0" }, "peerDependencies": { "effect": "^4.0.0-beta.25", "ioredis": "^5.7.0" } }], | |
| 266 | 266 | |
| 267 | "@effect/platform-node-shared": ["@effect/platform-node-shared@https://pkg.pr.new/Effect-TS/effect-smol/@effect/platform-node-shared@8881a9b606d84a6f5eb6615279138322984f5368", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.25" } }, "sha512-73FDHSTVLh/ZHeWrHFEbnCbjFE9gKi1YdJ9LEatDj0doZ8ouuTJW2BbqLDwMEfSf4zNQrxMEg+Jj/pb612HyWg=="], | |
| 267 | "@effect/platform-node-shared": ["@effect/platform-node-shared@https://pkg.pr.new/Effect-TS/effect-smol/@effect/platform-node-shared@8881a9b606d84a6f5eb6615279138322984f5368", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.25" } }], | |
| 268 | 268 | |
| 269 | "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@https://pkg.pr.new/Effect-TS/effect-smol/@effect/sql-sqlite-bun@8881a9b", { "peerDependencies": { "effect": "^4.0.0-beta.25" } }, "sha512-7Tcfkx/NfQILRHyO5c52I8NYrg6jBcxDAguTYx7tgbGHYU9WPQRGh/AkcRgQ+1fsUGjWdojSfd+WGb/r4ltYtQ=="], | |
| 269 | "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@https://pkg.pr.new/Effect-TS/effect-smol/@effect/sql-sqlite-bun@8881a9b", { "peerDependencies": { "effect": "^4.0.0-beta.25" } }], | |
| 270 | 270 | |
| 271 | "@effect/vitest": ["@effect/vitest@https://pkg.pr.new/Effect-TS/effect-smol/@effect/vitest@8881a9b", { "peerDependencies": { "effect": "^4.0.0-beta.25", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-QQxLK156FZVPGYqSUPnEcybDm6e45KLcXb30XcimIKbIxuJLkuyxHQJW2hUu7lxjCoCotj2B4vc96gPKH/3Deg=="], | |
| 271 | "@effect/vitest": ["@effect/vitest@https://pkg.pr.new/Effect-TS/effect-smol/@effect/vitest@8881a9b", { "peerDependencies": { "effect": "^4.0.0-beta.25", "vitest": "^3.0.0 || ^4.0.0" } }], | |
| 272 | 272 | |
| 273 | 273 | "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="], |
| 274 | 274 | |
| ... | ... | @@ -1010,7 +1010,7 @@ |
| 1010 | 1010 | |
| 1011 | 1011 | "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], |
| 1012 | 1012 | |
| 1013 | "effect": ["effect@https://pkg.pr.new/Effect-TS/effect-smol/effect@8881a9b", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-tZcsKgsLpQ5p1T5/duJHebWAqyG8owTuJdASj/2V+WPMuDlnB+uKvetMMXJsrNOyElUb3lVFeF2Mq00BbCnL9g=="], | |
| 1013 | "effect": ["effect@https://pkg.pr.new/Effect-TS/effect-smol/effect@8881a9b", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }], | |
| 1014 | 1014 | |
| 1015 | 1015 | "electron": ["electron@40.6.0", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-ett8W+yOFGDuM0vhJMamYSkrbV3LoaffzJd9GfjI96zRAxyrNqUSKqBpf/WGbQCweDxX2pkUCUfrv4wwKpsFZA=="], |
| 1016 | 1016 |