@oxygen-agent/cli 1.1010.644 → 1.1010.721

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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/command-manifest.js +1 -1
  3. package/dist/inbox-needs-reply-notice.d.ts +12 -0
  4. package/dist/inbox-needs-reply-notice.js +51 -0
  5. package/dist/index.js +186 -45
  6. package/dist/skills.js +48 -22
  7. package/node_modules/@oxygen/shared/dist/billing-anchors.d.ts +33 -2
  8. package/node_modules/@oxygen/shared/dist/billing-anchors.js +67 -2
  9. package/node_modules/@oxygen/shared/dist/billing.d.ts +63 -9
  10. package/node_modules/@oxygen/shared/dist/billing.js +96 -14
  11. package/node_modules/@oxygen/shared/dist/capability-discovery.js +11 -1
  12. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +4 -4
  13. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +4 -4
  14. package/node_modules/@oxygen/shared/dist/email-hard-bounce.d.ts +25 -0
  15. package/node_modules/@oxygen/shared/dist/email-hard-bounce.js +27 -0
  16. package/node_modules/@oxygen/shared/dist/feature-gates.d.ts +6 -1
  17. package/node_modules/@oxygen/shared/dist/feature-gates.js +7 -1
  18. package/node_modules/@oxygen/shared/dist/index.d.ts +2 -1
  19. package/node_modules/@oxygen/shared/dist/index.js +2 -1
  20. package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +114 -0
  21. package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +150 -0
  22. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +19 -2
  23. package/node_modules/@oxygen/shared/dist/plan-band.d.ts +118 -0
  24. package/node_modules/@oxygen/shared/dist/plan-band.js +147 -0
  25. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +131 -120
  26. package/node_modules/@oxygen/shared/dist/plan-limits.js +80 -71
  27. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +79 -14
  28. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +61 -12
  29. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +4 -3
  30. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +9 -3
  31. package/node_modules/@oxygen/shared/dist/process-resource.d.ts +4 -0
  32. package/node_modules/@oxygen/shared/dist/process-resource.js +25 -0
  33. package/node_modules/@oxygen/shared/dist/repricing.d.ts +130 -0
  34. package/node_modules/@oxygen/shared/dist/repricing.js +320 -0
  35. package/node_modules/@oxygen/shared/dist/sending-limits.d.ts +32 -0
  36. package/node_modules/@oxygen/shared/dist/sending-limits.js +49 -0
  37. package/node_modules/@oxygen/shared/dist/sequence-failures.js +4 -1
  38. package/node_modules/@oxygen/shared/dist/stripe-price-catalog.d.ts +24 -0
  39. package/node_modules/@oxygen/shared/dist/stripe-price-catalog.js +58 -1
  40. package/node_modules/@oxygen/shared/dist/table-capacity.d.ts +39 -10
  41. package/node_modules/@oxygen/shared/dist/table-capacity.js +68 -4
  42. package/node_modules/@oxygen/shared/dist/telemetry.d.ts +9 -0
  43. package/node_modules/@oxygen/shared/dist/telemetry.js +36 -2
  44. package/node_modules/@oxygen/shared/dist/trace-context.d.ts +29 -0
  45. package/node_modules/@oxygen/shared/dist/trace-context.js +88 -0
  46. package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
  47. package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
  48. package/package.json +1 -1
  49. package/node_modules/@oxygen/shared/dist/email-warmup-readiness.d.ts +0 -64
  50. package/node_modules/@oxygen/shared/dist/email-warmup-readiness.js +0 -90
@@ -11,10 +11,12 @@ const HOUR = 60 * 60;
11
11
  const DAY = 24 * HOUR;
12
12
  const MIB = 1024 * 1024;
13
13
  /**
14
- * One platform-wide Table import ceiling. A file can fill an empty physical
15
- * Table exactly to its retained-row capacity on every plan; imports into a
16
- * non-empty Table remain subject to that Table's remaining capacity and the
17
- * workspace-wide capacity envelope.
14
+ * The per-rung Table import ceiling this matrix reports: today's envelope. The
15
+ * ceiling ENFORCED on an import is the workspace's plan-band rows-per-Table
16
+ * limit (`resolveWorkspaceTableCapacity`, PROPOSED P-60: a file can fill an
17
+ * empty Table exactly), which the web import paths resolve per organization.
18
+ * Imports into a non-empty Table remain subject to that Table's remaining
19
+ * capacity and the workspace-wide envelope.
18
20
  */
19
21
  export const TABLE_IMPORT_ROW_LIMIT = WORKSPACE_TABLE_CAPACITY.tableRowLimit;
20
22
  // The platform request-body ceiling belongs to the same question as the import
@@ -33,38 +35,46 @@ export const MAX_CLI_JSON_BODY_BYTES = 2_000_000;
33
35
  * The per-rung limit matrix. `ai_live` deliberately equals `tool_live` at every
34
36
  * rung — one "live actions" mental model; the per-call cost asymmetry between
35
37
  * AI and tool calls is priced in credits, not throttled here.
38
+ *
39
+ * API rates follow the 2026-09 repricing (decision L2, ratified 2026-09-26):
40
+ * `cli.global` is the per-organization and per-key request total per minute,
41
+ * 1,200 / 3,000 / 6,000 / 12,000 / 30,000 from free to scale. The per-operation
42
+ * buckets below are PROPOSED (P-52, repricing spec § 4.2): each pre-repricing
43
+ * bucket multiplied by its rung's organization factor, 2x on free and 5x on
44
+ * every paid rung, and never above the rung's per-key total. `tenantSchema` and
45
+ * the flat `tenant_admin` guard in the web rate limiter are DDL abuse guards and
46
+ * stay unscaled.
36
47
  */
