@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
@@ -2,13 +2,14 @@ import { parseField } from "./field-parser.js";
2
2
  export function registerUgcCommands(program, { request: requestOxygen, handle }) {
3
3
  const ugc = program
4
4
  .command("ugc")
5
- .description("Manage UGC programs and independent creator participations: briefs, voice, posts, approvals, sponsorship and bounded amplification. Requires UGC availability. Start with memberships list in a creator workspace. See the oxygen-ugc skill; JSON reads return web_url for inspection.");
5
+ .description("Manage UGC programs and independent creator participations: voice, posts, approvals, sponsorship and bounded amplification. Requires UGC availability. Start with memberships list in a creator workspace. See the oxygen-ugc skill; JSON reads return web_url for inspection.");
6
6
  const groupDescriptions = {
7
- programs: "Programs you operate or joined. Lifecycle: create, update, duplicate (settings + briefs), archive (stops future work, keeps shared history, reversible with restore) and delete (permanent; only while no creator has ever joined).",
8
- creators: "Creator participations: invite, revoke an invite, accept in the creator workspace, connect a sender, change approval authority, or revoke.",
9
- memberships: "Active programs this creator workspace has joined. Read these before choosing a program for a personal post.",
10
- briefs: "Program briefs with ordered questions for creators.",
11
- posts: "Enrolled program posts: enroll existing posts, draft from briefs, edit, schedule, and record creator or brand approval.",
7
+ programs: "Programs you operate or joined; discover public programs from other brands and apply to them. Lifecycle: create, update, duplicate (settings), archive (stops future work, keeps shared history, reversible with restore) and delete (permanent; only while no creator has ever joined).",
8
+ creators: "Creator participations: invite, set one creator's own posting deal, revoke an invite, accept in the creator workspace, connect a sender, change approval authority, or revoke.",
9
+ memberships: "Active programs this creator workspace has joined, each with your deal (posting_target), this period's progress and your published posts. Your own numbers only. Read these before choosing a program for a personal post.",
10
+ applications: "Applications to public programs: the ones you sent as a creator, or the ones your program received as a brand.",
11
+ profile: "Your creator profile: the topics you post about, who follows you and your LinkedIn profile URL (used when you apply), readable by the brands whose programs you joined. Name, picture and headline come from your connected LinkedIn account.",
12
+ posts: "Enrolled program posts: enroll existing posts, draft from a topic, edit, schedule, record creator or brand approval, and schedule one-off comments on program posts.",
12
13
  analytics: "Stored daily program and creator performance.",
13
14
  knowledge: "Master Knowledge pages shared live with a program.",
14
15
  voice: "Creator voice profiles and imports.",
@@ -62,7 +63,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
62
63
  }));
63
64
  group("creators")
64
65
  .command("list")
65
- .description("Read creators and invitations, including persisted email delivery status. Read-only.")
66
+ .description("Read creators (name, picture, LinkedIn URL and posting_target, their own deal; null follows the program standard) and invitations, including persisted email delivery status. Read-only.")
66
67
  .option("--program-id <id>", "Program ID.")
67
68
  .option("--participation-id <id>", "Creator participation ID.")
68
69
  .option("--json", "Print a JSON envelope.")
@@ -74,26 +75,38 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
74
75
  query.set("participation_id", String(options.participationId));
75
76
  return requestOxygen(`/api/cli/ugc?${query}`);
76
77
  }));
77
- group("memberships")
78
- .command("list")
79
- .description("Read active program memberships for the creator workspace. Free, stored and provider-free.")
78
+ group("creators")
79
+ .command("invitation")
80
+ .description("Read what an invitation link points at before accepting it: the program, the invited email (masked), the posting deal, and can_accept with the reason when this account or workspace cannot accept it. Free, read-only.")
81
+ .requiredOption("--token <token>", "The token from the invitation link (?invite=...).")
80
82
  .option("--json", "Print a JSON envelope.")
