@oxygen-agent/cli 1.982.3 → 1.1003.12

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 (127) 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/command-manifest.d.ts +3 -2
  6. package/dist/command-manifest.js +10 -0
  7. package/dist/credentials.d.ts +1 -1
  8. package/dist/functions-commands.js +27 -7
  9. package/dist/help.d.ts +29 -0
  10. package/dist/help.js +139 -0
  11. package/dist/index.js +1875 -164
  12. package/dist/knowledge-mirror.d.ts +2 -2
  13. package/dist/runtime.d.ts +0 -15
  14. package/dist/runtime.js +1 -1
  15. package/dist/session.d.ts +4 -3
  16. package/dist/skills.d.ts +8 -7
  17. package/dist/skills.js +24 -10
  18. package/dist/transcript.d.ts +2 -1
  19. package/dist/ugc-commands.d.ts +3 -6
  20. package/dist/ugc-commands.js +2 -1200
  21. package/dist/util.d.ts +1 -1
  22. package/dist/util.js +1 -3
  23. package/node_modules/@oxygen/cli-ugc/dist/commands.d.ts +3 -0
  24. package/node_modules/@oxygen/cli-ugc/dist/commands.js +1178 -0
  25. package/node_modules/@oxygen/cli-ugc/dist/field-parser.d.ts +7 -0
  26. package/node_modules/@oxygen/cli-ugc/dist/field-parser.js +25 -0
  27. package/node_modules/@oxygen/cli-ugc/dist/index.d.ts +14 -0
  28. package/node_modules/@oxygen/cli-ugc/dist/index.js +5 -0
  29. package/node_modules/@oxygen/cli-ugc/package.json +15 -0
  30. package/node_modules/@oxygen/formula/dist/coerce.d.ts +10 -0
  31. package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
  32. package/node_modules/@oxygen/formula/dist/expression.js +14 -1
  33. package/node_modules/@oxygen/formula/dist/formula-functions.js +136 -1
  34. package/node_modules/@oxygen/formula/dist/hash.d.ts +19 -0
  35. package/node_modules/@oxygen/formula/dist/hash.js +199 -0
  36. package/node_modules/@oxygen/formula/dist/index.d.ts +1 -0
  37. package/node_modules/@oxygen/formula/dist/index.js +1 -0
  38. package/node_modules/@oxygen/formula/dist/value-cleaners.d.ts +74 -0
  39. package/node_modules/@oxygen/formula/dist/value-cleaners.js +358 -0
  40. package/node_modules/@oxygen/shared/dist/array-utils.d.ts +5 -0
  41. package/node_modules/@oxygen/shared/dist/array-utils.js +11 -0
  42. package/node_modules/@oxygen/shared/dist/billing.d.ts +103 -47
  43. package/node_modules/@oxygen/shared/dist/billing.js +150 -40
  44. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +17 -0
  45. package/node_modules/@oxygen/shared/dist/capability-discovery.js +114 -16
  46. package/node_modules/@oxygen/shared/dist/column-autofill.d.ts +52 -0
  47. package/node_modules/@oxygen/shared/dist/column-autofill.js +80 -0
  48. package/node_modules/@oxygen/shared/dist/column-output-fields.js +14 -10
  49. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.d.ts +108 -0
  50. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.js +545 -0
  51. package/node_modules/@oxygen/shared/dist/copilot-playbooks.d.ts +18 -0
  52. package/node_modules/@oxygen/shared/dist/copilot-playbooks.js +43 -0
  53. package/node_modules/@oxygen/shared/dist/copilot-skills.d.ts +15 -0
  54. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +31 -0
  55. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +41 -0
  56. package/node_modules/@oxygen/shared/dist/copilot-skills.js +6 -0
  57. package/node_modules/@oxygen/shared/dist/deploy-env.d.ts +74 -0
  58. package/node_modules/@oxygen/shared/dist/deploy-env.js +82 -0
  59. package/node_modules/@oxygen/shared/dist/dnc-rules.d.ts +130 -0
  60. package/node_modules/@oxygen/shared/dist/dnc-rules.js +221 -0
  61. package/node_modules/@oxygen/shared/dist/enrichment-intents.d.ts +103 -0
  62. package/node_modules/@oxygen/shared/dist/enrichment-intents.js +819 -0
  63. package/node_modules/@oxygen/shared/dist/error-message.d.ts +1 -0
  64. package/node_modules/@oxygen/shared/dist/error-message.js +3 -0
  65. package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -3
  66. package/node_modules/@oxygen/shared/dist/external-write-policy.d.ts +33 -0
  67. package/node_modules/@oxygen/shared/dist/external-write-policy.js +68 -0
  68. package/node_modules/@oxygen/shared/dist/format-percent.d.ts +8 -0
  69. package/node_modules/@oxygen/shared/dist/format-percent.js +13 -0
  70. package/node_modules/@oxygen/shared/dist/freemail-domains.d.ts +81 -0
  71. package/node_modules/@oxygen/shared/dist/freemail-domains.js +157 -0
  72. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.d.ts +1 -0
  73. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.js +1 -1
  74. package/node_modules/@oxygen/shared/dist/index.d.ts +14 -0
  75. package/node_modules/@oxygen/shared/dist/index.js +14 -0
  76. package/node_modules/@oxygen/shared/dist/json-path.js +1 -3
  77. package/node_modules/@oxygen/shared/dist/knowledge-bases.js +1 -3
  78. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +17 -2
  79. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +28 -6
  80. package/node_modules/@oxygen/shared/dist/langfuse.d.ts +12 -1
  81. package/node_modules/@oxygen/shared/dist/langfuse.js +57 -8
  82. package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +32 -0
  83. package/node_modules/@oxygen/shared/dist/linkedin-countries.js +359 -0
  84. package/node_modules/@oxygen/shared/dist/log-sink-selector.d.ts +39 -0
  85. package/node_modules/@oxygen/shared/dist/log-sink-selector.js +56 -0
  86. package/node_modules/@oxygen/shared/dist/log.d.ts +1 -0
  87. package/node_modules/@oxygen/shared/dist/log.js +6 -1
  88. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +17 -0
  89. package/node_modules/@oxygen/shared/dist/object-storage.js +21 -0
  90. package/node_modules/@oxygen/shared/dist/otlp-log-sink.d.ts +54 -0
  91. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +213 -0
  92. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +1 -0
  93. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +23 -22
  94. package/node_modules/@oxygen/shared/dist/plan-limits.js +45 -18
  95. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +48 -41
  96. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +36 -25
  97. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +22 -22
  98. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +40 -34
  99. package/node_modules/@oxygen/shared/dist/product-analytics-environment.js +9 -0
  100. package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +15 -0
  101. package/node_modules/@oxygen/shared/dist/product-analytics-events.js +15 -0
  102. package/node_modules/@oxygen/shared/dist/rate-window.d.ts +5 -0
  103. package/node_modules/@oxygen/shared/dist/rate-window.js +8 -0
  104. package/node_modules/@oxygen/shared/dist/research-output-contract.d.ts +33 -1
  105. package/node_modules/@oxygen/shared/dist/research-output-contract.js +65 -5
  106. package/node_modules/@oxygen/shared/dist/search-vocab.js +4 -5
  107. package/node_modules/@oxygen/shared/dist/select-options.js +6 -1
  108. package/node_modules/@oxygen/shared/dist/sequence-crm-events.d.ts +1 -1
  109. package/node_modules/@oxygen/shared/dist/sequence-failures.js +1 -5
  110. package/node_modules/@oxygen/shared/dist/sequence-hubspot-sync.d.ts +1 -1
  111. package/node_modules/@oxygen/shared/dist/sequences.d.ts +49 -0
  112. package/node_modules/@oxygen/shared/dist/sequences.js +134 -4
  113. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +22 -10
  114. package/node_modules/@oxygen/shared/dist/spend-safety.js +15 -21
  115. package/node_modules/@oxygen/shared/dist/sql-rows.d.ts +1 -0
  116. package/node_modules/@oxygen/shared/dist/sql-rows.js +3 -0
  117. package/node_modules/@oxygen/shared/dist/telemetry.js +9 -1
  118. package/node_modules/@oxygen/shared/dist/type-guards.d.ts +22 -0
  119. package/node_modules/@oxygen/shared/dist/type-guards.js +35 -0
  120. package/node_modules/@oxygen/shared/dist/value-readers.d.ts +21 -0
  121. package/node_modules/@oxygen/shared/dist/value-readers.js +59 -0
  122. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  123. package/node_modules/@oxygen/shared/package.json +60 -0
  124. package/node_modules/@oxygen/workflows/dist/graph/expression.js +2 -5
  125. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +15 -15
  126. package/node_modules/@oxygen/workflows/dist/graph/params.js +1 -1
  127. package/package.json +6 -3
