@thinkingai/ae-cli 6.1.27 → 6.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +52 -6
  2. package/README.zh.md +52 -6
  3. package/bin/ae-cli.js +5 -0
  4. package/bin/runtime-capabilities.json +5 -0
  5. package/cli-installation-guide.md +24 -3
  6. package/dist/{auth-WA7YGGRT.js → auth-OBQ5KVQM.js} +175 -45
  7. package/dist/{automation-VAAQBM7Y.js → automation-NAR5DDGL.js} +94 -38
  8. package/dist/{capability-GAAYJ3IQ.js → capability-LFSVNI5B.js} +57 -28
  9. package/dist/chunk-2UW3Y463.js +2289 -0
  10. package/dist/{chunk-VZZNLV3I.js → chunk-3SDHJOCR.js} +68 -18
  11. package/dist/chunk-6HAUVWOQ.js +132 -0
  12. package/dist/{chunk-5XJYLEVC.js → chunk-72NJKS7O.js} +4 -4
  13. package/dist/{chunk-Q5US7JC5.js → chunk-7JAVT5TK.js} +3 -3
  14. package/dist/{chunk-7KU2WNQE.js → chunk-CVCTFLSO.js} +37 -15
  15. package/dist/{chunk-GHXZK54S.js → chunk-H3K5UGYC.js} +41 -13
  16. package/dist/{chunk-OP44TT4H.js → chunk-IN7KKL6K.js} +4 -2
  17. package/dist/{chunk-S6M42KND.js → chunk-JEUXDY3B.js} +1 -1
  18. package/dist/{chunk-ZL7SGNIA.js → chunk-JNVVJ273.js} +58 -46
  19. package/dist/chunk-N6XBLRB7.js +105 -0
  20. package/dist/{chunk-AP7YP2NX.js → chunk-OAWPT7VP.js} +2 -2
  21. package/dist/{chunk-AQJPNWZF.js → chunk-PWXDWMCW.js} +7 -7
  22. package/dist/{chunk-CT7QDJS6.js → chunk-QVRIDN42.js} +2 -2
  23. package/dist/chunk-QZLRHGVH.js +222 -0
  24. package/dist/{chunk-RPBOAQQQ.js → chunk-QZUVLFNR.js} +1 -1
  25. package/dist/{chunk-3YVEAZUN.js → chunk-RJHGDWSC.js} +32 -21
  26. package/dist/{chunk-MWIA43UJ.js → chunk-VCZE3IWO.js} +10 -8
  27. package/dist/chunk-YVG6QD3V.js +233 -0
  28. package/dist/{chunk-WNGFSIOB.js → chunk-Z3Q2AEIN.js} +237 -86
  29. package/dist/{community-report-client-PEERQCX2.js → community-report-client-TJVCLZ3K.js} +1 -1
  30. package/dist/compat-check-CII6B74E.js +32 -0
  31. package/dist/{config-JOD5DOPE.js → config-YZ6O2UQ2.js} +40 -7
  32. package/dist/{context-NGVFPCBK.js → context-F6FCGTF3.js} +4 -4
  33. package/dist/{data-integration-BCLQFTGU.js → data-integration-6UAZO4GG.js} +207 -24
  34. package/dist/evaluation-4LO2O4AF.js +3714 -0
  35. package/dist/index.js +352 -81
  36. package/dist/{local-data-upload-client-TWMHFLUA.js → local-data-upload-client-KCMG6J62.js} +1 -1
  37. package/dist/{memory-CQKH2JAV.js → memory-HHPX3NF2.js} +6 -6
  38. package/dist/{metadata-NR3PHR23.js → metadata-TIFY24LW.js} +17 -9
  39. package/dist/{model-VX5M2CJ6.js → model-7UHGWYVR.js} +4 -4
  40. package/dist/{personal-semantic-preference-2RAI36P3.js → personal-semantic-preference-WKJEGPTM.js} +7 -6
  41. package/dist/{project-semantic-3BUGP3ZM.js → project-semantic-EIQVZNHW.js} +11 -10
  42. package/dist/{sync-RZIAV37C.js → sync-RV3OPCTI.js} +8 -7
  43. package/dist/{te-agent-AORRE2FM.js → te-agent-5ENVZJUH.js} +757 -94
  44. package/dist/{te-analysis-GP7DSQ7Q.js → te-analysis-USIK6ZZG.js} +584 -100
  45. package/dist/{te-community-42M7ICDO.js → te-community-WE2UU4XV.js} +722 -228
  46. package/dist/{te-dataops-BNKNZ4F2.js → te-dataops-XNMO7MBF.js} +9 -6
  47. package/dist/{te-engage-2CO6LRCX.js → te-engage-6C3HCFQR.js} +13 -12
  48. package/dist/{te-experiment-652CLXMU.js → te-experiment-LVTRI3QK.js} +55 -21
  49. package/dist/{te-kb-ULATOTQ3.js → te-kb-TUPGMVBY.js} +409 -85
  50. package/dist/{te-system-UGHVKBVV.js → te-system-YM657FKO.js} +6 -6
  51. package/dist/{te-team-YA6SNOJ3.js → te-team-G4VEJJNL.js} +64 -41
  52. package/dist/{things-DTCOQIQB.js → things-22KQWC23.js} +7 -7
  53. package/dist/{update-ESNYKUVR.js → update-XX4ILU7X.js} +11 -7
  54. package/dist/{workspace-JEOHKFPX.js → workspace-LYDAP647.js} +6 -6
  55. package/package.json +26 -11
  56. package/skills/ae-agent/SKILL.md +22 -3
  57. package/skills/ae-agent/references/command_index.md +8 -0
  58. package/skills/ae-agent/references/resource-package.md +57 -0
  59. package/skills/ae-analysis/SKILL.md +23 -10
  60. package/skills/ae-analysis/references/adhoc_export.md +1 -1
  61. package/skills/ae-analysis/references/agent_review_preflight.md +55 -10
  62. package/skills/ae-analysis/references/agent_review_priorities_comparisons.md +5 -3
  63. package/skills/ae-analysis/references/agent_review_submit_to_page.md +60 -24
  64. package/skills/ae-analysis/references/ai_models/event.md +58 -2
  65. package/skills/ae-analysis/references/ai_models/rank_list.md +1 -0
  66. package/skills/ae-analysis/references/ai_models/retention.md +2 -0
  67. package/skills/ae-analysis/references/ai_models/revenue.md +2 -0
  68. package/skills/ae-analysis/references/analysis_data_export.md +11 -1
  69. package/skills/ae-analysis/references/asset_batch_info_export.md +2 -2
  70. package/skills/ae-analysis/references/asset_batch_sql_export.md +2 -2
  71. package/skills/ae-analysis/references/asset_export.md +1 -1
  72. package/skills/ae-analysis/references/bi_panel_page_data_export.md +1 -1
  73. package/skills/ae-analysis/references/check_export.md +1 -1
  74. package/skills/ae-analysis/references/command_index.md +39 -26
  75. package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
  76. package/skills/ae-analysis/references/dashboard_report_get.md +6 -2
  77. package/skills/ae-analysis/references/dashboard_report_update.md +24 -5
  78. package/skills/ae-analysis/references/feedback_submit.md +1 -1
  79. package/skills/ae-analysis/references/governance_recommendation_export.md +40 -18
  80. package/skills/ae-analysis/references/governance_recommendation_run_update.md +13 -0
  81. package/skills/ae-analysis/references/live_data_export.md +1 -1
  82. package/skills/ae-analysis/references/metric_create.md +29 -0
  83. package/skills/ae-analysis/references/metric_get.md +2 -0
  84. package/skills/ae-analysis/references/metric_update.md +2 -0
  85. package/skills/ae-analysis/references/operation_record_export.md +1 -1
  86. package/skills/ae-analysis/references/plan_change_log_export.md +1 -1
  87. package/skills/ae-analysis/references/plan_export.md +1 -1
  88. package/skills/ae-analysis/references/project_info_get.md +4 -0
  89. package/skills/ae-analysis/references/project_member_group_add_members.md +35 -0
  90. package/skills/ae-analysis/references/project_member_group_create.md +25 -0
  91. package/skills/ae-analysis/references/project_member_group_delete.md +34 -0
  92. package/skills/ae-analysis/references/project_member_group_list.md +29 -0
  93. package/skills/ae-analysis/references/project_member_group_members.md +28 -0
  94. package/skills/ae-analysis/references/project_member_group_remove_members.md +35 -0
  95. package/skills/ae-analysis/references/project_member_group_rename.md +26 -0
  96. package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +9 -1
  97. package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +6 -1
  98. package/skills/ae-analysis/references/report_data_export.md +1 -1
  99. package/skills/ae-analysis/references/scenario_append.md +31 -0
  100. package/skills/ae-analysis/references/scenario_begin.md +11 -0
  101. package/skills/ae-analysis/references/scenario_collect.md +43 -0
  102. package/skills/ae-analysis/references/scenario_evaluation.md +18 -0
  103. package/skills/ae-analysis/references/scenario_get.md +15 -0
  104. package/skills/ae-analysis/references/scenario_list.md +64 -0
  105. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +73 -4
  106. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +14 -1
  107. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-schema.md +5 -1
  108. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/execution-contract.mjs +173 -0
  109. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +109 -64
  110. package/skills/ae-automation/SKILL.md +2 -2
  111. package/skills/ae-automation/references/cli.md +18 -1
  112. package/skills/ae-capability/SKILL.md +7 -3
  113. package/skills/ae-community/SKILL.md +77 -27
  114. package/skills/ae-community/references/community-analyzing-theme-comment.md +10 -8
  115. package/skills/ae-community/references/community-data-quality.md +68 -0
  116. package/skills/ae-community/references/community-query-evidence.md +85 -0
  117. package/skills/ae-community/references/community-scenario-capabilities.md +137 -0
  118. package/skills/ae-community/references/community-weekly-report.md +6 -3
  119. package/skills/ae-community/references/get_channel_info.md +7 -4
  120. package/skills/ae-community/references/get_comment_tag_analysis.md +3 -3
  121. package/skills/ae-community/references/get_comments_summary.md +4 -4
  122. package/skills/ae-community/references/get_corpus_tags.md +3 -3
  123. package/skills/ae-community/references/get_daily_summary.md +3 -3
  124. package/skills/ae-community/references/get_hot_topics.md +3 -3
  125. package/skills/ae-community/references/get_livestream_analysis.md +3 -3
  126. package/skills/ae-community/references/get_livestream_detail.md +4 -4
  127. package/skills/ae-community/references/get_livestream_list.md +3 -3
  128. package/skills/ae-community/references/get_livestream_overview.md +3 -3
  129. package/skills/ae-community/references/get_livestream_room_metrics.md +3 -3
  130. package/skills/ae-community/references/get_livestream_rooms.md +3 -3
  131. package/skills/ae-community/references/get_overview_metrics.md +3 -3
  132. package/skills/ae-community/references/get_post_detail.md +4 -4
  133. package/skills/ae-community/references/get_risk_content.md +5 -5
  134. package/skills/ae-community/references/get_sentiment_overview.md +4 -4
  135. package/skills/ae-community/references/get_tag_trends.md +3 -3
  136. package/skills/ae-community/references/get_topic_detail.md +3 -3
  137. package/skills/ae-community/references/list_sources.md +28 -0
  138. package/skills/ae-community/references/list_spaces.md +39 -0
  139. package/skills/ae-community/references/search_posts.md +21 -7
  140. package/skills/ae-data-integration/SKILL.md +6 -4
  141. package/skills/ae-data-integration/references/error-handling.md +1 -0
  142. package/skills/ae-data-integration/references/handoff.md +1 -1
  143. package/skills/ae-data-integration/references/sink-upload.md +11 -0
  144. package/skills/ae-data-integration/references/source-inspect.md +2 -1
  145. package/skills/ae-data-integration/references/transform.md +1 -1
  146. package/skills/ae-data-integration/references/ue-mapping.md +1 -1
  147. package/skills/ae-evaluation/SKILL.md +83 -0
  148. package/skills/ae-evaluation/references/access-and-members.md +55 -0
  149. package/skills/ae-evaluation/references/connections.md +78 -0
  150. package/skills/ae-evaluation/references/datasets.md +57 -0
  151. package/skills/ae-evaluation/references/evaluators.md +81 -0
  152. package/skills/ae-evaluation/references/files.md +33 -0
  153. package/skills/ae-evaluation/references/integrations.md +39 -0
  154. package/skills/ae-evaluation/references/runs.md +160 -0
  155. package/skills/ae-evaluation/references/schedules.md +31 -0
  156. package/skills/ae-experiment/SKILL.md +7 -1
  157. package/skills/ae-experiment/references/manage_experiment.md +18 -1
  158. package/skills/ae-experiment/references/query_experiment_detail.md +7 -0
  159. package/skills/ae-experiment/references/save_experiment.md +76 -2
  160. package/skills/ae-experiment/references/save_submit_experiment.md +7 -0
  161. package/skills/ae-kb/SKILL.md +33 -7
  162. package/skills/ae-kb/references/publication.md +81 -0
  163. package/skills/ae-kb/references/query-workflow.md +14 -1
  164. package/skills/ae-metadata/SKILL.md +3 -2
  165. package/skills/ae-metadata/references/metadata_data_table_download.md +7 -1
  166. package/skills/ae-metadata/references/metadata_data_table_get.md +37 -0
  167. package/skills/ae-system/SKILL.md +1 -1
  168. package/skills/ae-team/SKILL.md +2 -2
  169. package/skills/ae-team/references/run-start.md +1 -0
  170. package/skills/ae-team/references/run-watch.md +7 -5
  171. package/skills/ae-things/SKILL.md +53 -51
  172. package/skills/ae-things/references/cli.md +56 -54
  173. package/skills/ae-things-progress/SKILL.md +20 -20
  174. package/skills/ae-things-review/SKILL.md +19 -19
  175. package/skills/ae-workspace/SKILL.md +1 -1
  176. package/dist/chunk-6VNIR4AP.js +0 -1422
  177. 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