37
48
  export const PLAN_LIMITS = {
38
49
  free: {
39
50
  cli: {
40
- global: { keyRequestsPerMinute: 120, orgRequestsPerMinute: 600 },
41
- tenantRead: { requestsPerMinute: 60, orgUnits: { limit: 500_000, windowSeconds: HOUR } },
42
- tenantWrite: { requestsPerMinute: 30, orgUnits: { limit: 100_000, windowSeconds: HOUR } },
43
- bulkImport: { requestsPerMinute: 10, orgRequests: { limit: 100, windowSeconds: HOUR } },
44
- aiLive: { requestsPerMinute: 20, orgRequests: { limit: 100, windowSeconds: HOUR } },
45
- toolLive: { requestsPerMinute: 20, orgRequests: { limit: 100, windowSeconds: HOUR } },
46
- toolDryRun: { requestsPerMinute: 60, orgRequests: { limit: 500, windowSeconds: HOUR } },
51
+ global: { keyRequestsPerMinute: 1_200, orgRequestsPerMinute: 1_200 },
52
+ tenantRead: { requestsPerMinute: 120, orgUnits: { limit: 1_000_000, windowSeconds: HOUR } },
53
+ tenantWrite: { requestsPerMinute: 60, orgUnits: { limit: 200_000, windowSeconds: HOUR } },
54
+ bulkImport: { requestsPerMinute: 20, orgRequests: { limit: 200, windowSeconds: HOUR } },
55
+ aiLive: { requestsPerMinute: 40, orgRequests: { limit: 200, windowSeconds: HOUR } },
56
+ toolLive: { requestsPerMinute: 40, orgRequests: { limit: 200, windowSeconds: HOUR } },
57
+ toolDryRun: { requestsPerMinute: 120, orgRequests: { limit: 1_000, windowSeconds: HOUR } },
47
58
  tenantSchema: { requestsPerMinute: 20, orgRequests: { limit: 100, windowSeconds: HOUR } },
48
59
  maxWriteRowsPerRequest: 5_000,
49
60
  },
50
61
  web: {
51
- tenantRead: { requestsPerMinute: 120, orgUnits: { limit: 1_000_000, windowSeconds: HOUR } },
52
- tenantWrite: { requestsPerMinute: 60, orgUnits: { limit: 500_000, windowSeconds: HOUR } },
53
- columnRun: { requestsPerMinute: 30, orgUnits: { limit: 2_000, windowSeconds: HOUR } },
54
- import: { requestsPerMinute: 10, orgRequests: { limit: 100, windowSeconds: HOUR } },
62
+ tenantRead: { requestsPerMinute: 240, orgUnits: { limit: 2_000_000, windowSeconds: HOUR } },
63
+ tenantWrite: { requestsPerMinute: 120, orgUnits: { limit: 1_000_000, windowSeconds: HOUR } },
64
+ columnRun: { requestsPerMinute: 60, orgUnits: { limit: 4_000, windowSeconds: HOUR } },
65
+ import: { requestsPerMinute: 20, orgRequests: { limit: 200, windowSeconds: HOUR } },
55
66
  },
56
67
  import: {
57
68
  maxRowsPerFile: TABLE_IMPORT_ROW_LIMIT,
58
69
  maxFileBytes: 100 * MIB,
59
70
  maxDirectCsvBodyBytes: 10_000_000,
60
71
  },
61
- // Sized against the free tier's actual funding (OXP-10.2.4, 2026-08-17):
62
- // 5,000 credits at signup plus 5,000 on CLI/MCP activation, one time each,
63
- // with no monthly allowance to refill them. The previous ceilings were
64
- // written when `free` meant a churned org that could spend nothing, so they
65
- // were harmless at any value; now a single Agent run capped at 10,000 could
66
- // consume the ENTIRE lifetime grant, and one capped at 5,000 could consume
67
- // the whole signup grant before the customer saw anything work.
72
+ // Sized against the free tier's actual funding (OXP-10.2.4, 2026-08-17): one
73
+ // signup grant of FREE_SIGNUP_GRANT_CREDITS (1,000) with no monthly allowance
74
+ // to refill it. The previous ceilings were written when `free` meant a
75
+ // churned org that could spend nothing, so they were harmless at any value;
76
+ // an Agent run capped at the old 1,000 (today's unit) could consume the
77
+ // ENTIRE lifetime grant before the customer saw anything work.
68
78
  //
69
79
  // These are runaway guards, not the billing meter — a workspace that tops up
70
80
  // is bounded by its balance, not by these. The intent is only that no single
@@ -75,32 +85,31 @@ export const PLAN_LIMITS = {
75
85
  maxUpstreamCostUsd: 10,
76
86
  maxUpstreamCostUsdByok: 10,
77
87
  },
78
- // Left at 5,000/1,500 deliberately. The signup grant is exactly one default
79
- // Copilot session, and that is the point: a founder who picks the in-product
80
- // path over the CLI must be able to complete one real session on the base
81
- // grant alone. Lowering this would re-create the dead-on-arrival Copilot the
82
- // split grant exists to prevent.
88
+ // Left at 500/150 deliberately (5,000/1,500 before the 2026-09-19 unit
89
+ // change). A founder who picks the in-product path over the CLI must be able
90
+ // to complete one real Copilot session on the 1,000-credit signup grant
91
+ // alone. Lowering this would re-create a dead-on-arrival Copilot.
83
92
  copilot: { maxSessionBudgetCredits: 500, defaultPerTurnCreditCeiling: 150 },
84
93
  signals: { maxEvents: 100, maxWindowDays: 30 },
85
94
  tableActions: { maxActionsPerRun: 10 },
86
95
  },
87
96
  starter: {
88
97
  cli: {
89
- global: { keyRequestsPerMinute: 240, orgRequestsPerMinute: 600 },
90
- tenantRead: { requestsPerMinute: 120, orgUnits: { limit: 25_000_000, windowSeconds: DAY } },
91
- tenantWrite: { requestsPerMinute: 120, orgUnits: { limit: 5_000_000, windowSeconds: DAY } },
92
- bulkImport: { requestsPerMinute: 30, orgRequests: { limit: 500, windowSeconds: HOUR } },
93
- aiLive: { requestsPerMinute: 60, orgRequests: { limit: 5_000, windowSeconds: HOUR } },
94
- toolLive: { requestsPerMinute: 60, orgRequests: { limit: 5_000, windowSeconds: HOUR } },
95
- toolDryRun: { requestsPerMinute: 120, orgRequests: { limit: 2_000, windowSeconds: HOUR } },
98
+ global: { keyRequestsPerMinute: 3_000, orgRequestsPerMinute: 3_000 },
99
+ tenantRead: { requestsPerMinute: 600, orgUnits: { limit: 125_000_000, windowSeconds: DAY } },
100
+ tenantWrite: { requestsPerMinute: 600, orgUnits: { limit: 25_000_000, windowSeconds: DAY } },
101
+ bulkImport: { requestsPerMinute: 150, orgRequests: { limit: 2_500, windowSeconds: HOUR } },
102
+ aiLive: { requestsPerMinute: 300, orgRequests: { limit: 25_000, windowSeconds: HOUR } },
103
+ toolLive: { requestsPerMinute: 300, orgRequests: { limit: 25_000, windowSeconds: HOUR } },
104
+ toolDryRun: { requestsPerMinute: 600, orgRequests: { limit: 10_000, windowSeconds: HOUR } },
96
105
  tenantSchema: { requestsPerMinute: 60, orgRequests: { limit: 600, windowSeconds: HOUR } },
97
106
  maxWriteRowsPerRequest: 50_000,
98
107
  },
99
108
  web: {
100
- tenantRead: { requestsPerMinute: 300, orgUnits: { limit: 20_000_000, windowSeconds: DAY } },
101
- tenantWrite: { requestsPerMinute: 180, orgUnits: { limit: 10_000_000, windowSeconds: DAY } },
102
- columnRun: { requestsPerMinute: 120, orgUnits: { limit: 500_000, windowSeconds: DAY } },
103
- import: { requestsPerMinute: 30, orgRequests: { limit: 500, windowSeconds: HOUR } },
109
+ tenantRead: { requestsPerMinute: 1_500, orgUnits: { limit: 100_000_000, windowSeconds: DAY } },
110
+ tenantWrite: { requestsPerMinute: 900, orgUnits: { limit: 50_000_000, windowSeconds: DAY } },
111
+ columnRun: { requestsPerMinute: 600, orgUnits: { limit: 2_500_000, windowSeconds: DAY } },
112
+ import: { requestsPerMinute: 150, orgRequests: { limit: 2_500, windowSeconds: HOUR } },
104
113
  },
105
114
  import: {
106
115
  maxRowsPerFile: TABLE_IMPORT_ROW_LIMIT,
@@ -119,21 +128,21 @@ export const PLAN_LIMITS = {
119
128
  },
120
129
  pro: {
121
130
  cli: {
122
- global: { keyRequestsPerMinute: 240, orgRequestsPerMinute: 1_200 },
123
- tenantRead: { requestsPerMinute: 240, orgUnits: { limit: 50_000_000, windowSeconds: DAY } },
124
- tenantWrite: { requestsPerMinute: 240, orgUnits: { limit: 10_000_000, windowSeconds: DAY } },
125
- bulkImport: { requestsPerMinute: 60, orgRequests: { limit: 1_000, windowSeconds: HOUR } },
126
- aiLive: { requestsPerMinute: 120, orgRequests: { limit: 12_000, windowSeconds: HOUR } },
127
- toolLive: { requestsPerMinute: 120, orgRequests: { limit: 12_000, windowSeconds: HOUR } },
128
- toolDryRun: { requestsPerMinute: 120, orgRequests: { limit: 2_000, windowSeconds: HOUR } },
131
+ global: { keyRequestsPerMinute: 6_000, orgRequestsPerMinute: 6_000 },
132
+ tenantRead: { requestsPerMinute: 1_200, orgUnits: { limit: 250_000_000, windowSeconds: DAY } },
133
+ tenantWrite: { requestsPerMinute: 1_200, orgUnits: { limit: 50_000_000, windowSeconds: DAY } },
134
+ bulkImport: { requestsPerMinute: 300, orgRequests: { limit: 5_000, windowSeconds: HOUR } },
135
+ aiLive: { requestsPerMinute: 600, orgRequests: { limit: 60_000, windowSeconds: HOUR } },
136
+ toolLive: { requestsPerMinute: 600, orgRequests: { limit: 60_000, windowSeconds: HOUR } },
137
+ toolDryRun: { requestsPerMinute: 600, orgRequests: { limit: 10_000, windowSeconds: HOUR } },
129
138
  tenantSchema: { requestsPerMinute: 60, orgRequests: { limit: 600, windowSeconds: HOUR } },
130
139
  maxWriteRowsPerRequest: 50_000,
131
140
  },
132
141
  web: {
133
- tenantRead: { requestsPerMinute: 600, orgUnits: { limit: 40_000_000, windowSeconds: DAY } },
134
- tenantWrite: { requestsPerMinute: 360, orgUnits: { limit: 20_000_000, windowSeconds: DAY } },
135
- columnRun: { requestsPerMinute: 240, orgUnits: { limit: 1_000_000, windowSeconds: DAY } },
136
- import: { requestsPerMinute: 60, orgRequests: { limit: 1_000, windowSeconds: HOUR } },
142
+ tenantRead: { requestsPerMinute: 3_000, orgUnits: { limit: 200_000_000, windowSeconds: DAY } },
143
+ tenantWrite: { requestsPerMinute: 1_800, orgUnits: { limit: 100_000_000, windowSeconds: DAY } },
144
+ columnRun: { requestsPerMinute: 1_200, orgUnits: { limit: 5_000_000, windowSeconds: DAY } },
145
+ import: { requestsPerMinute: 300, orgRequests: { limit: 5_000, windowSeconds: HOUR } },
137
146
  },
138
147
  import: {
139
148
  maxRowsPerFile: TABLE_IMPORT_ROW_LIMIT,
@@ -152,21 +161,21 @@ export const PLAN_LIMITS = {
152
161
  },
153
162
  team: {
154
163
  cli: {
155
- global: { keyRequestsPerMinute: 240, orgRequestsPerMinute: 2_400 },
156
- tenantRead: { requestsPerMinute: 480, orgUnits: { limit: 100_000_000, windowSeconds: DAY } },
157
- tenantWrite: { requestsPerMinute: 480, orgUnits: { limit: 25_000_000, windowSeconds: DAY } },
158
- bulkImport: { requestsPerMinute: 120, orgRequests: { limit: 2_000, windowSeconds: HOUR } },
159
- aiLive: { requestsPerMinute: 240, orgRequests: { limit: 30_000, windowSeconds: HOUR } },
160
- toolLive: { requestsPerMinute: 240, orgRequests: { limit: 30_000, windowSeconds: HOUR } },
161
- toolDryRun: { requestsPerMinute: 120, orgRequests: { limit: 2_000, windowSeconds: HOUR } },
164
+ global: { keyRequestsPerMinute: 12_000, orgRequestsPerMinute: 12_000 },
165
+ tenantRead: { requestsPerMinute: 2_400, orgUnits: { limit: 500_000_000, windowSeconds: DAY } },
166
+ tenantWrite: { requestsPerMinute: 2_400, orgUnits: { limit: 125_000_000, windowSeconds: DAY } },
167
+ bulkImport: { requestsPerMinute: 600, orgRequests: { limit: 10_000, windowSeconds: HOUR } },
168
+ aiLive: { requestsPerMinute: 1_200, orgRequests: { limit: 150_000, windowSeconds: HOUR } },
169
+ toolLive: { requestsPerMinute: 1_200, orgRequests: { limit: 150_000, windowSeconds: HOUR } },
170
+ toolDryRun: { requestsPerMinute: 600, orgRequests: { limit: 10_000, windowSeconds: HOUR } },
162
171
  tenantSchema: { requestsPerMinute: 60, orgRequests: { limit: 600, windowSeconds: HOUR } },
163
172
  maxWriteRowsPerRequest: 50_000,
164
173
  },
165
174
  web: {
166
- tenantRead: { requestsPerMinute: 1_200, orgUnits: { limit: 100_000_000, windowSeconds: DAY } },
167
- tenantWrite: { requestsPerMinute: 720, orgUnits: { limit: 50_000_000, windowSeconds: DAY } },
168
- columnRun: { requestsPerMinute: 480, orgUnits: { limit: 2_500_000, windowSeconds: DAY } },
169
- import: { requestsPerMinute: 120, orgRequests: { limit: 2_000, windowSeconds: HOUR } },
175
+ tenantRead: { requestsPerMinute: 6_000, orgUnits: { limit: 500_000_000, windowSeconds: DAY } },
176
+ tenantWrite: { requestsPerMinute: 3_600, orgUnits: { limit: 250_000_000, windowSeconds: DAY } },
177
+ columnRun: { requestsPerMinute: 2_400, orgUnits: { limit: 12_500_000, windowSeconds: DAY } },
178
+ import: { requestsPerMinute: 600, orgRequests: { limit: 10_000, windowSeconds: HOUR } },
170
179
  },
171
180
  import: {
172
181
  maxRowsPerFile: TABLE_IMPORT_ROW_LIMIT,
@@ -185,21 +194,21 @@ export const PLAN_LIMITS = {
185
194
  },
186
195
  scale: {
187
196
  cli: {
188
- global: { keyRequestsPerMinute: 240, orgRequestsPerMinute: 6_000 },
189
- tenantRead: { requestsPerMinute: 1_000, orgUnits: { limit: 500_000_000, windowSeconds: DAY } },
190
- tenantWrite: { requestsPerMinute: 1_000, orgUnits: { limit: 100_000_000, windowSeconds: DAY } },
191
- bulkImport: { requestsPerMinute: 240, orgRequests: { limit: 5_000, windowSeconds: HOUR } },
192
- aiLive: { requestsPerMinute: 600, orgRequests: { limit: 100_000, windowSeconds: HOUR } },
193
- toolLive: { requestsPerMinute: 600, orgRequests: { limit: 100_000, windowSeconds: HOUR } },
194
- toolDryRun: { requestsPerMinute: 120, orgRequests: { limit: 2_000, windowSeconds: HOUR } },
197
+ global: { keyRequestsPerMinute: 30_000, orgRequestsPerMinute: 30_000 },
198
+ tenantRead: { requestsPerMinute: 5_000, orgUnits: { limit: 2_500_000_000, windowSeconds: DAY } },
199
+ tenantWrite: { requestsPerMinute: 5_000, orgUnits: { limit: 500_000_000, windowSeconds: DAY } },
200
+ bulkImport: { requestsPerMinute: 1_200, orgRequests: { limit: 25_000, windowSeconds: HOUR } },
201
+ aiLive: { requestsPerMinute: 3_000, orgRequests: { limit: 500_000, windowSeconds: HOUR } },
202
+ toolLive: { requestsPerMinute: 3_000, orgRequests: { limit: 500_000, windowSeconds: HOUR } },
203
+ toolDryRun: { requestsPerMinute: 600, orgRequests: { limit: 10_000, windowSeconds: HOUR } },
195
204
  tenantSchema: { requestsPerMinute: 60, orgRequests: { limit: 600, windowSeconds: HOUR } },
196
205
  maxWriteRowsPerRequest: 50_000,
197
206
  },
198
207
  web: {
199
- tenantRead: { requestsPerMinute: 2_000, orgUnits: { limit: 400_000_000, windowSeconds: DAY } },
200
- tenantWrite: { requestsPerMinute: 1_500, orgUnits: { limit: 200_000_000, windowSeconds: DAY } },
201
- columnRun: { requestsPerMinute: 1_000, orgUnits: { limit: 10_000_000, windowSeconds: DAY } },
202
- import: { requestsPerMinute: 240, orgRequests: { limit: 5_000, windowSeconds: HOUR } },
208
+ tenantRead: { requestsPerMinute: 10_000, orgUnits: { limit: 2_000_000_000, windowSeconds: DAY } },
209
+ tenantWrite: { requestsPerMinute: 7_500, orgUnits: { limit: 1_000_000_000, windowSeconds: DAY } },
210
+ columnRun: { requestsPerMinute: 5_000, orgUnits: { limit: 50_000_000, windowSeconds: DAY } },
211
+ import: { requestsPerMinute: 1_200, orgRequests: { limit: 25_000, windowSeconds: HOUR } },
203
212
  },
204
213
  import: {
205
214
  maxRowsPerFile: TABLE_IMPORT_ROW_LIMIT,
@@ -72,19 +72,73 @@ export declare const AI_COLUMN_CREDITS: {
72
72
  * never read.
73
73
  *
74
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.
75
+ * then reads: `serper.search` (0.5) finds the URLs, then an additive read turns the
76
+ * top result's ~160-char SERP teaser into real page text. The read tries OXYGEN's
77
+ * own `web.page_fetch` (0.1) first and `exa.contents` (0.5) only when the native
78
+ * fetch cannot read the page. So a typical row spends 0.6 and a preview reserves
79
+ * 4.6: the ceiling covers the `exa.search` fallback (3.5) firing when serper finds
80
+ * nothing plus both read lanes. A read miss leaves the row grounded on the snippets
81
+ * it already has.
81
82
  *
82
83
  * Both numbers are RESOLVER-DERIVED and pinned by pricing-sheet-conformance.test.ts
83
84
  * against the shipped default, so a re-price or a lane change fails a test rather
84
85
  * than quietly mispricing this page. Do not hand-edit them.
85
86
  */
86
- export declare const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 1;
87
- export declare const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.5;
87
+ export declare const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 0.6;
88
+ export declare const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.6;
89
+ /**
90
+ * Research depth (Claygent parity). `quick` is the single grounded pass priced
91
+ * above (the column's tier price plus AI_COLUMN_WEB_SEARCH_*; 2.1 typical at the
92
+ * Fast tier). A `standard` or `deep` row runs a bounded agent loop — several model
93
+ * turns over a growing evidence list — on a model the DEPTH fixes (standard on the
94
+ * Fast tier, deep on Balanced; the column's own tier applies to quick only), so its
95
+ * model leg is one flat price per row, reserved once:
96
+ *
97
+ * standard: 4.3 + 1.2 tools = 5.5 typical
98
+ * deep: 7.6 + 2.4 tools = 10 typical
99
+ *
100
+ * Founder-ratified 2026-09-26: 30-50% under Clay, >=5x markup. The Clay comparison
101
+ * it was set against: Clay web research bills per row in Data Credits — GPT-5 Nano
102
+ * 0.5 DC, Mini/Flash 1 DC, Claygent Neon 2 DC, Argon 3 DC — at >= $0.05 per DC plus
103
+ * ~$0.01 of action per row; OXYGEN credits are $0.01. Every figure must also keep
104
+ * >= 5x over the loop's modelled COGS. Pinned against the live estimator by
105
+ * @oxygen/integrations pricing-sheet-conformance.test.ts.
106
+ */
107
+ export declare const RESEARCH_DEPTH_MODEL_CREDITS: {
108
+ readonly standard: 4.3;
109
+ readonly deep: 7.6;
110
+ };
111
+ /** The tier whose model each loop depth runs on, whatever tier the column stores. */
112
+ export declare const RESEARCH_DEPTH_MODEL_TIER: {
113
+ readonly standard: "low";
114
+ readonly deep: "medium";
115
+ };
116
+ /**
117
+ * The tool half of a standard/deep row. `typical` is the ratified planning shape —
118
+ * standard: 2 serper searches + 2 native page reads; deep: 3 serper searches + 4
119
+ * native reads + 1 exa.contents fallback read. `reserved` is every budgeted tool
120
+ * call at its dearest lane — each web_search, the row's shared exa.search pool
121
+ * (standard 1, deep 2: the zero-result fallback and semantic_search draw on it),
122
+ * each read's full ladder, deep's one Firecrawl read and site crawls. Deep's
123
+ * company-news call is opt-in (a news lead-lane column) and adds its own price to
124
+ * the reserve only there. Resolver-derived, pinned like the above.
125
+ */
126
+ export declare const RESEARCH_DEPTH_GROUNDING_CREDITS: {
127
+ readonly standard: {
128
+ readonly typical: 1.2;
129
+ readonly reserved: 7.4;
130
+ };
131
+ readonly deep: {
132
+ readonly typical: 2.4;
133
+ readonly reserved: 19.8;
134
+ };
135
+ };
136
+ /** Typical per-row totals at each depth's default tier (founder-ratified 2026-09-26). */
137
+ export declare const RESEARCH_DEPTH_TYPICAL_ROW_CREDITS: {
138
+ readonly quick: 2.1;
139
+ readonly standard: 5.5;
140
+ readonly deep: 10;
141
+ };
88
142
  /** Workflow/automation actions (steps, tool calls, row writes) — capacity guard. */
89
143
  export declare const AUTOMATION_ACTION_CREDITS = 0.001;
90
144
  /**
@@ -113,7 +167,7 @@ export declare const MANAGED_INBOX_CREDITS_PER_MONTH: {
113
167
  * Costing only the outbound leg undercharges every call by 29%.
114
168
  */
115
169
  export declare const VOICE_MARKUP = 5;
116
- export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 500;
170
+ export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 1000;
117
171
  export declare const VOICE_CREDITS_PER_MINUTE = 9;
118
172
  export declare const VOICE_CREDITS_PER_AMD_CALL = 3.8;
119
173
  /** Managed domains: registrar at-cost × 1.25 (≈ a $10.44 .com → ~13,050 credits/yr). */
@@ -142,8 +196,12 @@ export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 16.6;
142
196
  * price; every per-action charge is 0. Per-MESSAGE sends on email and WhatsApp
143
197
  * stay 0 too — but a connected WhatsApp NUMBER carries its own monthly
144
198
  * connection fee, see WHATSAPP_ACCOUNT_CREDITS_PER_MONTH.
199
+ *
200
+ * The value is the seeded price after the 2026-09 repricing (3,400, decision
201
+ * 2.1). The price in force before its effective-date switch is lower: resolve
202
+ * it with repricedChargeCredits from `@oxygen/shared/repricing` on the server.
145
203
  */
146
- export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 1000;
204
+ export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3400;
147
205
  export declare const LINKEDIN_ACTION_CREDITS: {
148
206
  readonly visit_profile: 0;
149
207
  readonly invite: 0;
@@ -156,11 +214,18 @@ export declare const LINKEDIN_ACTION_CREDITS: {
156
214
  export declare const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = 0;
157
215
  /**
158
216
  * WhatsApp numbers: flat monthly connection fee per connected number, the same
159
- * seat shape as LinkedIn. Billed off the rolling-30d peak, so a number connected
160
- * part-way through a month still bills the full cycle. WhatsApp message sends
161
- * themselves remain 0 credits.
217
+ * seat shape as LinkedIn. WhatsApp message sends themselves remain 0 credits.
218
+ * Seeded at the 2026-09 repricing's price (3,000, decision 2.3); resolve the
219
+ * price in force with repricedChargeCredits.
220
+ */
221
+ export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3000;
222
+ /**
223
+ * X accounts: monthly credit reservation per connected account (2026-09
224
+ * repricing, decision 2.2). Like the LinkedIn and WhatsApp constants above this
225
+ * is the seeded, post-repricing price; show the price in force with
226
+ * repricedChargeCredits from `@oxygen/shared/repricing`.
162
227
  */
163
- export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 1000;
228
+ export declare const X_ACCOUNT_CREDITS_PER_MONTH = 1000;
164
229
  /** Dedicated egress IP add-on. */
165
230
  export declare const EGRESS_IP_CREDITS_PER_MONTH = 2500;
166
231
  /**
@@ -34,7 +34,7 @@
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_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";
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, X_ACCOUNT_CREDITS_PER_MONTH as SNAPSHOT_X_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;
@@ -67,19 +67,57 @@ export const AI_COLUMN_CREDITS = { low: 1.5, medium: 7.5, high: 25 };
67
67
  * never read.
68
68
  *
69
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.
70
+ * then reads: `serper.search` (0.5) finds the URLs, then an additive read turns the
71
+ * top result's ~160-char SERP teaser into real page text. The read tries OXYGEN's
72
+ * own `web.page_fetch` (0.1) first and `exa.contents` (0.5) only when the native
73
+ * fetch cannot read the page. So a typical row spends 0.6 and a preview reserves
74
+ * 4.6: the ceiling covers the `exa.search` fallback (3.5) firing when serper finds
75
+ * nothing plus both read lanes. A read miss leaves the row grounded on the snippets
76
+ * it already has.
76
77
  *
77
78
  * Both numbers are RESOLVER-DERIVED and pinned by pricing-sheet-conformance.test.ts
78
79
  * against the shipped default, so a re-price or a lane change fails a test rather
79
80
  * than quietly mispricing this page. Do not hand-edit them.
80
81
  */
81
- export const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 1;
82
- export const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.5;
82
+ export const AI_COLUMN_WEB_SEARCH_TYPICAL_CREDITS = 0.6;
83
+ export const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.6;
84
+ /**
85
+ * Research depth (Claygent parity). `quick` is the single grounded pass priced
86
+ * above (the column's tier price plus AI_COLUMN_WEB_SEARCH_*; 2.1 typical at the
87
+ * Fast tier). A `standard` or `deep` row runs a bounded agent loop — several model
88
+ * turns over a growing evidence list — on a model the DEPTH fixes (standard on the
89
+ * Fast tier, deep on Balanced; the column's own tier applies to quick only), so its
90
+ * model leg is one flat price per row, reserved once:
91
+ *
92
+ * standard: 4.3 + 1.2 tools = 5.5 typical
93
+ * deep: 7.6 + 2.4 tools = 10 typical
94
+ *
95
+ * Founder-ratified 2026-09-26: 30-50% under Clay, >=5x markup. The Clay comparison
96
+ * it was set against: Clay web research bills per row in Data Credits — GPT-5 Nano
97
+ * 0.5 DC, Mini/Flash 1 DC, Claygent Neon 2 DC, Argon 3 DC — at >= $0.05 per DC plus
98
+ * ~$0.01 of action per row; OXYGEN credits are $0.01. Every figure must also keep
99
+ * >= 5x over the loop's modelled COGS. Pinned against the live estimator by
100
+ * @oxygen/integrations pricing-sheet-conformance.test.ts.
101
+ */
102
+ export const RESEARCH_DEPTH_MODEL_CREDITS = { standard: 4.3, deep: 7.6 };
103
+ /** The tier whose model each loop depth runs on, whatever tier the column stores. */
104
+ export const RESEARCH_DEPTH_MODEL_TIER = { standard: "low", deep: "medium" };
105
+ /**
106
+ * The tool half of a standard/deep row. `typical` is the ratified planning shape —
107
+ * standard: 2 serper searches + 2 native page reads; deep: 3 serper searches + 4
108
+ * native reads + 1 exa.contents fallback read. `reserved` is every budgeted tool
109
+ * call at its dearest lane — each web_search, the row's shared exa.search pool
110
+ * (standard 1, deep 2: the zero-result fallback and semantic_search draw on it),
111
+ * each read's full ladder, deep's one Firecrawl read and site crawls. Deep's
112
+ * company-news call is opt-in (a news lead-lane column) and adds its own price to
113
+ * the reserve only there. Resolver-derived, pinned like the above.
114
+ */
115
+ export const RESEARCH_DEPTH_GROUNDING_CREDITS = {
116
+ standard: { typical: 1.2, reserved: 7.4 },
117
+ deep: { typical: 2.4, reserved: 19.8 },
118
+ };
119
+ /** Typical per-row totals at each depth's default tier (founder-ratified 2026-09-26). */
120
+ export const RESEARCH_DEPTH_TYPICAL_ROW_CREDITS = { quick: 2.1, standard: 5.5, deep: 10 };
83
121
  /** Workflow/automation actions (steps, tool calls, row writes) — capacity guard. */
84
122
  export const AUTOMATION_ACTION_CREDITS = SNAPSHOT_AUTOMATION_ACTION_CREDITS;
85
123
  /**
@@ -137,17 +175,28 @@ export const PLACEMENT_TEST_OVERAGE_CREDITS = SNAPSHOT_PLACEMENT_TEST_OVERAGE_CR
137
175
  * price; every per-action charge is 0. Per-MESSAGE sends on email and WhatsApp
138
176
  * stay 0 too — but a connected WhatsApp NUMBER carries its own monthly
139
177
  * connection fee, see WHATSAPP_ACCOUNT_CREDITS_PER_MONTH.
178
+ *
179
+ * The value is the seeded price after the 2026-09 repricing (3,400, decision
180
+ * 2.1). The price in force before its effective-date switch is lower: resolve
181
+ * it with repricedChargeCredits from `@oxygen/shared/repricing` on the server.
140
182
  */
141
183
  export const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = SNAPSHOT_LINKEDIN_ACCOUNT_CREDITS_PER_MONTH;
142
184
  export const LINKEDIN_ACTION_CREDITS = SNAPSHOT_LINKEDIN_ACTION_CREDITS;
143
185
  export const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = SNAPSHOT_LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH;
144
186
  /**
145
187
  * WhatsApp numbers: flat monthly connection fee per connected number, the same
146
- * seat shape as LinkedIn. Billed off the rolling-30d peak, so a number connected
147
- * part-way through a month still bills the full cycle. WhatsApp message sends
148
- * themselves remain 0 credits.
188
+ * seat shape as LinkedIn. WhatsApp message sends themselves remain 0 credits.
189
+ * Seeded at the 2026-09 repricing's price (3,000, decision 2.3); resolve the
190
+ * price in force with repricedChargeCredits.
149
191
  */
150
192
  export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = SNAPSHOT_WHATSAPP_ACCOUNT_CREDITS_PER_MONTH;
193
+ /**
194
+ * X accounts: monthly credit reservation per connected account (2026-09
195
+ * repricing, decision 2.2). Like the LinkedIn and WhatsApp constants above this
196
+ * is the seeded, post-repricing price; show the price in force with
197
+ * repricedChargeCredits from `@oxygen/shared/repricing`.
198
+ */
199
+ export const X_ACCOUNT_CREDITS_PER_MONTH = SNAPSHOT_X_ACCOUNT_CREDITS_PER_MONTH;
151
200
  /** Dedicated egress IP add-on. */
152
201
  export const EGRESS_IP_CREDITS_PER_MONTH = SNAPSHOT_EGRESS_IP_CREDITS_PER_MONTH;
153
202
  /**
@@ -15,8 +15,9 @@ 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 = 1000;
19
- export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 1000;
18
+ export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3400;
19
+ export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3000;
20
+ export declare const X_ACCOUNT_CREDITS_PER_MONTH = 1000;
20
21
  export declare const EGRESS_IP_CREDITS_PER_MONTH = 2500;
21
22
  export declare const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
22
23
  export declare const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
@@ -37,7 +38,7 @@ export declare const SENDING_SEAT_USD_CENTS: {
37
38
  export type SendingSeatKey = keyof typeof SENDING_SEAT_USD_CENTS;
38
39
  export declare const MANAGED_INBOX_USD_CENTS = 400;
39
40
  export declare const SENDING_DOMAIN_USD_CENTS = 1250;
40
- export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 500;
41
+ export declare const VOICE_NUMBER_CREDITS_PER_MONTH = 1000;
41
42
  export declare const VOICE_CREDITS_PER_MINUTE = 9;
42
43
  export declare const VOICE_CREDITS_PER_AMD_CALL = 3.8;
43
44
  /** Workflow steps, tool calls and row writes — a capacity guard, not a margin line. */
@@ -32,8 +32,14 @@ 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 = 1_000;
36
- export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 1_000;
35
+ //
36
+ // The connected-account reservations (LinkedIn, WhatsApp, X, phone number) carry
37
+ // the 2026-09 repricing's NEW price. Until its effective-date switch the price in
38
+ // force is lower; a surface that shows or charges one resolves it with
39
+ // repricedChargeCredits (@oxygen/shared/repricing), never from this literal alone.
40
+ export const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3_400;
41
+ export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3_000;
42
+ export const X_ACCOUNT_CREDITS_PER_MONTH = 1_000;
37
43
  export const EGRESS_IP_CREDITS_PER_MONTH = 2_500;
38
44
  export const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
39
45
  export const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
@@ -74,7 +80,7 @@ export const SENDING_SEAT_USD_CENTS = {
74
80
  export const MANAGED_INBOX_USD_CENTS = 400;
75
81
  export const SENDING_DOMAIN_USD_CENTS = 1_250;
76
82
  // --- voice ------------------------------------------------------------------
77
- export const VOICE_NUMBER_CREDITS_PER_MONTH = 500;
83
+ export const VOICE_NUMBER_CREDITS_PER_MONTH = 1_000;
78
84
  export const VOICE_CREDITS_PER_MINUTE = 9;
79
85
  export const VOICE_CREDITS_PER_AMD_CALL = 3.8;
80
86
  // --- per-action -------------------------------------------------------------
@@ -0,0 +1,4 @@
1
+ export declare function processResourceIdentity(): {
2
+ "host.name": string;
3
+ "service.instance.id": string;
4
+ };
@@ -0,0 +1,25 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { hostname } from "node:os";
3
+ /**
4
+ * The per-process OTel resource identity: which box, which process.
5
+ *
6
+ * The OTLP destinations turn resource auto-detection off (`autoDetectResources:
7
+ * false`) because Node's process detector copies argv verbatim — inline scripts
8
+ * and credentials included. That also dropped `host.name`, so every replica's
9
+ * spans, metrics and logs arrived indistinguishable. These two attributes are
10
+ * the safe part of what detection used to provide, stated explicitly.
11
+ *
12
+ * `service.instance.id` is minted once per process: a restart is a new
13
+ * instance, and two replicas on one host never collide the way a pid can.
14
+ */
15
+ const SERVICE_INSTANCE_ID = randomUUID();
16
+ export function processResourceIdentity() {
17
+ let host = "unknown";
18
+ try {
19
+ host = hostname() || "unknown";
20
+ }
21
+ catch {
22
+ // A sandbox without os access still gets a stable instance id.
23
+ }
24
+ return { "host.name": host, "service.instance.id": SERVICE_INSTANCE_ID };
25
+ }