@thinkingai/ae-cli 6.1.28 → 6.1.30

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 (117) hide show
  1. package/README.md +24 -4
  2. package/README.zh.md +24 -4
  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-NKD5Z5BQ.js → auth-ADZHUIJR.js} +30 -12
  7. package/dist/{automation-K32V2NKP.js → automation-FD2QZUP6.js} +6 -6
  8. package/dist/{capability-4CGSL7PK.js → capability-QXFRJYZD.js} +54 -26
  9. package/dist/{chunk-P6VFCH3P.js → chunk-2F64AZYH.js} +2 -2
  10. package/dist/{chunk-LMCYSVVA.js → chunk-4PSTYEG5.js} +50 -41
  11. package/dist/{chunk-KHS64JZQ.js → chunk-72NJKS7O.js} +4 -4
  12. package/dist/chunk-AVXDJAFC.js +132 -0
  13. package/dist/{chunk-GI5BMEZO.js → chunk-AWVZTN2B.js} +1 -1
  14. package/dist/chunk-CG773QXN.js +2289 -0
  15. package/dist/{chunk-UUD5RB36.js → chunk-E25OSZLJ.js} +3 -3
  16. package/dist/{chunk-UF244C5C.js → chunk-EUFP4M2A.js} +7 -7
  17. package/dist/{chunk-QW3R6O7L.js → chunk-HRUOV6EQ.js} +57 -15
  18. package/dist/{chunk-T44M3PLZ.js → chunk-JEUXDY3B.js} +1 -1
  19. package/dist/{chunk-2UWS5CUP.js → chunk-JSBLCLFE.js} +3 -3
  20. package/dist/{chunk-QSAR3GHY.js → chunk-OAWPT7VP.js} +2 -2
  21. package/dist/{chunk-2IYIYSUO.js → chunk-QVRIDN42.js} +2 -2
  22. package/dist/{chunk-P7KL7IOH.js → chunk-SOSFRU3O.js} +2 -2
  23. package/dist/{chunk-GTPWDLTE.js → chunk-TFORY6WY.js} +35 -14
  24. package/dist/{chunk-JJJIP2XQ.js → chunk-VDICGXCY.js} +2 -2
  25. package/dist/{chunk-UJ7UPRXK.js → chunk-Y3AM6LIO.js} +10 -8
  26. package/dist/chunk-YULUBP3R.js +222 -0
  27. package/dist/{chunk-X7DRLE62.js → chunk-YVG6QD3V.js} +1 -1
  28. package/dist/{chunk-ZW4VMY5H.js → chunk-Z3Q2AEIN.js} +152 -98
  29. package/dist/{community-report-client-S2K3A3Q6.js → community-report-client-TJVCLZ3K.js} +1 -1
  30. package/dist/compat-check-HERBTQZN.js +32 -0
  31. package/dist/{config-ASSAAIOI.js → config-E3KANXMK.js} +38 -6
  32. package/dist/{context-6RWLVOM5.js → context-CDB5H5PD.js} +4 -4
  33. package/dist/{data-integration-EXSUPUDZ.js → data-integration-QE37EQ3A.js} +207 -24
  34. package/dist/{evaluation-5YT4QLCL.js → evaluation-LR4YDYWL.js} +4 -4
  35. package/dist/index.js +297 -70
  36. package/dist/{local-data-upload-client-7HCPGIS3.js → local-data-upload-client-KCMG6J62.js} +1 -1
  37. package/dist/{memory-VCYLVPMI.js → memory-SNFR5M23.js} +6 -6
  38. package/dist/{metadata-YGI5M6OF.js → metadata-EXQYDZTH.js} +16 -8
  39. package/dist/{model-DPJHSD73.js → model-KEVCEXWD.js} +4 -4
  40. package/dist/{personal-semantic-preference-76TBKAPY.js → personal-semantic-preference-ETY3KU2O.js} +7 -6
  41. package/dist/{project-semantic-XOEBO2Q5.js → project-semantic-UHRMVOJF.js} +11 -10
  42. package/dist/{sync-7PP6KQ75.js → sync-XKEBXESC.js} +8 -7
  43. package/dist/{te-agent-PJVAPKBD.js → te-agent-S6UQR4IE.js} +11 -7
  44. package/dist/{te-analysis-OX62G5VD.js → te-analysis-WOFFCIBC.js} +185 -33
  45. package/dist/{te-community-QN3WMPNT.js → te-community-R7B6QYOO.js} +720 -228
  46. package/dist/{te-dataops-UKD2XN3E.js → te-dataops-KPILYVHA.js} +6 -5
  47. package/dist/{te-engage-X3DIXPRA.js → te-engage-IAUM6ONX.js} +13 -12
  48. package/dist/{te-experiment-MEIIK3DP.js → te-experiment-TMLRA7B3.js} +55 -21
  49. package/dist/{te-kb-73EWDFDF.js → te-kb-GKWPSLSY.js} +409 -85
  50. package/dist/{te-system-IE7NCKC3.js → te-system-CYWSK3UN.js} +6 -6
  51. package/dist/{te-team-MGQ5CNRW.js → te-team-ISN52YNG.js} +7 -6
  52. package/dist/{things-4JIBCA55.js → things-DDQ52Z3Q.js} +7 -7
  53. package/dist/{update-AX66IFMJ.js → update-CTLNTX35.js} +11 -7
  54. package/dist/{workspace-Q5NMEKEN.js → workspace-2CKQX2XL.js} +6 -6
  55. package/package.json +17 -7
  56. package/skills/ae-agent/references/resource-package.md +4 -0
  57. package/skills/ae-analysis/SKILL.md +14 -10
  58. package/skills/ae-analysis/references/agent_review_preflight.md +52 -11
  59. package/skills/ae-analysis/references/agent_review_priorities_comparisons.md +5 -3
  60. package/skills/ae-analysis/references/agent_review_submit_to_page.md +57 -25
  61. package/skills/ae-analysis/references/command_index.md +7 -3
  62. package/skills/ae-analysis/references/governance_recommendation_export.md +31 -17
  63. package/skills/ae-analysis/references/governance_recommendation_run_update.md +13 -0
  64. package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +9 -1
  65. package/skills/ae-analysis/references/scenario_append.md +6 -0
  66. package/skills/ae-analysis/references/scenario_begin.md +11 -0
  67. package/skills/ae-analysis/references/scenario_collect.md +10 -2
  68. package/skills/ae-analysis/references/scenario_evaluation.md +6 -18
  69. package/skills/ae-analysis/references/scenario_get.md +15 -0
  70. package/skills/ae-analysis/references/scenario_list.md +64 -0
  71. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +14 -1
  72. package/skills/ae-community/SKILL.md +77 -27
  73. package/skills/ae-community/references/community-analyzing-theme-comment.md +10 -8
  74. package/skills/ae-community/references/community-data-quality.md +68 -0
  75. package/skills/ae-community/references/community-query-evidence.md +85 -0
  76. package/skills/ae-community/references/community-scenario-capabilities.md +137 -0
  77. package/skills/ae-community/references/community-weekly-report.md +6 -3
  78. package/skills/ae-community/references/get_channel_info.md +7 -4
  79. package/skills/ae-community/references/get_comment_tag_analysis.md +3 -3
  80. package/skills/ae-community/references/get_comments_summary.md +4 -4
  81. package/skills/ae-community/references/get_corpus_tags.md +3 -3
  82. package/skills/ae-community/references/get_daily_summary.md +3 -3
  83. package/skills/ae-community/references/get_hot_topics.md +3 -3
  84. package/skills/ae-community/references/get_livestream_analysis.md +3 -3
  85. package/skills/ae-community/references/get_livestream_detail.md +4 -4
  86. package/skills/ae-community/references/get_livestream_list.md +3 -3
  87. package/skills/ae-community/references/get_livestream_overview.md +3 -3
  88. package/skills/ae-community/references/get_livestream_room_metrics.md +3 -3
  89. package/skills/ae-community/references/get_livestream_rooms.md +3 -3
  90. package/skills/ae-community/references/get_overview_metrics.md +3 -3
  91. package/skills/ae-community/references/get_post_detail.md +4 -4
  92. package/skills/ae-community/references/get_risk_content.md +5 -5
  93. package/skills/ae-community/references/get_sentiment_overview.md +4 -4
  94. package/skills/ae-community/references/get_tag_trends.md +3 -3
  95. package/skills/ae-community/references/get_topic_detail.md +3 -3
  96. package/skills/ae-community/references/list_sources.md +28 -0
  97. package/skills/ae-community/references/list_spaces.md +39 -0
  98. package/skills/ae-community/references/search_posts.md +21 -7
  99. package/skills/ae-data-integration/SKILL.md +6 -4
  100. package/skills/ae-data-integration/references/error-handling.md +1 -0
  101. package/skills/ae-data-integration/references/handoff.md +1 -1
  102. package/skills/ae-data-integration/references/sink-upload.md +11 -0
  103. package/skills/ae-data-integration/references/source-inspect.md +2 -1
  104. package/skills/ae-data-integration/references/transform.md +1 -1
  105. package/skills/ae-data-integration/references/ue-mapping.md +1 -1
  106. package/skills/ae-experiment/SKILL.md +7 -1
  107. package/skills/ae-experiment/references/manage_experiment.md +18 -1
  108. package/skills/ae-experiment/references/query_experiment_detail.md +7 -0
  109. package/skills/ae-experiment/references/save_experiment.md +76 -2
  110. package/skills/ae-experiment/references/save_submit_experiment.md +7 -0
  111. package/skills/ae-kb/SKILL.md +37 -8
  112. package/skills/ae-kb/references/publication.md +81 -0
  113. package/skills/ae-kb/references/query-workflow.md +20 -6
  114. package/skills/ae-kb-discovery/SKILL.md +15 -6
  115. package/skills/ae-metadata/SKILL.md +2 -2
  116. package/skills/ae-metadata/references/metadata_data_table_get.md +35 -0
  117. package/dist/chunk-ELCR235M.js +0 -1429