81
- .action((options) => handle("ugc memberships list", options, () => requestOxygen("/api/cli/ugc?view=memberships")));
82
- group("briefs")
83
+ .action((options) => handle("ugc creators invitation", options, () => requestOxygen(`/api/cli/ugc?${new URLSearchParams({ view: "invitation", token: String(options.token) })}`)));
84
+ group("programs")
85
+ .command("discover")
86
+ .description("Public programs from every brand on Oxygen that you can apply to, with each brand's deal and brief excerpt, and whether you already joined or applied. Free, read-only.")
87
+ .option("--json", "Print a JSON envelope.")
88
+ .action((options) => handle("ugc programs discover", options, () => requestOxygen("/api/cli/ugc?view=discover")));
89
+ group("applications")
83
90
  .command("list")
84
- .description("Read one program's UGC briefs. Read-only; requires --program-id.")
85
- .showHelpAfterError(`Briefs belong to a program. Run \`${program.name() || "oxygen"} ugc programs list --json\` to find its ID, then \`${program.name() || "oxygen"} ugc briefs list --program-id <id> --json\`.`)
86
- .requiredOption("--program-id <id>", "Program ID.")
87
- .option("--participation-id <id>", "Creator participation ID.")
91
+ .description("Applications to public programs. Without --program-id: the ones this creator workspace sent, with status. With --program-id: the ones your program received (brand), pending first. Read-only.")
92
+ .option("--program-id <id>", "Your program's ID, to see who applied to it.")
88
93
  .option("--json", "Print a JSON envelope.")
89
- .action((options) => handle("ugc briefs list", options, () => {
90
- const query = new URLSearchParams({ view: "briefs" });
94
+ .action((options) => handle("ugc applications list", options, () => {
95
+ const query = new URLSearchParams({ view: "applications" });
91
96
  if (options.programId)
92
97
  query.set("program_id", String(options.programId));
93
- if (options.participationId)
94
- query.set("participation_id", String(options.participationId));
95
98
  return requestOxygen(`/api/cli/ugc?${query}`);
96
99
  }));
100
+ group("profile")
101
+ .command("get")
102
+ .description("Read your creator profile (topics, audience and LinkedIn profile URL). Free, read-only.")
103
+ .option("--json", "Print a JSON envelope.")
104
+ .action((options) => handle("ugc profile get", options, () => requestOxygen("/api/cli/ugc?view=creator_profile")));
105
+ group("memberships")
106
+ .command("list")
107
+ .description("Read active program memberships for the creator workspace. Free, stored and provider-free.")
108
+ .option("--json", "Print a JSON envelope.")
109
+ .action((options) => handle("ugc memberships list", options, () => requestOxygen("/api/cli/ugc?view=memberships")));
97
110
  group("posts")
98
111
  .command("list")
99
112
  .description("Read UGC posts in the active workspace. Read-only.")
@@ -122,7 +135,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
122
135
  }));
123
136
  group("analytics")
124
137
  .command("get")
125
- .description("Read UGC analytics in the active workspace. Read-only.")
138
+ .description("Read UGC analytics in the active workspace. Read-only. The brand workspace sees every creator; a creator workspace only ever gets its own row, with or without --participation-id.")
126
139
  .requiredOption("--program-id <id>", "Program ID.")
127
140
  .option("--participation-id <id>", "Creator participation ID.")
128
141
  .option("--post-cursor <cursor>", "Next post_performance page from next_post_cursor; totals still cover all enrolled posts.")
