@oxygen-agent/cli 1.982.3 → 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 (127) 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 +27 -7
  9. package/dist/help.d.ts +29 -0
  10. package/dist/help.js +139 -0
  11. package/dist/index.js +1875 -164
  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/ugc-commands.d.ts +3 -6
  20. package/dist/ugc-commands.js +2 -1200
  21. package/dist/util.d.ts +1 -1
  22. package/dist/util.js +1 -3
  23. package/node_modules/@oxygen/cli-ugc/dist/commands.d.ts +3 -0
  24. package/node_modules/@oxygen/cli-ugc/dist/commands.js +1178 -0
  25. package/node_modules/@oxygen/cli-ugc/dist/field-parser.d.ts +7 -0
  26. package/node_modules/@oxygen/cli-ugc/dist/field-parser.js +25 -0
  27. package/node_modules/@oxygen/cli-ugc/dist/index.d.ts +14 -0
  28. package/node_modules/@oxygen/cli-ugc/dist/index.js +5 -0
  29. package/node_modules/@oxygen/cli-ugc/package.json +15 -0
  30. package/node_modules/@oxygen/formula/dist/coerce.d.ts +10 -0
  31. package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
  32. package/node_modules/@oxygen/formula/dist/expression.js +14 -1
  33. package/node_modules/@oxygen/formula/dist/formula-functions.js +136 -1
  34. package/node_modules/@oxygen/formula/dist/hash.d.ts +19 -0
  35. package/node_modules/@oxygen/formula/dist/hash.js +199 -0
  36. package/node_modules/@oxygen/formula/dist/index.d.ts +1 -0
  37. package/node_modules/@oxygen/formula/dist/index.js +1 -0
  38. package/node_modules/@oxygen/formula/dist/value-cleaners.d.ts +74 -0
  39. package/node_modules/@oxygen/formula/dist/value-cleaners.js +358 -0
  40. package/node_modules/@oxygen/shared/dist/array-utils.d.ts +5 -0
  41. package/node_modules/@oxygen/shared/dist/array-utils.js +11 -0
  42. package/node_modules/@oxygen/shared/dist/billing.d.ts +103 -47
  43. package/node_modules/@oxygen/shared/dist/billing.js +150 -40
  44. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +17 -0
  45. package/node_modules/@oxygen/shared/dist/capability-discovery.js +114 -16
  46. package/node_modules/@oxygen/shared/dist/column-autofill.d.ts +52 -0
  47. package/node_modules/@oxygen/shared/dist/column-autofill.js +80 -0
  48. package/node_modules/@oxygen/shared/dist/column-output-fields.js +14 -10
  49. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.d.ts +108 -0
  50. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.js +545 -0
  51. package/node_modules/@oxygen/shared/dist/copilot-playbooks.d.ts +18 -0
  52. package/node_modules/@oxygen/shared/dist/copilot-playbooks.js +43 -0
  53. package/node_modules/@oxygen/shared/dist/copilot-skills.d.ts +15 -0
  54. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +31 -0
  55. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +41 -0
  56. package/node_modules/@oxygen/shared/dist/copilot-skills.js +6 -0
  57. package/node_modules/@oxygen/shared/dist/deploy-env.d.ts +74 -0
  58. package/node_modules/@oxygen/shared/dist/deploy-env.js +82 -0
  59. package/node_modules/@oxygen/shared/dist/dnc-rules.d.ts +130 -0
  60. package/node_modules/@oxygen/shared/dist/dnc-rules.js +221 -0
  61. package/node_modules/@oxygen/shared/dist/enrichment-intents.d.ts +103 -0
  62. package/node_modules/@oxygen/shared/dist/enrichment-intents.js +819 -0
  63. package/node_modules/@oxygen/shared/dist/error-message.d.ts +1 -0
  64. package/node_modules/@oxygen/shared/dist/error-message.js +3 -0
  65. package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -3
  66. package/node_modules/@oxygen/shared/dist/external-write-policy.d.ts +33 -0
  67. package/node_modules/@oxygen/shared/dist/external-write-policy.js +68 -0
  68. package/node_modules/@oxygen/shared/dist/format-percent.d.ts +8 -0
  69. package/node_modules/@oxygen/shared/dist/format-percent.js +13 -0
  70. package/node_modules/@oxygen/shared/dist/freemail-domains.d.ts +81 -0
  71. package/node_modules/@oxygen/shared/dist/freemail-domains.js +157 -0
  72. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.d.ts +1 -0
  73. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.js +1 -1
  74. package/node_modules/@oxygen/shared/dist/index.d.ts +14 -0
  75. package/node_modules/@oxygen/shared/dist/index.js +14 -0
  76. package/node_modules/@oxygen/shared/dist/json-path.js +1 -3
  77. package/node_modules/@oxygen/shared/dist/knowledge-bases.js +1 -3
  78. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +17 -2
  79. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +28 -6
  80. package/node_modules/@oxygen/shared/dist/langfuse.d.ts +12 -1
  81. package/node_modules/@oxygen/shared/dist/langfuse.js +57 -8
  82. package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +32 -0
  83. package/node_modules/@oxygen/shared/dist/linkedin-countries.js +359 -0
  84. package/node_modules/@oxygen/shared/dist/log-sink-selector.d.ts +39 -0
  85. package/node_modules/@oxygen/shared/dist/log-sink-selector.js +56 -0
  86. package/node_modules/@oxygen/shared/dist/log.d.ts +1 -0
  87. package/node_modules/@oxygen/shared/dist/log.js +6 -1
  88. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +17 -0
  89. package/node_modules/@oxygen/shared/dist/object-storage.js +21 -0
  90. package/node_modules/@oxygen/shared/dist/otlp-log-sink.d.ts +54 -0
  91. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +213 -0
  92. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +1 -0
  93. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +23 -22
  94. package/node_modules/@oxygen/shared/dist/plan-limits.js +45 -18
  95. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +48 -41
  96. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +36 -25
  97. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +22 -22
  98. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +40 -34
  99. package/node_modules/@oxygen/shared/dist/product-analytics-environment.js +9 -0
  100. package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +15 -0
  101. package/node_modules/@oxygen/shared/dist/product-analytics-events.js +15 -0
  102. package/node_modules/@oxygen/shared/dist/rate-window.d.ts +5 -0
  103. package/node_modules/@oxygen/shared/dist/rate-window.js +8 -0
  104. package/node_modules/@oxygen/shared/dist/research-output-contract.d.ts +33 -1
  105. package/node_modules/@oxygen/shared/dist/research-output-contract.js +65 -5
  106. package/node_modules/@oxygen/shared/dist/search-vocab.js +4 -5
  107. package/node_modules/@oxygen/shared/dist/select-options.js +6 -1
  108. package/node_modules/@oxygen/shared/dist/sequence-crm-events.d.ts +1 -1
  109. package/node_modules/@oxygen/shared/dist/sequence-failures.js +1 -5
  110. package/node_modules/@oxygen/shared/dist/sequence-hubspot-sync.d.ts +1 -1
  111. package/node_modules/@oxygen/shared/dist/sequences.d.ts +49 -0
  112. package/node_modules/@oxygen/shared/dist/sequences.js +134 -4
  113. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +22 -10
  114. package/node_modules/@oxygen/shared/dist/spend-safety.js +15 -21
  115. package/node_modules/@oxygen/shared/dist/sql-rows.d.ts +1 -0
  116. package/node_modules/@oxygen/shared/dist/sql-rows.js +3 -0
  117. package/node_modules/@oxygen/shared/dist/telemetry.js +9 -1
  118. package/node_modules/@oxygen/shared/dist/type-guards.d.ts +22 -0
  119. package/node_modules/@oxygen/shared/dist/type-guards.js +35 -0
  120. package/node_modules/@oxygen/shared/dist/value-readers.d.ts +21 -0
  121. package/node_modules/@oxygen/shared/dist/value-readers.js +59 -0
  122. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  123. package/node_modules/@oxygen/shared/package.json +60 -0
  124. package/node_modules/@oxygen/workflows/dist/graph/expression.js +2 -5
  125. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +15 -15
  126. package/node_modules/@oxygen/workflows/dist/graph/params.js +1 -1
  127. package/package.json +6 -3