@@ -1,24 +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-Y3AM6LIO.js";
5
+ import {
6
+ registerCapabilityGatewayRoute,
7
+ resolveGatewayDomain
4
8
  } from "./chunk-KPQY44JQ.js";
9
+ import {
10
+ unwrapOutputData,
11
+ withOutputMetadata
12
+ } from "./chunk-YULUBP3R.js";
13
+ import {
14
+ CapabilityGatewayError,
15
+ buildCapabilityGatewayUrl,
16
+ requestCapabilityGatewayWithEnvelope
17
+ } from "./chunk-HRUOV6EQ.js";
5
18
  import {
6
19
  internalCallSourceHeaders
7
20
  } from "./chunk-Y74WTIKJ.js";
21
+ import "./chunk-CG773QXN.js";
8
22
  import {
9
23
  SecureStoreAuthError,
10
24
  getCliToken
11
- } from "./chunk-P7KL7IOH.js";
25
+ } from "./chunk-SOSFRU3O.js";
12
26
  import {
13
27
  getActiveHost,
14
- safeJsonParse
15
- } from "./chunk-LMCYSVVA.js";
28
+ parseJsonRequest,
29
+ safeJsonParse,
30
+ stringifyJsonRequest
31
+ } from "./chunk-4PSTYEG5.js";
16
32
  import {
17
33
  CliValidationError,
18
34
  PermissionError,
19
35
  externalCliTokenRequestOptions,
20
36
  logger
21
- } from "./chunk-ZW4VMY5H.js";
37
+ } from "./chunk-Z3Q2AEIN.js";
22
38
 
23
39
  // src/core/mcp.ts
