@thinkingai/ae-cli 6.0.55 → 6.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -6
- package/README.zh.md +35 -6
- package/bin/ae-cli.js +5 -0
- package/bin/runtime-capabilities.json +5 -0
- package/cli-installation-guide.md +24 -3
- package/dist/{auth-RQBO6MTY.js → auth-YEIJLBFY.js} +61 -19
- package/dist/{automation-VAAQBM7Y.js → automation-NAR5DDGL.js} +94 -38
- package/dist/{capability-JRIFC4AJ.js → capability-P7DD4Q73.js} +50 -21
- package/dist/{chunk-5XJYLEVC.js → chunk-72NJKS7O.js} +4 -4
- package/dist/chunk-752BSLZC.js +222 -0
- package/dist/{chunk-RGYPSEYD.js → chunk-7ABK2PEJ.js} +3 -3
- package/dist/{chunk-Q5US7JC5.js → chunk-7JAVT5TK.js} +3 -3
- package/dist/{chunk-GHXZK54S.js → chunk-H3K5UGYC.js} +41 -13
- package/dist/{chunk-OP44TT4H.js → chunk-IN7KKL6K.js} +4 -2
- package/dist/{chunk-VZZNLV3I.js → chunk-JCWM2TYP.js} +61 -15
- package/dist/{chunk-S6M42KND.js → chunk-JEUXDY3B.js} +1 -1
- package/dist/{chunk-ZL7SGNIA.js → chunk-JNVVJ273.js} +58 -46
- package/dist/chunk-N6XBLRB7.js +105 -0
- package/dist/{chunk-AP7YP2NX.js → chunk-OAWPT7VP.js} +2 -2
- package/dist/{chunk-7KU2WNQE.js → chunk-QEMQKVHW.js} +37 -15
- package/dist/{chunk-CT7QDJS6.js → chunk-QVRIDN42.js} +2 -2
- package/dist/{chunk-RPBOAQQQ.js → chunk-QZUVLFNR.js} +1 -1
- package/dist/{chunk-3YVEAZUN.js → chunk-RJHGDWSC.js} +32 -21
- package/dist/{chunk-374V5R6N.js → chunk-TKVVACEJ.js} +6 -4
- package/dist/chunk-TULINOLS.js +2283 -0
- package/dist/chunk-YVG6QD3V.js +233 -0
- package/dist/{chunk-WNGFSIOB.js → chunk-Z3Q2AEIN.js} +237 -86
- package/dist/chunk-ZGIYG473.js +132 -0
- package/dist/{community-report-client-PEERQCX2.js → community-report-client-TJVCLZ3K.js} +1 -1
- package/dist/compat-check-PMEGUPZU.js +32 -0
- package/dist/{config-SICKWZ2A.js → config-VWVPR4WW.js} +43 -10
- package/dist/{context-NGVFPCBK.js → context-F6FCGTF3.js} +4 -4
- package/dist/{data-integration-BCLQFTGU.js → data-integration-6UAZO4GG.js} +207 -24
- package/dist/evaluation-4LO2O4AF.js +3714 -0
- package/dist/index.js +343 -79
- package/dist/{local-data-upload-client-TWMHFLUA.js → local-data-upload-client-KCMG6J62.js} +1 -1
- package/dist/{memory-CQKH2JAV.js → memory-HHPX3NF2.js} +6 -6
- package/dist/{metadata-EMFGUI2W.js → metadata-HEQQEEG3.js} +17 -9
- package/dist/{model-VX5M2CJ6.js → model-7UHGWYVR.js} +4 -4
- package/dist/{personal-semantic-preference-SLWVVYZ4.js → personal-semantic-preference-V4L6ZWR2.js} +7 -6
- package/dist/{project-semantic-DPSZBKQD.js → project-semantic-NKHKJX6M.js} +7 -6
- package/dist/{sync-RZIAV37C.js → sync-ZJMXCRIN.js} +8 -7
- package/dist/{te-agent-AORRE2FM.js → te-agent-WBKIFEQD.js} +757 -94
- package/dist/{te-analysis-ISXKJKRT.js → te-analysis-ADX7RKO4.js} +578 -94
- package/dist/{te-community-42M7ICDO.js → te-community-PREDRXG3.js} +722 -228
- package/dist/{te-dataops-BNKNZ4F2.js → te-dataops-ITWJHO2U.js} +9 -6
- package/dist/{te-engage-BZE3MBKT.js → te-engage-VE2NUH5V.js} +7 -6
- package/dist/{te-kb-ULATOTQ3.js → te-kb-WSMOW7WS.js} +407 -83
- package/dist/{te-system-UGHVKBVV.js → te-system-YM657FKO.js} +6 -6
- package/dist/{te-team-YA6SNOJ3.js → te-team-T2WRLOOD.js} +64 -41
- package/dist/{things-DTCOQIQB.js → things-6QOMFXOG.js} +7 -7
- package/dist/{update-ESNYKUVR.js → update-I4MOUYOX.js} +11 -7
- package/dist/{workspace-JEOHKFPX.js → workspace-LYDAP647.js} +6 -6
- package/package.json +25 -11
- package/skills/ae-agent/SKILL.md +20 -3
- package/skills/ae-agent/references/command_index.md +8 -0
- package/skills/ae-agent/references/resource-package.md +57 -0
- package/skills/ae-analysis/SKILL.md +23 -10
- package/skills/ae-analysis/references/adhoc_export.md +1 -1
- package/skills/ae-analysis/references/agent_review_preflight.md +55 -10
- package/skills/ae-analysis/references/agent_review_priorities_comparisons.md +5 -3
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +60 -24
- package/skills/ae-analysis/references/ai_models/event.md +58 -2
- package/skills/ae-analysis/references/ai_models/rank_list.md +1 -0
- package/skills/ae-analysis/references/ai_models/retention.md +2 -0
- package/skills/ae-analysis/references/ai_models/revenue.md +2 -0
- package/skills/ae-analysis/references/analysis_data_export.md +11 -1
- package/skills/ae-analysis/references/asset_batch_info_export.md +2 -2
- package/skills/ae-analysis/references/asset_batch_sql_export.md +2 -2
- package/skills/ae-analysis/references/asset_export.md +1 -1
- package/skills/ae-analysis/references/bi_panel_page_data_export.md +1 -1
- package/skills/ae-analysis/references/check_export.md +1 -1
- package/skills/ae-analysis/references/command_index.md +39 -26
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/dashboard_report_get.md +6 -2
- package/skills/ae-analysis/references/dashboard_report_update.md +24 -5
- package/skills/ae-analysis/references/feedback_submit.md +1 -1
- package/skills/ae-analysis/references/governance_recommendation_export.md +40 -18
- package/skills/ae-analysis/references/governance_recommendation_run_update.md +13 -0
- package/skills/ae-analysis/references/live_data_export.md +1 -1
- package/skills/ae-analysis/references/metric_create.md +29 -0
- package/skills/ae-analysis/references/metric_get.md +2 -0
- package/skills/ae-analysis/references/metric_update.md +2 -0
- package/skills/ae-analysis/references/operation_record_export.md +1 -1
- package/skills/ae-analysis/references/plan_change_log_export.md +1 -1
- package/skills/ae-analysis/references/plan_export.md +1 -1
- package/skills/ae-analysis/references/project_info_get.md +4 -0
- package/skills/ae-analysis/references/project_member_group_add_members.md +35 -0
- package/skills/ae-analysis/references/project_member_group_create.md +25 -0
- package/skills/ae-analysis/references/project_member_group_delete.md +34 -0
- package/skills/ae-analysis/references/project_member_group_list.md +29 -0
- package/skills/ae-analysis/references/project_member_group_members.md +28 -0
- package/skills/ae-analysis/references/project_member_group_remove_members.md +35 -0
- package/skills/ae-analysis/references/project_member_group_rename.md +26 -0
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +9 -1
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +6 -1
- package/skills/ae-analysis/references/report_data_export.md +1 -1
- package/skills/ae-analysis/references/scenario_append.md +31 -0
- package/skills/ae-analysis/references/scenario_begin.md +11 -0
- package/skills/ae-analysis/references/scenario_collect.md +43 -0
- package/skills/ae-analysis/references/scenario_evaluation.md +18 -0
- package/skills/ae-analysis/references/scenario_get.md +15 -0
- package/skills/ae-analysis/references/scenario_list.md +64 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +73 -4
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +14 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-schema.md +5 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/execution-contract.mjs +173 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +109 -64
- package/skills/ae-automation/SKILL.md +2 -2
- package/skills/ae-automation/references/cli.md +18 -1
- package/skills/ae-capability/SKILL.md +7 -3
- package/skills/ae-community/SKILL.md +77 -27
- package/skills/ae-community/references/community-analyzing-theme-comment.md +10 -8
- package/skills/ae-community/references/community-data-quality.md +68 -0
- package/skills/ae-community/references/community-query-evidence.md +85 -0
- package/skills/ae-community/references/community-scenario-capabilities.md +137 -0
- package/skills/ae-community/references/community-weekly-report.md +6 -3
- package/skills/ae-community/references/get_channel_info.md +7 -4
- package/skills/ae-community/references/get_comment_tag_analysis.md +3 -3
- package/skills/ae-community/references/get_comments_summary.md +4 -4
- package/skills/ae-community/references/get_corpus_tags.md +3 -3
- package/skills/ae-community/references/get_daily_summary.md +3 -3
- package/skills/ae-community/references/get_hot_topics.md +3 -3
- package/skills/ae-community/references/get_livestream_analysis.md +3 -3
- package/skills/ae-community/references/get_livestream_detail.md +4 -4
- package/skills/ae-community/references/get_livestream_list.md +3 -3
- package/skills/ae-community/references/get_livestream_overview.md +3 -3
- package/skills/ae-community/references/get_livestream_room_metrics.md +3 -3
- package/skills/ae-community/references/get_livestream_rooms.md +3 -3
- package/skills/ae-community/references/get_overview_metrics.md +3 -3
- package/skills/ae-community/references/get_post_detail.md +4 -4
- package/skills/ae-community/references/get_risk_content.md +5 -5
- package/skills/ae-community/references/get_sentiment_overview.md +4 -4
- package/skills/ae-community/references/get_tag_trends.md +3 -3
- package/skills/ae-community/references/get_topic_detail.md +3 -3
- package/skills/ae-community/references/list_sources.md +28 -0
- package/skills/ae-community/references/list_spaces.md +39 -0
- package/skills/ae-community/references/search_posts.md +21 -7
- package/skills/ae-data-integration/SKILL.md +6 -4
- package/skills/ae-data-integration/references/error-handling.md +1 -0
- package/skills/ae-data-integration/references/handoff.md +1 -1
- package/skills/ae-data-integration/references/sink-upload.md +11 -0
- package/skills/ae-data-integration/references/source-inspect.md +2 -1
- package/skills/ae-data-integration/references/transform.md +1 -1
- package/skills/ae-data-integration/references/ue-mapping.md +1 -1
- package/skills/ae-evaluation/SKILL.md +83 -0
- package/skills/ae-evaluation/references/access-and-members.md +55 -0
- package/skills/ae-evaluation/references/connections.md +78 -0
- package/skills/ae-evaluation/references/datasets.md +57 -0
- package/skills/ae-evaluation/references/evaluators.md +81 -0
- package/skills/ae-evaluation/references/files.md +33 -0
- package/skills/ae-evaluation/references/integrations.md +39 -0
- package/skills/ae-evaluation/references/runs.md +160 -0
- package/skills/ae-evaluation/references/schedules.md +31 -0
- package/skills/ae-kb/SKILL.md +33 -6
- package/skills/ae-kb/references/publication.md +81 -0
- package/skills/ae-kb/references/query-workflow.md +14 -1
- package/skills/ae-metadata/SKILL.md +3 -2
- package/skills/ae-metadata/references/metadata_data_table_download.md +7 -1
- package/skills/ae-metadata/references/metadata_data_table_get.md +37 -0
- package/skills/ae-team/SKILL.md +2 -2
- package/skills/ae-team/references/run-start.md +1 -0
- package/skills/ae-team/references/run-watch.md +7 -5
- package/skills/ae-things/SKILL.md +53 -51
- package/skills/ae-things/references/cli.md +56 -54
- package/skills/ae-things-progress/SKILL.md +20 -20
- package/skills/ae-things-review/SKILL.md +19 -19
- package/dist/chunk-6VNIR4AP.js +0 -1422
- package/dist/chunk-CI24BDR2.js +0 -43
|
@@ -1,23 +1,40 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
createCapabilityCommand
|
|
4
|
+
} from "./chunk-TKVVACEJ.js";
|
|
5
|
+
import {
|
|
6
|
+
registerCapabilityGatewayRoute,
|
|
7
|
+
resolveGatewayDomain
|
|
4
8
|
} from "./chunk-KPQY44JQ.js";
|
|
9
|
+
import {
|
|
10
|
+
CapabilityGatewayError,
|
|
11
|
+
buildCapabilityGatewayUrl,
|
|
12
|
+
requestCapabilityGatewayWithEnvelope
|
|
13
|
+
} from "./chunk-JCWM2TYP.js";
|
|
14
|
+
import {
|
|
15
|
+
unwrapOutputData,
|
|
16
|
+
withOutputMetadata
|
|
17
|
+
} from "./chunk-752BSLZC.js";
|
|
5
18
|
import {
|
|
6
19
|
internalCallSourceHeaders
|
|
7
20
|
} from "./chunk-Y74WTIKJ.js";
|
|
21
|
+
import "./chunk-TULINOLS.js";
|
|
8
22
|
import {
|
|
9
23
|
SecureStoreAuthError,
|
|
10
24
|
getCliToken
|
|
11
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-H3K5UGYC.js";
|
|
12
26
|
import {
|
|
13
27
|
getActiveHost,
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
parseJsonRequest,
|
|
29
|
+
safeJsonParse,
|
|
30
|
+
stringifyJsonRequest
|
|
31
|
+
} from "./chunk-JNVVJ273.js";
|
|
16
32
|
import {
|
|
17
33
|
CliValidationError,
|
|
18
34
|
PermissionError,
|
|
35
|
+
externalCliTokenRequestOptions,
|
|
19
36
|
logger
|
|
20
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-Z3Q2AEIN.js";
|
|
21
38
|
|
|
22
39
|
// src/core/mcp.ts
|
|
23
40
|
async function permissionDetails(resp) {
|
|
@@ -95,7 +112,8 @@ async function mcpRequest(url, method, params = {}, hostOverride) {
|
|
|
95
112
|
const resp = await fetch(url, {
|
|
96
113
|
method: "POST",
|
|
97
114
|
headers,
|
|
98
|
-
body:
|
|
115
|
+
body: stringifyJsonRequest(body),
|
|
116
|
+
...externalCliTokenRequestOptions(url)
|
|
99
117
|
});
|
|
100
118
|
if (!resp.ok) {
|
|
101
119
|
if (resp.status === 403) {
|
|
@@ -200,13 +218,13 @@ var getChannelInfo = {
|
|
|
200
218
|
command: "+get_channel_info",
|
|
201
219
|
description: "Valid channel list for a community space (channel id and name).",
|
|
202
220
|
flags: [
|
|
203
|
-
{ name: "space-id", type: "
|
|
204
|
-
{ name: "game-id", type: "
|
|
221
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
222
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." }
|
|
205
223
|
],
|
|
206
224
|
risk: "read",
|
|
207
225
|
execute: async (ctx) => {
|
|
208
|
-
const spaceId = ctx.
|
|
209
|
-
const gameId = ctx.
|
|
226
|
+
const spaceId = ctx.int64("space-id");
|
|
227
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
210
228
|
const host = ctx.host();
|
|
211
229
|
const param = { gameId };
|
|
212
230
|
const args = { spaceId, param };
|
|
@@ -216,14 +234,219 @@ var getChannelInfo = {
|
|
|
216
234
|
}
|
|
217
235
|
};
|
|
218
236
|
|
|
237
|
+
// src/commands/te-community/support.ts
|
|
238
|
+
var INTEGER_ENUMS = {
|
|
239
|
+
"+get_comment_tag_analysis:resource-type": [0, 1],
|
|
240
|
+
"+get_post_detail:resource-type": [0, 1],
|
|
241
|
+
"+get_post_detail:danmu-order-by": [0, 1],
|
|
242
|
+
"+get_post_detail:reply-order-by": [0, 1],
|
|
243
|
+
"+get_livestream_detail:order-by": [0, 1],
|
|
244
|
+
"+get_hot_topics:order-by": [0, 1],
|
|
245
|
+
"+get_risk_content:order-by": [0],
|
|
246
|
+
"+search_posts:search-mode": [0, 1, 2],
|
|
247
|
+
"+search_posts:order-by": [0, 1, 2, 3, 4]
|
|
248
|
+
};
|
|
249
|
+
var INTEGER_LIST_ENUMS = {
|
|
250
|
+
"+get_livestream_detail:activity-types": [0, 1, 2, 3],
|
|
251
|
+
"+search_posts:resource-type": [0, 1],
|
|
252
|
+
"+search_posts:sentiment-types": [0, 1, 2]
|
|
253
|
+
};
|
|
254
|
+
function validateCommunityCommand(ctx, command) {
|
|
255
|
+
const gameId = ctx.optionalInt64("game-id");
|
|
256
|
+
const spaceId = command.flags.some((flag) => flag.name === "space-id") ? ctx.int64("space-id") : void 0;
|
|
257
|
+
if (spaceId !== void 0 && gameId !== void 0 && gameId !== spaceId) {
|
|
258
|
+
throw validationError(
|
|
259
|
+
"--game-id must match --space-id",
|
|
260
|
+
"Omit --game-id; it is a deprecated compatibility alias and defaults to --space-id."
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
validateTemporalFlag(ctx, command, "date", "date");
|
|
264
|
+
validateTemporalFlag(ctx, command, "start-time", "date-time");
|
|
265
|
+
validateTemporalFlag(ctx, command, "end-time", "date-time");
|
|
266
|
+
validateTemporalFlag(ctx, command, "anchor-time", "minute");
|
|
267
|
+
validateTemporalFlag(ctx, command, "year", "year");
|
|
268
|
+
validateRange(ctx, command);
|
|
269
|
+
validateInt64Csv(ctx, command, "channel-id-list");
|
|
270
|
+
validateInt64Csv(ctx, command, "risk-codes");
|
|
271
|
+
if (command.flags.some((flag) => flag.name === "tag-filters") && ctx.str("tag-filters").trim()) {
|
|
272
|
+
validateTagFilters(ctx.json("tag-filters"));
|
|
273
|
+
}
|
|
274
|
+
for (const [key, choices] of Object.entries(INTEGER_ENUMS)) {
|
|
275
|
+
const [commandName, flagName] = key.split(":");
|
|
276
|
+
if (command.command === commandName) validateIntegerEnum(ctx, command, flagName, choices);
|
|
277
|
+
}
|
|
278
|
+
for (const [key, choices] of Object.entries(INTEGER_LIST_ENUMS)) {
|
|
279
|
+
const [commandName, flagName] = key.split(":");
|
|
280
|
+
if (command.command === commandName) validateIntegerCsv(ctx, command, flagName, choices);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function stringCsv(ctx, name) {
|
|
284
|
+
const raw = ctx.str(name).trim();
|
|
285
|
+
if (!raw) return void 0;
|
|
286
|
+
const values = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
287
|
+
return values.length > 0 ? values : void 0;
|
|
288
|
+
}
|
|
289
|
+
function tagFilters(ctx) {
|
|
290
|
+
const raw = ctx.str("tag-filters").trim();
|
|
291
|
+
if (!raw) return void 0;
|
|
292
|
+
const value = ctx.json("tag-filters");
|
|
293
|
+
validateTagFilters(value);
|
|
294
|
+
return value;
|
|
295
|
+
}
|
|
296
|
+
function validateTemporalFlag(ctx, command, name, format) {
|
|
297
|
+
if (!command.flags.some((flag) => flag.name === name)) return;
|
|
298
|
+
const value = ctx.str(name).trim();
|
|
299
|
+
if (!value) return;
|
|
300
|
+
if (format === "year") {
|
|
301
|
+
if (!/^\d{4}$/.test(value)) {
|
|
302
|
+
throw validationError(`--${name} must use yyyy format`);
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (format === "minute") {
|
|
307
|
+
if (!parseDateTime(value, true)) {
|
|
308
|
+
throw validationError(`--${name} must use yyyy-MM-dd HH:mm format`);
|
|
309
|
+
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (format === "date") {
|
|
313
|
+
if (!parseDate(value)) {
|
|
314
|
+
throw validationError(`--${name} must be a valid date in yyyy-MM-dd format`);
|
|
315
|
+
}
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (!parseDate(value) && !parseDateTime(value, false)) {
|
|
319
|
+
throw validationError(
|
|
320
|
+
`--${name} must be a valid date or timestamp`,
|
|
321
|
+
"Use yyyy-MM-dd, yyyy-MM-dd HH:mm, or yyyy-MM-dd HH:mm:ss."
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function validateRange(ctx, command) {
|
|
326
|
+
if (!command.flags.some((flag) => flag.name === "start-time") || !command.flags.some((flag) => flag.name === "end-time")) return;
|
|
327
|
+
const start = temporalValue(ctx.str("start-time"));
|
|
328
|
+
const end = temporalValue(ctx.str("end-time"));
|
|
329
|
+
if (start !== void 0 && end !== void 0 && end < start) {
|
|
330
|
+
throw validationError("--end-time must not be earlier than --start-time");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function validateInt64Csv(ctx, command, name) {
|
|
334
|
+
if (!command.flags.some((flag) => flag.name === name)) return;
|
|
335
|
+
const raw = ctx.str(name).trim();
|
|
336
|
+
if (!raw) return;
|
|
337
|
+
const values = raw.split(",");
|
|
338
|
+
const max = (1n << 63n) - 1n;
|
|
339
|
+
for (const value of values) {
|
|
340
|
+
const item = value.trim();
|
|
341
|
+
if (!/^[1-9]\d*$/.test(item) || BigInt(item) > max) {
|
|
342
|
+
throw validationError(`--${name} must be a comma-separated list of positive int64 values`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function validateIntegerEnum(ctx, command, name, choices) {
|
|
347
|
+
if (!command.flags.some((flag) => flag.name === name)) return;
|
|
348
|
+
const raw = ctx.str(name).trim();
|
|
349
|
+
if (!raw) return;
|
|
350
|
+
const value = Number(raw);
|
|
351
|
+
if (!Number.isInteger(value) || !choices.includes(value)) {
|
|
352
|
+
throw validationError(`--${name} must be one of: ${choices.join(", ")}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function validateIntegerCsv(ctx, command, name, choices) {
|
|
356
|
+
if (!command.flags.some((flag) => flag.name === name)) return;
|
|
357
|
+
const raw = ctx.str(name).trim();
|
|
358
|
+
if (!raw) return;
|
|
359
|
+
const values = raw.split(",").map((value) => Number(value.trim()));
|
|
360
|
+
if (values.some((value) => !Number.isInteger(value) || !choices.includes(value))) {
|
|
361
|
+
throw validationError(
|
|
362
|
+
`--${name} must be a comma-separated list containing only: ${choices.join(", ")}`
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function validateTagFilters(value) {
|
|
367
|
+
if (!Array.isArray(value)) {
|
|
368
|
+
throw validationError("--tag-filters must be a JSON array");
|
|
369
|
+
}
|
|
370
|
+
const required = ["tagName", "tagCode", "inferenceType", "calcuSymbol"];
|
|
371
|
+
value.forEach((item, index) => {
|
|
372
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
373
|
+
throw validationError(`--tag-filters item ${index + 1} must be an object`);
|
|
374
|
+
}
|
|
375
|
+
const record2 = item;
|
|
376
|
+
for (const field2 of required) {
|
|
377
|
+
if (typeof record2[field2] !== "string" || !record2[field2].trim()) {
|
|
378
|
+
throw validationError(`--tag-filters item ${index + 1} requires non-empty ${field2}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const inferenceType = String(record2.inferenceType);
|
|
382
|
+
const calcuSymbol = String(record2.calcuSymbol);
|
|
383
|
+
if (inferenceType !== "label" && inferenceType !== "score") {
|
|
384
|
+
throw validationError(
|
|
385
|
+
`--tag-filters item ${index + 1} inferenceType must be label or score`,
|
|
386
|
+
"Use inferenceType from +get_corpus_tags; extract tags are not filterable by search_posts."
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
const allowedSymbols = inferenceType === "label" ? ["C04", "C05"] : ["C00", "C01", "C02", "C020", "C03", "C030", "C04", "C05", "C06"];
|
|
390
|
+
if (!allowedSymbols.includes(calcuSymbol)) {
|
|
391
|
+
throw validationError(
|
|
392
|
+
`--tag-filters item ${index + 1} calcuSymbol must be one of: ${allowedSymbols.join(", ")}`
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
if (inferenceType === "score" && !["C04", "C05"].includes(calcuSymbol)) {
|
|
396
|
+
if (!Array.isArray(record2.ftv)) {
|
|
397
|
+
throw validationError(
|
|
398
|
+
`--tag-filters item ${index + 1} ftv must be an array for score comparison ${calcuSymbol}`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
const requiredValues = calcuSymbol === "C06" ? 2 : 1;
|
|
402
|
+
if (record2.ftv.length < requiredValues) {
|
|
403
|
+
throw validationError(
|
|
404
|
+
`--tag-filters item ${index + 1} ftv requires at least ${requiredValues} value${requiredValues === 1 ? "" : "s"}`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
function parseDate(value) {
|
|
411
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
412
|
+
if (!match) return void 0;
|
|
413
|
+
return validatedUtc(Number(match[1]), Number(match[2]), Number(match[3]), 0, 0, 0);
|
|
414
|
+
}
|
|
415
|
+
function parseDateTime(value, minuteOnly) {
|
|
416
|
+
const pattern = minuteOnly ? /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})$/ : /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})(?::(\d{2}))?$/;
|
|
417
|
+
const match = pattern.exec(value);
|
|
418
|
+
if (!match) return void 0;
|
|
419
|
+
return validatedUtc(
|
|
420
|
+
Number(match[1]),
|
|
421
|
+
Number(match[2]),
|
|
422
|
+
Number(match[3]),
|
|
423
|
+
Number(match[4]),
|
|
424
|
+
Number(match[5]),
|
|
425
|
+
Number(match[6] ?? 0)
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
function validatedUtc(year, month, day, hour, minute, second) {
|
|
429
|
+
const value = new Date(Date.UTC(year, month - 1, day, hour, minute, second));
|
|
430
|
+
if (value.getUTCFullYear() !== year || value.getUTCMonth() !== month - 1 || value.getUTCDate() !== day || value.getUTCHours() !== hour || value.getUTCMinutes() !== minute || value.getUTCSeconds() !== second) return void 0;
|
|
431
|
+
return value.getTime();
|
|
432
|
+
}
|
|
433
|
+
function temporalValue(value) {
|
|
434
|
+
const trimmed = value.trim();
|
|
435
|
+
if (!trimmed) return void 0;
|
|
436
|
+
return parseDate(trimmed) ?? parseDateTime(trimmed, false);
|
|
437
|
+
}
|
|
438
|
+
function validationError(message, hint) {
|
|
439
|
+
return new CliValidationError(message, hint ? { hint } : void 0);
|
|
440
|
+
}
|
|
441
|
+
|
|
219
442
|
// src/commands/te-community/search_posts.ts
|
|
220
443
|
var searchPosts = {
|
|
221
444
|
service: "community",
|
|
222
445
|
command: "+search_posts",
|
|
223
446
|
description: "Search social posts/videos/feeds in a community space.",
|
|
224
447
|
flags: [
|
|
225
|
-
{ name: "space-id", type: "
|
|
226
|
-
{ name: "game-id", type: "
|
|
448
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
449
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
227
450
|
{ name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info (channelId). Comma-separated." },
|
|
228
451
|
{ name: "keywords", type: "string", required: false, desc: "Keyword filter list. Comma-separated." },
|
|
229
452
|
{ name: "start-time", type: "string", required: true, desc: "Content publish time lower bound. Format: yyyy-MM-dd." },
|
|
@@ -233,40 +456,46 @@ var searchPosts = {
|
|
|
233
456
|
{ name: "search-mode", type: "number", required: false, desc: 'Search mode: 0 tokenized (default), 1 exact substring (e.g. \\"#tag\\" matches only posts containing that full string), 2 author name.' },
|
|
234
457
|
{ name: "search-word", type: "string", required: false, desc: "Full-text query; used together with searchMode." },
|
|
235
458
|
{ name: "sentiment-types", type: "string", required: false, desc: "Sentiment filter: 0 negative, 1 positive, 2 neutral. Comma-separated." },
|
|
459
|
+
{ name: "topic-id-list", type: "string", required: false, desc: "Topic IDs from +get_hot_topics (topicId). Comma-separated." },
|
|
460
|
+
{ name: "tag-filters", type: "json", required: false, desc: "Corpus tag filter JSON array using tagName, tagCode, inferenceType, calcuSymbol, and optional ftv." },
|
|
236
461
|
{ name: "order-by", type: "number", required: false, desc: "Sort: 0 publish time desc, 1 weight desc, 2 publish time asc, 3 reply count desc, 4 heat desc." },
|
|
237
462
|
{ name: "page-num", type: "number", required: false, desc: "Page number, starting at 1." },
|
|
238
463
|
{ name: "page-size", type: "number", required: false, desc: "Page size. Max 10000." }
|
|
239
464
|
],
|
|
240
465
|
risk: "read",
|
|
241
466
|
execute: async (ctx) => {
|
|
242
|
-
const spaceId = ctx.
|
|
243
|
-
const gameId = ctx.
|
|
467
|
+
const spaceId = ctx.int64("space-id");
|
|
468
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
244
469
|
const startTime = ctx.str("start-time");
|
|
245
470
|
const endTime = ctx.str("end-time");
|
|
246
471
|
const host = ctx.host();
|
|
247
472
|
const param = { gameId, startTime, endTime };
|
|
248
473
|
const channelIdList = ctx.str("channel-id-list");
|
|
249
|
-
if (channelIdList) param.channelIdList = channelIdList.split(",").map(
|
|
474
|
+
if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
|
|
250
475
|
const keywords = ctx.str("keywords");
|
|
251
476
|
if (keywords) param.keywords = keywords.split(",");
|
|
252
|
-
const official = ctx.
|
|
477
|
+
const official = ctx.optionalBool("official");
|
|
253
478
|
if (official !== void 0) param.official = official;
|
|
254
479
|
const resourceType = ctx.str("resource-type");
|
|
255
480
|
if (resourceType) param.resourceType = resourceType.split(",").map(Number);
|
|
256
|
-
const searchMode = ctx.
|
|
481
|
+
const searchMode = ctx.optionalNum("search-mode");
|
|
257
482
|
if (searchMode !== void 0) param.searchMode = searchMode;
|
|
258
483
|
const searchWord = ctx.str("search-word");
|
|
259
484
|
if (searchWord) param.searchWord = searchWord;
|
|
260
485
|
const sentimentTypes = ctx.str("sentiment-types");
|
|
261
486
|
if (sentimentTypes) param.sentimentTypes = sentimentTypes.split(",").map(Number);
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
487
|
+
const topicIdList = stringCsv(ctx, "topic-id-list");
|
|
488
|
+
if (topicIdList) param.topicIdList = topicIdList;
|
|
489
|
+
const parsedTagFilters = tagFilters(ctx);
|
|
490
|
+
if (parsedTagFilters) param.tagFilters = parsedTagFilters;
|
|
491
|
+
const orderBy = ctx.optionalNum("order-by");
|
|
492
|
+
const pageNum = ctx.optionalNum("page-num");
|
|
493
|
+
const pageSize = ctx.optionalNum("page-size");
|
|
494
|
+
if (orderBy !== void 0 || pageNum !== void 0 || pageSize !== void 0) {
|
|
266
495
|
param.pagerHeader = {};
|
|
267
496
|
if (orderBy !== void 0) param.pagerHeader.orderBy = orderBy;
|
|
268
|
-
if (pageNum) param.pagerHeader.pageNum = pageNum;
|
|
269
|
-
if (pageSize) param.pagerHeader.pageSize = pageSize;
|
|
497
|
+
if (pageNum !== void 0) param.pagerHeader.pageNum = pageNum;
|
|
498
|
+
if (pageSize !== void 0) param.pagerHeader.pageSize = pageSize;
|
|
270
499
|
}
|
|
271
500
|
const args = { spaceId, param };
|
|
272
501
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
|
|
@@ -281,9 +510,9 @@ var getPostDetail = {
|
|
|
281
510
|
command: "+get_post_detail",
|
|
282
511
|
description: "Full detail for one post/video: body, media, subtitles, danmu, sentiment, keywords, topics, tag values, and comment pager.",
|
|
283
512
|
flags: [
|
|
284
|
-
{ name: "space-id", type: "
|
|
285
|
-
{ name: "game-id", type: "
|
|
286
|
-
{ name: "channel-id", type: "
|
|
513
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
514
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
515
|
+
{ name: "channel-id", type: "int64", required: true, min: 1, desc: "Channel ID." },
|
|
287
516
|
{ name: "uuid", type: "string", required: true, desc: "Content UUID (unique id)." },
|
|
288
517
|
{ name: "resource-type", type: "number", required: true, desc: "Resource type: 0 post, 1 video." },
|
|
289
518
|
{ name: "danmu-order-by", type: "number", required: false, desc: "Sort for danmu: 0 video timestamp desc, 1 publish time desc." },
|
|
@@ -295,30 +524,30 @@ var getPostDetail = {
|
|
|
295
524
|
],
|
|
296
525
|
risk: "read",
|
|
297
526
|
execute: async (ctx) => {
|
|
298
|
-
const spaceId = ctx.
|
|
299
|
-
const gameId = ctx.
|
|
300
|
-
const channelId = ctx.
|
|
527
|
+
const spaceId = ctx.int64("space-id");
|
|
528
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
529
|
+
const channelId = ctx.int64("channel-id");
|
|
301
530
|
const uuid = ctx.str("uuid");
|
|
302
531
|
const resourceType = ctx.num("resource-type");
|
|
303
532
|
const host = ctx.host();
|
|
304
533
|
const param = { gameId, channelId, uuid, resourceType };
|
|
305
|
-
const danmuOrderBy = ctx.
|
|
306
|
-
const danmuPageNum = ctx.
|
|
307
|
-
const danmuPageSize = ctx.
|
|
308
|
-
if (danmuOrderBy !== void 0 || danmuPageNum || danmuPageSize) {
|
|
534
|
+
const danmuOrderBy = ctx.optionalNum("danmu-order-by");
|
|
535
|
+
const danmuPageNum = ctx.optionalNum("danmu-page-num");
|
|
536
|
+
const danmuPageSize = ctx.optionalNum("danmu-page-size");
|
|
537
|
+
if (danmuOrderBy !== void 0 || danmuPageNum !== void 0 || danmuPageSize !== void 0) {
|
|
309
538
|
param.danmuPagerHeader = {};
|
|
310
539
|
if (danmuOrderBy !== void 0) param.danmuPagerHeader.orderBy = danmuOrderBy;
|
|
311
|
-
if (danmuPageNum) param.danmuPagerHeader.pageNum = danmuPageNum;
|
|
312
|
-
if (danmuPageSize) param.danmuPagerHeader.pageSize = danmuPageSize;
|
|
540
|
+
if (danmuPageNum !== void 0) param.danmuPagerHeader.pageNum = danmuPageNum;
|
|
541
|
+
if (danmuPageSize !== void 0) param.danmuPagerHeader.pageSize = danmuPageSize;
|
|
313
542
|
}
|
|
314
|
-
const replyOrderBy = ctx.
|
|
315
|
-
const replyPageNum = ctx.
|
|
316
|
-
const replyPageSize = ctx.
|
|
317
|
-
if (replyOrderBy !== void 0 || replyPageNum || replyPageSize) {
|
|
543
|
+
const replyOrderBy = ctx.optionalNum("reply-order-by");
|
|
544
|
+
const replyPageNum = ctx.optionalNum("reply-page-num");
|
|
545
|
+
const replyPageSize = ctx.optionalNum("reply-page-size");
|
|
546
|
+
if (replyOrderBy !== void 0 || replyPageNum !== void 0 || replyPageSize !== void 0) {
|
|
318
547
|
param.replyPagerHeader = {};
|
|
319
548
|
if (replyOrderBy !== void 0) param.replyPagerHeader.orderBy = replyOrderBy;
|
|
320
|
-
if (replyPageNum) param.replyPagerHeader.pageNum = replyPageNum;
|
|
321
|
-
if (replyPageSize) param.replyPagerHeader.pageSize = replyPageSize;
|
|
549
|
+
if (replyPageNum !== void 0) param.replyPagerHeader.pageNum = replyPageNum;
|
|
550
|
+
if (replyPageSize !== void 0) param.replyPagerHeader.pageSize = replyPageSize;
|
|
322
551
|
}
|
|
323
552
|
const args = { spaceId, param };
|
|
324
553
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
|
|
@@ -333,22 +562,22 @@ var getOverviewMetrics = {
|
|
|
333
562
|
command: "+get_overview_metrics",
|
|
334
563
|
description: "Overall community metrics in a date range: post/reply counts, sentiment counts, per-channel breakdown.",
|
|
335
564
|
flags: [
|
|
336
|
-
{ name: "space-id", type: "
|
|
337
|
-
{ name: "game-id", type: "
|
|
565
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
566
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
338
567
|
{ name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info (channelId)." },
|
|
339
568
|
{ name: "start-time", type: "string", required: true, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
340
569
|
{ name: "end-time", type: "string", required: true, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
|
|
341
570
|
],
|
|
342
571
|
risk: "read",
|
|
343
572
|
execute: async (ctx) => {
|
|
344
|
-
const spaceId = ctx.
|
|
345
|
-
const gameId = ctx.
|
|
573
|
+
const spaceId = ctx.int64("space-id");
|
|
574
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
346
575
|
const startTime = ctx.str("start-time");
|
|
347
576
|
const endTime = ctx.str("end-time");
|
|
348
577
|
const host = ctx.host();
|
|
349
578
|
const param = { gameId, startTime, endTime };
|
|
350
579
|
const channelIdList = ctx.str("channel-id-list");
|
|
351
|
-
if (channelIdList) param.channelIdList = channelIdList.split(",").map(
|
|
580
|
+
if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
|
|
352
581
|
const args = { spaceId, param };
|
|
353
582
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_analysis");
|
|
354
583
|
const result = await callMcpTool(mcpUrl, "get_overview_metrics", args, host);
|
|
@@ -362,8 +591,8 @@ var getSentimentOverview = {
|
|
|
362
591
|
command: "+get_sentiment_overview",
|
|
363
592
|
description: "Sentiment distribution and hot-keyword overview: top keywords per sentiment with trends, plus overall keyword ranking.",
|
|
364
593
|
flags: [
|
|
365
|
-
{ name: "space-id", type: "
|
|
366
|
-
{ name: "game-id", type: "
|
|
594
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
595
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
367
596
|
{ name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info (channelId)." },
|
|
368
597
|
{ name: "start-time", type: "string", required: true, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
369
598
|
{ name: "end-time", type: "string", required: true, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." },
|
|
@@ -372,18 +601,18 @@ var getSentimentOverview = {
|
|
|
372
601
|
],
|
|
373
602
|
risk: "read",
|
|
374
603
|
execute: async (ctx) => {
|
|
375
|
-
const spaceId = ctx.
|
|
376
|
-
const gameId = ctx.
|
|
604
|
+
const spaceId = ctx.int64("space-id");
|
|
605
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
377
606
|
const startTime = ctx.str("start-time");
|
|
378
607
|
const endTime = ctx.str("end-time");
|
|
379
608
|
const host = ctx.host();
|
|
380
609
|
const param = { gameId, startTime, endTime };
|
|
381
610
|
const channelIdList = ctx.str("channel-id-list");
|
|
382
|
-
if (channelIdList) param.channelIdList = channelIdList.split(",").map(
|
|
383
|
-
const isMerged = ctx.
|
|
611
|
+
if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
|
|
612
|
+
const isMerged = ctx.optionalBool("is-merged");
|
|
384
613
|
if (isMerged !== void 0) param.isMerged = isMerged;
|
|
385
|
-
const limit = ctx.
|
|
386
|
-
if (limit) param.limit = limit;
|
|
614
|
+
const limit = ctx.optionalNum("limit");
|
|
615
|
+
if (limit !== void 0) param.limit = limit;
|
|
387
616
|
const args = { spaceId, param };
|
|
388
617
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_analysis");
|
|
389
618
|
const result = await callMcpTool(mcpUrl, "get_sentiment_overview", args, host);
|
|
@@ -397,8 +626,8 @@ var getTagTrends = {
|
|
|
397
626
|
command: "+get_tag_trends",
|
|
398
627
|
description: "Daily tag trends: given tagCode and date range, returns counts and time series per tag value.",
|
|
399
628
|
flags: [
|
|
400
|
-
{ name: "space-id", type: "
|
|
401
|
-
{ name: "game-id", type: "
|
|
629
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
630
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
402
631
|
{ name: "tag-code", type: "string", required: true, desc: "Tag code (tagCode) from +get_corpus_tags." },
|
|
403
632
|
{ name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info." },
|
|
404
633
|
{ name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
@@ -406,13 +635,13 @@ var getTagTrends = {
|
|
|
406
635
|
],
|
|
407
636
|
risk: "read",
|
|
408
637
|
execute: async (ctx) => {
|
|
409
|
-
const spaceId = ctx.
|
|
410
|
-
const gameId = ctx.
|
|
638
|
+
const spaceId = ctx.int64("space-id");
|
|
639
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
411
640
|
const tagCode = ctx.str("tag-code");
|
|
412
641
|
const host = ctx.host();
|
|
413
642
|
const param = { gameId, tagCode };
|
|
414
643
|
const channelIdList = ctx.str("channel-id-list");
|
|
415
|
-
if (channelIdList) param.channelIdList = channelIdList.split(",").map(
|
|
644
|
+
if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
|
|
416
645
|
const startTime = ctx.str("start-time");
|
|
417
646
|
if (startTime) param.startTime = startTime;
|
|
418
647
|
const endTime = ctx.str("end-time");
|
|
@@ -430,14 +659,14 @@ var getDailySummary = {
|
|
|
430
659
|
command: "+get_daily_summary",
|
|
431
660
|
description: "Daily community summary for a given date: hot topic rankings and highlighted opinions (positive/negative).",
|
|
432
661
|
flags: [
|
|
433
|
-
{ name: "space-id", type: "
|
|
434
|
-
{ name: "game-id", type: "
|
|
662
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
663
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
435
664
|
{ name: "date", type: "string", required: true, desc: "Summary date. Format: yyyy-MM-dd." }
|
|
436
665
|
],
|
|
437
666
|
risk: "read",
|
|
438
667
|
execute: async (ctx) => {
|
|
439
|
-
const spaceId = ctx.
|
|
440
|
-
const gameId = ctx.
|
|
668
|
+
const spaceId = ctx.int64("space-id");
|
|
669
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
441
670
|
const date = ctx.str("date");
|
|
442
671
|
const host = ctx.host();
|
|
443
672
|
const param = { gameId, date };
|
|
@@ -454,23 +683,23 @@ var getHotTopics = {
|
|
|
454
683
|
command: "+get_hot_topics",
|
|
455
684
|
description: "Hot topics leaderboard over a time range.",
|
|
456
685
|
flags: [
|
|
457
|
-
{ name: "space-id", type: "
|
|
458
|
-
{ name: "game-id", type: "
|
|
686
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
687
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
459
688
|
{ name: "start-time", type: "string", required: false, desc: "Topic statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
460
689
|
{ name: "end-time", type: "string", required: false, desc: "Topic statistics range end (inclusive). Format: yyyy-MM-dd." },
|
|
461
690
|
{ name: "order-by", type: "number", required: false, desc: "Sort: 0 by topic heat desc, 1 by topic start time desc." }
|
|
462
691
|
],
|
|
463
692
|
risk: "read",
|
|
464
693
|
execute: async (ctx) => {
|
|
465
|
-
const spaceId = ctx.
|
|
466
|
-
const gameId = ctx.
|
|
694
|
+
const spaceId = ctx.int64("space-id");
|
|
695
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
467
696
|
const host = ctx.host();
|
|
468
697
|
const param = { gameId };
|
|
469
698
|
const startTime = ctx.str("start-time");
|
|
470
699
|
if (startTime) param.startTime = startTime;
|
|
471
700
|
const endTime = ctx.str("end-time");
|
|
472
701
|
if (endTime) param.endTime = endTime;
|
|
473
|
-
const orderBy = ctx.
|
|
702
|
+
const orderBy = ctx.optionalNum("order-by");
|
|
474
703
|
if (orderBy !== void 0) param.orderBy = orderBy;
|
|
475
704
|
const args = { spaceId, param };
|
|
476
705
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_hot");
|
|
@@ -485,16 +714,16 @@ var getTopicDetail = {
|
|
|
485
714
|
command: "+get_topic_detail",
|
|
486
715
|
description: "Deep stats for one topic in a range: content/reply totals, sentiment, per-channel daily trends, hot keywords.",
|
|
487
716
|
flags: [
|
|
488
|
-
{ name: "space-id", type: "
|
|
489
|
-
{ name: "game-id", type: "
|
|
717
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
718
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
490
719
|
{ name: "topic-id", type: "string", required: true, desc: "Topic ID from +get_hot_topics (topicId)." },
|
|
491
720
|
{ name: "start-time", type: "string", required: true, desc: "Statistics start date. Format: yyyy-MM-dd. Prefer topic startTime from +get_hot_topics." },
|
|
492
721
|
{ name: "end-time", type: "string", required: true, desc: "Statistics end date. Format: yyyy-MM-dd. Prefer topic endTime from +get_hot_topics." }
|
|
493
722
|
],
|
|
494
723
|
risk: "read",
|
|
495
724
|
execute: async (ctx) => {
|
|
496
|
-
const spaceId = ctx.
|
|
497
|
-
const gameId = ctx.
|
|
725
|
+
const spaceId = ctx.int64("space-id");
|
|
726
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
498
727
|
const topicId = ctx.str("topic-id");
|
|
499
728
|
const startTime = ctx.str("start-time");
|
|
500
729
|
const endTime = ctx.str("end-time");
|
|
@@ -513,15 +742,15 @@ var getLivestreamOverview = {
|
|
|
513
742
|
command: "+get_livestream_overview",
|
|
514
743
|
description: "Livestream overview trends: active rooms, session count, interactions, and streamed duration.",
|
|
515
744
|
flags: [
|
|
516
|
-
{ name: "space-id", type: "
|
|
517
|
-
{ name: "game-id", type: "
|
|
745
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
746
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
518
747
|
{ name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
519
748
|
{ name: "end-time", type: "string", required: false, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
|
|
520
749
|
],
|
|
521
750
|
risk: "read",
|
|
522
751
|
execute: async (ctx) => {
|
|
523
|
-
const spaceId = ctx.
|
|
524
|
-
const gameId = ctx.
|
|
752
|
+
const spaceId = ctx.int64("space-id");
|
|
753
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
525
754
|
const host = ctx.host();
|
|
526
755
|
const param = { gameId };
|
|
527
756
|
const startTime = ctx.str("start-time");
|
|
@@ -541,20 +770,20 @@ var getLivestreamRooms = {
|
|
|
541
770
|
command: "+get_livestream_rooms",
|
|
542
771
|
description: "Search live rooms by time range and channels; returns room list with stats.",
|
|
543
772
|
flags: [
|
|
544
|
-
{ name: "space-id", type: "
|
|
545
|
-
{ name: "game-id", type: "
|
|
773
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
774
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
546
775
|
{ name: "channel-id-list", type: "string", required: false, desc: "Channel ID list." },
|
|
547
776
|
{ name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
548
777
|
{ name: "end-time", type: "string", required: false, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
|
|
549
778
|
],
|
|
550
779
|
risk: "read",
|
|
551
780
|
execute: async (ctx) => {
|
|
552
|
-
const spaceId = ctx.
|
|
553
|
-
const gameId = ctx.
|
|
781
|
+
const spaceId = ctx.int64("space-id");
|
|
782
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
554
783
|
const host = ctx.host();
|
|
555
784
|
const param = { gameId };
|
|
556
785
|
const channelIdList = ctx.str("channel-id-list");
|
|
557
|
-
if (channelIdList) param.channelIdList = channelIdList.split(",").map(
|
|
786
|
+
if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
|
|
558
787
|
const startTime = ctx.str("start-time");
|
|
559
788
|
if (startTime) param.startTime = startTime;
|
|
560
789
|
const endTime = ctx.str("end-time");
|
|
@@ -572,17 +801,17 @@ var getLivestreamRoomMetrics = {
|
|
|
572
801
|
command: "+get_livestream_room_metrics",
|
|
573
802
|
description: "Core metrics and yearly calendar for one room: overview KPIs plus daily streamed-duration calendar.",
|
|
574
803
|
flags: [
|
|
575
|
-
{ name: "space-id", type: "
|
|
576
|
-
{ name: "game-id", type: "
|
|
577
|
-
{ name: "channel-id", type: "
|
|
804
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
805
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
806
|
+
{ name: "channel-id", type: "int64", required: true, min: 1, desc: "Channel ID from +get_livestream_rooms." },
|
|
578
807
|
{ name: "room-id", type: "string", required: true, desc: "Live room ID (roomId) from +get_livestream_rooms." },
|
|
579
808
|
{ name: "year", type: "string", required: false, desc: "Calendar year (yyyy)." }
|
|
580
809
|
],
|
|
581
810
|
risk: "read",
|
|
582
811
|
execute: async (ctx) => {
|
|
583
|
-
const spaceId = ctx.
|
|
584
|
-
const gameId = ctx.
|
|
585
|
-
const channelId = ctx.
|
|
812
|
+
const spaceId = ctx.int64("space-id");
|
|
813
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
814
|
+
const channelId = ctx.int64("channel-id");
|
|
586
815
|
const roomId = ctx.str("room-id");
|
|
587
816
|
const host = ctx.host();
|
|
588
817
|
const param = { gameId, channelId, roomId };
|
|
@@ -601,20 +830,20 @@ var getLivestreamList = {
|
|
|
601
830
|
command: "+get_livestream_list",
|
|
602
831
|
description: "List live sessions for a room in a time range (stream records).",
|
|
603
832
|
flags: [
|
|
604
|
-
{ name: "space-id", type: "
|
|
605
|
-
{ name: "game-id", type: "
|
|
606
|
-
{ name: "channel-id", type: "
|
|
833
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
834
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
835
|
+
{ name: "channel-id", type: "int64", required: false, min: 1, desc: "Channel ID from +get_livestream_rooms." },
|
|
607
836
|
{ name: "room-id", type: "string", required: false, desc: "Live room ID (roomId) from +get_livestream_rooms." },
|
|
608
837
|
{ name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
|
|
609
838
|
{ name: "end-time", type: "string", required: false, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
|
|
610
839
|
],
|
|
611
840
|
risk: "read",
|
|
612
841
|
execute: async (ctx) => {
|
|
613
|
-
const spaceId = ctx.
|
|
614
|
-
const gameId = ctx.
|
|
842
|
+
const spaceId = ctx.int64("space-id");
|
|
843
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
615
844
|
const host = ctx.host();
|
|
616
845
|
const param = { gameId };
|
|
617
|
-
const channelId = ctx.
|
|
846
|
+
const channelId = ctx.int64("channel-id");
|
|
618
847
|
if (channelId) param.channelId = channelId;
|
|
619
848
|
const roomId = ctx.str("room-id");
|
|
620
849
|
if (roomId) param.roomId = roomId;
|
|
@@ -635,8 +864,8 @@ var getLivestreamDetail = {
|
|
|
635
864
|
command: "+get_livestream_detail",
|
|
636
865
|
description: "One live session detail: interaction leaderboards and paginated interaction feed.",
|
|
637
866
|
flags: [
|
|
638
|
-
{ name: "space-id", type: "
|
|
639
|
-
{ name: "game-id", type: "
|
|
867
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
868
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
640
869
|
{ name: "stream-id", type: "string", required: true, desc: "Live session ID (streamId) from +get_livestream_list." },
|
|
641
870
|
{ name: "activity-types", type: "string", required: false, desc: "Activity type codes to filter details: 0 danmu, 1 gift, 2 superchat, 3 premium. Comma-separated." },
|
|
642
871
|
{ name: "anchor-time", type: "string", required: false, desc: "Anchor time for interactions. Format: yyyy-MM-dd HH:mm." },
|
|
@@ -647,8 +876,8 @@ var getLivestreamDetail = {
|
|
|
647
876
|
],
|
|
648
877
|
risk: "read",
|
|
649
878
|
execute: async (ctx) => {
|
|
650
|
-
const spaceId = ctx.
|
|
651
|
-
const gameId = ctx.
|
|
879
|
+
const spaceId = ctx.int64("space-id");
|
|
880
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
652
881
|
const streamId = ctx.str("stream-id");
|
|
653
882
|
const host = ctx.host();
|
|
654
883
|
const param = { gameId, streamId };
|
|
@@ -658,14 +887,14 @@ var getLivestreamDetail = {
|
|
|
658
887
|
if (anchorTime) param.anchorTime = anchorTime;
|
|
659
888
|
const searchWord = ctx.str("search-word");
|
|
660
889
|
if (searchWord) param.searchWord = searchWord;
|
|
661
|
-
const orderBy = ctx.
|
|
662
|
-
const pageNum = ctx.
|
|
663
|
-
const pageSize = ctx.
|
|
664
|
-
if (orderBy !== void 0 || pageNum || pageSize) {
|
|
890
|
+
const orderBy = ctx.optionalNum("order-by");
|
|
891
|
+
const pageNum = ctx.optionalNum("page-num");
|
|
892
|
+
const pageSize = ctx.optionalNum("page-size");
|
|
893
|
+
if (orderBy !== void 0 || pageNum !== void 0 || pageSize !== void 0) {
|
|
665
894
|
param.pagerHeader = {};
|
|
666
895
|
if (orderBy !== void 0) param.pagerHeader.orderBy = orderBy;
|
|
667
|
-
if (pageNum) param.pagerHeader.pageNum = pageNum;
|
|
668
|
-
if (pageSize) param.pagerHeader.pageSize = pageSize;
|
|
896
|
+
if (pageNum !== void 0) param.pagerHeader.pageNum = pageNum;
|
|
897
|
+
if (pageSize !== void 0) param.pagerHeader.pageSize = pageSize;
|
|
669
898
|
}
|
|
670
899
|
const args = { spaceId, param };
|
|
671
900
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
|
|
@@ -680,14 +909,14 @@ var getLivestreamAnalysis = {
|
|
|
680
909
|
command: "+get_livestream_analysis",
|
|
681
910
|
description: "AI-generated live session analysis report: highlight moments (time slices with metrics and AI insights) and sentiment opinions.",
|
|
682
911
|
flags: [
|
|
683
|
-
{ name: "space-id", type: "
|
|
684
|
-
{ name: "game-id", type: "
|
|
912
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
913
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
685
914
|
{ name: "stream-id", type: "string", required: true, desc: "Live session ID (streamId) from +get_livestream_list." }
|
|
686
915
|
],
|
|
687
916
|
risk: "read",
|
|
688
917
|
execute: async (ctx) => {
|
|
689
|
-
const spaceId = ctx.
|
|
690
|
-
const gameId = ctx.
|
|
918
|
+
const spaceId = ctx.int64("space-id");
|
|
919
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
691
920
|
const streamId = ctx.str("stream-id");
|
|
692
921
|
const host = ctx.host();
|
|
693
922
|
const param = { gameId, streamId };
|
|
@@ -704,18 +933,18 @@ var getCommentsSummary = {
|
|
|
704
933
|
command: "+get_comments_summary",
|
|
705
934
|
description: "Comment analytics summary for a post: sentiment mix and time trends. Aggregate stats only\u2014no raw comment list.",
|
|
706
935
|
flags: [
|
|
707
|
-
{ name: "space-id", type: "
|
|
708
|
-
{ name: "game-id", type: "
|
|
709
|
-
{ name: "channel-id", type: "
|
|
936
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
937
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
938
|
+
{ name: "channel-id", type: "int64", required: true, min: 1, desc: "Channel ID from search_posts results." },
|
|
710
939
|
{ name: "uuid", type: "string", required: true, desc: "Content UUID from search_posts results." },
|
|
711
940
|
{ name: "start-time", type: "string", required: false, desc: "Comment publish time lower bound; defaults to this post's publishTime from search_posts/get_post_detail." },
|
|
712
941
|
{ name: "end-time", type: "string", required: false, desc: "Comment publish time upper bound. Format: yyyy-MM-dd." }
|
|
713
942
|
],
|
|
714
943
|
risk: "read",
|
|
715
944
|
execute: async (ctx) => {
|
|
716
|
-
const spaceId = ctx.
|
|
717
|
-
const gameId = ctx.
|
|
718
|
-
const channelId = ctx.
|
|
945
|
+
const spaceId = ctx.int64("space-id");
|
|
946
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
947
|
+
const channelId = ctx.int64("channel-id");
|
|
719
948
|
const uuid = ctx.str("uuid");
|
|
720
949
|
const host = ctx.host();
|
|
721
950
|
const param = { gameId, channelId, uuid };
|
|
@@ -736,9 +965,9 @@ var getCommentTagAnalysis = {
|
|
|
736
965
|
command: "+get_comment_tag_analysis",
|
|
737
966
|
description: "Comment tag analysis: for a tagCode, counts and trends per tag value over time.",
|
|
738
967
|
flags: [
|
|
739
|
-
{ name: "space-id", type: "
|
|
740
|
-
{ name: "game-id", type: "
|
|
741
|
-
{ name: "channel-id", type: "
|
|
968
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
969
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
970
|
+
{ name: "channel-id", type: "int64", required: true, min: 1, desc: "Channel ID from search_posts results." },
|
|
742
971
|
{ name: "uuid", type: "string", required: true, desc: "Content UUID from search_posts results." },
|
|
743
972
|
{ name: "resource-type", type: "number", required: true, desc: "Resource type: 0 post, 1 video." },
|
|
744
973
|
{ name: "tag-code", type: "string", required: true, desc: "Tag code (tagCode) from +get_corpus_tags." },
|
|
@@ -747,9 +976,9 @@ var getCommentTagAnalysis = {
|
|
|
747
976
|
],
|
|
748
977
|
risk: "read",
|
|
749
978
|
execute: async (ctx) => {
|
|
750
|
-
const spaceId = ctx.
|
|
751
|
-
const gameId = ctx.
|
|
752
|
-
const channelId = ctx.
|
|
979
|
+
const spaceId = ctx.int64("space-id");
|
|
980
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
981
|
+
const channelId = ctx.int64("channel-id");
|
|
753
982
|
const uuid = ctx.str("uuid");
|
|
754
983
|
const resourceType = ctx.num("resource-type");
|
|
755
984
|
const tagCode = ctx.str("tag-code");
|
|
@@ -772,13 +1001,13 @@ var getCorpusTags = {
|
|
|
772
1001
|
command: "+get_corpus_tags",
|
|
773
1002
|
description: "List corpus tags (tagId, tagCode, tagName, inferenceType) to pick tagCode for filters.",
|
|
774
1003
|
flags: [
|
|
775
|
-
{ name: "space-id", type: "
|
|
776
|
-
{ name: "game-id", type: "
|
|
1004
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
1005
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." }
|
|
777
1006
|
],
|
|
778
1007
|
risk: "read",
|
|
779
1008
|
execute: async (ctx) => {
|
|
780
|
-
const spaceId = ctx.
|
|
781
|
-
const gameId = ctx.
|
|
1009
|
+
const spaceId = ctx.int64("space-id");
|
|
1010
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
782
1011
|
const host = ctx.host();
|
|
783
1012
|
const param = { gameId };
|
|
784
1013
|
const args = { spaceId, param };
|
|
@@ -794,8 +1023,8 @@ var getRiskContent = {
|
|
|
794
1023
|
command: "+get_risk_content",
|
|
795
1024
|
description: "List content flagged as risk/moderation items; filter by risk type and time.",
|
|
796
1025
|
flags: [
|
|
797
|
-
{ name: "space-id", type: "
|
|
798
|
-
{ name: "game-id", type: "
|
|
1026
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID. Discover it with: ae-cli community spaces list" },
|
|
1027
|
+
{ name: "game-id", type: "int64", required: false, min: 1, desc: "Deprecated compatibility alias; defaults to --space-id and must match it." },
|
|
799
1028
|
{ name: "start-time", type: "string", required: true, desc: "Risk content publish time lower bound. Format: yyyy-MM-dd." },
|
|
800
1029
|
{ name: "end-time", type: "string", required: true, desc: "Risk content publish time upper bound. Format: yyyy-MM-dd." },
|
|
801
1030
|
{ name: "risk-codes", type: "string", required: false, desc: "Risk type code list." },
|
|
@@ -807,26 +1036,26 @@ var getRiskContent = {
|
|
|
807
1036
|
],
|
|
808
1037
|
risk: "read",
|
|
809
1038
|
execute: async (ctx) => {
|
|
810
|
-
const spaceId = ctx.
|
|
811
|
-
const gameId = ctx.
|
|
1039
|
+
const spaceId = ctx.int64("space-id");
|
|
1040
|
+
const gameId = ctx.optionalInt64("game-id") ?? spaceId;
|
|
812
1041
|
const startTime = ctx.str("start-time");
|
|
813
1042
|
const endTime = ctx.str("end-time");
|
|
814
1043
|
const host = ctx.host();
|
|
815
1044
|
const param = { gameId, startTime, endTime };
|
|
816
1045
|
const riskCodes = ctx.str("risk-codes");
|
|
817
|
-
if (riskCodes) param.riskCodes = riskCodes.split(",").map(
|
|
1046
|
+
if (riskCodes) param.riskCodes = riskCodes.split(",").map((value) => BigInt(value.trim()));
|
|
818
1047
|
const searchWord = ctx.str("search-word");
|
|
819
1048
|
if (searchWord) param.searchWord = searchWord;
|
|
820
|
-
const includeTrends = ctx.
|
|
1049
|
+
const includeTrends = ctx.optionalBool("include-trends");
|
|
821
1050
|
if (includeTrends !== void 0) param.includeTrends = includeTrends;
|
|
822
|
-
const orderBy = ctx.
|
|
823
|
-
const pageNum = ctx.
|
|
824
|
-
const pageSize = ctx.
|
|
825
|
-
if (orderBy !== void 0 || pageNum || pageSize) {
|
|
1051
|
+
const orderBy = ctx.optionalNum("order-by");
|
|
1052
|
+
const pageNum = ctx.optionalNum("page-num");
|
|
1053
|
+
const pageSize = ctx.optionalNum("page-size");
|
|
1054
|
+
if (orderBy !== void 0 || pageNum !== void 0 || pageSize !== void 0) {
|
|
826
1055
|
param.pagerHeader = {};
|
|
827
1056
|
if (orderBy !== void 0) param.pagerHeader.orderBy = orderBy;
|
|
828
|
-
if (pageNum) param.pagerHeader.pageNum = pageNum;
|
|
829
|
-
if (pageSize) param.pagerHeader.pageSize = pageSize;
|
|
1057
|
+
if (pageNum !== void 0) param.pagerHeader.pageNum = pageNum;
|
|
1058
|
+
if (pageSize !== void 0) param.pagerHeader.pageSize = pageSize;
|
|
830
1059
|
}
|
|
831
1060
|
const args = { spaceId, param };
|
|
832
1061
|
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
|
|
@@ -927,36 +1156,36 @@ var StatsCollector = class {
|
|
|
927
1156
|
convertedIntegerFields: 0,
|
|
928
1157
|
fields: {}
|
|
929
1158
|
};
|
|
930
|
-
truncated(
|
|
1159
|
+
truncated(field2) {
|
|
931
1160
|
this.value.truncatedFields += 1;
|
|
932
|
-
this.increment(
|
|
1161
|
+
this.increment(field2);
|
|
933
1162
|
}
|
|
934
|
-
defaulted(
|
|
1163
|
+
defaulted(field2) {
|
|
935
1164
|
this.value.defaultedFields += 1;
|
|
936
|
-
this.increment(
|
|
1165
|
+
this.increment(field2);
|
|
937
1166
|
}
|
|
938
|
-
convertedInteger(
|
|
1167
|
+
convertedInteger(field2) {
|
|
939
1168
|
this.value.convertedIntegerFields += 1;
|
|
940
|
-
this.increment(
|
|
1169
|
+
this.increment(field2);
|
|
941
1170
|
}
|
|
942
|
-
increment(
|
|
943
|
-
this.value.fields[
|
|
1171
|
+
increment(field2) {
|
|
1172
|
+
this.value.fields[field2] = (this.value.fields[field2] ?? 0) + 1;
|
|
944
1173
|
}
|
|
945
1174
|
};
|
|
946
|
-
function
|
|
1175
|
+
function validationError2(code, message, location = {}) {
|
|
947
1176
|
throw new CommunityDataValidationError(code, message, location);
|
|
948
1177
|
}
|
|
949
1178
|
function isObject(value) {
|
|
950
1179
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
951
1180
|
}
|
|
952
|
-
function hasOwn(object,
|
|
953
|
-
return Object.prototype.hasOwnProperty.call(object,
|
|
1181
|
+
function hasOwn(object, field2) {
|
|
1182
|
+
return Object.prototype.hasOwnProperty.call(object, field2);
|
|
954
1183
|
}
|
|
955
|
-
function fieldLocation(context,
|
|
956
|
-
return { ...context.location, field };
|
|
1184
|
+
function fieldLocation(context, field2) {
|
|
1185
|
+
return { ...context.location, field: field2 };
|
|
957
1186
|
}
|
|
958
|
-
function statField(context,
|
|
959
|
-
return `${context.type}.${
|
|
1187
|
+
function statField(context, field2) {
|
|
1188
|
+
return `${context.type}.${field2}`;
|
|
960
1189
|
}
|
|
961
1190
|
function parseInteger(value, location, options = {}) {
|
|
962
1191
|
let integer;
|
|
@@ -965,7 +1194,7 @@ function parseInteger(value, location, options = {}) {
|
|
|
965
1194
|
integer = value;
|
|
966
1195
|
} else if (typeof value === "number") {
|
|
967
1196
|
if (!Number.isSafeInteger(value)) {
|
|
968
|
-
|
|
1197
|
+
validationError2(
|
|
969
1198
|
"community_invalid_integer",
|
|
970
1199
|
"The field must be a lossless integer number or a canonical decimal string.",
|
|
971
1200
|
location
|
|
@@ -974,7 +1203,7 @@ function parseInteger(value, location, options = {}) {
|
|
|
974
1203
|
integer = BigInt(value);
|
|
975
1204
|
} else if (typeof value === "string") {
|
|
976
1205
|
if (!CANONICAL_INTEGER.test(value) || value === "-0") {
|
|
977
|
-
|
|
1206
|
+
validationError2(
|
|
978
1207
|
"community_invalid_integer",
|
|
979
1208
|
"The field must be a lossless integer number or a canonical decimal string.",
|
|
980
1209
|
location
|
|
@@ -983,7 +1212,7 @@ function parseInteger(value, location, options = {}) {
|
|
|
983
1212
|
integer = BigInt(value);
|
|
984
1213
|
converted = true;
|
|
985
1214
|
} else {
|
|
986
|
-
|
|
1215
|
+
validationError2(
|
|
987
1216
|
"community_invalid_integer",
|
|
988
1217
|
"The field must be a lossless integer number or a canonical decimal string.",
|
|
989
1218
|
location
|
|
@@ -992,49 +1221,49 @@ function parseInteger(value, location, options = {}) {
|
|
|
992
1221
|
const minimum = options.min ?? INT64_MIN;
|
|
993
1222
|
const maximum = options.max ?? INT64_MAX;
|
|
994
1223
|
if (integer < minimum || integer > maximum) {
|
|
995
|
-
|
|
1224
|
+
validationError2("community_integer_out_of_range", "The field is outside its supported integer range.", location);
|
|
996
1225
|
}
|
|
997
1226
|
if (options.positive && integer <= 0n) {
|
|
998
|
-
|
|
1227
|
+
validationError2("community_integer_out_of_range", "The field must be a positive integer.", location);
|
|
999
1228
|
}
|
|
1000
1229
|
if (options.nonnegative && integer < 0n) {
|
|
1001
|
-
|
|
1230
|
+
validationError2("community_integer_out_of_range", "The field must be a nonnegative integer.", location);
|
|
1002
1231
|
}
|
|
1003
1232
|
return { value: integer, converted };
|
|
1004
1233
|
}
|
|
1005
|
-
function parsePositiveId(value,
|
|
1006
|
-
return parseInteger(value, { field }, { positive: true }).value;
|
|
1234
|
+
function parsePositiveId(value, field2) {
|
|
1235
|
+
return parseInteger(value, { field: field2 }, { positive: true }).value;
|
|
1007
1236
|
}
|
|
1008
|
-
function normalizeIntegerField(input, output,
|
|
1009
|
-
if (!hasOwn(input,
|
|
1237
|
+
function normalizeIntegerField(input, output, field2, context, options = {}) {
|
|
1238
|
+
if (!hasOwn(input, field2) || input[field2] === null) {
|
|
1010
1239
|
if (options.required) {
|
|
1011
|
-
|
|
1240
|
+
validationError2("community_required_field", "A required field is missing.", fieldLocation(context, field2));
|
|
1012
1241
|
}
|
|
1013
|
-
delete output[
|
|
1242
|
+
delete output[field2];
|
|
1014
1243
|
return void 0;
|
|
1015
1244
|
}
|
|
1016
|
-
const parsed = parseInteger(input[
|
|
1017
|
-
output[
|
|
1245
|
+
const parsed = parseInteger(input[field2], fieldLocation(context, field2), options);
|
|
1246
|
+
output[field2] = parsed.value;
|
|
1018
1247
|
if (parsed.converted) {
|
|
1019
|
-
context.stats.convertedInteger(statField(context,
|
|
1248
|
+
context.stats.convertedInteger(statField(context, field2));
|
|
1020
1249
|
}
|
|
1021
1250
|
return parsed.value;
|
|
1022
1251
|
}
|
|
1023
|
-
function normalizeSmallIntegerField(input, output,
|
|
1024
|
-
const integer = normalizeIntegerField(input, output,
|
|
1252
|
+
function normalizeSmallIntegerField(input, output, field2, context, options = {}) {
|
|
1253
|
+
const integer = normalizeIntegerField(input, output, field2, context, options);
|
|
1025
1254
|
if (integer === void 0) return void 0;
|
|
1026
1255
|
const result = Number(integer);
|
|
1027
|
-
output[
|
|
1256
|
+
output[field2] = result;
|
|
1028
1257
|
return result;
|
|
1029
1258
|
}
|
|
1030
|
-
function
|
|
1259
|
+
function parseDateTime2(value, location, requireTime = false) {
|
|
1031
1260
|
const match = /^(\d{4})-(\d{2})-(\d{2})(?: (\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?)?$/.exec(value);
|
|
1032
1261
|
if (!match) {
|
|
1033
|
-
|
|
1262
|
+
validationError2("community_invalid_datetime", "The field must use a supported Iris date-time format.", location);
|
|
1034
1263
|
}
|
|
1035
1264
|
const hasTime = match[4] !== void 0;
|
|
1036
1265
|
if (requireTime && !hasTime) {
|
|
1037
|
-
|
|
1266
|
+
validationError2("community_invalid_datetime", "The field must include a time component.", location);
|
|
1038
1267
|
}
|
|
1039
1268
|
const parts = {
|
|
1040
1269
|
year: Number(match[1]),
|
|
@@ -1047,33 +1276,33 @@ function parseDateTime(value, location, requireTime = false) {
|
|
|
1047
1276
|
hasTime
|
|
1048
1277
|
};
|
|
1049
1278
|
if (parts.year === 0 || parts.month < 1 || parts.month > 12 || parts.hour > 23 || parts.minute > 59 || parts.second > 59) {
|
|
1050
|
-
|
|
1279
|
+
validationError2("community_invalid_datetime", "The field must use a supported Iris date-time format.", location);
|
|
1051
1280
|
}
|
|
1052
1281
|
const calendarCheck = /* @__PURE__ */ new Date(0);
|
|
1053
1282
|
calendarCheck.setUTCFullYear(parts.year, parts.month - 1, parts.day);
|
|
1054
1283
|
calendarCheck.setUTCHours(parts.hour, parts.minute, parts.second, parts.millisecond);
|
|
1055
1284
|
if (calendarCheck.getUTCFullYear() !== parts.year || calendarCheck.getUTCMonth() !== parts.month - 1 || calendarCheck.getUTCDate() !== parts.day || calendarCheck.getUTCHours() !== parts.hour || calendarCheck.getUTCMinutes() !== parts.minute || calendarCheck.getUTCSeconds() !== parts.second || calendarCheck.getUTCMilliseconds() !== parts.millisecond) {
|
|
1056
|
-
|
|
1285
|
+
validationError2("community_invalid_datetime", "The field must use a supported Iris date-time format.", location);
|
|
1057
1286
|
}
|
|
1058
1287
|
return parts;
|
|
1059
1288
|
}
|
|
1060
|
-
function normalizeTextField(input, output,
|
|
1061
|
-
const path = options.path ??
|
|
1062
|
-
if (!hasOwn(input,
|
|
1289
|
+
function normalizeTextField(input, output, field2, context, options = {}) {
|
|
1290
|
+
const path = options.path ?? field2;
|
|
1291
|
+
if (!hasOwn(input, field2) || input[field2] === null) {
|
|
1063
1292
|
if (options.required) {
|
|
1064
|
-
|
|
1293
|
+
validationError2("community_required_field", "A required field is missing.", fieldLocation(context, path));
|
|
1065
1294
|
}
|
|
1066
|
-
delete output[
|
|
1295
|
+
delete output[field2];
|
|
1067
1296
|
return void 0;
|
|
1068
1297
|
}
|
|
1069
|
-
const value = input[
|
|
1298
|
+
const value = input[field2];
|
|
1070
1299
|
if (typeof value !== "string") {
|
|
1071
|
-
|
|
1300
|
+
validationError2("community_invalid_text", "The field must be a JSON string.", fieldLocation(context, path));
|
|
1072
1301
|
}
|
|
1073
1302
|
let normalized = value;
|
|
1074
1303
|
if (options.maxLength !== void 0 && normalized.length > options.maxLength) {
|
|
1075
1304
|
if (!options.truncate) {
|
|
1076
|
-
|
|
1305
|
+
validationError2(
|
|
1077
1306
|
"community_text_too_long",
|
|
1078
1307
|
`The field must not exceed ${options.maxLength} UTF-16 code units.`,
|
|
1079
1308
|
fieldLocation(context, path)
|
|
@@ -1083,9 +1312,9 @@ function normalizeTextField(input, output, field, context, options = {}) {
|
|
|
1083
1312
|
context.stats.truncated(statField(context, path));
|
|
1084
1313
|
}
|
|
1085
1314
|
if (options.dateTime) {
|
|
1086
|
-
|
|
1315
|
+
parseDateTime2(normalized, fieldLocation(context, path), options.requireTime);
|
|
1087
1316
|
}
|
|
1088
|
-
output[
|
|
1317
|
+
output[field2] = normalized;
|
|
1089
1318
|
return normalized;
|
|
1090
1319
|
}
|
|
1091
1320
|
function parseEncodedObject(value) {
|
|
@@ -1098,21 +1327,21 @@ function parseEncodedObject(value) {
|
|
|
1098
1327
|
return void 0;
|
|
1099
1328
|
}
|
|
1100
1329
|
}
|
|
1101
|
-
function normalizeFallbackObjectField(input, output,
|
|
1102
|
-
const object = hasOwn(input,
|
|
1330
|
+
function normalizeFallbackObjectField(input, output, field2, context) {
|
|
1331
|
+
const object = hasOwn(input, field2) && input[field2] !== null ? parseEncodedObject(input[field2]) : void 0;
|
|
1103
1332
|
if (object === void 0) {
|
|
1104
1333
|
const fallback = {};
|
|
1105
|
-
output[
|
|
1106
|
-
context.stats.defaulted(statField(context,
|
|
1334
|
+
output[field2] = fallback;
|
|
1335
|
+
context.stats.defaulted(statField(context, field2));
|
|
1107
1336
|
return fallback;
|
|
1108
1337
|
}
|
|
1109
|
-
output[
|
|
1338
|
+
output[field2] = object;
|
|
1110
1339
|
return object;
|
|
1111
1340
|
}
|
|
1112
|
-
function normalizeRequiredObjectValue(value, context,
|
|
1341
|
+
function normalizeRequiredObjectValue(value, context, field2) {
|
|
1113
1342
|
const object = parseEncodedObject(value);
|
|
1114
1343
|
if (object === void 0) {
|
|
1115
|
-
|
|
1344
|
+
validationError2("community_invalid_object", "The field must be a JSON object.", fieldLocation(context, field2));
|
|
1116
1345
|
}
|
|
1117
1346
|
return object;
|
|
1118
1347
|
}
|
|
@@ -1126,11 +1355,11 @@ function normalizeSubtitle(input, output, context) {
|
|
|
1126
1355
|
try {
|
|
1127
1356
|
value = parseCommunityJson(value);
|
|
1128
1357
|
} catch {
|
|
1129
|
-
|
|
1358
|
+
validationError2("community_invalid_array", "The field must be an array of JSON objects.", fieldLocation(context, "subtitle"));
|
|
1130
1359
|
}
|
|
1131
1360
|
}
|
|
1132
1361
|
if (!Array.isArray(value) || value.some((element) => !isObject(element))) {
|
|
1133
|
-
|
|
1362
|
+
validationError2("community_invalid_array", "The field must be an array of JSON objects.", fieldLocation(context, "subtitle"));
|
|
1134
1363
|
}
|
|
1135
1364
|
output.subtitle = value;
|
|
1136
1365
|
}
|
|
@@ -1143,23 +1372,23 @@ function normalizeMetrics(value, contentType, context, fieldPrefix) {
|
|
|
1143
1372
|
const metrics = normalizeRequiredObjectValue(value, context, fieldPrefix);
|
|
1144
1373
|
const names = Object.keys(metrics);
|
|
1145
1374
|
if (names.length === 0) {
|
|
1146
|
-
|
|
1375
|
+
validationError2("community_empty_metrics", "The metrics object must not be empty.", fieldLocation(context, fieldPrefix));
|
|
1147
1376
|
}
|
|
1148
1377
|
const allowed = metricNamesForContentType(contentType);
|
|
1149
1378
|
const normalized = { ...metrics };
|
|
1150
1379
|
for (const name of names) {
|
|
1151
|
-
const
|
|
1380
|
+
const field2 = `${fieldPrefix}.${name}`;
|
|
1152
1381
|
if (!allowed.has(name)) {
|
|
1153
|
-
|
|
1382
|
+
validationError2(
|
|
1154
1383
|
"community_invalid_metric",
|
|
1155
1384
|
"The metric name is not allowed for the selected content type.",
|
|
1156
|
-
fieldLocation(context,
|
|
1385
|
+
fieldLocation(context, field2)
|
|
1157
1386
|
);
|
|
1158
1387
|
}
|
|
1159
|
-
const parsed = parseInteger(metrics[name], fieldLocation(context,
|
|
1388
|
+
const parsed = parseInteger(metrics[name], fieldLocation(context, field2), { nonnegative: true });
|
|
1160
1389
|
normalized[name] = parsed.value;
|
|
1161
1390
|
if (parsed.converted) {
|
|
1162
|
-
context.stats.convertedInteger(statField(context,
|
|
1391
|
+
context.stats.convertedInteger(statField(context, field2));
|
|
1163
1392
|
}
|
|
1164
1393
|
}
|
|
1165
1394
|
return normalized;
|
|
@@ -1177,7 +1406,7 @@ function normalizeInteractionSidecar(input, output, context, contentType) {
|
|
|
1177
1406
|
path: "interaction.collect_time"
|
|
1178
1407
|
});
|
|
1179
1408
|
if (!hasOwn(interaction, "metrics") || interaction.metrics === null) {
|
|
1180
|
-
|
|
1409
|
+
validationError2("community_required_field", "A required field is missing.", fieldLocation(context, "interaction.metrics"));
|
|
1181
1410
|
}
|
|
1182
1411
|
normalized.metrics = normalizeMetrics(interaction.metrics, contentType, context, "interaction.metrics");
|
|
1183
1412
|
output.interaction = normalized;
|
|
@@ -1211,7 +1440,7 @@ function normalizeRootFields(input, output, context) {
|
|
|
1211
1440
|
normalizeTextField(input, output, "root_id", context, { required: true, maxLength: 32, truncate: true });
|
|
1212
1441
|
const rootType = normalizeTextField(input, output, "root_type", context, { required: true });
|
|
1213
1442
|
if (!ROOT_TYPES.has(rootType)) {
|
|
1214
|
-
|
|
1443
|
+
validationError2("community_invalid_enum", "The field contains an unsupported enum value.", fieldLocation(context, "root_type"));
|
|
1215
1444
|
}
|
|
1216
1445
|
}
|
|
1217
1446
|
function normalizeReply(input, context) {
|
|
@@ -1271,11 +1500,11 @@ function zonedDateTimeToEpochMilliseconds(parts, zoneId) {
|
|
|
1271
1500
|
return estimate;
|
|
1272
1501
|
}
|
|
1273
1502
|
function validateStreamId(roomId, streamStartTime, context) {
|
|
1274
|
-
const parts =
|
|
1503
|
+
const parts = parseDateTime2(streamStartTime, fieldLocation(context, "stream_start_time"), true);
|
|
1275
1504
|
const timestamp = zonedDateTimeToEpochMilliseconds(parts, context.zoneId);
|
|
1276
1505
|
const streamId = `${context.channelId}_${roomId}_${timestamp}`;
|
|
1277
1506
|
if (streamId.length > 64) {
|
|
1278
|
-
|
|
1507
|
+
validationError2(
|
|
1279
1508
|
"community_derived_id_too_long",
|
|
1280
1509
|
"The derived stream identifier exceeds its supported length.",
|
|
1281
1510
|
fieldLocation(context, "stream_start_time")
|
|
@@ -1313,9 +1542,9 @@ function normalizeLiveRoom(input, context) {
|
|
|
1313
1542
|
for (const metric of ["online", "heat", "noble_count", "guardian_count", "diamond_fan_count", "dfans_count"]) {
|
|
1314
1543
|
normalizeIntegerField(input, output, metric, context, { nonnegative: true });
|
|
1315
1544
|
}
|
|
1316
|
-
const guardianAliases = ["guardian_count", "diamond_fan_count", "dfans_count"].filter((
|
|
1545
|
+
const guardianAliases = ["guardian_count", "diamond_fan_count", "dfans_count"].filter((field2) => hasOwn(input, field2) && input[field2] !== null);
|
|
1317
1546
|
if (guardianAliases.length > 1) {
|
|
1318
|
-
|
|
1547
|
+
validationError2(
|
|
1319
1548
|
"community_conflicting_fields",
|
|
1320
1549
|
"Only one guardian metric alias may be supplied.",
|
|
1321
1550
|
fieldLocation(context, guardianAliases[1])
|
|
@@ -1334,16 +1563,16 @@ function normalizeLiveRoom(input, context) {
|
|
|
1334
1563
|
"diamond_fan_count",
|
|
1335
1564
|
"dfans_count"
|
|
1336
1565
|
];
|
|
1337
|
-
const hasStreamDetails = streamDependentFields.some((
|
|
1566
|
+
const hasStreamDetails = streamDependentFields.some((field2) => hasOwn(input, field2) && input[field2] !== null);
|
|
1338
1567
|
if (hasStreamDetails && streamStartTime === void 0) {
|
|
1339
|
-
|
|
1568
|
+
validationError2(
|
|
1340
1569
|
"community_required_field",
|
|
1341
1570
|
"A stream start time is required when stream details or metrics are supplied.",
|
|
1342
1571
|
fieldLocation(context, "stream_start_time")
|
|
1343
1572
|
);
|
|
1344
1573
|
}
|
|
1345
1574
|
if (uuid * 5n + 4n > INT64_MAX) {
|
|
1346
|
-
|
|
1575
|
+
validationError2(
|
|
1347
1576
|
"community_derived_id_overflow",
|
|
1348
1577
|
"A derived live metric identifier would exceed signed int64.",
|
|
1349
1578
|
fieldLocation(context, "uuid")
|
|
@@ -1359,14 +1588,14 @@ function normalizeLiveInteraction(input, context) {
|
|
|
1359
1588
|
normalizeIntegerField(input, output, "uuid", context, { required: true, nonnegative: true });
|
|
1360
1589
|
const activityType = normalizeTextField(input, output, "activity_type", context, { required: true });
|
|
1361
1590
|
if (!ACTIVITY_TYPES.has(activityType)) {
|
|
1362
|
-
|
|
1591
|
+
validationError2("community_invalid_enum", "The field contains an unsupported enum value.", fieldLocation(context, "activity_type"));
|
|
1363
1592
|
}
|
|
1364
1593
|
normalizeTextField(input, output, "activity_content", context, { required: true, maxLength: 1024, truncate: true });
|
|
1365
1594
|
normalizeTextField(input, output, "user_id", context, { maxLength: 80, truncate: true });
|
|
1366
1595
|
normalizeTextField(input, output, "user_name", context, { maxLength: 80, truncate: true });
|
|
1367
1596
|
const userExtra = normalizeFallbackObjectField(input, output, "user_extra", context);
|
|
1368
1597
|
if (stringifyCommunityJson(userExtra).length > 1024) {
|
|
1369
|
-
|
|
1598
|
+
validationError2(
|
|
1370
1599
|
"community_object_too_long",
|
|
1371
1600
|
"The compact user_extra object must not exceed 1024 UTF-16 code units.",
|
|
1372
1601
|
fieldLocation(context, "user_extra")
|
|
@@ -1407,14 +1636,14 @@ function normalizeInteraction(input, context) {
|
|
|
1407
1636
|
});
|
|
1408
1637
|
normalizeTextField(input, output, "collect_time", context, { required: true, dateTime: true });
|
|
1409
1638
|
if (!hasOwn(input, "metrics") || input.metrics === null) {
|
|
1410
|
-
|
|
1639
|
+
validationError2("community_required_field", "A required field is missing.", fieldLocation(context, "metrics"));
|
|
1411
1640
|
}
|
|
1412
1641
|
output.metrics = normalizeMetrics(input.metrics, contentType, context, "metrics");
|
|
1413
1642
|
return output;
|
|
1414
1643
|
}
|
|
1415
1644
|
function normalizeRecord(input, context) {
|
|
1416
1645
|
if (!isObject(input)) {
|
|
1417
|
-
|
|
1646
|
+
validationError2("community_invalid_record", "Each data record must be a JSON object.", context.location);
|
|
1418
1647
|
}
|
|
1419
1648
|
switch (context.type) {
|
|
1420
1649
|
case "post":
|
|
@@ -1437,7 +1666,7 @@ function normalizeRecord(input, context) {
|
|
|
1437
1666
|
}
|
|
1438
1667
|
function parseDataType(value, segment) {
|
|
1439
1668
|
if (typeof value !== "string" || !ALL_DATA_TYPES.has(value)) {
|
|
1440
|
-
|
|
1669
|
+
validationError2(
|
|
1441
1670
|
"community_invalid_data_type",
|
|
1442
1671
|
"The segment data_type must be one of the eight supported community data types.",
|
|
1443
1672
|
{ segment, field: "data_type" }
|
|
@@ -1447,20 +1676,20 @@ function parseDataType(value, segment) {
|
|
|
1447
1676
|
}
|
|
1448
1677
|
function normalizeSegment(input, segment, channelId, zoneId, stats) {
|
|
1449
1678
|
if (!isObject(input)) {
|
|
1450
|
-
|
|
1679
|
+
validationError2("community_invalid_segment", "Each payload segment must be a JSON object.", { segment });
|
|
1451
1680
|
}
|
|
1452
1681
|
if (!hasOwn(input, "data_type")) {
|
|
1453
|
-
|
|
1682
|
+
validationError2("community_required_field", "A required field is missing.", { segment, field: "data_type" });
|
|
1454
1683
|
}
|
|
1455
1684
|
if (!hasOwn(input, "data") || input.data === null) {
|
|
1456
|
-
|
|
1685
|
+
validationError2("community_required_field", "A required field is missing.", { segment, field: "data" });
|
|
1457
1686
|
}
|
|
1458
1687
|
const dataType = parseDataType(input.data_type, segment);
|
|
1459
1688
|
const records = Array.isArray(input.data) ? input.data : [input.data];
|
|
1460
1689
|
if (records.length === 0) {
|
|
1461
|
-
|
|
1690
|
+
validationError2("community_empty_data", "A segment data array must not be empty.", { segment, field: "data" });
|
|
1462
1691
|
}
|
|
1463
|
-
const normalized = records.map((
|
|
1692
|
+
const normalized = records.map((record2, index) => normalizeRecord(record2, {
|
|
1464
1693
|
type: dataType,
|
|
1465
1694
|
channelId,
|
|
1466
1695
|
zoneId,
|
|
@@ -1471,12 +1700,12 @@ function normalizeSegment(input, segment, channelId, zoneId, stats) {
|
|
|
1471
1700
|
}
|
|
1472
1701
|
function validateZoneId(value) {
|
|
1473
1702
|
if (typeof value !== "string" || value.length === 0) {
|
|
1474
|
-
|
|
1703
|
+
validationError2("community_invalid_zone_id", "zone_id must be a valid IANA time zone name.", { field: "zone_id" });
|
|
1475
1704
|
}
|
|
1476
1705
|
try {
|
|
1477
1706
|
new Intl.DateTimeFormat("en-US", { timeZone: value }).format(0);
|
|
1478
1707
|
} catch {
|
|
1479
|
-
|
|
1708
|
+
validationError2("community_invalid_zone_id", "zone_id must be a valid IANA time zone name.", { field: "zone_id" });
|
|
1480
1709
|
}
|
|
1481
1710
|
return value;
|
|
1482
1711
|
}
|
|
@@ -1488,7 +1717,7 @@ function normalizeCommunityReportInput(input) {
|
|
|
1488
1717
|
const hasDataMode = input.dataType !== void 0 || input.data !== void 0;
|
|
1489
1718
|
const hasPayloadMode = input.payload !== void 0;
|
|
1490
1719
|
if (hasDataMode === hasPayloadMode) {
|
|
1491
|
-
|
|
1720
|
+
validationError2(
|
|
1492
1721
|
"community_input_mode",
|
|
1493
1722
|
"Use exactly one input mode: data_type with data, or payload.",
|
|
1494
1723
|
{ field: "data/payload" }
|
|
@@ -1497,7 +1726,7 @@ function normalizeCommunityReportInput(input) {
|
|
|
1497
1726
|
let rawSegments;
|
|
1498
1727
|
if (hasDataMode) {
|
|
1499
1728
|
if (input.dataType === void 0 || input.data === void 0) {
|
|
1500
|
-
|
|
1729
|
+
validationError2(
|
|
1501
1730
|
"community_input_mode",
|
|
1502
1731
|
"The data_type and data fields must be supplied together.",
|
|
1503
1732
|
{ field: input.dataType === void 0 ? "data_type" : "data" }
|
|
@@ -1507,7 +1736,7 @@ function normalizeCommunityReportInput(input) {
|
|
|
1507
1736
|
} else {
|
|
1508
1737
|
rawSegments = Array.isArray(input.payload) ? input.payload : [input.payload];
|
|
1509
1738
|
if (rawSegments.length === 0) {
|
|
1510
|
-
|
|
1739
|
+
validationError2("community_empty_payload", "The payload array must not be empty.", { field: "payload" });
|
|
1511
1740
|
}
|
|
1512
1741
|
}
|
|
1513
1742
|
const stats = new StatsCollector();
|
|
@@ -1684,7 +1913,7 @@ function resolveCommunityReportEndpoint(flagValue, environment = process.env) {
|
|
|
1684
1913
|
}
|
|
1685
1914
|
return endpoint.toString();
|
|
1686
1915
|
}
|
|
1687
|
-
function readCommunityReportInput(raw,
|
|
1916
|
+
function readCommunityReportInput(raw, field2) {
|
|
1688
1917
|
const trimmed = raw.trim();
|
|
1689
1918
|
let text;
|
|
1690
1919
|
try {
|
|
@@ -1702,8 +1931,8 @@ function readCommunityReportInput(raw, field) {
|
|
|
1702
1931
|
"Unable to read the community JSON input.",
|
|
1703
1932
|
{
|
|
1704
1933
|
code: "community_input_read_failed",
|
|
1705
|
-
hint: `Pass --${
|
|
1706
|
-
location: { field }
|
|
1934
|
+
hint: `Pass --${field2} as inline JSON, an existing path, @path, or - for stdin.`,
|
|
1935
|
+
location: { field: field2 }
|
|
1707
1936
|
}
|
|
1708
1937
|
);
|
|
1709
1938
|
}
|
|
@@ -1716,7 +1945,7 @@ function readCommunityReportInput(raw, field) {
|
|
|
1716
1945
|
{
|
|
1717
1946
|
code: error.code,
|
|
1718
1947
|
hint: SCHEMA_VALIDATION_HINT,
|
|
1719
|
-
location: { field }
|
|
1948
|
+
location: { field: field2 }
|
|
1720
1949
|
}
|
|
1721
1950
|
);
|
|
1722
1951
|
}
|
|
@@ -1799,6 +2028,258 @@ function formatNormalization(stats) {
|
|
|
1799
2028
|
};
|
|
1800
2029
|
}
|
|
1801
2030
|
|
|
2031
|
+
// src/commands/te-community/spaces-list.ts
|
|
2032
|
+
var spacesList = createCapabilityCommand({
|
|
2033
|
+
cliService: "community",
|
|
2034
|
+
resource: "spaces",
|
|
2035
|
+
command: "list",
|
|
2036
|
+
capabilityId: "community.space.list",
|
|
2037
|
+
description: "List community spaces available to the current user.",
|
|
2038
|
+
flags: [],
|
|
2039
|
+
risk: "read",
|
|
2040
|
+
buildInput: () => ({})
|
|
2041
|
+
});
|
|
2042
|
+
var communitySpacesList = {
|
|
2043
|
+
...spacesList,
|
|
2044
|
+
async execute(ctx) {
|
|
2045
|
+
const result = await spacesList.execute(ctx);
|
|
2046
|
+
const data = unwrapOutputData(result);
|
|
2047
|
+
return Array.isArray(data) ? withOutputMetadata(result, { returned_count: data.length }) : result;
|
|
2048
|
+
}
|
|
2049
|
+
};
|
|
2050
|
+
|
|
2051
|
+
// src/commands/te-community/sources-list.ts
|
|
2052
|
+
var communitySourcesList = createCapabilityCommand({
|
|
2053
|
+
cliService: "community",
|
|
2054
|
+
resource: "sources",
|
|
2055
|
+
command: "list",
|
|
2056
|
+
capabilityId: "community.source.list",
|
|
2057
|
+
description: "List configured community ingestion sources and their channel/source IDs.",
|
|
2058
|
+
flags: [
|
|
2059
|
+
{
|
|
2060
|
+
name: "space-id",
|
|
2061
|
+
type: "int64",
|
|
2062
|
+
required: true,
|
|
2063
|
+
min: 1,
|
|
2064
|
+
desc: "Community space ID returned by `ae-cli community spaces list`."
|
|
2065
|
+
}
|
|
2066
|
+
],
|
|
2067
|
+
risk: "read",
|
|
2068
|
+
buildInput: (ctx) => ({
|
|
2069
|
+
game_id: ctx.int64("space-id")
|
|
2070
|
+
})
|
|
2071
|
+
});
|
|
2072
|
+
|
|
2073
|
+
// src/commands/te-community/evidence-fetch.ts
|
|
2074
|
+
import { createHash } from "crypto";
|
|
2075
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
2076
|
+
var CAPABILITY = "community.content.post_detail";
|
|
2077
|
+
var MAX_ITEMS = 20;
|
|
2078
|
+
var INT64_MAX2 = 9223372036854775807n;
|
|
2079
|
+
function invalid(message) {
|
|
2080
|
+
throw new CliValidationError(message, { hint: 'Use --input @file.json with {"items":[{"channel_id":"<ID>","uuid":"<UUID>","resource_type":0}]}.' });
|
|
2081
|
+
}
|
|
2082
|
+
function record(value) {
|
|
2083
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2084
|
+
}
|
|
2085
|
+
function int64(value) {
|
|
2086
|
+
if (typeof value === "number" && !Number.isSafeInteger(value)) invalid("Evidence IDs must be exact integers; use quoted int64 IDs.");
|
|
2087
|
+
if (!["string", "number", "bigint"].includes(typeof value) || !/^[1-9]\d*$/.test(String(value))) invalid("Evidence channel_id must be a positive int64.");
|
|
2088
|
+
if (BigInt(String(value)) > INT64_MAX2) invalid("Evidence channel_id exceeds signed int64.");
|
|
2089
|
+
return String(value);
|
|
2090
|
+
}
|
|
2091
|
+
function prepare(ctx) {
|
|
2092
|
+
let input;
|
|
2093
|
+
try {
|
|
2094
|
+
const raw = ctx.str("input").trim();
|
|
2095
|
+
input = parseJsonRequest(raw === "-" ? readFileSync2(0, "utf8") : raw.startsWith("@") ? readFileSync2(raw.slice(1), "utf8") : raw);
|
|
2096
|
+
} catch {
|
|
2097
|
+
invalid("Cannot read evidence input as JSON.");
|
|
2098
|
+
}
|
|
2099
|
+
if (!record(input) || Object.keys(input).some((k) => k !== "items") || !Array.isArray(input.items) || input.items.length < 1 || input.items.length > MAX_ITEMS) invalid("Evidence input must contain only items, with 1 to 20 entries.");
|
|
2100
|
+
const locators = input.items.map((value) => {
|
|
2101
|
+
if (!record(value) || Object.keys(value).some((k) => !["channel_id", "uuid", "resource_type"].includes(k))) invalid("Each evidence item must contain only channel_id, uuid, and resource_type.");
|
|
2102
|
+
const channelId = int64(value.channel_id);
|
|
2103
|
+
if (typeof value.uuid !== "string" || !value.uuid.trim() || value.uuid.length > 512 || /[\u0000-\u001f\u007f]/.test(value.uuid)) invalid("Evidence uuid must be a non-empty opaque ID of at most 512 characters without control characters.");
|
|
2104
|
+
if (value.resource_type !== 0 && value.resource_type !== 1) invalid("Evidence resource_type must be 0 (post) or 1 (video).");
|
|
2105
|
+
return { channel_id: channelId, uuid: value.uuid, resource_type: value.resource_type };
|
|
2106
|
+
});
|
|
2107
|
+
const spaceId = ctx.int64("space-id");
|
|
2108
|
+
if (spaceId < 1n || spaceId > INT64_MAX2) invalid("Evidence space-id must be a positive int64.");
|
|
2109
|
+
const maxChars = ctx.optionalNum("max-chars") ?? 1e5;
|
|
2110
|
+
if (!Number.isInteger(maxChars) || maxChars < 1 || maxChars > 1e6) invalid("--max-chars must be an integer between 1 and 1000000.");
|
|
2111
|
+
const unique = [...new Map(locators.map((item) => [JSON.stringify(item), item])).values()];
|
|
2112
|
+
return { spaceId, requested: locators.length, locators: unique, maxChars };
|
|
2113
|
+
}
|
|
2114
|
+
function request(spaceId, item) {
|
|
2115
|
+
return {
|
|
2116
|
+
game_id: spaceId,
|
|
2117
|
+
channel_id: BigInt(item.channel_id),
|
|
2118
|
+
uuid: item.uuid,
|
|
2119
|
+
resource_type: item.resource_type,
|
|
2120
|
+
reply_pager_header: { page_num: 1, page_size: 1 },
|
|
2121
|
+
danmu_pager_header: { page_num: 1, page_size: 1 }
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
function identity(host, spaceId, item) {
|
|
2125
|
+
return `community:${createHash("sha256").update(JSON.stringify([host.replace(/\/+$/, ""), String(spaceId), item.channel_id, item.resource_type, item.uuid])).digest("hex")}`;
|
|
2126
|
+
}
|
|
2127
|
+
function field(data, snake, camel = snake) {
|
|
2128
|
+
return data[snake] ?? data[camel];
|
|
2129
|
+
}
|
|
2130
|
+
function matches(data, item) {
|
|
2131
|
+
if (!record(data)) return false;
|
|
2132
|
+
const type = field(data, "resource_type", "resourceType");
|
|
2133
|
+
return String(field(data, "channel_id", "channelId")) === item.channel_id && data.uuid === item.uuid && (type === item.resource_type || type === (item.resource_type === 0 ? "POST" : "VIDEO"));
|
|
2134
|
+
}
|
|
2135
|
+
function evidenceText(data, remaining) {
|
|
2136
|
+
const text = {};
|
|
2137
|
+
const textFields = {};
|
|
2138
|
+
let used = 0;
|
|
2139
|
+
let truncated = false;
|
|
2140
|
+
for (const name of ["title", "content", "description", "subtitle"]) {
|
|
2141
|
+
const value = data[name];
|
|
2142
|
+
const parts = typeof value === "string" ? [value] : Array.isArray(value) && value.every((v) => typeof v === "string") ? value : null;
|
|
2143
|
+
if (parts === null) {
|
|
2144
|
+
text[name] = null;
|
|
2145
|
+
textFields[name] = { status: value == null ? "missing" : "unsupported_format" };
|
|
2146
|
+
continue;
|
|
2147
|
+
}
|
|
2148
|
+
let original = 0;
|
|
2149
|
+
let returned = 0;
|
|
2150
|
+
const clipped = [];
|
|
2151
|
+
for (const part of parts) {
|
|
2152
|
+
const chars = Array.from(part);
|
|
2153
|
+
original += chars.length;
|
|
2154
|
+
const kept = chars.slice(0, Math.max(0, remaining - used));
|
|
2155
|
+
returned += kept.length;
|
|
2156
|
+
used += kept.length;
|
|
2157
|
+
if (kept.length || chars.length === 0) clipped.push(kept.join(""));
|
|
2158
|
+
}
|
|
2159
|
+
text[name] = typeof value === "string" ? clipped[0] ?? "" : clipped;
|
|
2160
|
+
const cut = returned < original;
|
|
2161
|
+
truncated ||= cut;
|
|
2162
|
+
textFields[name] = { status: cut ? "truncated" : "available", original_chars: original, returned_chars: returned };
|
|
2163
|
+
}
|
|
2164
|
+
return { text, textFields, used, truncated };
|
|
2165
|
+
}
|
|
2166
|
+
function safeSource(data) {
|
|
2167
|
+
const value = field(data, "red_note_url", "redNoteUrl");
|
|
2168
|
+
if (typeof value !== "string" || value.length > 4096) return null;
|
|
2169
|
+
try {
|
|
2170
|
+
return ["https:", "http:"].includes(new URL(value).protocol) ? value : null;
|
|
2171
|
+
} catch {
|
|
2172
|
+
return null;
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
function safeError(error) {
|
|
2176
|
+
const code = (value, fallback) => typeof value === "string" && /^[A-Za-z0-9_-]{1,80}$/.test(value) ? value : fallback;
|
|
2177
|
+
if (error instanceof SecureStoreAuthError) return { type: "auth", code: "AUTH_REQUIRED", message: "Authentication is required to read evidence." };
|
|
2178
|
+
if (error instanceof PermissionError) return { type: "permission", code: code(error.code, "PERMISSION_DENIED"), message: "Access to this evidence was denied." };
|
|
2179
|
+
if (error instanceof CapabilityGatewayError) {
|
|
2180
|
+
const type = error.httpStatus === 401 ? "auth" : error.httpStatus === 403 ? "permission" : "api";
|
|
2181
|
+
return { type, code: code(error.code, "CAPABILITY_FAILED"), message: "Evidence could not be read from the capability service." };
|
|
2182
|
+
}
|
|
2183
|
+
return { type: "api", code: "REQUEST_FAILED", message: "Evidence request failed." };
|
|
2184
|
+
}
|
|
2185
|
+
var communityEvidenceFetch = {
|
|
2186
|
+
service: "community",
|
|
2187
|
+
resource: "evidence",
|
|
2188
|
+
command: "fetch",
|
|
2189
|
+
description: "Read up to 20 unique post/video sources with verified IDs, complete text, and explicit partial-result status.",
|
|
2190
|
+
flags: [
|
|
2191
|
+
{ name: "space-id", type: "int64", required: true, min: 1, desc: "Community space ID from spaces list." },
|
|
2192
|
+
{ name: "input", type: "string", required: true, sensitive: true, desc: "JSON object, @file.json, or - for stdin; items contain channel_id, uuid, resource_type." },
|
|
2193
|
+
{ name: "max-chars", type: "number", min: 1, max: 1e6, desc: "Combined returned text budget in Unicode code points (default 100000)." }
|
|
2194
|
+
],
|
|
2195
|
+
risk: "read",
|
|
2196
|
+
dryRun: (ctx) => {
|
|
2197
|
+
const plan = prepare(ctx);
|
|
2198
|
+
return {
|
|
2199
|
+
method: "POST",
|
|
2200
|
+
url: buildCapabilityGatewayUrl(ctx.host(), resolveGatewayDomain("community", "community"), `capabilities/${CAPABILITY}/execute`),
|
|
2201
|
+
body: {
|
|
2202
|
+
preview_only: true,
|
|
2203
|
+
requested: plan.requested,
|
|
2204
|
+
unique: plan.locators.length,
|
|
2205
|
+
max_chars: plan.maxChars,
|
|
2206
|
+
inputs: plan.locators.map((item) => ({ ...request(plan.spaceId, item), game_id: String(plan.spaceId), channel_id: item.channel_id }))
|
|
2207
|
+
}
|
|
2208
|
+
};
|
|
2209
|
+
},
|
|
2210
|
+
execute: async (ctx) => {
|
|
2211
|
+
const plan = prepare(ctx);
|
|
2212
|
+
const gatewayDomain = resolveGatewayDomain("community", "community");
|
|
2213
|
+
const items = [];
|
|
2214
|
+
let returnedChars = 0;
|
|
2215
|
+
let accessStopped = false;
|
|
2216
|
+
for (const item of plan.locators) {
|
|
2217
|
+
const base = { evidence_id: identity(ctx.host(), plan.spaceId, item), locator: { space_id: String(plan.spaceId), ...item } };
|
|
2218
|
+
if (returnedChars >= plan.maxChars || accessStopped) {
|
|
2219
|
+
items.push({ ...base, status: "not_fetched", reason: accessStopped ? "access_denied" : "text_budget_exhausted" });
|
|
2220
|
+
continue;
|
|
2221
|
+
}
|
|
2222
|
+
try {
|
|
2223
|
+
const response = await requestCapabilityGatewayWithEnvelope(ctx.host(), gatewayDomain, `capabilities/${CAPABILITY}/execute`, "POST", { input: request(plan.spaceId, item) });
|
|
2224
|
+
if (response.data == null) {
|
|
2225
|
+
items.push({ ...base, status: "missing", reason: "no_detail_returned" });
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
if (!matches(response.data, item)) {
|
|
2229
|
+
items.push({ ...base, status: "invalid_response", reason: "evidence_identity_mismatch" });
|
|
2230
|
+
continue;
|
|
2231
|
+
}
|
|
2232
|
+
const excerpt = evidenceText(response.data, plan.maxChars - returnedChars);
|
|
2233
|
+
returnedChars += excerpt.used;
|
|
2234
|
+
items.push({
|
|
2235
|
+
...base,
|
|
2236
|
+
status: "ok",
|
|
2237
|
+
text: excerpt.text,
|
|
2238
|
+
author: { user_id: field(response.data, "user_id", "userId") ?? null, user_name: field(response.data, "user_name", "userName") ?? null },
|
|
2239
|
+
publish_time: field(response.data, "publish_time", "publishTime") ?? null,
|
|
2240
|
+
last_update_time: field(response.data, "last_update_time", "lastUpdateTime") ?? null,
|
|
2241
|
+
source_url: safeSource(response.data),
|
|
2242
|
+
quality: {
|
|
2243
|
+
identity_verified: true,
|
|
2244
|
+
text_truncated: excerpt.truncated,
|
|
2245
|
+
source_completeness: "unknown",
|
|
2246
|
+
text_fields: excerpt.textFields,
|
|
2247
|
+
related_comments_included: false,
|
|
2248
|
+
related_media_included: false
|
|
2249
|
+
},
|
|
2250
|
+
...response.meta ? { meta: response.meta } : {}
|
|
2251
|
+
});
|
|
2252
|
+
} catch (error) {
|
|
2253
|
+
const failure = safeError(error);
|
|
2254
|
+
accessStopped = failure.type === "auth" || failure.type === "permission";
|
|
2255
|
+
items.push({ ...base, status: "error", error: failure });
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
return {
|
|
2259
|
+
contract_version: "community-evidence-v1",
|
|
2260
|
+
capability_id: CAPABILITY,
|
|
2261
|
+
host: ctx.host(),
|
|
2262
|
+
space_id: String(plan.spaceId),
|
|
2263
|
+
requested: plan.requested,
|
|
2264
|
+
unique: items.length,
|
|
2265
|
+
items,
|
|
2266
|
+
quality: {
|
|
2267
|
+
dataset_complete: false,
|
|
2268
|
+
batch_complete: items.every((item) => item.status === "ok" && !item.quality.text_truncated),
|
|
2269
|
+
returned_chars: returnedChars,
|
|
2270
|
+
max_chars: plan.maxChars,
|
|
2271
|
+
snapshot: false
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
2274
|
+
}
|
|
2275
|
+
};
|
|
2276
|
+
var communityEvidenceFetchAlias = {
|
|
2277
|
+
...communityEvidenceFetch,
|
|
2278
|
+
resource: void 0,
|
|
2279
|
+
command: "+fetch-evidence",
|
|
2280
|
+
description: "Compatibility alias for community evidence fetch."
|
|
2281
|
+
};
|
|
2282
|
+
|
|
1802
2283
|
// src/commands/te-community/index.ts
|
|
1803
2284
|
registerCapabilityGatewayRoute("community", { gatewayDomain: "community" });
|
|
1804
2285
|
registerMcpMappings({
|
|
@@ -1806,8 +2287,7 @@ registerMcpMappings({
|
|
|
1806
2287
|
"community_analysis": { componentName: "community", mappingPath: "analysis" },
|
|
1807
2288
|
"community_hot": { componentName: "community", mappingPath: "hot" }
|
|
1808
2289
|
});
|
|
1809
|
-
var
|
|
1810
|
-
communityDataReport,
|
|
2290
|
+
var communityReadCommands = [
|
|
1811
2291
|
// Content commands
|
|
1812
2292
|
getLivestreamList,
|
|
1813
2293
|
getLivestreamDetail,
|
|
@@ -1831,6 +2311,20 @@ var commands = [
|
|
|
1831
2311
|
getHotTopics,
|
|
1832
2312
|
getTopicDetail
|
|
1833
2313
|
];
|
|
2314
|
+
var commands = [
|
|
2315
|
+
communityDataReport,
|
|
2316
|
+
communityEvidenceFetch,
|
|
2317
|
+
communityEvidenceFetchAlias,
|
|
2318
|
+
communitySpacesList,
|
|
2319
|
+
communitySourcesList,
|
|
2320
|
+
...communityReadCommands.map((command) => ({
|
|
2321
|
+
...command,
|
|
2322
|
+
validate: (ctx) => {
|
|
2323
|
+
validateCommunityCommand(ctx, command);
|
|
2324
|
+
command.validate?.(ctx);
|
|
2325
|
+
}
|
|
2326
|
+
}))
|
|
2327
|
+
];
|
|
1834
2328
|
var te_community_default = commands;
|
|
1835
2329
|
export {
|
|
1836
2330
|
te_community_default as default
|