diff --git a/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx b/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx index 91b0b1b044e58..0dcf009c2e761 100644 --- a/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx +++ b/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx @@ -136,6 +136,7 @@ const AUTO_SETTLE_SETTING_KEYS: ReadonlySet = new Set([ "sidebarAutoSettleAfterDays", "autoResumeLimitedThreads", "snoozeLimitedThreads", + "autoRedeemCodexResetCredits", ]); function planServerSettingsWrites( diff --git a/apps/mobile/src/features/settings/ThreadSettingsSections.tsx b/apps/mobile/src/features/settings/ThreadSettingsSections.tsx index 2e77d4d3937e7..b0ba2fde900ea 100644 --- a/apps/mobile/src/features/settings/ThreadSettingsSections.tsx +++ b/apps/mobile/src/features/settings/ThreadSettingsSections.tsx @@ -1,3 +1,4 @@ +import { codexAutoResetSettingsInstances } from "@t3tools/shared/serverSettings"; import { Button } from "../../components/ui/Button"; import { AuthSettingsWriteScope, type ServerSettingsPatch } from "@t3tools/contracts"; import { useEnvironmentsWithScope } from "../../state/session"; @@ -76,10 +77,13 @@ export function AutoSettleSettingsRows(props: { return null; } + const codexInstances = codexAutoResetSettingsInstances(referenceSettings); + const writeToAll = ( patch: Partial & { autoResumeLimitedThreads?: boolean; snoozeLimitedThreads?: boolean; + autoRedeemCodexResetCredits?: ServerSettingsPatch["autoRedeemCodexResetCredits"]; }, ) => props.write(patch); @@ -118,6 +122,31 @@ export function AutoSettleSettingsRows(props: { disabled={disabled} onValueChange={(value) => writeToAll({ snoozeLimitedThreads: value })} /> + {displayTargets.length > 1 && codexInstances.length > 0 ? ( + + Select one server to change per-account reset settings. + + ) : displayTargets.length === 1 ? ( + codexInstances.map(([instanceId, instance]) => { + return ( + + writeToAll({ + autoRedeemCodexResetCredits: { + [instanceId]: value, + }, + }) + } + /> + ); + }) + ) : null} ) : null} diff --git a/apps/mobile/src/features/threads/UsageLimitRecoveryCard.tsx b/apps/mobile/src/features/threads/UsageLimitRecoveryCard.tsx index 791dc2ab5d847..313f9798c8acb 100644 --- a/apps/mobile/src/features/threads/UsageLimitRecoveryCard.tsx +++ b/apps/mobile/src/features/threads/UsageLimitRecoveryCard.tsx @@ -1,3 +1,4 @@ +import { codexResetRedemptionMessage } from "@t3tools/shared/usageFormat"; import { Button } from "../../components/ui/Button"; import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime"; import { AsyncResult } from "effect/reactivity"; @@ -28,6 +29,10 @@ export function UsageLimitRecoveryCard({ const resetPassed = useDeadlinePassed(resetAt === null ? null : Date.parse(resetAt)); const runId = thread.latestRun?.runId; const recovery = thread.limitRecovery; + const redemption = + recovery?.runId === runId && recovery?.resetAt === resetAt + ? recovery?.codexResetRedemption + : undefined; const scheduled = recovery?.runId === runId && recovery?.resetAt === resetAt && recovery?.autoResume; if ( @@ -75,6 +80,11 @@ export function UsageLimitRecoveryCard({ ? `Usage limit resets ${DateTime.toDateUtc(DateTime.makeUnsafe(resetAt)).toLocaleString()}.` : "The provider did not report a reset time. Retry manually when your limit is available."} + {redemption ? ( + + {codexResetRedemptionMessage(redemption)} + + ) : null} {canSchedule ? (