@tangle-network/agent-app 0.44.31 → 0.44.33

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.
@@ -12,6 +12,8 @@ import '../agent-activity-C8ZG0F0M.js';
12
12
  import '../flow-types-CJxEmaRy.js';
13
13
  import '../queue-VTBA5ONX.js';
14
14
  import '../sandbox-terminal-ChNEdHF8.js';
15
+ import '../billing-BibxgALe.js';
16
+ import '../billing/index.js';
15
17
  import '../catalog/index.js';
16
18
  import '../harness/index.js';
17
19
  import '../attachment-validation-CNkH91Gs.js';
@@ -3,7 +3,7 @@ import {
3
3
  ChatMessages,
4
4
  ModelPicker,
5
5
  ProviderLogo
6
- } from "../chunk-GCH3BUAZ.js";
6
+ } from "../chunk-NDVTYHLN.js";
7
7
  import "../chunk-FBVLEGEG.js";
8
8
  import "../chunk-YTMKRL3L.js";
9
9
  import "../chunk-GEYACSFW.js";
@@ -0,0 +1,193 @@
1
+ import { PlatformIdentity, PlatformBillingClient } from './billing/index.js';
2
+
3
+ /**
4
+ * Platform billing HTTP transport + tier state for apps on the shared
5
+ * Tangle balance model (id.tangle.tools). Reads authenticate as the user via
6
+ * their per-user platform key (the platform resolves the caller from the
7
+ * key; service or impersonation headers on read routes are rejected). The
8
+ * deduct write authenticates as the product service (`Bearer <serviceToken>`
9
+ * + `X-Service-Name`) and names the target user in the body. Also provides a
10
+ * fetch-backed implementation of the `/billing` module's
11
+ * `PlatformBillingClient` seam (type-only import — no runtime coupling).
12
+ */
13
+
14
+ /** Define available subscription tiers for the TanglePlan service */
15
+ type TanglePlanTier = 'free' | 'pro' | 'enterprise';
16
+ /** 'pro' | 'enterprise' pass through; anything else (null, unknown) → 'free'. */
17
+ declare function normalizeTanglePlanTier(plan: string | null | undefined): TanglePlanTier;
18
+ /** Represent platform billing HTTP errors with status code and detailed message */
19
+ declare class PlatformBillingHttpError extends Error {
20
+ readonly status: number;
21
+ constructor(status: number, detail: string);
22
+ }
23
+ /** Structural guard (name + numeric status) — robust across module instances. */
24
+ declare function isPlatformBillingHttpError(error: unknown): error is PlatformBillingHttpError;
25
+ /** Define HTTP options for platform billing including base URL, service token, product slug, fetch implementation, and timeout */
26
+ interface PlatformBillingHttpOptions {
27
+ /** Platform root, e.g. https://id.tangle.tools (trailing slashes stripped). */
28
+ baseUrl: string;
29
+ /** Used only by `deduct()`; resolved lazily so reads never require it.
30
+ * Throws at call time when empty. */
31
+ serviceToken: string | (() => string);
32
+ /** Product slug — the `X-Service-Name` header and the deduct `product` field. */
33
+ productSlug: string;
34
+ fetchImpl?: typeof fetch;
35
+ /** Default 10 000. */
36
+ timeoutMs?: number;
37
+ }
38
+ /** Describe subscription tier and status information for a platform user */
39
+ interface PlatformSubscriptionInfo {
40
+ tier: TanglePlanTier;
41
+ status: string | null;
42
+ }
43
+ /** Describe the platform balance and lifetime spending with an optional update timestamp */
44
+ interface PlatformBalanceSnapshot {
45
+ balance: number;
46
+ lifetimeSpent: number;
47
+ updatedAt?: string;
48
+ }
49
+ /** Describe a product's usage and spending metrics on the platform */
50
+ interface PlatformUsageProductRow {
51
+ product: string | null;
52
+ totalSpent: number;
53
+ count: number;
54
+ }
55
+ /** Lifecycle of a per-product seat subscription, mirroring the Stripe states
56
+ * the platform persists. 'none' = the user has never held this seat. */
57
+ type SeatStatus = 'none' | 'active' | 'trialing' | 'past_due' | 'canceled';
58
+ /** Price and included shared-wallet credit for one seat billing period. */
59
+ interface ProductSeatOfferPeriod {
60
+ priceCents: number;
61
+ includedCreditsCents: number;
62
+ }
63
+ /** Commercial terms returned by the platform's product catalog. Products use
64
+ * this exact object for display instead of duplicating prices in UI copy. */
65
+ interface ProductSeatOffer {
66
+ currency: 'usd';
67
+ interval: 'month';
68
+ recurring: ProductSeatOfferPeriod;
69
+ introductory: ProductSeatOfferPeriod | null;
70
+ }
71
+ /**
72
+ * Per-product entitlement snapshot from the platform — the single read that
73
+ * tells a product whether to show its workspace or the seat paywall. Shape
74
+ * matches `GET /v1/billing/product-entitlement?product=<id>`.
75
+ *
76
+ * `hasSeat` and `onFreeTier` are computed platform-side from the raw seat row
77
+ * + cumulative spend so the access rule is identical across products:
78
+ * - `hasSeat` — an active/trialing seat whose period has not lapsed.
79
+ * - `onFreeTier` — no active seat AND cumulative spend below the free cap
80
+ * ($2 / 200¢ lifetime). Keys off lifetime spend, not wallet
81
+ * balance, so a router top-up never re-opens free access.
82
+ */
83
+ interface ProductEntitlement {
84
+ seatStatus: SeatStatus;
85
+ /** ISO timestamp the active seat's paid period runs until; null when none. */
86
+ currentPeriodEnd: string | null;
87
+ /** Cumulative inference spend across the whole suite, in dollars. */
88
+ lifetimeSpentUsd: number;
89
+ hasSeat: boolean;
90
+ onFreeTier: boolean;
91
+ /** Present when the platform exposes catalog-backed commercial terms. */
92
+ offer?: ProductSeatOffer;
93
+ }
94
+ /** Define methods to interact with platform billing endpoints using user or service authentication */
95
+ interface PlatformBillingHttp {
96
+ /** GET /v1/plans/current (user bearer). */
97
+ getSubscription(userApiKey: string): Promise<PlatformSubscriptionInfo>;
98
+ /** GET /v1/billing/balance (user bearer). */
99
+ getBalance(userApiKey: string): Promise<PlatformBalanceSnapshot>;
100
+ /** GET /v1/billing/usage (user bearer). */
101
+ getUsageByProduct(userApiKey: string): Promise<PlatformUsageProductRow[]>;
102
+ /** GET /v1/billing/product-entitlement?product=<id> (user bearer). */
103
+ getProductEntitlement(userApiKey: string, productId: string): Promise<ProductEntitlement>;
104
+ /** POST /v1/billing/deduct (service token). */
105
+ deduct(input: {
106
+ platformUserId: string;
107
+ amountUsd: number;
108
+ type: string;
109
+ description: string;
110
+ referenceId: string;
111
+ }): Promise<void>;
112
+ /** Absolute URL of the platform's billing-management surface. */
113
+ billingUrl(): string;
114
+ /** Absolute URL of the catalog-backed seat checkout for `productId`. */
115
+ seatCheckoutUrl(productId: string): string;
116
+ }
117
+ /** Create a PlatformBillingHttp instance configured with given options and default behaviors */
118
+ declare function createPlatformBillingHttp(opts: PlatformBillingHttpOptions): PlatformBillingHttp;
119
+ /**
120
+ * Platform Stripe checkout URL for a product's catalog-backed seat. The
121
+ * platform resolves the product-specific price and introductory offer from the
122
+ * `product` query param. Mirrors the `billingUrl()` shape — a deterministic
123
+ * platform-rooted URL with no client-side pricing decisions.
124
+ */
125
+ declare function seatCheckoutUrl(baseUrl: string, productId: string): string;
126
+ /** Define policy settings for concurrency and overage allowance in a tangle tier */
127
+ interface TangleTierPolicy {
128
+ concurrency: number;
129
+ overageAllowed: boolean;
130
+ }
131
+ /** Define default concurrency and overage policies for each TanglePlanTier level */
132
+ declare const DEFAULT_TANGLE_TIER_POLICY: Record<TanglePlanTier, TangleTierPolicy>;
133
+ /** Describe the state of a Tangle plan tier including subscription, balance, spending, and concurrency details */
134
+ interface TangleTierState {
135
+ tier: TanglePlanTier;
136
+ subscriptionStatus: string | null;
137
+ remainingBalanceUsd: number;
138
+ lifetimeSpentUsd: number;
139
+ concurrency: number;
140
+ overageAllowed: boolean;
141
+ }
142
+ /**
143
+ * Read subscription + balance and project them onto the tier policy. A
144
+ * null/absent key fails CLOSED (free tier, zero balance) — a billable run is
145
+ * never started against an unknown balance. Platform errors throw; callers
146
+ * on the billable path choose their posture explicitly.
147
+ */
148
+ declare function readTangleTierState(http: PlatformBillingHttp, userApiKey: string | null | undefined, policy?: Record<TanglePlanTier, TangleTierPolicy>): Promise<TangleTierState>;
149
+ /** Lifetime free-tier cap: $2 (200¢) cumulative inference spend, expressed in
150
+ * dollars. Free product access ends once cumulative spend crosses this. */
151
+ declare const FREE_TIER_SPEND_CAP_USD = 2;
152
+ /**
153
+ * Default name of the per-app feature flag gating seat billing. While OFF the
154
+ * entitlement read is skipped and access fails OPEN (entitled) so nothing
155
+ * changes live until a product flips the flag.
156
+ */
157
+ declare const DEFAULT_SEAT_BILLING_ENABLED_ENV_VAR = "SEAT_BILLING_ENABLED";
158
+ /** Define options to configure seat billing flag environment variables and override flag name */
159
+ interface SeatBillingFlagOptions {
160
+ env?: Record<string, string | undefined>;
161
+ /** Override the flag name; default {@link DEFAULT_SEAT_BILLING_ENABLED_ENV_VAR}. */
162
+ flagEnvVar?: string;
163
+ }
164
+ /**
165
+ * Seat billing is OFF unless the flag is explicitly truthy ('true'/'1'/'on'/
166
+ * 'enabled'). Default OFF — pre-rollout, the paywall never engages. Returns
167
+ * false when no env is available (browser bundles) so the client stays
168
+ * fail-open there too.
169
+ */
170
+ declare function isSeatBillingEnabled(opts?: SeatBillingFlagOptions): boolean;
171
+ /**
172
+ * Read a user's entitlement for one product. Fails OPEN: an absent key,
173
+ * disabled flag, or unreachable seat endpoint all return a permissive snapshot
174
+ * (`hasSeat: true`) so consumers never break pre-rollout. The platform owns the
175
+ * `hasSeat`/`onFreeTier` computation; this client only transports + degrades
176
+ * safely.
177
+ *
178
+ * @param flag — pass {@link isSeatBillingEnabled} (or your own boolean) so the
179
+ * product owns when the gate engages. When false, no network call is made.
180
+ */
181
+ declare function getProductEntitlement(http: Pick<PlatformBillingHttp, 'getProductEntitlement'>, userApiKey: string | null | undefined, productId: string, flag?: boolean): Promise<ProductEntitlement>;
182
+ /** Entitled = holds an active seat OR is still inside the free tier. The one
183
+ * predicate every product uses. */
184
+ declare function isProductEntitled(ent: ProductEntitlement): boolean;
185
+ /** Define a contract for resolving platform identities based on user identifiers */
186
+ interface PlatformIdentityStore {
187
+ resolveIdentity(userId: string): Promise<PlatformIdentity | null>;
188
+ }
189
+ /** Concrete fetch-backed `PlatformBillingClient<TanglePlanTier>` for
190
+ * `createPlatformBalanceManager` (from `/billing`). */
191
+ declare function createTanglePlatformBillingClient(http: PlatformBillingHttp, identity: PlatformIdentityStore): PlatformBillingClient<TanglePlanTier>;
192
+
193
+ export { DEFAULT_SEAT_BILLING_ENABLED_ENV_VAR as D, FREE_TIER_SPEND_CAP_USD as F, type PlatformBalanceSnapshot as P, type SeatBillingFlagOptions as S, type TanglePlanTier as T, DEFAULT_TANGLE_TIER_POLICY as a, type PlatformBillingHttp as b, PlatformBillingHttpError as c, type PlatformBillingHttpOptions as d, type PlatformIdentityStore as e, type PlatformSubscriptionInfo as f, type PlatformUsageProductRow as g, type ProductEntitlement as h, type ProductSeatOffer as i, type ProductSeatOfferPeriod as j, type SeatStatus as k, type TangleTierPolicy as l, type TangleTierState as m, createPlatformBillingHttp as n, createTanglePlatformBillingClient as o, getProductEntitlement as p, isPlatformBillingHttpError as q, isProductEntitled as r, isSeatBillingEnabled as s, normalizeTanglePlanTier as t, readTangleTierState as u, seatCheckoutUrl as v };
@@ -97,7 +97,7 @@ import {
97
97
  flattenHistory,
98
98
  readSandboxBinaryBytes,
99
99
  statSandboxFileSize
100
- } from "../chunk-BAC2B2KI.js";
100
+ } from "../chunk-7WXG4ZFP.js";
101
101
  import "../chunk-LWSJK546.js";
