@oxygen-agent/cli 1.1014.619 → 1.1014.771

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 (65) hide show
  1. package/README.md +1 -1
  2. package/dist/command-manifest.js +15 -0
  3. package/dist/command-support.d.ts +5 -5
  4. package/dist/command-support.js +7 -7
  5. package/dist/commands/billing.js +12 -6
  6. package/dist/commands/columns.js +2 -2
  7. package/dist/commands/companies.js +1 -1
  8. package/dist/commands/copilot.js +1 -1
  9. package/dist/commands/dashboards.js +1 -1
  10. package/dist/commands/enrich-column.js +2 -2
  11. package/dist/commands/find.js +2 -2
  12. package/dist/commands/mailboxes.js +36 -0
  13. package/dist/commands/recipes.js +1 -1
  14. package/dist/commands/sequences.js +6 -6
  15. package/dist/commands/tables.js +1 -1
  16. package/dist/commands/verify.js +112 -11
  17. package/dist/http-client.js +1 -70
  18. package/dist/index.js +1 -1
  19. package/dist/refactor-internals/binary-download.d.ts +5 -0
  20. package/dist/refactor-internals/binary-download.js +71 -0
  21. package/node_modules/@oxygen/formula/dist/evaluate.js +2 -82
  22. package/node_modules/@oxygen/formula/dist/refactor-internals/novelty-score.d.ts +2 -0
  23. package/node_modules/@oxygen/formula/dist/refactor-internals/novelty-score.js +87 -0
  24. package/node_modules/@oxygen/shared/dist/billing.d.ts +15 -3
  25. package/node_modules/@oxygen/shared/dist/billing.js +19 -7
  26. package/node_modules/@oxygen/shared/dist/cancellation-reasons.d.ts +35 -0
  27. package/node_modules/@oxygen/shared/dist/cancellation-reasons.js +21 -0
  28. package/node_modules/@oxygen/shared/dist/capability-discovery.js +27 -1
  29. package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +6 -6
  30. package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +1 -1
  31. package/node_modules/@oxygen/shared/dist/contracts/limits-read.js +1 -0
  32. package/node_modules/@oxygen/shared/dist/contracts/teammates.js +41 -17
  33. package/node_modules/@oxygen/shared/dist/email-verification-batch.d.ts +26 -0
  34. package/node_modules/@oxygen/shared/dist/email-verification-batch.js +55 -0
  35. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +3 -3
  36. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +3 -3
  37. package/node_modules/@oxygen/shared/dist/knowledge-brain-draft.d.ts +70 -0
  38. package/node_modules/@oxygen/shared/dist/knowledge-brain-draft.js +42 -0
  39. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +1 -1
  40. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +1 -1
  41. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +3 -1
  42. package/node_modules/@oxygen/shared/dist/product-doctrine.js +1 -1
  43. package/node_modules/@oxygen/shared/dist/sequence-internals/esp-policy.d.ts +225 -0
  44. package/node_modules/@oxygen/shared/dist/sequence-internals/esp-policy.js +578 -0
  45. package/node_modules/@oxygen/shared/dist/sequences.d.ts +1 -226
  46. package/node_modules/@oxygen/shared/dist/sequences.js +2 -576
  47. package/node_modules/@oxygen/shared/dist/teammate-groups.d.ts +103 -24
  48. package/node_modules/@oxygen/shared/dist/teammate-groups.js +125 -32
  49. package/node_modules/@oxygen/shared/dist/teammate-messages.d.ts +1 -1
  50. package/node_modules/@oxygen/shared/dist/teammates.d.ts +28 -2
  51. package/node_modules/@oxygen/shared/dist/teammates.js +32 -2
  52. package/node_modules/@oxygen/shared/dist/user-capability-routing.js +40 -8
  53. package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
  54. package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
  55. package/node_modules/@oxygen/workflows/dist/graph/expression.d.ts +1 -16
  56. package/node_modules/@oxygen/workflows/dist/graph/expression.js +4 -224
  57. package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +2 -2
  58. package/node_modules/@oxygen/workflows/dist/index.d.ts +1 -63
  59. package/node_modules/@oxygen/workflows/dist/index.js +1 -193
  60. package/node_modules/@oxygen/workflows/dist/refactor-internals/condition-comparison.d.ts +18 -0
  61. package/node_modules/@oxygen/workflows/dist/refactor-internals/condition-comparison.js +222 -0
  62. package/node_modules/@oxygen/workflows/dist/refactor-internals/execution-policy.d.ts +64 -0
  63. package/node_modules/@oxygen/workflows/dist/refactor-internals/execution-policy.js +204 -0
  64. package/node_modules/@oxygen/workflows/package.json +4 -0
  65. package/package.json +1 -1