@@ -1,1203 +1,5 @@
1
+ import { registerUgcCommands as registerCommands, } from "@oxygen/cli-ugc";
1
2
  import { requestOxygen } from "./http-client.js";
2
- function parseField(value, field) {
3
- if (field.kind === "array" || field.kind === "object") {
4
- const parsed = JSON.parse(String(value));
5
- if (field.kind === "array"
6
- ? !Array.isArray(parsed) ||
7
- !parsed.every((item) => typeof item === "string")
8
- : !parsed || typeof parsed !== "object" || Array.isArray(parsed))
9
- throw new Error(`${field.name} must be a JSON ${field.kind === "array" ? "array of strings" : "object"}.`);
10
- return parsed;
11
- }
12
- if (field.kind === "number") {
13
- const parsed = Number(value);
14
- if (!Number.isFinite(parsed) || parsed < 0)
15
- throw new Error(`${field.name} must be a nonnegative finite number.`);
16
- return parsed;
17
- }
18
- if (field.kind === "boolean") {
19
- if (value === true || value === "true")
20
- return true;
21
- if (value === false || value === "false")
22
- return false;
23
- throw new Error(`${field.name} must be true or false.`);
24
- }
25
- return value;
26
- }
27
3
  export function registerUgcCommands(program, handle) {
28
- const ugc = program
29
- .command("ugc")
30
- .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.");
31
- const groupDescriptions = {
32
- 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).",
33
- creators: "Creator participations: invite, revoke an invite, accept in the creator workspace, connect a sender, change approval authority, or revoke.",
34
- memberships: "Active programs this creator workspace has joined. Read these before choosing a program for a personal post.",
35
- briefs: "Program briefs with ordered questions for creators.",
36
- posts: "Enrolled program posts: enroll existing posts, draft from briefs, edit, schedule, and record creator or brand approval.",
37
- analytics: "Stored daily program and creator performance.",
38
- knowledge: "Master Knowledge pages shared live with a program.",
39
- voice: "Creator voice profiles and imports.",
40
- sponsorship: "Seat and credit sponsorship per participation.",
41
- amplification: "Bounded, approval-gated amplification of enrolled posts.",
42
- "peer-amplification": "Creator-owned consent, sender, voice, caps and immutable receipts for engaging with peer posts in one program.",
43
- calendar: "Bounded enrolled-post calendar reads.",
44
- };
45
- const groups = new Map();
46
- const group = (name) => {
47
- let command = groups.get(name);
48
- if (!command) {
49
- command = ugc.command(name);
50
- const description = groupDescriptions[name];
51
- if (description)
52
- command.description(description);
53
- groups.set(name, command);
54
- }
55
- return command;
56
- };
57
- group("programs")
58
- .command("list")
59
- .description("Read UGC programs in the active workspace, archived ones included unless --status filters. Read-only.")
60
- .option("--program-id <id>", "Program ID.")
61
- .option("--participation-id <id>", "Creator participation ID.")
62
- .option("--status <active|archived>", "Only programs in this status.")
63
- .option("--json", "Print a JSON envelope.")
64
- .action((options) => handle("ugc programs list", options, () => {
65
- const query = new URLSearchParams({ view: "programs" });
66
- if (options.programId)
67
- query.set("program_id", String(options.programId));
68
- if (options.participationId)
69
- query.set("participation_id", String(options.participationId));
70
- if (options.status)
71
- query.set("status", String(options.status));
72
- return requestOxygen(`/api/cli/ugc?${query}`);
73
- }));
74
- group("programs")
75
- .command("get")
76
- .description("Read UGC program in the active workspace. Read-only.")
77
- .requiredOption("--program-id <id>", "Program ID.")
78
- .option("--participation-id <id>", "Creator participation ID.")
79
- .option("--json", "Print a JSON envelope.")
80
- .action((options) => handle("ugc programs get", options, () => {
81
- const query = new URLSearchParams({ view: "program" });
82
- if (options.programId)
83
- query.set("program_id", String(options.programId));
84
- if (options.participationId)
85
- query.set("participation_id", String(options.participationId));
86
- return requestOxygen(`/api/cli/ugc?${query}`);
87
- }));
88
- group("creators")
89
- .command("list")
90
- .description("Read creators and invitations, including persisted email delivery status. Read-only.")
91
- .option("--program-id <id>", "Program ID.")
92
- .option("--participation-id <id>", "Creator participation ID.")
93
- .option("--json", "Print a JSON envelope.")
94
- .action((options) => handle("ugc creators list", options, () => {
95
- const query = new URLSearchParams({ view: "participations" });
96
- if (options.programId)
97
- query.set("program_id", String(options.programId));
98
- if (options.participationId)
99
- query.set("participation_id", String(options.participationId));
100
- return requestOxygen(`/api/cli/ugc?${query}`);
101
- }));
102
- group("memberships")
103
- .command("list")
104
- .description("Read active program memberships for the creator workspace. Free, stored and provider-free.")
105
- .option("--json", "Print a JSON envelope.")
106
- .action((options) => handle("ugc memberships list", options, () => requestOxygen("/api/cli/ugc?view=memberships")));
107
- group("briefs")
108
- .command("list")
109
- .description("Read one program's UGC briefs. Read-only; requires --program-id.")
110
- .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\`.`)
111
- .requiredOption("--program-id <id>", "Program ID.")
112
- .option("--participation-id <id>", "Creator participation ID.")
113
- .option("--json", "Print a JSON envelope.")
114
- .action((options) => handle("ugc briefs list", options, () => {
115
- const query = new URLSearchParams({ view: "briefs" });
116
- if (options.programId)
117
- query.set("program_id", String(options.programId));
118
- if (options.participationId)
119
- query.set("participation_id", String(options.participationId));
120
- return requestOxygen(`/api/cli/ugc?${query}`);
121
- }));
122
- group("posts")
123
- .command("list")
124
- .description("Read UGC posts in the active workspace. Read-only.")
125
- .requiredOption("--program-id <id>", "Program ID.")
126
- .option("--participation-id <id>", "Creator participation ID.")
127
- .option("--post-id <id>", "Read one canonical post ID.")
128
- .option("--enrollment-version <n>", "Read one exact enrollment version after a post was removed and re-added.")
129
- .option("--cursor <cursor>", "Opaque next_cursor from the previous page.")
130
- .option("--limit <count>", "Posts per page, 1–500.")
131
- .option("--json", "Print a JSON envelope.")
132
- .action((options) => handle("ugc posts list", options, () => {
133
- const query = new URLSearchParams({ view: "posts" });
134
- if (options.programId)
135
- query.set("program_id", String(options.programId));
136
- if (options.participationId)
137
- query.set("participation_id", String(options.participationId));
138
- if (options.postId)
139
- query.set("post_id", String(options.postId));
140
- if (options.enrollmentVersion)
141
- query.set("enrollment_version", String(options.enrollmentVersion));
142
- if (options.cursor)
143
- query.set("cursor", String(options.cursor));
144
- if (options.limit)
145
- query.set("limit", String(options.limit));
146
- return requestOxygen(`/api/cli/ugc?${query}`);
147
- }));
148
- group("analytics")
149
- .command("get")
150
- .description("Read UGC analytics in the active workspace. Read-only.")
151
- .requiredOption("--program-id <id>", "Program ID.")
152
- .option("--participation-id <id>", "Creator participation ID.")
153
- .option("--post-cursor <cursor>", "Next post_performance page from next_post_cursor; totals still cover all enrolled posts.")
154
- .option("--limit <count>", "Post performance rows per page, up to 100.")
155
- .option("--json", "Print a JSON envelope.")
156
- .action((options) => handle("ugc analytics get", options, () => {
157
- const query = new URLSearchParams({ view: "analytics" });
158
- if (options.programId)
159
- query.set("program_id", String(options.programId));
160
- if (options.participationId)
161
- query.set("participation_id", String(options.participationId));
162
- if (options.postCursor)
163
- query.set("post_cursor", String(options.postCursor));
164
- if (options.limit)
165
- query.set("limit", String(options.limit));
166
- return requestOxygen(`/api/cli/ugc?${query}`);
167
- }));
168
- group("knowledge")
169
- .command("list")
170
- .description("Read UGC knowledge in the active workspace. Read-only.")
171
- .requiredOption("--program-id <id>", "Program ID.")
172
- .option("--participation-id <id>", "Creator participation ID.")
173
- .option("--json", "Print a JSON envelope.")
174
- .action((options) => handle("ugc knowledge list", options, () => {
175
- const query = new URLSearchParams({ view: "knowledge" });
176
- if (options.programId)
177
- query.set("program_id", String(options.programId));
178
- if (options.participationId)
179
- query.set("participation_id", String(options.participationId));
180
- return requestOxygen(`/api/cli/ugc?${query}`);
181
- }));
182
- group("voice")
183
- .command("get")
184
- .description("Read UGC voice in the active workspace. Read-only.")
185
- .option("--program-id <id>", "Program ID.")
186
- .requiredOption("--participation-id <id>", "Creator participation ID.")
187
- .option("--json", "Print a JSON envelope.")
188
- .action((options) => handle("ugc voice get", options, () => {
189
- const query = new URLSearchParams({ view: "voice" });
190
- if (options.programId)
191
- query.set("program_id", String(options.programId));
192
- if (options.participationId)
193
- query.set("participation_id", String(options.participationId));
194
- return requestOxygen(`/api/cli/ugc?${query}`);
195
- }));
196
- group("posts")
197
- .command("draft-status")
198
- .description("Read the original paid draft request and saved result without generating again. Creator workspace only, 0 credits.")
199
- .requiredOption("--participation-id <id>", "Creator participation ID.")
200
- .requiredOption("--request-id <id>", "Original draft request ID.")
201
- .option("--json", "Print a JSON envelope.")
202
- .action((options) => handle("ugc posts draft-status", options, () => {
203
- const query = new URLSearchParams({
204
- view: "draft_run",
205
- participation_id: String(options.participationId),
206
- request_id: String(options.requestId),
207
- });
208
- return requestOxygen(`/api/cli/ugc?${query}`);
209
- }));
210
- group("sponsorship")
211
- .command("get")
212
- .description("Read sponsorship in the active workspace. Creators see their remaining credits and exact organizer access; masters see program payment status. Read-only.")
213
- .requiredOption("--program-id <id>", "Program ID.")
214
- .option("--participation-id <id>", "Creator participation ID.")
215
- .option("--json", "Print a JSON envelope.")
216
- .action((options) => handle("ugc sponsorship get", options, () => {
217
- const query = new URLSearchParams({ view: "sponsorship" });
218
- if (options.programId)
219
- query.set("program_id", String(options.programId));
220
- if (options.participationId)
221
- query.set("participation_id", String(options.participationId));
222
- return requestOxygen(`/api/cli/ugc?${query}`);
223
- }));
224
- for (const spec of [
225
- {
226
- group: "calendar",
227
- command: "list",
228
- view: "calendar",
229
- description: "Read the program's enrolled post calendar in a bounded UTC date range (up to 42 days). Stored data only, 0 credits.",
230
- fields: [
231
- ["date_from", "Start ISO instant, inclusive.", true],
232
- ["date_to", "End ISO instant, exclusive.", true],
233
- [
234
- "calendar_cursor",
235
- "Calendar next_cursor from the previous page.",
236
- false,
237
- ],
238
- ["participation_id", "Filter to one creator participation.", false],
239
- ],
240
- },
241
- {
242
- group: "posts",
243
- command: "history",
244
- view: "post_history",
245
- description: "Read retained public comments, metrics, and publication receipts for one enrolled post. Stored data only, 0 credits.",
246
- fields: [
247
- ["post_id", "Enrolled source post UUID.", true],
248
- [
249
- "enrollment_version",
250
- "Exact enrollment_version returned by posts list; required to distinguish remove/re-enroll history.",
251
- true,
252
- ],
253
- ["participation_id", "Exact creator participation ID.", false],
254
- ["cursor", "next_comments_cursor from the previous page.", false],
255
- ["metric_cursor", "next_metrics_cursor from the previous page.", false],
256
- ["action_cursor", "next_actions_cursor from the previous page.", false],
257
- ],
258
- },
259
- {
260
- group: "amplification",
261
- command: "get",
262
- view: "amplification",
263
- description: "Read this program's current amplification authority and immutable action history. Master workspace only; 0 credits, no provider call.",
264
- fields: [["cursor", "next_cursor from the previous action page.", false]],
265
- },
266
- {
267
- group: "peer-amplification",
268
- command: "get",
269
- view: "peer_amplification",
270
- description: "Read this creator's own peer-engagement policy, host gate, readiness and immutable receipts. Creator workspace only; free and provider-free.",
271
- fields: [
272
- ["participation_id", "Exact creator participation ID.", true],
273
- ["cursor", "next_cursor from the previous action page.", false],
274
- ],
275
- programRequired: false,
276
- },
277
- ]) {
278
- const command = group(spec.group)
279
- .command(spec.command)
280
- .description(spec.description)
281
- .option("--limit <count>", "Rows per page, up to 100.")
282
- .option("--json", "Print a JSON envelope.");
283
- command["programRequired" in spec && spec.programRequired === false ? "option" : "requiredOption"]("--program-id <id>", "Program ID.");
284
- for (const [name, description, required] of spec.fields)
285
- command[required ? "requiredOption" : "option"](`--${name.replaceAll("_", "-")} <value>`, description);
286
- command.action((options) => handle(`ugc ${spec.group} ${spec.command}`, options, () => {
287
- const query = new URLSearchParams({ view: spec.view });
288
- if (options.programId)
289
- query.set("program_id", String(options.programId));
290
- for (const [name] of spec.fields) {
291
- const key = name.replace(/_([a-z])/g, (_match, letter) => letter.toUpperCase());
292
- if (options[key] !== undefined)
293
- query.set(name, String(options[key]));
294
- }
295
- if (options.limit)
296
- query.set("limit", String(options.limit));
297
- return requestOxygen(`/api/cli/ugc?${query}`);
298
- }));
299
- }
300
- const writes = [
301
- {
302
- action: "program_create",
303
- command: "programs create",
304
- description: "Create a master UGC program. Free: 0 credits, no provider call.",
305
- fields: [
306
- {
307
- name: "name",
308
- kind: "string",
309
- description: "Program name.",
310
- required: true,
311
- },
312
- {
313
- name: "product_url",
314
- kind: "string",
315
- description: "Product website URL.",
316
- required: true,
317
- },
318
- {
319
- name: "description",
320
- kind: "string",
321
- description: "Program description.",
322
- required: false,
323
- },
324
- {
325
- name: "knowledge_slugs",
326
- kind: "array",
327
- description: "Selected live master wiki slugs shared with creators; empty array clears sharing.",
328
- required: false,
329
- },
330
- {
331
- name: "brand_approval_required",
332
- kind: "boolean",
333
- description: "Require a separate brand approval before publishing.",
334
- required: false,
335
- },
336
- ],
337
- },
338
- {
339
- action: "program_update",
340
- command: "programs update",
341
- description: "Update program settings and selected shared knowledge.",
342
- fields: [
343
- {
344
- name: "program_id",
345
- kind: "string",
346
- description: "Program ID.",
347
- required: true,
348
- },
349
- {
350
- name: "name",
351
- kind: "string",
352
- description: "Program name.",
353
- required: false,
354
- },
355
- {
356
- name: "product_url",
357
- kind: "string",
358
- description: "Product website URL.",
359
- required: false,
360
- },
361
- {
362
- name: "description",
363
- kind: "string",
364
- description: "Program description.",
365
- required: false,
366
- },
367
- {
368
- name: "knowledge_slugs",
369
- kind: "array",
370
- description: "Selected live master wiki slugs shared with creators; empty array clears sharing.",
371
- required: false,
372
- },
373
- {
374
- name: "brand_approval_required",
375
- kind: "boolean",
376
- description: "Require a separate brand approval before publishing.",
377
- required: false,
378
- },
379
- {
380
- name: "peer_engagement_enabled",
381
- kind: "boolean",
382
- description: "Host permission for creators in this program to opt into peer engagement; enabling requires a signed-in master admin.",
383
- required: false,
384
- },
385
- {
386
- name: "status",
387
- kind: "string",
388
- description: "active or archived; prefer `programs archive` / `programs restore`.",
389
- required: false,
390
- },
391
- ],
392
- },
393
- {
394
- action: "program_update",
395
- command: "programs archive",
396
- description: "Archive a program: stop future access, publishing, tracking and amplification, revoke pending invitations and request cancellation of sponsorship renewals. Shared history is retained; `programs restore` re-activates it.",
397
- fixed: { status: "archived" },
398
- fields: [
399
- {
400
- name: "program_id",
401
- kind: "string",
402
- description: "Program ID.",
403
- required: true,
404
- },
405
- ],
406
- },
407
- {
408
- action: "program_update",
409
- command: "programs restore",
410
- description: "Restore an archived program. Creators removed earlier stay removed, revoked invitations stay revoked, and cancelled sponsorships need a new preview and confirmation.",
411
- fixed: { status: "active" },
412
- fields: [
413
- {
414
- name: "program_id",
415
- kind: "string",
416
- description: "Program ID.",
417
- required: true,
418
- },
419
- ],
420
- },
421
- {
422
- action: "program_duplicate",
423
- command: "programs duplicate",
424
- 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.",
425
- fields: [
426
- {
427
- name: "program_id",
428
- kind: "string",
429
- description: "Source program ID.",
430
- required: true,
431
- },
432
- {
433
- name: "name",
434
- kind: "string",
435
- description: 'Name of the copy; defaults to "<name> (copy)".',
436
- required: false,
437
- },
438
- {
439
- name: "include_briefs",
440
- kind: "boolean",
441
- description: "Copy the program's briefs (default true).",
442
- required: false,
443
- },
444
- ],
445
- },
446
- {
447
- action: "program_delete",
448
- command: "programs delete",
449
- 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`.",
450
- fields: [
451
- {
452
- name: "program_id",
453
- kind: "string",
454
- description: "Program ID.",
455
- required: true,
456
- },
457
- {
458
- name: "approved",
459
- kind: "boolean",
460
- description: "Confirm the previewed permanent deletion.",
461
- required: false,
462
- },
463
- ],
464
- },
465
- {
466
- action: "invite_create",
467
- command: "creators invite",
468
- description: "Preview an invitation email (0 credits); send with --approved --preview-token from that preview. Use --link-only to create a link without email.",
469
- fields: [
470
- {
471
- name: "program_id",
472
- kind: "string",
473
- description: "Program ID.",
474
- required: true,
475
- },
476
- {
477
- name: "email",
478
- kind: "string",
479
- description: "Exact creator email to receive the invitation.",
480
- required: true,
481
- },
482
- {
483
- name: "approved",
484
- kind: "boolean",
485
- description: "Authorize sending the exact previewed invitation email.",
486
- required: false,
487
- },
488
- {
489
- name: "preview_token",
490
- kind: "string",
491
- description: "Exact token from the invitation email preview.",
492
- required: false,
493
- },
494
- ],
495
- },
496
- {
497
- action: "invite_send",
498
- command: "creators send-invite",
499
- description: "Preview email for an existing pending invitation; send or resend with --approved --preview-token. Replaces the old link, keeps its expiry. Sent means provider accepted, not inbox delivery.",
500
- fields: [
501
- {
502
- name: "program_id",
503
- kind: "string",
504
- description: "Program ID.",
505
- required: true,
506
- },
507
- {
508
- name: "invitation_id",
509
- kind: "string",
510
- description: "Exact pending invitation ID from creators list.",
511
- required: true,
512
- },
513
- {
514
- name: "approved",
515
- kind: "boolean",
516
- description: "Authorize the exact previewed email send or resend.",
517
- required: false,
518
- },
519
- {
520
- name: "preview_token",
521
- kind: "string",
522
- description: "Exact token from this invitation email preview.",
523
- required: false,
524
- },
525
- ],
526
- },
527
- {
528
- action: "invite_revoke",
529
- command: "creators revoke-invite",
530
- description: "Revoke an unaccepted invitation.",
531
- fields: [
532
- {
533
- name: "program_id",
534
- kind: "string",
535
- description: "Program ID.",
536
- required: true,
537
- },
538
- {
539
- name: "invitation_id",
540
- kind: "string",
541
- description: "Exact invitation ID to revoke.",
542
- required: true,
543
- },
544
- ],
545
- },
546
- {
547
- action: "invite_accept",
548
- command: "creators accept",
549
- description: "Accept an exact invitation in the creator workspace and choose who may approve.",
550
- fields: [
551
- {
552
- name: "token",
553
- kind: "string",
554
- description: "Exact invitation token.",
555
- required: true,
556
- },
557
- {
558
- name: "approval_mode",
559
- kind: "string",
560
- description: "creator: creator approves; delegated: master operators may approve and schedule.",
561
- required: true,
562
- },
563
- {
564
- name: "linkedin_url",
565
- kind: "string",
566
- description: "Creator LinkedIn profile URL.",
567
- required: true,
568
- },
569
- ],
570
- },
571
- {
572
- action: "participation_update",
573
- command: "creators update",
574
- description: "Connect an existing LinkedIn sender, change approval authority, or leave the entire program. Revocation stops future sharing and program actions; your posts stay in your workspace and the organizer retains previously shared history. This workspace cannot currently rejoin the same program. To remove one post while staying, use ugc posts remove.",
575
- fields: [
576
- {
577
- name: "participation_id",
578
- kind: "string",
579
- description: "Creator participation ID.",
580
- required: true,
581
- },
582
- {
583
- name: "approval_mode",
584
- kind: "string",
585
- description: "creator: creator approves; delegated: master operators may approve and schedule.",
586
- required: false,
587
- },
588
- {
589
- name: "sender_account_id",
590
- kind: "string",
591
- description: "Existing physical LinkedIn connection ID; reused across programs.",
592
- required: false,
593
- },
594
- {
595
- name: "status",
596
- kind: "string",
597
- description: "Use revoked to leave the entire program. This participation cannot be restored.",
598
- required: false,
599
- },
600
- ],
601
- },
602
- {
603
- action: "brief_create",
604
- command: "briefs create",
605
- description: "Create a brief with ordered questions. Free: 0 credits, no provider call.",
606
- fields: [
607
- {
608
- name: "program_id",
609
- kind: "string",
610
- description: "Program ID.",
611
- required: true,
612
- },
613
- {
614
- name: "title",
615
- kind: "string",
616
- description: "Brief or post title.",
617
- required: true,
618
- },
619
- {
620
- name: "prompt",
621
- kind: "string",
622
- description: "Instructions for this brief.",
623
- required: true,
624
- },
625
- {
626
- name: "questions",
627
- kind: "array",
628
- description: "Ordered questions for the creator.",
629
- required: true,
630
- },
631
- {
632
- name: "cycle",
633
- kind: "string",
634
- description: "Brief cycle label.",
635
- required: false,
636
- },
637
- ],
638
- },
639
- {
640
- action: "brief_update",
641
- command: "briefs update",
642
- description: "Update a program brief.",
643
- fields: [
644
- {
645
- name: "program_id",
646
- kind: "string",
647
- description: "Program ID.",
648
- required: true,
649
- },
650
- {
651
- name: "brief_id",
652
- kind: "string",
653
- description: "Brief ID.",
654
- required: true,
655
- },
656
- {
657
- name: "title",
658
- kind: "string",
659
- description: "Brief or post title.",
660
- required: false,
661
- },
662
- {
663
- name: "prompt",
664
- kind: "string",
665
- description: "Instructions for this brief.",
666
- required: false,
667
- },
668
- {
669
- name: "questions",
670
- kind: "array",
671
- description: "Ordered questions for the creator.",
672
- required: false,
673
- },
674
- {
675
- name: "cycle",
676
- kind: "string",
677
- description: "Brief cycle label.",
678
- required: false,
679
- },
680
- ],
681
- },
682
- {
683
- action: "post_enroll",
684
- command: "posts enroll",
685
- description: "Enroll one existing creator-owned post in this participation.",
686
- fields: [
687
- {
688
- name: "participation_id",
689
- kind: "string",
690
- description: "Creator participation ID.",
691
- required: true,
692
- },
693
- {
694
- name: "post_id",
695
- kind: "string",
696
- description: "Canonical post ID.",
697
- required: true,
698
- },
699
- ],
700
- },
701
- {
702
- action: "post_remove",
703
- command: "posts remove",
704
- description: "Remove one creator-owned post from a program before publication while retaining immutable enrollment history. The personal draft remains in Publishing.",
705
- fields: [
706
- {
707
- name: "program_id",
708
- kind: "string",
709
- description: "Program ID.",
710
- required: true,
711
- },
712
- {
713
- name: "post_id",
714
- kind: "string",
715
- description: "Canonical personal post ID.",
716
- required: true,
717
- },
718
- {
719
- name: "enrollment_id",
720
- kind: "string",
721
- description: "Exact active enrollment ID returned by posts list.",
722
- required: true,
723
- },
724
- {
725
- name: "source_revision",
726
- kind: "string",
727
- description: "Exact current content fingerprint returned by posts list.",
728
- required: true,
729
- },
730
- ],
731
- },
732
- {
733
- action: "draft_create",
734
- command: "posts draft",
735
- 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.",
736
- fields: [
737
- {
738
- name: "request_id",
739
- kind: "string",
740
- description: "Request ID from preview. Reuse it after a timeout; a new ID is a new paid draft.",
741
- required: false,
742
- },
743
- {
744
- name: "participation_id",
745
- kind: "string",
746
- description: "Creator participation ID.",
747
- required: true,
748
- },
749
- {
750
- name: "brief_id",
751
- kind: "string",
752
- description: "Brief ID.",
753
- required: true,
754
- },
755
- {
756
- name: "answers",
757
- kind: "array",
758
- description: "Answers in brief question order.",
759
- required: true,
760
- },
761
- {
762
- name: "approved",
763
- kind: "boolean",
764
- description: "Explicit authorization of the exact preview or approval. Never inferred.",
765
- required: false,
766
- },
767
- {
768
- name: "max_credits",
769
- kind: "number",
770
- description: "Explicit credit ceiling from preview.",
771
- required: false,
772
- },
773
- ],
774
- },
775
- {
776
- action: "post_update",
777
- command: "posts update",
778
- description: "Edit or schedule an enrolled post with creator or delegated authority; publishing gates still apply.",
779
- fields: [
780
- {
781
- name: "program_id",
782
- kind: "string",
783
- description: "Program ID.",
784
- required: true,
785
- },
786
- {
787
- name: "post_id",
788
- kind: "string",
789
- description: "Canonical post ID.",
790
- required: true,
791
- },
792
- {
793
- name: "enrollment_version",
794
- kind: "number",
795
- description: "Exact enrollment version returned by posts list; always send it so a removed/re-enrolled post cannot reuse an old edit.",
796
- required: true,
797
- },
798
- {
799
- name: "title",
800
- kind: "string",
801
- description: "Brief or post title.",
802
- required: false,
803
- },
804
- {
805
- name: "content_text",
806
- kind: "string",
807
- description: "Edited post text.",
808
- required: false,
809
- },
810
- {
811
- name: "scheduled_for",
812
- kind: "string",
813
- description: "Future ISO-8601 publishing time with timezone.",
814
- required: false,
815
- },
816
- ],
817
- },
818
- {
819
- action: "post_approve",
820
- command: "posts approve",
821
- description: "Record creator or explicitly delegated operator approval of the current post.",
822
- fields: [
823
- {
824
- name: "program_id",
825
- kind: "string",
826
- description: "Program ID.",
827
- required: true,
828
- },
829
- {
830
- name: "post_id",
831
- kind: "string",
832
- description: "Canonical post ID.",
833
- required: true,
834
- },
835
- {
836
- name: "enrollment_version",
837
- kind: "number",
838
- description: "Exact enrollment version returned by posts list; always send it so approval binds the current enrollment.",
839
- required: true,
840
- },
841
- {
842
- name: "source_revision",
843
- kind: "string",
844
- description: "Exact reviewed content fingerprint returned by posts list.",
845
- required: true,
846
- },
847
- {
848
- name: "approved",
849
- kind: "boolean",
850
- description: "Explicit authorization of the exact preview or approval. Never inferred.",
851
- required: true,
852
- },
853
- ],
854
- },
855
- {
856
- action: "brand_approve",
857
- command: "posts brand-approve",
858
- description: "Record separate master brand approval of the current post.",
859
- fields: [
860
- {
861
- name: "program_id",
862
- kind: "string",
863
- description: "Program ID.",
864
- required: true,
865
- },
866
- {
867
- name: "post_id",
868
- kind: "string",
869
- description: "Canonical post ID.",
870
- required: true,
871
- },
872
- {
873
- name: "enrollment_version",
874
- kind: "number",
875
- description: "Exact enrollment version returned by posts list; always send it so brand approval binds the current enrollment.",
876
- required: true,
877
- },
878
- {
879
- name: "source_revision",
880
- kind: "string",
881
- description: "Exact reviewed content fingerprint returned by posts list.",
882
- required: true,
883
- },
884
- {
885
- name: "approved",
886
- kind: "boolean",
887
- description: "Explicit authorization of the exact preview or approval. Never inferred.",
888
- required: true,
889
- },
890
- ],
891
- },
892
- {
893
- action: "voice_import",
894
- command: "voice import",
895
- description: "Preview all retrievable LinkedIn history and voice inference; approve a total credit ceiling to start. Use --import-id to resume a safely interrupted import with its saved progress and spend.",
896
- fields: [
897
- {
898
- name: "participation_id",
899
- kind: "string",
900
- description: "Creator participation ID.",
901
- required: true,
902
- },
903
- {
904
- name: "import_id",
905
- kind: "string",
906
- description: "Existing safely interrupted import to resume; max-credits is its total ceiling including credits already used.",
907
- required: false,
908
- },
909
- {
910
- name: "approved",
911
- kind: "boolean",
912
- description: "Explicit authorization of the exact preview or approval. Never inferred.",
913
- required: false,
914
- },
915
- {
916
- name: "max_credits",
917
- kind: "number",
918
- description: "Explicit credit ceiling from preview.",
919
- required: false,
920
- },
921
- ],
922
- },
923
- {
924
- action: "voice_save",
925
- command: "voice save",
926
- description: "Save your own writing preferences and examples as a private provisional Knowledge voice. Free: 0 credits, no provider call or connected account required. Existing voice edits require its current revision.",
927
- fields: [
928
- {
929
- name: "participation_id",
930
- kind: "string",
931
- description: "Your creator participation ID.",
932
- required: true,
933
- },
934
- {
935
- name: "body",
936
- kind: "string",
937
- description: "Your own writing preferences or voice guide (Markdown).",
938
- required: true,
939
- },
940
- {
941
- name: "writing_examples",
942
- kind: "array",
943
- description: "JSON array of up to five examples you actually wrote; do not invent personal experiences.",
944
- required: false,
945
- },
946
- {
947
- name: "expected_revision",
948
- kind: "number",
949
- description: "Current profile revision returned by voice get, required when editing it.",
950
- required: false,
951
- },
952
- ],
953
- },
954
- {
955
- action: "sponsorship_cancel",
956
- command: "sponsorship cancel",
957
- description: "Preview stopping renewal for one program sponsorship. Confirm with --approved and a signed-in master admin. Participation and credits through the paid period remain available.",
958
- fields: [
959
- {
960
- name: "program_id",
961
- kind: "string",
962
- description: "Master program ID.",
963
- required: true,
964
- },
965
- {
966
- name: "participation_id",
967
- kind: "string",
968
- description: "Exact creator participation ID.",
969
- required: true,
970
- },
971
- {
972
- name: "approved",
973
- kind: "boolean",
974
- description: "Approve the exact cancellation preview. Omit for a free preview.",
975
- required: false,
976
- },
977
- ],
978
- },
979
- {
980
- action: "sponsorship_preview",
981
- command: "sponsorship preview",
982
- description: "Preview seat charges and monthly 10,000-credit creator grants as a signed-in master workspace admin. Org API keys cannot create this quote.",
983
- fields: [
984
- {
985
- name: "program_id",
986
- kind: "string",
987
- description: "Program ID.",
988
- required: true,
989
- },
990
- {
991
- name: "participation_ids",
992
- kind: "array",
993
- description: "Exact creator participation IDs to sponsor.",
994
- required: true,
995
- },
996
- ],
997
- },
998
- {
999
- action: "sponsorship_confirm",
1000
- command: "sponsorship confirm",
1001
- description: "Confirm the exact sponsorship quote as the same signed-in master workspace admin. Each program pays separately, even for the same account.",
1002
- fields: [
1003
- {
1004
- name: "program_id",
1005
- kind: "string",
1006
- description: "Program ID.",
1007
- required: true,
1008
- },
1009
- {
1010
- name: "participation_ids",
1011
- kind: "array",
1012
- description: "Exact creator participation IDs to sponsor.",
1013
- required: true,
1014
- },
1015
- {
1016
- name: "quote",
1017
- kind: "string",
1018
- description: "Exact sponsorship quote returned by preview.",
1019
- required: true,
1020
- },
1021
- {
1022
- name: "approved",
1023
- kind: "boolean",
1024
- description: "Explicit authorization of the exact preview or approval. Never inferred.",
1025
- required: true,
1026
- },
1027
- ],
1028
- },
1029
- {
1030
- action: "amplification_reconcile",
1031
- command: "amplification reconcile",
1032
- description: "Preview recording a provider observation for an uncertain program action. Confirmation needs a signed-in operator and --approved; it never contacts the provider or authorizes a retry.",
1033
- fields: [
1034
- {
1035
- name: "program_id",
1036
- kind: "string",
1037
- description: "Program ID in the master workspace.",
1038
- required: true,
1039
- },
1040
- {
1041
- name: "action_id",
1042
- kind: "string",
1043
- description: "Unresolved effect_unknown action ID.",
1044
- required: true,
1045
- },
1046
- {
1047
- name: "outcome",
1048
- kind: "string",
1049
- description: "Observed applied or not_applied outcome.",
1050
- required: true,
1051
- },
1052
- {
1053
- name: "evidence",
1054
- kind: "object",
1055
- description: "JSON object: provider_post_id, evidence_ref, observed_at ISO instant; applied needs provider_object_id and comments/reposts need exact observed_text. Optional note.",
1056
- required: true,
1057
- },
1058
- {
1059
- name: "approved",
1060
- kind: "boolean",
1061
- description: "Explicitly confirm this immutable observation. No retry is authorized.",
1062
- required: false,
1063
- },
1064
- ],
1065
- },
1066
- {
1067
- action: "amplification_save",
1068
- command: "amplification save",
1069
- description: "Save exact opted-in sender scope and bounded post-specific amplification. Enabling needs explicit approval.",
1070
- fields: [
1071
- {
1072
- name: "sender_voice_pages",
1073
- kind: "object",
1074
- description: "JSON map from each acting sender UUID to its selected active Knowledge voice page UUID. Required for comments or reposts; the exact mapping is approved with the policy.",
1075
- required: false,
1076
- },
1077
- {
1078
- name: "program_id",
1079
- kind: "string",
1080
- description: "Program ID.",
1081
- required: true,
1082
- },
1083
- {
1084
- name: "participant_sender_ids",
1085
- kind: "array",
1086
- description: "Exact opted-in participant sender IDs.",
1087
- required: true,
1088
- },
1089
- {
1090
- name: "actions",
1091
- kind: "array",
1092
- description: "Allowed post-specific amplification actions.",
1093
- required: true,
1094
- },
1095
- {
1096
- name: "enabled",
1097
- kind: "boolean",
1098
- description: "Enable the bounded amplification policy.",
1099
- required: true,
1100
- },
1101
- {
1102
- name: "max_actions_per_post",
1103
- kind: "number",
1104
- description: "Hard limit for amplification actions on each enrolled published post.",
1105
- required: true,
1106
- },
1107
- {
1108
- name: "max_credits_per_cycle",
1109
- kind: "number",
1110
- description: "Hard credit ceiling for the amplification cycle.",
1111
- required: true,
1112
- },
1113
- {
1114
- name: "approved",
1115
- kind: "boolean",
1116
- description: "Explicit authorization of the exact preview or approval. Never inferred.",
1117
- required: false,
1118
- },
1119
- {
1120
- name: "delay_min_seconds",
1121
- kind: "number",
1122
- description: "Minimum amplification delay, 60–3600 seconds.",
1123
- required: false,
1124
- },
1125
- {
1126
- name: "delay_max_seconds",
1127
- kind: "number",
1128
- description: "Maximum amplification delay, 60–86400 seconds.",
1129
- required: false,
1130
- },
1131
- ],
1132
- },
1133
- {
1134
- action: "peer_amplification_save",
1135
- command: "peer-amplification save",
1136
- description: "Preview or save this creator workspace's own peer-engagement consent, sender, voice and caps. The creator wallet pays; the host gate must also be enabled.",
1137
- fields: [
1138
- { name: "participation_id", kind: "string", description: "Exact creator participation ID.", required: true },
1139
- { name: "sender_account_id", kind: "string", description: "Creator's matching connected LinkedIn sender ID.", required: true },
1140
- { name: "voice_page_id", kind: "string", description: "Creator-owned active voice page ID, required for comment or repost.", required: false },
1141
- { name: "actions", kind: "array", description: "Allowed peer actions: reaction, comment or repost.", required: true },
1142
- { name: "enabled", kind: "boolean", description: "Enable or disable this creator-owned policy.", required: true },
1143
- { name: "expected_policy_version", kind: "number", description: "Current policy version from peer-amplification get; omit or use 0 on first save.", required: false },
1144
- { name: "max_actions_per_post", kind: "number", description: "Hard action cap per peer post.", required: true },
1145
- { name: "max_credits_per_cycle", kind: "number", description: "Hard creator-wallet credit cap per cycle.", required: true },
1146
- { name: "approved", kind: "boolean", description: "Confirm this exact creator-owned scope; omit for preview.", required: false },
1147
- { name: "delay_min_seconds", kind: "number", description: "Minimum delay, 60–3600 seconds.", required: false },
1148
- { name: "delay_max_seconds", kind: "number", description: "Maximum delay, 60–86400 seconds.", required: false },
1149
- ],
1150
- },
1151
- {
1152
- action: "peer_amplification_reconcile",
1153
- command: "peer-amplification reconcile",
1154
- description: "Preview recording observed evidence for this creator's effect_unknown peer action. Approval records the outcome without a provider call or retry.",
1155
- fields: [
1156
- { name: "participation_id", kind: "string", description: "Exact creator participation ID.", required: true },
1157
- { name: "action_id", kind: "string", description: "Exact effect_unknown peer action ID.", required: true },
1158
- { name: "outcome", kind: "string", description: "Observed applied or not_applied outcome.", required: true },
1159
- { name: "evidence", kind: "object", description: "JSON evidence: provider_post_id, evidence_ref and observed_at; applied may require provider_object_id and exact observed_text.", required: true },
1160
- { name: "approved", kind: "boolean", description: "Confirm this immutable observation; no retry is authorized.", required: false },
1161
- ],
1162
- },
1163
- ];
1164
- for (const spec of writes) {
1165
- const [family, leaf] = spec.command.split(" ");
1166
- const command = group(family).command(leaf).description(spec.description);
1167
- for (const field of spec.fields) {
1168
- const flag = `--${field.name.replaceAll("_", "-")}${field.name === "approved" ? "" : ` <${field.kind === "array" || field.kind === "object" ? "json" : field.kind === "boolean" ? "true|false" : "value"}>`}`;
1169
- if (field.required)
1170
- command.requiredOption(flag, field.description);
1171
- else
1172
- command.option(flag, field.description);
1173
- }
1174
- if (spec.action === "invite_create")
1175
- command.option("--link-only", "Create a shareable link without sending email.");
1176
- command
1177
- .option("--json", "Print a JSON envelope.")
1178
- .action((options) => handle(`ugc ${spec.command}`, options, () => {
1179
- const body = {
1180
- action: spec.action,
1181
- ...(spec.fixed ?? {}),
1182
- };
1183
- for (const field of spec.fields) {
1184
- const key = field.name.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1185
- if (options[key] !== undefined)
1186
- body[field.name] = parseField(options[key], field);
1187
- }
1188
- if (spec.action === "invite_create") {
1189
- body.send_email = options.linkOnly !== true;
1190
- if (options.linkOnly && (body.approved || body.preview_token))
1191
- throw new Error("--link-only cannot be combined with --approved or --preview-token.");
1192
- }
1193
- return requestOxygen("/api/cli/ugc", {
1194
- method: "POST",
1195
- body,
1196
- ...(spec.action === "draft_create" &&
1197
- typeof body.request_id === "string"
1198
- ? { idempotencyKey: body.request_id }
1199
- : {}),
1200
- });
1201
- }));
1202
- }
4
+ registerCommands(program, { request: requestOxygen, handle });
1203
5
  }