@@ -276,19 +289,25 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
276
289
  {
277
290
  action: "program_create",
278
291
  command: "programs create",
279
- description: "Create a master UGC program. Free: 0 credits, no provider call.",
292
+ description: "Create a master UGC program from its product link. The name defaults to the site's name and its icon is fetched from the site. Free: 0 credits, no provider call.",
280
293
  fields: [
281
294
  {
282
- name: "name",
295
+ name: "product_url",
283
296
  kind: "string",
284
- description: "Program name.",
297
+ description: "Product domain or link, e.g. acme.com.",
285
298
  required: true,
286
299
  },
287
300
  {
288
- name: "product_url",
301
+ name: "name",
289
302
  kind: "string",
290
- description: "Product website URL.",
291
- required: true,
303
+ description: "Program name; defaults to the product site's name, else its domain.",
304
+ required: false,
305
+ },
306
+ {
307
+ name: "brief",
308
+ kind: "string",
309
+ description: "Short creator brief (up to 1,200 characters): what the product is, who it is for, key facts and the call to action. Drafts are grounded in it.",
310
+ required: false,
292
311
  },
293
312
  {
294
313
  name: "description",
@@ -308,6 +327,18 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
308
327
  description: "Require a separate brand approval before publishing.",
309
328
  required: false,
310
329
  },
330
+ {
331
+ name: "posting_target",
332
+ kind: "posting_target",
333
+ description: "Posts each creator should publish by default: <n>/month, <n>/week or <n>/total (n 1–100), or none to clear. One creator's own deal: creators set-target.",
334
+ required: false,
335
+ },
336
+ {
337
+ name: "visibility",
338
+ kind: "string",
339
+ description: "private (default: invitation only) or public (listed in every creator's Discover, where creators apply and you approve).",
340
+ required: false,
341
+ },
311
342
  ],
312
343
  },