- registerCapabilityGatewayRoute
3
+ createCapabilityCommand
4
+ } from "./chunk-VCZE3IWO.js";
5
+ import {
6
+ registerCapabilityGatewayRoute,
7
+ resolveGatewayDomain
4
8
  } from "./chunk-KPQY44JQ.js";
9
+ import {
10
+ unwrapOutputData,
11
+ withOutputMetadata
12
+ } from "./chunk-QZLRHGVH.js";
13
+ import {
14
+ CapabilityGatewayError,
15
+ buildCapabilityGatewayUrl,
16
+ requestCapabilityGatewayWithEnvelope
17
+ } from "./chunk-3SDHJOCR.js";
5
18
  import {
6
19
  internalCallSourceHeaders
7
20
  } from "./chunk-Y74WTIKJ.js";
21
+ import "./chunk-2UW3Y463.js";
8
22
  import {
9
23
  SecureStoreAuthError,
10
24
  getCliToken
11
- } from "./chunk-GHXZK54S.js";
25
+ } from "./chunk-H3K5UGYC.js";
12
26
  import {
13
27
  getActiveHost,
14
- safeJsonParse
15
- } from "./chunk-ZL7SGNIA.js";
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-WNGFSIOB.js";
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: JSON.stringify(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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
204
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" }
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.num("space-id");
209
- const gameId = ctx.num("game-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
226
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
243
- const gameId = ctx.num("game-id");
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(Number);
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.bool("official");
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.num("search-mode");
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 orderBy = ctx.num("order-by");
263
- const pageNum = ctx.num("page-num");
264
- const pageSize = ctx.num("page-size");
265
- if (orderBy !== void 0 || pageNum || pageSize) {
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
285
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
286
- { name: "channel-id", type: "number", required: true, desc: "Channel ID." },
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.num("space-id");
299
- const gameId = ctx.num("game-id");
300
- const channelId = ctx.num("channel-id");
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.num("danmu-order-by");
306
- const danmuPageNum = ctx.num("danmu-page-num");
307
- const danmuPageSize = ctx.num("danmu-page-size");
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.num("reply-order-by");
315
- const replyPageNum = ctx.num("reply-page-num");
316
- const replyPageSize = ctx.num("reply-page-size");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
337
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
345
- const gameId = ctx.num("game-id");
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(Number);
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
366
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
376
- const gameId = ctx.num("game-id");
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(Number);
383
- const isMerged = ctx.bool("is-merged");
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.num("limit");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
401
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
410
- const gameId = ctx.num("game-id");
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(Number);
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
434
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
440
- const gameId = ctx.num("game-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
458
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
466
- const gameId = ctx.num("game-id");
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.num("order-by");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
489
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
497
- const gameId = ctx.num("game-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
517
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
524
- const gameId = ctx.num("game-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
545
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
553
- const gameId = ctx.num("game-id");
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(Number);
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
576
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
577
- { name: "channel-id", type: "number", required: true, desc: "Channel ID from +get_livestream_rooms." },
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.num("space-id");
584
- const gameId = ctx.num("game-id");
585
- const channelId = ctx.num("channel-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
605
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
606
- { name: "channel-id", type: "number", required: false, desc: "Channel ID from +get_livestream_rooms." },
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.num("space-id");
614
- const gameId = ctx.num("game-id");
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.num("channel-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
639
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
651
- const gameId = ctx.num("game-id");
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.num("order-by");
662
- const pageNum = ctx.num("page-num");
663
- const pageSize = ctx.num("page-size");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
684
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
690
- const gameId = ctx.num("game-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
708
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
709
- { name: "channel-id", type: "number", required: true, desc: "Channel ID from search_posts results." },
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.num("space-id");
717
- const gameId = ctx.num("game-id");
718
- const channelId = ctx.num("channel-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
740
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
741
- { name: "channel-id", type: "number", required: true, desc: "Channel ID from search_posts results." },
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.num("space-id");
751
- const gameId = ctx.num("game-id");
752
- const channelId = ctx.num("channel-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
776
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" }
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.num("space-id");
781
- const gameId = ctx.num("game-id");
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: "number", required: true, desc: "Identifier of the community space. SpaceId" },
798
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
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.num("space-id");
811
- const gameId = ctx.num("game-id");
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(Number);
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.bool("include-trends");
1049
+ const includeTrends = ctx.optionalBool("include-trends");
821
1050
  if (includeTrends !== void 0) param.includeTrends = includeTrends;
822
- const orderBy = ctx.num("order-by");
823
- const pageNum = ctx.num("page-num");
824
- const pageSize = ctx.num("page-size");
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(field) {
1159
+ truncated(field2) {
931
1160
  this.value.truncatedFields += 1;
932
- this.increment(field);
1161
+ this.increment(field2);
933
1162
  }
934
- defaulted(field) {
1163
+ defaulted(field2) {
935
1164
  this.value.defaultedFields += 1;
936
- this.increment(field);
1165
+ this.increment(field2);
937
1166
  }
938
- convertedInteger(field) {
1167
+ convertedInteger(field2) {
939
1168
  this.value.convertedIntegerFields += 1;
940
- this.increment(field);
1169
+ this.increment(field2);
941
1170
  }
942
- increment(field) {
943
- this.value.fields[field] = (this.value.fields[field] ?? 0) + 1;
1171
+ increment(field2) {
1172
+ this.value.fields[field2] = (this.value.fields[field2] ?? 0) + 1;
944
1173
  }
945
1174
  };
946
- function validationError(code, message, location = {}) {
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, field) {
953
- return Object.prototype.hasOwnProperty.call(object, field);
1181
+ function hasOwn(object, field2) {
1182
+ return Object.prototype.hasOwnProperty.call(object, field2);
954
1183
  }
955
- function fieldLocation(context, field) {
956
- return { ...context.location, field };
1184
+ function fieldLocation(context, field2) {
1185
+ return { ...context.location, field: field2 };
957
1186
  }
958
- function statField(context, field) {
959
- return `${context.type}.${field}`;
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
- validationError(
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
- validationError(
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
- validationError(
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
- validationError("community_integer_out_of_range", "The field is outside its supported integer range.", location);
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
- validationError("community_integer_out_of_range", "The field must be a positive integer.", location);
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
- validationError("community_integer_out_of_range", "The field must be a nonnegative integer.", location);
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, field) {
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, field, context, options = {}) {
1009
- if (!hasOwn(input, field) || input[field] === null) {
1237
+ function normalizeIntegerField(input, output, field2, context, options = {}) {
1238
+ if (!hasOwn(input, field2) || input[field2] === null) {
1010
1239
  if (options.required) {
1011
- validationError("community_required_field", "A required field is missing.", fieldLocation(context, field));
1240
+ validationError2("community_required_field", "A required field is missing.", fieldLocation(context, field2));
1012
1241
  }
1013
- delete output[field];
1242
+ delete output[field2];
1014
1243
  return void 0;
1015
1244
  }
1016
- const parsed = parseInteger(input[field], fieldLocation(context, field), options);
1017
- output[field] = parsed.value;
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, field));
1248
+ context.stats.convertedInteger(statField(context, field2));
1020
1249
  }
1021
1250
  return parsed.value;
1022
1251
  }
1023
- function normalizeSmallIntegerField(input, output, field, context, options = {}) {
1024
- const integer = normalizeIntegerField(input, output, field, context, options);
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[field] = result;
1256
+ output[field2] = result;
1028
1257
  return result;
1029
1258
  }
1030
- function parseDateTime(value, location, requireTime = false) {
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
- validationError("community_invalid_datetime", "The field must use a supported Iris date-time format.", location);
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
- validationError("community_invalid_datetime", "The field must include a time component.", location);
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
- validationError("community_invalid_datetime", "The field must use a supported Iris date-time format.", location);
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
- validationError("community_invalid_datetime", "The field must use a supported Iris date-time format.", location);
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, field, context, options = {}) {
1061
- const path = options.path ?? field;
1062
- if (!hasOwn(input, field) || input[field] === null) {
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
- validationError("community_required_field", "A required field is missing.", fieldLocation(context, path));
1293
+ validationError2("community_required_field", "A required field is missing.", fieldLocation(context, path));
1065
1294
  }
1066
- delete output[field];
1295
+ delete output[field2];
1067
1296
  return void 0;
1068
1297
  }
1069
- const value = input[field];
1298
+ const value = input[field2];
1070
1299
  if (typeof value !== "string") {
1071
- validationError("community_invalid_text", "The field must be a JSON string.", fieldLocation(context, path));
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
- validationError(
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
- parseDateTime(normalized, fieldLocation(context, path), options.requireTime);
1315
+ parseDateTime2(normalized, fieldLocation(context, path), options.requireTime);
1087
1316
  }
1088
- output[field] = normalized;
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, field, context) {
1102
- const object = hasOwn(input, field) && input[field] !== null ? parseEncodedObject(input[field]) : void 0;
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[field] = fallback;
1106
- context.stats.defaulted(statField(context, field));
1334
+ output[field2] = fallback;
1335
+ context.stats.defaulted(statField(context, field2));
1107
1336
  return fallback;
1108
1337
  }
1109
- output[field] = object;
1338
+ output[field2] = object;
1110
1339
  return object;
1111
1340
  }
1112
- function normalizeRequiredObjectValue(value, context, field) {
1341
+ function normalizeRequiredObjectValue(value, context, field2) {
1113
1342
  const object = parseEncodedObject(value);
1114
1343
  if (object === void 0) {
1115
- validationError("community_invalid_object", "The field must be a JSON object.", fieldLocation(context, field));
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
- validationError("community_invalid_array", "The field must be an array of JSON objects.", fieldLocation(context, "subtitle"));
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
- validationError("community_invalid_array", "The field must be an array of JSON objects.", fieldLocation(context, "subtitle"));
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
- validationError("community_empty_metrics", "The metrics object must not be empty.", fieldLocation(context, fieldPrefix));
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 field = `${fieldPrefix}.${name}`;
1380
+ const field2 = `${fieldPrefix}.${name}`;
1152
1381
  if (!allowed.has(name)) {
1153
- validationError(
1382
+ validationError2(
1154
1383
  "community_invalid_metric",
1155
1384
  "The metric name is not allowed for the selected content type.",
1156
- fieldLocation(context, field)
1385
+ fieldLocation(context, field2)
1157
1386
  );
1158
1387
  }
1159
- const parsed = parseInteger(metrics[name], fieldLocation(context, field), { nonnegative: true });
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, field));
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
- validationError("community_required_field", "A required field is missing.", fieldLocation(context, "interaction.metrics"));
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
- validationError("community_invalid_enum", "The field contains an unsupported enum value.", fieldLocation(context, "root_type"));
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 = parseDateTime(streamStartTime, fieldLocation(context, "stream_start_time"), true);
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
- validationError(
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((field) => hasOwn(input, field) && input[field] !== null);
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
- validationError(
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((field) => hasOwn(input, field) && input[field] !== null);
1566
+ const hasStreamDetails = streamDependentFields.some((field2) => hasOwn(input, field2) && input[field2] !== null);
1338
1567
  if (hasStreamDetails && streamStartTime === void 0) {
1339
- validationError(
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
- validationError(
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
- validationError("community_invalid_enum", "The field contains an unsupported enum value.", fieldLocation(context, "activity_type"));
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
- validationError(
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
- validationError("community_required_field", "A required field is missing.", fieldLocation(context, "metrics"));
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
- validationError("community_invalid_record", "Each data record must be a JSON object.", context.location);
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
- validationError(
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
- validationError("community_invalid_segment", "Each payload segment must be a JSON object.", { segment });
1679
+ validationError2("community_invalid_segment", "Each payload segment must be a JSON object.", { segment });
1451
1680
  }
1452
1681
  if (!hasOwn(input, "data_type")) {
1453
- validationError("community_required_field", "A required field is missing.", { segment, field: "data_type" });
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
- validationError("community_required_field", "A required field is missing.", { segment, field: "data" });
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
- validationError("community_empty_data", "A segment data array must not be empty.", { segment, field: "data" });
1690
+ validationError2("community_empty_data", "A segment data array must not be empty.", { segment, field: "data" });
1462
1691
  }
1463
- const normalized = records.map((record, index) => normalizeRecord(record, {
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
- validationError("community_invalid_zone_id", "zone_id must be a valid IANA time zone name.", { field: "zone_id" });
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
- validationError("community_invalid_zone_id", "zone_id must be a valid IANA time zone name.", { field: "zone_id" });
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
- validationError(
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
- validationError(
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
- validationError("community_empty_payload", "The payload array must not be empty.", { field: "payload" });
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, field) {
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 --${field} as inline JSON, an existing path, @path, or - for stdin.`,
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 commands = [
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