@oxygen-agent/cli 1.1010.650 → 1.1010.905

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 (114) hide show
  1. package/README.md +1 -1
  2. package/dist/auto-update.d.ts +129 -0
  3. package/dist/auto-update.js +392 -0
  4. package/dist/command-manifest.js +15 -1
  5. package/dist/credentials.d.ts +2 -0
  6. package/dist/credentials.js +6 -3
  7. package/dist/functions-commands.js +1 -1
  8. package/dist/http-client.js +28 -4
  9. package/dist/inbox-needs-reply-notice.d.ts +12 -0
  10. package/dist/inbox-needs-reply-notice.js +51 -0
  11. package/dist/index.js +756 -177
  12. package/dist/run-wait.d.ts +3 -1
  13. package/dist/run-wait.js +19 -5
  14. package/dist/skills.js +48 -22
  15. package/dist/streamed-file-import.d.ts +58 -0
  16. package/dist/streamed-file-import.js +115 -0
  17. package/dist/update.d.ts +29 -0
  18. package/dist/update.js +62 -16
  19. package/dist/workflow-plan-limit-notices.d.ts +8 -0
  20. package/dist/workflow-plan-limit-notices.js +28 -0
  21. package/node_modules/@oxygen/cli-ugc/dist/commands.js +3 -3
  22. package/node_modules/@oxygen/shared/dist/billing-anchors.d.ts +50 -2
  23. package/node_modules/@oxygen/shared/dist/billing-anchors.js +94 -2
  24. package/node_modules/@oxygen/shared/dist/billing.d.ts +247 -37
  25. package/node_modules/@oxygen/shared/dist/billing.js +418 -45
  26. package/node_modules/@oxygen/shared/dist/capability-discovery.js +66 -6
  27. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +6 -6
  28. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +6 -6
  29. package/node_modules/@oxygen/shared/dist/cost-estimate-view.d.ts +50 -0
  30. package/node_modules/@oxygen/shared/dist/cost-estimate-view.js +90 -0
  31. package/node_modules/@oxygen/shared/dist/cost-estimate.d.ts +167 -0
  32. package/node_modules/@oxygen/shared/dist/cost-estimate.js +361 -0
  33. package/node_modules/@oxygen/shared/dist/credit-gate.d.ts +26 -0
  34. package/node_modules/@oxygen/shared/dist/credit-gate.js +65 -0
  35. package/node_modules/@oxygen/shared/dist/email-deliverability-policy.d.ts +51 -0
  36. package/node_modules/@oxygen/shared/dist/email-deliverability-policy.js +101 -0
  37. package/node_modules/@oxygen/shared/dist/email-hard-bounce.d.ts +27 -0
  38. package/node_modules/@oxygen/shared/dist/email-hard-bounce.js +27 -0
  39. package/node_modules/@oxygen/shared/dist/error-redaction.d.ts +1 -1
  40. package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -1
  41. package/node_modules/@oxygen/shared/dist/feature-gates.d.ts +10 -1
  42. package/node_modules/@oxygen/shared/dist/feature-gates.js +12 -1
  43. package/node_modules/@oxygen/shared/dist/file-import.d.ts +13 -1
  44. package/node_modules/@oxygen/shared/dist/file-import.js +33 -6
  45. package/node_modules/@oxygen/shared/dist/hosted-ai.d.ts +73 -3
  46. package/node_modules/@oxygen/shared/dist/hosted-ai.js +246 -24
  47. package/node_modules/@oxygen/shared/dist/import-limits.d.ts +25 -1
  48. package/node_modules/@oxygen/shared/dist/import-limits.js +35 -2
  49. package/node_modules/@oxygen/shared/dist/index.d.ts +4 -23
  50. package/node_modules/@oxygen/shared/dist/index.js +4 -43
  51. package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +114 -0
  52. package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +150 -0
  53. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +9 -0
  54. package/node_modules/@oxygen/shared/dist/object-storage.js +17 -0
  55. package/node_modules/@oxygen/shared/dist/operational-telemetry.d.ts +41 -0
  56. package/node_modules/@oxygen/shared/dist/operational-telemetry.js +55 -0
  57. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +19 -2
  58. package/node_modules/@oxygen/shared/dist/plan-band.d.ts +234 -0
  59. package/node_modules/@oxygen/shared/dist/plan-band.js +312 -0
  60. package/node_modules/@oxygen/shared/dist/plan-capabilities.d.ts +77 -7
  61. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +87 -7
  62. package/node_modules/@oxygen/shared/dist/plan-limits-view.d.ts +219 -0
  63. package/node_modules/@oxygen/shared/dist/plan-limits-view.js +330 -0
  64. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +335 -126
  65. package/node_modules/@oxygen/shared/dist/plan-limits.js +277 -86
  66. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +158 -49
  67. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +139 -41
  68. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +42 -23
  69. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +56 -37
  70. package/node_modules/@oxygen/shared/dist/process-resource.d.ts +4 -0
  71. package/node_modules/@oxygen/shared/dist/process-resource.js +25 -0
  72. package/node_modules/@oxygen/shared/dist/provider-http-error.d.ts +10 -0
  73. package/node_modules/@oxygen/shared/dist/provider-http-error.js +27 -0
  74. package/node_modules/@oxygen/shared/dist/repricing.d.ts +257 -0
  75. package/node_modules/@oxygen/shared/dist/repricing.js +721 -0
  76. package/node_modules/@oxygen/shared/dist/semver.d.ts +21 -0
  77. package/node_modules/@oxygen/shared/dist/semver.js +41 -0
  78. package/node_modules/@oxygen/shared/dist/sending-limits.d.ts +30 -0
  79. package/node_modules/@oxygen/shared/dist/sending-limits.js +43 -0
  80. package/node_modules/@oxygen/shared/dist/sending-seats.d.ts +18 -15
  81. package/node_modules/@oxygen/shared/dist/sending-seats.js +22 -17
  82. package/node_modules/@oxygen/shared/dist/sequence-failures.js +4 -1
  83. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +57 -8
  84. package/node_modules/@oxygen/shared/dist/spend-safety.js +64 -11
  85. package/node_modules/@oxygen/shared/dist/stripe-price-catalog.d.ts +33 -1
  86. package/node_modules/@oxygen/shared/dist/stripe-price-catalog.js +71 -1
  87. package/node_modules/@oxygen/shared/dist/table-capacity.d.ts +68 -10
  88. package/node_modules/@oxygen/shared/dist/table-capacity.js +85 -4
  89. package/node_modules/@oxygen/shared/dist/telemetry-export-observer.d.ts +6 -0
  90. package/node_modules/@oxygen/shared/dist/telemetry-export-observer.js +13 -5
  91. package/node_modules/@oxygen/shared/dist/telemetry-resource.d.ts +40 -0
  92. package/node_modules/@oxygen/shared/dist/telemetry-resource.js +35 -0
  93. package/node_modules/@oxygen/shared/dist/telemetry.d.ts +9 -0
  94. package/node_modules/@oxygen/shared/dist/telemetry.js +41 -2
  95. package/node_modules/@oxygen/shared/dist/trace-context.d.ts +29 -0
  96. package/node_modules/@oxygen/shared/dist/trace-context.js +88 -0
  97. package/node_modules/@oxygen/shared/dist/ugc.d.ts +15 -0
  98. package/node_modules/@oxygen/shared/dist/ugc.js +29 -0
  99. package/node_modules/@oxygen/shared/dist/version.d.ts +1 -3
  100. package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
  101. package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
  102. package/node_modules/@oxygen/shared/dist/version.js +14 -27
  103. package/node_modules/@oxygen/shared/dist/workspace-file-storage.d.ts +5 -0
  104. package/node_modules/@oxygen/shared/dist/workspace-file-storage.js +5 -0
  105. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +3 -3
  106. package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +15 -1
  107. package/node_modules/@oxygen/workflows/dist/graph/types.js +15 -1
  108. package/node_modules/@oxygen/workflows/dist/index.d.ts +45 -0
  109. package/node_modules/@oxygen/workflows/dist/index.js +152 -2
  110. package/node_modules/@oxygen/workflows/dist/usage-estimate.d.ts +10 -1
  111. package/node_modules/@oxygen/workflows/dist/usage-estimate.js +33 -29
  112. package/package.json +1 -1
  113. package/node_modules/@oxygen/shared/dist/email-warmup-readiness.d.ts +0 -64
  114. package/node_modules/@oxygen/shared/dist/email-warmup-readiness.js +0 -90