313
344
  {
@@ -330,7 +361,13 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
330
361
  {
331
362
  name: "product_url",
332
363
  kind: "string",
333
- description: "Product website URL.",
364
+ description: "Product domain or link; a new one refreshes the icon.",
365
+ required: false,
366
+ },
367
+ {
368
+ name: "brief",
369
+ kind: "string",
370
+ description: "Short creator brief (up to 1,200 characters); an empty string clears it.",
334
371
  required: false,
335
372
  },
336
373
  {
@@ -351,6 +388,18 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
351
388
  description: "Require a separate brand approval before publishing.",
352
389
  required: false,
353
390
  },
391
+ {
392
+ name: "posting_target",
393
+ kind: "posting_target",
394
+ description: "Posts each creator should publish by default: <n>/month, <n>/week or <n>/total (n 1–100), or none to clear. One creator's own deal: creators set-target.",
395
+ required: false,
396
+ },
397
+ {
398
+ name: "visibility",
399
+ kind: "string",
400
+ description: "private (default: invitation only) or public (listed in every creator's Discover, where creators apply and you approve).",
401
+ required: false,
402
+ },
354
403
  {
355
404
  name: "peer_engagement_enabled",
356
405
  kind: "boolean",
@@ -396,7 +445,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
396
445
  {
397
446
  action: "program_duplicate",
398
447
  command: "programs duplicate",
399
- description: "Copy a program's settings, shared knowledge and brand review into a new active program, with its briefs by default. Free: 0 credits. Never copies creators, invitations, posts or sponsorship.",
448
+ description: "Copy a program's settings, shared knowledge, brand review and posting target into a new active program. Free: 0 credits. Never copies creators, invitations, posts or sponsorship.",
400
449
  fields: [
401
450
  {
402
451
  name: "program_id",
@@ -410,18 +459,12 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
410
459
  description: 'Name of the copy; defaults to "<name> (copy)".',
411
460
  required: false,
412
461
  },
413
- {
414
- name: "include_briefs",
415
- kind: "boolean",
416
- description: "Copy the program's briefs (default true).",
417
- required: false,
418
- },
419
462
  ],
420
463
  },
421
464
  {
422
465
  action: "program_delete",
423
466
  command: "programs delete",
424
- description: "Permanently delete a program with its briefs and pending invitations. A bare call previews the counts and whether it is deletable; pass --approved to delete. Allowed only while no creator has ever joined; otherwise use `programs archive`.",
467
+ description: "Permanently delete a program and its pending invitations. A bare call previews the counts and whether it is deletable; pass --approved to delete. Allowed only while no creator has ever joined; otherwise use `programs archive`.",
425
468
  fields: [
426
469
  {
427
470
  name: "program_id",
@@ -440,7 +483,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
440
483
  {
441
484
  action: "invite_create",
442
485
  command: "creators invite",
443
- description: "Preview an invitation email (0 credits); send with --approved --preview-token from that preview. Use --link-only to create a link without email.",
486
+ description: "Preview an invitation email (0 credits) for one creator (--email) or up to 50 at once (--emails); send with --approved --preview-token from that preview and the same recipients. Use --link-only to create links without email.",
444
487
  fields: [
445
488
  {
446
489
  name: "program_id",
@@ -452,7 +495,31 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
452
495
  name: "email",
453
496
  kind: "string",
454
497
  description: "Exact creator email to receive the invitation.",
455
- required: true,
498
+ required: false,
499
+ },
500
+ {
501
+ name: "emails",
502
+ kind: "email_list",
503
+ description: "Several creator emails, comma-separated or a JSON array (1–50, duplicates removed).",
504
+ required: false,
505
+ },
506
+ {
507
+ name: "posting_target",
508
+ kind: "posting_target",
509
+ description: "These creators' own deal when it differs from the program standard, e.g. 1/month; omit to follow the program. Change it later with creators set-target.",
510
+ required: false,
511
+ },
512
+ {
513
+ name: "email_subject",
514
+ kind: "string",
515
+ description: "Your own email subject (up to 200 characters); omit for the default.",
516
+ required: false,
517
+ },
518
+ {
519
+ name: "email_message",
520
+ kind: "string",
521
+ description: "Your own message (up to 3,000 characters); the Accept button and join link are always added below it. Omit for the default.",
522
+ required: false,
456
523
  },
457
524
  {
458
525
  name: "approved",
@@ -468,6 +535,92 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
468
535
  },
469
536
  ],
470
537
  },
538
+ {
539
+ action: "application_create",
540
+ command: "programs apply",
541
+ description: "Apply to a public program from programs discover, with a short note to the brand. The brand approves or declines; approval makes you a creator in the program and emails you. Free: 0 credits.",
542
+ fields: [
543
+ { name: "program_id", kind: "string", description: "Public program ID from programs discover.", required: true },
544
+ { name: "message", kind: "string", description: "Your note to the brand (up to 600 characters).", required: true },
545
+ { name: "linkedin_url", kind: "string", description: "Your LinkedIn profile URL; passing it also saves it to your profile. Omit to use the one on your profile (ugc profile get); if neither exists, ask the person rather than guess.", required: false },
546
+ ],
547
+ },
548
+ {
549
+ action: "application_decide",
550
+ command: "creators approve",
551
+ description: "Approve a pending application to your program (from applications list --program-id). The applicant becomes a creator at once and is emailed. Free: 0 credits.",
552
+ fixed: { decision: "approve" },
553
+ fields: [
554
+ { name: "program_id", kind: "string", description: "Program ID.", required: true },
555
+ { name: "application_id", kind: "string", description: "Pending application ID.", required: true },
556
+ ],
557
+ },
558
+ {
559
+ action: "application_decide",
560
+ command: "creators decline",
561
+ description: "Decline a pending application to your program. No email is sent. Free: 0 credits.",
562
+ fixed: { decision: "decline" },
563
+ fields: [
564
+ { name: "program_id", kind: "string", description: "Program ID.", required: true },
565
+ { name: "application_id", kind: "string", description: "Pending application ID.", required: true },
566
+ ],
567
+ },
568
+ {
569
+ action: "creator_profile_update",
570
+ command: "profile update",
571
+ description: "Save your creator profile, which brands whose programs you joined can read. --topics replaces the list; --audience \"\" clears it. Free: 0 credits.",
572
+ fields: [
573
+ {
574
+ name: "topics",
575
+ kind: "text_list",
576
+ description: "Topics you post about, comma-separated (up to 10, each up to 40 characters), e.g. \"B2B sales, outbound\".",
577
+ required: false,
578
+ },
579
+ {
580
+ name: "audience",
581
+ kind: "string",
582
+ description: "Who follows you, one line (up to 200 characters).",
583
+ required: false,
584
+ },
585
+ {
586
+ name: "linkedin_url",
587
+ kind: "string",
588
+ description: "Your LinkedIn profile URL, used when you apply to public programs; \"\" clears it.",
589
+ required: false,
590
+ },
591
+ ],
592
+ },
593
+ {
594
+ action: "creator_target_update",
595
+ command: "creators set-target",
596
+ description: "Set one creator's own posting deal, e.g. 1/month while the program asks for 2/month, on a joined creator (--participation-id) or a pending invitation (--invitation-id). none returns them to the program standard. Organizer only. Free: 0 credits.",
597
+ fields: [
598
+ {
599
+ name: "program_id",
600
+ kind: "string",
601
+ description: "Program ID.",
602
+ required: true,
603
+ },
604
+ {
605
+ name: "participation_id",
606
+ kind: "string",
607
+ description: "A joined creator's participation ID from creators list.",
608
+ required: false,
609
+ },
610
+ {
611
+ name: "invitation_id",
612
+ kind: "string",
613
+ description: "A pending invitation ID from creators list.",
614
+ required: false,
615
+ },
616
+ {
617
+ name: "posting_target",
618
+ kind: "posting_target",
619
+ description: "The creator's deal: <n>/month, <n>/week or <n>/total (n 1–100), or none for the program standard.",
620
+ required: true,
621
+ },
622
+ ],
623
+ },
471
624
  {
472
625
  action: "invite_send",
473
626
  command: "creators send-invite",
@@ -485,6 +638,18 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
485
638
  description: "Exact pending invitation ID from creators list.",
486
639
  required: true,
487
640
  },
641
+ {
642
+ name: "email_subject",
643
+ kind: "string",
644
+ description: "Your own email subject (up to 200 characters); omit for the default.",
645
+ required: false,
646
+ },
647
+ {
648
+ name: "email_message",
649
+ kind: "string",
650
+ description: "Your own message (up to 3,000 characters); the Accept button and join link are always added below it. Omit for the default.",
651
+ required: false,
652
+ },
488
653
  {
489
654
  name: "approved",
490
655
  kind: "boolean",
@@ -521,7 +686,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
521
686
  {
522
687
  action: "invite_accept",
523
688
  command: "creators accept",
524
- description: "Accept an exact invitation in the creator workspace and choose who may approve.",
689
+ description: "Accept an exact invitation in the creator workspace. Check it first with creators invitation --token; a refusal names its reason (wrong account, the program's own workspace, withdrawn or expired).",
525
690
  fields: [
526
691
  {
527
692
  name: "token",
@@ -532,8 +697,8 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
532
697
  {
533
698
  name: "approval_mode",
534
699
  kind: "string",
535
- description: "creator: creator approves; delegated: master operators may approve and schedule.",
536
- required: true,
700
+ description: "creator (default): you approve each post; delegated: master operators may approve and schedule.",
701
+ required: false,
537
702
  },
538
703
  {
539
704
  name: "linkedin_url",
@@ -574,86 +739,6 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
574
739
  },
575
740
  ],
576
741
  },
577
- {
578
- action: "brief_create",
579
- command: "briefs create",
580
- description: "Create a brief with ordered questions. Free: 0 credits, no provider call.",
581
- fields: [
582
- {
583
- name: "program_id",
584
- kind: "string",
585
- description: "Program ID.",
586
- required: true,
587
- },
588
- {
589
- name: "title",
590
- kind: "string",
591
- description: "Brief or post title.",
592
- required: true,
593
- },
594
- {
595
- name: "prompt",
596
- kind: "string",
597
- description: "Instructions for this brief.",
598
- required: true,
599
- },
600
- {
601
- name: "questions",
602
- kind: "array",
603
- description: "Ordered questions for the creator.",
604
- required: true,
605
- },
606
- {
607
- name: "cycle",
608
- kind: "string",
609
- description: "Brief cycle label.",
610
- required: false,
611
- },
612
- ],
613
- },
614
- {
615
- action: "brief_update",
616
- command: "briefs update",
617
- description: "Update a program brief.",
618
- fields: [
619
- {
620
- name: "program_id",
621
- kind: "string",
622
- description: "Program ID.",
623
- required: true,
624
- },
625
- {
626
- name: "brief_id",
627
- kind: "string",
628
- description: "Brief ID.",
629
- required: true,
630
- },
631
- {
632
- name: "title",
633
- kind: "string",
634
- description: "Brief or post title.",
635
- required: false,
636
- },
637
- {
638
- name: "prompt",
639
- kind: "string",
640
- description: "Instructions for this brief.",
641
- required: false,
642
- },
643
- {
644
- name: "questions",
645
- kind: "array",
646
- description: "Ordered questions for the creator.",
647
- required: false,
648
- },
649
- {
650
- name: "cycle",
651
- kind: "string",
652
- description: "Brief cycle label.",
653
- required: false,
654
- },
655
- ],
656
- },
657
742
  {
658
743
  action: "post_enroll",
659
744
  command: "posts enroll",
@@ -707,12 +792,21 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
707
792
  {
708
793
  action: "draft_create",
709
794
  command: "posts draft",
710
- description: "Preview AI drafting from brief answers. Execute only in the creator workspace with approved and a credit ceiling; publishing delegation does not grant authority to spend creator credits.",
795
+ description: "Draft a post from your topic in your voice, grounded in the program's shared pages. A bare call is a free preview; the creator repeats it with --request-id --approved --max-credits to run it.",
796
+ help: [
797
+ "",
798
+ "Two steps:",
799
+ " 1. Free preview (0 credits): run without --approved. It returns request_id and estimated_credits.",
800
+ " 2. Paid draft: from the creator's own workspace, repeat with --request-id <id> --approved --max-credits <ceiling>.",
801
+ "An organizer with delegated approval may preview but can never spend the creator's credits.",
802
+ "After a timeout, keep the same request_id and check `ugc posts draft-status`.",
803
+ "If the result has needs_answers with questions, add those details to --topic and preview again.",
804
+ ].join("\n"),
711
805
  fields: [
712
806
  {
713
807
  name: "request_id",
714
808
  kind: "string",
715
- description: "Request ID from preview. Reuse it after a timeout; a new ID is a new paid draft.",
809
+ description: "request_id returned by the free preview. Reuse it after a timeout; a new ID is a new paid draft.",
716
810
  required: false,
717
811
  },
718
812
  {
@@ -722,15 +816,9 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
722
816
  required: true,
723
817
  },
724
818
  {
725
- name: "brief_id",
819
+ name: "topic",
726
820
  kind: "string",
727
- description: "Brief ID.",
728
- required: true,
729
- },
730
- {
731
- name: "answers",
732
- kind: "array",
733
- description: "Answers in brief question order.",
821
+ description: "What you want to post about, including any personal experience to share (up to 4000 characters).",
734
822
  required: true,
735
823
  },
736
824
  {
@@ -742,7 +830,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
742
830
  {
743
831
  name: "max_credits",
744
832
  kind: "number",
745
- description: "Explicit credit ceiling from preview.",
833
+ description: "Credit ceiling for the paid run, at least the preview's estimate.",
746
834
  required: false,
747
835
  },
748
836
  ],
@@ -773,7 +861,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
773
861
  {
774
862
  name: "title",
775
863
  kind: "string",
776
- description: "Brief or post title.",
864
+ description: "Post title.",
777
865
  required: false,
778
866
  },
779
867
  {
@@ -788,6 +876,12 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
788
876
  description: "Future ISO-8601 publishing time with timezone.",
789
877
  required: false,
790
878
  },
879
+ {
880
+ name: "approve",
881
+ kind: "boolean",
882
+ description: "Your own post: true approves exactly what this saves, so it schedules without a separate posts approve. Signed-in creator only; brand review still applies.",
883
+ required: false,
884
+ },
791
885
  ],
792
886
  },
793
887
  {
@@ -1001,6 +1095,43 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
1001
1095
  },
1002
1096
  ],
1003
1097
  },
1098
+ {
1099
+ action: "comment_schedule",
1100
+ command: "posts comment schedule",
1101
+ description: "Schedule one exact comment on a creator's program post from one of this workspace's LinkedIn accounts; on a post not live yet it waits. Organizer workspace only. A bare call is a free preview; repeat with --approved to schedule it. 0 credits.",
1102
+ help: [
1103
+ "",
1104
+ "Two steps:",
1105
+ " 1. Preview (free, nothing saved): run without --approved. It shows the post, the account, the exact text and when it runs.",
1106
+ " 2. Schedule: repeat the same command with --approved from a signed-in session. The comment posts publicly on LinkedIn at --at,",
1107
+ " inside the account's active hours and daily comment limit; it can be cancelled until it runs.",
1108
+ "",
1109
+ "The post need not be live. Live means published through OXYGEN, with a LinkedIn post OXYGEN has confirmed.",
1110
+ "On a draft, in-review or scheduled post, or one shown as published without a confirmed LinkedIn post, the",
1111
+ "comment waits (waiting_for_post: true) and posts once the post is live, not before --at. If the post is still",
1112
+ "not live 14 days after --at, the comment fails and is never posted. A removed post cannot take a comment.",
1113
+ "Find post IDs with `oxygen ugc posts list --program-id <id>` and LinkedIn accounts with `oxygen senders list --json`.",
1114
+ "Check the result with `oxygen ugc posts list --program-id <id> --post-id <id>` (scheduled_comments).",
1115
+ ].join("\n"),
1116
+ fields: [
1117
+ { name: "program_id", kind: "string", description: "Program ID.", required: true },
1118
+ { name: "post_id", kind: "string", description: "Program post ID (post_id from posts list); it need not be live yet.", required: true },
1119
+ { name: "sender_account_id", kind: "string", description: "LinkedIn account connected in this workspace that posts the comment.", required: true },
1120
+ { name: "text", kind: "string", description: "Exact comment text, 1–1250 characters.", required: true },
1121
+ { name: "scheduled_for", flag: "at", kind: "string", description: "When to post: an ISO datetime with offset, or now.", required: true },
1122
+ { name: "approved", kind: "boolean", description: "Schedule the exact previewed comment. Never inferred.", required: false },
1123
+ { name: "max_credits", kind: "number", description: "Optional credit ceiling; the comment itself costs 0 credits.", required: false },
1124
+ ],
1125
+ },
1126
+ {
1127
+ action: "comment_cancel",
1128
+ command: "posts comment cancel",
1129
+ description: "Cancel a scheduled comment before it runs, including one still waiting for its post. Organizer workspace only; a comment that is already posting or posted cannot be cancelled.",
1130
+ fields: [
1131
+ { name: "program_id", kind: "string", description: "Program ID.", required: true },
1132
+ { name: "comment_id", kind: "string", description: "Scheduled comment ID from the post's scheduled_comments.", required: true },
1133
+ ],
1134
+ },
1004
1135
  {
1005
1136
  action: "amplification_reconcile",
1006
1137
  command: "amplification reconcile",
@@ -1076,7 +1207,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
1076
1207
  {
1077
1208
  name: "max_actions_per_post",
1078
1209
  kind: "number",
1079
- description: "Hard limit for amplification actions on each enrolled published post.",
1210
+ description: "Hard limit for amplification actions on each enrolled published post, at most 12.",
1080
1211
  required: true,
1081
1212
  },
1082
1213
  {
@@ -1091,6 +1222,13 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
1091
1222
  description: "Explicit authorization of the exact preview or approval. Never inferred.",
1092
1223
  required: false,
1093
1224
  },
1225
+ {
1226
+ name: "risk_acknowledged",
1227
+ flag: "acknowledge_risk",
1228
+ kind: "boolean",
1229
+ description: "Acknowledge that LinkedIn may warn, restrict or close accounts used for automated engagement. Required to enable.",
1230
+ required: false,
1231
+ },
1094
1232
  {
1095
1233
  name: "delay_min_seconds",
1096
1234
  kind: "number",
@@ -1116,9 +1254,10 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
1116
1254
  { name: "actions", kind: "array", description: "Allowed peer actions: reaction, comment or repost.", required: true },
1117
1255
  { name: "enabled", kind: "boolean", description: "Enable or disable this creator-owned policy.", required: true },
1118
1256
  { name: "expected_policy_version", kind: "number", description: "Current policy version from peer-amplification get; omit or use 0 on first save.", required: false },
1119
- { name: "max_actions_per_post", kind: "number", description: "Hard action cap per peer post.", required: true },
1257
+ { name: "max_actions_per_post", kind: "number", description: "Hard action cap per peer post, at most 12.", required: true },
1120
1258
  { name: "max_credits_per_cycle", kind: "number", description: "Hard creator-wallet credit cap per cycle.", required: true },
1121
1259
  { name: "approved", kind: "boolean", description: "Confirm this exact creator-owned scope; omit for preview.", required: false },
1260
+ { name: "risk_acknowledged", flag: "acknowledge_risk", kind: "boolean", description: "Acknowledge that LinkedIn may warn, restrict or close accounts used for automated engagement. Required to enable.", required: false },
1122
1261
  { name: "delay_min_seconds", kind: "number", description: "Minimum delay, 60–3600 seconds.", required: false },
1123
1262
  { name: "delay_max_seconds", kind: "number", description: "Maximum delay, 60–86400 seconds.", required: false },
1124
1263
  ],
@@ -1136,18 +1275,33 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
1136
1275
  ],
1137
1276
  },
1138
1277
  ];
1278
+ const subcommandDescriptions = {
1279
+ "posts comment": "One-off comments on a program post, live or not yet live: preview, schedule with approval, cancel.",
1280
+ };
1139
1281
  for (const spec of writes) {
1140
- const [family, leaf] = spec.command.split(" ");
1141
- const command = group(family).command(leaf).description(spec.description);
1282
+ const [family, ...path] = spec.command.split(" ");
1283
+ let parent = group(family);
1284
+ for (const [index, name] of path.slice(0, -1).entries()) {
1285
+ const existing = parent.commands.find((child) => child.name() === name);
1286
+ parent =
1287
+ existing ??
1288
+ parent
1289
+ .command(name)
1290
+ .description(subcommandDescriptions[[family, ...path.slice(0, index + 1)].join(" ")] ??
1291
+ name);
1292
+ }
1293
+ const command = parent.command(path.at(-1)).description(spec.description);
1294
+ if (spec.help)
1295
+ command.addHelpText("after", spec.help);
1142
1296
  for (const field of spec.fields) {
1143
- const flag = `--${field.name.replaceAll("_", "-")}${field.name === "approved" ? "" : ` <${field.kind === "array" || field.kind === "object" ? "json" : field.kind === "boolean" ? "true|false" : "value"}>`}`;
1297
+ const flag = `--${(field.flag ?? field.name).replaceAll("_", "-")}${field.name === "approved" || field.name === "risk_acknowledged" ? "" : ` <${field.kind === "array" || field.kind === "object" ? "json" : field.kind === "boolean" ? "true|false" : field.kind === "posting_target" ? "n/month|n/week|n/total|none" : field.kind === "email_list" ? "emails" : field.kind === "text_list" ? "a, b" : "value"}>`}`;
1144
1298
  if (field.required)
1145
1299
  command.requiredOption(flag, field.description);
1146
1300
  else
1147
1301
  command.option(flag, field.description);
1148
1302
  }
1149
1303
  if (spec.action === "invite_create")
1150
- command.option("--link-only", "Create a shareable link without sending email.");
1304
+ command.option("--link-only", "Create the invitation now and return its shareable link: no preview or approval token, no email, 0 credits.");
1151
1305
  command
1152
1306
  .option("--json", "Print a JSON envelope.")
1153
1307
  .action((options) => handle(`ugc ${spec.command}`, options, () => {
@@ -1156,11 +1310,13 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
1156
1310
  ...(spec.fixed ?? {}),
1157
1311
  };
1158
1312
  for (const field of spec.fields) {
1159
- const key = field.name.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1313
+ const key = (field.flag ?? field.name).replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1160
1314
  if (options[key] !== undefined)
1161
1315
  body[field.name] = parseField(options[key], field);
1162
1316
  }
1163
1317
  if (spec.action === "invite_create") {
1318
+ if ((body.email === undefined) === (body.emails === undefined))
1319
+ throw new Error("Pass exactly one of --email or --emails.");
1164
1320
  body.send_email = options.linkOnly !== true;
1165
1321
  if (options.linkOnly && (body.approved || body.preview_token))
1166
1322
  throw new Error("--link-only cannot be combined with --approved or --preview-token.");