@geoly-ai/social-hub-cli 0.0.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.
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +23 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +96 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +13 -0
- package/dist/config.test.js.map +1 -0
- package/dist/context-state.d.ts +9 -0
- package/dist/context-state.d.ts.map +1 -0
- package/dist/context-state.js +29 -0
- package/dist/context-state.js.map +1 -0
- package/dist/dry-run.d.ts +12 -0
- package/dist/dry-run.d.ts.map +1 -0
- package/dist/dry-run.js +18 -0
- package/dist/dry-run.js.map +1 -0
- package/dist/dry-run.test.d.ts +2 -0
- package/dist/dry-run.test.d.ts.map +1 -0
- package/dist/dry-run.test.js +21 -0
- package/dist/dry-run.test.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1342 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +303 -0
- package/dist/index.test.js.map +1 -0
- package/dist/output.d.ts +9 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +75 -0
- package/dist/output.js.map +1 -0
- package/dist/permissions.d.ts +32 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +101 -0
- package/dist/permissions.js.map +1 -0
- package/dist/permissions.test.d.ts +2 -0
- package/dist/permissions.test.d.ts.map +1 -0
- package/dist/permissions.test.js +17 -0
- package/dist/permissions.test.js.map +1 -0
- package/dist/register-admin.d.ts +3 -0
- package/dist/register-admin.d.ts.map +1 -0
- package/dist/register-admin.js +100 -0
- package/dist/register-admin.js.map +1 -0
- package/dist/register-batch.d.ts +3 -0
- package/dist/register-batch.d.ts.map +1 -0
- package/dist/register-batch.js +85 -0
- package/dist/register-batch.js.map +1 -0
- package/dist/register-extensions.d.ts +9 -0
- package/dist/register-extensions.d.ts.map +1 -0
- package/dist/register-extensions.js +550 -0
- package/dist/register-extensions.js.map +1 -0
- package/dist/register-ops.d.ts +4 -0
- package/dist/register-ops.d.ts.map +1 -0
- package/dist/register-ops.js +152 -0
- package/dist/register-ops.js.map +1 -0
- package/dist/register-shared.d.ts +3 -0
- package/dist/register-shared.d.ts.map +1 -0
- package/dist/register-shared.js +145 -0
- package/dist/register-shared.js.map +1 -0
- package/package.json +35 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1342 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { getSocialHubHealth } from "@geoly-ai/social-hub-sdk";
|
|
4
|
+
import { getBaseUrl, requireClient } from "./client.js";
|
|
5
|
+
import { registerAccountsExtensions, registerAuthAndConfig, registerPermissionsExplain, registerRedditExtensions, } from "./register-extensions.js";
|
|
6
|
+
import { registerAdminCommands } from "./register-admin.js";
|
|
7
|
+
import { registerBatchAndExport } from "./register-batch.js";
|
|
8
|
+
import { registerAgentContext, registerOpsRuntime, } from "./register-ops.js";
|
|
9
|
+
import { registerDoctorAndVersion } from "./register-shared.js";
|
|
10
|
+
const program = new Command();
|
|
11
|
+
program
|
|
12
|
+
.name("social-hub")
|
|
13
|
+
.description("Social Ops Hub CLI(API 与 @geoly-ai/social-hub-sdk 对齐)")
|
|
14
|
+
.showHelpAfterError();
|
|
15
|
+
registerAuthAndConfig(program);
|
|
16
|
+
registerDoctorAndVersion(program);
|
|
17
|
+
registerOpsRuntime(program);
|
|
18
|
+
registerAgentContext(program);
|
|
19
|
+
registerAdminCommands(program);
|
|
20
|
+
registerBatchAndExport(program);
|
|
21
|
+
program
|
|
22
|
+
.command("health")
|
|
23
|
+
.description("GET /health(无需 API Key)")
|
|
24
|
+
.action(async () => {
|
|
25
|
+
const baseUrl = getBaseUrl();
|
|
26
|
+
try {
|
|
27
|
+
const h = await getSocialHubHealth(baseUrl);
|
|
28
|
+
console.log(JSON.stringify(h, null, 2));
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
console.error(e instanceof Error ? e.message : e);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
// --- events ---
|
|
36
|
+
const events = program.command("events").description("互动事件");
|
|
37
|
+
events
|
|
38
|
+
.command("append")
|
|
39
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
40
|
+
.requiredOption("--type <type>", "事件类型,如 comment")
|
|
41
|
+
.option("--payload <json>", "JSON 对象", "{}")
|
|
42
|
+
.action(async (opts) => {
|
|
43
|
+
let payload = {};
|
|
44
|
+
try {
|
|
45
|
+
payload = JSON.parse(opts.payload ?? "{}");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
console.error("Invalid --payload JSON");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const res = await requireClient().appendEvent(opts.team, {
|
|
52
|
+
type: opts.type,
|
|
53
|
+
payload,
|
|
54
|
+
});
|
|
55
|
+
console.log(JSON.stringify(res, null, 2));
|
|
56
|
+
});
|
|
57
|
+
events
|
|
58
|
+
.command("list")
|
|
59
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
60
|
+
.option("-n, --limit <n>", "条数", "20")
|
|
61
|
+
.action(async (opts) => {
|
|
62
|
+
const res = await requireClient().listEvents(opts.team, Number(opts.limit));
|
|
63
|
+
console.log(JSON.stringify(res, null, 2));
|
|
64
|
+
});
|
|
65
|
+
events
|
|
66
|
+
.command("batch")
|
|
67
|
+
.description("POST /events/batch")
|
|
68
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
69
|
+
.requiredOption("-j, --json <json>", '{ "events": [ ... ] }')
|
|
70
|
+
.action(async (opts) => {
|
|
71
|
+
let body;
|
|
72
|
+
try {
|
|
73
|
+
body = JSON.parse(opts.json);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
console.error("Invalid -j / --json");
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const res = await requireClient().appendEventsBatch(opts.team, body);
|
|
80
|
+
console.log(JSON.stringify(res, null, 2));
|
|
81
|
+
});
|
|
82
|
+
// --- dashboard ---
|
|
83
|
+
const dashboard = program.command("dashboard").description("运营总览");
|
|
84
|
+
dashboard
|
|
85
|
+
.command("summary")
|
|
86
|
+
.description("GET /dashboard/summary")
|
|
87
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
88
|
+
.option("--from <iso>", "from ISO 日期")
|
|
89
|
+
.option("--to <iso>", "to ISO 日期")
|
|
90
|
+
.option("--trend-days <n>", "interactionTrendDays: 7 | 14 | 30")
|
|
91
|
+
.option("--campaign <uuid>", "campaignId 过滤")
|
|
92
|
+
.option("--brand <uuid>", "brandId 过滤")
|
|
93
|
+
.action(async (opts) => {
|
|
94
|
+
const res = await requireClient().getDashboardSummary(opts.team, {
|
|
95
|
+
from: opts.from,
|
|
96
|
+
to: opts.to,
|
|
97
|
+
interactionTrendDays: opts.trendDays ? Number(opts.trendDays) : undefined,
|
|
98
|
+
campaignId: opts.campaign,
|
|
99
|
+
brandId: opts.brand,
|
|
100
|
+
});
|
|
101
|
+
console.log(JSON.stringify(res, null, 2));
|
|
102
|
+
});
|
|
103
|
+
// --- calendar ---
|
|
104
|
+
const calendar = program.command("calendar").description("发布日历条目");
|
|
105
|
+
calendar
|
|
106
|
+
.command("list")
|
|
107
|
+
.description("GET /calendar-entries")
|
|
108
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
109
|
+
.option("--campaign <uuid>", "campaignId")
|
|
110
|
+
.option("--status <st>", "scheduled | running | succeeded | …")
|
|
111
|
+
.option("--from <iso>", "from 时间 ISO")
|
|
112
|
+
.option("--to <iso>", "to 时间 ISO")
|
|
113
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
114
|
+
.action(async (opts) => {
|
|
115
|
+
const res = await requireClient().listCalendarEntries(opts.team, {
|
|
116
|
+
campaignId: opts.campaign,
|
|
117
|
+
status: opts.status,
|
|
118
|
+
from: opts.from,
|
|
119
|
+
to: opts.to,
|
|
120
|
+
limit: Number(opts.limit),
|
|
121
|
+
});
|
|
122
|
+
console.log(JSON.stringify(res, null, 2));
|
|
123
|
+
});
|
|
124
|
+
calendar
|
|
125
|
+
.command("patch")
|
|
126
|
+
.description("PATCH /calendar-entries/:id(--body 为 JSON)")
|
|
127
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
128
|
+
.requiredOption("-e, --entry <entryId>", "Calendar entry UUID")
|
|
129
|
+
.requiredOption("--body <json>", '例如 {"status":"succeeded","permalink":"https://www.reddit.com/..."}')
|
|
130
|
+
.action(async (opts) => {
|
|
131
|
+
let body;
|
|
132
|
+
try {
|
|
133
|
+
body = JSON.parse(opts.body);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
console.error("Invalid --body JSON");
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
const res = await requireClient().updateCalendarEntry(opts.team, opts.entry, body);
|
|
140
|
+
console.log(JSON.stringify(res, null, 2));
|
|
141
|
+
});
|
|
142
|
+
// --- reddit ---
|
|
143
|
+
const reddit = program.command("reddit").description("Reddit 帖快照");
|
|
144
|
+
registerRedditExtensions(reddit);
|
|
145
|
+
reddit
|
|
146
|
+
.command("list")
|
|
147
|
+
.description("GET /reddit-post-snapshots")
|
|
148
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
149
|
+
.option("--campaign <uuid>", "campaignId")
|
|
150
|
+
.option("--entry <uuid>", "calendarEntryId")
|
|
151
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
152
|
+
.action(async (opts) => {
|
|
153
|
+
const res = await requireClient().listRedditPostSnapshots(opts.team, {
|
|
154
|
+
limit: Number(opts.limit),
|
|
155
|
+
campaignId: opts.campaign,
|
|
156
|
+
calendarEntryId: opts.entry,
|
|
157
|
+
});
|
|
158
|
+
console.log(JSON.stringify(res, null, 2));
|
|
159
|
+
});
|
|
160
|
+
reddit
|
|
161
|
+
.command("create-snapshot")
|
|
162
|
+
.description("POST /reddit-post-snapshots(手工补录)")
|
|
163
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
164
|
+
.requiredOption("-j, --json <json>", "createRedditPostSnapshot body JSON")
|
|
165
|
+
.action(async (opts) => {
|
|
166
|
+
let body;
|
|
167
|
+
try {
|
|
168
|
+
body = JSON.parse(opts.json);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
console.error("Invalid -j / --json");
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
const res = await requireClient().createRedditPostSnapshot(opts.team, body);
|
|
175
|
+
console.log(JSON.stringify(res, null, 2));
|
|
176
|
+
});
|
|
177
|
+
// --- jobs ---
|
|
178
|
+
const jobs = program.command("jobs").description("调度任务(scheduled jobs)");
|
|
179
|
+
jobs
|
|
180
|
+
.command("list")
|
|
181
|
+
.description("GET /scheduled-jobs")
|
|
182
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
183
|
+
.option("--status <st>", "scheduled | running | …")
|
|
184
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
185
|
+
.action(async (opts) => {
|
|
186
|
+
const res = await requireClient().listScheduledJobs(opts.team, {
|
|
187
|
+
limit: Number(opts.limit),
|
|
188
|
+
status: opts.status,
|
|
189
|
+
});
|
|
190
|
+
console.log(JSON.stringify(res, null, 2));
|
|
191
|
+
});
|
|
192
|
+
jobs
|
|
193
|
+
.command("summary")
|
|
194
|
+
.description("GET /scheduled-jobs/automation-summary")
|
|
195
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
196
|
+
.option("--hours <n>", "时间窗口(小时)", "24")
|
|
197
|
+
.action(async (opts) => {
|
|
198
|
+
const res = await requireClient().getScheduledJobsAutomationSummary(opts.team, Number(opts.hours));
|
|
199
|
+
console.log(JSON.stringify(res, null, 2));
|
|
200
|
+
});
|
|
201
|
+
jobs
|
|
202
|
+
.command("create")
|
|
203
|
+
.description("POST /scheduled-jobs(--json 为完整 body)")
|
|
204
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
205
|
+
.requiredOption("-j, --json <json>", "createScheduledJobBody JSON")
|
|
206
|
+
.action(async (opts) => {
|
|
207
|
+
let body;
|
|
208
|
+
try {
|
|
209
|
+
body = JSON.parse(opts.json);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
console.error("Invalid -j / --json");
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
const res = await requireClient().createScheduledJob(opts.team, body);
|
|
216
|
+
console.log(JSON.stringify(res, null, 2));
|
|
217
|
+
});
|
|
218
|
+
jobs
|
|
219
|
+
.command("batch")
|
|
220
|
+
.description("POST /scheduled-jobs/batch")
|
|
221
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
222
|
+
.requiredOption("-j, --json <json>", '{ "jobs": [ ... ] }')
|
|
223
|
+
.action(async (opts) => {
|
|
224
|
+
let body;
|
|
225
|
+
try {
|
|
226
|
+
body = JSON.parse(opts.json);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
console.error("Invalid -j / --json");
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const res = await requireClient().createScheduledJobsBatch(opts.team, body);
|
|
233
|
+
console.log(JSON.stringify(res, null, 2));
|
|
234
|
+
});
|
|
235
|
+
jobs
|
|
236
|
+
.command("retry")
|
|
237
|
+
.description("POST /scheduled-jobs/:id/retry")
|
|
238
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
239
|
+
.requiredOption("-i, --id <jobId>", "Job UUID")
|
|
240
|
+
.action(async (opts) => {
|
|
241
|
+
const res = await requireClient().retryScheduledJob(opts.team, opts.id);
|
|
242
|
+
console.log(JSON.stringify(res, null, 2));
|
|
243
|
+
});
|
|
244
|
+
jobs
|
|
245
|
+
.command("cancel")
|
|
246
|
+
.description("POST /scheduled-jobs/:id/cancel")
|
|
247
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
248
|
+
.requiredOption("-i, --id <jobId>", "Job UUID")
|
|
249
|
+
.action(async (opts) => {
|
|
250
|
+
const res = await requireClient().cancelScheduledJob(opts.team, opts.id);
|
|
251
|
+
console.log(JSON.stringify(res, null, 2));
|
|
252
|
+
});
|
|
253
|
+
// --- drafts & reports ---
|
|
254
|
+
const drafts = program.command("drafts").description("内容草稿");
|
|
255
|
+
drafts
|
|
256
|
+
.command("list")
|
|
257
|
+
.description("GET /content-drafts")
|
|
258
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
259
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
260
|
+
.action(async (opts) => {
|
|
261
|
+
const res = await requireClient().listContentDrafts(opts.team, Number(opts.limit));
|
|
262
|
+
console.log(JSON.stringify(res, null, 2));
|
|
263
|
+
});
|
|
264
|
+
const reports = program.command("reports").description("报告库");
|
|
265
|
+
reports
|
|
266
|
+
.command("list")
|
|
267
|
+
.description("GET /reports")
|
|
268
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
269
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
270
|
+
.option("--type <t>", "reddit-post-snapshot | account-status-snapshot | campaign-digest")
|
|
271
|
+
.action(async (opts) => {
|
|
272
|
+
const res = await requireClient().listReports(opts.team, {
|
|
273
|
+
limit: Number(opts.limit),
|
|
274
|
+
reportType: opts.type,
|
|
275
|
+
});
|
|
276
|
+
console.log(JSON.stringify(res, null, 2));
|
|
277
|
+
});
|
|
278
|
+
reports
|
|
279
|
+
.command("ingest")
|
|
280
|
+
.description("POST /reports/ingest")
|
|
281
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
282
|
+
.requiredOption("-j, --json <json>", "{ reportType, source, traceId? }")
|
|
283
|
+
.action(async (opts) => {
|
|
284
|
+
let body;
|
|
285
|
+
try {
|
|
286
|
+
body = JSON.parse(opts.json);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
console.error("Invalid -j / --json");
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
const res = await requireClient().ingestReport(opts.team, {
|
|
293
|
+
reportType: body.reportType,
|
|
294
|
+
source: body.source,
|
|
295
|
+
traceId: body.traceId,
|
|
296
|
+
});
|
|
297
|
+
console.log(JSON.stringify(res, null, 2));
|
|
298
|
+
});
|
|
299
|
+
// --- accounts ---
|
|
300
|
+
const accounts = program.command("accounts").description("社交账号");
|
|
301
|
+
registerAccountsExtensions(accounts);
|
|
302
|
+
accounts
|
|
303
|
+
.command("list")
|
|
304
|
+
.description("GET /accounts")
|
|
305
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
306
|
+
.option("--status <st>", "warming | active | …")
|
|
307
|
+
.option("--platform <p>", "平台")
|
|
308
|
+
.option("--campaign <uuid>", "campaignId")
|
|
309
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
310
|
+
.action(async (opts) => {
|
|
311
|
+
const res = await requireClient().listAccounts(opts.team, {
|
|
312
|
+
limit: Number(opts.limit),
|
|
313
|
+
status: opts.status,
|
|
314
|
+
platform: opts.platform,
|
|
315
|
+
campaignId: opts.campaign,
|
|
316
|
+
});
|
|
317
|
+
console.log(JSON.stringify(res, null, 2));
|
|
318
|
+
});
|
|
319
|
+
accounts
|
|
320
|
+
.command("create")
|
|
321
|
+
.description("POST /accounts")
|
|
322
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
323
|
+
.requiredOption("-j, --json <json>", "createAccount body JSON")
|
|
324
|
+
.action(async (opts) => {
|
|
325
|
+
let body;
|
|
326
|
+
try {
|
|
327
|
+
body = JSON.parse(opts.json);
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
console.error("Invalid -j / --json");
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|
|
333
|
+
const res = await requireClient().createAccount(opts.team, body);
|
|
334
|
+
console.log(JSON.stringify(res, null, 2));
|
|
335
|
+
});
|
|
336
|
+
// --- brands & campaigns ---
|
|
337
|
+
const brands = program.command("brands").description("品牌");
|
|
338
|
+
brands
|
|
339
|
+
.command("list")
|
|
340
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
341
|
+
.action(async (opts) => {
|
|
342
|
+
const res = await requireClient().listBrands(opts.team);
|
|
343
|
+
console.log(JSON.stringify(res, null, 2));
|
|
344
|
+
});
|
|
345
|
+
brands
|
|
346
|
+
.command("create")
|
|
347
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
348
|
+
.requiredOption("-j, --json <json>", "{ name, slug? }")
|
|
349
|
+
.action(async (opts) => {
|
|
350
|
+
let body;
|
|
351
|
+
try {
|
|
352
|
+
body = JSON.parse(opts.json);
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
console.error("Invalid -j / --json");
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
const res = await requireClient().createBrand(opts.team, {
|
|
359
|
+
name: String(body.name ?? ""),
|
|
360
|
+
slug: body.slug,
|
|
361
|
+
});
|
|
362
|
+
console.log(JSON.stringify(res, null, 2));
|
|
363
|
+
});
|
|
364
|
+
brands
|
|
365
|
+
.command("update")
|
|
366
|
+
.description("PATCH /brands/:id")
|
|
367
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
368
|
+
.requiredOption("-b, --brand <brandId>", "Brand UUID")
|
|
369
|
+
.requiredOption("-j, --json <json>", "update body")
|
|
370
|
+
.action(async (opts) => {
|
|
371
|
+
let body;
|
|
372
|
+
try {
|
|
373
|
+
body = JSON.parse(opts.json);
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
console.error("Invalid -j / --json");
|
|
377
|
+
process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
const res = await requireClient().updateBrand(opts.team, opts.brand, body);
|
|
380
|
+
console.log(JSON.stringify(res, null, 2));
|
|
381
|
+
});
|
|
382
|
+
const campaigns = program.command("campaigns").description("活动 Campaign");
|
|
383
|
+
campaigns
|
|
384
|
+
.command("list")
|
|
385
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
386
|
+
.option("--brand <uuid>", "brandId")
|
|
387
|
+
.action(async (opts) => {
|
|
388
|
+
const res = await requireClient().listCampaigns(opts.team, {
|
|
389
|
+
brandId: opts.brand,
|
|
390
|
+
});
|
|
391
|
+
console.log(JSON.stringify(res, null, 2));
|
|
392
|
+
});
|
|
393
|
+
campaigns
|
|
394
|
+
.command("create")
|
|
395
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
396
|
+
.requiredOption("-j, --json <json>", "{ brandId, name, startsAt?, endsAt? }")
|
|
397
|
+
.action(async (opts) => {
|
|
398
|
+
let body;
|
|
399
|
+
try {
|
|
400
|
+
body = JSON.parse(opts.json);
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
console.error("Invalid -j / --json");
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
const res = await requireClient().createCampaign(opts.team, body);
|
|
407
|
+
console.log(JSON.stringify(res, null, 2));
|
|
408
|
+
});
|
|
409
|
+
// --- publishing plans ---
|
|
410
|
+
const plans = program.command("plans").description("发布计划");
|
|
411
|
+
plans
|
|
412
|
+
.command("list")
|
|
413
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
414
|
+
.option("--campaign <uuid>", "campaignId")
|
|
415
|
+
.action(async (opts) => {
|
|
416
|
+
const res = await requireClient().listPublishingPlans(opts.team, {
|
|
417
|
+
campaignId: opts.campaign,
|
|
418
|
+
});
|
|
419
|
+
console.log(JSON.stringify(res, null, 2));
|
|
420
|
+
});
|
|
421
|
+
plans
|
|
422
|
+
.command("create")
|
|
423
|
+
.description("POST /publishing-plans(body 需含 entries 等)")
|
|
424
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
425
|
+
.requiredOption("-j, --json <json>", "createPublishingPlanBody JSON")
|
|
426
|
+
.action(async (opts) => {
|
|
427
|
+
let body;
|
|
428
|
+
try {
|
|
429
|
+
body = JSON.parse(opts.json);
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
console.error("Invalid -j / --json");
|
|
433
|
+
process.exit(1);
|
|
434
|
+
}
|
|
435
|
+
const res = await requireClient().createPublishingPlan(opts.team, body);
|
|
436
|
+
console.log(JSON.stringify(res, null, 2));
|
|
437
|
+
});
|
|
438
|
+
// --- audit & permissions & graph ---
|
|
439
|
+
const audit = program.command("audit").description("审计日志");
|
|
440
|
+
audit
|
|
441
|
+
.command("list")
|
|
442
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
443
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
444
|
+
.option("--type <t>", "事件 type 前缀")
|
|
445
|
+
.option("--actor <a>", "user | agent | cron")
|
|
446
|
+
.option("--result <r>", "succeeded | failed | skipped")
|
|
447
|
+
.option("--account <uuid>", "socialAccountId")
|
|
448
|
+
.action(async (opts) => {
|
|
449
|
+
const res = await requireClient().listAuditLogs(opts.team, {
|
|
450
|
+
limit: Number(opts.limit),
|
|
451
|
+
type: opts.type,
|
|
452
|
+
actor: opts.actor,
|
|
453
|
+
result: opts.result,
|
|
454
|
+
socialAccountId: opts.account,
|
|
455
|
+
});
|
|
456
|
+
console.log(JSON.stringify(res, null, 2));
|
|
457
|
+
});
|
|
458
|
+
const permissionsCmd = program
|
|
459
|
+
.command("permissions")
|
|
460
|
+
.description("权限矩阵与 CLI 能力说明");
|
|
461
|
+
permissionsCmd
|
|
462
|
+
.command("matrix")
|
|
463
|
+
.description("GET /permissions-matrix(原 social-hub permissions)")
|
|
464
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
465
|
+
.action(async (opts) => {
|
|
466
|
+
const res = await requireClient().getPermissionsMatrix(opts.team);
|
|
467
|
+
console.log(JSON.stringify(res, null, 2));
|
|
468
|
+
});
|
|
469
|
+
registerPermissionsExplain(permissionsCmd);
|
|
470
|
+
const graph = program.command("graph").description("账号图谱");
|
|
471
|
+
graph
|
|
472
|
+
.command("list")
|
|
473
|
+
.description("GET /account-graph")
|
|
474
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
475
|
+
.option("--account <uuid>", "socialAccountId")
|
|
476
|
+
.option("--edge <type>", "edgeType")
|
|
477
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
478
|
+
.action(async (opts) => {
|
|
479
|
+
const res = await requireClient().listAccountGraphEdges(opts.team, {
|
|
480
|
+
limit: Number(opts.limit),
|
|
481
|
+
socialAccountId: opts.account,
|
|
482
|
+
edgeType: opts.edge,
|
|
483
|
+
});
|
|
484
|
+
console.log(JSON.stringify(res, null, 2));
|
|
485
|
+
});
|
|
486
|
+
// --- drafts extended ---
|
|
487
|
+
drafts
|
|
488
|
+
.command("create")
|
|
489
|
+
.description("POST /content-drafts")
|
|
490
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
491
|
+
.requiredOption("-j, --json <json>", "{ campaignId, title, body }")
|
|
492
|
+
.action(async (opts) => {
|
|
493
|
+
let body;
|
|
494
|
+
try {
|
|
495
|
+
body = JSON.parse(opts.json);
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
console.error("Invalid -j / --json");
|
|
499
|
+
process.exit(1);
|
|
500
|
+
}
|
|
501
|
+
const res = await requireClient().createContentDraft(opts.team, body);
|
|
502
|
+
console.log(JSON.stringify(res, null, 2));
|
|
503
|
+
});
|
|
504
|
+
// --- compliance ---
|
|
505
|
+
const compliance = program.command("compliance").description("合规 / 风控");
|
|
506
|
+
compliance
|
|
507
|
+
.command("sanctions-list")
|
|
508
|
+
.description("GET /subreddit-sanctions")
|
|
509
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
510
|
+
.option("--account <uuid>", "socialAccountId")
|
|
511
|
+
.option("--sub <name>", "subreddit")
|
|
512
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
513
|
+
.action(async (opts) => {
|
|
514
|
+
const res = await requireClient().listSubredditSanctions(opts.team, {
|
|
515
|
+
limit: Number(opts.limit),
|
|
516
|
+
socialAccountId: opts.account,
|
|
517
|
+
subreddit: opts.sub,
|
|
518
|
+
});
|
|
519
|
+
console.log(JSON.stringify(res, null, 2));
|
|
520
|
+
});
|
|
521
|
+
compliance
|
|
522
|
+
.command("sanctions-create")
|
|
523
|
+
.description("POST /subreddit-sanctions")
|
|
524
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
525
|
+
.requiredOption("-j, --json <json>", "body JSON")
|
|
526
|
+
.action(async (opts) => {
|
|
527
|
+
let body;
|
|
528
|
+
try {
|
|
529
|
+
body = JSON.parse(opts.json);
|
|
530
|
+
}
|
|
531
|
+
catch {
|
|
532
|
+
console.error("Invalid -j / --json");
|
|
533
|
+
process.exit(1);
|
|
534
|
+
}
|
|
535
|
+
const res = await requireClient().createSubredditSanction(opts.team, body);
|
|
536
|
+
console.log(JSON.stringify(res, null, 2));
|
|
537
|
+
});
|
|
538
|
+
compliance
|
|
539
|
+
.command("risk-list")
|
|
540
|
+
.description("GET /account-risk-profiles")
|
|
541
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
542
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
543
|
+
.action(async (opts) => {
|
|
544
|
+
const res = await requireClient().listAccountRiskProfiles(opts.team, Number(opts.limit));
|
|
545
|
+
console.log(JSON.stringify(res, null, 2));
|
|
546
|
+
});
|
|
547
|
+
compliance
|
|
548
|
+
.command("risk-get")
|
|
549
|
+
.description("GET /social-accounts/:id/risk-profile")
|
|
550
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
551
|
+
.requiredOption("-a, --account <uuid>", "socialAccountId")
|
|
552
|
+
.action(async (opts) => {
|
|
553
|
+
const res = await requireClient().getAccountRiskProfile(opts.team, opts.account);
|
|
554
|
+
console.log(JSON.stringify(res, null, 2));
|
|
555
|
+
});
|
|
556
|
+
compliance
|
|
557
|
+
.command("risk-put")
|
|
558
|
+
.description("PUT /social-accounts/:id/risk-profile")
|
|
559
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
560
|
+
.requiredOption("-a, --account <uuid>", "socialAccountId")
|
|
561
|
+
.requiredOption("-j, --json <json>", "body")
|
|
562
|
+
.action(async (opts) => {
|
|
563
|
+
let body;
|
|
564
|
+
try {
|
|
565
|
+
body = JSON.parse(opts.json);
|
|
566
|
+
}
|
|
567
|
+
catch {
|
|
568
|
+
console.error("Invalid -j / --json");
|
|
569
|
+
process.exit(1);
|
|
570
|
+
}
|
|
571
|
+
const res = await requireClient().upsertAccountRiskProfile(opts.team, opts.account, body);
|
|
572
|
+
console.log(JSON.stringify(res, null, 2));
|
|
573
|
+
});
|
|
574
|
+
// --- openclaw ---
|
|
575
|
+
program
|
|
576
|
+
.command("openclaw-ingest")
|
|
577
|
+
.description("POST /openclaw-ingest")
|
|
578
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
579
|
+
.option("-j, --json <json>", '默认 {"mode":"dry-run"}')
|
|
580
|
+
.action(async (opts) => {
|
|
581
|
+
let body = {
|
|
582
|
+
mode: "dry-run",
|
|
583
|
+
};
|
|
584
|
+
if (opts.json) {
|
|
585
|
+
try {
|
|
586
|
+
body = JSON.parse(opts.json);
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
console.error("Invalid -j / --json");
|
|
590
|
+
process.exit(1);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
const res = await requireClient().triggerOpenClawIngest(opts.team, body);
|
|
594
|
+
console.log(JSON.stringify(res, null, 2));
|
|
595
|
+
});
|
|
596
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
597
|
+
// Group A: single-resource CRUD additions to existing command groups
|
|
598
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
599
|
+
accounts
|
|
600
|
+
.command("get")
|
|
601
|
+
.description("GET /accounts/:id")
|
|
602
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
603
|
+
.requiredOption("--account <uuid>", "Account UUID")
|
|
604
|
+
.action(async (opts) => {
|
|
605
|
+
const res = await requireClient().getAccount(opts.team, opts.account);
|
|
606
|
+
console.log(JSON.stringify(res, null, 2));
|
|
607
|
+
});
|
|
608
|
+
accounts
|
|
609
|
+
.command("update")
|
|
610
|
+
.description("PATCH /accounts/:id — 更新 handle / status / credentialsRef")
|
|
611
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
612
|
+
.requiredOption("--account <uuid>", "Account UUID")
|
|
613
|
+
.requiredOption("-j, --json <json>", "{ handle?, profileUrl?, status?, externalId?, karma?, accountAgeDays?, workflowStage?, metricsSource?, metricsUpdatedAt?, credentialsRef? }")
|
|
614
|
+
.action(async (opts) => {
|
|
615
|
+
const body = JSON.parse(opts.json);
|
|
616
|
+
const res = await requireClient().updateAccount(opts.team, opts.account, body);
|
|
617
|
+
console.log(JSON.stringify(res, null, 2));
|
|
618
|
+
});
|
|
619
|
+
campaigns
|
|
620
|
+
.command("get")
|
|
621
|
+
.description("GET /campaigns/:id")
|
|
622
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
623
|
+
.requiredOption("--campaign <uuid>", "Campaign UUID")
|
|
624
|
+
.action(async (opts) => {
|
|
625
|
+
const res = await requireClient().getCampaign(opts.team, opts.campaign);
|
|
626
|
+
console.log(JSON.stringify(res, null, 2));
|
|
627
|
+
});
|
|
628
|
+
campaigns
|
|
629
|
+
.command("update")
|
|
630
|
+
.description("PATCH /campaigns/:id")
|
|
631
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
632
|
+
.requiredOption("--campaign <uuid>", "Campaign UUID")
|
|
633
|
+
.requiredOption("-j, --json <json>", "{ name?, startsAt?, endsAt? }")
|
|
634
|
+
.action(async (opts) => {
|
|
635
|
+
const body = JSON.parse(opts.json);
|
|
636
|
+
const res = await requireClient().updateCampaign(opts.team, opts.campaign, body);
|
|
637
|
+
console.log(JSON.stringify(res, null, 2));
|
|
638
|
+
});
|
|
639
|
+
drafts
|
|
640
|
+
.command("get")
|
|
641
|
+
.description("GET /content-drafts/:id")
|
|
642
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
643
|
+
.requiredOption("--draft <uuid>", "Draft UUID")
|
|
644
|
+
.action(async (opts) => {
|
|
645
|
+
const res = await requireClient().getContentDraft(opts.team, opts.draft);
|
|
646
|
+
console.log(JSON.stringify(res, null, 2));
|
|
647
|
+
});
|
|
648
|
+
drafts
|
|
649
|
+
.command("update")
|
|
650
|
+
.description("PATCH /content-drafts/:id")
|
|
651
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
652
|
+
.requiredOption("--draft <uuid>", "Draft UUID")
|
|
653
|
+
.requiredOption("-j, --json <json>", "{ title?, body?, status? }")
|
|
654
|
+
.action(async (opts) => {
|
|
655
|
+
const body = JSON.parse(opts.json);
|
|
656
|
+
const res = await requireClient().updateContentDraft(opts.team, opts.draft, body);
|
|
657
|
+
console.log(JSON.stringify(res, null, 2));
|
|
658
|
+
});
|
|
659
|
+
drafts
|
|
660
|
+
.command("delete")
|
|
661
|
+
.description("DELETE /content-drafts/:id")
|
|
662
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
663
|
+
.requiredOption("--draft <uuid>", "Draft UUID")
|
|
664
|
+
.action(async (opts) => {
|
|
665
|
+
await requireClient().deleteContentDraft(opts.team, opts.draft);
|
|
666
|
+
console.log("OK");
|
|
667
|
+
});
|
|
668
|
+
plans
|
|
669
|
+
.command("cancel")
|
|
670
|
+
.description("DELETE /publishing-plans/:id(取消)")
|
|
671
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
672
|
+
.requiredOption("--plan <uuid>", "Plan UUID")
|
|
673
|
+
.action(async (opts) => {
|
|
674
|
+
await requireClient().cancelPublishingPlan(opts.team, opts.plan);
|
|
675
|
+
console.log("OK");
|
|
676
|
+
});
|
|
677
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
678
|
+
// Group B: new command groups
|
|
679
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
680
|
+
// --- agent-teams ---
|
|
681
|
+
const agentTeams = program.command("agent-teams").description("Agent 团队管理(admin only)");
|
|
682
|
+
agentTeams
|
|
683
|
+
.command("list")
|
|
684
|
+
.description("GET /v1/agent-teams")
|
|
685
|
+
.action(async () => {
|
|
686
|
+
const res = await requireClient().listAgentTeams();
|
|
687
|
+
console.log(JSON.stringify(res, null, 2));
|
|
688
|
+
});
|
|
689
|
+
agentTeams
|
|
690
|
+
.command("workspace-docs")
|
|
691
|
+
.description("GET /v1/agent-teams/:teamId/workspace-documents")
|
|
692
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
693
|
+
.option("--kind <kind>", "file|daily_report|weekly_report|ops_record")
|
|
694
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
695
|
+
.action(async (opts) => {
|
|
696
|
+
const res = await requireClient().listWorkspaceDocuments(opts.team, {
|
|
697
|
+
kind: opts.kind,
|
|
698
|
+
limit: Number(opts.limit),
|
|
699
|
+
});
|
|
700
|
+
console.log(JSON.stringify(res, null, 2));
|
|
701
|
+
});
|
|
702
|
+
agentTeams
|
|
703
|
+
.command("create")
|
|
704
|
+
.description("POST /v1/agent-teams — 新建团队(admin only)")
|
|
705
|
+
.requiredOption("--slug <slug>", "团队 slug(小写字母、数字、横线)")
|
|
706
|
+
.requiredOption("--name <name>", "团队名称")
|
|
707
|
+
.action(async (opts) => {
|
|
708
|
+
const res = await requireClient().createTeam({ slug: opts.slug, name: opts.name });
|
|
709
|
+
console.log(JSON.stringify(res, null, 2));
|
|
710
|
+
});
|
|
711
|
+
agentTeams
|
|
712
|
+
.command("update")
|
|
713
|
+
.description("PATCH /v1/agent-teams/:teamId — 更新团队(admin only)")
|
|
714
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
715
|
+
.requiredOption("-j, --json <json>", "{ slug?, name? }")
|
|
716
|
+
.action(async (opts) => {
|
|
717
|
+
const body = JSON.parse(opts.json);
|
|
718
|
+
const res = await requireClient().updateTeam(opts.team, body);
|
|
719
|
+
console.log(JSON.stringify(res, null, 2));
|
|
720
|
+
});
|
|
721
|
+
agentTeams
|
|
722
|
+
.command("add-member")
|
|
723
|
+
.description("POST /v1/agent-teams/:teamId/members — 添加成员(admin only)")
|
|
724
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
725
|
+
.requiredOption("--user <userId>", "User UUID")
|
|
726
|
+
.requiredOption("--role <role>", "admin|manager|supervisor|senior|internal|client")
|
|
727
|
+
.action(async (opts) => {
|
|
728
|
+
const res = await requireClient().addTeamMember(opts.team, {
|
|
729
|
+
userId: opts.user,
|
|
730
|
+
role: opts.role,
|
|
731
|
+
});
|
|
732
|
+
console.log(JSON.stringify(res, null, 2));
|
|
733
|
+
});
|
|
734
|
+
// --- intelligence (subreddit-intelligence) ---
|
|
735
|
+
const intel = program.command("intelligence").description("板块情报与 KOL 挖掘");
|
|
736
|
+
intel
|
|
737
|
+
.command("industry-pools-list")
|
|
738
|
+
.description("GET .../subreddit-intelligence/industry-pools")
|
|
739
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
740
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
741
|
+
.action(async (opts) => {
|
|
742
|
+
const res = await requireClient().listIndustryPools(opts.team, {
|
|
743
|
+
limit: Number(opts.limit),
|
|
744
|
+
});
|
|
745
|
+
console.log(JSON.stringify(res, null, 2));
|
|
746
|
+
});
|
|
747
|
+
intel
|
|
748
|
+
.command("watchlists-list")
|
|
749
|
+
.description("GET .../subreddit-intelligence/watchlists")
|
|
750
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
751
|
+
.option("--campaign <uuid>", "campaignId")
|
|
752
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
753
|
+
.option("--offset <n>", "offset", "0")
|
|
754
|
+
.action(async (opts) => {
|
|
755
|
+
const res = await requireClient().listSubredditWatchlists(opts.team, {
|
|
756
|
+
campaignId: opts.campaign,
|
|
757
|
+
limit: Number(opts.limit),
|
|
758
|
+
offset: Number(opts.offset),
|
|
759
|
+
});
|
|
760
|
+
console.log(JSON.stringify(res, null, 2));
|
|
761
|
+
});
|
|
762
|
+
intel
|
|
763
|
+
.command("watchlists-create")
|
|
764
|
+
.description("POST .../subreddit-intelligence/watchlists")
|
|
765
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
766
|
+
.requiredOption("-j, --json <json>", "{ subreddit, tags? }")
|
|
767
|
+
.action(async (opts) => {
|
|
768
|
+
const body = JSON.parse(opts.json);
|
|
769
|
+
const res = await requireClient().createSubredditWatchlist(opts.team, body);
|
|
770
|
+
console.log(JSON.stringify(res, null, 2));
|
|
771
|
+
});
|
|
772
|
+
intel
|
|
773
|
+
.command("watchlists-update")
|
|
774
|
+
.description("PATCH .../subreddit-intelligence/watchlists/:id")
|
|
775
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
776
|
+
.requiredOption("--id <uuid>", "Watchlist UUID")
|
|
777
|
+
.requiredOption("-j, --json <json>", "update body")
|
|
778
|
+
.action(async (opts) => {
|
|
779
|
+
const body = JSON.parse(opts.json);
|
|
780
|
+
const res = await requireClient().updateSubredditWatchlist(opts.team, opts.id, body);
|
|
781
|
+
console.log(JSON.stringify(res, null, 2));
|
|
782
|
+
});
|
|
783
|
+
intel
|
|
784
|
+
.command("watchlists-delete")
|
|
785
|
+
.description("DELETE .../subreddit-intelligence/watchlists/:id")
|
|
786
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
787
|
+
.requiredOption("--id <uuid>", "Watchlist UUID")
|
|
788
|
+
.action(async (opts) => {
|
|
789
|
+
await requireClient().deleteSubredditWatchlist(opts.team, opts.id);
|
|
790
|
+
console.log("OK");
|
|
791
|
+
});
|
|
792
|
+
intel
|
|
793
|
+
.command("hot-posts")
|
|
794
|
+
.description("GET .../subreddit-intelligence/hot-posts")
|
|
795
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
796
|
+
.option("--subreddit <name>", "板块名称")
|
|
797
|
+
.option("--sort <by>", "score|comments|capturedAt|upvoteRatio", "score")
|
|
798
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
799
|
+
.option("--offset <n>", "offset", "0")
|
|
800
|
+
.action(async (opts) => {
|
|
801
|
+
const res = await requireClient().listHotPosts(opts.team, {
|
|
802
|
+
subreddit: opts.subreddit,
|
|
803
|
+
sortBy: opts.sort,
|
|
804
|
+
limit: Number(opts.limit),
|
|
805
|
+
offset: Number(opts.offset),
|
|
806
|
+
});
|
|
807
|
+
console.log(JSON.stringify(res, null, 2));
|
|
808
|
+
});
|
|
809
|
+
intel
|
|
810
|
+
.command("hot-posts-create")
|
|
811
|
+
.description("POST .../subreddit-intelligence/hot-posts")
|
|
812
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
813
|
+
.requiredOption("-j, --json <json>", "hot post body")
|
|
814
|
+
.action(async (opts) => {
|
|
815
|
+
const body = JSON.parse(opts.json);
|
|
816
|
+
const res = await requireClient().createHotPost(opts.team, body);
|
|
817
|
+
console.log(JSON.stringify(res, null, 2));
|
|
818
|
+
});
|
|
819
|
+
intel
|
|
820
|
+
.command("hot-posts-export")
|
|
821
|
+
.description("GET .../subreddit-intelligence/hot-posts/export.csv")
|
|
822
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
823
|
+
.option("--subreddit <name>", "板块名称")
|
|
824
|
+
.option("-n, --limit <n>", "limit", "500")
|
|
825
|
+
.action(async (opts) => {
|
|
826
|
+
const csv = await requireClient().exportHotPostsCsv(opts.team, {
|
|
827
|
+
subreddit: opts.subreddit,
|
|
828
|
+
limit: Number(opts.limit),
|
|
829
|
+
});
|
|
830
|
+
process.stdout.write(csv);
|
|
831
|
+
});
|
|
832
|
+
intel
|
|
833
|
+
.command("kol-intents")
|
|
834
|
+
.description("GET .../subreddit-intelligence/kol-intents")
|
|
835
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
836
|
+
.option("--campaign <uuid>", "campaignId")
|
|
837
|
+
.option("--status <status>", "interested|contacting|connected|not_interested")
|
|
838
|
+
.option("--sort <by>", "createdAt|status|rating|karma|activity|lastActive", "createdAt")
|
|
839
|
+
.option("--order <order>", "asc|desc", "desc")
|
|
840
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
841
|
+
.option("--offset <n>", "offset", "0")
|
|
842
|
+
.action(async (opts) => {
|
|
843
|
+
const res = await requireClient().listKolIntents(opts.team, {
|
|
844
|
+
campaignId: opts.campaign,
|
|
845
|
+
status: opts.status,
|
|
846
|
+
sortBy: opts.sort,
|
|
847
|
+
sortOrder: opts.order,
|
|
848
|
+
limit: Number(opts.limit),
|
|
849
|
+
offset: Number(opts.offset),
|
|
850
|
+
});
|
|
851
|
+
console.log(JSON.stringify(res, null, 2));
|
|
852
|
+
});
|
|
853
|
+
intel
|
|
854
|
+
.command("kol-intents-create")
|
|
855
|
+
.description("POST .../subreddit-intelligence/kol-intents")
|
|
856
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
857
|
+
.requiredOption("-j, --json <json>", "kol intent body")
|
|
858
|
+
.action(async (opts) => {
|
|
859
|
+
const body = JSON.parse(opts.json);
|
|
860
|
+
const res = await requireClient().createKolIntent(opts.team, body);
|
|
861
|
+
console.log(JSON.stringify(res, null, 2));
|
|
862
|
+
});
|
|
863
|
+
intel
|
|
864
|
+
.command("dispatch")
|
|
865
|
+
.description("POST .../subreddit-intelligence/hot-posts/dispatch-task")
|
|
866
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
867
|
+
.requiredOption("-j, --json <json>", "{ hotPostId, socialAccountId, action, runAt? }")
|
|
868
|
+
.action(async (opts) => {
|
|
869
|
+
const body = JSON.parse(opts.json);
|
|
870
|
+
const res = await requireClient().dispatchTaskFromHotPost(opts.team, body);
|
|
871
|
+
console.log(JSON.stringify(res, null, 2));
|
|
872
|
+
});
|
|
873
|
+
// --- users ---
|
|
874
|
+
const usersCmd = program.command("users").description("团队成员管理");
|
|
875
|
+
usersCmd
|
|
876
|
+
.command("list")
|
|
877
|
+
.description("GET /users")
|
|
878
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
879
|
+
.action(async (opts) => {
|
|
880
|
+
const res = await requireClient().listUsers(opts.team);
|
|
881
|
+
console.log(JSON.stringify(res, null, 2));
|
|
882
|
+
});
|
|
883
|
+
usersCmd
|
|
884
|
+
.command("create")
|
|
885
|
+
.description("POST /users")
|
|
886
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
887
|
+
.requiredOption("-j, --json <json>", "{ email, password, role? }")
|
|
888
|
+
.action(async (opts) => {
|
|
889
|
+
const body = JSON.parse(opts.json);
|
|
890
|
+
const res = await requireClient().createUser(opts.team, body);
|
|
891
|
+
console.log(JSON.stringify(res, null, 2));
|
|
892
|
+
});
|
|
893
|
+
// --- brand-members ---
|
|
894
|
+
const brandMembersCmd = program.command("brand-members").description("品牌成员");
|
|
895
|
+
brandMembersCmd
|
|
896
|
+
.command("list")
|
|
897
|
+
.description("GET /brand-members")
|
|
898
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
899
|
+
.option("--user <uuid>", "userId 过滤")
|
|
900
|
+
.action(async (opts) => {
|
|
901
|
+
const res = await requireClient().listBrandMembers(opts.team, { userId: opts.user });
|
|
902
|
+
console.log(JSON.stringify(res, null, 2));
|
|
903
|
+
});
|
|
904
|
+
brandMembersCmd
|
|
905
|
+
.command("create")
|
|
906
|
+
.description("POST /brand-members")
|
|
907
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
908
|
+
.requiredOption("-j, --json <json>", "{ brandId, userId, role? }")
|
|
909
|
+
.action(async (opts) => {
|
|
910
|
+
const body = JSON.parse(opts.json);
|
|
911
|
+
const res = await requireClient().createBrandMember(opts.team, body);
|
|
912
|
+
console.log(JSON.stringify(res, null, 2));
|
|
913
|
+
});
|
|
914
|
+
// --- notification-channels ---
|
|
915
|
+
const notifChannels = program
|
|
916
|
+
.command("notification-channels")
|
|
917
|
+
.description("通知渠道管理");
|
|
918
|
+
notifChannels
|
|
919
|
+
.command("list")
|
|
920
|
+
.description("GET /notification-channels")
|
|
921
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
922
|
+
.option("--campaign <uuid>", "campaignId 过滤")
|
|
923
|
+
.action(async (opts) => {
|
|
924
|
+
const res = await requireClient().listNotificationChannels(opts.team, {
|
|
925
|
+
campaignId: opts.campaign,
|
|
926
|
+
});
|
|
927
|
+
console.log(JSON.stringify(res, null, 2));
|
|
928
|
+
});
|
|
929
|
+
notifChannels
|
|
930
|
+
.command("create")
|
|
931
|
+
.description("POST /notification-channels")
|
|
932
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
933
|
+
.requiredOption("-j, --json <json>", "{ provider, externalId, minRole?, campaignId? }")
|
|
934
|
+
.action(async (opts) => {
|
|
935
|
+
const body = JSON.parse(opts.json);
|
|
936
|
+
const res = await requireClient().createNotificationChannel(opts.team, body);
|
|
937
|
+
console.log(JSON.stringify(res, null, 2));
|
|
938
|
+
});
|
|
939
|
+
notifChannels
|
|
940
|
+
.command("update")
|
|
941
|
+
.description("PATCH /notification-channels/:id")
|
|
942
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
943
|
+
.requiredOption("--channel <uuid>", "Channel UUID")
|
|
944
|
+
.requiredOption("-j, --json <json>", "update body")
|
|
945
|
+
.action(async (opts) => {
|
|
946
|
+
const body = JSON.parse(opts.json);
|
|
947
|
+
const res = await requireClient().updateNotificationChannel(opts.team, opts.channel, body);
|
|
948
|
+
console.log(JSON.stringify(res, null, 2));
|
|
949
|
+
});
|
|
950
|
+
notifChannels
|
|
951
|
+
.command("delete")
|
|
952
|
+
.description("DELETE /notification-channels/:id")
|
|
953
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
954
|
+
.requiredOption("--channel <uuid>", "Channel UUID")
|
|
955
|
+
.action(async (opts) => {
|
|
956
|
+
await requireClient().deleteNotificationChannel(opts.team, opts.channel);
|
|
957
|
+
console.log("OK");
|
|
958
|
+
});
|
|
959
|
+
notifChannels
|
|
960
|
+
.command("test")
|
|
961
|
+
.description("POST /notification-channels/:id/test")
|
|
962
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
963
|
+
.requiredOption("--channel <uuid>", "Channel UUID")
|
|
964
|
+
.action(async (opts) => {
|
|
965
|
+
const res = await requireClient().testNotificationChannel(opts.team, opts.channel);
|
|
966
|
+
console.log(JSON.stringify(res, null, 2));
|
|
967
|
+
});
|
|
968
|
+
// --- api-keys ---
|
|
969
|
+
const apiKeys = program.command("api-keys").description("API Key 管理");
|
|
970
|
+
apiKeys
|
|
971
|
+
.command("list")
|
|
972
|
+
.description("GET /api-keys")
|
|
973
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
974
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
975
|
+
.action(async (opts) => {
|
|
976
|
+
const res = await requireClient().listApiKeys(opts.team, { limit: Number(opts.limit) });
|
|
977
|
+
console.log(JSON.stringify(res, null, 2));
|
|
978
|
+
});
|
|
979
|
+
apiKeys
|
|
980
|
+
.command("create")
|
|
981
|
+
.description("POST /api-keys")
|
|
982
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
983
|
+
.requiredOption("-j, --json <json>", "{ name, role, visibleCampaignIds? }")
|
|
984
|
+
.action(async (opts) => {
|
|
985
|
+
const body = JSON.parse(opts.json);
|
|
986
|
+
const res = await requireClient().createApiKey(opts.team, body);
|
|
987
|
+
console.log(JSON.stringify(res, null, 2));
|
|
988
|
+
});
|
|
989
|
+
apiKeys
|
|
990
|
+
.command("delete")
|
|
991
|
+
.description("DELETE /api-keys/:id")
|
|
992
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
993
|
+
.requiredOption("--key <uuid>", "API Key UUID")
|
|
994
|
+
.action(async (opts) => {
|
|
995
|
+
await requireClient().deleteApiKey(opts.team, opts.key);
|
|
996
|
+
console.log("OK");
|
|
997
|
+
});
|
|
998
|
+
apiKeys
|
|
999
|
+
.command("rotate")
|
|
1000
|
+
.description("POST /api-keys/:id/rotate")
|
|
1001
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1002
|
+
.requiredOption("--key <uuid>", "API Key UUID")
|
|
1003
|
+
.action(async (opts) => {
|
|
1004
|
+
const res = await requireClient().rotateApiKey(opts.team, opts.key);
|
|
1005
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1006
|
+
});
|
|
1007
|
+
apiKeys
|
|
1008
|
+
.command("batch-revoke")
|
|
1009
|
+
.description("POST /api-keys/batch/revoke")
|
|
1010
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1011
|
+
.requiredOption("-j, --json <json>", '{ "ids": ["uuid1","uuid2"] }')
|
|
1012
|
+
.action(async (opts) => {
|
|
1013
|
+
const body = JSON.parse(opts.json);
|
|
1014
|
+
const res = await requireClient().batchRevokeApiKeys(opts.team, body.ids);
|
|
1015
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1016
|
+
});
|
|
1017
|
+
apiKeys
|
|
1018
|
+
.command("batch-rotate")
|
|
1019
|
+
.description("POST /api-keys/batch/rotate")
|
|
1020
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1021
|
+
.requiredOption("-j, --json <json>", '{ "ids": ["uuid1","uuid2"] }')
|
|
1022
|
+
.action(async (opts) => {
|
|
1023
|
+
const body = JSON.parse(opts.json);
|
|
1024
|
+
const res = await requireClient().batchRotateApiKeys(opts.team, body.ids);
|
|
1025
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1026
|
+
});
|
|
1027
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1028
|
+
// Group C: scattered endpoint additions
|
|
1029
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1030
|
+
events
|
|
1031
|
+
.command("export-csv")
|
|
1032
|
+
.description("GET /events/export.csv(输出 CSV 到 stdout)")
|
|
1033
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1034
|
+
.option("--type <type>", "事件 type 过滤")
|
|
1035
|
+
.option("--actor <actor>", "user|agent|cron")
|
|
1036
|
+
.option("--result <result>", "succeeded|failed|skipped")
|
|
1037
|
+
.option("--account <uuid>", "socialAccountId 过滤")
|
|
1038
|
+
.option("--from <iso>", "createdFrom ISO 时间")
|
|
1039
|
+
.option("--to <iso>", "createdTo ISO 时间")
|
|
1040
|
+
.option("-n, --limit <n>", "limit", "1000")
|
|
1041
|
+
.action(async (opts) => {
|
|
1042
|
+
const csv = await requireClient().exportEventsCsv(opts.team, {
|
|
1043
|
+
type: opts.type,
|
|
1044
|
+
actor: opts.actor,
|
|
1045
|
+
result: opts.result,
|
|
1046
|
+
socialAccountId: opts.account,
|
|
1047
|
+
createdFrom: opts.from,
|
|
1048
|
+
createdTo: opts.to,
|
|
1049
|
+
limit: Number(opts.limit),
|
|
1050
|
+
});
|
|
1051
|
+
process.stdout.write(csv);
|
|
1052
|
+
});
|
|
1053
|
+
reports
|
|
1054
|
+
.command("create")
|
|
1055
|
+
.description("POST /reports(直写入库,非队列 ingest)")
|
|
1056
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1057
|
+
.requiredOption("-j, --json <json>", "{ reportType, title, source, contentMarkdown, summary?, campaignId?, traceId? }")
|
|
1058
|
+
.action(async (opts) => {
|
|
1059
|
+
const body = JSON.parse(opts.json);
|
|
1060
|
+
const res = await requireClient().createReport(opts.team, body);
|
|
1061
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1062
|
+
});
|
|
1063
|
+
jobs
|
|
1064
|
+
.command("agent-status")
|
|
1065
|
+
.description("POST /scheduled-jobs/:id/agent-status(Agent 回写任务状态)")
|
|
1066
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1067
|
+
.requiredOption("-i, --id <jobId>", "Job UUID")
|
|
1068
|
+
.requiredOption("-j, --json <json>", '{ "status": "running"|"succeeded"|"failed", "lastError"?, "payload"? }')
|
|
1069
|
+
.action(async (opts) => {
|
|
1070
|
+
const body = JSON.parse(opts.json);
|
|
1071
|
+
const res = await requireClient().updateJobAgentStatus(opts.team, opts.id, body);
|
|
1072
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1073
|
+
});
|
|
1074
|
+
program
|
|
1075
|
+
.command("permissions-update")
|
|
1076
|
+
.description("PATCH /permissions-matrix(更新权限矩阵,admin only)")
|
|
1077
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1078
|
+
.requiredOption("-j, --json <json>", "权限矩阵更新 body")
|
|
1079
|
+
.action(async (opts) => {
|
|
1080
|
+
const body = JSON.parse(opts.json);
|
|
1081
|
+
const res = await requireClient().updatePermissionsMatrix(opts.team, body);
|
|
1082
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1083
|
+
});
|
|
1084
|
+
graph
|
|
1085
|
+
.command("drilldown")
|
|
1086
|
+
.description("GET /account-graph/drilldown(账号追溯)")
|
|
1087
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1088
|
+
.requiredOption("--account <uuid>", "socialAccountId")
|
|
1089
|
+
.option("-n, --limit <n>", "limit", "20")
|
|
1090
|
+
.action(async (opts) => {
|
|
1091
|
+
const res = await requireClient().getAccountGraphDrilldown(opts.team, {
|
|
1092
|
+
socialAccountId: opts.account,
|
|
1093
|
+
limit: Number(opts.limit),
|
|
1094
|
+
});
|
|
1095
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1096
|
+
});
|
|
1097
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1098
|
+
// Group D: add filter params to existing list commands
|
|
1099
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1100
|
+
// events list → enhanced version
|
|
1101
|
+
events
|
|
1102
|
+
.command("list-full")
|
|
1103
|
+
.description("GET /events(含全部过滤参数)")
|
|
1104
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1105
|
+
.option("--type <type>", "事件 type")
|
|
1106
|
+
.option("--actor <actor>", "user|agent|cron")
|
|
1107
|
+
.option("--result <result>", "succeeded|failed|skipped")
|
|
1108
|
+
.option("--account <uuid>", "socialAccountId")
|
|
1109
|
+
.option("--from <iso>", "createdFrom ISO 时间")
|
|
1110
|
+
.option("--to <iso>", "createdTo ISO 时间")
|
|
1111
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
1112
|
+
.action(async (opts) => {
|
|
1113
|
+
const res = await requireClient().listEventsFiltered(opts.team, {
|
|
1114
|
+
type: opts.type,
|
|
1115
|
+
actor: opts.actor,
|
|
1116
|
+
result: opts.result,
|
|
1117
|
+
socialAccountId: opts.account,
|
|
1118
|
+
createdFrom: opts.from,
|
|
1119
|
+
createdTo: opts.to,
|
|
1120
|
+
limit: Number(opts.limit),
|
|
1121
|
+
});
|
|
1122
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1123
|
+
});
|
|
1124
|
+
calendar
|
|
1125
|
+
.command("list-full")
|
|
1126
|
+
.description("GET /calendar-entries(含全部过滤参数)")
|
|
1127
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1128
|
+
.option("--campaign <uuid>", "campaignId")
|
|
1129
|
+
.option("--plan <uuid>", "publishingPlanId")
|
|
1130
|
+
.option("--account <uuid>", "socialAccountId")
|
|
1131
|
+
.option("--status <st>", "scheduled|running|succeeded|…")
|
|
1132
|
+
.option("--from <iso>", "from ISO 时间")
|
|
1133
|
+
.option("--to <iso>", "to ISO 时间")
|
|
1134
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
1135
|
+
.action(async (opts) => {
|
|
1136
|
+
const res = await requireClient().listCalendarEntries(opts.team, {
|
|
1137
|
+
campaignId: opts.campaign,
|
|
1138
|
+
publishingPlanId: opts.plan,
|
|
1139
|
+
socialAccountId: opts.account,
|
|
1140
|
+
status: opts.status,
|
|
1141
|
+
from: opts.from,
|
|
1142
|
+
to: opts.to,
|
|
1143
|
+
limit: Number(opts.limit),
|
|
1144
|
+
});
|
|
1145
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1146
|
+
});
|
|
1147
|
+
jobs
|
|
1148
|
+
.command("list-full")
|
|
1149
|
+
.description("GET /scheduled-jobs(含全部过滤参数)")
|
|
1150
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1151
|
+
.option("--status <st>", "scheduled|running|…")
|
|
1152
|
+
.option("--account <uuid>", "socialAccountId")
|
|
1153
|
+
.option("--from <iso>", "from ISO 时间")
|
|
1154
|
+
.option("--to <iso>", "to ISO 时间")
|
|
1155
|
+
.option("-n, --limit <n>", "limit", "50")
|
|
1156
|
+
.action(async (opts) => {
|
|
1157
|
+
const res = await requireClient().listScheduledJobs(opts.team, {
|
|
1158
|
+
status: opts.status,
|
|
1159
|
+
socialAccountId: opts.account,
|
|
1160
|
+
from: opts.from,
|
|
1161
|
+
to: opts.to,
|
|
1162
|
+
limit: Number(opts.limit),
|
|
1163
|
+
});
|
|
1164
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1165
|
+
});
|
|
1166
|
+
reddit
|
|
1167
|
+
.command("list-full")
|
|
1168
|
+
.description("GET /reddit-post-snapshots(含全部过滤参数)")
|
|
1169
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1170
|
+
.option("--campaign <uuid>", "campaignId")
|
|
1171
|
+
.option("--entry <uuid>", "calendarEntryId")
|
|
1172
|
+
.option("--account <uuid>", "socialAccountId")
|
|
1173
|
+
.option("-n, --limit <n>", "limit", "100")
|
|
1174
|
+
.action(async (opts) => {
|
|
1175
|
+
const res = await requireClient().listRedditPostSnapshots(opts.team, {
|
|
1176
|
+
campaignId: opts.campaign,
|
|
1177
|
+
calendarEntryId: opts.entry,
|
|
1178
|
+
socialAccountId: opts.account,
|
|
1179
|
+
limit: Number(opts.limit),
|
|
1180
|
+
});
|
|
1181
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1182
|
+
});
|
|
1183
|
+
// --- session ---
|
|
1184
|
+
const session = program.command("session").description("会话管理(cookie-based)");
|
|
1185
|
+
session
|
|
1186
|
+
.command("login")
|
|
1187
|
+
.description("POST /v1/session/login")
|
|
1188
|
+
.requiredOption("--email <email>", "邮箱")
|
|
1189
|
+
.requiredOption("--password <password>", "密码")
|
|
1190
|
+
.action(async (opts) => {
|
|
1191
|
+
const res = await requireClient().sessionLogin({ email: opts.email, password: opts.password });
|
|
1192
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1193
|
+
});
|
|
1194
|
+
session
|
|
1195
|
+
.command("logout")
|
|
1196
|
+
.description("POST /v1/session/logout")
|
|
1197
|
+
.action(async () => {
|
|
1198
|
+
const res = await requireClient().sessionLogout();
|
|
1199
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1200
|
+
});
|
|
1201
|
+
session
|
|
1202
|
+
.command("me")
|
|
1203
|
+
.description("GET /v1/session/me")
|
|
1204
|
+
.action(async () => {
|
|
1205
|
+
const res = await requireClient().sessionMe();
|
|
1206
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1207
|
+
});
|
|
1208
|
+
session
|
|
1209
|
+
.command("active-team")
|
|
1210
|
+
.description("POST /v1/session/active-team")
|
|
1211
|
+
.requiredOption("--team <teamId>", "Team UUID")
|
|
1212
|
+
.action(async (opts) => {
|
|
1213
|
+
const res = await requireClient().sessionActiveTeam({ teamId: opts.team });
|
|
1214
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1215
|
+
});
|
|
1216
|
+
session
|
|
1217
|
+
.command("set-password")
|
|
1218
|
+
.description("POST /v1/session/set-password")
|
|
1219
|
+
.requiredOption("--email <email>", "邮箱")
|
|
1220
|
+
.requiredOption("--password <password>", "新密码")
|
|
1221
|
+
.option("--team <teamId>", "Team UUID(可选)")
|
|
1222
|
+
.action(async (opts) => {
|
|
1223
|
+
const res = await requireClient().sessionSetPassword({ email: opts.email, password: opts.password, teamId: opts.team });
|
|
1224
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1225
|
+
});
|
|
1226
|
+
session
|
|
1227
|
+
.command("update-profile")
|
|
1228
|
+
.description("PATCH /v1/session/profile")
|
|
1229
|
+
.requiredOption("--name <name>", "新姓名")
|
|
1230
|
+
.action(async (opts) => {
|
|
1231
|
+
const res = await requireClient().sessionUpdateProfile({ name: opts.name });
|
|
1232
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1233
|
+
});
|
|
1234
|
+
// --- accounts browser-envs (sub-commands under existing `accounts`) ---
|
|
1235
|
+
const browserEnvs = accounts.command("browser-envs").description("浏览器环境");
|
|
1236
|
+
browserEnvs
|
|
1237
|
+
.command("list-team")
|
|
1238
|
+
.description("GET /browser-environments(Team 全量)")
|
|
1239
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1240
|
+
.action(async (opts) => {
|
|
1241
|
+
const res = await requireClient().listTeamBrowserEnvironments(opts.team);
|
|
1242
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1243
|
+
});
|
|
1244
|
+
browserEnvs
|
|
1245
|
+
.command("list")
|
|
1246
|
+
.description("GET /accounts/:accountId/browser-environments")
|
|
1247
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1248
|
+
.requiredOption("-a, --account <accountId>", "Account UUID")
|
|
1249
|
+
.action(async (opts) => {
|
|
1250
|
+
const res = await requireClient().listAccountBrowserEnvironments(opts.team, opts.account);
|
|
1251
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1252
|
+
});
|
|
1253
|
+
browserEnvs
|
|
1254
|
+
.command("create")
|
|
1255
|
+
.description("POST /accounts/:accountId/browser-environments")
|
|
1256
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1257
|
+
.requiredOption("-a, --account <accountId>", "Account UUID")
|
|
1258
|
+
.option("-j, --json <json>", "env body JSON", "{}")
|
|
1259
|
+
.action(async (opts) => {
|
|
1260
|
+
let body = {};
|
|
1261
|
+
try {
|
|
1262
|
+
body = JSON.parse(opts.json);
|
|
1263
|
+
}
|
|
1264
|
+
catch {
|
|
1265
|
+
console.error("Invalid -j / --json");
|
|
1266
|
+
process.exit(1);
|
|
1267
|
+
}
|
|
1268
|
+
const res = await requireClient().createBrowserEnvironment(opts.team, opts.account, body);
|
|
1269
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1270
|
+
});
|
|
1271
|
+
// --- accounts personas ---
|
|
1272
|
+
const personas = accounts.command("personas").description("账号人设");
|
|
1273
|
+
personas
|
|
1274
|
+
.command("list")
|
|
1275
|
+
.description("GET /accounts/:accountId/personas")
|
|
1276
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1277
|
+
.requiredOption("-a, --account <accountId>", "Account UUID")
|
|
1278
|
+
.action(async (opts) => {
|
|
1279
|
+
const res = await requireClient().listAccountPersonas(opts.team, opts.account);
|
|
1280
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1281
|
+
});
|
|
1282
|
+
personas
|
|
1283
|
+
.command("create")
|
|
1284
|
+
.description("POST /accounts/:accountId/personas")
|
|
1285
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1286
|
+
.requiredOption("-a, --account <accountId>", "Account UUID")
|
|
1287
|
+
.requiredOption("--markdown <text>", "人设 Markdown 文本")
|
|
1288
|
+
.action(async (opts) => {
|
|
1289
|
+
const res = await requireClient().createAccountPersona(opts.team, opts.account, { markdown: opts.markdown });
|
|
1290
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1291
|
+
});
|
|
1292
|
+
// --- campaigns accounts ---
|
|
1293
|
+
const campaignAccounts = campaigns.command("accounts").description("Campaign 账号分配");
|
|
1294
|
+
campaignAccounts
|
|
1295
|
+
.command("list")
|
|
1296
|
+
.description("GET /campaigns/:campaignId/accounts")
|
|
1297
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1298
|
+
.requiredOption("-c, --campaign <campaignId>", "Campaign UUID")
|
|
1299
|
+
.action(async (opts) => {
|
|
1300
|
+
const res = await requireClient().listCampaignAccounts(opts.team, opts.campaign);
|
|
1301
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1302
|
+
});
|
|
1303
|
+
campaignAccounts
|
|
1304
|
+
.command("assign")
|
|
1305
|
+
.description("POST /campaigns/:campaignId/accounts")
|
|
1306
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1307
|
+
.requiredOption("-c, --campaign <campaignId>", "Campaign UUID")
|
|
1308
|
+
.requiredOption("-a, --account <socialAccountId>", "社交账号 UUID")
|
|
1309
|
+
.option("--visibility <v>", "public | private | internal")
|
|
1310
|
+
.action(async (opts) => {
|
|
1311
|
+
const res = await requireClient().assignCampaignAccount(opts.team, opts.campaign, {
|
|
1312
|
+
socialAccountId: opts.account,
|
|
1313
|
+
visibility: opts.visibility,
|
|
1314
|
+
});
|
|
1315
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1316
|
+
});
|
|
1317
|
+
campaignAccounts
|
|
1318
|
+
.command("remove")
|
|
1319
|
+
.description("DELETE /campaigns/:campaignId/accounts/:socialAccountId")
|
|
1320
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1321
|
+
.requiredOption("-c, --campaign <campaignId>", "Campaign UUID")
|
|
1322
|
+
.requiredOption("-a, --account <socialAccountId>", "社交账号 UUID")
|
|
1323
|
+
.action(async (opts) => {
|
|
1324
|
+
const res = await requireClient().removeCampaignAccount(opts.team, opts.campaign, opts.account);
|
|
1325
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1326
|
+
});
|
|
1327
|
+
// --- brand-members remove ---
|
|
1328
|
+
brandMembersCmd
|
|
1329
|
+
.command("remove")
|
|
1330
|
+
.description("DELETE /brand-members/:memberId")
|
|
1331
|
+
.requiredOption("-t, --team <teamId>", "Team UUID")
|
|
1332
|
+
.requiredOption("-m, --member <memberId>", "BrandMember UUID")
|
|
1333
|
+
.action(async (opts) => {
|
|
1334
|
+
const res = await requireClient().deleteBrandMember(opts.team, opts.member);
|
|
1335
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1336
|
+
});
|
|
1337
|
+
// Only parse when run directly (not when imported for testing)
|
|
1338
|
+
if (!process.env["VITEST"]) {
|
|
1339
|
+
program.parse();
|
|
1340
|
+
}
|
|
1341
|
+
export { program };
|
|
1342
|
+
//# sourceMappingURL=index.js.map
|