@@ -25,14 +25,22 @@
25
25
  * live in docs/free-tier-capability-matrix.md.
26
26
  *
27
27
  * WHY GATES ARE CHECKED BEFORE BALANCE. A connected sender is also a FIXED
28
- * monthly credit commitment (1,000 per mailbox, 10,000 per LinkedIn account,
29
- * 10,000 per WhatsApp number), and top-ups stay purchasable on free — so a free
30
- * workspace could buy 10,000 credits for $12.50 and fund a LinkedIn seat that
28
+ * monthly credit commitment (100 per mailbox, 1,000 per LinkedIn account,
29
+ * 1,000 per WhatsApp number), and top-ups stay purchasable on free — so a free
30
+ * workspace could buy 1,000 credits for $12.50 and fund a LinkedIn seat that
31
31
  * Starter prices at $99. Enforcing by balance would therefore price sending at
32
32
  * an eighth of Starter. The capability gate must run BEFORE any balance or
33
33
  * commitment check so the customer is told to upgrade, not to top up.
34
+ *
35
+ * THE 2026-09 REPRICING ENDS THAT ARGUMENT (decision 2.7). Connected accounts
36
+ * are repriced as credit reservations at their real price, so once they are
37
+ * billed that way (the credit gate, `OXYGEN_CREDIT_GATE_ENABLED`) credits are the
38
+ * only gate and the sending walls retire: `CREDIT_GATE_RETIRED_CAPABILITIES`.
39
+ * Until the gate is in force everything above still holds.
34
40
  */