102
102
  import "../chunk-CQZSAR77.js";
103
103
  import "../chunk-ICOHEZK6.js";
@@ -643,6 +643,40 @@ function createSandboxPrewarmer(shell, options) {
643
643
  };
644
644
  }
645
645
 
646
+ // src/sandbox/prewarm-claim-d1.ts
647
+ var DEFAULT_PREWARM_CLAIM_TABLE = "sandbox_prewarm_claims";
648
+ var PREWARM_CLAIM_TABLE_DDL = `CREATE TABLE IF NOT EXISTS ${DEFAULT_PREWARM_CLAIM_TABLE} (
649
+ key TEXT PRIMARY KEY,
650
+ expires_at INTEGER NOT NULL
651
+ )`;
652
+ var SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
653
+ function createD1PrewarmClaimStore(db, options = {}) {
654
+ const table = options.table ?? DEFAULT_PREWARM_CLAIM_TABLE;
655
+ if (!SAFE_IDENTIFIER.test(table)) {
656
+ throw new Error(`Invalid prewarm claim table name: ${JSON.stringify(table)}`);
657
+ }
658
+ const now = options.now ?? (() => Date.now());
659
+ const acquireSql = `INSERT INTO ${table} (key, expires_at) VALUES (?1, ?2)
660
+ ON CONFLICT(key) DO UPDATE SET expires_at = ?2 WHERE ${table}.expires_at <= ?3
661
+ RETURNING key`;
662
+ const releaseSql = `DELETE FROM ${table} WHERE key = ?1`;
663
+ const isHeldSql = `SELECT 1 AS held FROM ${table} WHERE key = ?1 AND expires_at > ?2`;
664
+ return {
665
+ async acquire(key, ttlSeconds) {
666
+ const at = now();
667
+ const row = await db.prepare(acquireSql).bind(key, at + ttlSeconds * 1e3, at).first();
668
+ return row != null;
669
+ },
670
+ async release(key) {
671
+ await db.prepare(releaseSql).bind(key).run();
672
+ },
673
+ async isHeld(key) {
674
+ const row = await db.prepare(isHeldSql).bind(key, now()).first();
675
+ return row != null;
676
+ }
677
+ };
678
+ }
679
+
646
680
  // src/sandbox/index.ts
647
681
  var DEFAULT_SANDBOX_DIRECT_KEY_NAMES = [
648
682
  "TCLOUD_SANDBOX_API_KEY",
@@ -1898,6 +1932,9 @@ export {
1898
1932
  bearerSubprotocolToken,
1899
1933
  terminalTokenFromRequest,
1900
1934
  createSandboxPrewarmer,
1935
+ DEFAULT_PREWARM_CLAIM_TABLE,
1936
+ PREWARM_CLAIM_TABLE_DDL,
1937
+ createD1PrewarmClaimStore,
1901
1938
  resolveSandboxClientCredentials,
1902
1939
  DEFAULT_SANDBOX_RESOURCES,
1903
1940
  getClient,
@@ -1941,4 +1978,4 @@ export {
1941
1978
  isTerminalPromptEvent,
1942
1979
  detectInteractiveQuestion
1943
1980
  };
1944
- //# sourceMappingURL=chunk-BAC2B2KI.js.map
1981
+ //# sourceMappingURL=chunk-7WXG4ZFP.js.map