@hachej/boring-core 0.1.42 → 0.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,224 @@
1
+ import { C as CoreConfig } from './types-CWtJ4kgd.js';
2
+ import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
3
+
4
+ interface RunMigrationsOptions {
5
+ migrationsFolder?: string;
6
+ }
7
+ declare function runMigrations(config: CoreConfig, options?: RunMigrationsOptions): Promise<void>;
8
+
9
+ declare class InsufficientCreditError extends Error {
10
+ readonly availableMicros: number;
11
+ readonly requiredMicros: number;
12
+ readonly statusCode = 402;
13
+ readonly code = "PAYMENT_REQUIRED";
14
+ constructor(availableMicros: number, requiredMicros: number);
15
+ }
16
+ interface MeteringBalance {
17
+ userId: string;
18
+ grantedMicros: number;
19
+ usedMicros: number;
20
+ remainingMicros: number;
21
+ activeReservedMicros: number;
22
+ /** remainingMicros minus activeReservedMicros; what a new reservation sees. */
23
+ availableMicros: number;
24
+ }
25
+ type CreditLedgerKind = 'grant' | 'purchase' | 'usage' | 'refund' | 'fallback';
26
+ /** One normalized, display-safe credit-ledger row for the account activity view.
27
+ * `amountMicros` is SIGNED: positive = credits added (grant/purchase), negative =
28
+ * consumed/removed (usage/refund). `description` is generic — no prompt/repo/model/
29
+ * provider/order/session details. */
30
+ interface CreditLedgerEntry {
31
+ id: string;
32
+ kind: CreditLedgerKind;
33
+ amountMicros: number;
34
+ createdAt: string;
35
+ description: string;
36
+ }
37
+ interface GrantOnceInput {
38
+ userId: string;
39
+ /** Unique per (userId, reason); repeat calls with the same reason are no-ops. */
40
+ reason: string;
41
+ amountMicros: number;
42
+ expiresAt?: Date;
43
+ }
44
+ interface ReserveInput {
45
+ userId: string;
46
+ workspaceId?: string;
47
+ sessionId?: string;
48
+ /** Stable run id; at most one active reservation may exist per runId. */
49
+ runId: string;
50
+ source?: string;
51
+ amountMicros: number;
52
+ ttlSeconds: number;
53
+ /**
54
+ * Reject when the user's available balance (remaining minus active
55
+ * reservations) is below this floor. Defaults to amountMicros, i.e. the
56
+ * reservation must fit entirely.
57
+ */
58
+ minAvailableMicros?: number;
59
+ }
60
+ interface ReserveResult {
61
+ reservationId: string;
62
+ }
63
+ interface RecordUsageInput {
64
+ /** Stable idempotency key; a second insert with the same id is a no-op. */
65
+ usageId: string;
66
+ userId: string;
67
+ workspaceId?: string;
68
+ sessionId?: string;
69
+ runId?: string;
70
+ messageId?: string;
71
+ source?: string;
72
+ provider?: string;
73
+ model?: string;
74
+ inputTokens?: number;
75
+ outputTokens?: number;
76
+ cacheReadTokens?: number;
77
+ cacheWriteTokens?: number;
78
+ /** Provider-reported cost, in micros, before host pricing policy. */
79
+ providerCostMicros?: number;
80
+ /** Host-priced cost actually charged against the balance. */
81
+ billedCostMicros: number;
82
+ stopReason?: string;
83
+ metadata?: Record<string, unknown>;
84
+ }
85
+ interface RecordUsageResult {
86
+ inserted: boolean;
87
+ }
88
+ type ReservationFinalStatus = 'settled' | 'released';
89
+ interface FinishReservationInput {
90
+ /** Preferred key: the id returned by reserve(). */
91
+ reservationId?: string;
92
+ /** Fallback key; pair with userId to scope across tenants. */
93
+ runId?: string;
94
+ userId?: string;
95
+ }
96
+ declare class PostgresMeteringStore {
97
+ private db;
98
+ constructor(db: PostgresJsDatabase);
99
+ /** Idempotently create a grant keyed by (userId, reason). */
100
+ grantOnce(input: GrantOnceInput): Promise<{
101
+ created: boolean;
102
+ }>;
103
+ /**
104
+ * Credit a purchase exactly once GLOBALLY per order id. The order id is the
105
+ * primary key, so a webhook retry or a delivery misrouted to a different user
106
+ * can never double-credit. A per-order advisory lock serializes this against
107
+ * revokePurchase so a refund that arrives BEFORE order_created (out-of-order
108
+ * delivery) leaves a 'refunded' tombstone that blocks this grant — the user
109
+ * never keeps credits for a refunded order. Returns `granted: false` when the
110
+ * order was already processed or has been refunded.
111
+ */
112
+ grantPurchaseOnce(input: {
113
+ orderId: string;
114
+ userId: string;
115
+ amountMicros: number;
116
+ source?: string;
117
+ storeId?: string;
118
+ testMode?: boolean;
119
+ currency?: string;
120
+ variantId?: string;
121
+ }): Promise<{
122
+ granted: boolean;
123
+ }>;
124
+ /**
125
+ * Revoke a refunded/disputed purchase. Under the same per-order advisory lock
126
+ * as grantPurchaseOnce, supports repeated PARTIAL refunds:
127
+ * - `refundFraction` is the cumulative fraction of the order (by money) that
128
+ * has been refunded — i.e. LS `refunded_amount / total` (both tax-inclusive),
129
+ * which maps the refund onto the same basis as the credited amount. The
130
+ * revoked credits = round(creditedMicros × fraction), capped at credited.
131
+ * The method debits only the delta since the last refund. Omit (undefined)
132
+ * for a full refund of the entire credited amount.
133
+ * - granted order → debit the delta, track cumulative `refunded_micros`, and
134
+ * mark 'refunded' once fully revoked; returns revoked=true when a debit was
135
+ * posted.
136
+ * - not yet seen → write a 'refunded' tombstone so a later order_created
137
+ * cannot grant; returns revoked=false (nothing was credited yet).
138
+ * - already fully refunded / no new delta → no-op; returns revoked=false.
139
+ */
140
+ revokePurchase(orderId: string, opts?: {
141
+ refundFraction?: number;
142
+ source?: string;
143
+ allowTombstone?: boolean;
144
+ expectedStoreId?: string;
145
+ expectedTestMode?: boolean;
146
+ expectedCurrency?: string;
147
+ }): Promise<{
148
+ revoked: boolean;
149
+ }>;
150
+ /**
151
+ * Insert a refund debit idempotently by id. If the id already exists (manual
152
+ * repair / corrupted retry), VERIFY the existing row is the same debit (user +
153
+ * amount) — throw on mismatch so a caller never records a refund the balance was
154
+ * not actually debited for. Returns true iff a new debit row was written.
155
+ */
156
+ private insertVerifiedLedgerDebit;
157
+ /** Total billed micros already recorded for a run (for fallback top-up so a
158
+ * partial-success run isn't charged the hold ON TOP of its real usage). */
159
+ billedMicrosForRun(userId: string, runId: string): Promise<number>;
160
+ /** Total billed micros for a specific RESERVATION (run attempt). Preferred over
161
+ * billedMicrosForRun for fallback top-up: runId is reused on client-nonce
162
+ * replay, so summing by runId would count a prior attempt's billing and let a
163
+ * later reusing attempt settle free. */
164
+ billedMicrosForReservation(userId: string, reservationId: string): Promise<number>;
165
+ /** Durably record that an ACTIVE reservation must be charged the fallback hold if
166
+ * it expires, BEFORE attempting the actual fallback charge. Committed on its own so
167
+ * the intent survives a subsequent failed charge write — the expiry sweep then
168
+ * charges a marked reservation even with zero billed rows (no free started run on a
169
+ * brief finalization-time DB outage). Idempotent; a no-op on a non-active row. */
170
+ markReservationFallbackCharge(userId: string, reservationId: string): Promise<void>;
171
+ getBalance(userId: string, now?: Date): Promise<MeteringBalance>;
172
+ /** Most-recent credit ledger for the account activity view: grants/purchases
173
+ * (positive) merged with usage/refund/fallback debits (negative), newest first,
174
+ * scoped to the user and capped at `limit` (clamped 1..50). Descriptions are
175
+ * generic/sanitized; zero-amount usage rows (zero-token) are omitted as noise. */
176
+ listLedger(userId: string, limit: number): Promise<CreditLedgerEntry[]>;
177
+ /**
178
+ * Reserve credit for a run. Serialized per user (advisory transaction
179
+ * lock) so concurrent reservations cannot jointly overdraw. Idempotent per
180
+ * runId: re-reserving while a reservation is still active returns the
181
+ * existing reservation instead of double-holding. Throws
182
+ * InsufficientCreditError when the available balance is below
183
+ * minAvailableMicros (default: the reservation amount itself).
184
+ */
185
+ reserve(input: ReserveInput, now?: Date): Promise<ReserveResult>;
186
+ /** Idempotent ledger insert; returns whether a new row was written. Serialized
187
+ * under the user's advisory lock so a positive debit is ordered with that user's
188
+ * reserve()/expiry: a debit that pushes the balance below the floor is visible to a
189
+ * concurrent reserve (which then waits and is refused), keeping the documented
190
+ * "overshoot → next run refused" boundary even for over-budget/misrouted runs. */
191
+ recordUsage(input: RecordUsageInput): Promise<RecordUsageResult>;
192
+ /**
193
+ * Finish a reservation. Settling also recovers reservations that expired
194
+ * before a delayed settlement retry, so charged usage never leaves a
195
+ * reservation dangling. Releasing only touches active rows. Idempotent:
196
+ * repeat calls are no-ops.
197
+ *
198
+ * A runId may have more than one row (an expired row plus a fresh active
199
+ * retry), so the runId fallback resolves to the single newest matching row
200
+ * — a settle never flips both the dead and the live reservation together.
201
+ */
202
+ finishReservation(input: FinishReservationInput, status: ReservationFinalStatus): Promise<{
203
+ updated: boolean;
204
+ }>;
205
+ /** Expire stale active reservations without charging. Returns the count. */
206
+ expireStaleReservations(now?: Date): Promise<number>;
207
+ /**
208
+ * Expire one user's stale active reservations under the SINGLE charge-aware
209
+ * policy. CALLER MUST already hold pg_advisory_xact_lock(hashtext(userId)).
210
+ * A reservation that reached TTL without an explicit settle/release had a failed
211
+ * finalization: if it has POSITIVE billed usage (`billedTotal > 0`) OR carries the
212
+ * durable `charge_on_expire` marker, the run did chargeable work, so top it up to
213
+ * the hold (idempotent) rather than free it; a reservation with only zero-billed
214
+ * rows and no marker is a non-billable/pre-execution abandon and is freed (so a
215
+ * user who closed the tab isn't over-charged).
216
+ */
217
+ private expireUserStaleReservations;
218
+ private computeBalance;
219
+ private sumGrants;
220
+ private sumUsage;
221
+ private sumActiveReservations;
222
+ }
223
+
224
+ export { type CreditLedgerEntry as C, type FinishReservationInput as F, type GrantOnceInput as G, InsufficientCreditError as I, type MeteringBalance as M, PostgresMeteringStore as P, type RecordUsageInput as R, type RecordUsageResult as a, type ReservationFinalStatus as b, type ReserveInput as c, type ReserveResult as d, type RunMigrationsOptions as e, runMigrations as r };
@@ -10,16 +10,28 @@ interface ChatFirstPublicShellOptions {
10
10
  eyebrow?: string;
11
11
  title?: string;
12
12
  description?: string;
13
+ footer?: ReactNode;
13
14
  };