35
- import type { PlanTier } from "./billing.js";
41
+ import type { PlanTier, PricingPlanDefinition } from "./billing.js";
42
+ import { CREDIT_GATE_RETIRED_CAPABILITIES, isCapabilityRetiredByCreditGate } from "./credit-gate.js";
43
+ import { type RepricingOptions } from "./repricing.js";
36
44
  export declare const PLAN_GATED_CAPABILITIES: readonly ["sender_connect", "sequence_dispatch", "publishing_connect", "publishing_deliver", "managed_email_infrastructure", "byok_provider_keys"];
37
45
  export type PlanGatedCapability = (typeof PLAN_GATED_CAPABILITIES)[number];
38
46
  /**
@@ -56,14 +64,76 @@ export type PlanGatedCapabilityCopy = {
56
64
  export declare const PLAN_GATED_CAPABILITY_COPY: Record<PlanGatedCapability, PlanGatedCapabilityCopy>;
57
65
  export declare function isPlanGatedCapability(value: unknown): value is PlanGatedCapability;
58
66
  /**
59
- * The whole boundary, in one expression.
67
+ * The walls credits replace once the credit gate is in force (repricing
68
+ * 2026-09, decision 2.7, slice S22).
69
+ *
70
+ * "Credits are the only gate": a free workspace may connect accounts, send,
71
+ * publish and buy managed infrastructure if it holds the credits. Each of these
72
+ * is paid for by a monthly credit reservation or a credit purchase, so the plan
73
+ * wall has nothing left to protect — but only once those reservations are
74
+ * actually BILLED, which is exactly what the credit gate asserts at boot
75
+ * (`assertCreditGateArmed`). Until then every one of them stays walled exactly
76
+ * as before.
77
+ *
78
+ * Two capabilities stay walled under the gate:
79
+ * - `byok_provider_keys`: bringing your own keys needs a plan that includes it
80
+ * ($99 or above from the repricing's effective date).
81
+ * - `publishing_connect`: the only publishing connects that still reach it are
82
+ * Instagram, TikTok, YouTube and Facebook, which have no reservation price yet
83
+ * (P-18). Connecting them without one would make them free and unmetered, so
84
+ * they stay on the plan until that price is ratified.
85
+ */
86
+ export { CREDIT_GATE_RETIRED_CAPABILITIES, isCapabilityRetiredByCreditGate };
87
+ /**
88
+ * The whole boundary for one plan, in one expression.
60
89
  *
61
- * Note this asks about the TIER, not about entitlement. A churned workspace and
90
+ * Note this asks about the PLAN, not about entitlement. A churned workspace and
62
91
  * a brand-new one both resolve to `free` and both get the same answer here —
63
92
  * one entitlement, one capability set, differing only in grants and upgrade
64
93
  * copy (founder, 2026-08-17).
94
+ *
95
+ * BYOK reads the plan's own `byokEnabled`, never the tier: every Oxygen size
96
+ * shares the tier `oxygen`, and only $99 and above include BYOK once the
97
+ * repricing is in force. Everything else is the founder's one line, free versus
98
+ * paid. `creditGateInForce` retires the walls credits pay for (above).
99
+ */
100
+ export declare function planAllowsCapability(plan: Pick<PricingPlanDefinition, "tier" | "byokEnabled">, capability: PlanGatedCapability, options?: {
101
+ creditGateInForce?: boolean;
102
+ }): boolean;
103
+ /**
104
+ * The smallest purchasable plan that includes BYOK right now: `oxygen_49` until
105
+ * the repricing's effective date, `oxygen_99` from it (decision 2.7).
65
106
  */
