@oxygen-agent/cli 1.987.20 → 1.1003.12

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.
Files changed (106) hide show
  1. package/README.md +1 -1
  2. package/dist/admin-primary-providers-render.d.ts +0 -2
  3. package/dist/admin-primary-providers-render.js +1 -1
  4. package/dist/browser-login.js +1 -4
  5. package/dist/command-manifest.d.ts +3 -2
  6. package/dist/command-manifest.js +10 -0
  7. package/dist/credentials.d.ts +1 -1
  8. package/dist/functions-commands.js +6 -2
  9. package/dist/help.d.ts +8 -0
  10. package/dist/help.js +46 -0
  11. package/dist/index.js +1569 -123
  12. package/dist/knowledge-mirror.d.ts +2 -2
  13. package/dist/runtime.d.ts +0 -15
  14. package/dist/runtime.js +1 -1
  15. package/dist/session.d.ts +4 -3
  16. package/dist/skills.d.ts +8 -7
  17. package/dist/skills.js +24 -10
  18. package/dist/transcript.d.ts +2 -1
  19. package/dist/util.d.ts +1 -1
  20. package/dist/util.js +1 -3
  21. package/node_modules/@oxygen/formula/dist/coerce.d.ts +10 -0
  22. package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
  23. package/node_modules/@oxygen/formula/dist/formula-functions.js +65 -0
  24. package/node_modules/@oxygen/formula/dist/hash.d.ts +19 -0
  25. package/node_modules/@oxygen/formula/dist/hash.js +199 -0
  26. package/node_modules/@oxygen/formula/dist/value-cleaners.d.ts +6 -1
  27. package/node_modules/@oxygen/formula/dist/value-cleaners.js +10 -26
  28. package/node_modules/@oxygen/shared/dist/array-utils.d.ts +5 -0
  29. package/node_modules/@oxygen/shared/dist/array-utils.js +11 -0
  30. package/node_modules/@oxygen/shared/dist/billing.d.ts +78 -22
  31. package/node_modules/@oxygen/shared/dist/billing.js +150 -40
  32. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +17 -0
  33. package/node_modules/@oxygen/shared/dist/capability-discovery.js +89 -16
  34. package/node_modules/@oxygen/shared/dist/column-autofill.d.ts +52 -0
  35. package/node_modules/@oxygen/shared/dist/column-autofill.js +80 -0
  36. package/node_modules/@oxygen/shared/dist/column-output-fields.js +2 -6
  37. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.d.ts +108 -0
  38. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.js +545 -0
  39. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +2 -2
  40. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +2 -2
  41. package/node_modules/@oxygen/shared/dist/deploy-env.d.ts +74 -0
  42. package/node_modules/@oxygen/shared/dist/deploy-env.js +82 -0
  43. package/node_modules/@oxygen/shared/dist/dnc-rules.d.ts +130 -0
  44. package/node_modules/@oxygen/shared/dist/dnc-rules.js +221 -0
  45. package/node_modules/@oxygen/shared/dist/enrichment-intents.d.ts +103 -0
  46. package/node_modules/@oxygen/shared/dist/enrichment-intents.js +819 -0
  47. package/node_modules/@oxygen/shared/dist/error-message.d.ts +1 -0
  48. package/node_modules/@oxygen/shared/dist/error-message.js +3 -0
  49. package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -3
  50. package/node_modules/@oxygen/shared/dist/external-write-policy.d.ts +33 -0
  51. package/node_modules/@oxygen/shared/dist/external-write-policy.js +68 -0
  52. package/node_modules/@oxygen/shared/dist/format-percent.d.ts +8 -0
  53. package/node_modules/@oxygen/shared/dist/format-percent.js +13 -0
  54. package/node_modules/@oxygen/shared/dist/freemail-domains.d.ts +81 -0
  55. package/node_modules/@oxygen/shared/dist/freemail-domains.js +157 -0
  56. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.d.ts +1 -0
  57. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.js +1 -1
  58. package/node_modules/@oxygen/shared/dist/index.d.ts +13 -0
  59. package/node_modules/@oxygen/shared/dist/index.js +13 -0
  60. package/node_modules/@oxygen/shared/dist/json-path.js +1 -3
  61. package/node_modules/@oxygen/shared/dist/knowledge-bases.js +1 -3
  62. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +2 -2
  63. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +2 -2
  64. package/node_modules/@oxygen/shared/dist/langfuse.js +9 -0
  65. package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +32 -0
  66. package/node_modules/@oxygen/shared/dist/linkedin-countries.js +359 -0
  67. package/node_modules/@oxygen/shared/dist/log-sink-selector.d.ts +39 -0
  68. package/node_modules/@oxygen/shared/dist/log-sink-selector.js +56 -0
  69. package/node_modules/@oxygen/shared/dist/log.d.ts +1 -0
  70. package/node_modules/@oxygen/shared/dist/log.js +6 -1
  71. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +17 -0
  72. package/node_modules/@oxygen/shared/dist/object-storage.js +21 -0
  73. package/node_modules/@oxygen/shared/dist/otlp-log-sink.d.ts +54 -0
  74. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +213 -0
  75. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +1 -0
  76. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +23 -22
  77. package/node_modules/@oxygen/shared/dist/plan-limits.js +45 -18
  78. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +48 -41
  79. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +36 -25
  80. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +22 -22
  81. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +40 -34
  82. package/node_modules/@oxygen/shared/dist/product-analytics-environment.js +9 -0
  83. package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +15 -0
  84. package/node_modules/@oxygen/shared/dist/product-analytics-events.js +15 -0
  85. package/node_modules/@oxygen/shared/dist/rate-window.d.ts +5 -0
  86. package/node_modules/@oxygen/shared/dist/rate-window.js +8 -0
  87. package/node_modules/@oxygen/shared/dist/research-output-contract.js +1 -3
  88. package/node_modules/@oxygen/shared/dist/search-vocab.js +4 -5
  89. package/node_modules/@oxygen/shared/dist/select-options.js +6 -1
  90. package/node_modules/@oxygen/shared/dist/sequence-failures.js +1 -5
  91. package/node_modules/@oxygen/shared/dist/sequences.d.ts +23 -0
  92. package/node_modules/@oxygen/shared/dist/sequences.js +110 -4
  93. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +22 -10
  94. package/node_modules/@oxygen/shared/dist/spend-safety.js +15 -21
  95. package/node_modules/@oxygen/shared/dist/sql-rows.d.ts +1 -0
  96. package/node_modules/@oxygen/shared/dist/sql-rows.js +3 -0
  97. package/node_modules/@oxygen/shared/dist/telemetry.js +9 -1
  98. package/node_modules/@oxygen/shared/dist/type-guards.d.ts +22 -0
  99. package/node_modules/@oxygen/shared/dist/type-guards.js +35 -0
  100. package/node_modules/@oxygen/shared/dist/value-readers.d.ts +21 -0
  101. package/node_modules/@oxygen/shared/dist/value-readers.js +59 -0
  102. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  103. package/node_modules/@oxygen/shared/package.json +50 -0
  104. package/node_modules/@oxygen/workflows/dist/graph/expression.js +2 -5
  105. package/node_modules/@oxygen/workflows/dist/graph/params.js +1 -1
  106. package/package.json +2 -2