14
15
  suggestions?: ChatSuggestion[];
16
+ /**
17
+ * Hand-drawn "Your agent" / "Your remote computer" annotations point at the
18
+ * composer and the workspace surface to teach the empty public shell. Apps
19
+ * that open a center panel on load (e.g. a landing page) should disable them,
20
+ * otherwise the fixed-position arrows overlay the open panel. Defaults to on.
21
+ */
22
+ showTeachingArrows?: boolean;
15
23
  }
16
24
 
17
25
  type ChatEntryMode = 'auth-first' | 'chat-first';
18
- interface CoreWorkspaceAgentFrontProps<TSession extends WorkspaceAgentSession = WorkspaceAgentSession> extends Omit<WorkspaceAgentFrontProps<TSession>, 'workspaceId' | 'frontPluginHotReload' | 'hotReloadEnabled'> {
26
+ type RoutedWorkspaceAgentProps<TSession extends WorkspaceAgentSession = WorkspaceAgentSession> = Omit<WorkspaceAgentFrontProps<TSession>, 'workspaceId' | 'frontPluginHotReload' | 'hotReloadEnabled'>;
27
+ interface CoreWorkspaceAgentFrontProps<TSession extends WorkspaceAgentSession = WorkspaceAgentSession> extends RoutedWorkspaceAgentProps<TSession> {
19
28
  /** Core consumes plugins statically for now; app-level hot reload is explicitly unsupported. */
20
29
  hotReload?: false;
21
30
  chatEntryMode?: ChatEntryMode;
22
31
  chatFirstPublicShell?: ChatFirstPublicShellOptions;
32
+ /** Extra workspace props used only by the unauthenticated chat-first public shell. */
33
+ chatFirstPublicWorkspaceProps?: Partial<RoutedWorkspaceAgentProps<TSession>>;
34
+ publicPaths?: string[];
23
35
  authPages?: CoreFrontAuthPagesOverride;
24
36
  cspNonce?: string;
25
37
  children?: ReactNode;
@@ -29,6 +41,207 @@ interface CoreWorkspaceAgentFrontProps<TSession extends WorkspaceAgentSession =
29
41
  loadingFallback?: ReactNode;
30
42
  bootPreloadPaths?: string[];
31
43
  }
32
- declare function CoreWorkspaceAgentFront<TSession extends WorkspaceAgentSession = WorkspaceAgentSession>({ authPages, cspNonce, children, workspaceRoute, workspaceIdParam, workspaceHref, loadingFallback, bootPreloadPaths, topBarLeft, topBarRight, appTitle, bridgeEndpoint, hotReload, chatEntryMode, chatFirstPublicShell, ...workspaceProps }: CoreWorkspaceAgentFrontProps<TSession>): react_jsx_runtime.JSX.Element;
44
+ /** Default top-bar right content. Exported so apps can compose extra widgets
45
+ * (e.g. a credit balance badge) alongside the user menu. */
46
+ declare function DefaultTopBarRight(): react_jsx_runtime.JSX.Element;
47
+ declare function CoreWorkspaceAgentFront<TSession extends WorkspaceAgentSession = WorkspaceAgentSession>({ authPages, cspNonce, children, workspaceRoute, workspaceIdParam, workspaceHref, loadingFallback, bootPreloadPaths, topBarLeft, topBarRight, appTitle, bridgeEndpoint, hotReload, chatEntryMode, chatFirstPublicShell, chatFirstPublicWorkspaceProps, publicPaths, ...workspaceProps }: CoreWorkspaceAgentFrontProps<TSession>): react_jsx_runtime.JSX.Element;
33
48
 
34
- export { type ChatFirstPublicShellOptions, CoreWorkspaceAgentFront, type CoreWorkspaceAgentFrontProps };
49
+ interface CreditBalanceBadgeProps {
50
+ /** Base URL for the credits API (default: same origin). */
51
+ apiBaseUrl?: string;
52
+ /** Fallback enable for the add-credits action. The server's `checkoutEnabled`
53
+ * (from /api/credits/balance) takes precedence when present. */
54
+ buyEnabled?: boolean;
55
+ /** Poll interval for the balance, ms (default 30s). */
56
+ pollMs?: number;
57
+ locale?: string;
58
+ }
59
+ /**
60
+ * Top-bar credit balance: a DISCRETE remaining-balance figure plus a small "+" button.
61
+ * Clicking "+" opens a popover of fixed top-up amounts (Anthropic-style); picking one starts
62
+ * the server-created checkout and opens it. Polls `/api/credits/balance`; hides itself when
63
+ * credits are disabled or the user is unauthenticated.
64
+ */
65
+ declare function CreditBalanceBadge({ apiBaseUrl, buyEnabled, pollMs, locale, }: CreditBalanceBadgeProps): react_jsx_runtime.JSX.Element | null;
66
+
67
+ interface CreditsSettingsPanelProps {
68
+ /** Base URL for the credits API (default: same origin). */
69
+ apiBaseUrl?: string;
70
+ locale?: string;
71
+ }
72
+ /**
73
+ * Account-settings "Billing & credits" panel: current balance (+ debt/low notices,
74
+ * staleness), a pack picker → checkout, and a lazy-loaded recent-activity list.
75
+ * Renders nothing when credits are disabled or the user is unauthenticated.
76
+ */
77
+ declare function CreditsSettingsPanel({ apiBaseUrl, locale }: CreditsSettingsPanelProps): react_jsx_runtime.JSX.Element | null;
78
+
79
+ /** Front-end helpers for the credit balance badge + buy-credits flow. */
80
+ /** Display-ready credit pack (server-authored). The client never infers price from
81
+ * the id and never sees the provider's price/variant id. */
82
+ interface CreditPack {
83
+ id: string;
84
+ creditMicros: number;
85
+ /** Price in the currency's minor unit (e.g. cents). For a custom pack, the MINIMUM. */
86
+ priceMinor: number;
87
+ currency: string;
88
+ label: string;
89
+ isDefault: boolean;
90
+ /** Pay-what-you-want pack: the buyer enters the amount on the hosted checkout, so
91
+ * `creditMicros` is 0 here and `priceMinor` is the minimum. The picker shows an
92
+ * "enter amount" option instead of a fixed price. */
93
+ custom?: boolean;
94
+ }
95
+ interface CreditBalanceResponse {
96
+ enabled: boolean;
97
+ userId: string;
98
+ grantedMicros: number;
99
+ usedMicros: number;
100
+ remainingMicros: number;
101
+ activeReservedMicros: number;
102
+ availableMicros: number;
103
+ /** Amount owed when the ledger went negative (e.g. refund of spent credits). */
104
+ debtMicros: number;
105
+ /** Server truth: whether the Buy-credits checkout is wired (avoids client drift). */
106
+ checkoutEnabled?: boolean;
107
+ /** Display-ready packs (present only when checkout is wired). */
108
+ packs?: CreditPack[];
109
+ currency: 'credits';
110
+ }
111
+ type CreditLedgerKind = 'grant' | 'purchase' | 'usage' | 'refund' | 'fallback';
112
+ /** One credit-activity row (mirrors the server `CreditLedgerEntry`). `amountMicros`
113
+ * is signed: positive = added, negative = consumed/removed. */
114
+ interface CreditLedgerEntry {
115
+ id: string;
116
+ kind: CreditLedgerKind;
117
+ amountMicros: number;
118
+ createdAt: string;
119
+ description: string;
120
+ }
121
+ /** Format SIGNED credit micros as a currency string with an explicit +/− sign.
122
+ * `currency` is the configured display currency (1 credit-unit = 1 major unit); defaults
123
+ * to EUR for callers without a configured purchase currency. */
124
+ declare function formatSignedCreditMicros(micros: number, currency?: string, locale?: string): string;
125
+ /** Format a minor-unit price (e.g. cents) in its currency for pack labels/buttons. */
126
+ declare function formatMinorPrice(priceMinor: number, currency: string, locale?: string): string;
127
+ /** Format credit micros as a currency string. 1 credit-unit = 1 major unit of the
128
+ * configured display `currency` (µ/1e6). Defaults to EUR for callers without a
129
+ * configured purchase currency (e.g. a consumption-only deployment). */
130
+ declare function formatCreditMicros(micros: number, currency?: string, locale?: string): string;
131
+ /** True when the remaining balance is at or below the low-balance threshold. */
132
+ declare function isLowBalance(micros: number, thresholdMicros?: number): boolean;
133
+ /** Stable server error code for an out-of-credits rejection (mirrors the agent's
134
+ * ErrorCode enum). Kept here so the credits feature owns the credit↔code mapping
135
+ * and the agent stays billing-agnostic. */
136
+ declare const PAYMENT_REQUIRED_ERROR_CODE = "PAYMENT_REQUIRED";
137
+ /** True when a run-rejected notice was an out-of-credits rejection. Hosts use this
138
+ * in renderNoticeAction to decide whether to show the Buy-credits CTA. */
139
+ declare function isPaymentRequiredNotice(notice: {
140
+ errorCode?: string;
141
+ }): boolean;
142
+
143
+ /** Window event other code can dispatch to force an immediate balance refetch —
144
+ * e.g. the chat dispatching `window.dispatchEvent(new Event(CREDITS_REFRESH_EVENT))`
145
+ * when a run finishes, so the balance updates without waiting for the poll. */
146
+ declare const CREDITS_REFRESH_EVENT = "credits:refresh";
147
+ interface UseCreditBalanceOptions {
148
+ /** Base URL for the credits API (default: same origin). */
149
+ apiBaseUrl?: string;
150
+ /** Poll interval for the balance, ms (default 30s). */
151
+ pollMs?: number;
152
+ /** Credit pack id to purchase (server maps it to a Lemon Squeezy variant). */
153
+ pack?: string;
154
+ }
155
+ interface UseCreditBalanceResult {
156
+ /** Latest balance, or null before the first successful load. */
157
+ balance: CreditBalanceResponse | null;
158
+ /** True when credits are disabled or the user is unauthenticated (UI should hide). */
159
+ hidden: boolean;
160
+ /** Set when a balance fetch failed (network/server) before a successful load; null
161
+ * otherwise. Lets a consumer show an error state rather than an endless spinner. */
162
+ error: string | null;
163
+ /** Refetch the balance now. */
164
+ refresh: () => Promise<void>;
165
+ /** Refetch now, then a short backoff burst (~15s) — credit writes settle
166
+ * asynchronously after a run/purchase, so a single refetch can read a stale value.
167
+ * Concurrent bursts are deduped (a new call restarts the window). */
168
+ refreshWithRetry: () => void;
169
+ /** Start a Lemon Squeezy checkout (server creates it, sets the buyer id from the
170
+ * session) and open it in a new tab. Resolves to an error message on failure.
171
+ * Pass a pack id to buy a specific pack. */
172
+ buy: (pack?: string) => Promise<string | null>;
173
+ /** True while a checkout request is in flight. */
174
+ buying: boolean;
175
+ /** Epoch ms of the last successful balance read (null before first load). */
176
+ lastUpdatedAt: number | null;
177
+ /** True while a refresh (incl. a retry burst) is in flight. */
178
+ updating: boolean;
179
+ }
180
+ /**
181
+ * Shared credit-balance state for the top-bar badge and the settings panel:
182
+ * polls `/api/credits/balance`, refetches on window focus and on the
183
+ * `credits:refresh` event, and exposes a server-side checkout action. The buyer
184
+ * id is set SERVER-side (POST /api/credits/checkout) so the client never supplies it.
185
+ */
186
+ declare function useCreditBalance({ apiBaseUrl, pollMs, pack, }?: UseCreditBalanceOptions): UseCreditBalanceResult;
187
+
188
+ interface UseCreditHistoryResult {
189
+ entries: CreditLedgerEntry[] | null;
190
+ loading: boolean;
191
+ error: boolean;
192
+ /** Fetch (or refetch) the activity. Call lazily, e.g. when the section expands. */
193
+ load: () => Promise<void>;
194
+ }
195
+ /**
196
+ * Lazy loader for the account credit-activity list (`GET /api/credits/history`).
197
+ * Does NOT fetch on mount — call `load()` when the section is opened. `entries` is
198
+ * null until the first load; `[]` means "no activity yet".
199
+ */
200
+ declare function useCreditHistory(apiBaseUrl?: string, limit?: number): UseCreditHistoryResult;
201
+
202
+ type CheckoutReturnStatus = 'idle' | 'checking' | 'confirmed' | 'processing' | 'cancelled';
203
+ interface UseCheckoutReturnHandlerOptions {
204
+ apiBaseUrl?: string;
205
+ /** Query param name the LS redirect uses (default 'checkout'). */
206
+ param?: string;
207
+ }
208
+ interface UseCheckoutReturnHandlerResult {
209
+ status: CheckoutReturnStatus;
210
+ dismiss: () => void;
211
+ }
212
+ /**
213
+ * Handle the return from a Lemon Squeezy hosted checkout. The URL marker (`?checkout=
214
+ * return|success|cancelled`) is NOT treated as proof of payment — on a return we poll
215
+ * the AUTHENTICATED balance and only show success once it actually increases (credits
216
+ * settle asynchronously via the webhook). The marker is stripped immediately so a reload
217
+ * can't replay it, and a `credits:refresh` event + BroadcastChannel signal refresh any
218
+ * other open app tab. Returns the status for a small banner to render.
219
+ */
220
+ declare function useCheckoutReturnHandler({ apiBaseUrl, param }?: UseCheckoutReturnHandlerOptions): UseCheckoutReturnHandlerResult;
221
+
222
+ interface CheckoutReturnBannerProps {
223
+ apiBaseUrl?: string;
224
+ /** Query param the LS redirect uses (default 'checkout'). */
225
+ param?: string;
226
+ }
227
+ /**
228
+ * Renders the post-checkout return state (see useCheckoutReturnHandler). Mount it once
229
+ * near the app root. It NEVER claims success from the URL — only after the server
230
+ * balance actually increases. ARIA-live so the status is announced. Self-hides when idle.
231
+ */
232
+ declare function CheckoutReturnBanner({ apiBaseUrl, param }: CheckoutReturnBannerProps): react_jsx_runtime.JSX.Element | null;
233
+
234
+ interface BuyCreditsNoticeActionProps {
235
+ /** Base URL for the credits API (default: same origin). */
236
+ apiBaseUrl?: string;
237
+ label?: string;
238
+ }
239
+ /**
240
+ * Inline "Buy credits" action for a PAYMENT_REQUIRED run-rejected notice. Self-contained:
241
+ * starts a server-created checkout (the buyer id is set server-side) on click. Renders
242
+ * nothing once the server reports checkout is disabled, so it can't dangle a dead button.
243
+ * Mount it from a host's renderNoticeAction (see isPaymentRequiredNotice).
244
+ */
245
+ declare function BuyCreditsNoticeAction({ apiBaseUrl, label }: BuyCreditsNoticeActionProps): react_jsx_runtime.JSX.Element | null;
246
+
247
+ export { BuyCreditsNoticeAction, type BuyCreditsNoticeActionProps, CREDITS_REFRESH_EVENT, type ChatFirstPublicShellOptions, CheckoutReturnBanner, type CheckoutReturnBannerProps, type CheckoutReturnStatus, CoreWorkspaceAgentFront, type CoreWorkspaceAgentFrontProps, CreditBalanceBadge, type CreditBalanceBadgeProps, type CreditBalanceResponse, type CreditLedgerEntry, type CreditLedgerKind, type CreditPack, CreditsSettingsPanel, type CreditsSettingsPanelProps, DefaultTopBarRight, PAYMENT_REQUIRED_ERROR_CODE, type UseCheckoutReturnHandlerResult, type UseCreditBalanceOptions, type UseCreditBalanceResult, type UseCreditHistoryResult, formatCreditMicros, formatMinorPrice, formatSignedCreditMicros, isLowBalance, isPaymentRequiredNotice, useCheckoutReturnHandler, useCreditBalance, useCreditHistory };