@oxygen-agent/cli 1.1011.974 → 1.1012.2
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.
- package/README.md +1 -1
- package/dist/command-manifest.d.ts +3 -1
- package/dist/command-manifest.js +29 -0
- package/dist/crm-support-flags.d.ts +1 -0
- package/dist/crm-support-flags.js +5 -1
- package/dist/customer-operation-commands.js +30 -1
- package/dist/help.js +10 -2
- package/dist/http-client.d.ts +4 -0
- package/dist/http-client.js +21 -10
- package/dist/index.js +326 -111
- package/dist/sender-limits-flags.d.ts +7 -0
- package/dist/sender-limits-flags.js +13 -0
- package/dist/transcript.js +1 -1
- package/node_modules/@oxygen/formula/dist/expression.js +16 -0
- package/node_modules/@oxygen/shared/dist/attempt-provenance.d.ts +30 -0
- package/node_modules/@oxygen/shared/dist/attempt-provenance.js +98 -0
- package/node_modules/@oxygen/shared/dist/byok-connect.js +2 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +8 -1
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +172 -13
- package/node_modules/@oxygen/shared/dist/cli-result.js +6 -0
- package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +19 -7
- package/node_modules/@oxygen/shared/dist/contracts/crm-attributes.d.ts +7 -1
- package/node_modules/@oxygen/shared/dist/contracts/crm-attributes.js +5 -1
- package/node_modules/@oxygen/shared/dist/contracts/crm-support.d.ts +14 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-support.js +4 -0
- package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +5 -5
- package/node_modules/@oxygen/shared/dist/contracts/geo.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/contracts/geo.js +138 -0
- package/node_modules/@oxygen/shared/dist/contracts/operations.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/contracts/operations.js +4 -3
- package/node_modules/@oxygen/shared/dist/contracts/publishing-reads.js +1 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-row-removal.d.ts +16 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-row-removal.js +27 -0
- package/node_modules/@oxygen/shared/dist/cost-estimate.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/cost-estimate.js +23 -8
- package/node_modules/@oxygen/shared/dist/enrichment-intents.js +2 -1
- package/node_modules/@oxygen/shared/dist/external-effect-arming.d.ts +54 -0
- package/node_modules/@oxygen/shared/dist/external-effect-arming.js +90 -0
- package/node_modules/@oxygen/shared/dist/geo.d.ts +247 -0
- package/node_modules/@oxygen/shared/dist/geo.js +314 -0
- package/node_modules/@oxygen/shared/dist/knowledge-seed-content.js +2 -2
- package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +9 -0
- package/node_modules/@oxygen/shared/dist/linkedin-countries.js +1 -1
- package/node_modules/@oxygen/shared/dist/linkedin-quota-denial.d.ts +48 -0
- package/node_modules/@oxygen/shared/dist/linkedin-quota-denial.js +94 -0
- package/node_modules/@oxygen/shared/dist/managed-email-branding.d.ts +15 -0
- package/node_modules/@oxygen/shared/dist/managed-email-branding.js +81 -0
- package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +20 -24
- package/node_modules/@oxygen/shared/dist/pricing-sheet.js +15 -16
- package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +3 -3
- package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +3 -3
- package/node_modules/@oxygen/shared/dist/product-doctrine.js +6 -5
- package/node_modules/@oxygen/shared/dist/provider-balance-signal.js +3 -2
- package/node_modules/@oxygen/shared/dist/recipes.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/recipes.js +1 -0
- package/node_modules/@oxygen/shared/dist/repricing.d.ts +4 -14
- package/node_modules/@oxygen/shared/dist/repricing.js +25 -64
- package/node_modules/@oxygen/shared/dist/research-depth.d.ts +11 -0
- package/node_modules/@oxygen/shared/dist/research-depth.js +7 -0
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/node_modules/@oxygen/shared/dist/whatsapp-sender-limits.d.ts +88 -0
- package/node_modules/@oxygen/shared/dist/whatsapp-sender-limits.js +118 -0
- package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.d.ts +15 -0
- package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.js +33 -0
- package/node_modules/@oxygen/shared/package.json +15 -5
- package/node_modules/@oxygen/workflows/dist/usage-estimate.js +9 -5
- package/package.json +1 -1
- package/node_modules/@oxygen/shared/dist/vercel-sandbox-fetch.d.ts +0 -9
- package/node_modules/@oxygen/shared/dist/vercel-sandbox-fetch.js +0 -33
|
@@ -70,3 +70,97 @@ export function linkedInQuotaParkedUntil(metadata, key) {
|
|
|
70
70
|
const ms = Date.parse(raw);
|
|
71
71
|
return Number.isNaN(ms) ? 0 : ms;
|
|
72
72
|
}
|
|
73
|
+
// ===== Inbox sync failures that are not quota denials (OXP-1.11.72) =====
|
|
74
|
+
//
|
|
75
|
+
// A quota denial parks the sender until its budget resets (above). Every other
|
|
76
|
+
// whole-sender inbox sync failure used to leave the sender eligible on the next
|
|
77
|
+
// backstop pass: in the week to 2026-10-07 production retried one sender 45
|
|
78
|
+
// times through "Managed provider capacity is busy." and 24 senders every few
|
|
79
|
+
// minutes through a 27-minute LinkedIn 5xx incident, and nothing on the sender
|
|
80
|
+
// said so. These failures now park on a bounded, doubling backoff and leave an
|
|
81
|
+
// inspectable record that the next successful sync clears.
|
|
82
|
+
/**
|
|
83
|
+
* Where a sender's inbox sync is parked until, quota or failure backoff alike,
|
|
84
|
+
* in the freeform `sender_accounts.metadata` jsonb.
|
|
85
|
+
*/
|
|
86
|
+
export const INBOX_SYNC_BACKOFF_KEY = "inbox_sync_backoff_until";
|
|
87
|
+
/** The sender metadata key holding the latest non-quota inbox sync failure. */
|
|
88
|
+
export const INBOX_SYNC_FAILURE_KEY = "inbox_sync_failure";
|
|
89
|
+
// Refusals raised before the read leaves the process that clear on their own:
|
|
90
|
+
// the managed-provider limiter after waiting out its window, a runtime with no
|
|
91
|
+
// quota enforcer registered, and an unsizable worker fleet. The same set the
|
|
92
|
+
// LinkedIn ingestion drip defers on.
|
|
93
|
+
const TRANSIENT_CODES = new Set([
|
|
94
|
+
"rate_limit_exceeded",
|
|
95
|
+
"linkedin_quota_enforcement_unavailable",
|
|
96
|
+
"worker_fleet_discovery_unavailable",
|
|
97
|
+
]);
|
|
98
|
+
/** First park after a non-quota failure; it doubles per consecutive failure. */
|
|
99
|
+
export const INBOX_SYNC_FAILURE_BASE_BACKOFF_MS = 5 * 60 * 1000;
|
|
100
|
+
/** No non-quota failure parks a sender longer than this. */
|
|
101
|
+
export const INBOX_SYNC_FAILURE_MAX_BACKOFF_MS = 2 * 60 * 60 * 1000;
|
|
102
|
+
function errorStatus(error) {
|
|
103
|
+
const status = isRecord(error) ? error.status : undefined;
|
|
104
|
+
return typeof status === "number" && Number.isFinite(status) ? status : null;
|
|
105
|
+
}
|
|
106
|
+
/** Quota, authentication (401/403), transient (capacity, 429, 5xx, retryable), else other. */
|
|
107
|
+
export function classifyInboxSyncFailure(error) {
|
|
108
|
+
if (isLinkedInQuotaDenial(error))
|
|
109
|
+
return "quota";
|
|
110
|
+
const status = errorStatus(error);
|
|
111
|
+
if (status === 401 || status === 403)
|
|
112
|
+
return "authentication";
|
|
113
|
+
if (error instanceof OxygenError && TRANSIENT_CODES.has(error.code))
|
|
114
|
+
return "transient";
|
|
115
|
+
if (status === 429 || (status !== null && status >= 500))
|
|
116
|
+
return "transient";
|
|
117
|
+
if (isRecord(error) && error.retryable === true)
|
|
118
|
+
return "transient";
|
|
119
|
+
return "other";
|
|
120
|
+
}
|
|
121
|
+
/** The latest non-quota inbox sync failure recorded on a sender, or null. */
|
|
122
|
+
export function readInboxSyncFailure(metadata) {
|
|
123
|
+
const raw = isRecord(metadata) ? metadata[INBOX_SYNC_FAILURE_KEY] : undefined;
|
|
124
|
+
if (!isRecord(raw) || typeof raw.consecutive !== "number" || raw.consecutive < 1 || typeof raw.first_at !== "string")
|
|
125
|
+
return null;
|
|
126
|
+
return raw;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The park and record for a whole-sender inbox sync failure that is not a quota
|
|
130
|
+
* denial: 5 min, doubling per consecutive failure, capped at 2 h. Null for a
|
|
131
|
+
* quota denial, which keeps its own park (linkedInQuotaBackoffUntil).
|
|
132
|
+
*/
|
|
133
|
+
export function inboxSyncFailureBackoff(error, metadata, now) {
|
|
134
|
+
const failureClass = classifyInboxSyncFailure(error);
|
|
135
|
+
if (failureClass === "quota")
|
|
136
|
+
return null;
|
|
137
|
+
const previous = readInboxSyncFailure(metadata);
|
|
138
|
+
const consecutive = (previous?.consecutive ?? 0) + 1;
|
|
139
|
+
const delay = Math.min(INBOX_SYNC_FAILURE_BASE_BACKOFF_MS * 2 ** Math.min(consecutive - 1, 16), INBOX_SYNC_FAILURE_MAX_BACKOFF_MS);
|
|
140
|
+
const until = new Date(now.getTime() + delay);
|
|
141
|
+
return {
|
|
142
|
+
until,
|
|
143
|
+
record: {
|
|
144
|
+
class: failureClass,
|
|
145
|
+
code: error instanceof OxygenError ? error.code : null,
|
|
146
|
+
status: errorStatus(error),
|
|
147
|
+
consecutive,
|
|
148
|
+
first_at: previous?.first_at ?? now.toISOString(),
|
|
149
|
+
last_at: now.toISOString(),
|
|
150
|
+
retry_at: until.toISOString(),
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A sender's whole-inbox sync state for health reads: the last successful sync,
|
|
156
|
+
* the latest failure that was not a quota denial (cleared by the next success),
|
|
157
|
+
* and until when the background sync leaves the sender alone.
|
|
158
|
+
*/
|
|
159
|
+
export function inboxSyncHealth(sender, now = new Date()) {
|
|
160
|
+
const parkedUntil = linkedInQuotaParkedUntil(sender.metadata, INBOX_SYNC_BACKOFF_KEY);
|
|
161
|
+
return {
|
|
162
|
+
last_synced_at: sender.lastInboxSyncAt ? sender.lastInboxSyncAt.toISOString() : null,
|
|
163
|
+
background_sync_paused_until: parkedUntil > now.getTime() ? new Date(parkedUntil).toISOString() : null,
|
|
164
|
+
last_failure: readInboxSyncFailure(sender.metadata),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Public vocabulary for OXYGEN-managed email services. Backend ids stay in storage. */
|
|
2
|
+
export type ManagedEmailProduct = "warmup" | "placement";
|
|
3
|
+
export declare const OXYGEN_WARMUP_PROVIDER = "oxygen_warmup";
|
|
4
|
+
export declare const OXYGEN_PLACEMENT_PROVIDER = "oxygen_placement";
|
|
5
|
+
export declare function managedEmailProviderInput(value: unknown, product: ManagedEmailProduct): unknown;
|
|
6
|
+
export declare function isManagedWarmupProvider(value: unknown): boolean;
|
|
7
|
+
export declare function isManagedPlacementProvider(value: unknown): boolean;
|
|
8
|
+
export declare function managedEmailMessage(value: string, product?: ManagedEmailProduct): string;
|
|
9
|
+
/**
|
|
10
|
+
* Project only service identifiers and copy. Preserve URLs, ids, hashes, dates,
|
|
11
|
+
* customer-authored subject/body/configuration, and provider evidence verbatim.
|
|
12
|
+
* The caller must choose a managed email surface; do not apply to generic BYOK tools.
|
|
13
|
+
*/
|
|
14
|
+
export declare function publicManagedEmail<T>(value: T, product?: ManagedEmailProduct): T;
|
|
15
|
+
export declare function publicManagedEmailCommand<T>(command: string, value: T): T;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const OXYGEN_WARMUP_PROVIDER = "oxygen_warmup";
|
|
2
|
+
export const OXYGEN_PLACEMENT_PROVIDER = "oxygen_placement";
|
|
3
|
+
export function managedEmailProviderInput(value, product) {
|
|
4
|
+
const publicId = product === "warmup" ? OXYGEN_WARMUP_PROVIDER : OXYGEN_PLACEMENT_PROVIDER;
|
|
5
|
+
return typeof value === "string" && value.trim().toLowerCase() === publicId ? "sendkit" : value;
|
|
6
|
+
}
|
|
7
|
+
export function isManagedWarmupProvider(value) {
|
|
8
|
+
return value === "sendkit" || value === OXYGEN_WARMUP_PROVIDER;
|
|
9
|
+
}
|
|
10
|
+
export function isManagedPlacementProvider(value) {
|
|
11
|
+
return value === "sendkit" || value === OXYGEN_PLACEMENT_PROVIDER;
|
|
12
|
+
}
|
|
13
|
+
// These are service-owned fields, never arbitrary customer content or opaque receipts.
|
|
14
|
+
const IDENTIFIER_FIELDS = new Set([
|
|
15
|
+
"provider", "active_provider", "warmup_provider", "warmupProvider", "warmupRail",
|
|
16
|
+
"action", "code", "failure_code", "error_code", "credential_source", "credentialSource",
|
|
17
|
+
"method", "handoff", "reason_code", "kind", "type", "source",
|
|
18
|
+
]);
|
|
19
|
+
const COPY_FIELDS = new Set([
|
|
20
|
+
"message", "note", "reason", "description", "hint", "transport_hint", "next_step",
|
|
21
|
+
"next_action", "nextAction", "label", "title", "instruction", "instructions", "warnings",
|
|
22
|
+
"recommendation", "recommendations", "limitations", "next_external_write", "price_note",
|
|
23
|
+
"error", "errors", "summary", "blocker", "blockers", "detail", "details_text", "provider_label",
|
|
24
|
+
]);
|
|
25
|
+
export function managedEmailMessage(value, product = "warmup") {
|
|
26
|
+
const label = product === "warmup" ? "OXYGEN Warm-up" : "OXYGEN placement evaluation";
|
|
27
|
+
if (product === "placement") {
|
|
28
|
+
value = value.replace(/(?:SendKit|OXYGEN placement evaluation) does not document whether inbox, spam, and missing summary values are counts or percentages; Oxygen preserves the values without conversion\./gi, "Summary units are unverified (counts or percentages); values are shown as recorded, without conversion.");
|
|
29
|
+
}
|
|
30
|
+
return value.replace(/SendKit(?:'s)?\s+warm-?up/gi, label).replace(/SendKit/gi, label);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Project only service identifiers and copy. Preserve URLs, ids, hashes, dates,
|
|
34
|
+
* customer-authored subject/body/configuration, and provider evidence verbatim.
|
|
35
|
+
* The caller must choose a managed email surface; do not apply to generic BYOK tools.
|
|
36
|
+
*/
|
|
37
|
+
export function publicManagedEmail(value, product = "warmup") {
|
|
38
|
+
const opaqueFields = new Set(["plan_hash", "id", "subject", "body", "body_text", "body_html", "config", "warmupConfig", "rampConfig", "email_address", "emailAddress", "tags", "displayName", "signatureHtml"]);
|
|
39
|
+
function project(entry, field = "", context = product) {
|
|
40
|
+
const publicId = context === "warmup" ? OXYGEN_WARMUP_PROVIDER : OXYGEN_PLACEMENT_PROVIDER;
|
|
41
|
+
if (opaqueFields.has(field))
|
|
42
|
+
return entry;
|
|
43
|
+
if (typeof entry === "string") {
|
|
44
|
+
if (field === "source_id" || field === "sourceId") {
|
|
45
|
+
return entry.replace(/^warmup:sendkit:/, "warmup:oxygen_warmup:");
|
|
46
|
+
}
|
|
47
|
+
if (IDENTIFIER_FIELDS.has(field)) {
|
|
48
|
+
if (entry.toLowerCase() === "sendkit")
|
|
49
|
+
return publicId;
|
|
50
|
+
return entry.replace(/sendkit_/gi, `${publicId}_`).replace(/_sendkit/gi, `_${publicId}`);
|
|
51
|
+
}
|
|
52
|
+
return COPY_FIELDS.has(field) ? managedEmailMessage(entry, context) : entry;
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(entry))
|
|
55
|
+
return entry.map((item) => project(item, field, context));
|
|
56
|
+
if (!entry || typeof entry !== "object" || entry instanceof Date)
|
|
57
|
+
return entry;
|
|
58
|
+
const record = entry;
|
|
59
|
+
// Existing customer-owned bindings stay private; never label their usage managed warmup.
|
|
60
|
+
const groupKey = record.key && typeof record.key === "object" && !Array.isArray(record.key)
|
|
61
|
+
? record.key : null;
|
|
62
|
+
const privateUsage = (record.provider === "sendkit" || groupKey?.provider === "sendkit") &&
|
|
63
|
+
(record.type === "byok_usage" || (typeof record.byok_usage_events === "number" && record.byok_usage_events > 0));
|
|
64
|
+
return Object.fromEntries(Object.entries(record).map(([key, item]) => [
|
|
65
|
+
{ sendkit_google: "oxygen_warmup_google", sendkit_microsoft: "oxygen_warmup_microsoft", sendkit_binding: "oxygen_placement_binding", sendkitBinding: "oxygen_placement_binding" }[key] ?? key,
|
|
66
|
+
privateUsage && key === "provider" ? "private_integration"
|
|
67
|
+
: privateUsage && key === "key" ? project({ ...groupKey, provider: "private_integration" }, key, context)
|
|
68
|
+
: privateUsage && key === "tool_id" ? null
|
|
69
|
+
: privateUsage && key === "description" ? "Existing private integration usage."
|
|
70
|
+
: project(item, key, /^warmup/i.test(key) ? "warmup" : /^placement/i.test(key) ? "placement" : context),
|
|
71
|
+
]));
|
|
72
|
+
}
|
|
73
|
+
return project(value);
|
|
74
|
+
}
|
|
75
|
+
export function publicManagedEmailCommand(command, value) {
|
|
76
|
+
if (/^(mailboxes|managed-inboxes|billing)(?: |$)/.test(command))
|
|
77
|
+
return publicManagedEmail(value);
|
|
78
|
+
if (/^deliverability(?: |$)/.test(command))
|
|
79
|
+
return publicManagedEmail(value, "placement");
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
@@ -137,11 +137,7 @@ export declare const RESEARCH_DEPTH_MODEL_CREDITS: {
|
|
|
137
137
|
readonly standard: 4.3;
|
|
138
138
|
readonly deep: 7.6;
|
|
139
139
|
};
|
|
140
|
-
/** The tier whose model each loop depth runs on
|
|
141
|
-
export declare const RESEARCH_DEPTH_MODEL_TIER: {
|
|
142
|
-
readonly standard: "low";
|
|
143
|
-
readonly deep: "medium";
|
|
144
|
-
};
|
|
140
|
+
/** The tier whose model each loop depth runs on lives in ./research-depth.ts: a routing fact, not a price. */
|
|
145
141
|
/**
|
|
146
142
|
* The tool half of a standard/deep row. `typical` is the ratified planning shape —
|
|
147
143
|
* standard: 2 serper searches + 2 native page reads; deep: 3 serper searches + 4
|
|
@@ -177,18 +173,18 @@ export declare const RESEARCH_DEPTH_TYPICAL_ROW_CREDITS: {
|
|
|
177
173
|
*/
|
|
178
174
|
export { AUTOMATION_STEP_CREDITS_REPRICING } from "./repricing.js";
|
|
179
175
|
/**
|
|
180
|
-
* The flat mailbox line of a managed Google
|
|
181
|
-
*
|
|
182
|
-
* included, bills beside it:
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* (min/typical/max all equal) so callers that destructure any field need
|
|
186
|
-
* shape change.
|
|
176
|
+
* The flat mailbox line of a managed Google or Microsoft 365 inbox: 300 (founder,
|
|
177
|
+
* 2026-10-07; repricing decision 3.1 had set 400 for Google alone). Its 100-credit
|
|
178
|
+
* mailbox connection, warm-up included, bills beside it: 400 all-in, which
|
|
179
|
+
* `managedInboxAllInCredits()` from `@oxygen/shared/repricing` quotes. The price
|
|
180
|
+
* charged is the pricing book's row; this is its committed default. Kept as an
|
|
181
|
+
* object (min/typical/max all equal) so callers that destructure any field need
|
|
182
|
+
* no shape change.
|
|
187
183
|
*/
|
|
188
184
|
export declare const MANAGED_INBOX_CREDITS_PER_MONTH: {
|
|
189
|
-
readonly min:
|
|
190
|
-
readonly typical:
|
|
191
|
-
readonly max:
|
|
185
|
+
readonly min: 300;
|
|
186
|
+
readonly typical: 300;
|
|
187
|
+
readonly max: 300;
|
|
192
188
|
};
|
|
193
189
|
/**
|
|
194
190
|
* VOICE (the call channel). One price per connected minute, 5 credits ($0.05),
|
|
@@ -221,17 +217,17 @@ export declare const SENDING_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 1250;
|
|
|
221
217
|
* THE ALLOWANCE IS LOAD-BEARING, not a perk. Placement COGS is per TEST
|
|
222
218
|
* ($0.1327 on EmailGuard's Agency plan), not per inbox, so an unbounded seat
|
|
223
219
|
* inverts its own margin: at $1.00/inbox-month the EIGHTH test in a cycle was
|
|
224
|
-
* already sold at a loss. Two included tests cost $0.265 against $1.
|
|
225
|
-
* revenue at
|
|
220
|
+
* already sold at a loss. Two included tests cost $0.265 against $1.00 of
|
|
221
|
+
* revenue at today's price, and everything past them bills
|
|
226
222
|
* PLACEMENT_TEST_OVERAGE_CREDITS. Orgs on their own EmailGuard key (BYOK) pay 0.
|
|
227
223
|
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* a surface that quotes or bills uses
|
|
231
|
-
* `
|
|
232
|
-
* the switch's instant)
|
|
224
|
+
* Monitoring is 100 credits per inbox-month (founder, 2026-10-07; the 2026-09
|
|
225
|
+
* repricing had set 135). The extra test is the RATIFIED 66 (slice S30), whose rise
|
|
226
|
+
* waits for the S07 effective-date switch, so a surface that quotes or bills uses
|
|
227
|
+
* `deliverabilitySeatCredits()` and `placementTestCredits()` from
|
|
228
|
+
* `@oxygen/shared/repricing` (16.6 for the test until the switch's instant).
|
|
233
229
|
*/
|
|
234
|
-
export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH =
|
|
230
|
+
export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
|
|
235
231
|
export declare const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
|
|
236
232
|
export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 66;
|
|
237
233
|
/**
|
|
@@ -262,7 +258,7 @@ export declare const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = 0;
|
|
|
262
258
|
* Seeded at the 2026-09 repricing's price (3,000, decision 2.3); resolve the
|
|
263
259
|
* price in force with repricedChargeCredits.
|
|
264
260
|
*/
|
|
265
|
-
export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH =
|
|
261
|
+
export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3400;
|
|
266
262
|
/**
|
|
267
263
|
* X accounts: monthly credit reservation per connected account (2026-09
|
|
268
264
|
* repricing, decision 2.2). Like the LinkedIn and WhatsApp constants above this
|
|
@@ -134,8 +134,7 @@ export const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.6;
|
|
|
134
134
|
* likely under 5x once a loop runs more than two turns.
|
|
135
135
|
*/
|
|
136
136
|
export const RESEARCH_DEPTH_MODEL_CREDITS = { standard: 4.3, deep: 7.6 };
|
|
137
|
-
/** The tier whose model each loop depth runs on
|
|
138
|
-
export const RESEARCH_DEPTH_MODEL_TIER = { standard: "low", deep: "medium" };
|
|
137
|
+
/** The tier whose model each loop depth runs on lives in ./research-depth.ts: a routing fact, not a price. */
|
|
139
138
|
/**
|
|
140
139
|
* The tool half of a standard/deep row. `typical` is the ratified planning shape —
|
|
141
140
|
* standard: 2 serper searches + 2 native page reads; deep: 3 serper searches + 4
|
|
@@ -161,13 +160,13 @@ export const RESEARCH_DEPTH_TYPICAL_ROW_CREDITS = { quick: 2.1, standard: 5.5, d
|
|
|
161
160
|
*/
|
|
162
161
|
export { AUTOMATION_STEP_CREDITS_REPRICING } from "./repricing.js";
|
|
163
162
|
/**
|
|
164
|
-
* The flat mailbox line of a managed Google
|
|
165
|
-
*
|
|
166
|
-
* included, bills beside it:
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* (min/typical/max all equal) so callers that destructure any field need
|
|
170
|
-
* shape change.
|
|
163
|
+
* The flat mailbox line of a managed Google or Microsoft 365 inbox: 300 (founder,
|
|
164
|
+
* 2026-10-07; repricing decision 3.1 had set 400 for Google alone). Its 100-credit
|
|
165
|
+
* mailbox connection, warm-up included, bills beside it: 400 all-in, which
|
|
166
|
+
* `managedInboxAllInCredits()` from `@oxygen/shared/repricing` quotes. The price
|
|
167
|
+
* charged is the pricing book's row; this is its committed default. Kept as an
|
|
168
|
+
* object (min/typical/max all equal) so callers that destructure any field need
|
|
169
|
+
* no shape change.
|
|
171
170
|
*/
|
|
172
171
|
export const MANAGED_INBOX_CREDITS_PER_MONTH = {
|
|
173
172
|
min: SNAPSHOT_MANAGED_INBOX_CREDITS_PER_MONTH,
|
|
@@ -205,15 +204,15 @@ export const SENDING_DOMAIN_CREDITS_PER_YEAR_TYPICAL = SNAPSHOT_SENDING_DOMAIN_C
|
|
|
205
204
|
* THE ALLOWANCE IS LOAD-BEARING, not a perk. Placement COGS is per TEST
|
|
206
205
|
* ($0.1327 on EmailGuard's Agency plan), not per inbox, so an unbounded seat
|
|
207
206
|
* inverts its own margin: at $1.00/inbox-month the EIGHTH test in a cycle was
|
|
208
|
-
* already sold at a loss. Two included tests cost $0.265 against $1.
|
|
209
|
-
* revenue at
|
|
207
|
+
* already sold at a loss. Two included tests cost $0.265 against $1.00 of
|
|
208
|
+
* revenue at today's price, and everything past them bills
|
|
210
209
|
* PLACEMENT_TEST_OVERAGE_CREDITS. Orgs on their own EmailGuard key (BYOK) pay 0.
|
|
211
210
|
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* a surface that quotes or bills uses
|
|
215
|
-
* `
|
|
216
|
-
* the switch's instant)
|
|
211
|
+
* Monitoring is 100 credits per inbox-month (founder, 2026-10-07; the 2026-09
|
|
212
|
+
* repricing had set 135). The extra test is the RATIFIED 66 (slice S30), whose rise
|
|
213
|
+
* waits for the S07 effective-date switch, so a surface that quotes or bills uses
|
|
214
|
+
* `deliverabilitySeatCredits()` and `placementTestCredits()` from
|
|
215
|
+
* `@oxygen/shared/repricing` (16.6 for the test until the switch's instant).
|
|
217
216
|
*/
|
|
218
217
|
export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = SNAPSHOT_DELIVERABILITY_SEAT_CREDITS_PER_MONTH;
|
|
219
218
|
export const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = SNAPSHOT_DELIVERABILITY_INCLUDED_TESTS_PER_INBOX;
|
|
@@ -15,13 +15,13 @@ export declare const SUBSCRIPTION_USD_PER_100 = 1;
|
|
|
15
15
|
/** Applied to actual provider inference cost at settle time. */
|
|
16
16
|
export declare const COPILOT_CREDIT_MARKUP_MULTIPLIER = 5;
|
|
17
17
|
export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3400;
|
|
18
|
-
export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH =
|
|
18
|
+
export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3400;
|
|
19
19
|
export declare const X_ACCOUNT_CREDITS_PER_MONTH = 1000;
|
|
20
20
|
export declare const EGRESS_IP_CREDITS_PER_MONTH = 2500;
|
|
21
21
|
export declare const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
|
|
22
|
-
export declare const MANAGED_INBOX_CREDITS_PER_MONTH =
|
|
22
|
+
export declare const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
|
|
23
23
|
export declare const MAILBOX_WARMUP_CREDITS_PER_MONTH = 0;
|
|
24
|
-
export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH =
|
|
24
|
+
export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
|
|
25
25
|
/** Included inbox-placement tests per subscribed inbox per cycle. */
|
|
26
26
|
export declare const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
|
|
27
27
|
/** A placement test beyond the included allowance. */
|
|
@@ -37,13 +37,13 @@ export const COPILOT_CREDIT_MARKUP_MULTIPLIER = 5;
|
|
|
37
37
|
// force is lower; a surface that shows or charges one resolves it with
|
|
38
38
|
// repricedChargeCredits (@oxygen/shared/repricing), never from this literal alone.
|
|
39
39
|
export const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3_400;
|
|
40
|
-
export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH =
|
|
40
|
+
export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3_400;
|
|
41
41
|
export const X_ACCOUNT_CREDITS_PER_MONTH = 1_000;
|
|
42
42
|
export const EGRESS_IP_CREDITS_PER_MONTH = 2_500;
|
|
43
43
|
export const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
|
|
44
|
-
export const MANAGED_INBOX_CREDITS_PER_MONTH =
|
|
44
|
+
export const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
|
|
45
45
|
export const MAILBOX_WARMUP_CREDITS_PER_MONTH = 0;
|
|
46
|
-
export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH =
|
|
46
|
+
export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
|
|
47
47
|
/** Included inbox-placement tests per subscribed inbox per cycle. */
|
|
48
48
|
export const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
|
|
49
49
|
/** A placement test beyond the included allowance. */
|
|
@@ -49,22 +49,23 @@ function rosterLines(routes) {
|
|
|
49
49
|
* a grown or shrunk route array and watching the output follow.
|
|
50
50
|
*/
|
|
51
51
|
export function renderOxygenProductDoctrine(routes = OXYGEN_PRIMITIVE_ROUTES) {
|
|
52
|
-
return `OXYGEN is hosted revenue infrastructure for B2B startups; OXYGEN OS
|
|
52
|
+
return `OXYGEN is hosted revenue infrastructure for B2B startups; OXYGEN OS has five layers. Control (CLI, MCP, web, desktop, Copilot) calls one contract, owns no state; External holds integrations. Between them, the ${routes.length} primitives, each owns its facts:
|
|
53
53
|
|
|
54
54
|
${rosterLines(routes)}
|
|
55
55
|
|
|
56
|
-
Use native primitives
|
|
56
|
+
Use native primitives: state, approvals, costs, provenance and runs stay inspectable; never rebuild one with scripts, cron, files, or a second engine.
|
|
57
57
|
|
|
58
58
|
Ownership law — one owner per fact, no primitive re-implements another:
|
|
59
59
|
|
|
60
|
+
- Geo owns AI-search prompts, answers, citations and experiments; staff/dev pilot only.
|
|
60
61
|
- Records hold canonical truth; Tables hold disposable work promoted onto Records — a row is a candidate, not canon. Tables own typed rows, formulas, AI and tool columns, waterfalls, cell state, and provenance; simple row dependencies stay chained Table columns, not Workflows.
|
|
61
62
|
- Interaction state, not recipient count, owns LinkedIn routing: net-new outreach is Sequences even for one recipient and one step; a reply in an existing thread or one direct email is Messages, holding conversation content, stored once. Cadence, enrollment, sender rotation, suppression, and reply-stop are Sequences.
|
|
62
|
-
- Signals hold durable typed events
|
|
63
|
+
- Signals hold durable typed events; they record what happened, and acting on one is Workflows or Sequences; an inbound reply is both, a reaction only a Signal.
|
|
63
64
|
- Deterministic scheduled, cron, webhook, event, branching, waiting, retrying, or approval-gated orchestration belongs to hosted OXYGEN Workflows: schema → lint → apply → call, and local files are authoring inputs only. Adaptive goals, persistent threads, and checkpoints belong to governed Agents, owning first-class runs and calling Workflows as child actions; neither compiles into the other nor is a store — a draft is Messages, a note Records activity, and Workflow outreach enrolls into an active, bounded Sequence and never sends raw provider messages.
|
|
64
65
|
- Posts hold broadcast artifacts and engagement telemetry; Publishing owns approval-gated scheduling, dispatch, retries, and provenance; Ads owns competitor ad intelligence; Tags are the cross-primitive label vocabulary; Dashboards curates native reporting; Observability is the read lens over runs, costs, and failures, never a second engine.
|
|
65
|
-
-
|
|
66
|
+
- Knowledge Graph describes customer kinds (ICP, personas, offers, rubrics, voice); Records holds the companies and people they describe. Store durable knowledge there, not chat memory: read pages, cite their slugs, search before minting a near-duplicate, file durable findings back. Canonical voice and positioning stay proposal-gated. Pinned canonical context is auto-applied to AI copy; if reported missing, say so rather than write off-voice. Recipes package motions that read it, advisory only.
|
|
66
67
|
|
|
67
|
-
Paid provider work and external writes require a preview on a small sample, exact scope, approval, and a hard credit or action ceiling. Never infer spend authority from tool authority.
|
|
68
|
+
Paid provider work and external writes require a preview on a small sample, exact scope, approval, and a hard credit or action ceiling. Never infer spend authority from tool authority. Show deep-links, costs, failures, retries and approval needs; name missing context, never guess.`;
|
|
68
69
|
}
|
|
69
70
|
/** The rendered doctrine for the shipped primitive roster. */
|
|
70
71
|
export const OXYGEN_PRODUCT_DOCTRINE = renderOxygenProductDoctrine();
|
|
@@ -101,8 +101,9 @@ export const MANAGED_BALANCE_FLOORS = {
|
|
|
101
101
|
// to us, which sits at 0.00 in the normal case (it did on 2026-09-07) and goes
|
|
102
102
|
// negative after a refund. A floor here would page daily about nothing.
|
|
103
103
|
stripe: null,
|
|
104
|
-
//
|
|
105
|
-
//
|
|
104
|
+
// No balance concept at all. Neither is probed any more (Vercel left the stack
|
|
105
|
+
// on 2026-10-06); null keeps a historical row from ever reading as a low wallet
|
|
106
|
+
// under the generic default floor.
|
|
106
107
|
vercel: null,
|
|
107
108
|
neon: null,
|
|
108
109
|
};
|
|
@@ -9,7 +9,7 @@ export declare const RECIPE_STATUSES: readonly ["draft", "beta", "stable", "depr
|
|
|
9
9
|
export type RecipeStatus = typeof RECIPE_STATUSES[number];
|
|
10
10
|
export declare const RECIPE_BENCHMARK_BASES: readonly ["estimate", "observed"];
|
|
11
11
|
export type RecipeBenchmarkBasis = typeof RECIPE_BENCHMARK_BASES[number];
|
|
12
|
-
export declare const RECIPE_PRIMITIVES: readonly ["knowledge-graph", "recipes", "records", "tables", "messages", "posts", "signals", "dashboards", "ads", "tags", "sequences", "publishing", "workflows", "agents", "observability"];
|
|
12
|
+
export declare const RECIPE_PRIMITIVES: readonly ["knowledge-graph", "recipes", "records", "tables", "messages", "posts", "signals", "dashboards", "geo", "ads", "tags", "sequences", "publishing", "workflows", "agents", "observability"];
|
|
13
13
|
export type RecipePrimitive = typeof RECIPE_PRIMITIVES[number];
|
|
14
14
|
export declare const RECIPE_PREREQUISITE_KINDS: readonly ["sender", "mailbox", "domain", "integration", "knowledge", "asset", "plan", "data"];
|
|
15
15
|
export type RecipePrerequisiteKind = typeof RECIPE_PREREQUISITE_KINDS[number];
|
|
@@ -118,28 +118,18 @@ export declare const AUTOMATION_STEP_CREDITS_REPRICING: RepricedValue<0.001 | 0.
|
|
|
118
118
|
* approved ceiling, so it starts with the price and not before.
|
|
119
119
|
*/
|
|
120
120
|
export declare const AUTOMATION_STEPS_COUNT_TOWARD_RUN_CAP_REPRICING: RepricedValue<boolean>;
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
* cycle's placement-test allowance, 100 -> 135 credits a month. Existing
|
|
124
|
-
* subscriptions pay the price in force at each renewal.
|
|
125
|
-
*/
|
|
126
|
-
export declare const DELIVERABILITY_SEAT_REPRICING: RepricedValue<100 | 135>;
|
|
121
|
+
/** EmailGuard monitoring per subscribed inbox-month, in credits, including its placement tests. */
|
|
122
|
+
export declare function deliverabilitySeatCredits(): number;
|
|
127
123
|
/**
|
|
128
124
|
* S30 (decision 3.6; flat literal, proposal P-29): one managed placement test
|
|
129
125
|
* past an inbox's included allowance, or on an inbox with no monitoring
|
|
130
126
|
* subscription, 16.6 -> 66 credits. Tests on your own EmailGuard key stay 0.
|
|
131
127
|
*/
|
|
132
128
|
export declare const PLACEMENT_TEST_REPRICING: RepricedValue<16.6 | 66>;
|
|
133
|
-
/** EmailGuard monitoring per subscribed inbox-month, in credits, at the price in force. */
|
|
134
|
-
export declare function deliverabilitySeatCredits(options?: RepricingOptions): number;
|
|
135
129
|
/** One managed placement test beyond the included allowance, in credits, at the price in force. */
|
|
136
130
|
export declare function placementTestCredits(options?: RepricingOptions): number;
|
|
137
|
-
/**
|
|
138
|
-
export declare
|
|
139
|
-
/** What a managed Google inbox costs a month, all-in: mailbox, connection and warm-up. */
|
|
140
|
-
export declare const MANAGED_INBOX_ALL_IN_REPRICING: RepricedValue<number>;
|
|
141
|
-
/** A managed Google inbox's monthly credits, all-in, at the switch state (marketing and docs). */
|
|
142
|
-
export declare function managedInboxAllInCredits(options?: RepricingOptions): number;
|
|
131
|
+
/** A managed inbox's committed monthly credits, all-in: the flat mailbox line plus its connection. */
|
|
132
|
+
export declare function managedInboxAllInCredits(): number;
|
|
143
133
|
/**
|
|
144
134
|
* S41 (decision 6.3): a provider call made with the customer's own API key
|
|
145
135
|
* (BYOK) pays a 0.05-credit platform fee, up from nothing. The vendor still
|
|
@@ -240,7 +240,8 @@ export const S20_RESERVATION_PRICE_RISES = [
|
|
|
240
240
|
unit: "credits_per_number_per_month",
|
|
241
241
|
description: "Monthly credit reservation for a connected WhatsApp number.",
|
|
242
242
|
before: 1_000,
|
|
243
|
-
|
|
243
|
+
// Decision 2.3 set 3,000; the founder made it 3,400, a LinkedIn account's price (2026-10-07).
|
|
244
|
+
after: 3_400,
|
|
244
245
|
}),
|
|
245
246
|
defineRepricedValue({
|
|
246
247
|
key: "seat.phone_number",
|
|
@@ -286,25 +287,16 @@ export const AUTOMATION_STEPS_COUNT_TOWARD_RUN_CAP_REPRICING = defineRepricedVal
|
|
|
286
287
|
before: false,
|
|
287
288
|
after: true,
|
|
288
289
|
});
|
|
289
|
-
// ---- S30 (
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
// `
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
key: "commitment.deliverability_unit",
|
|
300
|
-
kind: "price",
|
|
301
|
-
slice: "S30",
|
|
302
|
-
decision: "3.5",
|
|
303
|
-
unit: "credits_per_inbox_per_month",
|
|
304
|
-
description: "EmailGuard monitoring per subscribed inbox, including its included placement tests each cycle.",
|
|
305
|
-
before: 100,
|
|
306
|
-
after: SNAPSHOT_DELIVERABILITY_SEAT_CREDITS,
|
|
307
|
-
});
|
|
290
|
+
// ---- S30 (decision 3.6): the extra placement test on the 5x markup. -------
|
|
291
|
+
// The key is the pricing-seed charge key, so the seed row and the snapshot carry
|
|
292
|
+
// the new price, `after` reads it from the snapshot (one definition), and
|
|
293
|
+
// `repricedValue` holds the old price until the instant. EmailGuard monitoring
|
|
294
|
+
// itself rose 100 -> 135 here (decision 3.5) until the founder set it back to a
|
|
295
|
+
// round 100 on 2026-10-07, so nothing about it moves at the switch any more.
|
|
296
|
+
/** EmailGuard monitoring per subscribed inbox-month, in credits, including its placement tests. */
|
|
297
|
+
export function deliverabilitySeatCredits() {
|
|
298
|
+
return SNAPSHOT_DELIVERABILITY_SEAT_CREDITS;
|
|
299
|
+
}
|
|
308
300
|
/**
|
|
309
301
|
* S30 (decision 3.6; flat literal, proposal P-29): one managed placement test
|
|
310
302
|
* past an inbox's included allowance, or on an inbox with no monitoring
|
|
@@ -320,51 +312,23 @@ export const PLACEMENT_TEST_REPRICING = defineRepricedValue({
|
|
|
320
312
|
before: 16.6,
|
|
321
313
|
after: SNAPSHOT_PLACEMENT_TEST_CREDITS,
|
|
322
314
|
});
|
|
323
|
-
/** EmailGuard monitoring per subscribed inbox-month, in credits, at the price in force. */
|
|
324
|
-
export function deliverabilitySeatCredits(options = {}) {
|
|
325
|
-
return repricedValue(DELIVERABILITY_SEAT_REPRICING, options);
|
|
326
|
-
}
|
|
327
315
|
/** One managed placement test beyond the included allowance, in credits, at the price in force. */
|
|
328
316
|
export function placementTestCredits(options = {}) {
|
|
329
317
|
return repricedValue(PLACEMENT_TEST_REPRICING, options);
|
|
330
318
|
}
|
|
331
|
-
// ---- S32
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
export const MANAGED_MAILBOX_REPRICING = defineRepricedValue({
|
|
345
|
-
key: "commitment.managed_mailbox",
|
|
346
|
-
kind: "price",
|
|
347
|
-
slice: "S32",
|
|
348
|
-
decision: "3.1",
|
|
349
|
-
unit: "credits_per_inbox_per_month",
|
|
350
|
-
description: "The mailbox line of a managed Google inbox, a flat price. Its 100-credit mailbox connection, with warm-up included, is billed beside it.",
|
|
351
|
-
before: 300,
|
|
352
|
-
after: SNAPSHOT_MANAGED_MAILBOX_CREDITS,
|
|
353
|
-
});
|
|
354
|
-
/** What a managed Google inbox costs a month, all-in: mailbox, connection and warm-up. */
|
|
355
|
-
export const MANAGED_INBOX_ALL_IN_REPRICING = defineRepricedValue({
|
|
356
|
-
key: "managed_inbox.google_all_in_credits",
|
|
357
|
-
kind: "price",
|
|
358
|
-
slice: "S32",
|
|
359
|
-
decision: "3.1",
|
|
360
|
-
unit: "credits_per_inbox_per_month",
|
|
361
|
-
description: "A managed Google inbox, all-in: the mailbox plus its mailbox connection, warm-up included. Inbox placement is an optional add-on.",
|
|
362
|
-
before: 400,
|
|
363
|
-
after: SNAPSHOT_MANAGED_MAILBOX_CREDITS + SNAPSHOT_SENDING_MAILBOX_CREDITS,
|
|
364
|
-
});
|
|
365
|
-
/** A managed Google inbox's monthly credits, all-in, at the switch state (marketing and docs). */
|
|
366
|
-
export function managedInboxAllInCredits(options = {}) {
|
|
367
|
-
return repricedValue(MANAGED_INBOX_ALL_IN_REPRICING, options);
|
|
319
|
+
// ---- S32: a managed inbox, all-in. --------------------------------------
|
|
320
|
+
// Once the all-in price applies (`isManagedInboxAllInPriceActive` in
|
|
321
|
+
// @oxygen/integrations: the 2026-09 switch AND credit commitments billing
|
|
322
|
+
// `sending_mailbox` and `managed_mailbox`), a Google or Microsoft 365 mailbox sells
|
|
323
|
+
// at the pricing book's flat `commitment.managed_mailbox` line and an Azure tenant at
|
|
324
|
+
// its flat `commitment.managed_azure_tenant` (founder, 2026-10-07: one inbox price,
|
|
325
|
+
// a round tenant price). Each inbox also holds the 100-credit mailbox connection,
|
|
326
|
+
// warm-up included. Before it, a mailbox was priced from vendor cost and warm-up
|
|
327
|
+
// billed beside it: 300 + 100 for Google at the $2.50 contracted cost, the same 400
|
|
328
|
+
// a month, so nothing about the all-in total moves at the switch.
|
|
329
|
+
/** A managed inbox's committed monthly credits, all-in: the flat mailbox line plus its connection. */
|
|
330
|
+
export function managedInboxAllInCredits() {
|
|
331
|
+
return SNAPSHOT_MANAGED_MAILBOX_CREDITS + SNAPSHOT_SENDING_MAILBOX_CREDITS;
|
|
368
332
|
}
|
|
369
333
|
/**
|
|
370
334
|
* S41 (decision 6.3): a provider call made with the customer's own API key
|
|
@@ -611,10 +575,7 @@ export const REPRICING_2026_09_SCHEDULE = [
|
|
|
611
575
|
TOPUP_RATE_REPRICING,
|
|
612
576
|
...storageCutEntries(),
|
|
613
577
|
...S20_RESERVATION_PRICE_RISES,
|
|
614
|
-
DELIVERABILITY_SEAT_REPRICING,
|
|
615
578
|
PLACEMENT_TEST_REPRICING,
|
|
616
|
-
MANAGED_MAILBOX_REPRICING,
|
|
617
|
-
MANAGED_INBOX_ALL_IN_REPRICING,
|
|
618
579
|
EMAIL_MAILBOX_DAILY_CAP_MAXIMUM,
|
|
619
580
|
EMAIL_MAILBOX_OLD_DEFAULT_DAILY_CAP,
|
|
620
581
|
AUTOMATION_STEP_CREDITS_REPRICING,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The model tier each AI-column research-loop depth runs on, whatever tier the
|
|
3
|
+
* column stores. A routing fact, not a price: the credits a depth costs come from
|
|
4
|
+
* the pricing book (OXP-1.22.25 retires the committed price sheet), so this lives
|
|
5
|
+
* apart from every price.
|
|
6
|
+
*/
|
|
7
|
+
export declare const RESEARCH_DEPTH_MODEL_TIER: {
|
|
8
|
+
readonly standard: "low";
|
|
9
|
+
readonly deep: "medium";
|
|
10
|
+
};
|
|
11
|
+
export type ResearchLoopDepth = keyof typeof RESEARCH_DEPTH_MODEL_TIER;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The model tier each AI-column research-loop depth runs on, whatever tier the
|
|
3
|
+
* column stores. A routing fact, not a price: the credits a depth costs come from
|
|
4
|
+
* the pricing book (OXP-1.22.25 retires the committed price sheet), so this lives
|
|
5
|
+
* apart from every price.
|
|
6
|
+
*/
|
|
7
|
+
export const RESEARCH_DEPTH_MODEL_TIER = { standard: "low", deep: "medium" };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const OXYGEN_VERSION: string;
|
|
2
|
-
export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.
|
|
2
|
+
export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.922.14";
|