@@ -2,13 +2,38 @@ export declare const WEEKLY_USAGE_WINDOW_DAYS = 7;
2
2
  export declare const BILLING_CURRENCIES: readonly ["usd"];
3
3
  export type BillingCurrency = (typeof BILLING_CURRENCIES)[number];
4
4
  export declare const DEFAULT_BILLING_CURRENCY: BillingCurrency;
5
- export type SelfServePlanTier = "starter" | "pro" | "team";
5
+ /**
6
+ * The SIX purchasable rungs of the one "Oxygen" product (founder 2026-09-19).
7
+ *
8
+ * These are plan KEYS — what Stripe sells and what `subscriptions.tier` stores —
9
+ * not tiers. They all share the single `oxygen` entitlement tier, which is the
10
+ * coarse rung plan-limits.ts and spend-safety.ts enforce against.
11
+ *
12
+ * Why keys and not six tiers: six tiers would force six new columns into every
13
+ * `Record<PlanTier, …>` ladder (plan limits, trigger ceilings, BYOK caps), i.e.
14
+ * ~40 invented numbers on an axis nobody ratified. Why not reuse starter/pro/team
15
+ * instead: then `plan.tier` would be ambiguous between a grandfathered $99
16
+ * Starter and a $49 Oxygen, and plan-change.ts — which refuses when
17
+ * `currentTier === targetTier` — would call a real $49 -> $99 upgrade
18
+ * `plan_unchanged`.
19
+ */
20
+ export declare const OXYGEN_PLAN_KEYS: readonly ["oxygen_49", "oxygen_99", "oxygen_199", "oxygen_499", "oxygen_999", "oxygen_1999"];
21
+ export type OxygenPlanKey = (typeof OXYGEN_PLAN_KEYS)[number];
22
+ /**
23
+ * starter/pro/team were the self-serve catalog until 2026-09-19. They are no
24
+ * longer purchasable, but live subscriptions still bill against their Stripe
25
+ * prices, so they remain resolvable tiers forever.
26
+ */
27
+ export type LegacySelfServePlanTier = "starter" | "pro" | "team";
28
+ export type SelfServePlanTier = "oxygen" | LegacySelfServePlanTier;
6
29
  export type ContactSalesPlanTier = "scale" | "enterprise";
7
30
  export type PlanTier = "free" | SelfServePlanTier | ContactSalesPlanTier;
8
31
  export type UsageLimitedPlanTier = Exclude<PlanTier, "enterprise">;
