@oxygen-agent/cli 1.1013.38 → 1.1013.59

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 CHANGED
@@ -34,4 +34,4 @@ oxygen update
34
34
 
35
35
  For product documentation, visit https://oxygen-agent.com/docs. For support, visit https://oxygen-agent.com.
36
36
 
37
- Version: 1.1013.38
37
+ Version: 1.1013.59
@@ -113,6 +113,7 @@ const MUTATING_COMMANDS = new Set([
113
113
  // Creates an approval or Checkout link; a first plan's Checkout can start the
114
114
  // first-month offer window. The plan changes only after an admin confirms.
115
115
  "billing change",
116
+ "billing retain",
116
117
  // --approved records a domain's renewal exit, or with --revoke resumes renewals.
117
118
  "managed-inboxes exit",
118
119
  // A default preview is free; approval restores provider seats and billing.
package/dist/index.js CHANGED
@@ -11652,11 +11652,12 @@ Examples:
11652
11652
  }))
11653
11653
  .addCommand(new Command("cancel")
11654
11654
  .description("Turn off subscription renewal. For a yearly commitment paid monthly, remaining monthly payments continue through commitment_ends_at; the plan stays usable until then. Other plans end at their paid period or trial end with no further subscription renewal charge. This command costs no Oxygen credits. Separately funded external resources keep renewing; preview `workspace infrastructure-exit` to end those too. Prints the end date; undo before then with billing resume.")
11655
+ .option("--comment <text>", "Written cancellation feedback (1–2,000 characters).")
11655
11656
  .option("--json", "Print a JSON envelope.")
11656
11657
  .action(async (options) => {
11657
11658
  await handleAsyncAction("billing cancel", options, () => requestOxygen("/api/cli/billing/cancel", {
11658
11659
  method: "POST",
11659
- body: { action: "cancel" },
11660
+ body: { action: "cancel", ...(options.comment !== undefined ? { comment: options.comment } : {}) },
11660
11661
  }));
11661
11662
  }))
11662
11663
  .addCommand(new Command("resume")
@@ -11667,6 +11668,19 @@ Examples:
11667
11668
  method: "POST",
11668
11669
  body: { action: "resume" },
11669
11670
  }));
11671
+ }))
11672
+ .addCommand(new Command("retention-offer")
11673
+ .description("Preview a one-month discount before cancelling your monthly subscription. Reports eligibility, the next invoice price and normal price. Reads only; no discount is applied.")
11674
+ .option("--json", "Print a JSON envelope.")
11675
+ .action(async (options) => {
11676
+ await handleAsyncAction("billing retention-offer", options, () => requestOxygen("/api/cli/billing/cancel", { method: "POST", body: { action: "offer" } }));
11677
+ }))
11678
+ .addCommand(new Command("retain")
11679
+ .description("Stay subscribed with the one-month retention discount from billing retention-offer. Restores renewal if cancellation was scheduled. No charge today; the normal price returns afterwards.")
11680
+ .requiredOption("--offer <id>", "The offer_id from the retention offer preview.")
11681
+ .option("--json", "Print a JSON envelope.")
11682
+ .action(async (options) => {
11683
+ await handleAsyncAction("billing retain", options, () => requestOxygen("/api/cli/billing/cancel", { method: "POST", body: { action: "retain", offer_id: options.offer } }));
11670
11684
  }))