66
- export declare function planTierAllowsCapability(tier: PlanTier, _capability: PlanGatedCapability): boolean;
107
+ export declare function byokMinimumPlanKey(options?: RepricingOptions): "oxygen_49" | "oxygen_99";
108
+ /** How a refusal names `byokMinimumPlanKey` in a sentence: "a paid plan" or "the $99 plan or above". */
109
+ export declare function byokMinimumPlanPhrase(options?: RepricingOptions): string;
110
+ /**
111
+ * P-20 (PROPOSED default): a $49 workspace keeps using the keys it connected
112
+ * before the repricing's effective date until its plan changes; new keys need
113
+ * $99. True only for a connection made before an instant that has passed, on
114
+ * the plan key `oxygen_49` — any other plan either includes BYOK or never did.
115
+ *
116
+ * "Until the plan changes" is read from the current plan key: a move off $49
117
+ * ends the grandfathering. No plan-change history is stored, so a workspace that
118
+ * leaves $49 and comes back after the date is not told apart from one that
119
+ * stayed; only keys connected before the date ever qualify.
120
+ */
121
+ export declare function byokConnectionGrandfathered(input: {
122
+ planKey: string | null | undefined;
123
+ connectionCreatedAt: Date | string | null | undefined;
124
+ }, options?: RepricingOptions): boolean;
125
+ /**
126
+ * The access requirements of a tool that runs ONLY on the customer's own key.
127
+ *
128
+ * One definition for the provider catalog, the Composio catalog and both access
129
+ * resolvers. The tier list is display metadata: every paid tier has at least one
130
+ * plan with BYOK, and whether THIS plan has it is `plan.byokEnabled`, which the
131
+ * access resolver checks separately.
132
+ */
133
+ export declare function byokOnlyAccessRequirements(): {
134
+ byok_required: true;
135
+ required_plan_tiers: PlanTier[];
136
+ };
67
137
  export declare const FREE_TIER_ENTITLEMENT_ENABLED_ENV_VAR = "OXYGEN_FREE_TIER_ENTITLEMENT_ENABLED";
