@oxygen-agent/cli 1.987.20 → 1.1010.1

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 (176) hide show
  1. package/README.md +1 -1
  2. package/dist/admin-primary-providers-render.d.ts +0 -2
  3. package/dist/admin-primary-providers-render.js +1 -1
  4. package/dist/browser-login.js +1 -4
  5. package/dist/column-decision-options.d.ts +20 -0
  6. package/dist/column-decision-options.js +54 -0
  7. package/dist/command-manifest.d.ts +3 -2
  8. package/dist/command-manifest.js +25 -2
  9. package/dist/credentials.d.ts +1 -1
  10. package/dist/functions-commands.js +13 -9
  11. package/dist/help.d.ts +8 -0
  12. package/dist/help.js +46 -0
  13. package/dist/index.js +2751 -242
  14. package/dist/knowledge-mirror.d.ts +2 -2
  15. package/dist/runtime.d.ts +0 -15
  16. package/dist/runtime.js +1 -1
  17. package/dist/search-ai-filter-notice.d.ts +17 -0
  18. package/dist/search-ai-filter-notice.js +38 -0
  19. package/dist/session.d.ts +4 -3
  20. package/dist/skills.d.ts +8 -7
  21. package/dist/skills.js +58 -20
  22. package/dist/transcript.d.ts +2 -1
  23. package/dist/util.d.ts +10 -1
  24. package/dist/util.js +14 -2
  25. package/node_modules/@oxygen/cli-ugc/dist/commands.js +296 -140
  26. package/node_modules/@oxygen/cli-ugc/dist/field-parser.d.ts +9 -0
  27. package/node_modules/@oxygen/cli-ugc/dist/field-parser.js +34 -0
  28. package/node_modules/@oxygen/formula/dist/coerce.d.ts +10 -0
  29. package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
  30. package/node_modules/@oxygen/formula/dist/formula-functions.js +65 -0
  31. package/node_modules/@oxygen/formula/dist/hash.d.ts +19 -0
  32. package/node_modules/@oxygen/formula/dist/hash.js +199 -0
  33. package/node_modules/@oxygen/formula/dist/value-cleaners.d.ts +6 -1
  34. package/node_modules/@oxygen/formula/dist/value-cleaners.js +10 -26
  35. package/node_modules/@oxygen/recipe-sdk/dist/index.d.ts +13 -0
  36. package/node_modules/@oxygen/shared/dist/array-utils.d.ts +5 -0
  37. package/node_modules/@oxygen/shared/dist/array-utils.js +11 -0
  38. package/node_modules/@oxygen/shared/dist/billing.d.ts +99 -22
  39. package/node_modules/@oxygen/shared/dist/billing.js +195 -40
  40. package/node_modules/@oxygen/shared/dist/byok-connect.js +5 -0
  41. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +27 -0
  42. package/node_modules/@oxygen/shared/dist/capability-discovery.js +311 -28
  43. package/node_modules/@oxygen/shared/dist/cli-http-error.d.ts +8 -0
  44. package/node_modules/@oxygen/shared/dist/cli-http-error.js +8 -0
  45. package/node_modules/@oxygen/shared/dist/cli-result.js +1 -0
  46. package/node_modules/@oxygen/shared/dist/column-autofill.d.ts +52 -0
  47. package/node_modules/@oxygen/shared/dist/column-autofill.js +62 -0
  48. package/node_modules/@oxygen/shared/dist/column-decision.d.ts +50 -0
  49. package/node_modules/@oxygen/shared/dist/column-decision.js +228 -0
  50. package/node_modules/@oxygen/shared/dist/column-output-fields.js +2 -6
  51. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.d.ts +113 -0
  52. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.js +548 -0
  53. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +6 -6
  54. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +6 -6
  55. package/node_modules/@oxygen/shared/dist/cutover-freeze.d.ts +26 -0
  56. package/node_modules/@oxygen/shared/dist/cutover-freeze.js +52 -0
  57. package/node_modules/@oxygen/shared/dist/data-suppliers.d.ts +57 -0
  58. package/node_modules/@oxygen/shared/dist/data-suppliers.js +59 -0
  59. package/node_modules/@oxygen/shared/dist/deploy-env.d.ts +74 -0
  60. package/node_modules/@oxygen/shared/dist/deploy-env.js +82 -0
  61. package/node_modules/@oxygen/shared/dist/dnc-rules.d.ts +130 -0
  62. package/node_modules/@oxygen/shared/dist/dnc-rules.js +221 -0
  63. package/node_modules/@oxygen/shared/dist/enrichment-intents.d.ts +107 -0
  64. package/node_modules/@oxygen/shared/dist/enrichment-intents.js +809 -0
  65. package/node_modules/@oxygen/shared/dist/error-message.d.ts +1 -0
  66. package/node_modules/@oxygen/shared/dist/error-message.js +3 -0
  67. package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -3
  68. package/node_modules/@oxygen/shared/dist/external-write-policy.d.ts +33 -0
  69. package/node_modules/@oxygen/shared/dist/external-write-policy.js +68 -0
  70. package/node_modules/@oxygen/shared/dist/format-percent.d.ts +8 -0
  71. package/node_modules/@oxygen/shared/dist/format-percent.js +13 -0
  72. package/node_modules/@oxygen/shared/dist/freemail-domains.d.ts +81 -0
  73. package/node_modules/@oxygen/shared/dist/freemail-domains.js +157 -0
  74. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.d.ts +1 -0
  75. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.js +1 -1
  76. package/node_modules/@oxygen/shared/dist/hosted-ai.d.ts +60 -4
  77. package/node_modules/@oxygen/shared/dist/hosted-ai.js +125 -10
  78. package/node_modules/@oxygen/shared/dist/index.d.ts +15 -0
  79. package/node_modules/@oxygen/shared/dist/index.js +15 -0
  80. package/node_modules/@oxygen/shared/dist/json-path.js +1 -3
  81. package/node_modules/@oxygen/shared/dist/knowledge-bases.js +1 -3
  82. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +2 -2
  83. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +2 -2
  84. package/node_modules/@oxygen/shared/dist/langfuse.d.ts +44 -1
  85. package/node_modules/@oxygen/shared/dist/langfuse.js +416 -14
  86. package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +33 -0
  87. package/node_modules/@oxygen/shared/dist/linkedin-countries.js +361 -0
  88. package/node_modules/@oxygen/shared/dist/linkedin-country-timezones.d.ts +24 -0
  89. package/node_modules/@oxygen/shared/dist/linkedin-country-timezones.js +276 -0
  90. package/node_modules/@oxygen/shared/dist/linkedin-message-deletion.d.ts +2 -0
  91. package/node_modules/@oxygen/shared/dist/linkedin-message-deletion.js +5 -0
  92. package/node_modules/@oxygen/shared/dist/linkedin-post-keywords.d.ts +44 -0
  93. package/node_modules/@oxygen/shared/dist/linkedin-post-keywords.js +116 -0
  94. package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +96 -0
  95. package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +123 -0
  96. package/node_modules/@oxygen/shared/dist/llm-durable-capture.d.ts +24 -0
  97. package/node_modules/@oxygen/shared/dist/llm-durable-capture.js +89 -0
  98. package/node_modules/@oxygen/shared/dist/llm-prompts.d.ts +75 -0
  99. package/node_modules/@oxygen/shared/dist/llm-prompts.js +161 -0
  100. package/node_modules/@oxygen/shared/dist/log-sink-selector.d.ts +39 -0
  101. package/node_modules/@oxygen/shared/dist/log-sink-selector.js +56 -0
  102. package/node_modules/@oxygen/shared/dist/log.d.ts +1 -0
  103. package/node_modules/@oxygen/shared/dist/log.js +6 -1
  104. package/node_modules/@oxygen/shared/dist/mailbox-egress-ownership.d.ts +90 -0
  105. package/node_modules/@oxygen/shared/dist/mailbox-egress-ownership.js +130 -0
  106. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +17 -0
  107. package/node_modules/@oxygen/shared/dist/object-storage.js +21 -0
  108. package/node_modules/@oxygen/shared/dist/operational-telemetry.d.ts +24 -0
  109. package/node_modules/@oxygen/shared/dist/operational-telemetry.js +73 -0
  110. package/node_modules/@oxygen/shared/dist/otlp-log-sink.d.ts +79 -0
  111. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +366 -0
  112. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +1 -0
  113. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +23 -22
  114. package/node_modules/@oxygen/shared/dist/plan-limits.js +45 -18
  115. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +48 -41
  116. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +36 -25
  117. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +22 -22
  118. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +40 -34
  119. package/node_modules/@oxygen/shared/dist/product-analytics-environment.js +9 -0
  120. package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +36 -2
  121. package/node_modules/@oxygen/shared/dist/product-analytics-events.js +36 -1
  122. package/node_modules/@oxygen/shared/dist/rate-window.d.ts +5 -0
  123. package/node_modules/@oxygen/shared/dist/rate-window.js +8 -0
  124. package/node_modules/@oxygen/shared/dist/redaction.js +4 -1
  125. package/node_modules/@oxygen/shared/dist/research-output-contract.js +1 -3
  126. package/node_modules/@oxygen/shared/dist/scraper-lane-credential.d.ts +18 -0
  127. package/node_modules/@oxygen/shared/dist/scraper-lane-credential.js +23 -0
  128. package/node_modules/@oxygen/shared/dist/search-vocab.js +4 -5
  129. package/node_modules/@oxygen/shared/dist/select-options.js +6 -1
  130. package/node_modules/@oxygen/shared/dist/sequence-failures.js +1 -5
  131. package/node_modules/@oxygen/shared/dist/sequences.d.ts +23 -0
  132. package/node_modules/@oxygen/shared/dist/sequences.js +115 -5
  133. package/node_modules/@oxygen/shared/dist/signup-lead-payload.d.ts +80 -0
  134. package/node_modules/@oxygen/shared/dist/signup-lead-payload.js +198 -0
  135. package/node_modules/@oxygen/shared/dist/social-capabilities.d.ts +6 -0
  136. package/node_modules/@oxygen/shared/dist/social-capabilities.js +25 -16
  137. package/node_modules/@oxygen/shared/dist/social-post-metrics-core.d.ts +32 -0
  138. package/node_modules/@oxygen/shared/dist/social-post-metrics-core.js +32 -0
  139. package/node_modules/@oxygen/shared/dist/social-post-metrics-linkedin.d.ts +31 -0
  140. package/node_modules/@oxygen/shared/dist/social-post-metrics-linkedin.js +103 -0
  141. package/node_modules/@oxygen/shared/dist/social-post-metrics-series.d.ts +96 -0
  142. package/node_modules/@oxygen/shared/dist/social-post-metrics-series.js +213 -0
  143. package/node_modules/@oxygen/shared/dist/social-post-metrics-x.d.ts +13 -0
  144. package/node_modules/@oxygen/shared/dist/social-post-metrics-x.js +78 -0
  145. package/node_modules/@oxygen/shared/dist/social-post-metrics.d.ts +36 -0
  146. package/node_modules/@oxygen/shared/dist/social-post-metrics.js +51 -0
  147. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +22 -10
  148. package/node_modules/@oxygen/shared/dist/spend-safety.js +15 -21
  149. package/node_modules/@oxygen/shared/dist/sql-rows.d.ts +1 -0
  150. package/node_modules/@oxygen/shared/dist/sql-rows.js +3 -0
  151. package/node_modules/@oxygen/shared/dist/stripe-price-catalog.d.ts +36 -0
  152. package/node_modules/@oxygen/shared/dist/stripe-price-catalog.js +184 -0
  153. package/node_modules/@oxygen/shared/dist/stripe-subscription-kind.d.ts +41 -0
  154. package/node_modules/@oxygen/shared/dist/stripe-subscription-kind.js +44 -0
  155. package/node_modules/@oxygen/shared/dist/table-limits.d.ts +3 -0
  156. package/node_modules/@oxygen/shared/dist/table-limits.js +3 -0
  157. package/node_modules/@oxygen/shared/dist/telemetry-export-observer.d.ts +94 -0
  158. package/node_modules/@oxygen/shared/dist/telemetry-export-observer.js +298 -0
  159. package/node_modules/@oxygen/shared/dist/telemetry.d.ts +11 -0
  160. package/node_modules/@oxygen/shared/dist/telemetry.js +28 -2
  161. package/node_modules/@oxygen/shared/dist/type-guards.d.ts +22 -0
  162. package/node_modules/@oxygen/shared/dist/type-guards.js +35 -0
  163. package/node_modules/@oxygen/shared/dist/ugc.d.ts +22 -11
  164. package/node_modules/@oxygen/shared/dist/ugc.js +10 -0
  165. package/node_modules/@oxygen/shared/dist/value-readers.d.ts +21 -0
  166. package/node_modules/@oxygen/shared/dist/value-readers.js +59 -0
  167. package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -0
  168. package/node_modules/@oxygen/shared/dist/version.generated.js +2 -0
  169. package/node_modules/@oxygen/shared/dist/version.js +8 -1
  170. package/node_modules/@oxygen/shared/dist/workspace-event-catalog.js +0 -23
  171. package/node_modules/@oxygen/shared/dist/workspace-file-storage.d.ts +29 -0
  172. package/node_modules/@oxygen/shared/dist/workspace-file-storage.js +31 -0
  173. package/node_modules/@oxygen/shared/package.json +59 -0
  174. package/node_modules/@oxygen/workflows/dist/graph/expression.js +2 -5
  175. package/node_modules/@oxygen/workflows/dist/graph/params.js +1 -1
  176. package/package.json +3 -2
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.987.20
37
+ Version: 1.1010.1
@@ -1,5 +1,3 @@
1
- /** Age of an ISO stamp as a short human span, measured against `now`. */
2
- export declare function ago(iso: unknown, now?: Date): string;
3
1
  export type RenderOptions = {
4
2
  /** Binary name to print inside suggested commands. */
5
3
  binary?: string;
@@ -47,7 +47,7 @@ function pct(value) {
47
47
  return `${Math.round(parsed * 100)}%`;
48
48
  }
49
49
  /** Age of an ISO stamp as a short human span, measured against `now`. */
50
- export function ago(iso, now = new Date()) {
50
+ function ago(iso, now = new Date()) {
51
51
  const raw = str(iso);
52
52
  if (!raw)
53
53
  return "never";
@@ -2,7 +2,7 @@ import { execFileSync } from "node:child_process";
2
2
  import { randomBytes, timingSafeEqual } from "node:crypto";
3
3
  import { createServer } from "node:http";
4
4
  import { hostname } from "node:os";
5
- import { OXYGEN_VERSION, OxygenError, deriveCliLoginConfirmationCode } from "@oxygen/shared";
5
+ import { OXYGEN_VERSION, OxygenError, deriveCliLoginConfirmationCode, sleep } from "@oxygen/shared";
6
6
  import { requestOxygen } from "./http-client.js";
7
7
  import { readErrorMessage } from "./util.js";
8
8
  const CALLBACK_HOST = "127.0.0.1";
@@ -133,9 +133,6 @@ function safeHostname() {
133
133
  return undefined;
134
134
  }
135
135
  }
136
- function sleep(ms) {
137
- return new Promise((resolve) => setTimeout(resolve, ms));
138
- }
139
136
  export async function createBrowserLoginSession(apiUrl) {
140
137
  const state = randomBytes(32).toString("base64url");
141
138
  let settled = false;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `columns add` classification flags: `--classify <labels>`, `--yes-no <question>`
3
+ * and `--score <levels>` author an AI column answered by System One
4
+ * (`definition.decision`). The server validates the shape; this only turns the
5
+ * flags into it and refuses combinations that would author something else.
6
+ */
7
+ export type ColumnDecisionFlagOptions = {
8
+ classify?: string;
9
+ yesNo?: string;
10
+ score?: string;
11
+ minConfidence?: string;
12
+ grounding?: string;
13
+ };
14
+ export type ColumnDecisionFlags = {
15
+ /** The question, when `--yes-no` carried it; `--classify` and `--score` take `--prompt`. */
16
+ question: string | null;
17
+ decision: Record<string, unknown>;
18
+ };
19
+ /** Null when no classification flag was passed. */
20
+ export declare function readColumnDecisionFlags(options: ColumnDecisionFlagOptions): ColumnDecisionFlags | null;
@@ -0,0 +1,54 @@
1
+ import { OxygenError } from "@oxygen/shared/cli-result";
2
+ import { COLUMN_DECISION_GROUNDINGS, } from "@oxygen/shared/column-decision";
3
+ function readFlag(value) {
4
+ if (typeof value !== "string")
5
+ return null;
6
+ const trimmed = value.trim();
7
+ return trimmed.length > 0 ? trimmed : null;
8
+ }
9
+ function splitList(value) {
10
+ return value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
11
+ }
12
+ function invalid(message) {
13
+ return new OxygenError("invalid_request", message, { exitCode: 1 });
14
+ }
15
+ /** Null when no classification flag was passed. */
16
+ export function readColumnDecisionFlags(options) {
17
+ const classify = readFlag(options.classify);
18
+ const yesNo = readFlag(options.yesNo);
19
+ const scoreLevels = readFlag(options.score);
20
+ const chosen = [classify ? "--classify" : null, yesNo ? "--yes-no" : null, scoreLevels ? "--score" : null]
21
+ .filter((flag) => flag !== null);
22
+ const minConfidenceRaw = readFlag(options.minConfidence);
23
+ const groundingRaw = readFlag(options.grounding);
24
+ if (chosen.length === 0) {
25
+ if (minConfidenceRaw || groundingRaw) {
26
+ throw invalid("--min-confidence and --grounding apply to a classification column: add --classify, --yes-no or --score.");
27
+ }
28
+ return null;
29
+ }
30
+ if (chosen.length > 1) {
31
+ throw invalid(`A classification column has one mode: pass one of ${chosen.join(", ")}, not several.`);
32
+ }
33
+ const mode = classify ? "labels" : yesNo ? "yes_no" : "score";
34
+ const decision = { engine: "system_one", mode };
35
+ if (classify)
36
+ decision.labels = splitList(classify);
37
+ if (scoreLevels)
38
+ decision.levels = splitList(scoreLevels);
39
+ if (minConfidenceRaw) {
40
+ const value = Number(minConfidenceRaw);
41
+ if (!Number.isFinite(value)) {
42
+ throw invalid(`--min-confidence must be a number from 0 to 1, e.g. 0.8 (got ${minConfidenceRaw}).`);
43
+ }
44
+ decision.minConfidence = value;
45
+ }
46
+ if (groundingRaw) {
47
+ const grounding = groundingRaw.toLowerCase();
48
+ if (!COLUMN_DECISION_GROUNDINGS.includes(grounding)) {
49
+ throw invalid(`--grounding must be ${COLUMN_DECISION_GROUNDINGS.join(" or ")} (got ${groundingRaw}).`);
50
+ }
51
+ decision.grounding = grounding;
52
+ }
53
+ return { question: yesNo, decision };
54
+ }
@@ -1,10 +1,10 @@
1
1
  import type { Command } from "commander";
2
- export type CommandManifestFlag = {
2
+ type CommandManifestFlag = {
3
3
  flags: string;
4
4
  description: string;
5
5
  required: boolean;
6
6
  };
7
- export type CommandManifestArgument = {
7
+ type CommandManifestArgument = {
8
8
  name: string;
9
9
  required: boolean;
10
10
  description: string;
@@ -46,3 +46,4 @@ export declare function getCommandManifestEntry(manifest: CommandManifest, exact
46
46
  invoke: string;
47
47
  }) | null;
48
48
  export declare function suggestCommandNames(manifest: CommandManifest, query: string, limit?: number): string[];
49
+ export {};
@@ -26,6 +26,10 @@ const COMMAND_SEARCH_STOP_WORDS = new Set([
26
26
  // advertised the most consequential collaboration write as a read.
27
27
  const MUTATING_VERBS = new Set([
28
28
  "brand-approve", "revoke-invite", "confirm",
29
+ // Exact leaf: `ugc creators set-target` writes one creator's posting deal.
30
+ "set-target",
31
+ // `ugc creators decline` settles an application for good.
32
+ "decline",
29
33
  "accept", "ack", "add", "adopt", "apply", "approve", "archive",
30
34
  "assign", "attach",
31
35
  // `linkedin intent autoenroll` arms (or revokes) a STANDING grant to contact
@@ -37,6 +41,16 @@ const MUTATING_VERBS = new Set([
37
41
  // recurring write, and --run can connect newly eligible mailboxes immediately.
38
42
  "auto-enroll",
39
43
  "backfill",
44
+ // `dashboards widgets refresh` calls a provider and bills the workspace. It is
45
+ // currently the only `refresh` leaf; the default (mutates:false) would
46
+ // advertise the one dashboard command that spends money as a read, to every
47
+ // agent and in the public CLI reference.
48
+ "refresh",
49
+ // Exact hyphenated leaf, because the `backfill` entry above matches the whole
50
+ // leaf token and never `crm-backfill`. `suppressions crm-backfill --live`
51
+ // creates CRM person records for everyone on the do-not-contact list, so the
52
+ // default (mutates:false) would advertise a bulk workspace write as a read.
53
+ "crm-backfill",
40
54
  // A noun leaf, so the default would advertise `projects color` — a tenant
41
55
  // write — to every agent as a read. `decide` is the same case.
42
56
  "color",
@@ -54,7 +68,7 @@ const MUTATING_VERBS = new Set([
54
68
  // `support chat` starts or continues a customer-authored Plain Thread. The
55
69
  // conversational noun is still a real external write.
56
70
  "buy", "call", "cancel", "chat", "chat-action", "claim", "clear",
57
- "comment", "configure", "connect", "create", "decide", "delete", "delist", "disable",
71
+ "comment", "configure", "connect", "create", "decide", "delete", "delete-message", "delist", "disable",
58
72
  "disconnect", "dispatch", "done", "draft", "duplicate", "edit", "emit", "enable", "enroll",
59
73
  // Exact leaf, not a `field` prefix: `support admin field-set` writes a Plain
60
74
  // Thread field, while a future `field-get` would be a read.
@@ -63,7 +77,7 @@ const MUTATING_VERBS = new Set([
63
77
  "label-add", "label-remove", "launch", "log", "login", "logout", "mark-all-read", "mark-read", "materialize", "merge",
64
78
  "migrate",
65
79
  "move", "note", "off", "onboard", "order", "pause", "pin", "priority", "provision",
66
- "publish", "purchase", "purge", "push", "react", "reconcile", "record", "recover-pending",
80
+ "publish", "purchase", "purge", "push", "react", "reactivate", "reconcile", "record", "recover-pending",
67
81
  "recover-capacity", "register", "reject", "relink", "remove", "rename", "reorder", "reply", "request",
68
82
  "replay", "rerun", "rescan", "resend", "reset", "resolve", "restore", "resume",
69
83
  "retry", "retype", "revoke", "rotate", "run", "save", "schedule",
@@ -82,11 +96,19 @@ const MUTATING_VERBS = new Set([
82
96
  const MUTATING_COMMANDS = new Set([
83
97
  "mailboxes warmup status",
84
98
  "mailboxes warmup reconnect",
99
+ // A noun leaf with its own action (not a group), so the default would
100
+ // advertise a STANDING per-viewer paid-enrichment toggle as a read. `enrichment`
101
+ // itself is not a MUTATING_VERBS entry because the other two `enrichment`
102
+ // leaves in this file (`crm enrichment`, `enrichment` catalogue) are groups
103
+ // whose own subcommands (list/set/enable/disable/backfill, catalog/entries)
104
+ // already carry their own correctly-classified verbs.
105
+ "viewers enrichment",
85
106
  ]);
86
107
  // `--approved` usually identifies a paid or externally mutating execution
87
108
  // mode, but a small number of approved operations are explicitly
88
109
  // zero-credit. Keep those exceptions exact so discovery never invents spend.
89
110
  const ZERO_CREDIT_APPROVAL_COMMANDS = new Set([
111
+ "inbox delete-message",
90
112
  "tables watcher preview",
91
113
  "knowledge repositories connect",
92
114
  "knowledge repositories resolve",
@@ -132,6 +154,7 @@ const READ_ONLY_COMMANDS = new Set([
132
154
  // invocation still previews, so machine-readable discovery must not imply that
133
155
  // calling the command without its confirmation flag writes anything.
134
156
  const PREVIEW_BY_DEFAULT_COMMANDS = new Set([
157
+ "inbox delete-message",
135
158
  "tables watcher preview",
136
159
  "ugc creators invite",
137
160
  "ugc creators send-invite",
@@ -34,7 +34,7 @@ export declare function defaultApiUrl(env?: NodeJS.ProcessEnv): string;
34
34
  * look identical, and a drifted profile turns a prod-labelled binary into a report
35
35
  * about dev that reads as a production outage (OXY-4091).
36
36
  */
37
- export type CliEndpointContext = {
37
+ type CliEndpointContext = {
38
38
  apiUrl: string;
39
39
  /** Active profile name, or null when no named profile supplied the credentials. */
40
40
  profile: string | null;
@@ -3,10 +3,10 @@ import { parseJsonObject } from "./cli-values.js";
3
3
  import { requestOxygen } from "./http-client.js";
4
4
  export function registerFunctionsCommands(program, handle) {
5
5
  const functions = program.command("functions")
6
- .description("Browse OXYGEN's ready-made Functions (work email, mobile phone, company funding stage, ...), favourite them, bind them to a table, or create, edit and publish your own Functions backed by ordinary Tables.")
7
- .addHelpText("after", "\nOXYGEN-managed Functions are pre-built and priced: `functions list --managed` shows each one with its per-row credit estimate before you attach it. Attaching (`functions bind`) is free; only `columns run` spends, after a dry run. A managed Function is read-only; `functions duplicate <function>` gives you an editable copy.\nDraft edits are isolated. Publishing updates future invocations of every caller; queued, in-flight and past runs retain their captured version. Existing caller caps never increase automatically.\nFlow: draft → describe → publish → bind → columns run --dry-run → approved run → runs.\nA bound Function executes on its own published execution table and writes named outputs back to the calling table. The call stays visible from the caller: `table-runs list --table <caller> --status all` lists the run, and the binding column's cell holds the outcome (status, outputs, credits, invocation and run ids). Address a Function by id, slug, or the display name shown by `functions list`.\nWorked example with commands: `oxygen skills install --skill oxygen-gtm --project`, then read its recipes/callable-tables.md.\n");
8
- functions.command("list").description("List the Function library: OXYGEN-managed Functions with their per-row credit estimate, plus your workspace's own drafts and published Functions (up to 500).")
9
- .option("--managed", "Only OXYGEN-managed Functions (pre-built, priced, read-only; duplicate to customize).")
6
+ .description("Create, publish and reuse your workspace's Functions backed by ordinary Tables.")
7
+ .addHelpText("after", "\n`functions list` shows your workspace's drafts and published Functions with per-row credit estimates. Attaching (`functions bind`) is free; only `columns run` spends, after a dry run. Use `functions duplicate <function>` to start an editable copy.\nDraft edits are isolated. Publishing updates future invocations of every caller; queued, in-flight and past runs retain their captured version. Existing caller caps never increase automatically.\nFlow: draft → describe → publish → bind → columns run --dry-run → approved run → runs.\nA bound Function executes on its own published execution table and writes named outputs back to the calling table. The call stays visible from the caller: `table-runs list --table <caller> --status all` lists the run, and the binding column's cell holds the outcome (status, outputs, credits, invocation and run ids). Address a Function by id, slug, or the display name shown by `functions list`.\nWorked example with commands: `oxygen skills install --skill oxygen-gtm --project`, then read its recipes/callable-tables.md.\n");
8
+ functions.command("list").description("List your workspace's drafts and published Functions with per-row credit estimates (up to 500).")
9
+ .option("--managed", "Retired compatibility filter; returns an empty list. Use the workspace library without this flag.")
10
10
  .option("--favorites", "Only the Functions you favourited (`functions favorite <function>`).")
11
11
  .option("--json", "Print a JSON envelope.")
12
12
  .action((options) => handle("functions list", options, () => {
@@ -20,11 +20,11 @@ export function registerFunctionsCommands(program, handle) {
20
20
  .option("--json", "Print a JSON envelope.")
21
21
  .action((ref, options) => handle(`functions ${command}`, options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: command, function: ref } })));
22
22
  }
23
- functions.command("duplicate <function>").description("Copy a Function's steps into a new editable draft of your own (same inputs and outputs, no rows). The way to customize an OXYGEN-managed Function.")
23
+ functions.command("duplicate <function>").description("Copy a Function's steps into a new editable draft (same inputs and outputs, no rows).")
24
24
  .option("--name <name>", "Display name for the copy. Defaults to '<source> (copy)'.")
25
25
  .option("--json", "Print a JSON envelope.")
26
26
  .action((ref, options) => handle("functions duplicate", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "duplicate", function: ref, ...(options.name ? { display_name: options.name } : {}) } })));
27
- functions.command("describe <function>").description("Inspect a Function's inputs, outputs, steps, per-row credit estimate, caps, and whether it is OXYGEN-managed or your own draft/published version.")
27
+ functions.command("describe <function>").description("Inspect a Function's inputs, outputs, steps, per-row credit estimate, caps, and draft or published version.")
28
28
  .option("--json", "Print a JSON envelope.")
29
29
  .action((ref, options) => handle("functions describe", options, () => requestOxygen(`/api/cli/functions?${new URLSearchParams({ function: ref })}`)));
30
30
  functions.command("draft [function]").description("Create a Function draft, or save an existing Function's draft; executes nothing.")
@@ -47,13 +47,17 @@ export function registerFunctionsCommands(program, handle) {
47
47
  functions.command("rename <function> <name>").description("Rename a Function while preserving its identity, callers and published execution.")
48
48
  .option("--json", "Print a JSON envelope.")
49
49
  .action((ref, name, options) => handle("functions rename", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "rename", function: ref, display_name: name } })));
50
- functions.command("delete <function>").description("Preview removal from the Function library; preserves backing tables, rows and run history. Connected callers or active runs block deletion.")
51
- .addHelpText("after", "\nDeletion is final: there is no restore, unlike `tables delete`. To reuse the logic, `tables duplicate` the backing Table and draft a new Function from the copy.\n")
50
+ functions.command("delete <function>").description("Preview removal from the Function library, then remove it with --yes; preserves backing tables, rows and run history. Connected callers or active runs block deletion.")
51
+ .addHelpText("after", "\nDeleting your own Function is final: there is no restore, unlike `tables delete`. To reuse the logic, `tables duplicate` the backing Table and draft a new Function from the copy.\n")
52
52
  .option("--yes", "Confirm removal of this Function after reviewing its callers.")
53
53
  .option("--json", "Print a JSON envelope.")
54
54
  .action((ref, options) => handle("functions delete", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "delete", function: ref, approved: options.yes === true } })));
55
+ functions.command("restore").description("Retired: OXYGEN-provided Functions can no longer be restored. Create a workspace Function instead.")
56
+ .option("--catalog-id <id...>", "Legacy catalog identifiers; restoration is no longer available.")
57
+ .option("--json", "Print a JSON envelope.")
58
+ .action((options) => handle("functions restore", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "restore_managed", ...(options.catalogId?.length ? { catalog_ids: options.catalogId } : {}) } })));
55
59
  functions.command("bind <table> <function>").description("Add a Function column with explicit input/output mappings and a caller credit cap. Create each mapped output column on the caller table first with `columns add`; bind rejects an output mapped to a column the caller table does not have.")
56
- .requiredOption("--inputs-json <json>", "Object mapping Function input keys to caller column keys.")
60
+ .requiredOption("--inputs-json <json>", "Map Function input keys to caller columns or nested JSON paths, e.g. profile.company.domain.")
57
61
  .requiredOption("--outputs-json <json>", "Object mapping Function output keys to existing caller column keys.")
58
62
  .requiredOption("--max-credits-per-item <n>", "Hard credit ceiling for each caller row; future publishes cannot raise it.")
59
63
  .option("--overwrite-policy <policy>", "Callback writes: empty_only or overwrite.", "empty_only")
package/dist/help.d.ts CHANGED
@@ -20,4 +20,12 @@ export declare function enableCommandSuggestions(command: Command): void;
20
20
  * lists the real subcommands. Returns null when argv does not describe an
21
21
  * unknown subcommand (an unknown OPTION has its own handling).
22
22
  */
23
+ /**
24
+ * Hint for `error: unknown option '--filter'`. Commander's own suggester stops
25
+ * at three edits, so `--filter` never reaches `--filter-json`; a flag that is a
26
+ * prefix of exactly one option on that command (or of which exactly one option
27
+ * is a prefix) names it. Returns null when commander's output already says it
28
+ * all, or when the flag is not a long option.
29
+ */
30
+ export declare function unknownOptionHint(program: Command, argv: readonly string[], message: string): string | null;
23
31
  export declare function unknownCommandHint(program: Command, argv: readonly string[]): string | null;
package/dist/help.js CHANGED
@@ -214,6 +214,52 @@ const COMMAND_SYNONYMS = {
214
214
  * lists the real subcommands. Returns null when argv does not describe an
215
215
  * unknown subcommand (an unknown OPTION has its own handling).
216
216
  */
217
+ /**
218
+ * Hint for `error: unknown option '--filter'`. Commander's own suggester stops
219
+ * at three edits, so `--filter` never reaches `--filter-json`; a flag that is a
220
+ * prefix of exactly one option on that command (or of which exactly one option
221
+ * is a prefix) names it. Returns null when commander's output already says it
222
+ * all, or when the flag is not a long option.
223
+ */
224
+ export function unknownOptionHint(program, argv, message) {
225
+ const flag = /unknown option '(--[^']+)'/.exec(message)?.[1];
226
+ if (!flag)
227
+ return null;
228
+ const [command, path] = resolveCommandPath(program, argv);
229
+ const longs = new Set();
230
+ for (let current = command; current; current = current.parent) {
231
+ for (const option of current.options)
232
+ if (option.long)
233
+ longs.add(option.long);
234
+ }
235
+ const bare = flag.split("=")[0].toLowerCase();
236
+ if (longs.has(bare))
237
+ return null;
238
+ const candidates = [...longs].filter((long) => long.startsWith(bare) || bare.startsWith(long));
239
+ const helpLine = `Run \`${path} --help\` for its options.`;
240
+ if (candidates.length === 1) {
241
+ return `Hint: \`${path}\` has no \`${bare}\`. Did you mean \`${candidates[0]}\`? ${helpLine}`;
242
+ }
243
+ if (candidates.length > 1 && candidates.length <= 4) {
244
+ return `Hint: \`${path}\` has no \`${bare}\`. Did you mean one of ${candidates.map((c) => `\`${c}\``).join(", ")}? ${helpLine}`;
245
+ }
246
+ return `Hint: \`${path}\` has no \`${bare}\`. ${helpLine}`;
247
+ }
248
+ /** Walk the command path in argv (stopping at the first option) and return the deepest command with its printable path. */
249
+ function resolveCommandPath(program, argv) {
250
+ let current = program;
251
+ let path = program.name();
252
+ for (const token of argv) {
253
+ if (token.startsWith("-"))
254
+ break;
255
+ const child = current.commands.find((candidate) => candidate.name() === token || candidate.aliases().includes(token));
256
+ if (!child)
257
+ break;
258
+ current = child;
259
+ path = `${path} ${token}`;
260
+ }
261
+ return [current, path];
262
+ }
217
263
  export function unknownCommandHint(program, argv) {
218
264
  let current = program;
219
265
  let path = program.name();