@@ -3,7 +3,7 @@
3
3
  * page's "what credits buy" table, the pricing calculator, and docs.
4
4
  *
5
5
  * Pricing Model 2.0 (founder-ratified 2026-07-14): ONE credit pool pays for
6
- * everything; 1 USD = 1,000 credits.
6
+ * everything; 1 USD = 100 credits.
7
7
  *
8
8
  * THIS FILE NO LONGER DECLARES PRICES. It used to carry hand-copied literals
9
9
  * under a comment asking the next person to remember to update them — which is
@@ -36,9 +36,9 @@
36
36
  */
37
37
  export { creditsToUsd, usdToCredits } from "./pricing-snapshot.generated.js";
38
38
  export declare const PRICING_SHEET_VERIFIED = "2026-07";
39
- export declare const PRICING_CREDITS_PER_USD = 1000;
40
- /** On-demand top-up price per 1,000 credits (USD); subscriptions pay $1.00. */
41
- export declare const TOPUP_USD_PER_1K = 1.25;
39
+ export declare const PRICING_CREDITS_PER_USD = 100;
40
+ /** On-demand top-up price per 100 credits (USD); subscriptions pay $1.00. */
41
+ export declare const TOPUP_USD_PER_100 = 1.25;
42
42
  export declare const SENDING_SEAT_USD_CENTS: {
43
43
  readonly linkedin: 3000;
44
44
  readonly whatsapp: 3000;
@@ -47,7 +47,7 @@ export declare const SENDING_SEAT_USD_CENTS: {
47
47
  };
48
48
  export declare const MANAGED_INBOX_USD_CENTS = 400;
49
49
  export declare const SENDING_DOMAIN_USD_CENTS = 1250;
50
- export declare const SUBSCRIPTION_USD_PER_1K = 1;
50
+ export declare const SUBSCRIPTION_USD_PER_100 = 1;
51
51
  /**
52
52
  * AI column runs, honest 5× of modeled tier COGS.
53
53
  *
@@ -58,28 +58,35 @@ export declare const SUBSCRIPTION_USD_PER_1K = 1;
58
58
  * quietly mispricing the page.
59
59
  */
60
60
  export declare const AI_COLUMN_CREDITS: {
61
- readonly low: 15;
62
- readonly medium: 75;
63
- readonly high: 250;
61
+ readonly low: 1.5;
62
+ readonly medium: 7.5;
63
+ readonly high: 25;
64
64
  };
65
65
  /**
66
- * Web-search grounding, billed per SEARCH on top of the model — not a flat adder.
66
+ * Web-search grounding, billed per PROVIDER CALL on top of the model — not a flat
67
+ * adder.
67
68
  *
68
- * This replaces `AI_COLUMN_WEB_SEARCH_SURCHARGE_CREDITS = 25`, which was a real
69
- * under-quote on a public pricing surface: it was a leftover from the bundled
70
- * `*_with_web_search` model tiers that were removed when grounding moved onto
71
- * native providers, and the billing path never read it. Actual customer price is
72
- * the managed provider's own per-search charge (cogs-rates.ts): exa 35, parallel
73
- * 5, firecrawl 80 at the default 5 results. The default column runs exa primary
74
- * with parallel as its one fallback (WEB_SEARCH_ENGINES), so a row costs 35 when
75
- * the primary answers and reserves 40 for the case where both lanes fire.
69
+ * This replaced `AI_COLUMN_WEB_SEARCH_SURCHARGE_CREDITS = 25`, a real under-quote on
70
+ * a public surface: a leftover from the bundled `*_with_web_search` model tiers that
71
+ * were removed when grounding moved onto native providers, which the billing path
72
+ * never read.
76
73
  *
77
- * Resolver-derived like AI_COLUMN_CREDITS above, and pinned by the same test.
74
+ * The figures below describe the DEFAULT research column, which since D53 discovers
75
+ * then reads: `serper.search` (0.5) finds the URLs, then one additive
76
+ * `exa.contents` read (0.5) turns the top result's ~160-char SERP teaser into real
77
+ * page text. So a typical row spends 1 and a preview reserves 4.5, because the
78
+ * ceiling must also cover the `exa.search` fallback (3.5) firing when serper finds
79
+ * nothing. The read carries no fallback of its own — a read miss leaves the row
80
+ * grounded on the snippets it already has.
81
+ *
82
+ * Both numbers are RESOLVER-DERIVED and pinned by pricing-sheet-conformance.test.ts
83
+ * against the shipped default, so a re-price or a lane change fails a test rather
84
+ * than quietly mispricing this page. Do not hand-edit them.
78
85
  */
79
- export declare const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 35;
80
- export declare const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 40;
86
+ export declare const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 1;
87
+ export declare const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.5;
81
88
  /** Workflow/automation actions (steps, tool calls, row writes) — capacity guard. */
82
- export declare const AUTOMATION_ACTION_CREDITS = 0.01;
89
+ export declare const AUTOMATION_ACTION_CREDITS = 0.001;
83
90
  /**
84
91
  * Managed email inboxes: founder-ratified flat price (2026-07-25), superseding
85
92
  * the earlier dynamic vendor-COGS × 1.25 range. Kept as an object (min/typical/max
@@ -88,9 +95,9 @@ export declare const AUTOMATION_ACTION_CREDITS = 0.01;
88
95
  */
89
96
  export declare const MANAGED_INBOX_MARKUP = 1.25;
90
97
  export declare const MANAGED_INBOX_CREDITS_PER_MONTH: {
91
- readonly min: 3000;
92
- readonly typical: 3000;
93
- readonly max: 3000;
98
+ readonly min: 300;
99
+ readonly typical: 300;
100
+ readonly max: 300;
94
101
  };
95
102
  /**
96
103
  * VOICE (the call channel). Marked up 5×, not the 1.25× infra rule the inbox and
@@ -106,12 +113,12 @@ export declare const MANAGED_INBOX_CREDITS_PER_MONTH: {
106
113
  * Costing only the outbound leg undercharges every call by 29%.
107
114
  */
108
115
  export declare const VOICE_MARKUP = 5;
109
- export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 5000;
110
- export declare const VOICE_CREDITS_PER_MINUTE = 90;
111
- export declare const VOICE_CREDITS_PER_AMD_CALL = 38;
116
+ export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 500;
117
+ export declare const VOICE_CREDITS_PER_MINUTE = 9;
118
+ export declare const VOICE_CREDITS_PER_AMD_CALL = 3.8;
112
119
  /** Managed domains: registrar at-cost × 1.25 (≈ a $10.44 .com → ~13,050 credits/yr). */
113
120
  export declare const MANAGED_DOMAIN_MARKUP = 1.25;
114
- export declare const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 13050;
121
+ export declare const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 1305;
115
122
  /**
116
123
  * Inbox deliverability (EmailGuard placement seat). A flat monthly price per
117
124
  * SUBSCRIBED inbox covering continuous deliverability monitoring (blacklist,
@@ -126,9 +133,9 @@ export declare const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 13050;
126
133
  * revenue — a ~73% margin — and everything past them bills
127
134
  * PLACEMENT_TEST_OVERAGE_CREDITS. Orgs on their own EmailGuard key (BYOK) pay 0.
128
135
  */
129
- export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 1000;
136
+ export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
130
137
  export declare const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
131
- export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 166;
138
+ export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 16.6;
132
139
  /**
133
140
  * LinkedIn accounts: founder decision (2026-07-25) — a PURE seat model. The
134
141
  * flat monthly connection fee per connected account is the WHOLE LinkedIn
@@ -136,7 +143,7 @@ export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 166;
136
143
  * stay 0 too — but a connected WhatsApp NUMBER carries its own monthly
137
144
  * connection fee, see WHATSAPP_ACCOUNT_CREDITS_PER_MONTH.
138
145
  */
139
- export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 10000;
146
+ export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 1000;
140
147
  export declare const LINKEDIN_ACTION_CREDITS: {
141
148
  readonly visit_profile: 0;
142
149
  readonly invite: 0;
@@ -153,9 +160,9 @@ export declare const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = 0;
153
160
  * part-way through a month still bills the full cycle. WhatsApp message sends
154
161
  * themselves remain 0 credits.
155
162
  */
156
- export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 10000;
163
+ export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 1000;
157
164
  /** Dedicated egress IP add-on. */
158
- export declare const EGRESS_IP_CREDITS_PER_MONTH = 25000;
165
+ export declare const EGRESS_IP_CREDITS_PER_MONTH = 2500;
159
166
  /**
160
167
  * Email + WhatsApp sends cost nothing per message — the pool pays for inboxes and
161
168
  * connected accounts, not for sends.
@@ -170,13 +177,13 @@ export declare const SEND_CREDITS = 0;
170
177
  * pricing seed.
171
178
  */
172
179
  export declare const ENRICHMENT_CREDITS: {
173
- readonly email_verify: 2.245;
174
- readonly email_find_typical: 85;
175
- readonly phone_find_typical: 990;
176
- readonly company_enrich_typical: 99;
177
- readonly web_search: 5;
178
- readonly page_scrape: 40;
179
- readonly linkedin_profile_scrape: 10;
180
+ readonly email_verify: 0.225;
181
+ readonly email_find_typical: 8.5;
182
+ readonly phone_find_typical: 99;
183
+ readonly company_enrich_typical: 9.9;
184
+ readonly web_search: 0.5;
185
+ readonly page_scrape: 4;
186
+ readonly linkedin_profile_scrape: 1;
180
187
  };
181
188
  /** Editable calculator default: blended credits per fully-enriched row. */
182
- export declare const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = 100;
189
+ export declare const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = 10;
@@ -3,7 +3,7 @@
3
3
  * page's "what credits buy" table, the pricing calculator, and docs.
4
4
  *
5
5
  * Pricing Model 2.0 (founder-ratified 2026-07-14): ONE credit pool pays for
6
- * everything; 1 USD = 1,000 credits.
6
+ * everything; 1 USD = 100 credits.
7
7
  *
8
8
  * THIS FILE NO LONGER DECLARES PRICES. It used to carry hand-copied literals
9
9
  * under a comment asking the next person to remember to update them — which is
@@ -34,19 +34,19 @@
34
34
  * loadPricingBook() instead of importing this file, so a staff re-price at
35
35
  * /admin/costs takes effect without a deploy.
36
36
  */
37
- import { AUTOMATION_ACTION_CREDITS as SNAPSHOT_AUTOMATION_ACTION_CREDITS, CREDITS_PER_USD as SNAPSHOT_CREDITS_PER_USD, DELIVERABILITY_INCLUDED_TESTS_PER_INBOX as SNAPSHOT_DELIVERABILITY_INCLUDED_TESTS_PER_INBOX, DELIVERABILITY_SEAT_CREDITS_PER_MONTH as SNAPSHOT_DELIVERABILITY_SEAT_CREDITS_PER_MONTH, EGRESS_IP_CREDITS_PER_MONTH as SNAPSHOT_EGRESS_IP_CREDITS_PER_MONTH, MANAGED_INBOX_USD_CENTS as SNAPSHOT_MANAGED_INBOX_USD_CENTS, SENDING_DOMAIN_USD_CENTS as SNAPSHOT_SENDING_DOMAIN_USD_CENTS, SENDING_SEAT_USD_CENTS as SNAPSHOT_SENDING_SEAT_USD_CENTS, ENRICHMENT_CREDITS_PER_ROW_TYPICAL as SNAPSHOT_ENRICHMENT_CREDITS_PER_ROW_TYPICAL, LINKEDIN_ACCOUNT_CREDITS_PER_MONTH as SNAPSHOT_LINKEDIN_ACCOUNT_CREDITS_PER_MONTH, LINKEDIN_ACTION_CREDITS as SNAPSHOT_LINKEDIN_ACTION_CREDITS, LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH as SNAPSHOT_LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH, MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL as SNAPSHOT_MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL, MANAGED_DOMAIN_MARKUP as SNAPSHOT_MANAGED_DOMAIN_MARKUP, MANAGED_INBOX_CREDITS_PER_MONTH as SNAPSHOT_MANAGED_INBOX_CREDITS_PER_MONTH, MANAGED_INBOX_MARKUP as SNAPSHOT_MANAGED_INBOX_MARKUP, PLACEMENT_TEST_OVERAGE_CREDITS as SNAPSHOT_PLACEMENT_TEST_OVERAGE_CREDITS, PRICE_SHEET_VERIFIED as SNAPSHOT_PRICE_SHEET_VERIFIED, SEND_CREDITS as SNAPSHOT_SEND_CREDITS, SUBSCRIPTION_USD_PER_1K as SNAPSHOT_SUBSCRIPTION_USD_PER_1K, TOPUP_USD_PER_1K as SNAPSHOT_TOPUP_USD_PER_1K, VOICE_CREDITS_PER_AMD_CALL as SNAPSHOT_VOICE_CREDITS_PER_AMD_CALL, VOICE_CREDITS_PER_MINUTE as SNAPSHOT_VOICE_CREDITS_PER_MINUTE, VOICE_MARKUP as SNAPSHOT_VOICE_MARKUP, VOICE_NUMBER_CREDITS_PER_MONTH as SNAPSHOT_VOICE_NUMBER_CREDITS_PER_MONTH, WHATSAPP_ACCOUNT_CREDITS_PER_MONTH as SNAPSHOT_WHATSAPP_ACCOUNT_CREDITS_PER_MONTH, } from "./pricing-snapshot.generated.js";
37
+ import { AUTOMATION_ACTION_CREDITS as SNAPSHOT_AUTOMATION_ACTION_CREDITS, CREDITS_PER_USD as SNAPSHOT_CREDITS_PER_USD, DELIVERABILITY_INCLUDED_TESTS_PER_INBOX as SNAPSHOT_DELIVERABILITY_INCLUDED_TESTS_PER_INBOX, DELIVERABILITY_SEAT_CREDITS_PER_MONTH as SNAPSHOT_DELIVERABILITY_SEAT_CREDITS_PER_MONTH, EGRESS_IP_CREDITS_PER_MONTH as SNAPSHOT_EGRESS_IP_CREDITS_PER_MONTH, MANAGED_INBOX_USD_CENTS as SNAPSHOT_MANAGED_INBOX_USD_CENTS, SENDING_DOMAIN_USD_CENTS as SNAPSHOT_SENDING_DOMAIN_USD_CENTS, SENDING_SEAT_USD_CENTS as SNAPSHOT_SENDING_SEAT_USD_CENTS, ENRICHMENT_CREDITS_PER_ROW_TYPICAL as SNAPSHOT_ENRICHMENT_CREDITS_PER_ROW_TYPICAL, LINKEDIN_ACCOUNT_CREDITS_PER_MONTH as SNAPSHOT_LINKEDIN_ACCOUNT_CREDITS_PER_MONTH, LINKEDIN_ACTION_CREDITS as SNAPSHOT_LINKEDIN_ACTION_CREDITS, LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH as SNAPSHOT_LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH, MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL as SNAPSHOT_MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL, MANAGED_DOMAIN_MARKUP as SNAPSHOT_MANAGED_DOMAIN_MARKUP, MANAGED_INBOX_CREDITS_PER_MONTH as SNAPSHOT_MANAGED_INBOX_CREDITS_PER_MONTH, MANAGED_INBOX_MARKUP as SNAPSHOT_MANAGED_INBOX_MARKUP, PLACEMENT_TEST_OVERAGE_CREDITS as SNAPSHOT_PLACEMENT_TEST_OVERAGE_CREDITS, PRICE_SHEET_VERIFIED as SNAPSHOT_PRICE_SHEET_VERIFIED, SEND_CREDITS as SNAPSHOT_SEND_CREDITS, SUBSCRIPTION_USD_PER_100 as SNAPSHOT_SUBSCRIPTION_USD_PER_100, TOPUP_USD_PER_100 as SNAPSHOT_TOPUP_USD_PER_100, VOICE_CREDITS_PER_AMD_CALL as SNAPSHOT_VOICE_CREDITS_PER_AMD_CALL, VOICE_CREDITS_PER_MINUTE as SNAPSHOT_VOICE_CREDITS_PER_MINUTE, VOICE_MARKUP as SNAPSHOT_VOICE_MARKUP, VOICE_NUMBER_CREDITS_PER_MONTH as SNAPSHOT_VOICE_NUMBER_CREDITS_PER_MONTH, WHATSAPP_ACCOUNT_CREDITS_PER_MONTH as SNAPSHOT_WHATSAPP_ACCOUNT_CREDITS_PER_MONTH, } from "./pricing-snapshot.generated.js";
38
38
  export { creditsToUsd, usdToCredits } from "./pricing-snapshot.generated.js";
39
39
  export const PRICING_SHEET_VERIFIED = SNAPSHOT_PRICE_SHEET_VERIFIED;
40
40
  export const PRICING_CREDITS_PER_USD = SNAPSHOT_CREDITS_PER_USD;
41
- /** On-demand top-up price per 1,000 credits (USD); subscriptions pay $1.00. */
42
- export const TOPUP_USD_PER_1K = SNAPSHOT_TOPUP_USD_PER_1K;
41
+ /** On-demand top-up price per 100 credits (USD); subscriptions pay $1.00. */
42
+ export const TOPUP_USD_PER_100 = SNAPSHOT_TOPUP_USD_PER_100;
43
43
  // Dollar-priced CAPACITY, re-exported on the client-safe subpath so the pricing
44
44
  // calculator and the marketing sections quote the same numbers the product
45
45
  // charges. These are not credits and must never be converted as if they were.
46
46
  export const SENDING_SEAT_USD_CENTS = SNAPSHOT_SENDING_SEAT_USD_CENTS;
47
47
  export const MANAGED_INBOX_USD_CENTS = SNAPSHOT_MANAGED_INBOX_USD_CENTS;
48
48
  export const SENDING_DOMAIN_USD_CENTS = SNAPSHOT_SENDING_DOMAIN_USD_CENTS;
49
- export const SUBSCRIPTION_USD_PER_1K = SNAPSHOT_SUBSCRIPTION_USD_PER_1K;
49
+ export const SUBSCRIPTION_USD_PER_100 = SNAPSHOT_SUBSCRIPTION_USD_PER_100;
50
50
  /**
51
51
  * AI column runs, honest 5× of modeled tier COGS.
52
52
  *
@@ -56,23 +56,30 @@ export const SUBSCRIPTION_USD_PER_1K = SNAPSHOT_SUBSCRIPTION_USD_PER_1K;
56
56
  * against the live estimator, so a tier re-price fails a test rather than
57
57
  * quietly mispricing the page.
58
58
  */
59
- export const AI_COLUMN_CREDITS = { low: 15, medium: 75, high: 250 };
59
+ export const AI_COLUMN_CREDITS = { low: 1.5, medium: 7.5, high: 25 };
60
60
  /**
61
- * Web-search grounding, billed per SEARCH on top of the model — not a flat adder.
61
+ * Web-search grounding, billed per PROVIDER CALL on top of the model — not a flat
62
+ * adder.
62
63
  *
63
- * This replaces `AI_COLUMN_WEB_SEARCH_SURCHARGE_CREDITS = 25`, which was a real
64
- * under-quote on a public pricing surface: it was a leftover from the bundled
65
- * `*_with_web_search` model tiers that were removed when grounding moved onto
66
- * native providers, and the billing path never read it. Actual customer price is
67
- * the managed provider's own per-search charge (cogs-rates.ts): exa 35, parallel
68
- * 5, firecrawl 80 at the default 5 results. The default column runs exa primary
69
- * with parallel as its one fallback (WEB_SEARCH_ENGINES), so a row costs 35 when
70
- * the primary answers and reserves 40 for the case where both lanes fire.
64
+ * This replaced `AI_COLUMN_WEB_SEARCH_SURCHARGE_CREDITS = 25`, a real under-quote on
65
+ * a public surface: a leftover from the bundled `*_with_web_search` model tiers that
66
+ * were removed when grounding moved onto native providers, which the billing path
67
+ * never read.
71
68
  *
72
- * Resolver-derived like AI_COLUMN_CREDITS above, and pinned by the same test.
69
+ * The figures below describe the DEFAULT research column, which since D53 discovers
70
+ * then reads: `serper.search` (0.5) finds the URLs, then one additive
71
+ * `exa.contents` read (0.5) turns the top result's ~160-char SERP teaser into real
72
+ * page text. So a typical row spends 1 and a preview reserves 4.5, because the
73
+ * ceiling must also cover the `exa.search` fallback (3.5) firing when serper finds
74
+ * nothing. The read carries no fallback of its own — a read miss leaves the row
75
+ * grounded on the snippets it already has.
76
+ *
77
+ * Both numbers are RESOLVER-DERIVED and pinned by pricing-sheet-conformance.test.ts
78
+ * against the shipped default, so a re-price or a lane change fails a test rather
79
+ * than quietly mispricing this page. Do not hand-edit them.
73
80
  */
74
- export const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 35;
75
- export const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 40;
81
+ export const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 1;
82
+ export const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.5;
76
83
  /** Workflow/automation actions (steps, tool calls, row writes) — capacity guard. */
77
84
  export const AUTOMATION_ACTION_CREDITS = SNAPSHOT_AUTOMATION_ACTION_CREDITS;
78
85
  /**
@@ -157,13 +164,17 @@ export const SEND_CREDITS = SNAPSHOT_SEND_CREDITS;
157
164
  * pricing seed.
158
165
  */
159
166
  export const ENRICHMENT_CREDITS = {
160
- email_verify: 2.245, // MillionVerifier first pass (exactly 5x COGS)
161
- email_find_typical: 85, // Hunter-class finder; cheap waterfall steps run 15–99
162
- phone_find_typical: 990, // Prospeo/Findymail-class mobile
163
- company_enrich_typical: 99,
164
- web_search: 5, // Serper
165
- page_scrape: 40, // Firecrawl (wedge price)
166
- linkedin_profile_scrape: 10, // Managed profile credit at $0.002 COGS, exactly 5x
167
+ // The ONLY price in the 2026-09-19 re-denomination that is not an exact /10.
168
+ // 2.245 / 10 = 0.2245, and credits are numeric(18,3) — the fourth decimal does
169
+ // not exist in the ledger. Rounded UP to 0.225 (+0.22%) per this file's
170
+ // standing preference for overestimating a quote rather than under-charging.
171
+ email_verify: 0.225, // MillionVerifier first pass (~5x COGS; see note above)
172
+ email_find_typical: 8.5, // Hunter-class finder; cheap waterfall steps run 1.5–9.9
173
+ phone_find_typical: 99, // Prospeo/Findymail-class mobile
174
+ company_enrich_typical: 9.9,
175
+ web_search: 0.5, // Serper
176
+ page_scrape: 4, // Firecrawl (wedge price)
177
+ linkedin_profile_scrape: 1, // Managed profile credit at $0.002 COGS, exactly 5x
167
178
  };
168
179
  /** Editable calculator default: blended credits per fully-enriched row. */
169
180
  export const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = SNAPSHOT_ENRICHMENT_CREDITS_PER_ROW_TYPICAL;
@@ -1,33 +1,33 @@
1
1
  /** Period the customer-facing price sheet was last reconciled end to end. */
2
2
  export declare const PRICE_SHEET_VERIFIED = "2026-07";
3
- /** $1 = 1_000 credits (Pricing Model 2.0). */
4
- export declare const CREDITS_PER_USD = 1000;
3
+ /** $1 = 100 credits (Pricing Model 2.1). */
4
+ export declare const CREDITS_PER_USD = 100;
5
5
  /** The divisor in the markup formula; exact inverse of CREDITS_PER_USD. */
6
- export declare const CREDIT_USD_VALUE = 0.001;
7
- /** On-demand top-up, in USD cents per 1,000 credits. */
8
- export declare const TOPUP_USD_CENTS_PER_1K_CREDITS = 125;
9
- /** On-demand top-up price per 1,000 credits, in USD. */
10
- export declare const TOPUP_USD_PER_1K = 1.25;
6
+ export declare const CREDIT_USD_VALUE = 0.01;
7
+ /** On-demand top-up, in USD cents per 100 credits. */
8
+ export declare const TOPUP_USD_CENTS_PER_100_CREDITS = 125;
9
+ /** On-demand top-up price per 100 credits, in USD. */
10
+ export declare const TOPUP_USD_PER_100 = 1.25;
11
11
  /** Subscription credits convert at face value, making them exactly 20% cheaper. */
12
- export declare const SUBSCRIPTION_USD_PER_1K = 1;
12
+ export declare const SUBSCRIPTION_USD_PER_100 = 1;
13
13
  export declare const MANAGED_INBOX_MARKUP = 1.25;
14
14
  export declare const MANAGED_DOMAIN_MARKUP = 1.25;
15
15
  export declare const VOICE_MARKUP = 5;
16
16
  /** Applied to actual provider inference cost at settle time. */
17
17
  export declare const COPILOT_CREDIT_MARKUP_MULTIPLIER = 5;
18
- export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 10000;
19
- export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 10000;
20
- export declare const EGRESS_IP_CREDITS_PER_MONTH = 25000;
21
- export declare const SENDING_MAILBOX_CREDITS_PER_MONTH = 1000;
22
- export declare const MANAGED_INBOX_CREDITS_PER_MONTH = 3000;
23
- export declare const MAILBOX_WARMUP_CREDITS_PER_MONTH = 1000;
24
- export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 1000;
18
+ export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 1000;
19
+ export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 1000;
20
+ export declare const EGRESS_IP_CREDITS_PER_MONTH = 2500;
21
+ export declare const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
22
+ export declare const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
23
+ export declare const MAILBOX_WARMUP_CREDITS_PER_MONTH = 100;
24
+ export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
25
25
  /** Included inbox-placement tests per subscribed inbox per cycle. */
26
26
  export declare const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
27
27
  /** A placement test beyond the included allowance. */
28
- export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 166;
28
+ export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 16.6;
29
29
  /** Representative, not billed: a typical .com at MANAGED_DOMAIN_MARKUP. */
30
- export declare const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 13050;
30
+ export declare const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 1305;
31
31
  export declare const SENDING_SEAT_USD_CENTS: {
32
32
  readonly linkedin: 3000;
33
33
  readonly whatsapp: 3000;
@@ -37,11 +37,11 @@ export declare const SENDING_SEAT_USD_CENTS: {
37
37
  export type SendingSeatKey = keyof typeof SENDING_SEAT_USD_CENTS;
38
38
  export declare const MANAGED_INBOX_USD_CENTS = 400;
39
39
  export declare const SENDING_DOMAIN_USD_CENTS = 1250;
40
- export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 5000;
41
- export declare const VOICE_CREDITS_PER_MINUTE = 90;
42
- export declare const VOICE_CREDITS_PER_AMD_CALL = 38;
40
+ export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 500;
41
+ export declare const VOICE_CREDITS_PER_MINUTE = 9;
42
+ export declare const VOICE_CREDITS_PER_AMD_CALL = 3.8;
43
43
  /** Workflow steps, tool calls and row writes — a capacity guard, not a margin line. */
44
- export declare const AUTOMATION_ACTION_CREDITS = 0.01;
44
+ export declare const AUTOMATION_ACTION_CREDITS = 0.001;
45
45
  /** Email, LinkedIn and WhatsApp sends are free; the pool pays for seats and inboxes. */
46
46
  export declare const SEND_CREDITS = 0;
47
47
  /** Every LinkedIn action is 0 under the pure seat model. */
@@ -54,7 +54,7 @@ export declare const LINKEDIN_ACTION_CREDITS: {
54
54
  readonly like_post: 0;
55
55
  readonly comment_post: 0;
56
56
  };
57
- export declare const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = 100;
57
+ export declare const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = 10;
58
58
  export declare const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = 0;
59
59
  export type PricingPlanSnapshot = {
60
60
  readonly planKey: string;
@@ -15,16 +15,16 @@
15
15
  /** Period the customer-facing price sheet was last reconciled end to end. */
16
16
  export const PRICE_SHEET_VERIFIED = "2026-07";
17
17
  // --- conversion -------------------------------------------------------------
18
- /** $1 = 1_000 credits (Pricing Model 2.0). */
19
- export const CREDITS_PER_USD = 1_000;
18
+ /** $1 = 100 credits (Pricing Model 2.1). */
19
+ export const CREDITS_PER_USD = 100;
20
20
  /** The divisor in the markup formula; exact inverse of CREDITS_PER_USD. */
21
- export const CREDIT_USD_VALUE = 0.001;
22
- /** On-demand top-up, in USD cents per 1,000 credits. */
23
- export const TOPUP_USD_CENTS_PER_1K_CREDITS = 125;
24
- /** On-demand top-up price per 1,000 credits, in USD. */
25
- export const TOPUP_USD_PER_1K = 1.25;
21
+ export const CREDIT_USD_VALUE = 0.01;
22
+ /** On-demand top-up, in USD cents per 100 credits. */
23
+ export const TOPUP_USD_CENTS_PER_100_CREDITS = 125;
24
+ /** On-demand top-up price per 100 credits, in USD. */
25
+ export const TOPUP_USD_PER_100 = 1.25;
26
26
  /** Subscription credits convert at face value, making them exactly 20% cheaper. */
27
- export const SUBSCRIPTION_USD_PER_1K = 1;
27
+ export const SUBSCRIPTION_USD_PER_100 = 1;
28
28
  // --- markups ----------------------------------------------------------------
29
29
  export const MANAGED_INBOX_MARKUP = 1.25;
30
30
  export const MANAGED_DOMAIN_MARKUP = 1.25;
@@ -32,19 +32,19 @@ export const VOICE_MARKUP = 5;
32
32
  /** Applied to actual provider inference cost at settle time. */
33
33
  export const COPILOT_CREDIT_MARKUP_MULTIPLIER = 5;
34
34
  // --- seats and recurring charges --------------------------------------------
35
- export const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 10_000;
36
- export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 10_000;
37
- export const EGRESS_IP_CREDITS_PER_MONTH = 25_000;
38
- export const SENDING_MAILBOX_CREDITS_PER_MONTH = 1_000;
39
- export const MANAGED_INBOX_CREDITS_PER_MONTH = 3_000;
40
- export const MAILBOX_WARMUP_CREDITS_PER_MONTH = 1_000;
41
- export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 1_000;
35
+ export const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 1_000;
36
+ export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 1_000;
37
+ export const EGRESS_IP_CREDITS_PER_MONTH = 2_500;
38
+ export const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
39
+ export const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
40
+ export const MAILBOX_WARMUP_CREDITS_PER_MONTH = 100;
41
+ export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
42
42
  /** Included inbox-placement tests per subscribed inbox per cycle. */
43
43
  export const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
44
44
  /** A placement test beyond the included allowance. */
45
- export const PLACEMENT_TEST_OVERAGE_CREDITS = 166;
45
+ export const PLACEMENT_TEST_OVERAGE_CREDITS = 16.6;
46
46
  /** Representative, not billed: a typical .com at MANAGED_DOMAIN_MARKUP. */
47
- export const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 13_050;
47
+ export const MANAGED_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 1_305;
48
48
  // --- sending seats (USD, Stripe-billed) --------------------------------------
49
49
  //
50
50
  // The seat model (OXP-15). These are DOLLARS, not credits, and they do not
@@ -74,12 +74,12 @@ export const SENDING_SEAT_USD_CENTS = {
74
74
  export const MANAGED_INBOX_USD_CENTS = 400;
75
75
  export const SENDING_DOMAIN_USD_CENTS = 1_250;
76
76
  // --- voice ------------------------------------------------------------------
77
- export const VOICE_NUMBER_CREDITS_PER_MONTH = 5_000;
78
- export const VOICE_CREDITS_PER_MINUTE = 90;
79
- export const VOICE_CREDITS_PER_AMD_CALL = 38;
77
+ export const VOICE_NUMBER_CREDITS_PER_MONTH = 500;
78
+ export const VOICE_CREDITS_PER_MINUTE = 9;
79
+ export const VOICE_CREDITS_PER_AMD_CALL = 3.8;
80
80
  // --- per-action -------------------------------------------------------------
81
81
  /** Workflow steps, tool calls and row writes — a capacity guard, not a margin line. */
82
- export const AUTOMATION_ACTION_CREDITS = 0.01;
82
+ export const AUTOMATION_ACTION_CREDITS = 0.001;
83
83
  /** Email, LinkedIn and WhatsApp sends are free; the pool pays for seats and inboxes. */
84
84
  export const SEND_CREDITS = 0;
85
85
  /** Every LinkedIn action is 0 under the pure seat model. */
@@ -93,23 +93,29 @@ export const LINKEDIN_ACTION_CREDITS = {
93
93
  comment_post: 0,
94
94
  };
95
95
  // --- pricing-calculator defaults (not prices) -------------------------------
96
- export const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = 100;
96
+ export const ENRICHMENT_CREDITS_PER_ROW_TYPICAL = 10;
97
97
  export const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = 0;
98
98
  export const PRICING_PLAN_SNAPSHOT = [
99
99
  { planKey: "free", tier: "free", isLegacy: false, monthlyPriceCents: 0, monthlyCredits: 0, weeklyCreditsLimit: null, rolloverCap: null, byokEnabled: false },
100
- { planKey: "starter", tier: "starter", isLegacy: false, monthlyPriceCents: 9_900, monthlyCredits: 99_000, weeklyCreditsLimit: null, rolloverCap: 99_000, byokEnabled: true },
101
- { planKey: "pro", tier: "pro", isLegacy: false, monthlyPriceCents: 24_900, monthlyCredits: 249_000, weeklyCreditsLimit: null, rolloverCap: 249_000, byokEnabled: true },
102
- { planKey: "team", tier: "team", isLegacy: false, monthlyPriceCents: 74_900, monthlyCredits: 749_000, weeklyCreditsLimit: null, rolloverCap: 749_000, byokEnabled: true },
103
- { planKey: "scale", tier: "scale", isLegacy: false, monthlyPriceCents: null, monthlyCredits: 10_000_000, weeklyCreditsLimit: null, rolloverCap: 10_000_000, byokEnabled: true },
100
+ { planKey: "oxygen_49", tier: "oxygen", isLegacy: false, monthlyPriceCents: 4_900, monthlyCredits: 4_900, weeklyCreditsLimit: null, rolloverCap: 4_900, byokEnabled: true },
101
+ { planKey: "oxygen_99", tier: "oxygen", isLegacy: false, monthlyPriceCents: 9_900, monthlyCredits: 9_900, weeklyCreditsLimit: null, rolloverCap: 9_900, byokEnabled: true },
102
+ { planKey: "oxygen_199", tier: "oxygen", isLegacy: false, monthlyPriceCents: 19_900, monthlyCredits: 19_900, weeklyCreditsLimit: null, rolloverCap: 19_900, byokEnabled: true },
103
+ { planKey: "oxygen_499", tier: "oxygen", isLegacy: false, monthlyPriceCents: 49_900, monthlyCredits: 49_900, weeklyCreditsLimit: null, rolloverCap: 49_900, byokEnabled: true },
104
+ { planKey: "oxygen_999", tier: "oxygen", isLegacy: false, monthlyPriceCents: 99_900, monthlyCredits: 99_900, weeklyCreditsLimit: null, rolloverCap: 99_900, byokEnabled: true },
105
+ { planKey: "oxygen_1999", tier: "oxygen", isLegacy: false, monthlyPriceCents: 199_900, monthlyCredits: 199_900, weeklyCreditsLimit: null, rolloverCap: 199_900, byokEnabled: true },
106
+ { planKey: "scale", tier: "scale", isLegacy: false, monthlyPriceCents: null, monthlyCredits: 1_000_000, weeklyCreditsLimit: null, rolloverCap: 1_000_000, byokEnabled: true },
104
107
  { planKey: "enterprise", tier: "enterprise", isLegacy: false, monthlyPriceCents: null, monthlyCredits: null, weeklyCreditsLimit: null, rolloverCap: null, byokEnabled: true },
105
- { planKey: "launch_50", tier: "starter", isLegacy: true, monthlyPriceCents: 5_000, monthlyCredits: 200_000, weeklyCreditsLimit: 200_000, rolloverCap: 200_000, byokEnabled: true },
106
- { planKey: "starter_50", tier: "starter", isLegacy: true, monthlyPriceCents: 5_000, monthlyCredits: 200_000, weeklyCreditsLimit: 200_000, rolloverCap: 200_000, byokEnabled: true },
107
- { planKey: "pro_149", tier: "pro", isLegacy: true, monthlyPriceCents: 14_900, monthlyCredits: 1_000_000, weeklyCreditsLimit: 1_000_000, rolloverCap: 1_000_000, byokEnabled: true },
108
- { planKey: "team_399", tier: "team", isLegacy: true, monthlyPriceCents: 39_900, monthlyCredits: 3_000_000, weeklyCreditsLimit: 3_000_000, rolloverCap: 3_000_000, byokEnabled: true },
109
- { planKey: "growth_250", tier: "pro", isLegacy: true, monthlyPriceCents: 25_000, monthlyCredits: 250_000, weeklyCreditsLimit: 100_000, rolloverCap: 250_000, byokEnabled: true },
110
- { planKey: "scale_750", tier: "team", isLegacy: true, monthlyPriceCents: 75_000, monthlyCredits: 750_000, weeklyCreditsLimit: 300_000, rolloverCap: 750_000, byokEnabled: true },
111
- { planKey: "starter_legacy", tier: "starter", isLegacy: true, monthlyPriceCents: null, monthlyCredits: 200_000, weeklyCreditsLimit: null, rolloverCap: 200_000, byokEnabled: true },
112
- { planKey: "scale_legacy", tier: "scale", isLegacy: true, monthlyPriceCents: null, monthlyCredits: 1_200_000, weeklyCreditsLimit: null, rolloverCap: 2_400_000, byokEnabled: true },
108
+ { planKey: "starter", tier: "starter", isLegacy: true, monthlyPriceCents: 9_900, monthlyCredits: 9_900, weeklyCreditsLimit: null, rolloverCap: 9_900, byokEnabled: true },
109
+ { planKey: "pro", tier: "pro", isLegacy: true, monthlyPriceCents: 24_900, monthlyCredits: 24_900, weeklyCreditsLimit: null, rolloverCap: 24_900, byokEnabled: true },
110
+ { planKey: "team", tier: "team", isLegacy: true, monthlyPriceCents: 74_900, monthlyCredits: 74_900, weeklyCreditsLimit: null, rolloverCap: 74_900, byokEnabled: true },
111
+ { planKey: "launch_50", tier: "starter", isLegacy: true, monthlyPriceCents: 5_000, monthlyCredits: 20_000, weeklyCreditsLimit: 20_000, rolloverCap: 20_000, byokEnabled: true },
112
+ { planKey: "starter_50", tier: "starter", isLegacy: true, monthlyPriceCents: 5_000, monthlyCredits: 20_000, weeklyCreditsLimit: 20_000, rolloverCap: 20_000, byokEnabled: true },
113
+ { planKey: "pro_149", tier: "pro", isLegacy: true, monthlyPriceCents: 14_900, monthlyCredits: 100_000, weeklyCreditsLimit: 100_000, rolloverCap: 100_000, byokEnabled: true },
114
+ { planKey: "team_399", tier: "team", isLegacy: true, monthlyPriceCents: 39_900, monthlyCredits: 300_000, weeklyCreditsLimit: 300_000, rolloverCap: 300_000, byokEnabled: true },
115
+ { planKey: "growth_250", tier: "pro", isLegacy: true, monthlyPriceCents: 25_000, monthlyCredits: 25_000, weeklyCreditsLimit: 10_000, rolloverCap: 25_000, byokEnabled: true },
116
+ { planKey: "scale_750", tier: "team", isLegacy: true, monthlyPriceCents: 75_000, monthlyCredits: 75_000, weeklyCreditsLimit: 30_000, rolloverCap: 75_000, byokEnabled: true },
117
+ { planKey: "starter_legacy", tier: "starter", isLegacy: true, monthlyPriceCents: null, monthlyCredits: 20_000, weeklyCreditsLimit: null, rolloverCap: 20_000, byokEnabled: true },
118
+ { planKey: "scale_legacy", tier: "scale", isLegacy: true, monthlyPriceCents: null, monthlyCredits: 120_000, weeklyCreditsLimit: null, rolloverCap: 240_000, byokEnabled: true },
113
119
  ];
114
120
  export function creditsToUsd(credits) {
115
121
  return credits / CREDITS_PER_USD;
@@ -24,6 +24,15 @@ export function resolveProductAnalyticsEnvironmentFromEnv(env = process.env) {
24
24
  ?? env.NEXT_PUBLIC_SENTRY_ENVIRONMENT);
25
25
  if (explicit)
26
26
  return explicit;
27
+ // The self-hosted selector is the first non-explicit signal: a self-hosted box
28
+ // has no VERCEL_ENV and no FLY_APP_NAME, so without it every environment
29
+ // (including the production shadow) would fall through to LOCAL. `shadow` is
30
+ // DEV: it carries production-shaped data but is not production traffic.
31
+ const deployEnv = env.OXYGEN_DEPLOY_ENV?.trim().toLowerCase();
32
+ if (deployEnv === "selfhost-prod")
33
+ return "PROD";
34
+ if (deployEnv === "selfhost-shadow" || deployEnv === "selfhost-dev")
35
+ return "DEV";
27
36
  const vercelEnv = env.VERCEL_ENV ?? env.NEXT_PUBLIC_VERCEL_ENV;
28
37
  if (vercelEnv === "production")
29
38
  return "PROD";
@@ -101,6 +101,21 @@ export declare const PRODUCT_EVENTS: {
101
101
  readonly HERO_LOOKUP_SUBMITTED: "hero_lookup_submitted";
102
102
  readonly HERO_LOOKUP_RENDERED: "hero_lookup_rendered";
103
103
  readonly HERO_SIGNUP_CLICKED: "hero_signup_clicked";
104
+ /**
105
+ * Web navigation timing, measured in the browser from the click on an
106
+ * internal link (capture phase, before Next's own handler) to: the first
107
+ * visible feedback, the URL commit, and the destination's own readiness
108
+ * seam (`lib/analytics/navigation-readiness.ts`). Properties are route
109
+ * TEMPLATES (ids collapsed), a duration and enums — never a raw path, a
110
+ * query string or page content. PostHog owns these because they answer
111
+ * "how does the product feel per route per release", which is a usage
112
+ * question joinable to the funnel; a navigation that never became usable
113
+ * is a defect and is ALSO beaconed to Axiom as a client error.
114
+ */
115
+ readonly WEB_NAVIGATION_FEEDBACK: "web_navigation_feedback";
116
+ readonly WEB_NAVIGATION_MEANINGFUL: "web_navigation_meaningful";
117
+ readonly WEB_NAVIGATION_USABLE: "web_navigation_usable";
118
+ readonly WEB_NAVIGATION_USABLE_TIMEOUT: "web_navigation_usable_timeout";
104
119
  /** Pipeline heartbeat: proves ingestion is alive when the product is quiet. */
105
120
  readonly POSTHOG_CANARY: "posthog_canary";
106
121
  };
@@ -101,6 +101,21 @@ export const PRODUCT_EVENTS = {
101
101
  HERO_LOOKUP_SUBMITTED: "hero_lookup_submitted",
102
102
  HERO_LOOKUP_RENDERED: "hero_lookup_rendered",
103
103
  HERO_SIGNUP_CLICKED: "hero_signup_clicked",
104
+ /**
105
+ * Web navigation timing, measured in the browser from the click on an
106
+ * internal link (capture phase, before Next's own handler) to: the first
107
+ * visible feedback, the URL commit, and the destination's own readiness
108
+ * seam (`lib/analytics/navigation-readiness.ts`). Properties are route
109
+ * TEMPLATES (ids collapsed), a duration and enums — never a raw path, a
110
+ * query string or page content. PostHog owns these because they answer
111
+ * "how does the product feel per route per release", which is a usage
112
+ * question joinable to the funnel; a navigation that never became usable
113
+ * is a defect and is ALSO beaconed to Axiom as a client error.
114
+ */
115
+ WEB_NAVIGATION_FEEDBACK: "web_navigation_feedback",
116
+ WEB_NAVIGATION_MEANINGFUL: "web_navigation_meaningful",
117
+ WEB_NAVIGATION_USABLE: "web_navigation_usable",
118
+ WEB_NAVIGATION_USABLE_TIMEOUT: "web_navigation_usable_timeout",
104
119
  /** Pipeline heartbeat: proves ingestion is alive when the product is quiet. */
105
120
  POSTHOG_CANARY: "posthog_canary",
106
121
  };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Fixed-window bucketing arithmetic shared by every rate/spend limiter.
3
+ */
4
+ /** The start of the fixed `windowSeconds` window containing `now`. */
5
+ export declare function startOfWindow(now: Date, windowSeconds: number): Date;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Fixed-window bucketing arithmetic shared by every rate/spend limiter.
3
+ */
4
+ /** The start of the fixed `windowSeconds` window containing `now`. */
5
+ export function startOfWindow(now, windowSeconds) {
6
+ const windowMs = windowSeconds * 1000;
7
+ return new Date(Math.floor(now.getTime() / windowMs) * windowMs);
8
+ }
@@ -14,6 +14,34 @@ export declare function deriveResearchOutputContract(prompt: string, options: {
14
14
  evidenceRequired: boolean;
15
15
  }): ResearchOutputContract | null;
16
16
  export declare function buildResearchOutputSchema(contract: ResearchOutputContract | null): Record<string, unknown>;
17
+ /**
18
+ * Whether a found answer MUST cite evidence. Shared by the write-path normalizer
19
+ * (which bakes it into the derived research contract), the runner (which
20
+ * validates the model output against it) and the output-field reader, so none
21
+ * of them can disagree.
22
+ *
23
+ * Explicit "strict" always requires it. A FETCH column requires it by default —
24
+ * the evidence is the one page the customer pointed at, so an answer that cites
25
+ * nothing answered from memory — unless the author chose "estimate".
26
+ */
27
+ export declare function researchEvidenceRequired(webSearch: unknown): boolean;
28
+ /**
29
+ * True for a model-facing schema in the research envelope shape — the derived
30
+ * contract, the legacy broad schema, or a catalog template's typed answer
31
+ * envelope — as opposed to a hand-authored schema that replaces the envelope
32
+ * entirely. The output-field reader rewrites only the former into the stored
33
+ * cell shape (`sources` in, `citations` out); the latter is used verbatim.
34
+ */
35
+ export declare function isResearchEnvelopeSchema(schema: unknown): boolean;
36
+ /**
37
+ * The model-facing schema for a research column whose ANSWER is a typed object
38
+ * (a catalog template such as a pricing summary): the same
39
+ * `{answer, found, confidence, citations}` envelope the derived contract uses,
40
+ * with `answer` replaced by the template's own object schema. The runner still
41
+ * resolves `citations` to real sources on the way to the cell, so a typed
42
+ * extraction cannot cite a page that was never fetched either.
43
+ */
44
+ export declare function buildResearchOutputSchemaForAnswer(answerSchema: Record<string, unknown>): Record<string, unknown>;
17
45
  /**
18
46
  * The schema of the research cell as it is actually STORED — which is not the
19
47
  * schema the model answers in.
@@ -27,7 +55,11 @@ export declare function buildResearchOutputSchema(contract: ResearchOutputContra
27
55
  * `buildResearchOutputSchema` would offer `citations`, which no cell has, and
28
56
  * hide `sources`, which every cell does.
29
57
  */
30
- export declare function buildResearchCellSchema(contract: ResearchOutputContract | null): Record<string, unknown>;
58
+ export declare function buildResearchCellSchema(contract: ResearchOutputContract | null,
59
+ /** A column's own model-facing schema (a catalog template's typed answer
60
+ * envelope). When given it replaces the derived one, so the cell shape of a
61
+ * typed extraction exposes `answer.plan_count`, not a string answer. */
62
+ modelSchemaOverride?: Record<string, unknown> | null): Record<string, unknown>;
31
63
  /**
32
64
  * Is this research column's output schema OWNED BY THE SERVER, i.e. re-derived
33
65
  * from the prompt rather than authored by hand?