24
40
  async function permissionDetails(resp) {
@@ -96,7 +112,7 @@ async function mcpRequest(url, method, params = {}, hostOverride) {
96
112
  const resp = await fetch(url, {
97
113
  method: "POST",
98
114
  headers,
99
- body: JSON.stringify(body),
115
+ body: stringifyJsonRequest(body),
100
116
  ...externalCliTokenRequestOptions(url)
101
117
  });
102
118
  if (!resp.ok) {
@@ -202,13 +218,13 @@ var getChannelInfo = {
202
218
  command: "+get_channel_info",
203
219
  description: "Valid channel list for a community space (channel id and name).",
204
220
  flags: [
205
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
206
- { 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." }
207
223
  ],
208
224
  risk: "read",
209
225
  execute: async (ctx) => {
210
- const spaceId = ctx.num("space-id");
211
- const gameId = ctx.num("game-id");
226
+ const spaceId = ctx.int64("space-id");
227
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
212
228
  const host = ctx.host();
213
229
  const param = { gameId };
214
230
  const args = { spaceId, param };
@@ -218,14 +234,219 @@ var getChannelInfo = {
218
234
  }
219
235
  };
220
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
+
221
442
  // src/commands/te-community/search_posts.ts
222
443
  var searchPosts = {
223
444
  service: "community",
224
445
  command: "+search_posts",
225
446
  description: "Search social posts/videos/feeds in a community space.",
226
447
  flags: [
227
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
228
- { 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." },
229
450
  { name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info (channelId). Comma-separated." },
230
451
  { name: "keywords", type: "string", required: false, desc: "Keyword filter list. Comma-separated." },
231
452
  { name: "start-time", type: "string", required: true, desc: "Content publish time lower bound. Format: yyyy-MM-dd." },
@@ -235,40 +456,46 @@ var searchPosts = {
235
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.' },
236
457
  { name: "search-word", type: "string", required: false, desc: "Full-text query; used together with searchMode." },
237
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." },
238
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." },
239
462
  { name: "page-num", type: "number", required: false, desc: "Page number, starting at 1." },
240
463
  { name: "page-size", type: "number", required: false, desc: "Page size. Max 10000." }
241
464
  ],
242
465
  risk: "read",
243
466
  execute: async (ctx) => {
244
- const spaceId = ctx.num("space-id");
245
- const gameId = ctx.num("game-id");
467
+ const spaceId = ctx.int64("space-id");
468
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
246
469
  const startTime = ctx.str("start-time");
247
470
  const endTime = ctx.str("end-time");
248
471
  const host = ctx.host();
249
472
  const param = { gameId, startTime, endTime };
250
473
  const channelIdList = ctx.str("channel-id-list");
251
- if (channelIdList) param.channelIdList = channelIdList.split(",").map(Number);
474
+ if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
252
475
  const keywords = ctx.str("keywords");
253
476
  if (keywords) param.keywords = keywords.split(",");
254
- const official = ctx.bool("official");
477
+ const official = ctx.optionalBool("official");
255
478
  if (official !== void 0) param.official = official;
256
479
  const resourceType = ctx.str("resource-type");
257
480
  if (resourceType) param.resourceType = resourceType.split(",").map(Number);
258
- const searchMode = ctx.num("search-mode");
481
+ const searchMode = ctx.optionalNum("search-mode");
259
482
  if (searchMode !== void 0) param.searchMode = searchMode;
260
483
  const searchWord = ctx.str("search-word");
261
484
  if (searchWord) param.searchWord = searchWord;
262
485
  const sentimentTypes = ctx.str("sentiment-types");
263
486
  if (sentimentTypes) param.sentimentTypes = sentimentTypes.split(",").map(Number);
264
- const orderBy = ctx.num("order-by");
265
- const pageNum = ctx.num("page-num");
266
- const pageSize = ctx.num("page-size");
267
- 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) {
268
495
  param.pagerHeader = {};
269
496
  if (orderBy !== void 0) param.pagerHeader.orderBy = orderBy;
270
- if (pageNum) param.pagerHeader.pageNum = pageNum;
271
- if (pageSize) param.pagerHeader.pageSize = pageSize;
497
+ if (pageNum !== void 0) param.pagerHeader.pageNum = pageNum;
498
+ if (pageSize !== void 0) param.pagerHeader.pageSize = pageSize;
272
499
  }
273
500
  const args = { spaceId, param };
274
501
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
@@ -283,9 +510,9 @@ var getPostDetail = {
283
510
  command: "+get_post_detail",
284
511
  description: "Full detail for one post/video: body, media, subtitles, danmu, sentiment, keywords, topics, tag values, and comment pager.",
285
512
  flags: [
286
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
287
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
288
- { 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." },
289
516
  { name: "uuid", type: "string", required: true, desc: "Content UUID (unique id)." },
290
517
  { name: "resource-type", type: "number", required: true, desc: "Resource type: 0 post, 1 video." },
291
518
  { name: "danmu-order-by", type: "number", required: false, desc: "Sort for danmu: 0 video timestamp desc, 1 publish time desc." },
@@ -297,30 +524,30 @@ var getPostDetail = {
297
524
  ],
298
525
  risk: "read",
299
526
  execute: async (ctx) => {
300
- const spaceId = ctx.num("space-id");
301
- const gameId = ctx.num("game-id");
302
- 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");
303
530
  const uuid = ctx.str("uuid");
304
531
  const resourceType = ctx.num("resource-type");
305
532
  const host = ctx.host();
306
533
  const param = { gameId, channelId, uuid, resourceType };
307
- const danmuOrderBy = ctx.num("danmu-order-by");
308
- const danmuPageNum = ctx.num("danmu-page-num");
309
- const danmuPageSize = ctx.num("danmu-page-size");
310
- 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) {
311
538
  param.danmuPagerHeader = {};
312
539
  if (danmuOrderBy !== void 0) param.danmuPagerHeader.orderBy = danmuOrderBy;
313
- if (danmuPageNum) param.danmuPagerHeader.pageNum = danmuPageNum;
314
- if (danmuPageSize) param.danmuPagerHeader.pageSize = danmuPageSize;
540
+ if (danmuPageNum !== void 0) param.danmuPagerHeader.pageNum = danmuPageNum;
541
+ if (danmuPageSize !== void 0) param.danmuPagerHeader.pageSize = danmuPageSize;
315
542
  }
316
- const replyOrderBy = ctx.num("reply-order-by");
317
- const replyPageNum = ctx.num("reply-page-num");
318
- const replyPageSize = ctx.num("reply-page-size");
319
- 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) {
320
547
  param.replyPagerHeader = {};
321
548
  if (replyOrderBy !== void 0) param.replyPagerHeader.orderBy = replyOrderBy;
322
- if (replyPageNum) param.replyPagerHeader.pageNum = replyPageNum;
323
- if (replyPageSize) param.replyPagerHeader.pageSize = replyPageSize;
549
+ if (replyPageNum !== void 0) param.replyPagerHeader.pageNum = replyPageNum;
550
+ if (replyPageSize !== void 0) param.replyPagerHeader.pageSize = replyPageSize;
324
551
  }
325
552
  const args = { spaceId, param };
326
553
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
@@ -335,22 +562,22 @@ var getOverviewMetrics = {
335
562
  command: "+get_overview_metrics",
336
563
  description: "Overall community metrics in a date range: post/reply counts, sentiment counts, per-channel breakdown.",
337
564
  flags: [
338
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
339
- { 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." },
340
567
  { name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info (channelId)." },
341
568
  { name: "start-time", type: "string", required: true, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
342
569
  { name: "end-time", type: "string", required: true, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
343
570
  ],
344
571
  risk: "read",
345
572
  execute: async (ctx) => {
346
- const spaceId = ctx.num("space-id");
347
- const gameId = ctx.num("game-id");
573
+ const spaceId = ctx.int64("space-id");
574
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
348
575
  const startTime = ctx.str("start-time");
349
576
  const endTime = ctx.str("end-time");
350
577
  const host = ctx.host();
351
578
  const param = { gameId, startTime, endTime };
352
579
  const channelIdList = ctx.str("channel-id-list");
353
- if (channelIdList) param.channelIdList = channelIdList.split(",").map(Number);
580
+ if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
354
581
  const args = { spaceId, param };
355
582
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_analysis");
356
583
  const result = await callMcpTool(mcpUrl, "get_overview_metrics", args, host);
@@ -364,8 +591,8 @@ var getSentimentOverview = {
364
591
  command: "+get_sentiment_overview",
365
592
  description: "Sentiment distribution and hot-keyword overview: top keywords per sentiment with trends, plus overall keyword ranking.",
366
593
  flags: [
367
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
368
- { 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." },
369
596
  { name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info (channelId)." },
370
597
  { name: "start-time", type: "string", required: true, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
371
598
  { name: "end-time", type: "string", required: true, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." },
@@ -374,18 +601,18 @@ var getSentimentOverview = {
374
601
  ],
375
602
  risk: "read",
376
603
  execute: async (ctx) => {
377
- const spaceId = ctx.num("space-id");
378
- const gameId = ctx.num("game-id");
604
+ const spaceId = ctx.int64("space-id");
605
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
379
606
  const startTime = ctx.str("start-time");
380
607
  const endTime = ctx.str("end-time");
381
608
  const host = ctx.host();
382
609
  const param = { gameId, startTime, endTime };
383
610
  const channelIdList = ctx.str("channel-id-list");
384
- if (channelIdList) param.channelIdList = channelIdList.split(",").map(Number);
385
- 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");
386
613
  if (isMerged !== void 0) param.isMerged = isMerged;
387
- const limit = ctx.num("limit");
388
- if (limit) param.limit = limit;
614
+ const limit = ctx.optionalNum("limit");
615
+ if (limit !== void 0) param.limit = limit;
389
616
  const args = { spaceId, param };
390
617
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_analysis");
391
618
  const result = await callMcpTool(mcpUrl, "get_sentiment_overview", args, host);
@@ -399,8 +626,8 @@ var getTagTrends = {
399
626
  command: "+get_tag_trends",
400
627
  description: "Daily tag trends: given tagCode and date range, returns counts and time series per tag value.",
401
628
  flags: [
402
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
403
- { 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." },
404
631
  { name: "tag-code", type: "string", required: true, desc: "Tag code (tagCode) from +get_corpus_tags." },
405
632
  { name: "channel-id-list", type: "string", required: false, desc: "Channel IDs from +get_channel_info." },
406
633
  { name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
@@ -408,13 +635,13 @@ var getTagTrends = {
408
635
  ],
409
636
  risk: "read",
410
637
  execute: async (ctx) => {
411
- const spaceId = ctx.num("space-id");
412
- const gameId = ctx.num("game-id");
638
+ const spaceId = ctx.int64("space-id");
639
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
413
640
  const tagCode = ctx.str("tag-code");
414
641
  const host = ctx.host();
415
642
  const param = { gameId, tagCode };
416
643
  const channelIdList = ctx.str("channel-id-list");
417
- if (channelIdList) param.channelIdList = channelIdList.split(",").map(Number);
644
+ if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
418
645
  const startTime = ctx.str("start-time");
419
646
  if (startTime) param.startTime = startTime;
420
647
  const endTime = ctx.str("end-time");
@@ -432,14 +659,14 @@ var getDailySummary = {
432
659
  command: "+get_daily_summary",
433
660
  description: "Daily community summary for a given date: hot topic rankings and highlighted opinions (positive/negative).",
434
661
  flags: [
435
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
436
- { 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." },
437
664
  { name: "date", type: "string", required: true, desc: "Summary date. Format: yyyy-MM-dd." }
438
665
  ],
439
666
  risk: "read",
440
667
  execute: async (ctx) => {
441
- const spaceId = ctx.num("space-id");
442
- const gameId = ctx.num("game-id");
668
+ const spaceId = ctx.int64("space-id");
669
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
443
670
  const date = ctx.str("date");
444
671
  const host = ctx.host();
445
672
  const param = { gameId, date };
@@ -456,23 +683,23 @@ var getHotTopics = {
456
683
  command: "+get_hot_topics",
457
684
  description: "Hot topics leaderboard over a time range.",
458
685
  flags: [
459
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
460
- { 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." },
461
688
  { name: "start-time", type: "string", required: false, desc: "Topic statistics range start (inclusive). Format: yyyy-MM-dd." },
462
689
  { name: "end-time", type: "string", required: false, desc: "Topic statistics range end (inclusive). Format: yyyy-MM-dd." },
463
690
  { name: "order-by", type: "number", required: false, desc: "Sort: 0 by topic heat desc, 1 by topic start time desc." }
464
691
  ],
465
692
  risk: "read",
466
693
  execute: async (ctx) => {
467
- const spaceId = ctx.num("space-id");
468
- const gameId = ctx.num("game-id");
694
+ const spaceId = ctx.int64("space-id");
695
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
469
696
  const host = ctx.host();
470
697
  const param = { gameId };
471
698
  const startTime = ctx.str("start-time");
472
699
  if (startTime) param.startTime = startTime;
473
700
  const endTime = ctx.str("end-time");
474
701
  if (endTime) param.endTime = endTime;
475
- const orderBy = ctx.num("order-by");
702
+ const orderBy = ctx.optionalNum("order-by");
476
703
  if (orderBy !== void 0) param.orderBy = orderBy;
477
704
  const args = { spaceId, param };
478
705
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_hot");
@@ -487,16 +714,16 @@ var getTopicDetail = {
487
714
  command: "+get_topic_detail",
488
715
  description: "Deep stats for one topic in a range: content/reply totals, sentiment, per-channel daily trends, hot keywords.",
489
716
  flags: [
490
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
491
- { 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." },
492
719
  { name: "topic-id", type: "string", required: true, desc: "Topic ID from +get_hot_topics (topicId)." },
493
720
  { name: "start-time", type: "string", required: true, desc: "Statistics start date. Format: yyyy-MM-dd. Prefer topic startTime from +get_hot_topics." },
494
721
  { name: "end-time", type: "string", required: true, desc: "Statistics end date. Format: yyyy-MM-dd. Prefer topic endTime from +get_hot_topics." }
495
722
  ],
496
723
  risk: "read",
497
724
  execute: async (ctx) => {
498
- const spaceId = ctx.num("space-id");
499
- const gameId = ctx.num("game-id");
725
+ const spaceId = ctx.int64("space-id");
726
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
500
727
  const topicId = ctx.str("topic-id");
501
728
  const startTime = ctx.str("start-time");
502
729
  const endTime = ctx.str("end-time");
@@ -515,15 +742,15 @@ var getLivestreamOverview = {
515
742
  command: "+get_livestream_overview",
516
743
  description: "Livestream overview trends: active rooms, session count, interactions, and streamed duration.",
517
744
  flags: [
518
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
519
- { 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." },
520
747
  { name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
521
748
  { name: "end-time", type: "string", required: false, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
522
749
  ],
523
750
  risk: "read",
524
751
  execute: async (ctx) => {
525
- const spaceId = ctx.num("space-id");
526
- const gameId = ctx.num("game-id");
752
+ const spaceId = ctx.int64("space-id");
753
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
527
754
  const host = ctx.host();
528
755
  const param = { gameId };
529
756
  const startTime = ctx.str("start-time");
@@ -543,20 +770,20 @@ var getLivestreamRooms = {
543
770
  command: "+get_livestream_rooms",
544
771
  description: "Search live rooms by time range and channels; returns room list with stats.",
545
772
  flags: [
546
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
547
- { 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." },
548
775
  { name: "channel-id-list", type: "string", required: false, desc: "Channel ID list." },
549
776
  { name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
550
777
  { name: "end-time", type: "string", required: false, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
551
778
  ],
552
779
  risk: "read",
553
780
  execute: async (ctx) => {
554
- const spaceId = ctx.num("space-id");
555
- const gameId = ctx.num("game-id");
781
+ const spaceId = ctx.int64("space-id");
782
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
556
783
  const host = ctx.host();
557
784
  const param = { gameId };
558
785
  const channelIdList = ctx.str("channel-id-list");
559
- if (channelIdList) param.channelIdList = channelIdList.split(",").map(Number);
786
+ if (channelIdList) param.channelIdList = channelIdList.split(",").map((value) => BigInt(value.trim()));
560
787
  const startTime = ctx.str("start-time");
561
788
  if (startTime) param.startTime = startTime;
562
789
  const endTime = ctx.str("end-time");
@@ -574,17 +801,17 @@ var getLivestreamRoomMetrics = {
574
801
  command: "+get_livestream_room_metrics",
575
802
  description: "Core metrics and yearly calendar for one room: overview KPIs plus daily streamed-duration calendar.",
576
803
  flags: [
577
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
578
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
579
- { 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." },
580
807
  { name: "room-id", type: "string", required: true, desc: "Live room ID (roomId) from +get_livestream_rooms." },
581
808
  { name: "year", type: "string", required: false, desc: "Calendar year (yyyy)." }
582
809
  ],
583
810
  risk: "read",
584
811
  execute: async (ctx) => {
585
- const spaceId = ctx.num("space-id");
586
- const gameId = ctx.num("game-id");
587
- 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");
588
815
  const roomId = ctx.str("room-id");
589
816
  const host = ctx.host();
590
817
  const param = { gameId, channelId, roomId };
@@ -603,20 +830,20 @@ var getLivestreamList = {
603
830
  command: "+get_livestream_list",
604
831
  description: "List live sessions for a room in a time range (stream records).",
605
832
  flags: [
606
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
607
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
608
- { 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." },
609
836
  { name: "room-id", type: "string", required: false, desc: "Live room ID (roomId) from +get_livestream_rooms." },
610
837
  { name: "start-time", type: "string", required: false, desc: "Statistics range start (inclusive). Format: yyyy-MM-dd." },
611
838
  { name: "end-time", type: "string", required: false, desc: "Statistics range end (inclusive). Format: yyyy-MM-dd." }
612
839
  ],
613
840
  risk: "read",
614
841
  execute: async (ctx) => {
615
- const spaceId = ctx.num("space-id");
616
- const gameId = ctx.num("game-id");
842
+ const spaceId = ctx.int64("space-id");
843
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
617
844
  const host = ctx.host();
618
845
  const param = { gameId };
619
- const channelId = ctx.num("channel-id");
846
+ const channelId = ctx.int64("channel-id");
620
847
  if (channelId) param.channelId = channelId;
621
848
  const roomId = ctx.str("room-id");
622
849
  if (roomId) param.roomId = roomId;
@@ -637,8 +864,8 @@ var getLivestreamDetail = {
637
864
  command: "+get_livestream_detail",
638
865
  description: "One live session detail: interaction leaderboards and paginated interaction feed.",
639
866
  flags: [
640
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
641
- { 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." },
642
869
  { name: "stream-id", type: "string", required: true, desc: "Live session ID (streamId) from +get_livestream_list." },
643
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." },
644
871
  { name: "anchor-time", type: "string", required: false, desc: "Anchor time for interactions. Format: yyyy-MM-dd HH:mm." },
@@ -649,8 +876,8 @@ var getLivestreamDetail = {
649
876
  ],
650
877
  risk: "read",
651
878
  execute: async (ctx) => {
652
- const spaceId = ctx.num("space-id");
653
- const gameId = ctx.num("game-id");
879
+ const spaceId = ctx.int64("space-id");
880
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
654
881
  const streamId = ctx.str("stream-id");
655
882
  const host = ctx.host();
656
883
  const param = { gameId, streamId };
@@ -660,14 +887,14 @@ var getLivestreamDetail = {
660
887
  if (anchorTime) param.anchorTime = anchorTime;
661
888
  const searchWord = ctx.str("search-word");
662
889
  if (searchWord) param.searchWord = searchWord;
663
- const orderBy = ctx.num("order-by");
664
- const pageNum = ctx.num("page-num");
665
- const pageSize = ctx.num("page-size");
666
- 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) {
667
894
  param.pagerHeader = {};
668
895
  if (orderBy !== void 0) param.pagerHeader.orderBy = orderBy;
669
- if (pageNum) param.pagerHeader.pageNum = pageNum;
670
- if (pageSize) param.pagerHeader.pageSize = pageSize;
896
+ if (pageNum !== void 0) param.pagerHeader.pageNum = pageNum;
897
+ if (pageSize !== void 0) param.pagerHeader.pageSize = pageSize;
671
898
  }
672
899
  const args = { spaceId, param };
673
900
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
@@ -682,14 +909,14 @@ var getLivestreamAnalysis = {
682
909
  command: "+get_livestream_analysis",
683
910
  description: "AI-generated live session analysis report: highlight moments (time slices with metrics and AI insights) and sentiment opinions.",
684
911
  flags: [
685
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
686
- { 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." },
687
914
  { name: "stream-id", type: "string", required: true, desc: "Live session ID (streamId) from +get_livestream_list." }
688
915
  ],
689
916
  risk: "read",
690
917
  execute: async (ctx) => {
691
- const spaceId = ctx.num("space-id");
692
- const gameId = ctx.num("game-id");
918
+ const spaceId = ctx.int64("space-id");
919
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
693
920
  const streamId = ctx.str("stream-id");
694
921
  const host = ctx.host();
695
922
  const param = { gameId, streamId };
@@ -706,18 +933,18 @@ var getCommentsSummary = {
706
933
  command: "+get_comments_summary",
707
934
  description: "Comment analytics summary for a post: sentiment mix and time trends. Aggregate stats only\u2014no raw comment list.",
708
935
  flags: [
709
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
710
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
711
- { 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." },
712
939
  { name: "uuid", type: "string", required: true, desc: "Content UUID from search_posts results." },
713
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." },
714
941
  { name: "end-time", type: "string", required: false, desc: "Comment publish time upper bound. Format: yyyy-MM-dd." }
715
942
  ],
716
943
  risk: "read",
717
944
  execute: async (ctx) => {
718
- const spaceId = ctx.num("space-id");
719
- const gameId = ctx.num("game-id");
720
- 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");
721
948
  const uuid = ctx.str("uuid");
722
949
  const host = ctx.host();
723
950
  const param = { gameId, channelId, uuid };
@@ -738,9 +965,9 @@ var getCommentTagAnalysis = {
738
965
  command: "+get_comment_tag_analysis",
739
966
  description: "Comment tag analysis: for a tagCode, counts and trends per tag value over time.",
740
967
  flags: [
741
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
742
- { name: "game-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
743
- { 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." },
744
971
  { name: "uuid", type: "string", required: true, desc: "Content UUID from search_posts results." },
745
972
  { name: "resource-type", type: "number", required: true, desc: "Resource type: 0 post, 1 video." },
746
973
  { name: "tag-code", type: "string", required: true, desc: "Tag code (tagCode) from +get_corpus_tags." },
@@ -749,9 +976,9 @@ var getCommentTagAnalysis = {
749
976
  ],
750
977
  risk: "read",
751
978
  execute: async (ctx) => {
752
- const spaceId = ctx.num("space-id");
753
- const gameId = ctx.num("game-id");
754
- 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");
755
982
  const uuid = ctx.str("uuid");
756
983
  const resourceType = ctx.num("resource-type");
757
984
  const tagCode = ctx.str("tag-code");
@@ -774,13 +1001,13 @@ var getCorpusTags = {
774
1001
  command: "+get_corpus_tags",
775
1002
  description: "List corpus tags (tagId, tagCode, tagName, inferenceType) to pick tagCode for filters.",
776
1003
  flags: [
777
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
778
- { 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." }
779
1006
  ],
780
1007
  risk: "read",
781
1008
  execute: async (ctx) => {
782
- const spaceId = ctx.num("space-id");
783
- const gameId = ctx.num("game-id");
1009
+ const spaceId = ctx.int64("space-id");
1010
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
784
1011
  const host = ctx.host();
785
1012
  const param = { gameId };
786
1013
  const args = { spaceId, param };
@@ -796,8 +1023,8 @@ var getRiskContent = {
796
1023
  command: "+get_risk_content",
797
1024
  description: "List content flagged as risk/moderation items; filter by risk type and time.",
798
1025
  flags: [
799
- { name: "space-id", type: "number", required: true, desc: "Identifier of the community space. SpaceId" },
800
- { 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." },
801
1028
  { name: "start-time", type: "string", required: true, desc: "Risk content publish time lower bound. Format: yyyy-MM-dd." },
802
1029
  { name: "end-time", type: "string", required: true, desc: "Risk content publish time upper bound. Format: yyyy-MM-dd." },
803
1030
  { name: "risk-codes", type: "string", required: false, desc: "Risk type code list." },
@@ -809,26 +1036,26 @@ var getRiskContent = {
809
1036
  ],
810
1037
  risk: "read",
811
1038
  execute: async (ctx) => {
812
- const spaceId = ctx.num("space-id");
813
- const gameId = ctx.num("game-id");
1039
+ const spaceId = ctx.int64("space-id");
1040
+ const gameId = ctx.optionalInt64("game-id") ?? spaceId;
814
1041
  const startTime = ctx.str("start-time");
815
1042
  const endTime = ctx.str("end-time");
816
1043
  const host = ctx.host();
817
1044
  const param = { gameId, startTime, endTime };
818
1045
  const riskCodes = ctx.str("risk-codes");
819
- if (riskCodes) param.riskCodes = riskCodes.split(",").map(Number);
1046
+ if (riskCodes) param.riskCodes = riskCodes.split(",").map((value) => BigInt(value.trim()));
820
1047
  const searchWord = ctx.str("search-word");
821
1048
  if (searchWord) param.searchWord = searchWord;
822
- const includeTrends = ctx.bool("include-trends");
1049
+ const includeTrends = ctx.optionalBool("include-trends");
823
1050
  if (includeTrends !== void 0) param.includeTrends = includeTrends;
824
- const orderBy = ctx.num("order-by");
825
- const pageNum = ctx.num("page-num");
826
- const pageSize = ctx.num("page-size");
827
- 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) {
828
1055
  param.pagerHeader = {};
829
1056
  if (orderBy !== void 0) param.pagerHeader.orderBy = orderBy;
830
- if (pageNum) param.pagerHeader.pageNum = pageNum;
831
- if (pageSize) param.pagerHeader.pageSize = pageSize;
1057
+ if (pageNum !== void 0) param.pagerHeader.pageNum = pageNum;
1058
+ if (pageSize !== void 0) param.pagerHeader.pageSize = pageSize;
832
1059
  }
833
1060
  const args = { spaceId, param };
834
1061
  const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, "community_content");
@@ -929,36 +1156,36 @@ var StatsCollector = class {
929
1156
  convertedIntegerFields: 0,
930
1157
  fields: {}
931
1158
  };
932
- truncated(field) {
1159
+ truncated(field2) {
933
1160
  this.value.truncatedFields += 1;
934
- this.increment(field);
1161
+ this.increment(field2);
935
1162
  }
936
- defaulted(field) {
1163
+ defaulted(field2) {
937
1164
  this.value.defaultedFields += 1;
938
- this.increment(field);
1165
+ this.increment(field2);
939
1166
  }
940
- convertedInteger(field) {
1167
+ convertedInteger(field2) {
941
1168
  this.value.convertedIntegerFields += 1;
942
- this.increment(field);
1169
+ this.increment(field2);
943
1170
  }
944
- increment(field) {
945
- this.value.fields[field] = (this.value.fields[field] ?? 0) + 1;
1171
+ increment(field2) {
1172
+ this.value.fields[field2] = (this.value.fields[field2] ?? 0) + 1;
946
1173
  }
947
1174
  };
948
- function validationError(code, message, location = {}) {
1175
+ function validationError2(code, message, location = {}) {
949
1176
  throw new CommunityDataValidationError(code, message, location);
950
1177
  }
951
1178
  function isObject(value) {
952
1179
  return value !== null && typeof value === "object" && !Array.isArray(value);
953
1180
  }
954
- function hasOwn(object, field) {
955
- return Object.prototype.hasOwnProperty.call(object, field);
1181
+ function hasOwn(object, field2) {
1182
+ return Object.prototype.hasOwnProperty.call(object, field2);
956
1183
  }
957
- function fieldLocation(context, field) {
958
- return { ...context.location, field };
1184
+ function fieldLocation(context, field2) {
1185
+ return { ...context.location, field: field2 };
959
1186
  }
960
- function statField(context, field) {
961
- return `${context.type}.${field}`;
1187
+ function statField(context, field2) {
1188
+ return `${context.type}.${field2}`;
962
1189
  }
963
1190
  function parseInteger(value, location, options = {}) {
964
1191
  let integer;
@@ -967,7 +1194,7 @@ function parseInteger(value, location, options = {}) {
967
1194
  integer = value;
968
1195
  } else if (typeof value === "number") {
969
1196
  if (!Number.isSafeInteger(value)) {
970
- validationError(
1197
+ validationError2(
971
1198
  "community_invalid_integer",
972
1199
  "The field must be a lossless integer number or a canonical decimal string.",
973
1200
  location
@@ -976,7 +1203,7 @@ function parseInteger(value, location, options = {}) {
976
1203
  integer = BigInt(value);
977
1204
  } else if (typeof value === "string") {
978
1205
  if (!CANONICAL_INTEGER.test(value) || value === "-0") {
979
- validationError(
1206
+ validationError2(
980
1207
  "community_invalid_integer",
981
1208
  "The field must be a lossless integer number or a canonical decimal string.",
982
1209
  location
@@ -985,7 +1212,7 @@ function parseInteger(value, location, options = {}) {
985
1212
  integer = BigInt(value);
986
1213
  converted = true;
987
1214
  } else {
988
- validationError(
1215
+ validationError2(
989
1216
  "community_invalid_integer",
990
1217
  "The field must be a lossless integer number or a canonical decimal string.",
991
1218
  location
@@ -994,49 +1221,49 @@ function parseInteger(value, location, options = {}) {
994
1221
  const minimum = options.min ?? INT64_MIN;
995
1222
  const maximum = options.max ?? INT64_MAX;
996
1223
  if (integer < minimum || integer > maximum) {
997
- 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);
998
1225
  }
999
1226
  if (options.positive && integer <= 0n) {
1000
- 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);
1001
1228
  }
1002
1229
  if (options.nonnegative && integer < 0n) {
1003
- 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);
1004
1231
  }
1005
1232
  return { value: integer, converted };
1006
1233
  }
1007
- function parsePositiveId(value, field) {
1008
- return parseInteger(value, { field }, { positive: true }).value;
1234
+ function parsePositiveId(value, field2) {
1235
+ return parseInteger(value, { field: field2 }, { positive: true }).value;
1009
1236
  }
1010
- function normalizeIntegerField(input, output, field, context, options = {}) {
1011
- if (!hasOwn(input, field) || input[field] === null) {
1237
+ function normalizeIntegerField(input, output, field2, context, options = {}) {
1238
+ if (!hasOwn(input, field2) || input[field2] === null) {
1012
1239
  if (options.required) {
1013
- 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));
1014
1241
  }
1015
- delete output[field];
1242
+ delete output[field2];
1016
1243
  return void 0;
1017
1244
  }
1018
- const parsed = parseInteger(input[field], fieldLocation(context, field), options);
1019
- output[field] = parsed.value;
1245
+ const parsed = parseInteger(input[field2], fieldLocation(context, field2), options);
1246
+ output[field2] = parsed.value;
1020
1247
  if (parsed.converted) {
1021
- context.stats.convertedInteger(statField(context, field));
1248
+ context.stats.convertedInteger(statField(context, field2));
1022
1249
  }
1023
1250
  return parsed.value;
1024
1251
  }
1025
- function normalizeSmallIntegerField(input, output, field, context, options = {}) {
1026
- 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);
1027
1254
  if (integer === void 0) return void 0;
1028
1255
  const result = Number(integer);
1029
- output[field] = result;
1256
+ output[field2] = result;
1030
1257
  return result;
1031
1258
  }
1032
- function parseDateTime(value, location, requireTime = false) {
1259
+ function parseDateTime2(value, location, requireTime = false) {
1033
1260
  const match = /^(\d{4})-(\d{2})-(\d{2})(?: (\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?)?$/.exec(value);
1034
1261
  if (!match) {
1035
- 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);
1036
1263
  }
1037
1264
  const hasTime = match[4] !== void 0;
1038
1265
  if (requireTime && !hasTime) {
1039
- 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);
1040
1267
  }
1041
1268
  const parts = {
1042
1269
  year: Number(match[1]),
@@ -1049,33 +1276,33 @@ function parseDateTime(value, location, requireTime = false) {
1049
1276
  hasTime
1050
1277
  };
1051
1278
  if (parts.year === 0 || parts.month < 1 || parts.month > 12 || parts.hour > 23 || parts.minute > 59 || parts.second > 59) {
1052
- 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);
1053
1280
  }
1054
1281
  const calendarCheck = /* @__PURE__ */ new Date(0);
1055
1282
  calendarCheck.setUTCFullYear(parts.year, parts.month - 1, parts.day);
1056
1283
  calendarCheck.setUTCHours(parts.hour, parts.minute, parts.second, parts.millisecond);
1057
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) {
1058
- 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);
1059
1286
  }
1060
1287
  return parts;
1061
1288
  }
1062
- function normalizeTextField(input, output, field, context, options = {}) {
1063
- const path = options.path ?? field;
1064
- 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) {
1065
1292
  if (options.required) {
1066
- 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));
1067
1294
  }
1068
- delete output[field];
1295
+ delete output[field2];
1069
1296
  return void 0;
1070
1297
  }
1071
- const value = input[field];
1298
+ const value = input[field2];
1072
1299
  if (typeof value !== "string") {
1073
- 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));
1074
1301
  }
1075
1302
  let normalized = value;
1076
1303
  if (options.maxLength !== void 0 && normalized.length > options.maxLength) {
1077
1304
  if (!options.truncate) {
1078
- validationError(
1305
+ validationError2(
1079
1306
  "community_text_too_long",
1080
1307
  `The field must not exceed ${options.maxLength} UTF-16 code units.`,
1081
1308
  fieldLocation(context, path)
@@ -1085,9 +1312,9 @@ function normalizeTextField(input, output, field, context, options = {}) {
1085
1312
  context.stats.truncated(statField(context, path));
1086
1313
  }
1087
1314
  if (options.dateTime) {
1088
- parseDateTime(normalized, fieldLocation(context, path), options.requireTime);
1315
+ parseDateTime2(normalized, fieldLocation(context, path), options.requireTime);
1089
1316
  }
1090
- output[field] = normalized;
1317
+ output[field2] = normalized;
1091
1318
  return normalized;
1092
1319
  }
1093
1320
  function parseEncodedObject(value) {
@@ -1100,21 +1327,21 @@ function parseEncodedObject(value) {
1100
1327
  return void 0;
1101
1328
  }
1102
1329
  }
1103
- function normalizeFallbackObjectField(input, output, field, context) {
1104
- 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;
1105
1332
  if (object === void 0) {
1106
1333
  const fallback = {};
1107
- output[field] = fallback;
1108
- context.stats.defaulted(statField(context, field));
1334
+ output[field2] = fallback;
1335
+ context.stats.defaulted(statField(context, field2));
1109
1336
  return fallback;
1110
1337
  }
1111
- output[field] = object;
1338
+ output[field2] = object;
1112
1339
  return object;
1113
1340
  }
1114
- function normalizeRequiredObjectValue(value, context, field) {
1341
+ function normalizeRequiredObjectValue(value, context, field2) {
1115
1342
  const object = parseEncodedObject(value);
1116
1343
  if (object === void 0) {
1117
- 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));
1118
1345
  }
1119
1346
  return object;
1120
1347
  }
@@ -1128,11 +1355,11 @@ function normalizeSubtitle(input, output, context) {
1128
1355
  try {
1129
1356
  value = parseCommunityJson(value);
1130
1357
  } catch {
1131
- 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"));
1132
1359
  }
1133
1360
  }
1134
1361
  if (!Array.isArray(value) || value.some((element) => !isObject(element))) {
1135
- 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"));
1136
1363
  }
1137
1364
  output.subtitle = value;
1138
1365
  }
@@ -1145,23 +1372,23 @@ function normalizeMetrics(value, contentType, context, fieldPrefix) {
1145
1372
  const metrics = normalizeRequiredObjectValue(value, context, fieldPrefix);
1146
1373
  const names = Object.keys(metrics);
1147
1374
  if (names.length === 0) {
1148
- 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));
1149
1376
  }
1150
1377
  const allowed = metricNamesForContentType(contentType);
1151
1378
  const normalized = { ...metrics };
1152
1379
  for (const name of names) {
1153
- const field = `${fieldPrefix}.${name}`;
1380
+ const field2 = `${fieldPrefix}.${name}`;
1154
1381
  if (!allowed.has(name)) {
1155
- validationError(
1382
+ validationError2(
1156
1383
  "community_invalid_metric",
1157
1384
  "The metric name is not allowed for the selected content type.",
1158
- fieldLocation(context, field)
1385
+ fieldLocation(context, field2)
1159
1386
  );
1160
1387
  }
1161
- const parsed = parseInteger(metrics[name], fieldLocation(context, field), { nonnegative: true });
1388
+ const parsed = parseInteger(metrics[name], fieldLocation(context, field2), { nonnegative: true });
1162
1389
  normalized[name] = parsed.value;
1163
1390
  if (parsed.converted) {
1164
- context.stats.convertedInteger(statField(context, field));
1391
+ context.stats.convertedInteger(statField(context, field2));
1165
1392
  }
1166
1393
  }
1167
1394
  return normalized;
@@ -1179,7 +1406,7 @@ function normalizeInteractionSidecar(input, output, context, contentType) {
1179
1406
  path: "interaction.collect_time"
1180
1407
  });
1181
1408
  if (!hasOwn(interaction, "metrics") || interaction.metrics === null) {
1182
- 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"));
1183
1410
  }
1184
1411
  normalized.metrics = normalizeMetrics(interaction.metrics, contentType, context, "interaction.metrics");
1185
1412
  output.interaction = normalized;
@@ -1213,7 +1440,7 @@ function normalizeRootFields(input, output, context) {
1213
1440
  normalizeTextField(input, output, "root_id", context, { required: true, maxLength: 32, truncate: true });
1214
1441
  const rootType = normalizeTextField(input, output, "root_type", context, { required: true });
1215
1442
  if (!ROOT_TYPES.has(rootType)) {
1216
- 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"));
1217
1444
  }
1218
1445
  }
1219
1446
  function normalizeReply(input, context) {
@@ -1273,11 +1500,11 @@ function zonedDateTimeToEpochMilliseconds(parts, zoneId) {
1273
1500
  return estimate;
1274
1501
  }
1275
1502
  function validateStreamId(roomId, streamStartTime, context) {
1276
- const parts = parseDateTime(streamStartTime, fieldLocation(context, "stream_start_time"), true);
1503
+ const parts = parseDateTime2(streamStartTime, fieldLocation(context, "stream_start_time"), true);
1277
1504
  const timestamp = zonedDateTimeToEpochMilliseconds(parts, context.zoneId);
1278
1505
  const streamId = `${context.channelId}_${roomId}_${timestamp}`;
1279
1506
  if (streamId.length > 64) {
1280
- validationError(
1507
+ validationError2(
1281
1508
  "community_derived_id_too_long",
1282
1509
  "The derived stream identifier exceeds its supported length.",
1283
1510
  fieldLocation(context, "stream_start_time")
@@ -1315,9 +1542,9 @@ function normalizeLiveRoom(input, context) {
1315
1542
  for (const metric of ["online", "heat", "noble_count", "guardian_count", "diamond_fan_count", "dfans_count"]) {
1316
1543
  normalizeIntegerField(input, output, metric, context, { nonnegative: true });
1317
1544
  }
1318
- 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);
1319
1546
  if (guardianAliases.length > 1) {
1320
- validationError(
1547
+ validationError2(
1321
1548
  "community_conflicting_fields",
1322
1549
  "Only one guardian metric alias may be supplied.",
1323
1550
  fieldLocation(context, guardianAliases[1])
@@ -1336,16 +1563,16 @@ function normalizeLiveRoom(input, context) {
1336
1563
  "diamond_fan_count",
1337
1564
  "dfans_count"
1338
1565
  ];
1339
- const hasStreamDetails = streamDependentFields.some((field) => hasOwn(input, field) && input[field] !== null);
1566
+ const hasStreamDetails = streamDependentFields.some((field2) => hasOwn(input, field2) && input[field2] !== null);
1340
1567
  if (hasStreamDetails && streamStartTime === void 0) {
1341
- validationError(
1568
+ validationError2(
1342
1569
  "community_required_field",
1343
1570
  "A stream start time is required when stream details or metrics are supplied.",
1344
1571
  fieldLocation(context, "stream_start_time")
1345
1572
  );
1346
1573
  }
1347
1574
  if (uuid * 5n + 4n > INT64_MAX) {
1348
- validationError(
1575
+ validationError2(
1349
1576
  "community_derived_id_overflow",
1350
1577
  "A derived live metric identifier would exceed signed int64.",
1351
1578
  fieldLocation(context, "uuid")
@@ -1361,14 +1588,14 @@ function normalizeLiveInteraction(input, context) {
1361
1588
  normalizeIntegerField(input, output, "uuid", context, { required: true, nonnegative: true });
1362
1589
  const activityType = normalizeTextField(input, output, "activity_type", context, { required: true });
1363
1590
  if (!ACTIVITY_TYPES.has(activityType)) {
1364
- 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"));
1365
1592
  }
1366
1593
  normalizeTextField(input, output, "activity_content", context, { required: true, maxLength: 1024, truncate: true });
1367
1594
  normalizeTextField(input, output, "user_id", context, { maxLength: 80, truncate: true });
1368
1595
  normalizeTextField(input, output, "user_name", context, { maxLength: 80, truncate: true });
1369
1596
  const userExtra = normalizeFallbackObjectField(input, output, "user_extra", context);
1370
1597
  if (stringifyCommunityJson(userExtra).length > 1024) {
1371
- validationError(
1598
+ validationError2(
1372
1599
  "community_object_too_long",
1373
1600
  "The compact user_extra object must not exceed 1024 UTF-16 code units.",
1374
1601
  fieldLocation(context, "user_extra")
@@ -1409,14 +1636,14 @@ function normalizeInteraction(input, context) {
1409
1636
  });
1410
1637
  normalizeTextField(input, output, "collect_time", context, { required: true, dateTime: true });
1411
1638
  if (!hasOwn(input, "metrics") || input.metrics === null) {
1412
- 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"));
1413
1640
  }
1414
1641
  output.metrics = normalizeMetrics(input.metrics, contentType, context, "metrics");
1415
1642
  return output;
1416
1643
  }
1417
1644
  function normalizeRecord(input, context) {
1418
1645
  if (!isObject(input)) {
1419
- 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);
1420
1647
  }
1421
1648
  switch (context.type) {
1422
1649
  case "post":
@@ -1439,7 +1666,7 @@ function normalizeRecord(input, context) {
1439
1666
  }
1440
1667
  function parseDataType(value, segment) {
1441
1668
  if (typeof value !== "string" || !ALL_DATA_TYPES.has(value)) {
1442
- validationError(
1669
+ validationError2(
1443
1670
  "community_invalid_data_type",
1444
1671
  "The segment data_type must be one of the eight supported community data types.",
1445
1672
  { segment, field: "data_type" }
@@ -1449,20 +1676,20 @@ function parseDataType(value, segment) {
1449
1676
  }
1450
1677
  function normalizeSegment(input, segment, channelId, zoneId, stats) {
1451
1678
  if (!isObject(input)) {
1452
- 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 });
1453
1680
  }
1454
1681
  if (!hasOwn(input, "data_type")) {
1455
- 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" });
1456
1683
  }
1457
1684
  if (!hasOwn(input, "data") || input.data === null) {
1458
- 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" });
1459
1686
  }
1460
1687
  const dataType = parseDataType(input.data_type, segment);
1461
1688
  const records = Array.isArray(input.data) ? input.data : [input.data];
1462
1689
  if (records.length === 0) {
1463
- 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" });
1464
1691
  }
1465
- const normalized = records.map((record, index) => normalizeRecord(record, {
1692
+ const normalized = records.map((record2, index) => normalizeRecord(record2, {
1466
1693
  type: dataType,
1467
1694
  channelId,
1468
1695
  zoneId,
@@ -1473,12 +1700,12 @@ function normalizeSegment(input, segment, channelId, zoneId, stats) {
1473
1700
  }
1474
1701
  function validateZoneId(value) {
1475
1702
  if (typeof value !== "string" || value.length === 0) {
1476
- 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" });
1477
1704
  }
1478
1705
  try {
1479
1706
  new Intl.DateTimeFormat("en-US", { timeZone: value }).format(0);
1480
1707
  } catch {
1481
- 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" });
1482
1709
  }
1483
1710
  return value;
1484
1711
  }
@@ -1490,7 +1717,7 @@ function normalizeCommunityReportInput(input) {
1490
1717
  const hasDataMode = input.dataType !== void 0 || input.data !== void 0;
1491
1718
  const hasPayloadMode = input.payload !== void 0;
1492
1719
  if (hasDataMode === hasPayloadMode) {
1493
- validationError(
1720
+ validationError2(
1494
1721
  "community_input_mode",
1495
1722
  "Use exactly one input mode: data_type with data, or payload.",
1496
1723
  { field: "data/payload" }
@@ -1499,7 +1726,7 @@ function normalizeCommunityReportInput(input) {
1499
1726
  let rawSegments;
1500
1727
  if (hasDataMode) {
1501
1728
  if (input.dataType === void 0 || input.data === void 0) {
1502
- validationError(
1729
+ validationError2(
1503
1730
  "community_input_mode",
1504
1731
  "The data_type and data fields must be supplied together.",
1505
1732
  { field: input.dataType === void 0 ? "data_type" : "data" }
@@ -1509,7 +1736,7 @@ function normalizeCommunityReportInput(input) {
1509
1736
  } else {
1510
1737
  rawSegments = Array.isArray(input.payload) ? input.payload : [input.payload];
1511
1738
  if (rawSegments.length === 0) {
1512
- 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" });
1513
1740
  }
1514
1741
  }
1515
1742
  const stats = new StatsCollector();
@@ -1686,7 +1913,7 @@ function resolveCommunityReportEndpoint(flagValue, environment = process.env) {
1686
1913
  }
1687
1914
  return endpoint.toString();
1688
1915
  }
1689
- function readCommunityReportInput(raw, field) {
1916
+ function readCommunityReportInput(raw, field2) {
1690
1917
  const trimmed = raw.trim();
1691
1918
  let text;
1692
1919
  try {
@@ -1704,8 +1931,8 @@ function readCommunityReportInput(raw, field) {
1704
1931
  "Unable to read the community JSON input.",
1705
1932
  {
1706
1933
  code: "community_input_read_failed",
1707
- hint: `Pass --${field} as inline JSON, an existing path, @path, or - for stdin.`,
1708
- location: { field }
1934
+ hint: `Pass --${field2} as inline JSON, an existing path, @path, or - for stdin.`,
1935
+ location: { field: field2 }
1709
1936
  }
1710
1937
  );
1711
1938
  }
@@ -1718,7 +1945,7 @@ function readCommunityReportInput(raw, field) {
1718
1945
  {
1719
1946
  code: error.code,
1720
1947
  hint: SCHEMA_VALIDATION_HINT,
1721
- location: { field }
1948
+ location: { field: field2 }
1722
1949
  }
1723
1950
  );
1724
1951
  }
@@ -1801,6 +2028,258 @@ function formatNormalization(stats) {
1801
2028
  };
1802
2029
  }
1803
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
+
1804
2283
  // src/commands/te-community/index.ts
1805
2284
  registerCapabilityGatewayRoute("community", { gatewayDomain: "community" });
1806
2285
  registerMcpMappings({
@@ -1808,8 +2287,7 @@ registerMcpMappings({
1808
2287
  "community_analysis": { componentName: "community", mappingPath: "analysis" },
1809
2288
  "community_hot": { componentName: "community", mappingPath: "hot" }
1810
2289
  });
1811
- var commands = [
1812
- communityDataReport,
2290
+ var communityReadCommands = [
1813
2291
  // Content commands
1814
2292
  getLivestreamList,
1815
2293
  getLivestreamDetail,
@@ -1833,6 +2311,20 @@ var commands = [
1833
2311
  getHotTopics,
1834
2312
  getTopicDetail
1835
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
+ ];
1836
2328
  var te_community_default = commands;
1837
2329
  export {
1838
2330
  te_community_default as default