- Build signin URL with redirect param so users return to their
original page after re-authentication
- Replace naive refresh lock with token-based ownership to prevent
cross-tab lock release conflicts
- Add stale lock detection with max age to avoid deadlocks from
crashed tabs
- Add timeout to waitUntilTokenRefreshed to prevent infinite polling
- Add tests for signin redirect URL building and refresh token logic
Problem:\n- In variable inspect artifacts view, clicking Reset All invalidates sandbox download query keys.\n- If a previously selected file has been removed, the download-url query may still refetch with stale path and return 400.\n- Default query retry amplifies this into repeated failed requests in this scenario.\n\nSolution:\n- Extend sandbox file invalidation with an option to skip download query refetch.\n- Use that option in Reset All flow so download-url queries are marked stale without immediate refetch.\n- Derive selected file path from latest sandbox flat data and disable download-url query when file no longer exists.\n- Disable retry only for artifacts-tab download-url query to avoid repeated 400 retries in this path.\n- Align tree selectedPath with derived selectedFilePath and add hook tests for invalidation behavior.\n\nValidation:\n- pnpm vitest --run service/use-sandbox-file.spec.tsx
Replaced plain array query key in useSandboxFileDownloadUrl with
oRPC-generated queryKey for type safety and consistency. Added
downloadFile cache invalidation to useInvalidateSandboxFiles so
stale download URLs are cleared after workflow/chatflow runs.
Add useInvalidateSandboxFiles hook and call it alongside
fetchInspectVars/invalidAllLastRun so the Artifacts tab refreshes
automatically when a chatflow preview or workflow debug run finishes.
Follow-up to SSR prefetch migration (2833965). Eliminates the Zustand
middleman that was syncing TanStack Query data into a separate store.
- Remove useGlobalPublicStore Zustand store entirely
- Create hooks/use-global-public.ts with useSystemFeatures,
useSystemFeaturesQuery, useIsSystemFeaturesPending, useSetupStatusQuery
- Migrate all 93 consumers to import from @/hooks/use-global-public
- Simplify global-public-context.tsx to a thin provider component
- Update 18 test files to mock the new hook interface
- Fix SetupStatusResponse.setup_at type from Date to string (JSON)
- Fix setup-status.spec.ts mock target to match consoleClient
BREAKING CHANGE: useGlobalPublicStore is removed. Use useSystemFeatures()
from @/hooks/use-global-public instead.
BREAKING CHANGE: commonLayout is now an async Server Component that
prefetches user-profile and current-workspace on the server via
TanStack Query's prefetchQuery + HydrationBoundary pattern. This
replaces the previous purely client-side data fetching approach.
Key changes:
- **SSR data prefetch (root layout)**: prefetch systemFeatures and
setupStatus in the root layout server component, wrap children with
HydrationBoundary to hydrate TanStack Query cache on the client.
- **SSR data prefetch (commonLayout)**: convert commonLayout from a
client component to an async server component that prefetches
user-profile (with x-version/x-env response headers) and
current-workspace. Client-side providers/UI extracted to a new
layout-client.tsx component.
- **Add loading.tsx (Next.js convention)**: add a Next.js loading.tsx
file in commonLayout that shows a centered spinner. This replaces the
deleted Splash component but works via Next.js built-in Suspense
boundary for route segments, not a client-side overlay.
- **Extract shared SSR fetch utilities (utils/ssr-fetch.ts)**: create
serverFetch (unauthenticated) and serverFetchWithAuth (with cookie
forwarding + CSRF token). getAuthHeaders is wrapped with React.cache()
for per-request deduplication across multiple SSR fetches.
- **Refactor AppInitializer**: split single monolithic async IIFE effect
into three independent useEffects (oauth tracking, education verify,
setup status check). Use useReducer for init flag, useRef to prevent
duplicate tracking in StrictMode. Now reads setupStatus from TanStack
Query cache (useSetupStatusQuery) instead of fetching independently.
- **Refactor global-public-context**: move Zustand store sync from
queryFn side-effect to a dedicated useEffect, keeping queryFn pure.
fetchSystemFeatures now simply returns the API response.
- **Fix usePSInfo SSR crash**: defer globalThis.location access from
hook top-level to callback execution time via getDomain() helper,
preventing "Cannot read properties of undefined" during server render.
- **Remove Splash component**: delete the client-side loading overlay
that relied on useIsLogin polling, replaced by Next.js loading.tsx.
- **Remove staleTime/gcTime overrides in useUserProfile**: allow the
SSR-prefetched data to be reused via default cache policy instead of
forcing refetch on every mount.
- **Revert middleware auth guard**: remove the cookie-based session
check in proxy.ts that caused false redirects to /signin for
authenticated users (Dify's auth uses token refresh, not simple
cookie presence).
- Updated API routes to use app_id instead of sandbox_id for file operations, aligning with user-specific sandbox workspaces.
- Enhanced SandboxFileService and related classes to accommodate app_id in file listing and download functionalities.
- Refactored storage key generation for sandbox archives to include app_id, ensuring proper file organization.
- Adjusted frontend contracts and services to reflect the new app_id parameter in API calls.
Wire up the "Create Blank Skill" action card to open a modal where
users enter a skill name. The modal validates against existing skill
names in real-time and creates a folder with a SKILL.md file via
batchUpload, then opens the file as a pinned tab.
Add `enabled` parameter to tool query hooks so non-plugin nodes
(LLM, Code, IfElse, etc.) avoid registering React Query observers.
Extract shared matching functions into plugin-install-check utils to
eliminate duplicate logic between the hook and the checklist.
- Add BundleManifest with dsl_filename for 100% tree ID restoration
- Implement two-step import flow: prepare (get upload URL) + confirm
- Use sandbox for zip extraction and file upload via presigned URLs
- Store import session in Redis with 1h TTL
- Add SandboxUploadItem for symmetric download/upload API
- Remove legacy source_zip_extractor, inline logic in service
- Update frontend to use new prepare/confirm API flow
The toolbar download button now uses the already-fetched download URL
from useQuery (zero extra requests), while tree node downloads keep
using useMutation with React Query-managed isPending state instead of
a hand-rolled useState wrapper.
Implement ReadOnlyFilePreview to render sandbox files by type
(code, markdown, image, video, SQLite, unsupported) using existing
skill viewer components with readOnly support. Add
useSandboxFileDownloadUrl and useFetchTextContent hooks for data
fetching, and generalize useFileTypeInfo to accept any file-like
object.
Enhance getFileIconType to accept an extension parameter and cover all
13 FileAppearanceTypeEnum types using an O(1) Map lookup. Update all
call sites to pass the API-provided extension for accurate icon display.
Change onSuccess to onSettled for upload mutations so the file tree
refreshes regardless of success or failure, ensuring consistency when
backend creates nodes but storage upload fails.