68
138
  /**
69
139
  * Fail-closed rollout switch for capability-scoped entitlement.
@@ -25,13 +25,21 @@
25
25
  * live in docs/free-tier-capability-matrix.md.
26
26
  *
27
27
  * WHY GATES ARE CHECKED BEFORE BALANCE. A connected sender is also a FIXED
28
- * monthly credit commitment (1,000 per mailbox, 10,000 per LinkedIn account,
29
- * 10,000 per WhatsApp number), and top-ups stay purchasable on free — so a free
30
- * workspace could buy 10,000 credits for $12.50 and fund a LinkedIn seat that
28
+ * monthly credit commitment (100 per mailbox, 1,000 per LinkedIn account,
29
+ * 1,000 per WhatsApp number), and top-ups stay purchasable on free — so a free
30
+ * workspace could buy 1,000 credits for $12.50 and fund a LinkedIn seat that
31
31
  * Starter prices at $99. Enforcing by balance would therefore price sending at
32
32
  * an eighth of Starter. The capability gate must run BEFORE any balance or
33
33
  * commitment check so the customer is told to upgrade, not to top up.
34
+ *
35
+ * THE 2026-09 REPRICING ENDS THAT ARGUMENT (decision 2.7). Connected accounts
36
+ * are repriced as credit reservations at their real price, so once they are
37
+ * billed that way (the credit gate, `OXYGEN_CREDIT_GATE_ENABLED`) credits are the
38
+ * only gate and the sending walls retire: `CREDIT_GATE_RETIRED_CAPABILITIES`.
39
+ * Until the gate is in force everything above still holds.
34
40
  */
41
+ import { CREDIT_GATE_RETIRED_CAPABILITIES, isCapabilityRetiredByCreditGate } from "./credit-gate.js";
42
+ import { OXYGEN_49_BYOK_REPRICING, readRepricingSwitch, repricedValue, } from "./repricing.js";
35
43
  export const PLAN_GATED_CAPABILITIES = [
36
44
  "sender_connect",
37
45
  "sequence_dispatch",
@@ -94,15 +102,87 @@ export function isPlanGatedCapability(value) {
94
102
  && PLAN_GATED_CAPABILITIES.includes(value));
95
103
  }
96
104
  /**
97
- * The whole boundary, in one expression.
105
+ * The walls credits replace once the credit gate is in force (repricing
106
+ * 2026-09, decision 2.7, slice S22).
107
+ *
108
+ * "Credits are the only gate": a free workspace may connect accounts, send,
109
+ * publish and buy managed infrastructure if it holds the credits. Each of these
110
+ * is paid for by a monthly credit reservation or a credit purchase, so the plan
111
+ * wall has nothing left to protect — but only once those reservations are
112
+ * actually BILLED, which is exactly what the credit gate asserts at boot
113
+ * (`assertCreditGateArmed`). Until then every one of them stays walled exactly
114
+ * as before.
115
+ *
116
+ * Two capabilities stay walled under the gate:
117
+ * - `byok_provider_keys`: bringing your own keys needs a plan that includes it
118
+ * ($99 or above from the repricing's effective date).
119
+ * - `publishing_connect`: the only publishing connects that still reach it are
120
+ * Instagram, TikTok, YouTube and Facebook, which have no reservation price yet
121
+ * (P-18). Connecting them without one would make them free and unmetered, so
122
+ * they stay on the plan until that price is ratified.
123
+ */
124
+ export { CREDIT_GATE_RETIRED_CAPABILITIES, isCapabilityRetiredByCreditGate };
125
+ /**
126
+ * The whole boundary for one plan, in one expression.
98
127
  *
99
- * Note this asks about the TIER, not about entitlement. A churned workspace and
128
+ * Note this asks about the PLAN, not about entitlement. A churned workspace and
100
129
  * a brand-new one both resolve to `free` and both get the same answer here —
101
130
  * one entitlement, one capability set, differing only in grants and upgrade
102
131
  * copy (founder, 2026-08-17).
132
+ *
133
+ * BYOK reads the plan's own `byokEnabled`, never the tier: every Oxygen size
134
+ * shares the tier `oxygen`, and only $99 and above include BYOK once the
135
+ * repricing is in force. Everything else is the founder's one line, free versus
136
+ * paid. `creditGateInForce` retires the walls credits pay for (above).
137
+ */
138
+ export function planAllowsCapability(plan, capability, options = {}) {
139
+ if (options.creditGateInForce && isCapabilityRetiredByCreditGate(capability))
140
+ return true;
141
+ if (capability === "byok_provider_keys")
142
+ return plan.byokEnabled;
143
+ return plan.tier !== "free";
144
+ }
145
+ /**
146
+ * The smallest purchasable plan that includes BYOK right now: `oxygen_49` until
147
+ * the repricing's effective date, `oxygen_99` from it (decision 2.7).
148
+ */
149
+ export function byokMinimumPlanKey(options = {}) {
150
+ return repricedValue(OXYGEN_49_BYOK_REPRICING, options) ? "oxygen_49" : "oxygen_99";
151
+ }
152
+ /** How a refusal names `byokMinimumPlanKey` in a sentence: "a paid plan" or "the $99 plan or above". */
153
+ export function byokMinimumPlanPhrase(options = {}) {
154
+ return byokMinimumPlanKey(options) === "oxygen_99" ? "the $99 plan or above" : "a paid plan";
155
+ }
156
+ /**
157
+ * P-20 (PROPOSED default): a $49 workspace keeps using the keys it connected
158
+ * before the repricing's effective date until its plan changes; new keys need
159
+ * $99. True only for a connection made before an instant that has passed, on
160
+ * the plan key `oxygen_49` — any other plan either includes BYOK or never did.
161
+ *
162
+ * "Until the plan changes" is read from the current plan key: a move off $49
163
+ * ends the grandfathering. No plan-change history is stored, so a workspace that
164
+ * leaves $49 and comes back after the date is not told apart from one that
165
+ * stayed; only keys connected before the date ever qualify.
166
+ */
167
+ export function byokConnectionGrandfathered(input, options = {}) {
168
+ if (input.planKey !== "oxygen_49" || !input.connectionCreatedAt)
169
+ return false;
170
+ const state = readRepricingSwitch(options);
171
+ if (state.status !== "in_force")
172
+ return false;
173
+ const createdAt = new Date(input.connectionCreatedAt).getTime();
174
+ return Number.isFinite(createdAt) && createdAt < state.effectiveAt.getTime();
175
+ }
176
+ /**
177
+ * The access requirements of a tool that runs ONLY on the customer's own key.
178
+ *
179
+ * One definition for the provider catalog, the Composio catalog and both access
180
+ * resolvers. The tier list is display metadata: every paid tier has at least one
181
+ * plan with BYOK, and whether THIS plan has it is `plan.byokEnabled`, which the
182
+ * access resolver checks separately.
103
183
  */
