@oxygen-agent/cli 1.354.0 → 1.377.3

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.
@@ -28,6 +28,12 @@ export type PricingPlanMetadata = Record<string, unknown> | null | undefined;
28
28
  export declare const CONTACT_SALES_URL = "https://cal.com/tim-scheuer-mxbib9/45";
29
29
  export declare const CREDITS_PER_USD = 1000;
30
30
  export declare const TOPUP_USD_CENTS_PER_1K_CREDITS = 125;
31
+ export declare const CREDIT_TOPUP_MIN_CREDITS = 8000;
32
+ export declare const CREDIT_TOPUP_MAX_CREDITS = 200000;
33
+ export declare const CREDIT_TOPUP_STEP_CREDITS = 1000;
34
+ export declare const CREDIT_TOPUP_DEFAULT_CREDITS = 20000;
35
+ export declare function isValidCreditTopupCredits(credits: number): boolean;
36
+ export declare function creditTopupUsdCents(credits: number): number | null;
31
37
  export declare const AUTOMATION_ACTION_CREDITS = 0.01;
32
38
  export declare const CREDIT_TOPUP_PACKS: readonly [{
33
39
  readonly id: "10";
@@ -51,13 +57,15 @@ export type CreditTopupPackId = CreditTopupPack["id"];
51
57
  export declare function resolveCreditTopupPack(id: string | null | undefined): CreditTopupPack | null;
52
58
  export declare const TRIAL_PERIOD_DAYS = 7;
53
59
  export declare const TRIAL_CREDIT_GRANT = 20000;
60
+ export declare const WALKTHROUGH_COMPLETION_BONUS_CREDITS = 1000;
61
+ export declare const WALKTHROUGH_SCRAPE_MAX_CREDITS = 2000;
54
62
  export declare const BASE_PRICING_PLANS: {
55
63
  readonly free: {
56
64
  readonly tier: "free";
57
65
  readonly name: "Free";
58
66
  readonly monthlyPriceCents: 0;
59
67
  readonly monthlyCredits: 10000;
60
- readonly weeklyCreditsLimit: 10000;
68
+ readonly weeklyCreditsLimit: null;
61
69
  readonly rolloverCap: 10000;
62
70
  readonly monthlyAutomationActions: null;
63
71
  readonly automationOverageCentsPerMillion: null;
@@ -65,14 +73,14 @@ export declare const BASE_PRICING_PLANS: {
65
73
  readonly byokEnabled: false;
66
74
  readonly description: "Get $10 in credits on us every month — try OXYGEN with managed email, phone enrichment, and AI credits.";
67
75
  readonly ctaLabel: "Start free";
68
- readonly features: readonly ["$10 in credits every month", "Automation actions at 0.01 credits each", "All integrations", "Workflows", "No card required"];
76
+ readonly features: readonly ["$10 in credits every month", "All integrations", "Workflows", "No card required"];
69
77
  };
70
78
  readonly starter: {
71
79
  readonly tier: "starter";
72
80
  readonly name: "Starter";
73
81
  readonly monthlyPriceCents: 9900;
74
82
  readonly monthlyCredits: 99000;
75
- readonly weeklyCreditsLimit: 40000;
83
+ readonly weeklyCreditsLimit: null;
76
84
  readonly rolloverCap: 99000;
77
85
  readonly monthlyAutomationActions: null;
78
86
  readonly automationOverageCentsPerMillion: null;
@@ -80,14 +88,14 @@ export declare const BASE_PRICING_PLANS: {
80
88
  readonly byokEnabled: true;
81
89
  readonly description: "For founders running focused managed enrichment and AI columns.";
82
90
  readonly ctaLabel: "Choose Starter";
83
- readonly features: readonly ["99,000 credits every month", "All integrations", "Workflows — automation actions at 0.01 credits each", "Bring your own keys", "Standard support"];
91
+ readonly features: readonly ["99,000 credits every month", "All integrations", "Workflows", "Bring your own keys", "Standard support"];
84
92
  };
85
93
  readonly pro: {
86
94
  readonly tier: "pro";
87
95
  readonly name: "Pro";
88
96
  readonly monthlyPriceCents: 24900;
89
97
  readonly monthlyCredits: 249000;
90
- readonly weeklyCreditsLimit: 100000;
98
+ readonly weeklyCreditsLimit: null;
91
99
  readonly rolloverCap: 249000;
92
100
  readonly monthlyAutomationActions: null;
93
101
  readonly automationOverageCentsPerMillion: null;
@@ -97,14 +105,14 @@ export declare const BASE_PRICING_PLANS: {
97
105
  readonly badge: "Most popular";
98
106
  readonly highlighted: true;
99
107
  readonly ctaLabel: "Choose Pro";
100
- readonly features: readonly ["249,000 credits every month", "All integrations", "Workflows — automation actions at 0.01 credits each", "Bring your own keys", "Standard support"];
108
+ readonly features: readonly ["249,000 credits every month", "All integrations", "Workflows", "Bring your own keys", "Standard support"];
101
109
  };
102
110
  readonly team: {
103
111
  readonly tier: "team";
104
112
  readonly name: "Team";
105
113
  readonly monthlyPriceCents: 74900;
106
114
  readonly monthlyCredits: 749000;
107
- readonly weeklyCreditsLimit: 300000;
115
+ readonly weeklyCreditsLimit: null;
108
116
  readonly rolloverCap: 749000;
109
117
  readonly monthlyAutomationActions: null;
110
118
  readonly automationOverageCentsPerMillion: null;
@@ -112,14 +120,14 @@ export declare const BASE_PRICING_PLANS: {
112
120
  readonly byokEnabled: true;
113
121
  readonly description: "For small GTM teams and agencies running shared workflows with their own AI keys.";
114
122
  readonly ctaLabel: "Choose Team";
115
- readonly features: readonly ["749,000 credits every month", "All integrations", "Workflows — automation actions at 0.01 credits each", "Bring your own keys", "Premium support"];
123
+ readonly features: readonly ["749,000 credits every month", "All integrations", "Workflows", "Bring your own keys", "Premium support"];
116
124
  };
117
125
  readonly scale: {
118
126
  readonly tier: "scale";
119
127
  readonly name: "Scale";
120
128
  readonly monthlyPriceCents: null;
121
129
  readonly monthlyCredits: 10000000;
122
- readonly weeklyCreditsLimit: 10000000;
130
+ readonly weeklyCreditsLimit: null;
123
131
  readonly rolloverCap: 10000000;
124
132
  readonly monthlyAutomationActions: null;
125
133
  readonly automationOverageCentsPerMillion: null;
@@ -128,7 +136,7 @@ export declare const BASE_PRICING_PLANS: {
128
136
  readonly description: "For high-volume GTM teams that need custom limits and rollout support.";
129
137
  readonly ctaLabel: "Contact sales";
130
138
  readonly contactHref: "https://cal.com/tim-scheuer-mxbib9/45";
131
- readonly features: readonly ["10,000,000+ managed credits / month", "Automation actions at 0.01 credits each", "Phone number enrichment on managed credits", "Custom provider routing and BYOK policies", "Dedicated onboarding"];
139
+ readonly features: readonly ["10,000,000+ managed credits / month", "Workflows", "Phone number enrichment on managed credits", "Custom provider routing and BYOK policies", "Dedicated onboarding"];
132
140
  };
133
141
  readonly enterprise: {
134
142
  readonly tier: "enterprise";
@@ -152,6 +160,22 @@ export declare const SELF_SERVE_PLAN_TIERS: readonly SelfServePlanTier[];
152
160
  export declare const CONTACT_SALES_PLAN_TIERS: readonly ContactSalesPlanTier[];
153
161
  export declare const ACTIVE_SUBSCRIPTION_STATUSES: readonly ["active", "trialing", "past_due"];
154
162
  export type ActiveSubscriptionStatus = (typeof ACTIVE_SUBSCRIPTION_STATUSES)[number];
163
+ export declare const BILLING_VISIBLE_SUBSCRIPTION_STATUSES: readonly ["active", "trialing", "past_due", "unpaid", "paused", "incomplete"];
164
+ export type BillingVisibleSubscriptionStatus = (typeof BILLING_VISIBLE_SUBSCRIPTION_STATUSES)[number];
165
+ export declare const PAST_DUE_GRACE_DAYS = 7;
166
+ export type SubscriptionEntitlementReason = "active" | "trialing" | "past_due_grace" | "past_due_grace_expired" | "missing_past_due_period_start" | "trial_expired" | "missing_trial_end" | "unpaid" | "paused" | "incomplete" | "canceled" | "incomplete_expired" | "missing_subscription";
167
+ export type SubscriptionEntitlement = {
168
+ entitled: boolean;
169
+ reason: SubscriptionEntitlementReason;
170
+ graceEndsAt: Date | null;
171
+ };
172
+ export declare function resolveSubscriptionEntitlement(input: {
173
+ status: string | null | undefined;
174
+ currentPeriodStart?: Date | null;
175
+ currentPeriodEnd?: Date | null;
176
+ trialEnd?: Date | null;
177
+ now?: Date;
178
+ }): SubscriptionEntitlement;
155
179
  export type ResolvedPricingPlan = PricingPlanDefinition;
156
180
  export declare function resolveBasePricingPlan(tier: string | null | undefined): ResolvedPricingPlan | null;
157
181
  export declare function applyPricingPlanMetadataOverrides(// skipcq: JS-R1005
@@ -9,6 +9,23 @@ export const CONTACT_SALES_URL = "https://cal.com/tim-scheuer-mxbib9/45";
9
9
  // credits bought on demand.
10
10
  export const CREDITS_PER_USD = 1_000;
11
11
  export const TOPUP_USD_CENTS_PER_1K_CREDITS = 125;
12
+ // Keep on-demand purchases inside the same $10-$250 spend envelope as the
13
+ // original fixed packs, but let customers choose any 1,000-credit increment.
14
+ export const CREDIT_TOPUP_MIN_CREDITS = 8_000;
15
+ export const CREDIT_TOPUP_MAX_CREDITS = 200_000;
16
+ export const CREDIT_TOPUP_STEP_CREDITS = 1_000;
17
+ export const CREDIT_TOPUP_DEFAULT_CREDITS = 20_000;
18
+ export function isValidCreditTopupCredits(credits) {
19
+ return Number.isInteger(credits)
20
+ && credits >= CREDIT_TOPUP_MIN_CREDITS
21
+ && credits <= CREDIT_TOPUP_MAX_CREDITS
22
+ && credits % CREDIT_TOPUP_STEP_CREDITS === 0;
23
+ }
24
+ export function creditTopupUsdCents(credits) {
25
+ if (!isValidCreditTopupCredits(credits))
26
+ return null;
27
+ return (credits / 1_000) * TOPUP_USD_CENTS_PER_1K_CREDITS;
28
+ }
12
29
  // Workflow/automation actions (steps, tool calls, row writes, retries) draw
13
30
  // from the same credit pool at a flat capacity-guard rate — the old separate
14
31
  // monthly action allowance + USD overage meter economy is retired (2026-07-14).
@@ -30,13 +47,20 @@ export function resolveCreditTopupPack(id) {
30
47
  // credit exhaustion or when the trial clock elapses, whichever comes first.
31
48
  export const TRIAL_PERIOD_DAYS = 7;
32
49
  export const TRIAL_CREDIT_GRANT = 20_000;
50
+ // Onboarding walkthrough (2026-07-21): completing the in-product walkthrough
51
+ // grants a one-off bonus (idempotent per billing owner), and the walkthrough's
52
+ // "start scraping engagers" step may spend at most this many credits on the
53
+ // managed cookieless scraper (founder-approved budget; the rest of the kickoff
54
+ // is free connected-account reads).
55
+ export const WALKTHROUGH_COMPLETION_BONUS_CREDITS = 1_000;
56
+ export const WALKTHROUGH_SCRAPE_MAX_CREDITS = 2_000;
33
57
  export const BASE_PRICING_PLANS = {
34
58
  free: {
35
59
  tier: "free",
36
60
  name: "Free",
37
61
  monthlyPriceCents: 0,
38
62
  monthlyCredits: 10_000,
39
- weeklyCreditsLimit: 10_000,
63
+ weeklyCreditsLimit: null,
40
64
  rolloverCap: 10_000,
41
65
  monthlyAutomationActions: null,
42
66
  automationOverageCentsPerMillion: null,
@@ -46,7 +70,6 @@ export const BASE_PRICING_PLANS = {
46
70
  ctaLabel: "Start free",
47
71
  features: [
48
72
  "$10 in credits every month",
49
- "Automation actions at 0.01 credits each",
50
73
  "All integrations",
51
74
  "Workflows",
52
75
  "No card required",
@@ -57,7 +80,7 @@ export const BASE_PRICING_PLANS = {
57
80
  name: "Starter",
58
81
  monthlyPriceCents: 9_900,
59
82
  monthlyCredits: 99_000,
60
- weeklyCreditsLimit: 40_000,
83
+ weeklyCreditsLimit: null,
61
84
  rolloverCap: 99_000,
62
85
  monthlyAutomationActions: null,
63
86
  automationOverageCentsPerMillion: null,
@@ -68,7 +91,7 @@ export const BASE_PRICING_PLANS = {
68
91
  features: [
69
92
  "99,000 credits every month",
70
93
  "All integrations",
71
- "Workflows — automation actions at 0.01 credits each",
94
+ "Workflows",
72
95
  "Bring your own keys",
73
96
  "Standard support",
74
97
  ],
@@ -78,7 +101,7 @@ export const BASE_PRICING_PLANS = {
78
101
  name: "Pro",
79
102
  monthlyPriceCents: 24_900,
80
103
  monthlyCredits: 249_000,
81
- weeklyCreditsLimit: 100_000,
104
+ weeklyCreditsLimit: null,
82
105
  rolloverCap: 249_000,
83
106
  monthlyAutomationActions: null,
84
107
  automationOverageCentsPerMillion: null,
@@ -91,7 +114,7 @@ export const BASE_PRICING_PLANS = {
91
114
  features: [
92
115
  "249,000 credits every month",
93
116
  "All integrations",
94
- "Workflows — automation actions at 0.01 credits each",
117
+ "Workflows",
95
118
  "Bring your own keys",
96
119
  "Standard support",
97
120
  ],
@@ -101,7 +124,7 @@ export const BASE_PRICING_PLANS = {
101
124
  name: "Team",
102
125
  monthlyPriceCents: 74_900,
103
126
  monthlyCredits: 749_000,
104
- weeklyCreditsLimit: 300_000,
127
+ weeklyCreditsLimit: null,
105
128
  rolloverCap: 749_000,
106
129
  monthlyAutomationActions: null,
107
130
  automationOverageCentsPerMillion: null,
@@ -112,7 +135,7 @@ export const BASE_PRICING_PLANS = {
112
135
  features: [
113
136
  "749,000 credits every month",
114
137
  "All integrations",
115
- "Workflows — automation actions at 0.01 credits each",
138
+ "Workflows",
116
139
  "Bring your own keys",
117
140
  "Premium support",
118
141
  ],
@@ -122,7 +145,7 @@ export const BASE_PRICING_PLANS = {
122
145
  name: "Scale",
123
146
  monthlyPriceCents: null,
124
147
  monthlyCredits: 10_000_000,
125
- weeklyCreditsLimit: 10_000_000,
148
+ weeklyCreditsLimit: null,
126
149
  rolloverCap: 10_000_000,
127
150
  monthlyAutomationActions: null,
128
151
  automationOverageCentsPerMillion: null,
@@ -133,7 +156,7 @@ export const BASE_PRICING_PLANS = {
133
156
  contactHref: CONTACT_SALES_URL,
134
157
  features: [
135
158
  "10,000,000+ managed credits / month",
136
- "Automation actions at 0.01 credits each",
159
+ "Workflows",
137
160
  "Phone number enrichment on managed credits",
138
161
  "Custom provider routing and BYOK policies",
139
162
  "Dedicated onboarding",
@@ -181,6 +204,52 @@ export const ACTIVE_SUBSCRIPTION_STATUSES = [
181
204
  "trialing",
182
205
  "past_due",
183
206
  ];
207
+ export const BILLING_VISIBLE_SUBSCRIPTION_STATUSES = [
208
+ ...ACTIVE_SUBSCRIPTION_STATUSES,
209
+ "unpaid",
210
+ "paused",
211
+ "incomplete",
212
+ ];
213
+ export const PAST_DUE_GRACE_DAYS = 7;
214
+ export function resolveSubscriptionEntitlement(input) {
215
+ const now = input.now ?? new Date();
216
+ if (!input.status) {
217
+ return { entitled: false, reason: "missing_subscription", graceEndsAt: null };
218
+ }
219
+ if (input.status === "active") {
220
+ return { entitled: true, reason: "active", graceEndsAt: null };
221
+ }
222
+ if (input.status === "trialing") {
223
+ const trialEnd = input.trialEnd ?? input.currentPeriodEnd ?? null;
224
+ if (!trialEnd) {
225
+ return { entitled: false, reason: "missing_trial_end", graceEndsAt: null };
226
+ }
227
+ return trialEnd.getTime() <= now.getTime()
228
+ ? { entitled: false, reason: "trial_expired", graceEndsAt: null }
229
+ : { entitled: true, reason: "trialing", graceEndsAt: null };
230
+ }
231
+ if (input.status === "past_due") {
232
+ if (!input.currentPeriodStart) {
233
+ return {
234
+ entitled: false,
235
+ reason: "missing_past_due_period_start",
236
+ graceEndsAt: null,
237
+ };
238
+ }
239
+ const graceEndsAt = new Date(input.currentPeriodStart.getTime() + PAST_DUE_GRACE_DAYS * 24 * 60 * 60 * 1000);
240
+ return graceEndsAt.getTime() > now.getTime()
241
+ ? { entitled: true, reason: "past_due_grace", graceEndsAt }
242
+ : { entitled: false, reason: "past_due_grace_expired", graceEndsAt };
243
+ }
244
+ if (input.status === "unpaid"
245
+ || input.status === "paused"
246
+ || input.status === "incomplete"
247
+ || input.status === "canceled"
248
+ || input.status === "incomplete_expired") {
249
+ return { entitled: false, reason: input.status, graceEndsAt: null };
250
+ }
251
+ return { entitled: false, reason: "missing_subscription", graceEndsAt: null };
252
+ }
184
253
  const LEGACY_PRICING_PLAN_OVERRIDES = {
185
254
  launch_50: {
186
255
  ...BASE_PRICING_PLANS.starter,
@@ -280,6 +349,7 @@ plan, metadata) {
280
349
  ?? readString(record, "custom_plan_description");
281
350
  const monthlyCredits = readCreditLimit(config, "monthlyCredits", "monthly_credits", "monthly_credit_limit");
282
351
  const weeklyCreditsLimit = readCreditLimit(config, "weeklyCreditsLimit", "weekly_credits_limit", "weekly_credit_limit");
352
+ const weeklyCreditsLimitDisabled = hasExplicitNull(config, "weeklyCreditsLimit", "weekly_credits_limit", "weekly_credit_limit");
283
353
  const rolloverCap = readCreditLimit(config, "rolloverCap", "rollover_cap", "rollover_credits");
284
354
  const monthlyAutomationActions = readCreditLimit(config, "monthlyAutomationActions", "monthly_automation_actions", "automation_actions", "automation_action_limit");
285
355
  const automationOverageCentsPerMillion = readCreditLimit(config, "automationOverageCentsPerMillion", "automation_overage_cents_per_million", "automation_action_overage_cents_per_million");
@@ -292,7 +362,9 @@ plan, metadata) {
292
362
  ...plan,
293
363
  name: name ?? plan.name,
294
364
  monthlyCredits: monthlyCredits ?? plan.monthlyCredits,
295
- weeklyCreditsLimit: weeklyCreditsLimit ?? plan.weeklyCreditsLimit,
365
+ weeklyCreditsLimit: weeklyCreditsLimitDisabled
366
+ ? null
367
+ : weeklyCreditsLimit ?? plan.weeklyCreditsLimit,
296
368
  rolloverCap: rolloverCap ?? plan.rolloverCap,
297
369
  monthlyAutomationActions: monthlyAutomationActions ?? plan.monthlyAutomationActions,
298
370
  automationOverageCentsPerMillion: automationOverageCentsPerMillion ?? plan.automationOverageCentsPerMillion,
@@ -339,6 +411,9 @@ function readCreditLimit(record, ...keys) {
339
411
  }
340
412
  return null;
341
413
  }
414
+ function hasExplicitNull(record, ...keys) {
415
+ return keys.some((key) => Object.hasOwn(record, key) && record[key] === null);
416
+ }
342
417
  export function getCurrentFreeTierCycleKey(date = new Date()) {
343
418
  const year = date.getUTCFullYear();
344
419
  const month = String(date.getUTCMonth() + 1).padStart(2, "0");
@@ -0,0 +1,12 @@
1
+ export type CopilotJourney = {
2
+ slug: string;
3
+ title: string;
4
+ description: string;
5
+ /** Existing catalog recipe slugs this journey leans on (advisory only). */
6
+ recipeSlugs: readonly string[];
7
+ /** The first user message a journey card seeds into a new session. */
8
+ seedMessage: string;
9
+ };
10
+ export declare const COPILOT_JOURNEYS: readonly CopilotJourney[];
11
+ export type CopilotJourneySlug = (typeof COPILOT_JOURNEYS)[number]["slug"];
12
+ export declare function getCopilotJourney(slug: string): CopilotJourney | null;
@@ -0,0 +1,36 @@
1
+ // Workspace Copilot guided journeys (ADR 0013 §11). One canonical copy shared by
2
+ // the runtime (system-prompt grounding on the named recipes) and the web journey
3
+ // cards (seeding a session's first message) — the data is pure and client-safe.
4
+ // Each journey is a thin descriptor over EXISTING advisory catalog Recipes:
5
+ // journeys add no runtime behavior, and every guardrail (never enroll/send/buy/
6
+ // change DNS without approval) rides those recipes' own approval gates.
7
+ export const COPILOT_JOURNEYS = [
8
+ {
9
+ slug: "inbound-led-outbound",
10
+ title: "Inbound-led outbound",
11
+ description: "Turn LinkedIn engagement, profile views, and replies into a segmented outreach motion.",
12
+ recipeSlugs: [
13
+ "profile-viewer-outreach",
14
+ "daily-warm-lead-queue",
15
+ "reply-to-meeting",
16
+ ],
17
+ seedMessage: "Help me turn my recent LinkedIn engagement (profile views, post reactions, replies) into a safe, segmented outreach motion. Start by showing me what signals and connected identities I have.",
18
+ },
19
+ {
20
+ slug: "tam-sourcing",
21
+ title: "Map your market",
22
+ description: "Source and segment your addressable market from your ICP, starting with a bounded sample.",
23
+ recipeSlugs: ["icp-to-account-map", "outbound-pilot-50"],
24
+ seedMessage: "Help me map my total addressable market from my ICP. Ground it in my company profile and website, source a bounded sample first, and show me coverage and credit estimates before expanding.",
25
+ },
26
+ {
27
+ slug: "email-infra-setup",
28
+ title: "Outbound infrastructure",
29
+ description: "Domains, inboxes, warmup, sender posture — reviewed and approved before anything is bought or sent.",
30
+ recipeSlugs: ["email-infra-setup"],
31
+ seedMessage: "Inspect my current sending setup (domains, inboxes, warmup, senders, caps, deliverability) and propose what's missing for a safe cold-email motion. Show quotes and costs — do not buy or change anything without my approval.",
32
+ },
33
+ ];
34
+ export function getCopilotJourney(slug) {
35
+ return COPILOT_JOURNEYS.find((journey) => journey.slug === slug) ?? null;
36
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Canonical hosted-AI model registry — the single source of truth for which
3
+ * OXYGEN-hosted model backs each reasoning tier of each hosted-AI use case, its
4
+ * human-readable name, its fallback chain, the OpenRouter reasoning effort to
5
+ * request, and the conservative pre-call price estimates used ONLY to size
6
+ * credit reservations (billing always settles on the provider's actual
7
+ * `usage.cost`, never on the numbers here).
8
+ *
9
+ * Two use cases share the registry today:
10
+ * - `ai_column` — managed AI table columns. Its default model ids are
11
+ * re-sourced verbatim by `@oxygen/integrations` (`ai-column-runner.ts`
12
+ * `DEFAULT_REASONING_MODELS`) and `@oxygen/tenant-db` (`ai-models.ts`
13
+ * `DEFAULT_MANAGED_REASONING_MODELS`). Those modules keep owning the
14
+ * `OXYGEN_OPENROUTER_MODEL_*` env-override resolution; this registry only
15
+ * supplies the defaults, so AI-column behavior is byte-for-byte unchanged.
16
+ * - `copilot` — the hosted copilot. Its model + fallback chain accept Doppler
17
+ * overrides (`OXYGEN_COPILOT_MODEL_*` / `OXYGEN_COPILOT_FALLBACK_*`) applied
18
+ * here by `resolveHostedAiModel`.
19
+ *
20
+ * Kept as a leaf module (mirrors ./pricing-sheet.ts): no imports, so any package
21
+ * can re-source the catalog without dragging in the shared barrel.
22
+ */
23
+ export type HostedAiLevel = "low" | "medium" | "high";
24
+ export type HostedAiUseCase = "ai_column" | "copilot" | "agent";
25
+ export type HostedAiModelSpec = {
26
+ /** OpenRouter model id, e.g. "deepseek/deepseek-v4-flash". */
27
+ model: string;
28
+ /** Human-readable label for dashboards/UI. */
29
+ displayName: string;
30
+ /** Ordered fallback model ids tried when `model` is unavailable. */
31
+ fallbackModels: readonly string[];
32
+ /**
33
+ * OpenRouter reasoning effort to request; omit entirely for models that only
34
+ * support their max mode (Kimi K3) — the request builder sends no reasoning
35
+ * param for those.
36
+ */
37
+ reasoningEffort?: "low" | "medium" | "high";
38
+ /**
39
+ * Conservative pre-call estimation prices (USD per 1M tokens). Billing settles
40
+ * on actual `usage.cost`; these ONLY size credit reservations.
41
+ */
42
+ estPromptUsdPerM: number;
43
+ estCompletionUsdPerM: number;
44
+ /** Upper bound on completion tokens requested for this tier. */
45
+ maxOutputTokens: number;
46
+ };
47
+ export declare const HOSTED_AI_MODEL_REGISTRY: Record<HostedAiUseCase, Record<HostedAiLevel, HostedAiModelSpec>>;
48
+ /** The reasoning tier the hosted copilot runs at by default. */
49
+ export declare const COPILOT_DEFAULT_LEVEL: HostedAiLevel;
50
+ export declare const AGENT_DEFAULT_LEVEL: HostedAiLevel;
51
+ /**
52
+ * Resolve the model spec for a hosted-AI use case + reasoning level.
53
+ *
54
+ * For `copilot`, Doppler overrides are applied here:
55
+ * - `OXYGEN_COPILOT_MODEL_{LOW,MEDIUM,HIGH}` replaces `.model` (and, since no
56
+ * separate label is supplied, `.displayName` falls back to the model id).
57
+ * - `OXYGEN_COPILOT_FALLBACK_{LOW,MEDIUM,HIGH}` replaces `.fallbackModels`
58
+ * from a comma-separated list.
59
+ *
60
+ * For `ai_column`, NO env handling is applied here: `@oxygen/integrations`
61
+ * `ai-column-runner.ts` (`resolveModel`/`resolveAiColumnTierModels`) and
62
+ * `@oxygen/tenant-db` `ai-models.ts` (`resolveManagedReasoningModels`) remain
63
+ * the sole owners of `OXYGEN_OPENROUTER_MODEL_*` resolution, so the AI-column
64
+ * path is untouched.
65
+ */
66
+ /**
67
+ * Look a model id up across the priced registry (same-use-case tiers first).
68
+ * A session-level model override must land on a spec that carries ITS OWN
69
+ * pricing/limits — splicing an arbitrary id onto another tier's spec sizes the
70
+ * credit reservation for the wrong model and breaks the spend ceiling.
71
+ */
72
+ export declare function findHostedAiModelSpec(model: string, preferredUseCase?: HostedAiUseCase): HostedAiModelSpec | null;
73
+ export declare function resolveHostedAiModel(input: {
74
+ useCase: HostedAiUseCase;
75
+ level: HostedAiLevel;
76
+ env?: Record<string, string | undefined>;
77
+ }): HostedAiModelSpec;
78
+ /**
79
+ * Convenience map of each reasoning tier's default `.model` id for a use case.
80
+ * `@oxygen/integrations` and `@oxygen/tenant-db` re-source their AI-column
81
+ * default catalogs from `hostedAiDefaultModels("ai_column")` so the model ids
82
+ * live in exactly one place. Returns a fresh object each call.
83
+ */
84
+ export declare function hostedAiDefaultModels(useCase: HostedAiUseCase): Record<HostedAiLevel, string>;
85
+ /**
86
+ * Whether the hosted copilot is enabled for this environment. FAIL CLOSED: only
87
+ * the exact strings "1" or "true" (case-insensitive, trimmed) enable it;
88
+ * anything else — unset, "", "0", "false" — leaves it off.
89
+ */
90
+ export declare function isCopilotEnabled(env?: Record<string, string | undefined>): boolean;