diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json
index 3252fe193fd..4bdd3ebfec8 100644
--- a/oxlint-suppressions.json
+++ b/oxlint-suppressions.json
@@ -5082,11 +5082,6 @@
"count": 4
}
},
- "web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts": {
- "@tanstack/query/prefer-query-options": {
- "count": 1
- }
- },
"web/features/agent-v2/agent-detail/logs/__tests__/page.spec.tsx": {
"@tanstack/query/prefer-query-options": {
"count": 1
diff --git a/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx b/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx
index e9673e63cee..c6597e09d95 100644
--- a/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx
@@ -535,10 +535,26 @@ vi.mock('../components/preview/header', () => ({
}))
vi.mock('../components/preview/versions-panel', () => ({
- AgentPreviewVersionsPanel: (props: { onSelectVersion: (versionId: string) => void }) => (
-
+ AgentPreviewVersionsPanel: (props: {
+ onBeforeRestore?: () => Promise
+ onSelectVersion: (versionId: string | null) => void
+ onVersionRestored?: () => Promise
+ }) => (
+ <>
+
+
+ >
),
}))
@@ -2859,6 +2875,64 @@ describe('AgentConfigurePage', () => {
expect(screen.queryByRole('region', { name: 'build-draft-bar' })).not.toBeInTheDocument()
})
+ it('should save pending draft edits before restoring from the version menu and rebase the composer', async () => {
+ const user = userEvent.setup()
+ const queryClient = createQueryClient()
+ const draftSave = createDeferredPromise<{ agent_soul: object }>()
+ mocks.saveComposerDraft.mockReturnValue(draftSave.promise)
+ const refetchComposer = vi.fn(async () => {
+ mocks.queryState.composer = {
+ ...mocks.queryState.composer,
+ data: {
+ agent_soul: {
+ prompt: { system_prompt: 'restored prompt' },
+ },
+ },
+ }
+ return {}
+ })
+ mocks.queryState.composer = {
+ data: {
+ agent_soul: {
+ prompt: { system_prompt: 'draft prompt' },
+ },
+ },
+ isFetching: false,
+ isError: false,
+ isPending: false,
+ isSuccess: true,
+ refetch: refetchComposer,
+ }
+
+ render(
+
+
+ ,
+ )
+
+ await user.click(screen.getByRole('button', { name: 'edit prompt' }))
+ await user.click(screen.getByRole('button', { name: 'open versions' }))
+ await user.click(screen.getByRole('button', { name: 'restore from version menu' }))
+
+ expect(mocks.saveComposerDraft).toHaveBeenCalledTimes(1)
+ expect(refetchComposer).not.toHaveBeenCalled()
+ expect(screen.getByRole('region', { name: 'orchestrate-panel' })).toHaveTextContent(
+ 'prompt:edited draft prompt',
+ )
+
+ draftSave.resolve({ agent_soul: {} })
+
+ await waitFor(() => {
+ expect(screen.getByRole('region', { name: 'orchestrate-panel' })).toHaveTextContent(
+ 'prompt:restored prompt',
+ )
+ })
+ expect(refetchComposer).toHaveBeenCalledTimes(1)
+ expect(screen.getByRole('region', { name: 'orchestrate-panel' })).toHaveTextContent(
+ 'readonly:no',
+ )
+ })
+
it('should rebase the composer from the restored version', async () => {
const user = userEvent.setup()
const queryClient = createQueryClient()
diff --git a/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-build-draft.spec.tsx b/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-build-draft.spec.tsx
new file mode 100644
index 00000000000..08040d8c76b
--- /dev/null
+++ b/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-build-draft.spec.tsx
@@ -0,0 +1,101 @@
+import type { PropsWithChildren } from 'react'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { act, renderHook, waitFor } from '@testing-library/react'
+import { useAgentConfigureBuildDraftData } from '../use-agent-configure-build-draft'
+
+const mocks = vi.hoisted(() => ({
+ request: vi.fn(),
+ toastError: vi.fn(),
+}))
+
+vi.mock('@/app/notifications', () => ({
+ toast: { error: mocks.toastError },
+}))
+
+vi.mock('@/service/console', () => ({
+ consoleQuery: {
+ agent: {
+ byAgentId: {
+ buildDraft: {
+ get: {
+ queryOptions: ({ context }: { context?: { silent?: boolean } }) => ({
+ queryKey: ['agent', 'agent-1', 'build-draft'],
+ queryFn: async () => {
+ try {
+ return await mocks.request()
+ } catch (error) {
+ if (!context?.silent) mocks.toastError('Request failed')
+ throw error
+ }
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+}))
+
+function setup() {
+ const queryClient = new QueryClient({
+ defaultOptions: { queries: { retry: false } },
+ })
+ const setSoulSourceOverride = vi.fn()
+ const wrapper = ({ children }: PropsWithChildren) => (
+ {children}
+ )
+ const hook = renderHook(
+ () =>
+ useAgentConfigureBuildDraftData({
+ agentId: 'agent-1',
+ activeVersionId: 'version-1',
+ isBuildMode: true,
+ isViewingVersion: false,
+ setSoulSourceOverride,
+ soulSourceOverride: null,
+ }),
+ { wrapper },
+ )
+
+ return { ...hook, setSoulSourceOverride }
+}
+
+describe('build draft refresh errors', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ mocks.request.mockReset()
+ })
+
+ it('returns to the normal draft without a toast when a later refresh finds no build draft', async () => {
+ mocks.request.mockResolvedValueOnce({ draft: { id: 'build-draft-1' } })
+ const { result, setSoulSourceOverride } = setup()
+ await waitFor(() => expect(result.current.isActive).toBe(true))
+
+ const notFound = new Response(null, { status: 404 })
+ mocks.request.mockRejectedValueOnce(notFound)
+ await act(async () => {
+ const refreshed = await result.current.refetch()
+ expect(refreshed.error).toBe(notFound)
+ })
+
+ await waitFor(() => expect(result.current.soulSource).toBe('draft'))
+ expect(setSoulSourceOverride).toHaveBeenCalledWith('draft')
+ expect(mocks.toastError).not.toHaveBeenCalled()
+ })
+
+ it('still notifies when refreshing the build draft fails unexpectedly', async () => {
+ mocks.request.mockResolvedValueOnce({ draft: { id: 'build-draft-1' } })
+ const { result, setSoulSourceOverride } = setup()
+ await waitFor(() => expect(result.current.isActive).toBe(true))
+
+ const serverError = new Response(null, { status: 500 })
+ mocks.request.mockRejectedValueOnce(serverError)
+ await act(async () => {
+ const refreshed = await result.current.refetch()
+ expect(refreshed.error).toBe(serverError)
+ })
+
+ expect(mocks.toastError).toHaveBeenCalledTimes(1)
+ expect(setSoulSourceOverride).not.toHaveBeenCalled()
+ })
+})
diff --git a/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx b/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx
index 0cf1139cd32..f996b9a5b83 100644
--- a/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx
@@ -628,6 +628,22 @@ function AgentConfigurePageComposerContent({
agentId={agentId}
activeVersionId={activeVersionId}
onSelectVersion={selectVersion}
+ restoreDisabled={
+ buildDraft.isActive ||
+ buildDraftActionsDisabled ||
+ isEnteringBuildMode ||
+ isPublishing
+ }
+ onBeforeRestore={async () => {
+ if (!isViewingVersion) {
+ await waitForPendingPreviewDraftSave()
+ await saveDraft()
+ }
+ }}
+ onVersionRestored={async () => {
+ await composerQuery.refetch()
+ onComposerRebase()
+ }}
onClose={() => setShowPreviewVersions(false)}
/>
)}
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx
index 954167d03ee..59545c03e78 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx
@@ -14,11 +14,26 @@ import {
agentComposerSavedDraftAtom,
} from '@/features/agent-v2/agent-composer/store'
import { agentComposerPromptAtom } from '@/features/agent-v2/agent-composer/store-modules/prompt'
+import { consoleQuery } from '@/service/console'
+import { createNuqsTestWrapper } from '@/test/nuqs-testing'
import { AgentConfigurePublishBar } from '../publish-bar'
type PublishHandler = NonNullable['onPublish']>
type PublishMock = Mock
+const restoreAccess = vi.hoisted(() => ({
+ canRestore: true,
+ plan: 'professional',
+ onUrlUpdate: vi.fn(),
+}))
+vi.mock('@/features/agent-v2/permissions', () => ({
+ useAgentPermissions: () => ({ canReleaseAndVersion: restoreAccess.canRestore }),
+}))
+vi.mock('@/features/system-features/state', async () => {
+ const { atom } = await import('jotai')
+ return { deploymentEditionAtom: atom('CLOUD') }
+})
+
const hotkeyRegistrations = vi.hoisted(
() =>
new Map<
@@ -84,8 +99,24 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
+vi.mock('@/features/system-features/client', () => ({
+ systemFeaturesQueryOptions: () => ({
+ queryKey: ['system-features'],
+ queryFn: async () => ({ deployment_edition: 'CLOUD' }),
+ }),
+}))
+
vi.mock('@/service/console', () => ({
consoleQuery: {
+ features: {
+ get: {
+ queryOptions: (options: Record) => ({
+ ...options,
+ queryKey: ['features'],
+ queryFn: async () => ({ billing: { subscription: { plan: restoreAccess.plan } } }),
+ }),
+ },
+ },
agent: {
byAgentId: {
get: {
@@ -137,7 +168,10 @@ vi.mock('@/service/console', () => ({
byVersionId: {
restore: {
post: {
- mutationOptions: () => ({ mutationFn: restoreVersionMutation }),
+ mutationOptions: (options: Record) => ({
+ ...options,
+ mutationFn: restoreVersionMutation,
+ }),
},
},
},
@@ -239,6 +273,10 @@ function renderPublishBar({
mutations: { retry: false },
},
})
+ queryClient.setQueryData(consoleQuery.features.get.queryOptions({}).queryKey, {
+ billing: { subscription: { plan: restoreAccess.plan } },
+ })
+ const { wrapper: NuqsWrapper } = createNuqsTestWrapper({ onUrlUpdate: restoreAccess.onUrlUpdate })
const store = createStore()
store.set(agentComposerPromptAtom, prompt)
setupStore?.(store)
@@ -270,20 +308,22 @@ function renderPublishBar({
}
const renderPublishBarTree = (nextProps?: { isPublishing?: boolean }) => (
-
-
-
-
-
+
+
+
+
+
+
+
)
const view = render(renderPublishBarTree())
@@ -301,6 +341,8 @@ describe('AgentConfigurePublishBar', () => {
beforeEach(() => {
vi.clearAllMocks()
hotkeyRegistrations.clear()
+ restoreAccess.canRestore = true
+ restoreAccess.plan = 'professional'
restoreVersionMutation.mockResolvedValue({
active_config_snapshot_id: 'snapshot-2',
result: 'success',
@@ -393,8 +435,13 @@ describe('AgentConfigurePublishBar', () => {
expect(screen.getByText('Stable version')).toBeInTheDocument()
expect(screen.getByText('agentV2.agentDetail.versionHistory.viewOnly')).toBeInTheDocument()
expect(screen.getByText('formatted:1710000000 · Alice')).toBeInTheDocument()
- fireEvent.click(
- screen.getByRole('button', { name: 'agentV2.agentDetail.versionHistory.restore' }),
+ const user = userEvent.setup()
+ await user.click(
+ screen.getByRole('button', { name: /agentV2.agentDetail.versionHistory.restore/ }),
+ )
+ expect(restoreVersionMutation).not.toHaveBeenCalled()
+ await user.click(
+ within(await screen.findByRole('alertdialog')).getByRole('button', { name: /restore/i }),
)
await waitFor(() => {
@@ -413,6 +460,75 @@ describe('AgentConfigurePublishBar', () => {
expect(toastMock.success).toHaveBeenCalledWith('common.api.actionSuccess')
})
+ it('shows the agent upgrade dialog before opening pricing on the sandbox plan', async () => {
+ restoreAccess.plan = 'sandbox'
+ const user = userEvent.setup()
+ const { onExitVersions, onVersionRestored } = renderPublishBar({
+ selectedVersionSnapshot: activeConfigSnapshot,
+ })
+ await user.click(
+ screen.getByRole('button', { name: /agentV2.agentDetail.versionHistory.restore/ }),
+ )
+ const dialog = await screen.findByRole('dialog', { name: 'billing.upgrade.agentRestore.title' })
+ expect(dialog).toHaveAccessibleDescription('billing.upgrade.agentRestore.description')
+ expect(restoreAccess.onUrlUpdate).not.toHaveBeenCalled()
+ expect(restoreVersionMutation).not.toHaveBeenCalled()
+ await user.click(
+ within(dialog).getByRole('button', { name: 'billing.triggerLimitModal.upgrade' }),
+ )
+ expect(restoreAccess.onUrlUpdate).toHaveBeenCalledWith(
+ expect.objectContaining({ queryString: '?pricing=open' }),
+ )
+ await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument())
+ expect(restoreVersionMutation).not.toHaveBeenCalled()
+ expect(onExitVersions).not.toHaveBeenCalled()
+ expect(onVersionRestored).not.toHaveBeenCalled()
+ })
+
+ it('prevents duplicate restoration and cancellation while the request is pending', async () => {
+ const deferred = createDeferredPromise()
+ restoreVersionMutation.mockImplementationOnce(async () => {
+ await deferred.promise
+ return { active_config_snapshot_id: 'snapshot-2', result: 'success' }
+ })
+ const user = userEvent.setup()
+ const { onExitVersions } = renderPublishBar({ selectedVersionSnapshot: activeConfigSnapshot })
+ await user.click(
+ screen.getByRole('button', { name: /agentV2.agentDetail.versionHistory.restore/ }),
+ )
+ const dialog = await screen.findByRole('alertdialog')
+ const confirm = within(dialog).getByRole('button', { name: /restore/i })
+ await user.click(confirm)
+ await waitFor(() => expect(confirm).toHaveAttribute('aria-disabled', 'true'))
+ expect(within(dialog).getByRole('button', { name: /cancel/i })).toBeDisabled()
+ await user.click(confirm)
+ expect(restoreVersionMutation).toHaveBeenCalledTimes(1)
+ expect(onExitVersions).not.toHaveBeenCalled()
+ await act(async () => {
+ deferred.resolve()
+ await deferred.promise
+ })
+ await waitFor(() => expect(onExitVersions).toHaveBeenCalledTimes(1))
+ })
+
+ it('keeps the selected version open when restoration fails', async () => {
+ restoreVersionMutation.mockRejectedValueOnce(new Error('Restore failed'))
+ const user = userEvent.setup()
+ const { onExitVersions, onVersionRestored } = renderPublishBar({
+ selectedVersionSnapshot: activeConfigSnapshot,
+ })
+ await user.click(
+ screen.getByRole('button', { name: /agentV2.agentDetail.versionHistory.restore/ }),
+ )
+ await user.click(
+ within(await screen.findByRole('alertdialog')).getByRole('button', { name: /restore/i }),
+ )
+ await waitFor(() => expect(restoreVersionMutation).toHaveBeenCalledTimes(1))
+ expect(onExitVersions).not.toHaveBeenCalled()
+ expect(onVersionRestored).not.toHaveBeenCalled()
+ expect(screen.getByRole('alertdialog')).toBeInTheDocument()
+ })
+
it('should render saved time from the latest draft save timestamp', () => {
renderPublishBar({ draftSavedAt: 1710000100000 })
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx
index 5efe1ed2266..6c643b2eaab 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx
@@ -12,7 +12,7 @@ import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd'
import { StatusDot } from '@langgenius/dify-ui/status-dot'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { formatForDisplay, useHotkey } from '@tanstack/react-hotkeys'
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
+import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
import { useId, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -21,6 +21,8 @@ import { isAgentComposerDirtyAtom } from '@/features/agent-v2/agent-composer/sto
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
import useTimestamp from '@/hooks/use-timestamp'
import { consoleQuery } from '@/service/console'
+import { AgentVersionRestoreDialogs } from '../../preview/versions-panel/restore-dialogs'
+import { useAgentVersionRestore } from '../../preview/versions-panel/use-agent-version-restore'
import { AgentPublishImpactDetails } from './publish-impact-details'
const PUBLISH_AGENT_HOTKEY = 'Mod+Shift+P' satisfies Hotkey
@@ -133,57 +135,15 @@ export function AgentConfigurePublishBar({
enabled: publishIsAvailable && !isPublishing && !selectedVersionSnapshot,
})
useQuery(workflowReferencesQueryOptions)
- const restoreVersionMutation = useMutation(
- consoleQuery.agent.byAgentId.versions.byVersionId.restore.post.mutationOptions(),
- )
+ const restore = useAgentVersionRestore({
+ agentId,
+ onRestored: async () => {
+ await onVersionRestored?.()
+ onExitVersions?.()
+ },
+ })
const canPublish = publishIsAvailable && !isPublishing
- const handleRestoreVersion = (versionId: string) => {
- if (restoreVersionMutation.isPending) return
-
- restoreVersionMutation.mutate(
- {
- params: {
- agent_id: agentId,
- version_id: versionId,
- },
- },
- {
- onSuccess: async () => {
- await Promise.all([
- queryClient.invalidateQueries({
- queryKey: consoleQuery.agent.byAgentId.get.queryKey({
- input: {
- params: {
- agent_id: agentId,
- },
- },
- }),
- }),
- queryClient.invalidateQueries({
- queryKey: consoleQuery.agent.byAgentId.composer.get.queryKey({
- input: {
- params: {
- agent_id: agentId,
- },
- },
- }),
- }),
- queryClient.invalidateQueries({
- queryKey: consoleQuery.agent.byAgentId.versions.get.key(),
- }),
- ])
- await onVersionRestored?.()
- onExitVersions?.()
- toast.success(tCommon(($) => $['api.actionSuccess']))
- },
- onError: () => {
- toast.error(tCommon(($) => $['api.actionFailed']))
- },
- },
- )
- }
-
const handlePublish = async () => {
if (!canPublish) return
@@ -237,12 +197,27 @@ export function AgentConfigurePublishBar({
if (selectedVersionSnapshot) {
return (
-
+ <>
+ restore.requestRestore(selectedVersionSnapshot) : undefined
+ }
+ />
+
+ >
)
}
@@ -420,11 +395,13 @@ function PublishBarActions({
function AgentVersionRestoreBar({
version,
isRestoring = false,
+ restoreDisabled,
onExitVersions,
onRestoreVersion,
}: {
version: AgentConfigSnapshotSummaryResponse
isRestoring?: boolean
+ restoreDisabled?: boolean
onExitVersions?: () => void
onRestoreVersion?: (versionId: string) => void
}) {
@@ -461,9 +438,9 @@ function AgentVersionRestoreBar({
- {onExport && (
+ {(onExport || onRestore) && (
- onExport(version.id)}
- className="gap-2"
- >
-
- {t(($) => $.exportApp, { ns: 'app' })}
- {showUpgrade && (
-
- {t(($) => $['upgradeBtn.encourageShort'], { ns: 'billing' })}
-
- )}
-
+ {onRestore && (
+ onRestore(version)}
+ className="gap-2"
+ >
+
+ {tWorkflow(($) => $['common.restore'])}
+ {showUpgrade && (
+
+ {t(($) => $['upgradeBtn.encourageShort'], { ns: 'billing' })}
+
+ )}
+
+ )}
+ {onExport && (
+ onExport(version.id)}
+ className="gap-2"
+ >
+
+ {t(($) => $.exportApp, { ns: 'app' })}
+ {showUpgrade && (
+
+ {t(($) => $['upgradeBtn.encourageShort'], { ns: 'billing' })}
+
+ )}
+
+ )}
)}
diff --git a/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts b/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts
index 4c09def0579..c62c08ceb11 100644
--- a/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts
+++ b/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts
@@ -11,7 +11,7 @@ import type {
AgentFileNode,
AgentSoulConfigFormState,
} from '@/features/agent-v2/agent-composer/form-state'
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
+import { queryOptions, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import isEqual from 'fast-deep-equal'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -156,51 +156,42 @@ export function useAgentConfigureBuildDraftData({
setSoulSourceOverride: (source: AgentConfigureSoulSource | null) => void
soulSourceOverride: AgentConfigureSoulSource | null
}) {
- const shouldSilenceBuildDraftCheckRef = useRef(true)
+ const { t } = useTranslation('common')
const buildDraftQueryInput = {
params: {
agent_id: agentId,
},
}
const buildDraftQueryOptions = consoleQuery.agent.byAgentId.buildDraft.get.queryOptions({
- input: {
- params: buildDraftQueryInput.params,
- },
- context: {},
- })
- const silentBuildDraftQueryOptions = consoleQuery.agent.byAgentId.buildDraft.get.queryOptions({
input: {
params: buildDraftQueryInput.params,
},
context: {
silent: true,
},
- queryKey: buildDraftQueryOptions.queryKey,
- })
- const buildDraftQuery = useQuery({
- ...buildDraftQueryOptions,
- enabled:
- isBuildMode &&
- !isViewingVersion &&
- soulSourceOverride !== 'draft' &&
- soulSourceOverride !== 'view-version',
- queryFn: async (context) => {
- try {
- const queryOptions = shouldSilenceBuildDraftCheckRef.current
- ? silentBuildDraftQueryOptions
- : buildDraftQueryOptions
-
- shouldSilenceBuildDraftCheckRef.current = false
- return await queryOptions.queryFn(context)
- } catch (error) {
- if (isNotFoundResponse(error)) setSoulSourceOverride('draft')
- throw error
- }
- },
- retry: false,
- refetchOnReconnect: false,
- refetchOnWindowFocus: false,
})
+ const buildDraftQuery = useQuery(
+ queryOptions({
+ ...buildDraftQueryOptions,
+ enabled:
+ isBuildMode &&
+ !isViewingVersion &&
+ soulSourceOverride !== 'draft' &&
+ soulSourceOverride !== 'view-version',
+ queryFn: async (context) => {
+ try {
+ return await buildDraftQueryOptions.queryFn(context)
+ } catch (error) {
+ if (isNotFoundResponse(error)) setSoulSourceOverride('draft')
+ else toast.error(t(($) => $['api.actionFailed']))
+ throw error
+ }
+ },
+ retry: false,
+ refetchOnReconnect: false,
+ refetchOnWindowFocus: false,
+ }),
+ )
const {
data: buildDraftData,
dataUpdatedAt: buildDraftDataUpdatedAt,
diff --git a/web/i18n/locales/ar-TN/billing.json b/web/i18n/locales/ar-TN/billing.json
index 291b2bea519..d6ed2f1f5e3 100644
--- a/web/i18n/locales/ar-TN/billing.json
+++ b/web/i18n/locales/ar-TN/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "أحداث المشغل",
"upgrade.addChunks.description": "لقد وصلت إلى الحد الأقصى لإضافة الأجزاء لهذا الخطة.",
"upgrade.addChunks.title": "قم بالترقية لمواصلة إضافة المقاطع",
+ "upgrade.agentRestore.description": "استعادة إصدارات تطبيق الوكيل غير متاحة في خطتك الحالية.",
+ "upgrade.agentRestore.title": "قم بالترقية لاستعادة إصدارات تطبيق الوكيل",
"upgrade.uploadMultipleFiles.description": "ارفع عدة مستندات دفعة واحدة وزِد الحد الأقصى لحجم كل ملف إلى 50 MB.",
"upgrade.uploadMultipleFiles.title": "قم بالترقية لإتاحة رفع الملفات دفعة واحدة والملفات الأكبر حجمًا",
"upgrade.uploadMultiplePages.description": "لقد وصلت إلى حد التحميل — يمكن اختيار ورفع مستند واحد فقط في كل مرة على الخطة الحالية الخاصة بك.",
diff --git a/web/i18n/locales/az-AZ/billing.json b/web/i18n/locales/az-AZ/billing.json
index 0ff11c7b562..94d4c5a681b 100644
--- a/web/i18n/locales/az-AZ/billing.json
+++ b/web/i18n/locales/az-AZ/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "Tətikləmə hadisələri",
"upgrade.addChunks.description": "Bu plan üzrə fraqment əlavə etmə limitinə çatmısınız.",
"upgrade.addChunks.title": "Fraqment əlavə etməyə davam etmək üçün planın yüksəldilməsi",
+ "upgrade.agentRestore.description": "Cari planınızda agent tətbiqinin versiyalarının bərpası əlçatan deyil.",
+ "upgrade.agentRestore.title": "Agent tətbiqinin versiyalarını bərpa etmək üçün planın yüksəldilməsi",
"upgrade.uploadMultipleFiles.description": "Bir neçə sənədi eyni anda yüklə və hər faylın maksimum ölçüsünü 50 MB-a qədər artır.",
"upgrade.uploadMultipleFiles.title": "Toplu yükləmə və daha böyük fayllar üçün planın yüksəldilməsi",
"upgrade.uploadMultiplePages.description": "Yükləmə limitinə çatmısınız: cari planınızda eyni anda yalnız bir sənəd seçib yükləyə bilərsiniz.",
diff --git a/web/i18n/locales/de-DE/billing.json b/web/i18n/locales/de-DE/billing.json
index 7c2d546157d..2ee83981b93 100644
--- a/web/i18n/locales/de-DE/billing.json
+++ b/web/i18n/locales/de-DE/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "AUSLÖSEEREIGNISSE",
"upgrade.addChunks.description": "Sie haben das Limit für das Hinzufügen von Abschnitten in diesem Tarif erreicht.",
"upgrade.addChunks.title": "Upgraden, um weiterhin Abschnitte hinzuzufügen",
+ "upgrade.agentRestore.description": "Die Wiederherstellung von Versionen der Agenten-App ist in Ihrem aktuellen Tarif nicht verfügbar.",
+ "upgrade.agentRestore.title": "Upgraden, um Versionen der Agenten-App wiederherzustellen",
"upgrade.uploadMultipleFiles.description": "Laden Sie mehrere Dokumente gleichzeitig hoch und erhöhen Sie die maximale Größe pro Datei auf 50 MB.",
"upgrade.uploadMultipleFiles.title": "Upgrade durchführen, um Batch-Uploads und größere Dateien freizuschalten",
"upgrade.uploadMultiplePages.description": "Sie haben das Upload-Limit erreicht – in Ihrem aktuellen Tarif kann jeweils nur ein Dokument ausgewählt und hochgeladen werden.",
diff --git a/web/i18n/locales/en-US/billing.json b/web/i18n/locales/en-US/billing.json
index e083ccd185e..04cc06479a6 100644
--- a/web/i18n/locales/en-US/billing.json
+++ b/web/i18n/locales/en-US/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "TRIGGER EVENTS",
"upgrade.addChunks.description": "You’ve reached the limit of adding chunks for this plan.",
"upgrade.addChunks.title": "Upgrade to continue adding chunks",
+ "upgrade.agentRestore.description": "Agent app version restoration is not available on your current plan.",
+ "upgrade.agentRestore.title": "Upgrade to restore agent app versions",
"upgrade.uploadMultipleFiles.description": "Upload multiple documents at once and increase the maximum size per file to 50 MB.",
"upgrade.uploadMultipleFiles.title": "Upgrade to unlock batch uploads and larger files",
"upgrade.uploadMultiplePages.description": "You’ve reached the upload limit — only one document can be selected and uploaded at a time on your current plan.",
diff --git a/web/i18n/locales/es-ES/billing.json b/web/i18n/locales/es-ES/billing.json
index f0e9c648e88..0cce83c59ee 100644
--- a/web/i18n/locales/es-ES/billing.json
+++ b/web/i18n/locales/es-ES/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "EVENTOS DESENCADENANTES",
"upgrade.addChunks.description": "Has alcanzado el límite de agregar fragmentos para este plan.",
"upgrade.addChunks.title": "Actualiza para seguir agregando fragmentos",
+ "upgrade.agentRestore.description": "La restauración de versiones de la aplicación de agente no está disponible en tu plan actual.",
+ "upgrade.agentRestore.title": "Actualiza para restaurar versiones de la aplicación de agente",
"upgrade.uploadMultipleFiles.description": "Sube varios documentos a la vez y aumenta el tamaño máximo por archivo a 50 MB.",
"upgrade.uploadMultipleFiles.title": "Mejora tu plan para desbloquear las cargas por lotes y los archivos de mayor tamaño",
"upgrade.uploadMultiplePages.description": "Has alcanzado el límite de carga: solo se puede seleccionar y subir un documento a la vez en tu plan actual.",
diff --git a/web/i18n/locales/fa-IR/billing.json b/web/i18n/locales/fa-IR/billing.json
index 996579466e7..4ef916cee0b 100644
--- a/web/i18n/locales/fa-IR/billing.json
+++ b/web/i18n/locales/fa-IR/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "رویدادهای محرک",
"upgrade.addChunks.description": "شما به حد اضافه کردن بخشها برای این طرح رسیدهاید.",
"upgrade.addChunks.title": "برای ادامه افزودن بخشها ارتقا دهید",
+ "upgrade.agentRestore.description": "بازیابی نسخههای برنامهٔ عامل در طرح فعلی شما در دسترس نیست.",
+ "upgrade.agentRestore.title": "برای بازیابی نسخههای برنامهٔ عامل ارتقا دهید",
"upgrade.uploadMultipleFiles.description": "چند سند را بهطور همزمان بارگذاری کنید و حداکثر اندازه هر فایل را به 50 MB افزایش دهید.",
"upgrade.uploadMultipleFiles.title": "برای فعالکردن بارگذاری گروهی و فایلهای بزرگتر، ارتقا دهید",
"upgrade.uploadMultiplePages.description": "شما به حد آپلود رسیدهاید — در طرح فعلی خود تنها میتوانید یک سند را در هر بار انتخاب و آپلود کنید.",
diff --git a/web/i18n/locales/fr-FR/billing.json b/web/i18n/locales/fr-FR/billing.json
index a3d3b2504f7..2bc33c3486a 100644
--- a/web/i18n/locales/fr-FR/billing.json
+++ b/web/i18n/locales/fr-FR/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "ÉVÉNEMENTS DÉCLENCHEURS",
"upgrade.addChunks.description": "Vous avez atteint la limite d'ajout de morceaux pour ce plan.",
"upgrade.addChunks.title": "Mettez à niveau pour continuer à ajouter des morceaux",
+ "upgrade.agentRestore.description": "La restauration des versions de l’application d’agent n'est pas disponible avec votre plan actuel.",
+ "upgrade.agentRestore.title": "Mettez à niveau pour restaurer les versions de l’application d’agent",
"upgrade.uploadMultipleFiles.description": "Importez plusieurs documents à la fois et augmentez la taille maximale par fichier à 50 MB.",
"upgrade.uploadMultipleFiles.title": "Passez à une offre supérieure pour débloquer les importations groupées et les fichiers plus volumineux",
"upgrade.uploadMultiplePages.description": "Vous avez atteint la limite de téléchargement — un seul document peut être sélectionné et téléchargé à la fois avec votre abonnement actuel.",
diff --git a/web/i18n/locales/hi-IN/billing.json b/web/i18n/locales/hi-IN/billing.json
index 8e8bdcbd2fe..faa8e515a55 100644
--- a/web/i18n/locales/hi-IN/billing.json
+++ b/web/i18n/locales/hi-IN/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "ट्रिगर घटनाएँ",
"upgrade.addChunks.description": "आप इस योजना के लिए टुकड़े जोड़ने की सीमा तक पहुँच चुके हैं।",
"upgrade.addChunks.title": "अधिक चंक्स जोड़ने के लिए अपग्रेड करें",
+ "upgrade.agentRestore.description": "आपकी वर्तमान योजना में एजेंट ऐप संस्करण पुनर्स्थापना उपलब्ध नहीं है।",
+ "upgrade.agentRestore.title": "एजेंट ऐप संस्करणों को पुनर्स्थापित करने के लिए अपग्रेड करें",
"upgrade.uploadMultipleFiles.description": "एक साथ कई दस्तावेज़ अपलोड करें और प्रति फ़ाइल अधिकतम साइज़ सीमा बढ़ाकर 50 MB करें।",
"upgrade.uploadMultipleFiles.title": "बैच अपलोड और बड़ी फ़ाइलों की सुविधा अनलॉक करने के लिए अपग्रेड करें",
"upgrade.uploadMultiplePages.description": "आपने अपलोड की सीमा तक पहुँच लिया है — आपके वर्तमान प्लान पर एक समय में केवल एक ही दस्तावेज़ चुना और अपलोड किया जा सकता है।",
diff --git a/web/i18n/locales/id-ID/billing.json b/web/i18n/locales/id-ID/billing.json
index f0b6c986624..5af8b7c650c 100644
--- a/web/i18n/locales/id-ID/billing.json
+++ b/web/i18n/locales/id-ID/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "PERISTIWA PEMICU",
"upgrade.addChunks.description": "Anda telah mencapai batas penambahan potongan untuk paket ini.",
"upgrade.addChunks.title": "Tingkatkan untuk terus menambahkan potongan",
+ "upgrade.agentRestore.description": "Pemulihan versi aplikasi agen tidak tersedia di paket Anda saat ini.",
+ "upgrade.agentRestore.title": "Tingkatkan untuk memulihkan versi aplikasi agen",
"upgrade.uploadMultipleFiles.description": "Upload beberapa dokumen sekaligus dan tingkatkan ukuran maksimum per file menjadi 50 MB.",
"upgrade.uploadMultipleFiles.title": "Upgrade untuk membuka upload batch dan file berukuran lebih besar",
"upgrade.uploadMultiplePages.description": "Anda telah mencapai batas unggah — hanya satu dokumen yang dapat dipilih dan diunggah sekaligus dengan paket Anda saat ini.",
diff --git a/web/i18n/locales/it-IT/billing.json b/web/i18n/locales/it-IT/billing.json
index 7af48590d6f..fac0800abbf 100644
--- a/web/i18n/locales/it-IT/billing.json
+++ b/web/i18n/locales/it-IT/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "EVENTI DI ATTIVAZIONE",
"upgrade.addChunks.description": "Hai raggiunto il limite di aggiunta di blocchi per questo piano.",
"upgrade.addChunks.title": "Aggiorna per continuare ad aggiungere blocchi",
+ "upgrade.agentRestore.description": "Il ripristino delle versioni dell'app agente non è disponibile nel tuo piano attuale.",
+ "upgrade.agentRestore.title": "Esegui l'upgrade per ripristinare le versioni dell'app agente",
"upgrade.uploadMultipleFiles.description": "Carica più documenti contemporaneamente e aumenta la dimensione massima per file a 50 MB.",
"upgrade.uploadMultipleFiles.title": "Passa a un piano superiore per sbloccare i caricamenti in batch e i file di dimensioni maggiori",
"upgrade.uploadMultiplePages.description": "Hai raggiunto il limite di caricamento: sul tuo piano attuale può essere selezionato e caricato un solo documento alla volta.",
diff --git a/web/i18n/locales/ja-JP/billing.json b/web/i18n/locales/ja-JP/billing.json
index 436bca4a009..c463002f26a 100644
--- a/web/i18n/locales/ja-JP/billing.json
+++ b/web/i18n/locales/ja-JP/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "TRIGGER EVENTS",
"upgrade.addChunks.description": "このプランでは、チャンク追加の上限に達しています。",
"upgrade.addChunks.title": "アップグレードして、チャンクを引き続き追加できるようにしてください。",
+ "upgrade.agentRestore.description": "現在のプランでは、エージェントアプリのバージョンの復元は利用できません。",
+ "upgrade.agentRestore.title": "アップグレードしてエージェントアプリのバージョンを復元",
"upgrade.uploadMultipleFiles.description": "複数のドキュメントを一度にアップロードでき、1ファイルあたりのサイズ上限も50 MBに引き上げられます。",
"upgrade.uploadMultipleFiles.title": "アップグレードして一括アップロードと大容量ファイルを利用",
"upgrade.uploadMultiplePages.description": "現在のプランではアップロード上限に達しています。1回の操作で選択・アップロードできるドキュメントは1つのみです。",
diff --git a/web/i18n/locales/ko-KR/billing.json b/web/i18n/locales/ko-KR/billing.json
index 7f8be34c418..0e9a21d59d2 100644
--- a/web/i18n/locales/ko-KR/billing.json
+++ b/web/i18n/locales/ko-KR/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "트리거 이벤트",
"upgrade.addChunks.description": "이 요금제에서는 더 이상 청크를 추가할 수 있는 한도에 도달했습니다.",
"upgrade.addChunks.title": "계속해서 조각을 추가하려면 업그레이드하세요",
+ "upgrade.agentRestore.description": "현재 플랜에서는 에이전트 앱 버전 복원을 사용할 수 없습니다.",
+ "upgrade.agentRestore.title": "에이전트 앱 버전을 복원하려면 업그레이드하세요",
"upgrade.uploadMultipleFiles.description": "여러 문서를 한 번에 업로드하고 파일당 최대 크기를 50MB로 늘리세요.",
"upgrade.uploadMultipleFiles.title": "업그레이드하여 일괄 업로드와 대용량 파일을 이용하세요",
"upgrade.uploadMultiplePages.description": "업로드 한도에 도달했습니다 — 현재 요금제에서는 한 번에 한 개의 문서만 선택하고 업로드할 수 있습니다.",
diff --git a/web/i18n/locales/lo-LA/billing.json b/web/i18n/locales/lo-LA/billing.json
index 0a8b63d3cf8..ed51dfa9681 100644
--- a/web/i18n/locales/lo-LA/billing.json
+++ b/web/i18n/locales/lo-LA/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "ເຫດການຕົວເລີ່ມຕົ້ນ",
"upgrade.addChunks.description": "ທ່ານໄດ້ໃຊ້ງານຮອດຂີດຈຳກັດໃນການເພີ່ມ Chunk ສຳລັບແພັກເກດນີ້ແລ້ວ.",
"upgrade.addChunks.title": "ອັບເກຣດເພື່ອເພີ່ມ Chunk ຕໍ່",
+ "upgrade.agentRestore.description": "ການກູ້ຄືນເວີຊັນແອັບ Agent ບໍ່ສາມາດໃຊ້ງານໄດ້ໃນແພັກເກດປັດຈຸບັນຂອງທ່ານ.",
+ "upgrade.agentRestore.title": "ອັບເກຣດເພື່ອກູ້ຄືນເວີຊັນແອັບ Agent",
"upgrade.uploadMultipleFiles.description": "ອັບໂຫລດເອກະສານຫຼາຍອັນພ້ອມກັນເພື່ອປະຢັດເວລາ ແລະ ເພີ່ມປະສິດທິພາບ.",
"upgrade.uploadMultipleFiles.title": "ອັບເກຣດເພື່ອປົດລັອກການອັບໂຫລດເອກະສານແບບເປັນກຸ່ມ",
"upgrade.uploadMultiplePages.description": "ທ່ານຮອດຂີດຈຳກັດການອັບໂຫລດແລ້ວ — ສາມາດເລືອກ ແລະ ອັບໂຫລດເອກະສານໄດ້ເທື່ອລະອັນໃນແພັກເກດປັດຈຸບັນ.",
diff --git a/web/i18n/locales/nl-NL/billing.json b/web/i18n/locales/nl-NL/billing.json
index d8fdb375b7c..6f31346fbdb 100644
--- a/web/i18n/locales/nl-NL/billing.json
+++ b/web/i18n/locales/nl-NL/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "TRIGGER EVENTS",
"upgrade.addChunks.description": "You’ve reached the limit of adding chunks for this plan.",
"upgrade.addChunks.title": "Upgrade to continue adding chunks",
+ "upgrade.agentRestore.description": "Het herstellen van versies van de agent-app is niet beschikbaar in je huidige abonnement.",
+ "upgrade.agentRestore.title": "Upgrade om versies van de agent-app te herstellen",
"upgrade.uploadMultipleFiles.description": "Upload meerdere documenten tegelijk en verhoog de maximale bestandsgrootte naar 50 MB.",
"upgrade.uploadMultipleFiles.title": "Upgrade je abonnement om batchuploads en grotere bestanden te ontgrendelen",
"upgrade.uploadMultiplePages.description": "You’ve reached the upload limit — only one document can be selected and uploaded at a time on your current plan.",
diff --git a/web/i18n/locales/pl-PL/billing.json b/web/i18n/locales/pl-PL/billing.json
index 566f19fc8d8..5f0ee8c2430 100644
--- a/web/i18n/locales/pl-PL/billing.json
+++ b/web/i18n/locales/pl-PL/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "WYDARZENIA WYZWALAJĄCE",
"upgrade.addChunks.description": "Osiągnąłeś limit dodawania fragmentów w tym planie.",
"upgrade.addChunks.title": "Uaktualnij, aby kontynuować dodawanie fragmentów",
+ "upgrade.agentRestore.description": "Przywracanie wersji aplikacji agenta nie jest dostępne w obecnym planie.",
+ "upgrade.agentRestore.title": "Ulepsz plan, aby przywracać wersje aplikacji agenta",
"upgrade.uploadMultipleFiles.description": "Przesyłaj wiele dokumentów jednocześnie i zwiększ maksymalny rozmiar pojedynczego pliku do 50 MB.",
"upgrade.uploadMultipleFiles.title": "Przejdź na wyższy plan, aby odblokować przesyłanie zbiorcze i większe pliki",
"upgrade.uploadMultiplePages.description": "Osiągnąłeś limit przesyłania — w ramach obecnego planu można wybrać i przesłać tylko jeden dokument naraz.",
diff --git a/web/i18n/locales/pt-BR/billing.json b/web/i18n/locales/pt-BR/billing.json
index 66901d210b6..6c1246601e3 100644
--- a/web/i18n/locales/pt-BR/billing.json
+++ b/web/i18n/locales/pt-BR/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "EVENTOS DE GATILHO",
"upgrade.addChunks.description": "Você atingiu o limite de adição de blocos para este plano.",
"upgrade.addChunks.title": "Faça upgrade para continuar adicionando blocos",
+ "upgrade.agentRestore.description": "A restauração de versões do aplicativo de agente não está disponível no seu plano atual.",
+ "upgrade.agentRestore.title": "Faça upgrade para restaurar versões do aplicativo de agente",
"upgrade.uploadMultipleFiles.description": "Envie vários documentos de uma só vez e aumente o tamanho máximo por arquivo para 50 MB.",
"upgrade.uploadMultipleFiles.title": "Faça upgrade para liberar uploads em lote e arquivos maiores",
"upgrade.uploadMultiplePages.description": "Você atingiu o limite de upload — apenas um documento pode ser selecionado e enviado por vez no seu plano atual.",
diff --git a/web/i18n/locales/ro-RO/billing.json b/web/i18n/locales/ro-RO/billing.json
index a8fa038ef9e..8d2fe1c6e62 100644
--- a/web/i18n/locales/ro-RO/billing.json
+++ b/web/i18n/locales/ro-RO/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "EVENIMENTE DECLANȘATOARE",
"upgrade.addChunks.description": "Ai atins limita de adăugare a segmentelor pentru acest plan.",
"upgrade.addChunks.title": "Actualizează pentru a continua să adaugi segmente",
+ "upgrade.agentRestore.description": "Restaurarea versiunilor aplicației agent nu este disponibilă în planul tău actual.",
+ "upgrade.agentRestore.title": "Fă upgrade pentru a restaura versiunile aplicației agent",
"upgrade.uploadMultipleFiles.description": "Încarcă mai multe documente simultan și mărește dimensiunea maximă pentru fiecare fișier la 50 MB.",
"upgrade.uploadMultipleFiles.title": "Treci la un plan superior pentru a debloca încărcările în lot și fișierele mai mari",
"upgrade.uploadMultiplePages.description": "Ați atins limita de încărcare — poate fi selectat și încărcat doar un singur document odată în planul dvs. actual.",
diff --git a/web/i18n/locales/ru-RU/billing.json b/web/i18n/locales/ru-RU/billing.json
index 3e0d130ac6c..135a5488ab7 100644
--- a/web/i18n/locales/ru-RU/billing.json
+++ b/web/i18n/locales/ru-RU/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "СОБЫТИЯ-ИНИЦИАТОРЫ",
"upgrade.addChunks.description": "Вы достигли предела добавления чанков по этому тарифному плану.",
"upgrade.addChunks.title": "Обновите версию, чтобы продолжить добавление блоков",
+ "upgrade.agentRestore.description": "Восстановление версий приложения агента недоступно в вашем текущем плане.",
+ "upgrade.agentRestore.title": "Обновите план, чтобы восстанавливать версии приложения агента",
"upgrade.uploadMultipleFiles.description": "Загружайте несколько документов одновременно и увеличьте максимальный размер одного файла до 50 МБ.",
"upgrade.uploadMultipleFiles.title": "Перейдите на более высокий тариф, чтобы разблокировать пакетную загрузку и файлы большего размера",
"upgrade.uploadMultiplePages.description": "Вы достигли лимита загрузки — на вашем текущем тарифном плане можно выбрать и загрузить только один документ за раз.",
diff --git a/web/i18n/locales/sl-SI/billing.json b/web/i18n/locales/sl-SI/billing.json
index 6a965eb97c3..e6feee1f0e4 100644
--- a/web/i18n/locales/sl-SI/billing.json
+++ b/web/i18n/locales/sl-SI/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "SPROŽITVENI DOGODKI",
"upgrade.addChunks.description": "Dosegli ste omejitev dodajanja delov za ta načrt.",
"upgrade.addChunks.title": "Nadgradite, da nadaljujete z dodajanjem delov",
+ "upgrade.agentRestore.description": "Obnovitev različic aplikacije agenta v vašem trenutnem paketu ni na voljo.",
+ "upgrade.agentRestore.title": "Nadgradite za obnovitev različic aplikacije agenta",
"upgrade.uploadMultipleFiles.description": "Naložite več dokumentov hkrati in povečajte največjo velikost posamezne datoteke na 50 MB.",
"upgrade.uploadMultipleFiles.title": "Nadgradite paket, da odklenete paketno nalaganje in večje datoteke",
"upgrade.uploadMultiplePages.description": "Dosegli ste omejitev nalaganja — na vašem trenutnem načrtu je mogoče izbrati in naložiti le en dokument naenkrat.",
diff --git a/web/i18n/locales/th-TH/billing.json b/web/i18n/locales/th-TH/billing.json
index a48941b8220..8d50b2891f3 100644
--- a/web/i18n/locales/th-TH/billing.json
+++ b/web/i18n/locales/th-TH/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "เหตุการณ์ทริกเกอร์",
"upgrade.addChunks.description": "คุณได้ถึงขีดจำกัดในการเพิ่มชิ้นส่วนสำหรับแผนนี้แล้ว",
"upgrade.addChunks.title": "อัปเกรดเพื่อเพิ่มชิ้นส่วนต่อ",
+ "upgrade.agentRestore.description": "การกู้คืนเวอร์ชันแอปเอเจนต์ไม่พร้อมใช้งานในแผนปัจจุบันของคุณ",
+ "upgrade.agentRestore.title": "อัปเกรดเพื่อกู้คืนเวอร์ชันแอปเอเจนต์",
"upgrade.uploadMultipleFiles.description": "อัปโหลดเอกสารหลายไฟล์พร้อมกัน และเพิ่มขนาดสูงสุดต่อไฟล์เป็น 50 MB",
"upgrade.uploadMultipleFiles.title": "อัปเกรดเพื่อปลดล็อกการอัปโหลดแบบเป็นชุดและไฟล์ขนาดใหญ่ขึ้น",
"upgrade.uploadMultiplePages.description": "คุณได้ถึงขีดจำกัดการอัปโหลดแล้ว — สามารถเลือกและอัปโหลดเอกสารได้เพียงไฟล์เดียวต่อครั้งในแผนปัจจุบันของคุณ",
diff --git a/web/i18n/locales/tr-TR/billing.json b/web/i18n/locales/tr-TR/billing.json
index 1a48ee18b17..371fa676801 100644
--- a/web/i18n/locales/tr-TR/billing.json
+++ b/web/i18n/locales/tr-TR/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "TETİKLEYİCİ OLAYLAR",
"upgrade.addChunks.description": "Bu plan için parça ekleme sınırına ulaştınız.",
"upgrade.addChunks.title": "Parçalar eklemeye devam etmek için yükseltin",
+ "upgrade.agentRestore.description": "Ajan uygulaması sürümü geri yükleme mevcut planınızda kullanılamaz.",
+ "upgrade.agentRestore.title": "Ajan uygulaması sürümlerini geri yüklemek için yükseltin",
"upgrade.uploadMultipleFiles.description": "Birden fazla belgeyi aynı anda yükleyin ve dosya başına maksimum boyutu 50 MB'a çıkarın.",
"upgrade.uploadMultipleFiles.title": "Toplu yüklemelerin ve daha büyük dosyaların kilidini açmak için yükseltin",
"upgrade.uploadMultiplePages.description": "Yükleme sınırına ulaştınız — mevcut planınızda aynı anda yalnızca bir belge seçip yükleyebilirsiniz.",
diff --git a/web/i18n/locales/uk-UA/billing.json b/web/i18n/locales/uk-UA/billing.json
index 41def182026..7b54159213b 100644
--- a/web/i18n/locales/uk-UA/billing.json
+++ b/web/i18n/locales/uk-UA/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "ПОДІЇ-ТРИГЕРИ",
"upgrade.addChunks.description": "Ви досягли межі додавання фрагментів для цього плану.",
"upgrade.addChunks.title": "Оновіть, щоб продовжити додавати частини",
+ "upgrade.agentRestore.description": "Відновлення версій застосунку агента недоступне у вашому поточному плані.",
+ "upgrade.agentRestore.title": "Оновіть план, щоб відновлювати версії застосунку агента",
"upgrade.uploadMultipleFiles.description": "Завантажуйте кілька документів одночасно та збільште максимальний розмір одного файлу до 50 МБ.",
"upgrade.uploadMultipleFiles.title": "Перейдіть на вищий тариф, щоб розблокувати пакетне завантаження та більші файли",
"upgrade.uploadMultiplePages.description": "Ви досягли ліміту завантаження — на вашому поточному плані можна вибрати та завантажити лише один документ одночасно.",
diff --git a/web/i18n/locales/vi-VN/billing.json b/web/i18n/locales/vi-VN/billing.json
index 24636225fbc..c74de88548c 100644
--- a/web/i18n/locales/vi-VN/billing.json
+++ b/web/i18n/locales/vi-VN/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "SỰ KIỆN KÍCH HOẠT",
"upgrade.addChunks.description": "Bạn đã đạt đến giới hạn thêm phần cho gói này.",
"upgrade.addChunks.title": "Nâng cấp để tiếp tục thêm các phần",
+ "upgrade.agentRestore.description": "Tính năng khôi phục phiên bản ứng dụng tác tử không khả dụng trong gói hiện tại của bạn.",
+ "upgrade.agentRestore.title": "Nâng cấp để khôi phục các phiên bản ứng dụng tác tử",
"upgrade.uploadMultipleFiles.description": "Tải lên nhiều tài liệu cùng lúc và tăng kích thước tối đa cho mỗi tệp lên 50 MB.",
"upgrade.uploadMultipleFiles.title": "Nâng cấp để mở khóa tính năng tải lên hàng loạt và tệp có dung lượng lớn hơn",
"upgrade.uploadMultiplePages.description": "Bạn đã đạt đến giới hạn tải lên — chỉ có thể chọn và tải lên một tài liệu trong một lần với gói hiện tại của bạn.",
diff --git a/web/i18n/locales/zh-Hans/billing.json b/web/i18n/locales/zh-Hans/billing.json
index 73ed83814b3..1965de8175d 100644
--- a/web/i18n/locales/zh-Hans/billing.json
+++ b/web/i18n/locales/zh-Hans/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "触发事件额度",
"upgrade.addChunks.description": "您已达到此计划的添加分段上限。",
"upgrade.addChunks.title": "升级以继续添加分段",
+ "upgrade.agentRestore.description": "当前套餐不支持恢复 Agent 应用版本。",
+ "upgrade.agentRestore.title": "升级以恢复 Agent 应用版本",
"upgrade.uploadMultipleFiles.description": "一次可上传多个文档,单个文件大小上限也将提升至 50 MB。",
"upgrade.uploadMultipleFiles.title": "升级以解锁批量上传和更大的文件",
"upgrade.uploadMultiplePages.description": "您已达到当前套餐的上传限制 —— 该套餐每次只能选择并上传 1 个文档。",
diff --git a/web/i18n/locales/zh-Hant/billing.json b/web/i18n/locales/zh-Hant/billing.json
index 33f0824a325..940ca6b0aad 100644
--- a/web/i18n/locales/zh-Hant/billing.json
+++ b/web/i18n/locales/zh-Hant/billing.json
@@ -160,6 +160,8 @@
"triggerLimitModal.usageTitle": "觸發事件",
"upgrade.addChunks.description": "您已達到此方案可新增區塊的上限。",
"upgrade.addChunks.title": "升級以繼續添加區塊",
+ "upgrade.agentRestore.description": "目前方案不支援還原 Agent 應用程式版本。",
+ "upgrade.agentRestore.title": "升級以還原 Agent 應用程式版本",
"upgrade.uploadMultipleFiles.description": "一次上傳多份文件,並將單一檔案的大小上限提高至 50 MB。",
"upgrade.uploadMultipleFiles.title": "升級方案,解鎖批次上傳與更大檔案",
"upgrade.uploadMultiplePages.description": "您已達到上傳限制 — 在您目前的方案下,每次只能選擇並上傳一個文件。",