{t( - 'auto.components.billing.capReachedHint', - 'Raise the cap to keep starting sandboxes. Your files are safe.' + 'auto.components.billing.capReachedHint2', + 'Raise the cap to start sandboxes again. Your sandboxes are asleep, and your files are safe.' )}
) : null} diff --git a/src/renderer/src/components/billing/plan-billing-copy.ts b/src/renderer/src/components/billing/plan-billing-copy.ts index 8563da88b66..df35f015606 100644 --- a/src/renderer/src/components/billing/plan-billing-copy.ts +++ b/src/renderer/src/components/billing/plan-billing-copy.ts @@ -48,22 +48,22 @@ export function denyReasonCopy( case 'included_hours_exhausted': return canManage ? t( - 'auto.components.billing.reasonExhausted3', - 'Out of sandbox hours for this month. Turn on overage to keep starting sandboxes. Your files are safe.' + 'auto.components.billing.reasonExhausted4', + 'Out of sandbox hours for this month. Running sandboxes go to sleep and new ones can’t start. Nothing is deleted, and your files are safe. Turn on overage to start sandboxes again.' ) : t( - 'auto.components.billing.reasonExhaustedMember2', - 'Out of sandbox hours for this month. Ask an owner or admin to add hours. Your files are safe.' + 'auto.components.billing.reasonExhaustedMember3', + 'Out of sandbox hours for this month. Running sandboxes go to sleep and new ones can’t start. Nothing is deleted, and your files are safe. Ask an owner or admin to add hours.' ) case 'overage_cap_reached': return canManage ? t( - 'auto.components.billing.reasonCapAdmin2', - 'Spend cap reached. Raise the monthly spend cap to keep starting sandboxes. Your files are safe.' + 'auto.components.billing.reasonCapAdmin3', + 'Spend cap reached. Running sandboxes go to sleep and new ones can’t start. Nothing is deleted, and your files are safe. Raise the monthly spend cap to start sandboxes again.' ) : t( - 'auto.components.billing.reasonCapMember3', - 'Spend cap reached. Ask an owner or admin to raise the spend cap. Your files are safe.' + 'auto.components.billing.reasonCapMember4', + 'Spend cap reached. Running sandboxes go to sleep and new ones can’t start. Nothing is deleted, and your files are safe. Ask an owner or admin to raise the spend cap.' ) } } diff --git a/src/renderer/src/components/billing/plans/TeamPlanCard.tsx b/src/renderer/src/components/billing/plans/TeamPlanCard.tsx index b4cd0843ff7..d4f9d177058 100644 --- a/src/renderer/src/components/billing/plans/TeamPlanCard.tsx +++ b/src/renderer/src/components/billing/plans/TeamPlanCard.tsx @@ -70,8 +70,8 @@ export function TeamPlanCard({ ), t('auto.components.billing.plans.featureReady', 'Ready in seconds, nothing to set up or host'), t( - 'auto.components.billing.plans.featureOverage6', - 'Optional overage at {{rate}} per sandbox hour, up to a monthly spend cap you set ({{cap}} by default)', + 'auto.components.billing.plans.featureOverage7', + 'Optional overage at {{rate}} per sandbox hour, billed by the minute, up to a monthly spend cap you set ({{cap}} by default)', { rate: formatRateCents(team.overageCentsPerHour, locale), cap: formatCents(team.defaultSpendCapCents, locale) diff --git a/src/renderer/src/components/run-actions/RunActionButton.tsx b/src/renderer/src/components/run-actions/RunActionButton.tsx index e803e5c5e41..a58f30259a2 100644 --- a/src/renderer/src/components/run-actions/RunActionButton.tsx +++ b/src/renderer/src/components/run-actions/RunActionButton.tsx @@ -1,8 +1,13 @@ -import React, { useEffect, useMemo, useState } from 'react' +import React, { useEffect, useMemo, useRef, useState } from 'react' import { useAppStore } from '@/store' import { useShortcutLabel } from '@/hooks/useShortcutLabel' import { useWorktreeRuntimeTarget } from '@/runtime/rpc/targets/use-worktree-runtime-target' -import { workspacePortScanKeyForTarget } from '@/lib/workspace-ports/workspace-port-actions' +import { + openWorkspacePortInBrowser, + refreshWorkspacePortScanAfterStop, + workspacePortScanKeyForTarget +} from '@/lib/workspace-ports/workspace-port-actions' +import { useTranslate } from '@/i18n/use-translate' import { getWorkspacePortsByWorktreeId } from '@/lib/workspace-ports/workspace-port-groups' import { loadWorktreeRunActions, @@ -10,6 +15,7 @@ import { type WorktreeRunActions } from '@/lib/run-actions/run-action-config' import { startRunAction, stopRunAction } from '@/lib/run-actions/run-action-controller' +import { autoRunProvisionedWorkspaceOnce } from '@/lib/run-actions/run-action-events' import { useWorktreeRunActionRuns, type RunActionRun } from '@/lib/run-actions/run-actions-store' import type { WorkspacePort } from '../../../../shared/workspace-ports' import { RunActionButtonView } from './RunActionButtonView' @@ -61,6 +67,53 @@ function focusRunTab(run: RunActionRun): void { state.setActiveTab(findLiveRunTabId(state, run.worktreeId, run.tabId) ?? run.tabId) } +/** "Web stopped" / "Web failed" when a run ends; the view reads it out through a polite live region. */ +function useRunEndAnnouncement(runs: Record