11671
11685
  .addCommand(new Command("topup")
11672
11686
  .description("Buy a custom amount of on-demand credits. Run without an amount to see the current price per 100 credits (`usd_per_100_credits`), the allowed range and the packs; checkout happens in Stripe, the price is shown before you pay, and purchased credits never expire. Plan credits cost less. `usd_per_1k_credits` is a deprecated name for the same per-100 price, not a price per 1,000 credits.")
@@ -102,7 +102,7 @@ export const OXYGEN_CAPABILITY_ROUTES = [
102
102
  gatewayCommands: ["billing balance", "billing usage", "billing audit", "billing estimate", "budget list", "billing invoices", "pricing customer-credit-prices"],
103
103
  skills: ["oxygen-gtm", "oxygen-diagnostics"],
104
104
  endpointSections: ["billing", "budget", "limits", "pricing"],
105
- intentTerms: ["billing", "credits", "credit balance", "customer credit prices", "credit price catalog", "usage", "spend", "cost", "cost estimate", "monthly cost", "budget", "subscription", "invoice", "vat", "vat number", "tax id", "cancel plan", "change plan", "upgrade", "downgrade", "subscription plans", "annual plan", "yearly commitment", "yearly saving", "annual discount"],
105
+ intentTerms: ["billing", "credits", "credit balance", "customer credit prices", "credit price catalog", "usage", "spend", "cost", "cost estimate", "monthly cost", "budget", "subscription", "invoice", "vat", "vat number", "tax id", "cancel plan", "change plan", "upgrade", "downgrade", "subscription plans", "annual plan", "yearly commitment", "yearly saving", "annual discount", "retention offer", "cancellation reason", "winback discount"],
106
106
  },
107
107
  {
108
108
  id: "support-and-feedback",
@@ -1043,7 +1043,7 @@ function routeCardFor(card, query) {
1043
1043
  card = { ...card, posture: "read_only", execution: providerRead.execution };
1044
1044
  const spendRead = card.id === "billing-and-budgets" && !providerRead ? spendBreakdownRecommendation(query) : null;
1045
1045
  if (spendRead)
1046
- card = { ...card, posture: "read_only", execution: spendRead.execution };
1046
+ card = { ...card, posture: "mixed", execution: spendRead.execution };
1047
1047
  const blockRead = card.primitive === "sequences" ? sendingBlockReadRecommendation(query) : null;
1048
1048
  if (blockRead)
1049
1049
  card = { ...card, posture: "read_only", execution: blockRead.execution };
@@ -1512,10 +1512,24 @@ function tableRowRemovalRecommendation(query) {
1512
1512
  }
1513
1513
  /** Reads of grid values/state are separate from executing or resolving actions. */
1514
1514
  function tableReadRecommendation(query) {
1515
- if (!/\btables?\b/.test(query) || isFunctionIntent(query) || isSecondPartyDecisionIntent(query)
1515
+ if (isFunctionIntent(query) || isSecondPartyDecisionIntent(query)
1516
1516
  || /\b(workflows?|agents?|actions?|items?|retry|resolve|effects?|imports?|webhooks?|feeds?|enrich\w*|create|add|insert|upsert|update|delete|remove|rename|hide|archive|columns? run)\b/.test(query)
1517
1517
  || /\b(run|execute|start|cancel)\s+(?:(?:the|my|these)\s+)?(?:columns?|table|enrichment)\b/.test(query))
1518
1518
  return null;
1519
+ // An explicit order over existing labels reads rows; it does not classify
1520
+ // them or create a rank column. The column-only wording also names Tables.
1521
+ if (/\b(tables?|rows?|columns?)\b/.test(query)
1522
+ && /\b(sort(?:s|ed|ing)?|order(?:s|ed|ing)?|rank(?:s|ed|ing)?)\b/.test(query)
1523
+ && /\b(custom|explicit)\b/.test(query)
1524
+ && /\b(labels?|values?|priority|select|options?)\b/.test(query)
1525
+ && !/\b(classif\w*|categori[sz]\w*|tag(?:ging)?|assign|set|change|edit|reorder\w*|mov(?:e|es|ed|ing)|sav(?:e|es|ed|ing)|configur(?:e|es|ed|ing)|calculat(?:e|es|ed|ing)|scor(?:e|es|ed|ing)|enroll\w*|send\w*|sequences?|campaigns?)\b/.test(query)
1526
+ && !/\b(do not|don't|avoid|without)\s+(sort|order|rank)\w*\b/.test(query))
1527
+ return {
1528
+ tools: ["oxygen_tables_query", "oxygen_tables_describe"], commands: ["tables query", "tables describe"],
1529
+ execution: "Raw tables query supports sorts[].valueOrder (alias value_order) for an explicit label order. Inspect the Table's column keys and query schema first. Values are trimmed/lowercased and deduplicated; asc puts listed values first and unlisted/null last, desc reverses. An empty list uses ordinary sorting. Keep the same sorts when following its cursor. format=grid rejects sorts; rows-page and saved-view sort formats have separate schemas. This read does not classify rows or run columns.",
1530
+ };
1531
+ if (!/\btables?\b/.test(query))
1532
+ return null;
1519
1533
  if (/\bcells?\b/.test(query) && /\b(history|changes?|provenance)\b/.test(query))
1520
1534
  return {
1521
1535
  tools: ["oxygen_tables_cell_history", "oxygen_tables_cell_inspect"], commands: ["cells history", "cells inspect"],
@@ -1763,7 +1777,7 @@ function spendBreakdownRecommendation(query) {
1763
1777
  return null;
1764
1778
  return {
1765
1779
  tools: ["oxygen_billing_audit", "oxygen_billing_usage"], commands: ["billing audit", "billing usage"],
1766
- execution: "Read where managed credits went with oxygen_billing_audit: spend_by_category ranks each area's credits and share of managed_credits_spent, largest first, over the whole window; group_by provider, tool, model, run or workspace narrows it. Spent is reserved minus released in the window; it differs from captured (oxygen_billing_usage's managed_credits_used) by holds still open and holds settling across the window edge, so do not attribute the whole gap to open holds. External MCP uses oxygen_capabilities_call; built-in agents invoke the native capability. Reads cost 0 credits.",
1780
+ execution: "Read where managed credits went with oxygen_billing_audit: spend_by_category ranks each area's credits and share of managed_credits_spent, largest first, over the whole window; group_by provider, tool, model, run or workspace narrows it. Spent is reserved minus released in the window; it differs from captured (oxygen_billing_usage's managed_credits_used) by holds still open and holds settling across the window edge, so do not attribute the whole gap to open holds. External MCP uses oxygen_capabilities_call; built-in agents invoke the native capability. Reports cost 0 credits; billing audit may apply due plan grants or credit expiry.",
1767
1781
  };
1768
1782
  }
1769
1783
  function sendingBlockReadRecommendation(query) {
@@ -1789,10 +1803,16 @@ function isSpintaxIntent(query) {
1789
1803
  return /\b(wording|copy|message|draft|subject(?: line)?)\b.{0,45}\b(variations?|variants?|paraphrase|rewrite)\b/.test(query)
1790
1804
  || /\b(paraphrase|rewrite|variations?)\b.{0,45}\b(wording|copy|message|draft|subject(?: line)?)\b/.test(query);
1791
1805
  }
1806
+ function isSubscriptionRetentionIntent(query) {
1807
+ return /\b(retention offer|win[ -]?back discount|cancellation (?:reason|feedback)|written cancellation)\b/.test(query)
1808
+ || /\b(stay|cancel|cancelling)\b/.test(query) && /\b(discount|next month|subscription reason)\b/.test(query);
1809
+ }
1792
1810
  function explicitCapabilityIntent(query) {
1793
1811
  // Importing an AI answer is GEO evidence, rather than a Table file import.
1794
1812
  if (/\b(?:geo|aeo|ai (?:(?:search|answer) )?visibility|consumer ai answers?|answer engine optimization|generative engine optimization)\b/.test(query))
1795
1813
  return ROUTE_BY_ID.get("geo") ?? null;
1814
+ if (isSubscriptionRetentionIntent(query))
1815
+ return ROUTE_BY_ID.get("billing-and-budgets") ?? null;
1796
1816
  if (isConnectionPriceIntent(query))
1797
1817
  return ROUTE_BY_ID.get("billing-and-budgets") ?? null;
1798
1818
  if (sentLinkedInInvitationReadRecommendation(query))
@@ -2142,6 +2162,9 @@ function recommendationsFor(card, query) {
2142
2162
  const spendRead = card.id === "billing-and-budgets" ? spendBreakdownRecommendation(query) : null;
2143
2163
  if (spendRead)
2144
2164
  return spendRead;
2165
+ if (card.id === "billing-and-budgets" && isSubscriptionRetentionIntent(query)) {
2166
+ return { tools: ["oxygen_billing_cancel"], commands: ["billing retention-offer", "billing cancel", "billing retain"] };
2167
+ }
2145
2168
  if (card.id === "billing-and-budgets" && isConnectionPriceIntent(query)) {
2146
2169
  return {
2147
2170
  tools: ["oxygen_billing_commitments"],
@@ -1 +1 @@
1
- export declare const OXYGEN_BUILD_VERSION = "1.1013.38";
1
+ export declare const OXYGEN_BUILD_VERSION = "1.1013.59";
@@ -1,2 +1,2 @@
1
1
  // GENERATED by scripts/ci/version-stamp.mjs from VERSION + git history. Do not edit; do not commit.
2
- export const OXYGEN_BUILD_VERSION = "1.1013.38";
2
+ export const OXYGEN_BUILD_VERSION = "1.1013.59";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxygen-agent/cli",
3
- "version": "1.1013.38",
3
+ "version": "1.1013.59",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",