@oxygen-agent/cli 1.272.83 → 1.275.0
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/index.js +98 -11
- package/node_modules/@oxygen/shared/dist/billing.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/billing.js +5 -5
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1325,6 +1325,8 @@ export function createProgram() {
|
|
|
1325
1325
|
.option("--table-ids <ids>", "Comma-separated table ids to attach.")
|
|
1326
1326
|
.option("--deep-links <urls>", "Comma-separated https://oxygen-agent.com/... links.")
|
|
1327
1327
|
.option("--slack-permalink <url>", "Slack message permalink (https://*.slack.com/...) to attach as context.")
|
|
1328
|
+
.option("--slack-channel-id <id>", "Slack channel id (e.g. C0123ABC456) the report came from.")
|
|
1329
|
+
.option("--customer-workspace <label>", "Customer workspace (org name/slug) a forwarded report concerns.")
|
|
1328
1330
|
.option("--json", "Print a JSON envelope.")
|
|
1329
1331
|
.action(async (options) => {
|
|
1330
1332
|
await handleAsyncAction("support ticket create", options, () => requestOxygen("/api/cli/support/tickets", {
|
|
@@ -1370,6 +1372,32 @@ export function createProgram() {
|
|
|
1370
1372
|
}))
|
|
1371
1373
|
.addCommand(new Command("admin")
|
|
1372
1374
|
.description("Staff-only support triage commands.")
|
|
1375
|
+
.addCommand(new Command("file")
|
|
1376
|
+
.description("File a support ticket into a customer's workspace on their behalf (staff only).")
|
|
1377
|
+
.requiredOption("--organization <organization>", "Target organization id or slug the ticket belongs to.")
|
|
1378
|
+
.requiredOption("--subject <subject>", "One-line summary of the customer's request.")
|
|
1379
|
+
.option("--body <body>", "The customer's request in their words, plus any staff notes.")
|
|
1380
|
+
.option("--severity <severity>", "low | normal | high. Defaults to normal.")
|
|
1381
|
+
.option("--category <category>", "Optional category label, e.g. bug, feature, question.")
|
|
1382
|
+
.option("--source <source>", "Where the ticket originated. Only slack is supported today.")
|
|
1383
|
+
.option("--operation <operation>", "The operation/tool involved, if known.")
|
|
1384
|
+
.option("--error-code <code>", "The error envelope code, if known.")
|
|
1385
|
+
.option("--run-ids <ids>", "Comma-separated run ids to attach.")
|
|
1386
|
+
.option("--table-ids <ids>", "Comma-separated table ids to attach.")
|
|
1387
|
+
.option("--deep-links <urls>", "Comma-separated https://oxygen-agent.com/... links.")
|
|
1388
|
+
.option("--slack-permalink <url>", "Slack message permalink (https://*.slack.com/...) to attach as context.")
|
|
1389
|
+
.option("--slack-channel-id <id>", "Slack channel id (e.g. C0123ABC456) the report came from.")
|
|
1390
|
+
.option("--customer-workspace <label>", "Customer workspace label when --org is not the customer's own org.")
|
|
1391
|
+
.option("--json", "Print a JSON envelope.")
|
|
1392
|
+
.action(async (options) => {
|
|
1393
|
+
await handleAsyncAction("support admin file", options, () => requestOxygen("/api/cli/admin/support/tickets", {
|
|
1394
|
+
method: "POST",
|
|
1395
|
+
body: {
|
|
1396
|
+
...buildSupportTicketBody(options),
|
|
1397
|
+
organization: readOption(options.organization),
|
|
1398
|
+
},
|
|
1399
|
+
}));
|
|
1400
|
+
}))
|
|
1373
1401
|
.addCommand(new Command("list")
|
|
1374
1402
|
.description("List support tickets across all organizations (staff only).")
|
|
1375
1403
|
.option("--status <status>", "Filter by status.")
|
|
@@ -4643,6 +4671,52 @@ export function createProgram() {
|
|
|
4643
4671
|
...(options.approve ? { approve: true } : {}),
|
|
4644
4672
|
},
|
|
4645
4673
|
}));
|
|
4674
|
+
}))
|
|
4675
|
+
.addCommand(new Command("register")
|
|
4676
|
+
.description("STAFF: register a manually-purchased egress IP (e.g. IPRoyal ISP-dedicated) into this environment's inventory. Secrets never pass here — --credential-ref names the Doppler family EGRESS_CRED_<REF>_USERNAME/_PASSWORD, set separately in Doppler. Register, then `egress assign`, then enable EGRESS_POOL_ENABLED (pool mode fails closed for unassigned mailboxes).")
|
|
4677
|
+
.requiredOption("--host <host>", "Proxy hostname or IP — bare, no scheme/port/credentials.")
|
|
4678
|
+
.requiredOption("--port <port>", "Proxy port (1-65535).")
|
|
4679
|
+
.requiredOption("--credential-ref <ref>", "Doppler credential-family name (A-Z, 0-9, _), e.g. IPROYAL.")
|
|
4680
|
+
.option("--vendor <vendor>", "Vendor slug for inventory provenance.", "iproyal")
|
|
4681
|
+
.option("--protocol <protocol>", "Proxy protocol: http (default), https, or socks5.")
|
|
4682
|
+
.option("--tier <tier>", "shared (default) or dedicated (requires --dedicated-org).")
|
|
4683
|
+
.option("--dedicated-org <orgId>", "Organization id a dedicated-tier IP is reserved for.")
|
|
4684
|
+
.option("--session-label <label>", "Optional vendor session/order label for provenance.")
|
|
4685
|
+
.option("--json", "Print a JSON envelope.")
|
|
4686
|
+
.action(async (options) => {
|
|
4687
|
+
await handleAsyncAction("egress register", options, () => requestOxygen("/api/cli/egress/register", {
|
|
4688
|
+
method: "POST",
|
|
4689
|
+
body: {
|
|
4690
|
+
host: readOption(options.host),
|
|
4691
|
+
port: Number(readOption(options.port)),
|
|
4692
|
+
credential_ref: readOption(options.credentialRef),
|
|
4693
|
+
vendor: readOption(options.vendor),
|
|
4694
|
+
...(readOption(options.protocol) ? { protocol: readOption(options.protocol) } : {}),
|
|
4695
|
+
...(readOption(options.tier) ? { tier: readOption(options.tier) } : {}),
|
|
4696
|
+
...(readOption(options.dedicatedOrg) ? { dedicated_organization_id: readOption(options.dedicatedOrg) } : {}),
|
|
4697
|
+
...(readOption(options.sessionLabel) ? { session_label: readOption(options.sessionLabel) } : {}),
|
|
4698
|
+
},
|
|
4699
|
+
}));
|
|
4700
|
+
}))
|
|
4701
|
+
.addCommand(new Command("assign")
|
|
4702
|
+
.description("Assign sending mailboxes to inventoried egress IPs — least-loaded across the active pool, or pinned with --ip. Existing open assignments are kept (stable for life; use rotate to re-home a burned IP). Admin/owner role; no spend, 0 credits.")
|
|
4703
|
+
.option("--mailboxes <list>", "Comma-separated mailbox ids or addresses to assign.")
|
|
4704
|
+
.option("--all", "Assign every sending mailbox in the pool that lacks an open assignment.")
|
|
4705
|
+
.option("--ip <egressIpId>", "Pin the targeted mailboxes to this egress IP id (must be active and org-visible).")
|
|
4706
|
+
.option("--json", "Print a JSON envelope.")
|
|
4707
|
+
.action(async (options) => {
|
|
4708
|
+
await handleAsyncAction("egress assign", options, () => {
|
|
4709
|
+
const list = readOption(options.mailboxes);
|
|
4710
|
+
const mailboxes = list ? list.split(",").map((entry) => entry.trim()).filter(Boolean) : [];
|
|
4711
|
+
return requestOxygen("/api/cli/egress/assign", {
|
|
4712
|
+
method: "POST",
|
|
4713
|
+
body: {
|
|
4714
|
+
...(mailboxes.length > 0 ? { mailboxes } : {}),
|
|
4715
|
+
...(options.all ? { all: true } : {}),
|
|
4716
|
+
...(readOption(options.ip) ? { egress_ip_id: readOption(options.ip) } : {}),
|
|
4717
|
+
},
|
|
4718
|
+
});
|
|
4719
|
+
});
|
|
4646
4720
|
})));
|
|
4647
4721
|
program
|
|
4648
4722
|
.command("directory")
|
|
@@ -7405,31 +7479,35 @@ export function createProgram() {
|
|
|
7405
7479
|
await handleAsyncAction("mailboxes oauth-health", options, () => requestOxygen("/api/cli/mailboxes/oauth-health"));
|
|
7406
7480
|
}))
|
|
7407
7481
|
.addCommand(new Command("warmup")
|
|
7408
|
-
.description("Mailbox warmup via Instantly
|
|
7482
|
+
.description("Mailbox warmup via Instantly — BYOK over your connected Instantly account, or --billing-mode managed via the OXYGEN-managed Instantly workspace (both 0 Oxygen credits).")
|
|
7409
7483
|
.addCommand(new Command("enable")
|
|
7410
|
-
.description("Enable Instantly warmup for sending mailboxes and stamp each mailbox's warmup state. Targets the whole pool unless --mailboxes is given.")
|
|
7484
|
+
.description("Enable Instantly warmup for sending mailboxes and stamp each mailbox's warmup state. Targets the whole pool unless --mailboxes is given. Omit --billing-mode for automatic: BYOK when your Instantly is connected, else managed when enabled on the deployment.")
|
|
7411
7485
|
.option("--mailboxes <list>", "Comma-separated mailbox ids or addresses to warm. Omit to warm the whole pool.")
|
|
7412
|
-
.option("--connection <id>", "Instantly connection id. Defaults to the org's active Instantly connection.")
|
|
7486
|
+
.option("--connection <id>", "Instantly connection id (forces BYOK). Defaults to the org's active Instantly connection.")
|
|
7487
|
+
.option("--billing-mode <mode>", "byok = your Instantly connection; managed = the OXYGEN-managed Instantly workspace.")
|
|
7413
7488
|
.option("--dry-run", "Simulate without calling Instantly (mailboxes marked pending).")
|
|
7414
7489
|
.option("--json", "Print a JSON envelope.")
|
|
7415
7490
|
.action(async (options) => {
|
|
7416
7491
|
await handleAsyncAction("mailboxes warmup enable", options, () => {
|
|
7417
7492
|
const mailboxes = readCsvOption(options.mailboxes);
|
|
7418
7493
|
const connection = readOption(options.connection);
|
|
7494
|
+
const billingMode = readOption(options.billingMode);
|
|
7419
7495
|
return requestOxygen("/api/cli/mailboxes/warmup", {
|
|
7420
7496
|
method: "POST",
|
|
7421
7497
|
body: {
|
|
7422
7498
|
...(mailboxes.length > 0 ? { mailboxes } : {}),
|
|
7423
7499
|
...(connection ? { connection_id: connection } : {}),
|
|
7500
|
+
...(billingMode ? { billing_mode: billingMode } : {}),
|
|
7424
7501
|
...(options.dryRun ? { dry_run: true } : {}),
|
|
7425
7502
|
},
|
|
7426
7503
|
});
|
|
7427
7504
|
});
|
|
7428
7505
|
}))
|
|
7429
7506
|
.addCommand(new Command("status")
|
|
7430
|
-
.description("Sync Instantly's warmup analytics into the pool, updating each mailbox's warmup state. Targets the whole pool unless --mailboxes is given.")
|
|
7507
|
+
.description("Sync Instantly's warmup analytics into the pool, updating each mailbox's warmup state. Targets the whole pool unless --mailboxes is given. Omit --billing-mode for automatic: BYOK when connected, else managed when enabled.")
|
|
7431
7508
|
.option("--mailboxes <list>", "Comma-separated mailbox ids or addresses to sync. Omit to sync the whole pool.")
|
|
7432
|
-
.option("--connection <id>", "Instantly connection id. Defaults to the org's active Instantly connection.")
|
|
7509
|
+
.option("--connection <id>", "Instantly connection id (forces BYOK). Defaults to the org's active Instantly connection.")
|
|
7510
|
+
.option("--billing-mode <mode>", "byok = your Instantly connection; managed = the OXYGEN-managed Instantly workspace.")
|
|
7433
7511
|
.option("--dry-run", "Skip the Instantly call (mailboxes marked pending).")
|
|
7434
7512
|
.option("--json", "Print a JSON envelope.")
|
|
7435
7513
|
.action(async (options) => {
|
|
@@ -7441,6 +7519,9 @@ export function createProgram() {
|
|
|
7441
7519
|
const connection = readOption(options.connection);
|
|
7442
7520
|
if (connection)
|
|
7443
7521
|
params.set("connection_id", connection);
|
|
7522
|
+
const billingMode = readOption(options.billingMode);
|
|
7523
|
+
if (billingMode)
|
|
7524
|
+
params.set("billing_mode", billingMode);
|
|
7444
7525
|
if (options.dryRun)
|
|
7445
7526
|
params.set("dry_run", "true");
|
|
7446
7527
|
const suffix = params.toString();
|
|
@@ -7497,14 +7578,15 @@ export function createProgram() {
|
|
|
7497
7578
|
await handleAsyncAction("mailboxes order-status", options, () => requestOxygen(`/api/cli/mailboxes/orders/${encodeURIComponent(order)}`));
|
|
7498
7579
|
})));
|
|
7499
7580
|
program.addCommand(new Command("deliverability")
|
|
7500
|
-
.description("External email deliverability: fleet reputation health and DIRECTIONAL inbox-placement (spam) tests. Placement tests are approval-gated paid runs (managed
|
|
7581
|
+
.description("External email deliverability: fleet reputation health and DIRECTIONAL inbox-placement (spam) tests via EmailGuard or Zapmail. Placement tests are approval-gated paid runs (managed bills Oxygen credits; BYOK = 0 Oxygen credits — Zapmail BYOK bills your Zapmail wallet ~$2/test); fail closed with 409 when no health provider is connected.")
|
|
7501
7582
|
.addCommand(new Command("placement-test")
|
|
7502
7583
|
.description("Directional inbox-placement (spam) tests: run, list, and get. Results estimate inbox-vs-spam landing from seed inboxes.")
|
|
7503
7584
|
.addCommand(new Command("run")
|
|
7504
|
-
.description("Start a placement test for one sending mailbox. Without --approved this returns a PREVIEW (billing mode + credits_required). Re-run with --approved and --max-credits >= credits_required to send.")
|
|
7585
|
+
.description("Start a placement test for one sending mailbox. Without --approved this returns a PREVIEW (billing mode + credits_required). Re-run with --approved and --max-credits >= credits_required to send. Zapmail runs test Zapmail-hosted mailboxes ONLY, compose their own probe (subject/body ignored), and complete async (2-24h).")
|
|
7505
7586
|
.argument("<mailbox>", "Sending mailbox address to test (e.g. ada@send.acme.com).")
|
|
7506
|
-
.option("--
|
|
7507
|
-
.option("--
|
|
7587
|
+
.option("--provider <provider>", "Health provider: emailguard or zapmail. Omit to auto-resolve (Zapmail-hosted mailboxes route to zapmail, else emailguard).")
|
|
7588
|
+
.option("--subject <subject>", "Optional subject for the seed message (zapmail ignores it beyond labeling the test).")
|
|
7589
|
+
.option("--body <text>", "Optional plain-text body for the seed message (ignored by zapmail).")
|
|
7508
7590
|
.option("--approved", "Actually run the test (otherwise a preview is returned).")
|
|
7509
7591
|
.option("--max-credits <n>", "Credit cap the caller accepts (must be >= credits_required for managed runs).")
|
|
7510
7592
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -7513,6 +7595,7 @@ export function createProgram() {
|
|
|
7513
7595
|
method: "POST",
|
|
7514
7596
|
body: {
|
|
7515
7597
|
mailbox,
|
|
7598
|
+
...(readOption(options.provider) ? { provider: readOption(options.provider) } : {}),
|
|
7516
7599
|
...(readOption(options.subject) ? { subject: readOption(options.subject) } : {}),
|
|
7517
7600
|
...(readOption(options.body) ? { body_text: readOption(options.body) } : {}),
|
|
7518
7601
|
...(options.approved ? { approved: true } : {}),
|
|
@@ -7521,7 +7604,7 @@ export function createProgram() {
|
|
|
7521
7604
|
}));
|
|
7522
7605
|
}))
|
|
7523
7606
|
.addCommand(new Command("list")
|
|
7524
|
-
.description("List recent directional inbox-placement tests with status, billing mode, seed set, score, and credits used.")
|
|
7607
|
+
.description("List recent directional inbox-placement tests with status, health provider, billing mode, seed set, score, and credits used.")
|
|
7525
7608
|
.option("--limit <n>", "Max rows (default 50, cap 200).")
|
|
7526
7609
|
.option("--json", "Print a JSON envelope.")
|
|
7527
7610
|
.action(async (options) => {
|
|
@@ -7531,7 +7614,7 @@ export function createProgram() {
|
|
|
7531
7614
|
});
|
|
7532
7615
|
}))
|
|
7533
7616
|
.addCommand(new Command("get")
|
|
7534
|
-
.description("Get one directional inbox-placement test by id — status, seed inboxes, per-provider results, and score.")
|
|
7617
|
+
.description("Get one directional inbox-placement test by id — status, health provider, seed inboxes, per-provider results, and score. Zapmail results land async (2-24h); keep polling while status is awaiting_results.")
|
|
7535
7618
|
.argument("<id>", "Placement test id.")
|
|
7536
7619
|
.option("--json", "Print a JSON envelope.")
|
|
7537
7620
|
.action(async (id, options) => {
|
|
@@ -12176,6 +12259,10 @@ function buildSupportTicketBody(options) {
|
|
|
12176
12259
|
context.error_code = readOption(options.errorCode);
|
|
12177
12260
|
if (readOption(options.slackPermalink))
|
|
12178
12261
|
context.slack_permalink = readOption(options.slackPermalink);
|
|
12262
|
+
if (readOption(options.slackChannelId))
|
|
12263
|
+
context.slack_channel_id = readOption(options.slackChannelId);
|
|
12264
|
+
if (readOption(options.customerWorkspace))
|
|
12265
|
+
context.customer_workspace = readOption(options.customerWorkspace);
|
|
12179
12266
|
const runIds = readCsvOption(options.runIds);
|
|
12180
12267
|
const tableIds = readCsvOption(options.tableIds);
|
|
12181
12268
|
const deepLinks = readCsvOption(options.deepLinks);
|
|
@@ -119,7 +119,7 @@ export declare const BASE_PRICING_PLANS: {
|
|
|
119
119
|
readonly description: "Custom procurement, invoicing, limits, and rollout support.";
|
|
120
120
|
readonly ctaLabel: "Talk to us";
|
|
121
121
|
readonly contactHref: "https://cal.com/tim-scheuer-mxbib9/45";
|
|
122
|
-
readonly features: readonly ["
|
|
122
|
+
readonly features: readonly ["Everything in Team", "Custom usage limits", "Volume pricing", "Custom invoicing and billing", "Dedicated support"];
|
|
123
123
|
};
|
|
124
124
|
};
|
|
125
125
|
export declare const PUBLIC_PLAN_ORDER: readonly PlanTier[];
|
|
@@ -126,11 +126,11 @@ export const BASE_PRICING_PLANS = {
|
|
|
126
126
|
ctaLabel: "Talk to us",
|
|
127
127
|
contactHref: CONTACT_SALES_URL,
|
|
128
128
|
features: [
|
|
129
|
-
"
|
|
130
|
-
"Custom
|
|
131
|
-
"
|
|
132
|
-
"Custom
|
|
133
|
-
"
|
|
129
|
+
"Everything in Team",
|
|
130
|
+
"Custom usage limits",
|
|
131
|
+
"Volume pricing",
|
|
132
|
+
"Custom invoicing and billing",
|
|
133
|
+
"Dedicated support",
|
|
134
134
|
],
|
|
135
135
|
},
|
|
136
136
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const OXYGEN_VERSION = "1.
|
|
1
|
+
export declare const OXYGEN_VERSION = "1.275.0";
|
|
2
2
|
export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.181.0";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const OXYGEN_VERSION = "1.
|
|
1
|
+
export const OXYGEN_VERSION = "1.275.0";
|
|
2
2
|
// Bump this only when deployed CLI/API contracts require a newer CLI.
|
|
3
3
|
// 1.181.0: paid table action runs and background columns run require
|
|
4
4
|
// approved=true in addition to max_credits; older CLIs cannot send the flag.
|