@@ -89,231 +89,7 @@ export declare const SEQUENCE_EMAIL_COLUMN_KEYS: readonly ["email", "email_addre
89
89
  * Returns the trimmed raw value (callers normalize/lowercase as needed) or null.
90
90
  */
91
91
  export declare function recipientEmailFromRow(rowValues: Record<string, unknown> | null | undefined, emailColumnKey?: string | null): string | null;
92
- /**
93
- * ESP (email service provider) MATCHING mode for a sequence (settings.esp_matching).
94
- * Deliverability lore: a send lands better when the SENDING mailbox and the
95
- * RECIPIENT sit on the same provider (Google→Google, Microsoft→Microsoft), so at
96
- * mailbox-pick the dispatcher can bias rotation toward a same-ESP mailbox.
97
- * - "off" — no ESP bias; rotation is pure LRU / domain-spread.
98
- * - "prefer" — (DEFAULT) pick a same-ESP mailbox when one is available, else
99
- * fall back to any sendable mailbox (never blocks a send). On by default
100
- * because it only ever improves deliverability and cannot starve sends.
101
- * - "strict" — require a same-ESP mailbox; when none is available the action is
102
- * DEFERRED with a visible skipped_reason rather than sent cross-provider.
103
- * Power-user setting, reachable via CLI/MCP; the web "Provider Matching"
104
- * checkbox toggles off↔prefer only.
105
- */
106
- export declare const ESP_MATCHING_MODES: readonly ["off", "prefer", "strict"];
107
- export type EspMatchingMode = (typeof ESP_MATCHING_MODES)[number];
108
- export declare const DEFAULT_ESP_MATCHING_MODE: EspMatchingMode;
109
- export declare function isEspMatchingMode(value: unknown): value is EspMatchingMode;
110
- /**
111
- * Validate settings.esp_matching before persistence. Absent/null is valid and
112
- * means DEFAULT_ESP_MATCHING_MODE, which is "prefer" — an unset sequence still
113
- * biases rotation toward a same-provider sender, so a workspace whose senders on
114
- * one provider are in bad standing concentrates that provider's recipients on
115
- * them until an operator sets "off". Any other value must be one of the three
116
- * modes. Pure; throws OxygenError("invalid_sequence_settings") on a bad value so
117
- * the CLI / MCP / API report an identical error. Called from the tenant-db
118
- * settings validator alongside the budget/prioritization checks.
119
- */
120
- export declare function validateEspMatchingSetting(value: unknown): void;
121
- /**
122
- * The MATCHABLE email-provider a recipient routes through — the narrow set ESP
123
- * matching can act on. Kept intentionally aligned with EMAIL_MAILBOX_PROVIDERS in
124
- * tenant-db so a mailbox's `provider` and a resolved recipient ESP compare
125
- * directly: we can only bias rotation toward a provider we can actually SEND
126
- * from, and the pool is Google/Microsoft only.
127
- *
128
- * This is deliberately NARROWER than RECIPIENT_ESP_FAMILIES (what we DISPLAY).
129
- * A domain behind Proofpoint has family "proofpoint" but may still be matchable
130
- * as "microsoft" — see resolveEspFamily.
131
- */
132
- export declare const RECIPIENT_ESPS: readonly ["google", "microsoft"];
133
- export type RecipientEsp = (typeof RECIPIENT_ESPS)[number];
134
- /**
135
- * WEIGHTED SENDER ROUTING — the object form of settings.esp_matching.
136
- *
137
- * The three scalar modes above answer one question ("bias toward the recipient's
138
- * own provider, yes or no"), and they bake in the assumption that same-provider
139
- * is always better. That assumption fails whenever one provider's senders are in
140
- * bad standing: a workspace whose Google-hosted domains are refused by Gmail
141
- * wants its Google-hosted RECIPIENTS served from Microsoft senders, which no
142
- * scalar mode can express. "off" does not express it either, because free
143
- * rotation still hands Google recipients a Google sender in proportion to the
144
- * pool.
145
- *
146
- * So the object form states the routing directly, as SEND SHARES per recipient
147
- * provider:
148
- *
149
- * { mode: "prefer",
150
- * routes: { google: { microsoft: 100 }, microsoft: { microsoft: 100 } },
151
- * exclude: [{ domain: "burned.example", from_recipients: ["google"] }] }
152
- *
153
- * `routes` is keyed by the RECIPIENT's resolved provider; the inner map is the
154
- * SENDER provider. Weights are relative shares, so { google: 3, microsoft: 1 }
155
- * and { google: 75, microsoft: 25 } are the same policy and nothing has to sum
156
- * to 100. An omitted weight is zero. A bucket whose entry is explicitly present
157
- * but carries no positive weight means "no opinion, rotate freely for this
158
- * recipient class"; a bucket the operator never mentioned keeps the historical
159
- * same-provider default, so editing Google routing cannot silently change how
160
- * Microsoft recipients are served.
161
- *
162
- * `exclude` is a hard never, not a preference: a sender domain listed here is
163
- * removed from the candidate pool for the named recipient buckets (all buckets
164
- * when `from_recipients` is absent) in EVERY mode, including "off", and it
165
- * survives the prefer-fallback. A deliverability guard that a matching toggle
166
- * could disarm would not be a guard.
167
- *
168
- * The scalar modes remain valid values and are read as policies, so there is one
169
- * routing code path rather than two: "prefer" becomes { mode: "prefer" } with no
170
- * routes, which resolves to the same-provider default and behaves exactly as it
171
- * did before.
172
- */
173
- export declare const ESP_ROUTE_BUCKETS: readonly ["google", "microsoft", "unknown"];
174
- /** The RECIPIENT side of a route: a matchable provider, or "unknown" when resolution failed. */
175
- export type EspRouteBucket = (typeof ESP_ROUTE_BUCKETS)[number];
176
- /** The SENDER side of a route: relative send shares per mailbox provider. */
177
- export type EspRouteWeights = Partial<Record<RecipientEsp, number>>;
178
- export type EspSenderExclusion = {
179
- domain: string;
180
- from_recipients?: EspRouteBucket[];
181
- };
182
- export type EspRoutingPolicy = {
183
- mode?: EspMatchingMode;
184
- routes?: Partial<Record<EspRouteBucket, EspRouteWeights>>;
185
- exclude?: EspSenderExclusion[];
186
- };
187
- /** settings.esp_matching accepts either the legacy scalar or the routing policy. */
188
- export type EspMatchingSetting = EspMatchingMode | EspRoutingPolicy;
189
- /**
190
- * A policy with every field present, which is what the dispatcher and the launch
191
- * preview consume. Produced only by espPolicyFromSetting so both surfaces answer
192
- * identically from the same stored value.
193
- */
194
- export type ResolvedEspPolicy = {
195
- mode: EspMatchingMode;
196
- routes: Partial<Record<EspRouteBucket, EspRouteWeights>>;
197
- exclude: Array<{
198
- domain: string;
199
- buckets: readonly EspRouteBucket[];
200
- }>;
201
- };
202
- /** Cap on settings.esp_matching.exclude — a routing policy, not a suppression list. */
203
- export declare const MAX_ESP_SENDER_EXCLUSIONS = 50;
204
- /** Upper bound on a single route weight; relative shares never need more. */
205
- export declare const MAX_ESP_ROUTE_WEIGHT = 1000000;
206
- export declare function isEspRouteBucket(value: unknown): value is EspRouteBucket;
207
- /**
208
- * A sending domain as the mailbox table stores it: lowercase, no leading "@".
209
- * Mirrors lower(split_part(email_address, '@', 2)) in pickEmailMailbox so an
210
- * exclusion the operator typed as "@Burned.Example " still matches.
211
- */
212
- export declare function normalizeEspSenderDomain(value: string): string;
213
- /**
214
- * LENIENT read of a persisted settings.esp_matching (never throws — a read must
215
- * not break a send). Absent, null, or malformed reads as the default policy, and
216
- * a malformed FIELD bails the WHOLE object rather than half-applying a routing
217
- * policy, which is the readMailboxRampConfig convention in tenant-db. The strict
218
- * counterpart that guards the write path is validateEspMatchingSetting.
219
- */
220
- export declare function espPolicyFromSetting(value: unknown): ResolvedEspPolicy;
221
- /**
222
- * The effective send shares for one recipient bucket. An explicitly-present
223
- * entry wins even when it is empty or all-zero (that is the operator saying
224
- * "rotate freely here"); a bucket that was never mentioned keeps the historical
225
- * same-provider default, and "unknown" has no same-provider to default to.
226
- */
227
- export declare function espRouteWeightsFor(policy: ResolvedEspPolicy, bucket: EspRouteBucket): EspRouteWeights;
228
- /**
229
- * The sender providers to try, best first, for one recipient bucket — a
230
- * deterministic weighted shuffle WITHOUT replacement.
231
- *
232
- * Returning an ORDER rather than a single draw is what makes "prefer" correct:
233
- * a 90/10 Google policy over a pool holding no Google mailbox must send 100%
234
- * from Microsoft, not defer and not fall through to provider-blind rotation.
235
- * An empty result means "no opinion" and the caller rotates freely.
236
- *
237
- * Deterministic by construction: the seed carries the enrollment and step, never
238
- * a clock or Math.random, so a dry-run preview and the later live send choose
239
- * the same provider, and a replan after a defer re-derives the same route.
240
- * Candidates are enumerated in RECIPIENT_ESPS order rather than object-key
241
- * order, because jsonb does not preserve key order and a policy that round-trips
242
- * through the database must not reroute the fleet.
243
- */
244
- export declare function espRouteCandidates(input: {
245
- policy: ResolvedEspPolicy;
246
- recipient: EspRouteBucket;
247
- seed: string;
248
- }): RecipientEsp[];
249
- /**
250
- * Sending domains that must not serve this recipient bucket, normalized and
251
- * de-duplicated for pickEmailMailbox. Applies in every mode and survives the
252
- * prefer-fallback — see the exclude contract above.
253
- */
254
- export declare function espExcludedSenderDomains(policy: ResolvedEspPolicy, bucket: EspRouteBucket): string[];
255
- /**
256
- * The DISPLAY taxonomy: the mail-infrastructure family a recipient domain sits
257
- * on. Wider than RecipientEsp because "everything that isn't Google or Microsoft"
258
- * is not one thing — a list that is 23% Proofpoint is a very different
259
- * deliverability problem from one that is 23% self-hosted, and collapsing both to
260
- * null (today's behavior) hides that. Split into three groups:
261
- *
262
- * - MAILBOX providers (google, microsoft) — imply a matchable ESP.
263
- * - GATEWAY vendors (proofpoint, mimecast, ...) — security filters that sit IN
264
- * FRONT of a mailbox provider. Their MX tells you the filter, NOT where the
265
- * mailbox lives; the SPF fallback is what sees behind them.
266
- * - OTHER mailbox hosts (zoho, yahoo, fastmail, ...) and self_hosted — real
267
- * destinations we simply cannot send as, so never matchable.
268
- */
269
- export declare const RECIPIENT_ESP_FAMILIES: readonly ["google", "microsoft", "proofpoint", "mimecast", "barracuda", "cisco", "zscaler", "trendmicro", "sophos", "zoho", "yahoo", "apple", "proton", "fastmail", "gmx", "amazon", "self_hosted"];
270
- export type RecipientEspFamily = (typeof RECIPIENT_ESP_FAMILIES)[number];
271
- export declare function isRecipientEspFamily(value: unknown): value is RecipientEspFamily;
272
- export declare function isEspGatewayFamily(family: RecipientEspFamily | null | undefined): boolean;
273
- /**
274
- * The matchable ESP a display family implies, or null when the family is a
275
- * gateway (unknown until SPF) or a provider we cannot send as. The ONLY place
276
- * family → esp is decided, so display and matching can't drift.
277
- */
278
- export declare function matchableEspFromFamily(family: RecipientEspFamily | null | undefined): RecipientEsp | null;
279
- /**
280
- * Map a domain's resolved MX exchange hostnames to a DISPLAY family. Returns null
281
- * when no host matches any known vendor — the caller records that as
282
- * "self_hosted" only once it is sure the lookup itself succeeded (an empty/failed
283
- * answer is "unknown", which is a different fact).
284
- */
285
- export declare function familyFromMxHosts(hosts: readonly string[] | null | undefined): RecipientEspFamily | null;
286
- /**
287
- * Resolve the matchable ESP from a domain's TXT records by reading its SPF
288
- * mechanisms. Scans every `v=spf1` record's include:/redirect= targets.
289
- *
290
- * AMBIGUITY IS NOT GUESSED: a domain mid-migration (or running Workspace
291
- * alongside an Office tenant) can include BOTH vendors. Returning either one
292
- * would be a coin flip that strict matching then acts on, so a both-match
293
- * degrades to null ("unknown") and the caller falls back / defers honestly.
294
- */
295
- export declare function espFromSpfRecords(records: readonly string[] | null | undefined): RecipientEsp | null;
296
- /**
297
- * Infer a recipient's DISPLAY family from its domain string alone,
298
- * DETERMINISTICALLY, for the well-known consumer/freemail domains. Returns null
299
- * for any other domain — the caller then resolves via the cached MX (+ SPF)
300
- * lookup, because a custom domain fronted by Workspace / M365 / a gateway is not
301
- * decidable from the string. Pure: the single source of truth for the map.
302
- */
303
- export declare function inferRecipientEspFamily(domain: string | null | undefined): RecipientEspFamily | null;
304
- /**
305
- * Infer a recipient's MATCHABLE ESP from its domain string. Narrow by design:
306
- * only the Google/Microsoft consumer domains resolve here, everything else
307
- * (including yahoo/proton/icloud, which are real but unsendable-as) is null.
308
- * Unchanged contract — the dispatcher's fast path still calls this.
309
- */
310
- export declare function inferRecipientEsp(domain: string | null | undefined): RecipientEsp | null;
311
- /**
312
- * Back-compat narrow view of familyFromMxHosts: MX hosts → matchable ESP. Now
313
- * derived from the family table so the two can't drift, and gateway MX hosts
314
- * correctly yield null here (they need the SPF signal to become matchable).
315
- */
316
- export declare function espFromMxHosts(hosts: readonly string[] | null | undefined): RecipientEsp | null;
92
+ export { ESP_MATCHING_MODES, type EspMatchingMode, DEFAULT_ESP_MATCHING_MODE, isEspMatchingMode, validateEspMatchingSetting, RECIPIENT_ESPS, type RecipientEsp, ESP_ROUTE_BUCKETS, type EspRouteBucket, type EspRouteWeights, type EspSenderExclusion, type EspRoutingPolicy, type EspMatchingSetting, type ResolvedEspPolicy, MAX_ESP_SENDER_EXCLUSIONS, MAX_ESP_ROUTE_WEIGHT, isEspRouteBucket, normalizeEspSenderDomain, espPolicyFromSetting, espRouteWeightsFor, espRouteCandidates, espExcludedSenderDomains, RECIPIENT_ESP_FAMILIES, type RecipientEspFamily, isRecipientEspFamily, isEspGatewayFamily, matchableEspFromFamily, familyFromMxHosts, espFromSpfRecords, inferRecipientEspFamily, inferRecipientEsp, espFromMxHosts, } from "./sequence-internals/esp-policy.js";
317
93
  /**
318
94
  * row_values keys an enrollment's phone number may live under, in
319
95
  * send-precedence order, for WhatsApp sends. The enroll path resolves the FIRST
@@ -1284,4 +1060,3 @@ export declare function secondsSinceSendWindowStart(window: SequenceSendWindow,
1284
1060
  * never hand back an instant the gate would reject.
1285
1061
  */
1286
1062
  export declare function nextSendWindowOpenAt(window: SequenceSendWindow, now: Date, timezone?: string): Date | null;
1287
- export {};