104
- export function planTierAllowsCapability(tier, _capability) {
105
- return tier !== "free";
184
+ export function byokOnlyAccessRequirements() {
185
+ return { byok_required: true, required_plan_tiers: [...PLAN_GATE_QUALIFYING_TIERS] };
106
186
  }
107
187
  export const FREE_TIER_ENTITLEMENT_ENABLED_ENV_VAR = "OXYGEN_FREE_TIER_ENTITLEMENT_ENABLED";
108
188
  /**
@@ -0,0 +1,219 @@
1
+ /**
2
+ * How `GET /api/cli/limits` reads to a person: the seven plan sizes side by
3
+ * side, the workspace's own spend defaults, and what the 2026-09 repricing
4
+ * schedule moves (decision F.2: the value in force and the value pending for
5
+ * it). The MCP `oxygen.plan-limits` widget and the web Settings → Plan limits
6
+ * tab both render from here, so the two cannot disagree on a label or a
7
+ * pending value. Pure and browser-safe: it formats an envelope it is handed and
8
+ * reads nothing else.
9
+ */
10
+ /** What a band's storage moves to (`plan_bands[].storage.target`, decision F.2). */
11
+ export type PlanLimitsStorageTarget = {
12
+ table_row_limit?: number;
13
+ workspace_row_limit?: number;
14
+ workspace_database_limit_bytes?: number;
15
+ import_max_rows_per_file?: number;
16
+ };
17
+ export type PlanLimitsBandRow = {
18
+ band?: string;
19
+ label?: string;
20
+ limits_tier?: string;
21
+ current?: boolean;
22
+ monthly_price_usd?: number | null;
23
+ monthly_credits?: number | null;
24
+ volume_bonus_percent?: number | null;
25
+ usd_per_100_credits?: number | null;
26
+ api?: {
27
+ org_requests_per_minute?: number;
28
+ key_requests_per_minute?: number;
29
+ tenant_read_requests_per_key_per_minute?: number;
30
+ tenant_write_requests_per_key_per_minute?: number;
31
+ live_action_requests_per_key_per_minute?: number;
32
+ };
33
+ storage?: {
34
+ table_row_limit?: number;
35
+ workspace_row_limit?: number;
36
+ workspace_database_limit_bytes?: number;
37
+ import_max_rows_per_file?: number;
38
+ import_max_file_bytes?: number;
39
+ status?: string;
40
+ effective_at?: string | null;
41
+ target?: PlanLimitsStorageTarget | null;
42
+ };
43
+ spend?: {
44
+ trigger_run_credit_ceiling?: number | null;
45
+ auto_run_batch_credit_ceiling?: number | null;
46
+ agent_run_max_total_credits?: number;
47
+ copilot_approval_free_per_call_credits?: number;
48
+ copilot_approval_free_per_session_credits?: number;
49
+ org_daily_guard_block_credits?: number | null;
50
+ byok_column_run_max_rows?: number | null;
51
+ };
52
+ tables?: {
53
+ max_rows_per_write_request?: number;
54
+ max_columns_per_run?: number;
55
+ };
56
+ signals?: {
57
+ max_events?: number;
58
+ max_window_days?: number;
59
+ };
60
+ webhooks?: {
61
+ ingress_requests_per_target_per_minute?: number;
62
+ };
63
+ workflows?: {
64
+ cron_min_interval_minutes?: number;
65
+ };
66
+ };
67
+ export type PlanLimitsWorkflowLimits = {
68
+ cron_min_interval_minutes?: number;
69
+ code_node_max_timeout_seconds?: number;
70
+ run_attempt_timeout_minutes?: number;
71
+ };
72
+ export type PlanLimitsStorageCapacity = {
73
+ platform_guard?: {
74
+ table_row_limit?: number;
75
+ workspace_row_limit?: number;
76
+ workspace_database_limit_bytes?: number;
77
+ };
78
+ usage?: {
79
+ workspace_rows?: number | null;
80
+ largest_table_rows?: number | null;
81
+ largest_table?: {
82
+ id?: string;
83
+ name?: string;
84
+ } | null;
85
+ workspace_database_bytes?: number;
86
+ } | null;
87
+ };
88
+ export type PlanLimitsScheduledChange = {
89
+ key?: string;
90
+ kind?: string;
91
+ unit?: string;
92
+ description?: string;
93
+ value_before?: unknown;
94
+ value_after?: unknown;
95
+ };
96
+ export type PlanLimitsPricingSchedule = {
97
+ effective_at?: string;
98
+ status?: string;
99
+ changes?: PlanLimitsScheduledChange[];
100
+ };
101
+ type ChannelLimit = {
102
+ default_per_day?: number;
103
+ max_per_day?: number | null;
104
+ };
105
+ export type PlanLimitsSendingLimits = {
106
+ email_per_mailbox?: ChannelLimit;
107
+ whatsapp_per_number?: ChannelLimit;
108
+ voice_per_number?: ChannelLimit;
109
+ linkedin_per_account?: {
110
+ invites_per_day?: number;
111
+ invites_per_day_max?: number;
112
+ messages_per_day?: number;
113
+ };
114
+ };
115
+ export type PlanLimitsSpendDefaults = {
116
+ trigger_run_credit_ceiling?: number | null;
117
+ auto_run_batch_credit_ceiling?: number | null;
118
+ agent_run_max_total_credits?: number;
119
+ agent_run_max_inference_credits?: number;
120
+ /** The most a run approved above the default may spend (decision F.4). */
121
+ agent_run_approved_max_credits?: number;
122
+ copilot_approval_free_per_call_credits?: number;
123
+ copilot_approval_free_per_session_credits?: number;
124
+ copilot_attended_turn_backstop_credits?: number;
125
+ org_daily_spend_guard?: {
126
+ applies?: boolean;
127
+ source?: string;
128
+ warn_credits?: number | null;
129
+ block_credits?: number | null;
130
+ spent_today?: number | null;
131
+ };
132
+ applies_to?: Record<string, string>;
133
+ };
134
+ /** The slice of the `limits show` envelope this module reads. */
135
+ export type PlanLimitsEnvelope = {
136
+ plan_band?: string;
137
+ plan_band_label?: string;
138
+ limits_tier?: string;
139
+ plan_bands?: PlanLimitsBandRow[];
140
+ sending_limits?: PlanLimitsSendingLimits;
141
+ workflow_limits?: PlanLimitsWorkflowLimits;
142
+ shared_billing?: boolean;
143
+ storage_capacity?: PlanLimitsStorageCapacity;
144
+ spend_safety_defaults?: PlanLimitsSpendDefaults;
145
+ pricing_schedule?: PlanLimitsPricingSchedule;
146
+ deepLink?: string;
147
+ web_url?: string;
148
+ billing_url?: string;
149
+ };
150
+ export declare function formatLimitCount(value: number | null | undefined): string;
151
+ export declare function formatLimitCredits(value: number | null | undefined): string;
152
+ export declare function formatLimitBytes(value: number | null | undefined): string;
153
+ /**
154
+ * `storage.<band>.<field>` / `workflows.…` / `spend.…` / `agents.…` → the
155
+ * value it takes once the scheduled change is in force. Empty unless the
156
+ * schedule is still ahead (`status: "scheduled"`).
157
+ */
158
+ export declare function scheduledLimitChanges(schedule: PlanLimitsPricingSchedule | undefined): Map<string, number>;
159
+ export type PlanLimitsLadder = {
160
+ bands: Array<{
161
+ band: string;
162
+ label: string;
163
+ current: boolean;
164
+ }>;
165
+ rows: Array<{
166
+ label: string;
167
+ cells: string[];
168
+ }>;
169
+ /** What `→` and `†` mean, when a cell uses them. */
170
+ notes: string[];
171
+ };
172
+ /** Every plan size's limits side by side, with the pending value after `→`. */
173
+ export declare function planLimitsLadder(payload: PlanLimitsEnvelope): PlanLimitsLadder;
174
+ /**
175
+ * The workspace's own usage against the limits it enforces, so "how close am
176
+ * I?" sits beside "what would a bigger plan give me?". The largest Table is
177
+ * named, so a full one is identifiable (decision F.2).
178
+ */
179
+ export declare function planLimitsStorageUsageLine(storage: PlanLimitsStorageCapacity | undefined): string | null;
180
+ /** Sending limits are the same on every plan: one row per channel. */
181
+ export declare function planLimitsSendingRows(sending: PlanLimitsSendingLimits | undefined): Array<{
182
+ label: string;
183
+ defaultPerDay: string;
184
+ maximumPerDay: string;
185
+ }>;
186
+ /**
187
+ * The Code step and run attempt limits are the same on every plan; the fastest
188
+ * schedule, which differs, is a row of the ladder.
189
+ */
190
+ export declare function planLimitsWorkflowNote(workflows: PlanLimitsWorkflowLimits | undefined): string | null;
191
+ export type PlanLimitsSpendDefaultRow = {
192
+ label: string;
193
+ value: string;
194
+ /** The value from the scheduled date, when one is set and it differs. */
195
+ next: string | null;
196
+ /** What the default bounds, from `spend_safety_defaults.applies_to`. */
197
+ scope: string | null;
198
+ };
199
+ /**
200
+ * The workspace's own spend defaults, each with what it bounds and the value
201
+ * it takes on the scheduled date (L5.1–L5.4). Read from the plan size the
202
+ * workspace is on (`plan_band`, `limits_tier`), so the pending value is the
203
+ * one this workspace will get.
204
+ */
205
+ export declare function planLimitsSpendDefaults(payload: PlanLimitsEnvelope): PlanLimitsSpendDefaultRow[];
206
+ export type PlanLimitsScheduleRow = {
207
+ key: string;
208
+ description: string;
209
+ before: string;
210
+ after: string;
211
+ };
212
+ export type PlanLimitsSchedule = {
213
+ effectiveAt: string;
214
+ inForce: boolean;
215
+ rows: PlanLimitsScheduleRow[];
216
+ };
217
+ /** Every price and limit the dated repricing moves, before and after. */
218
+ export declare function planLimitsSchedule(schedule: PlanLimitsPricingSchedule | undefined): PlanLimitsSchedule | null;
219
+ export {};