9
32
  export type PricingPlanDefinition = {
10
33
  tier: PlanTier;
11
34
  name: string;
35
+ /** Grandfathered: still resolves and still bills, never offered for purchase. */
36
+ isLegacy?: boolean;
12
37
  monthlyPriceCents: number | null;
13
38
  monthlyCredits: number | null;
14
39
  weeklyCreditsLimit: number | null;
@@ -26,12 +51,12 @@ export type PricingPlanDefinition = {
26
51
  };
27
52
  export type PricingPlanMetadata = Record<string, unknown> | null | undefined;
28
53
  export declare const CONTACT_SALES_URL = "mailto:priority@oxygen-agent.com";
29
- export declare const CREDITS_PER_USD = 1000;
30
- export declare const TOPUP_USD_CENTS_PER_1K_CREDITS = 125;
31
- export declare const CREDIT_TOPUP_MIN_CREDITS = 8000;
32
- export declare const CREDIT_TOPUP_MAX_CREDITS = 1000000;
33
- export declare const CREDIT_TOPUP_STEP_CREDITS = 1000;
34
- export declare const CREDIT_TOPUP_DEFAULT_CREDITS = 20000;
54
+ export declare const CREDITS_PER_USD = 100;
55
+ export declare const TOPUP_USD_CENTS_PER_100_CREDITS = 125;
56
+ export declare const CREDIT_TOPUP_MIN_CREDITS = 800;
57
+ export declare const CREDIT_TOPUP_MAX_CREDITS = 100000;
58
+ export declare const CREDIT_TOPUP_STEP_CREDITS = 100;
59
+ export declare const CREDIT_TOPUP_DEFAULT_CREDITS = 2000;
35
60
  export declare function isValidCreditTopupCredits(credits: number): boolean;
36
61
  /**
37
62
  * A shortfall expressed as an amount `oxygen billing topup` will actually SELL:
@@ -51,7 +76,7 @@ export declare function isValidCreditTopupCredits(credits: number): boolean;
51
76
  */
52
77
  export declare function creditTopupAmountForShortfall(credits: number): number;
53
78
  export declare function creditTopupUsdCents(credits: number): number | null;
54
- export declare const AUTOMATION_ACTION_CREDITS = 0.01;
79
+ export declare const AUTOMATION_ACTION_CREDITS = 0.001;
55
80
  /** Kinds of resource that carry a fixed monthly credit commitment. */
56
81
  export declare const CREDIT_COMMITMENT_KINDS: readonly ["sending_mailbox", "managed_mailbox", "mailbox_warmup", "deliverability_unit", "linkedin_account", "whatsapp_account"];
57
82
  export type CreditCommitmentKind = (typeof CREDIT_COMMITMENT_KINDS)[number];
@@ -61,12 +86,12 @@ export type CreditCommitmentKind = (typeof CREDIT_COMMITMENT_KINDS)[number];
61
86
  * Gmail and Microsoft inboxes included — and it STACKS on Oxygen-sold mailboxes,
62
87
  * which additionally pay their own mailbox/warmup/placement lines.
63
88
  */
64
- export declare const SENDING_MAILBOX_MONTHLY_CREDITS = 1000;
89
+ export declare const SENDING_MAILBOX_MONTHLY_CREDITS = 100;
65
90
  /**
66
91
  * Oxygen-sold managed mailbox per month, in credits ($3.00). Flat, superseding
67
92
  * the dynamic vendor-COGS x 1.25 quote for the recurring mailbox line.
68
93
  */
69
- export declare const MANAGED_MAILBOX_MONTHLY_CREDITS = 3000;
94
+ export declare const MANAGED_MAILBOX_MONTHLY_CREDITS = 300;
70
95
  /**
71
96
  * Grace window after a commitment goes past_due before the owning subsystem may
72
97
  * suspend the resource. Notify -> pause -> lapse; never auto-cancel. Aligned with
@@ -109,25 +134,25 @@ export declare function ratifiedCommitmentCredits(kind: CreditCommitmentKind): n
109
134
  export declare const CREDIT_TOPUP_PACKS: readonly [{
110
135
  readonly id: "10";
111
136
  readonly usdCents: 1000;
112
- readonly credits: 8000;
137
+ readonly credits: 800;
113
138
  }, {
114
139
  readonly id: "25";
115
140
  readonly usdCents: 2500;
116
- readonly credits: 20000;
141
+ readonly credits: 2000;
117
142
  }, {
118
143
  readonly id: "100";
119
144
  readonly usdCents: 10000;
120
- readonly credits: 80000;
145
+ readonly credits: 8000;
121
146
  }, {
122
147
  readonly id: "250";
123
148
  readonly usdCents: 25000;
124
- readonly credits: 200000;
149
+ readonly credits: 20000;
125
150
  }];
126
151
  export type CreditTopupPack = (typeof CREDIT_TOPUP_PACKS)[number];
127
152
  export type CreditTopupPackId = CreditTopupPack["id"];
128
153
  export declare function resolveCreditTopupPack(id: string | null | undefined): CreditTopupPack | null;
129
154
  export declare const TRIAL_PERIOD_DAYS = 7;
130
- export declare const TRIAL_CREDIT_GRANT = 20000;
155
+ export declare const TRIAL_CREDIT_GRANT = 2000;
131
156
  /**
132
157
  * Free-tier entry (founder-ratified 2026-08-16; grant collapsed to a single
133
158
  * 10,000-credit signup grant 2026-08-26).
@@ -153,7 +178,7 @@ export declare const TRIAL_CREDIT_GRANT = 20000;
153
178
  * mints it a second time. Top-ups stay purchasable on free, which is what keeps
154
179
  * the metered surface open-ended rather than capped at the grant.
155
180
  */
156
- export declare const FREE_SIGNUP_GRANT_CREDITS = 10000;
181
+ export declare const FREE_SIGNUP_GRANT_CREDITS = 1000;
157
182
  export declare const FREE_TIER_GRANTS_ENABLED_ENV_VAR = "OXYGEN_FREE_TIER_GRANTS_ENABLED";
158
183
  /**
159
184
  * Fail-closed rollout switch for the free-tier grants, matching the staged
@@ -168,8 +193,8 @@ export declare const FREE_TIER_GRANTS_ENABLED_ENV_VAR = "OXYGEN_FREE_TIER_GRANTS
168
193
  * population before the cutover posture is decided.
169
194
  */
170
195
  export declare function freeTierGrantsEnabled(env?: Record<string, string | undefined>): boolean;
171
- export declare const WALKTHROUGH_COMPLETION_BONUS_CREDITS = 1000;
172
- export declare const WALKTHROUGH_SCRAPE_MAX_CREDITS = 2000;
196
+ export declare const WALKTHROUGH_COMPLETION_BONUS_CREDITS = 100;
197
+ export declare const WALKTHROUGH_SCRAPE_MAX_CREDITS = 200;
173
198
  export declare const BASE_PRICING_PLANS: {
174
199
  readonly free: {
175
200
  readonly monthlyPriceCents: number | null;
@@ -186,6 +211,23 @@ export declare const BASE_PRICING_PLANS: {
186
211
  readonly ctaLabel: "Upgrade";
187
212
  readonly features: readonly ["CRM, Tables, Workflows, and Knowledge — unmetered", "Sequences: author, preview, and enroll", "Agents and Workspace Copilot", "Credits for enrichment and AI, topped up any time"];
188
213
  };
214
+ readonly oxygen: {
215
+ readonly monthlyPriceCents: number | null;
216
+ readonly monthlyCredits: number | null;
217
+ readonly weeklyCreditsLimit: number | null;
218
+ readonly rolloverCap: number | null;
219
+ readonly byokEnabled: boolean;
220
+ readonly tier: "oxygen";
221
+ readonly name: "Oxygen";
222
+ readonly monthlyAutomationActions: null;
223
+ readonly automationOverageCentsPerMillion: null;
224
+ readonly automationOverageEnabledDefault: false;
225
+ readonly description: "Your whole GTM stack. One plan — choose the credits you need.";
226
+ readonly badge: "Your whole GTM stack";
227
+ readonly highlighted: true;
228
+ readonly ctaLabel: "Get started";
229
+ readonly features: readonly [string, "All integrations", "Workflows", "Bring your own keys", "Standard support"];
230
+ };
189
231
  readonly starter: {
190
232
  readonly monthlyPriceCents: number | null;
191
233
  readonly monthlyCredits: number | null;
@@ -194,12 +236,13 @@ export declare const BASE_PRICING_PLANS: {
194
236
  readonly byokEnabled: boolean;
195
237
  readonly tier: "starter";
196
238
  readonly name: "Starter";
239
+ readonly isLegacy: true;
197
240
  readonly monthlyAutomationActions: null;
198
241
  readonly automationOverageCentsPerMillion: null;
199
242
  readonly automationOverageEnabledDefault: false;
200
243
  readonly description: "For founders running focused managed enrichment and AI columns.";
201
244
  readonly ctaLabel: "Choose Starter";
202
- readonly features: readonly ["99,000 credits every month", "All integrations", "Workflows", "Bring your own keys", "Standard support"];
245
+ readonly features: readonly [string, "All integrations", "Workflows", "Bring your own keys", "Standard support"];
203
246
  };
204
247
  readonly pro: {
205
248
  readonly monthlyPriceCents: number | null;
@@ -209,6 +252,7 @@ export declare const BASE_PRICING_PLANS: {
209
252
  readonly byokEnabled: boolean;
210
253
  readonly tier: "pro";
211
254
  readonly name: "Pro";
255
+ readonly isLegacy: true;
212
256
  readonly monthlyAutomationActions: null;
213
257
  readonly automationOverageCentsPerMillion: null;
214
258
  readonly automationOverageEnabledDefault: false;
@@ -216,7 +260,7 @@ export declare const BASE_PRICING_PLANS: {
216
260
  readonly badge: "Most popular";
217
261
  readonly highlighted: true;
218
262
  readonly ctaLabel: "Choose Pro";
219
- readonly features: readonly ["249,000 credits every month", "All integrations", "Workflows", "Bring your own keys", "Standard support"];
263
+ readonly features: readonly [string, "All integrations", "Workflows", "Bring your own keys", "Standard support"];
220
264
  };
221
265
  readonly team: {
222
266
  readonly monthlyPriceCents: number | null;
@@ -226,12 +270,13 @@ export declare const BASE_PRICING_PLANS: {
226
270
  readonly byokEnabled: boolean;
227
271
  readonly tier: "team";
228
272
  readonly name: "Team";
273
+ readonly isLegacy: true;
229
274
  readonly monthlyAutomationActions: null;
230
275
  readonly automationOverageCentsPerMillion: null;
231
276
  readonly automationOverageEnabledDefault: false;
232
277
  readonly description: "For small GTM teams and agencies running shared workflows with their own AI keys.";
233
278
  readonly ctaLabel: "Choose Team";
234
- readonly features: readonly ["749,000 credits every month", "All integrations", "Workflows", "Bring your own keys", "Premium support"];
279
+ readonly features: readonly [string, "All integrations", "Workflows", "Bring your own keys", "Premium support"];
235
280
  };
236
281
  readonly scale: {
237
282
  readonly monthlyPriceCents: number | null;
@@ -247,7 +292,7 @@ export declare const BASE_PRICING_PLANS: {
247
292
  readonly description: "For high-volume GTM teams that need custom limits and rollout support.";
248
293
  readonly ctaLabel: "Contact sales";
249
294
  readonly contactHref: "mailto:priority@oxygen-agent.com";
250
- readonly features: readonly ["10,000,000+ managed credits / month", "Workflows", "Phone number enrichment on managed credits", "Custom provider routing and BYOK policies", "Dedicated onboarding"];
295
+ readonly features: readonly [string, "Workflows", "Phone number enrichment on managed credits", "Custom provider routing and BYOK policies", "Dedicated onboarding"];
251
296
  };
252
297
  readonly enterprise: {
253
298
  readonly monthlyPriceCents: number | null;
@@ -266,8 +311,17 @@ export declare const BASE_PRICING_PLANS: {
266
311
  readonly features: readonly ["Everything in Team", "Custom usage limits", "Volume pricing", "Dedicated support"];
267
312
  };
268
313
  };
314
+ /** One public card; the six rungs are a selector inside it. */
269
315
  export declare const PUBLIC_PLAN_ORDER: readonly PlanTier[];
316
+ /**
317
+ * Tiers whose Stripe prices must still RESOLVE. Deliberately wider than what is
318
+ * purchasable: starter/pro/team are grandfathered, so a live subscription on one
319
+ * of their prices must keep mapping to a plan. Use PURCHASABLE_PLAN_KEYS for
320
+ * anything that offers a plan for sale.
321
+ */
270
322
  export declare const SELF_SERVE_PLAN_TIERS: readonly SelfServePlanTier[];
323
+ /** What a customer can actually buy or switch to, cheapest first. */
324
+ export declare const PURCHASABLE_PLAN_KEYS: readonly OxygenPlanKey[];
271
325
  export declare const CONTACT_SALES_PLAN_TIERS: readonly ContactSalesPlanTier[];
272
326
  export declare const ACTIVE_SUBSCRIPTION_STATUSES: readonly ["active", "trialing", "past_due"];
273
327
  export type ActiveSubscriptionStatus = (typeof ACTIVE_SUBSCRIPTION_STATUSES)[number];
@@ -294,6 +348,8 @@ export declare function resolveBasePricingPlan(tier: string | null | undefined):
294
348
  export declare function applyPricingPlanMetadataOverrides(// skipcq: JS-R1005
295
349
  plan: PricingPlanDefinition, metadata: PricingPlanMetadata): PricingPlanDefinition;
296
350
  export declare function isSelfServePlanTier(value: string): value is SelfServePlanTier;
351
+ /** True for the six rungs a customer may buy or switch to. */
352
+ export declare function isPurchasablePlanKey(value: string): value is OxygenPlanKey;
297
353
  export declare function isBillingCurrency(value: string): value is BillingCurrency;
298
354
  export declare function normalizeBillingCurrency(value: string | null | undefined): BillingCurrency;
299
355
  export declare function getCurrentFreeTierCycleKey(date?: Date): string;
@@ -1,34 +1,62 @@
1
- import { AUTOMATION_ACTION_CREDITS as SNAPSHOT_AUTOMATION_ACTION_CREDITS, CREDITS_PER_USD as SNAPSHOT_CREDITS_PER_USD, PRICING_PLAN_SNAPSHOT, TOPUP_USD_CENTS_PER_1K_CREDITS as SNAPSHOT_TOPUP_USD_CENTS_PER_1K_CREDITS, } from "./pricing-snapshot.generated.js";
1
+ import { AUTOMATION_ACTION_CREDITS as SNAPSHOT_AUTOMATION_ACTION_CREDITS, CREDITS_PER_USD as SNAPSHOT_CREDITS_PER_USD, PRICING_PLAN_SNAPSHOT, TOPUP_USD_CENTS_PER_100_CREDITS as SNAPSHOT_TOPUP_USD_CENTS_PER_100_CREDITS, } from "./pricing-snapshot.generated.js";
2
2
  import { freeTierEntitlementEnabled } from "./plan-capabilities.js";
3
+ import { asRecordOrNull } from "./type-guards.js";
3
4
  export const WEEKLY_USAGE_WINDOW_DAYS = 7;
4
5
  export const BILLING_CURRENCIES = ["usd"];
5
6
  export const DEFAULT_BILLING_CURRENCY = "usd";
7
+ /**
8
+ * The SIX purchasable rungs of the one "Oxygen" product (founder 2026-09-19).
9
+ *
10
+ * These are plan KEYS — what Stripe sells and what `subscriptions.tier` stores —
11
+ * not tiers. They all share the single `oxygen` entitlement tier, which is the
12
+ * coarse rung plan-limits.ts and spend-safety.ts enforce against.
13
+ *
14
+ * Why keys and not six tiers: six tiers would force six new columns into every
15
+ * `Record<PlanTier, …>` ladder (plan limits, trigger ceilings, BYOK caps), i.e.
16
+ * ~40 invented numbers on an axis nobody ratified. Why not reuse starter/pro/team
17
+ * instead: then `plan.tier` would be ambiguous between a grandfathered $99
18
+ * Starter and a $49 Oxygen, and plan-change.ts — which refuses when
19
+ * `currentTier === targetTier` — would call a real $49 -> $99 upgrade
20
+ * `plan_unchanged`.
21
+ */
22
+ export const OXYGEN_PLAN_KEYS = [
23
+ "oxygen_49",
24
+ "oxygen_99",
25
+ "oxygen_199",
26
+ "oxygen_499",
27
+ "oxygen_999",
28
+ "oxygen_1999",
29
+ ];
6
30
  // Scale/Enterprise contact routes to the shared support inbox, not to a
7
31
  // founder's calendar. priority@oxygen-agent.com is the Plain Email channel
8
32
  // (PLAIN_SUPPORT_EMAIL_ADDRESS), so an enterprise enquiry lands in the support
9
33
  // queue as a Thread that either founder can pick up, instead of hard-coding one
10
34
  // person's booking page into every public pricing card.
11
35
  export const CONTACT_SALES_URL = "mailto:priority@oxygen-agent.com";
12
- // One Oxygen credit is worth $0.001 of managed work: $1 = 1,000 credits.
36
+ // One Oxygen credit is worth $0.01 of managed work: $1 = 100 credits.
13
37
  // Subscription plans convert at face value — every subscription dollar grants
14
- // exactly 1,000 credits — while on-demand top-up packs price the same credit
15
- // at $1.25 per 1,000, making subscription credits exactly 20% cheaper than
38
+ // exactly 100 credits — while on-demand top-up packs price the same credit
39
+ // at $1.25 per 100, making subscription credits exactly 20% cheaper than
16
40
  // credits bought on demand.
17
41
  //
42
+ // Re-denominated from $1 = 1,000 credits on 2026-09-19. That was a PURE unit
43
+ // change: every credit-denominated price divided by 10 in the same release, so
44
+ // the USD cost of every action is unchanged.
45
+ //
18
46
  // Sourced from the generated snapshot rather than declared here: this pair was
19
47
  // previously written down in seven production modules, and if any two ever
20
48
  // disagreed every markup-derived price would be silently wrong by the ratio.
21
49
  // Change them in packages/control-db/src/pricing/seed.ts.
22
50
  export const CREDITS_PER_USD = SNAPSHOT_CREDITS_PER_USD;
23
- export const TOPUP_USD_CENTS_PER_1K_CREDITS = SNAPSHOT_TOPUP_USD_CENTS_PER_1K_CREDITS;
51
+ export const TOPUP_USD_CENTS_PER_100_CREDITS = SNAPSHOT_TOPUP_USD_CENTS_PER_100_CREDITS;
24
52
  // On-demand purchases start at the original fixed packs' $10 floor and run up
25
- // to a $1,250 ceiling, in any 1,000-credit increment. The ceiling is a
53
+ // to a $1,250 ceiling, in any 100-credit increment. The ceiling is a
26
54
  // single-checkout guard rail, not a spend cap: a workspace that needs more
27
55
  // tops up again (purchased credits never expire).
28
- export const CREDIT_TOPUP_MIN_CREDITS = 8_000;
29
- export const CREDIT_TOPUP_MAX_CREDITS = 1_000_000;
30
- export const CREDIT_TOPUP_STEP_CREDITS = 1_000;
31
- export const CREDIT_TOPUP_DEFAULT_CREDITS = 20_000;
56
+ export const CREDIT_TOPUP_MIN_CREDITS = 800;
57
+ export const CREDIT_TOPUP_MAX_CREDITS = 100_000;
58
+ export const CREDIT_TOPUP_STEP_CREDITS = 100;
59
+ export const CREDIT_TOPUP_DEFAULT_CREDITS = 2_000;
32
60
  export function isValidCreditTopupCredits(credits) {
33
61
  return Number.isInteger(credits)
34
62
  && credits >= CREDIT_TOPUP_MIN_CREDITS
@@ -58,7 +86,7 @@ export function creditTopupAmountForShortfall(credits) {
58
86
  export function creditTopupUsdCents(credits) {
59
87
  if (!isValidCreditTopupCredits(credits))
60
88
  return null;
61
- return (credits / 1_000) * TOPUP_USD_CENTS_PER_1K_CREDITS;
89
+ return (credits / 100) * TOPUP_USD_CENTS_PER_100_CREDITS;
62
90
  }
63
91
  // Workflow/automation actions (steps, tool calls, row writes, retries) draw
64
92
  // from the same credit pool at a flat capacity-guard rate — the old separate
@@ -101,12 +129,12 @@ export const CREDIT_COMMITMENT_KINDS = [
101
129
  * Gmail and Microsoft inboxes included — and it STACKS on Oxygen-sold mailboxes,
102
130
  * which additionally pay their own mailbox/warmup/placement lines.
103
131
  */
104
- export const SENDING_MAILBOX_MONTHLY_CREDITS = 1_000;
132
+ export const SENDING_MAILBOX_MONTHLY_CREDITS = 100;
105
133
  /**
106
134
  * Oxygen-sold managed mailbox per month, in credits ($3.00). Flat, superseding
107
135
  * the dynamic vendor-COGS x 1.25 quote for the recurring mailbox line.
108
136
  */
109
- export const MANAGED_MAILBOX_MONTHLY_CREDITS = 3_000;
137
+ export const MANAGED_MAILBOX_MONTHLY_CREDITS = 300;
110
138
  /**
111
139
  * Grace window after a commitment goes past_due before the owning subsystem may
112
140
  * suspend the resource. Notify -> pause -> lapse; never auto-cancel. Aligned with
@@ -168,10 +196,10 @@ export function ratifiedCommitmentCredits(kind) {
168
196
  }
169
197
  }
170
198
  export const CREDIT_TOPUP_PACKS = [
171
- { id: "10", usdCents: 1_000, credits: 8_000 },
172
- { id: "25", usdCents: 2_500, credits: 20_000 },
173
- { id: "100", usdCents: 10_000, credits: 80_000 },
174
- { id: "250", usdCents: 25_000, credits: 200_000 },
199
+ { id: "10", usdCents: 1_000, credits: 800 },
200
+ { id: "25", usdCents: 2_500, credits: 2_000 },
201
+ { id: "100", usdCents: 10_000, credits: 8_000 },
202
+ { id: "250", usdCents: 25_000, credits: 20_000 },
175
203
  ];
176
204
  export function resolveCreditTopupPack(id) {
177
205
  if (!id)
@@ -184,7 +212,7 @@ export function resolveCreditTopupPack(id) {
184
212
  // to that paid plan on credit exhaustion or when the trial clock elapses,
185
213
  // whichever comes first. Starter remains the signup default.
186
214
  export const TRIAL_PERIOD_DAYS = 7;
187
- export const TRIAL_CREDIT_GRANT = 20_000;
215
+ export const TRIAL_CREDIT_GRANT = 2_000;
188
216
  /**
189
217
  * Free-tier entry (founder-ratified 2026-08-16; grant collapsed to a single
190
218
  * 10,000-credit signup grant 2026-08-26).
@@ -210,7 +238,7 @@ export const TRIAL_CREDIT_GRANT = 20_000;
210
238
  * mints it a second time. Top-ups stay purchasable on free, which is what keeps
211
239
  * the metered surface open-ended rather than capped at the grant.
212
240
  */
213
- export const FREE_SIGNUP_GRANT_CREDITS = 10_000;
241
+ export const FREE_SIGNUP_GRANT_CREDITS = 1_000;
214
242
  export const FREE_TIER_GRANTS_ENABLED_ENV_VAR = "OXYGEN_FREE_TIER_GRANTS_ENABLED";
215
243
  /**
216
244
  * Fail-closed rollout switch for the free-tier grants, matching the staged
@@ -236,8 +264,8 @@ export function freeTierGrantsEnabled(env = process.env) {
236
264
  // "start scraping engagers" step may spend at most this many credits on the
237
265
  // managed cookieless scraper (founder-approved budget; the rest of the kickoff
238
266
  // is free connected-account reads).
239
- export const WALKTHROUGH_COMPLETION_BONUS_CREDITS = 1_000;
240
- export const WALKTHROUGH_SCRAPE_MAX_CREDITS = 2_000;
267
+ export const WALKTHROUGH_COMPLETION_BONUS_CREDITS = 100;
268
+ export const WALKTHROUGH_SCRAPE_MAX_CREDITS = 200;
241
269
  /**
242
270
  * The five NUMERIC fields of a plan, read from the generated pricing snapshot.
243
271
  *
@@ -262,6 +290,20 @@ function planPricing(planKey) {
262
290
  byokEnabled: row.byokEnabled,
263
291
  };
264
292
  }
293
+ /**
294
+ * The monthly-credit feature bullet, DERIVED rather than written down.
295
+ *
296
+ * These strings used to be hand-typed literals ("99,000 credits every month").
297
+ * A re-denomination then had to find and retype every one of them, which is
298
+ * exactly how a price sheet ends up quoting a number the product does not
299
+ * charge. Never reintroduce a literal here.
300
+ */
301
+ function monthlyCreditsFeature(planKey) {
302
+ const credits = planPricing(planKey).monthlyCredits;
303
+ if (credits === null)
304
+ return "Custom monthly credits";
305
+ return `${credits.toLocaleString("en-US")} credits every month`;
306
+ }
265
307
  export const BASE_PRICING_PLANS = {
266
308
  // The ENTRY tier since 2026-08-16, superseding the 2026-07-22 retirement that
267
309
  // left this as the unentitled fallback for churned / never-subscribed orgs.
@@ -294,9 +336,33 @@ export const BASE_PRICING_PLANS = {
294
336
  "Credits for enrichment and AI, topped up any time",
295
337
  ],
296
338
  },
339
+ // The one purchasable product since 2026-09-19. Its numbers are the ENTRY
340
+ // rung ($49); the other five live in OXYGEN_PLAN_OVERRIDES and share this
341
+ // tier. Anything that needs a rung's real allowance must resolve the plan
342
+ // KEY (resolveBasePricingPlan("oxygen_499")), never this representative row.
343
+ oxygen: {
344
+ tier: "oxygen",
345
+ name: "Oxygen",
346
+ ...planPricing("oxygen_49"),
347
+ monthlyAutomationActions: null,
348
+ automationOverageCentsPerMillion: null,
349
+ automationOverageEnabledDefault: false,
350
+ description: "Your whole GTM stack. One plan — choose the credits you need.",
351
+ badge: "Your whole GTM stack",
352
+ highlighted: true,
353
+ ctaLabel: "Get started",
354
+ features: [
355
+ monthlyCreditsFeature("oxygen_49"),
356
+ "All integrations",
357
+ "Workflows",
358
+ "Bring your own keys",
359
+ "Standard support",
360
+ ],
361
+ },
297
362
  starter: {
298
363
  tier: "starter",
299
364
  name: "Starter",
365
+ isLegacy: true,
300
366
  ...planPricing("starter"),
301
367
  monthlyAutomationActions: null,
302
368
  automationOverageCentsPerMillion: null,
@@ -304,7 +370,7 @@ export const BASE_PRICING_PLANS = {
304
370
  description: "For founders running focused managed enrichment and AI columns.",
305
371
  ctaLabel: "Choose Starter",
306
372
  features: [
307
- "99,000 credits every month",
373
+ monthlyCreditsFeature("starter"),
308
374
  "All integrations",
309
375
  "Workflows",
310
376
  "Bring your own keys",
@@ -314,6 +380,7 @@ export const BASE_PRICING_PLANS = {
314
380
  pro: {
315
381
  tier: "pro",
316
382
  name: "Pro",
383
+ isLegacy: true,
317
384
  ...planPricing("pro"),
318
385
  monthlyAutomationActions: null,
319
386
  automationOverageCentsPerMillion: null,
@@ -323,7 +390,7 @@ export const BASE_PRICING_PLANS = {
323
390
  highlighted: true,
324
391
  ctaLabel: "Choose Pro",
325
392
  features: [
326
- "249,000 credits every month",
393
+ monthlyCreditsFeature("pro"),
327
394
  "All integrations",
328
395
  "Workflows",
329
396
  "Bring your own keys",
@@ -333,6 +400,7 @@ export const BASE_PRICING_PLANS = {
333
400
  team: {
334
401
  tier: "team",
335
402
  name: "Team",
403
+ isLegacy: true,
336
404
  ...planPricing("team"),
337
405
  monthlyAutomationActions: null,
338
406
  automationOverageCentsPerMillion: null,
@@ -340,7 +408,7 @@ export const BASE_PRICING_PLANS = {
340
408
  description: "For small GTM teams and agencies running shared workflows with their own AI keys.",
341
409
  ctaLabel: "Choose Team",
342
410
  features: [
343
- "749,000 credits every month",
411
+ monthlyCreditsFeature("team"),
344
412
  "All integrations",
345
413
  "Workflows",
346
414
  "Bring your own keys",
@@ -358,7 +426,7 @@ export const BASE_PRICING_PLANS = {
358
426
  ctaLabel: "Contact sales",
359
427
  contactHref: CONTACT_SALES_URL,
360
428
  features: [
361
- "10,000,000+ managed credits / month",
429
+ monthlyCreditsFeature("scale"),
362
430
  "Workflows",
363
431
  "Phone number enrichment on managed credits",
364
432
  "Custom provider routing and BYOK policies",
@@ -383,16 +451,22 @@ export const BASE_PRICING_PLANS = {
383
451
  ],
384
452
  },
385
453
  };
386
- export const PUBLIC_PLAN_ORDER = [
387
- "starter",
388
- "pro",
389
- "team",
390
- ];
454
+ /** One public card; the six rungs are a selector inside it. */
455
+ export const PUBLIC_PLAN_ORDER = ["oxygen"];
456
+ /**
457
+ * Tiers whose Stripe prices must still RESOLVE. Deliberately wider than what is
458
+ * purchasable: starter/pro/team are grandfathered, so a live subscription on one
459
+ * of their prices must keep mapping to a plan. Use PURCHASABLE_PLAN_KEYS for
460
+ * anything that offers a plan for sale.
461
+ */
391
462
  export const SELF_SERVE_PLAN_TIERS = [
463
+ "oxygen",
392
464
  "starter",
393
465
  "pro",
394
466
  "team",
395
467
  ];
468
+ /** What a customer can actually buy or switch to, cheapest first. */
469
+ export const PURCHASABLE_PLAN_KEYS = OXYGEN_PLAN_KEYS;
396
470
  export const CONTACT_SALES_PLAN_TIERS = [
397
471
  "scale",
398
472
  "enterprise",
@@ -465,6 +539,37 @@ export function resolveSubscriptionEntitlement(input) {
465
539
  }
466
540
  return { entitled: false, reason: "missing_subscription", graceEndsAt: null };
467
541
  }
542
+ /**
543
+ * The six purchasable rungs, keyed by plan key.
544
+ *
545
+ * Each is the representative `oxygen` plan with that rung's real price and
546
+ * allowance substituted in. `tier` stays "oxygen" for all six — the rung is the
547
+ * key, the entitlement is the tier.
548
+ */
549
+ const OXYGEN_PLAN_OVERRIDES = {
550
+ oxygen_49: oxygenRung("oxygen_49"),
551
+ oxygen_99: oxygenRung("oxygen_99"),
552
+ oxygen_199: oxygenRung("oxygen_199"),
553
+ oxygen_499: oxygenRung("oxygen_499"),
554
+ oxygen_999: oxygenRung("oxygen_999"),
555
+ oxygen_1999: oxygenRung("oxygen_1999"),
556
+ };
557
+ function oxygenRung(planKey) {
558
+ const pricing = planPricing(planKey);
559
+ const dollars = pricing.monthlyPriceCents === null
560
+ ? null
561
+ : Math.round(pricing.monthlyPriceCents / 100);
562
+ return {
563
+ ...BASE_PRICING_PLANS.oxygen,
564
+ ...pricing,
565
+ name: dollars === null ? "Oxygen" : `Oxygen $${dollars.toLocaleString("en-US")}`,
566
+ ctaLabel: dollars === null ? "Get started" : `Choose $${dollars.toLocaleString("en-US")}`,
567
+ features: [
568
+ monthlyCreditsFeature(planKey),
569
+ ...BASE_PRICING_PLANS.oxygen.features.slice(1),
570
+ ],
571
+ };
572
+ }
468
573
  const LEGACY_PRICING_PLAN_OVERRIDES = {
469
574
  launch_50: {
470
575
  ...BASE_PRICING_PLANS.starter,
@@ -515,6 +620,12 @@ const LEGACY_PRICING_PLAN_OVERRIDES = {
515
620
  export function resolveBasePricingPlan(tier) {
516
621
  if (!tier)
517
622
  return null;
623
+ // Plan KEYS before tiers: `subscriptions.tier` stores "oxygen_499", and the
624
+ // rung's own allowance — not the representative $49 row — is what the
625
+ // customer paid for.
626
+ const oxygen = OXYGEN_PLAN_OVERRIDES[tier];
627
+ if (oxygen)
628
+ return oxygen;
518
629
  if (tier in BASE_PRICING_PLANS) {
519
630
  return BASE_PRICING_PLANS[tier];
520
631
  }
@@ -523,13 +634,13 @@ export function resolveBasePricingPlan(tier) {
523
634
  }
524
635
  export function applyPricingPlanMetadataOverrides(// skipcq: JS-R1005
525
636
  plan, metadata) {
526
- const record = readRecord(metadata);
637
+ const record = asRecordOrNull(metadata);
527
638
  if (!record)
528
639
  return plan;
529
- const config = readRecord(record.billing_plan)
530
- ?? readRecord(record.custom_plan)
531
- ?? readRecord(record.custom_limits)
532
- ?? readRecord(record.plan_limits)
640
+ const config = asRecordOrNull(record.billing_plan)
641
+ ?? asRecordOrNull(record.custom_plan)
642
+ ?? asRecordOrNull(record.custom_limits)
643
+ ?? asRecordOrNull(record.plan_limits)
533
644
  ?? record;
534
645
  const name = readString(config, "name")
535
646
  ?? readString(config, "plan_name")
@@ -567,17 +678,16 @@ plan, metadata) {
567
678
  export function isSelfServePlanTier(value) {
568
679
  return SELF_SERVE_PLAN_TIERS.includes(value);
569
680
  }
681
+ /** True for the six rungs a customer may buy or switch to. */
682
+ export function isPurchasablePlanKey(value) {
683
+ return PURCHASABLE_PLAN_KEYS.includes(value);
684
+ }
570
685
  export function isBillingCurrency(value) {
571
686
  return BILLING_CURRENCIES.includes(value);
572
687
  }
573
688
  export function normalizeBillingCurrency(value) {
574
689
  return value && isBillingCurrency(value) ? value : DEFAULT_BILLING_CURRENCY;
575
690
  }
576
- function readRecord(value) {
577
- if (!value || typeof value !== "object" || Array.isArray(value))
578
- return null;
579
- return value;
580
- }
581
691
  function readString(record, key) {
582
692
  const value = record[key];
583
693
  return typeof value === "string" && value.trim() ? value.trim() : null;
@@ -1,3 +1,4 @@
1
+ import { type EnrichmentIntentTaxonomyEntry } from "./enrichment-intents.js";
1
2
  import { type RecipePrimitive } from "./recipes.js";
2
3
  export type CapabilityLayer = "Control" | "Knowledge" | "Data" | "Action" | "External";
3
4
  export type CapabilityPosture = "read_only" | "workspace_write" | "paid_read" | "external_write" | "mixed";
@@ -29,6 +30,22 @@ export type CapabilityRouteMatch = {
29
30
  * intent is that narrow; `recommendedCommands[0]` is the same command.
30
31
  */
31
32
  exactCommand?: string;
33
+ /**
34
+ * The opinionated enrichment catalogue row a data-type ask resolves to
35
+ * ("get the funding round" -> enrich_company:funding). Present only when
36
+ * the ask names a data type; the catalogue command is then the first
37
+ * recommendation, ahead of any raw provider tool.
38
+ */
39
+ catalogIntent?: {
40
+ id: string;
41
+ label: string;
42
+ status: EnrichmentIntentTaxonomyEntry["status"];
43
+ group: EnrichmentIntentTaxonomyEntry["group"];
44
+ /** The catalogue-first path: read the row, then add/preview; `exactCommand` names the row. */
45
+ tools: string[];
46
+ commands: string[];
47
+ exactCommand: string;
48
+ };
32
49
  };
33
50
  export type PrimitiveRouteMatch = CapabilityRouteMatch & {
34
51
  card: PrimitiveRouteCard;