gangtise-openapi-cli 0.10.10 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -112,6 +112,7 @@ cp -r gangtise-openapi ~/.hermes/skills/gangtise-openapi
112
112
  | | `foreign-report list` / `download` | 外资研报(含中文翻译下载) |
113
113
  | | `announcement list` / `download` | 公告(含 Markdown 下载) |
114
114
  | **Quote** | `day-kline` / `day-kline-hk` | A股/港股日K线 |
115
+ | | `index-day-kline` | 沪深京指数日K线 |
115
116
  | | `minute-kline` | A股分钟K线 |
116
117
  | **Fundamental** | `income-statement` / `balance-sheet` / `cash-flow` | 三大财务报表(累计) |
117
118
  | | `income-statement-quarterly` / `cash-flow-quarterly` | 利润表/现金流量表(单季度) |
@@ -135,6 +136,7 @@ cp -r gangtise-openapi ~/.hermes/skills/gangtise-openapi
135
136
  | **Vault** | `drive-list` / `drive-download` | 云盘文件列表与下载 |
136
137
  | | `record-list` / `record-download` | 录音速记列表与下载 |
137
138
  | | `my-conference-list` / `my-conference-download` | 我的会议列表与下载 |
139
+ | | `wechat-message-list` / `wechat-chatroom-list` | 群消息列表与群ID查询 |
138
140
  | **Raw** | `call` | 原始接口调用(可访问任意 endpoint) |
139
141
 
140
142
  ## 命令概览
@@ -187,6 +189,7 @@ gangtise ai knowledge-batch --query 比亚迪 --query 最近热门概念
187
189
  - `vault drive-list`
188
190
  - `vault record-list`
189
191
  - `vault my-conference-list`
192
+ - `vault wechat-message-list`
190
193
  - `ai hot-topic`
191
194
 
192
195
  规则:
@@ -252,7 +255,7 @@ gangtise insight roadshow list --institution C100000017
252
255
 
253
256
  ```bash
254
257
  gangtise quote day-kline --security 600519.SH --start-date 2026-03-01 --end-date 2026-03-31
255
- # 不传 --security 默认返回全市场,不传 --start-date 默认往前一年,不传 --end-date 默认最新
258
+ # 查最近/最新 K 线建议显式传 --start-date/--end-date;只传 --limit 会截取查询窗口开头,不等于最近N条
256
259
  gangtise quote day-kline --format json
257
260
  # 全市场查询(--security all)
258
261
  gangtise quote day-kline --security all --start-date 2026-04-01 --end-date 2026-04-01 --limit 100 --format json
@@ -260,6 +263,8 @@ gangtise quote day-kline --security all --start-date 2026-04-01 --end-date 2026-
260
263
  gangtise quote day-kline-hk --security 00700.HK --start-date 2026-03-01 --end-date 2026-03-31
261
264
  # 港股全市场
262
265
  gangtise quote day-kline-hk --security all --start-date 2026-04-01 --end-date 2026-04-01 --limit 100 --format json
266
+ # 沪深京指数日K线
267
+ gangtise quote index-day-kline --security 000001.SH --security 399001.SZ --start-date 2024-05-01 --end-date 2024-05-20 --field securityCode --field tradeDate --field close --field volume
263
268
  # A股分钟K线
264
269
  gangtise quote minute-kline --security 600519.SH --start-time "2026-04-15 09:30:00" --end-time "2026-04-15 15:00:00" --field open --field close --field volume
265
270
  ```
@@ -341,6 +346,10 @@ gangtise vault record-download --record-id 49412 --content-type summary
341
346
  gangtise vault my-conference-list --keyword AI --category earningsCall --institution C100000027
342
347
  # 我的会议下载(--content-type: asr/summary)
343
348
  gangtise vault my-conference-download --conference-id 43319 --content-type asr
349
+
350
+ # 群消息:先按群名称查群ID,再按群ID查消息
351
+ gangtise vault wechat-chatroom-list --room-name "AI学习群,投研分享群" --size 50
352
+ gangtise vault wechat-message-list --keyword AI应用 --wechat-group-id ueKEGyhdjFGkjyebh --category text --category url --tag roadShow --tag meetingSummary --size 50
344
353
  ```
345
354
 
346
355
  ### Raw
package/dist/src/cli.js CHANGED
@@ -3,8 +3,10 @@ import { Command, Option } from "commander";
3
3
  import { checkAsyncContent, pollAsyncContent, POLL_MAX_ATTEMPTS } from "./core/asyncContent.js";
4
4
  import { readTokenCache } from "./core/auth.js";
5
5
  import { collectKeyValue, collectList, collectNumberList, maybeArray, parseFrom, parseNumberOption, parseOptionalNumberOption, parseSize, parseTimestamp13 } from "./core/args.js";
6
+ import { buildQuoteKlineBody, buildWechatChatroomListBody, buildWechatMessageListBody } from "./core/commandBodies.js";
6
7
  import { loadConfig } from "./core/config.js";
7
8
  import { resolveTitle, saveDownloadResult } from "./core/download.js";
9
+ import { ENDPOINTS } from "./core/endpoints.js";
8
10
  import { ApiError, ConfigError } from "./core/errors.js";
9
11
  import { normalizeRows } from "./core/normalize.js";
10
12
  import { parseOutputFormat } from "./core/output.js";
@@ -185,11 +187,15 @@ program.addCommand(insight);
185
187
  const quote = new Command("quote").description("Quote APIs");
186
188
  quote.command("day-kline").option("--security <code>", "Security code (A-share: .SH/.SZ/.BJ, or 'all' for full market)", collectList, []).option("--start-date <date>", "Start date (default: 1 year before end-date)").option("--end-date <date>", "End date (default: latest)").option("--limit <number>", "Max rows per request (default: 6000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
187
189
  const client = await createClient();
188
- await printData(await client.call("quote.day-kline", { securityList: maybeArray(options.security), startDate: options.startDate, endDate: options.endDate, limit: parseOptionalNumberOption(options.limit, "--limit", { integer: true, min: 1 }), fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
190
+ await printData(await client.call("quote.day-kline", buildQuoteKlineBody(options)), parseOutputFormat(options.format), options.output);
189
191
  });
190
192
  quote.command("day-kline-hk").option("--security <code>", "Security code (HK stock: .HK, or 'all' for full market)", collectList, []).option("--start-date <date>", "Start date (default: 1 year before end-date)").option("--end-date <date>", "End date (default: latest)").option("--limit <number>", "Max rows per request (default: 6000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
191
193
  const client = await createClient();
192
- await printData(await client.call("quote.day-kline-hk", { securityList: maybeArray(options.security), startDate: options.startDate, endDate: options.endDate, limit: parseOptionalNumberOption(options.limit, "--limit", { integer: true, min: 1 }), fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
194
+ await printData(await client.call("quote.day-kline-hk", buildQuoteKlineBody(options)), parseOutputFormat(options.format), options.output);
195
+ });
196
+ quote.command("index-day-kline").option("--security <code>", "Index code (.SH/.SZ/.BJ, or 'all' for full market)", collectList, []).option("--start-date <date>", "Start date (default: 1 year before end-date)").option("--end-date <date>", "End date (default: latest)").option("--limit <number>", "Max rows per request (default: 6000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
197
+ const client = await createClient();
198
+ await printData(await client.call("quote.index-day-kline", buildQuoteKlineBody(options)), parseOutputFormat(options.format), options.output);
193
199
  });
194
200
  quote.command("minute-kline").option("--security <code>", "Security code (A-share only: .SH/.SZ/.BJ)").option("--start-time <datetime>", "Start time (yyyy-MM-dd HH:mm:ss)").option("--end-time <datetime>", "End time (yyyy-MM-dd HH:mm:ss)").option("--limit <number>", "Max rows per request (default: 5000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
195
201
  const client = await createClient();
@@ -197,26 +203,15 @@ quote.command("minute-kline").option("--security <code>", "Security code (A-shar
197
203
  });
198
204
  program.addCommand(quote);
199
205
  const fundamental = new Command("fundamental").description("Fundamental APIs");
200
- fundamental.command("income-statement").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--fiscal-year <year>", "Fiscal year", collectList, []).option("--period <period>", "Period", collectList, []).option("--report-type <type>", "Report type", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
201
- const client = await createClient();
202
- await printData(await client.call("fundamental.income-statement", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, fiscalYear: maybeArray(options.fiscalYear), period: options.period.length ? options.period : undefined, reportType: options.reportType.length ? options.reportType : undefined, fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
203
- });
204
- fundamental.command("income-statement-quarterly").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--fiscal-year <year>", "Fiscal year", collectList, []).option("--period <period>", "Period: q1/q2/q3/q4/latest", collectList, []).option("--report-type <type>", "Report type", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
205
- const client = await createClient();
206
- await printData(await client.call("fundamental.income-statement-quarterly", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, fiscalYear: maybeArray(options.fiscalYear), period: options.period.length ? options.period : undefined, reportType: options.reportType.length ? options.reportType : undefined, fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
207
- });
208
- fundamental.command("balance-sheet").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--fiscal-year <year>", "Fiscal year", collectList, []).option("--period <period>", "Period", collectList, []).option("--report-type <type>", "Report type", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
206
+ const addFinancialReport = (name, endpointKey, periodHelp = "Period") => fundamental.command(name).requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--fiscal-year <year>", "Fiscal year", collectList, []).option("--period <period>", periodHelp, collectList, []).option("--report-type <type>", "Report type", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
209
207
  const client = await createClient();
210
- await printData(await client.call("fundamental.balance-sheet", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, fiscalYear: maybeArray(options.fiscalYear), period: options.period.length ? options.period : undefined, reportType: options.reportType.length ? options.reportType : undefined, fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
211
- });
212
- fundamental.command("cash-flow").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--fiscal-year <year>", "Fiscal year", collectList, []).option("--period <period>", "Period", collectList, []).option("--report-type <type>", "Report type", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
213
- const client = await createClient();
214
- await printData(await client.call("fundamental.cash-flow", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, fiscalYear: maybeArray(options.fiscalYear), period: options.period.length ? options.period : undefined, reportType: options.reportType.length ? options.reportType : undefined, fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
215
- });
216
- fundamental.command("cash-flow-quarterly").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--fiscal-year <year>", "Fiscal year", collectList, []).option("--period <period>", "Period: q1/q2/q3/q4/latest", collectList, []).option("--report-type <type>", "Report type", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
217
- const client = await createClient();
218
- await printData(await client.call("fundamental.cash-flow-quarterly", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, fiscalYear: maybeArray(options.fiscalYear), period: options.period.length ? options.period : undefined, reportType: options.reportType.length ? options.reportType : undefined, fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
208
+ await printData(await client.call(endpointKey, { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, fiscalYear: maybeArray(options.fiscalYear), period: options.period.length ? options.period : undefined, reportType: options.reportType.length ? options.reportType : undefined, fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
219
209
  });
210
+ addFinancialReport("income-statement", "fundamental.income-statement");
211
+ addFinancialReport("income-statement-quarterly", "fundamental.income-statement-quarterly", "Period: q1/q2/q3/q4/latest");
212
+ addFinancialReport("balance-sheet", "fundamental.balance-sheet");
213
+ addFinancialReport("cash-flow", "fundamental.cash-flow");
214
+ addFinancialReport("cash-flow-quarterly", "fundamental.cash-flow-quarterly", "Period: q1/q2/q3/q4/latest");
220
215
  fundamental.command("main-business").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").addOption(new Option("--breakdown <type>", "Breakdown: product/industry/region").choices(["product", "industry", "region"]).default("product")).option("--period <type>", "Period: interim/annual", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
221
216
  const client = await createClient();
222
217
  await printData(await client.call("fundamental.main-business", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, breakdown: options.breakdown, periodList: maybeArray(options.period), fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
@@ -394,9 +389,21 @@ vault.command("my-conference-download").requiredOption("--conference-id <id>").r
394
389
  const title = options.output ? undefined : await resolveTitle(client, result, "vault.my-conference.list", "conferenceId", options.conferenceId);
395
390
  await saveDownloadResult(result, `conference-${options.conferenceId}`, options.output ?? title);
396
391
  });
392
+ vault.command("wechat-message-list").option("--from <number>", "Starting offset", "0").option("--size <number>", "Total rows to return; omit to fetch all").option("--start-time <datetime>").option("--end-time <datetime>").option("--keyword <text>").option("--wechat-group-id <id>", "WeChat group ID", collectList, []).option("--industry <id>", "Industry ID", collectList, []).option("--category <name>", "Message type: text/image/documents/url", collectList, []).option("--tag <name>", "Tag: roadShow/research/strategyMeeting/meetingSummary/industryComment/companyComment/earningsReview", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
393
+ const client = await createClient();
394
+ await printData(await client.call("vault.wechat-message.list", buildWechatMessageListBody(options)), parseOutputFormat(options.format), options.output);
395
+ });
396
+ vault.command("wechat-chatroom-list").option("--from <number>", "Starting offset", "0").option("--size <number>", "Rows to return", "20").option("--room-name <name>", "WeChat group name; repeat or comma-separate for multiple names", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
397
+ const client = await createClient();
398
+ await printData(await client.call("vault.wechat-chatroom.list", buildWechatChatroomListBody(options)), parseOutputFormat(options.format), options.output);
399
+ });
397
400
  program.addCommand(vault);
398
401
  program.addCommand(ai);
399
402
  program.command("raw").description("Raw API calls").addCommand(new Command("call").argument("<endpointKey>").option("--body <json>").option("--query <key=value>", "Query string pair", collectKeyValue, {}).option("--format <format>", "Output format", "json").option("--output <path>").action(async (endpointKey, options) => {
403
+ const endpoint = ENDPOINTS[endpointKey];
404
+ if (!endpoint) {
405
+ throw new ConfigError(`Unknown endpoint key: ${endpointKey}`);
406
+ }
400
407
  const client = await createClient();
401
408
  let body;
402
409
  if (options.body) {
@@ -408,13 +415,39 @@ program.command("raw").description("Raw API calls").addCommand(new Command("call
408
415
  }
409
416
  }
410
417
  const data = await client.call(endpointKey, body, options.query);
411
- if (data && typeof data === "object" && "data" in data && data.data instanceof Uint8Array) {
418
+ if (endpoint.kind === "download") {
412
419
  await saveDownloadResult(data, "download.bin", options.output);
413
420
  return;
414
421
  }
415
422
  await printData(data, parseOutputFormat(options.format), options.output);
416
423
  }));
424
+ async function checkForUpdate(timeoutMs = 2000) {
425
+ const https = await import("node:https");
426
+ await new Promise((resolve) => {
427
+ const req = https.get("https://registry.npmjs.org/gangtise-openapi-cli/latest", (res) => {
428
+ let body = "";
429
+ res.on("data", (chunk) => { body += chunk; });
430
+ res.on("end", () => {
431
+ try {
432
+ const latest = JSON.parse(body).version;
433
+ if (latest && latest !== CLI_VERSION) {
434
+ process.stderr.write(`Update available: ${CLI_VERSION} → ${latest}\nRun: npm update -g gangtise-openapi-cli\n`);
435
+ }
436
+ }
437
+ catch { /* ignore */ }
438
+ resolve();
439
+ });
440
+ });
441
+ req.on("error", () => resolve());
442
+ req.setTimeout(timeoutMs, () => { req.destroy(); resolve(); });
443
+ });
444
+ }
417
445
  async function main() {
446
+ if (process.argv.includes("--version") || process.argv.includes("-V")) {
447
+ process.stdout.write(`${CLI_VERSION}\n`);
448
+ await checkForUpdate();
449
+ return;
450
+ }
418
451
  try {
419
452
  await program.parseAsync(process.argv);
420
453
  }
@@ -435,23 +468,3 @@ async function main() {
435
468
  }
436
469
  }
437
470
  void main();
438
- // Background update check on --version
439
- if (process.argv.includes("--version") || process.argv.includes("-V")) {
440
- import("node:https").then((https) => {
441
- const req = https.get("https://registry.npmjs.org/gangtise-openapi-cli/latest", (res) => {
442
- let body = "";
443
- res.on("data", (chunk) => { body += chunk; });
444
- res.on("end", () => {
445
- try {
446
- const latest = JSON.parse(body).version;
447
- if (latest && latest !== CLI_VERSION) {
448
- process.stderr.write(`\nUpdate available: ${CLI_VERSION} → ${latest}\nRun: npm update -g gangtise-openapi-cli\n`);
449
- }
450
- }
451
- catch { /* ignore */ }
452
- });
453
- });
454
- req.on("error", () => { });
455
- req.setTimeout(3000, () => { req.destroy(); });
456
- }).catch(() => { });
457
- }
@@ -10,10 +10,7 @@ export async function readTokenCache(filePath) {
10
10
  }
11
11
  return null;
12
12
  }
13
- catch (error) {
14
- if (error.code === "ENOENT") {
15
- return null;
16
- }
13
+ catch {
17
14
  return null;
18
15
  }
19
16
  }
@@ -1,7 +1,7 @@
1
1
  import { request } from "undici";
2
2
  import { isTokenCacheValid, normalizeToken, readTokenCache, requireAccessCredentials, writeTokenCache } from "./auth.js";
3
3
  import { ApiError, ValidationError } from "./errors.js";
4
- import { ENDPOINTS, ENDPOINT_REGISTRY } from "./endpoints.js";
4
+ import { ENDPOINTS } from "./endpoints.js";
5
5
  import { getLookupData } from "./lookupData/index.js";
6
6
  export class GangtiseClient {
7
7
  config;
@@ -24,7 +24,7 @@ export class GangtiseClient {
24
24
  }
25
25
  async doTokenRefresh() {
26
26
  const credentials = requireAccessCredentials(this.config.accessKey, this.config.secretKey);
27
- const envelope = await this.requestJson(ENDPOINTS.authLogin, {
27
+ const envelope = await this.requestJson(ENDPOINTS["auth.login"], {
28
28
  accessKey: credentials.accessKey,
29
29
  secretKey: credentials.secretKey,
30
30
  }, false);
@@ -38,7 +38,12 @@ export class GangtiseClient {
38
38
  return accessToken;
39
39
  }
40
40
  isEnvelope(parsed) {
41
- return Boolean(parsed && typeof parsed === 'object' && 'code' in parsed);
41
+ if (!parsed || typeof parsed !== 'object')
42
+ return false;
43
+ const obj = parsed;
44
+ if (!('code' in obj))
45
+ return false;
46
+ return 'msg' in obj || 'data' in obj || 'success' in obj || 'status' in obj;
42
47
  }
43
48
  throwHttpError(parsed, statusCode) {
44
49
  if (this.isEnvelope(parsed)) {
@@ -251,7 +256,7 @@ export class GangtiseClient {
251
256
  };
252
257
  }
253
258
  async call(endpointKey, body, query) {
254
- const endpoint = ENDPOINT_REGISTRY[endpointKey];
259
+ const endpoint = ENDPOINTS[endpointKey];
255
260
  if (!endpoint) {
256
261
  throw new ApiError(`Unknown endpoint key: ${endpointKey}`);
257
262
  }
@@ -0,0 +1,30 @@
1
+ import { maybeArray, parseFrom, parseOptionalNumberOption, parseSize } from "./args.js";
2
+ export function buildQuoteKlineBody(options) {
3
+ return {
4
+ securityList: maybeArray(options.security),
5
+ startDate: options.startDate,
6
+ endDate: options.endDate,
7
+ limit: parseOptionalNumberOption(options.limit, "--limit", { integer: true, min: 1 }),
8
+ fieldList: maybeArray(options.field),
9
+ };
10
+ }
11
+ export function buildWechatMessageListBody(options) {
12
+ return {
13
+ from: parseFrom(options.from),
14
+ size: parseSize(options.size),
15
+ startTime: options.startTime,
16
+ endTime: options.endTime,
17
+ keyword: options.keyword,
18
+ wechatGroupIdList: maybeArray(options.wechatGroupId),
19
+ industryIdList: maybeArray(options.industry),
20
+ categoryList: maybeArray(options.category),
21
+ tagList: maybeArray(options.tag),
22
+ };
23
+ }
24
+ export function buildWechatChatroomListBody(options) {
25
+ return {
26
+ from: parseFrom(options.from),
27
+ size: parseSize(options.size),
28
+ roomName: options.roomName.length > 0 ? options.roomName.join(",") : undefined,
29
+ };
30
+ }
@@ -1,68 +1,71 @@
1
1
  export const ENDPOINTS = {
2
- authLogin: {
2
+ // ─── auth ───
3
+ "auth.login": {
3
4
  key: "auth.login",
4
5
  method: "POST",
5
6
  path: "/application/auth/oauth/open/loginV2",
6
7
  kind: "json",
7
8
  description: "Get access token",
8
9
  },
9
- lookupResearchAreas: {
10
+ // ─── lookup (served from local data, not HTTP) ───
11
+ "lookup.research-areas.list": {
10
12
  key: "lookup.research-areas.list",
11
13
  method: "GET",
12
14
  path: "/guide/research-area-local",
13
15
  kind: "json",
14
16
  description: "List research areas from local docs",
15
17
  },
16
- lookupBrokerOrgs: {
18
+ "lookup.broker-orgs.list": {
17
19
  key: "lookup.broker-orgs.list",
18
20
  method: "GET",
19
21
  path: "/guide/broker-orgs-local",
20
22
  kind: "json",
21
23
  description: "List broker orgs from local docs",
22
24
  },
23
- lookupMeetingOrgs: {
25
+ "lookup.meeting-orgs.list": {
24
26
  key: "lookup.meeting-orgs.list",
25
27
  method: "GET",
26
28
  path: "/guide/meeting-orgs-local",
27
29
  kind: "json",
28
30
  description: "List meeting orgs from local docs",
29
31
  },
30
- lookupIndustries: {
32
+ "lookup.industries.list": {
31
33
  key: "lookup.industries.list",
32
34
  method: "GET",
33
35
  path: "/guide/industries-local",
34
36
  kind: "json",
35
37
  description: "List industries from local docs",
36
38
  },
37
- lookupRegions: {
39
+ "lookup.regions.list": {
38
40
  key: "lookup.regions.list",
39
41
  method: "GET",
40
42
  path: "/guide/regions-local",
41
43
  kind: "json",
42
44
  description: "List regions from local docs",
43
45
  },
44
- lookupAnnouncementCategories: {
46
+ "lookup.announcement-categories.list": {
45
47
  key: "lookup.announcement-categories.list",
46
48
  method: "GET",
47
49
  path: "/guide/announcement-categories-local",
48
50
  kind: "json",
49
51
  description: "List announcement categories from local docs",
50
52
  },
51
- lookupIndustryCodes: {
53
+ "lookup.industry-codes.list": {
52
54
  key: "lookup.industry-codes.list",
53
55
  method: "GET",
54
56
  path: "/guide/industry-codes-local",
55
57
  kind: "json",
56
58
  description: "List Shenwan industry codes from local docs",
57
59
  },
58
- lookupThemeIds: {
60
+ "lookup.theme-ids.list": {
59
61
  key: "lookup.theme-ids.list",
60
62
  method: "GET",
61
63
  path: "/guide/theme-ids-local",
62
64
  kind: "json",
63
65
  description: "List theme IDs from local docs",
64
66
  },
65
- insightOpinionList: {
67
+ // ─── insight ───
68
+ "insight.opinion.list": {
66
69
  key: "insight.opinion.list",
67
70
  method: "POST",
68
71
  path: "/application/open-insight/chief-opinion/getList",
@@ -70,7 +73,7 @@ export const ENDPOINTS = {
70
73
  description: "List chief opinions",
71
74
  pagination: { enabled: true, maxPageSize: 50 },
72
75
  },
73
- insightSummaryList: {
76
+ "insight.summary.list": {
74
77
  key: "insight.summary.list",
75
78
  method: "POST",
76
79
  path: "/application/open-insight/summary/v2/getList",
@@ -78,14 +81,14 @@ export const ENDPOINTS = {
78
81
  description: "List summaries",
79
82
  pagination: { enabled: true, maxPageSize: 50 },
80
83
  },
81
- insightSummaryDownload: {
84
+ "insight.summary.download": {
82
85
  key: "insight.summary.download",
83
86
  method: "GET",
84
87
  path: "/application/open-insight/summary/v2/download/file",
85
88
  kind: "download",
86
89
  description: "Download summary file",
87
90
  },
88
- insightRoadshowList: {
91
+ "insight.roadshow.list": {
89
92
  key: "insight.roadshow.list",
90
93
  method: "POST",
91
94
  path: "/application/open-insight/schedule/roadshow/getList",
@@ -93,7 +96,7 @@ export const ENDPOINTS = {
93
96
  description: "List roadshows",
94
97
  pagination: { enabled: true, maxPageSize: 50 },
95
98
  },
96
- insightSiteVisitList: {
99
+ "insight.site-visit.list": {
97
100
  key: "insight.site-visit.list",
98
101
  method: "POST",
99
102
  path: "/application/open-insight/schedule/site-visit/getList",
@@ -101,7 +104,7 @@ export const ENDPOINTS = {
101
104
  description: "List site visits",
102
105
  pagination: { enabled: true, maxPageSize: 50 },
103
106
  },
104
- insightStrategyList: {
107
+ "insight.strategy.list": {
105
108
  key: "insight.strategy.list",
106
109
  method: "POST",
107
110
  path: "/application/open-insight/schedule/strategy-meeting/getList",
@@ -109,7 +112,7 @@ export const ENDPOINTS = {
109
112
  description: "List strategy meetings",
110
113
  pagination: { enabled: true, maxPageSize: 50 },
111
114
  },
112
- insightForumList: {
115
+ "insight.forum.list": {
113
116
  key: "insight.forum.list",
114
117
  method: "POST",
115
118
  path: "/application/open-insight/schedule/forum/getList",
@@ -117,7 +120,7 @@ export const ENDPOINTS = {
117
120
  description: "List forums",
118
121
  pagination: { enabled: true, maxPageSize: 50 },
119
122
  },
120
- insightResearchList: {
123
+ "insight.research.list": {
121
124
  key: "insight.research.list",
122
125
  method: "POST",
123
126
  path: "/application/open-insight/broker-report/getList",
@@ -125,14 +128,14 @@ export const ENDPOINTS = {
125
128
  description: "List broker research reports",
126
129
  pagination: { enabled: true, maxPageSize: 50 },
127
130
  },
128
- insightResearchDownload: {
131
+ "insight.research.download": {
129
132
  key: "insight.research.download",
130
133
  method: "GET",
131
134
  path: "/application/open-insight/broker-report/download/file",
132
135
  kind: "download",
133
136
  description: "Download broker research report",
134
137
  },
135
- insightForeignReportList: {
138
+ "insight.foreign-report.list": {
136
139
  key: "insight.foreign-report.list",
137
140
  method: "POST",
138
141
  path: "/application/open-insight/foreign-report/getList",
@@ -140,14 +143,14 @@ export const ENDPOINTS = {
140
143
  description: "List foreign reports",
141
144
  pagination: { enabled: true, maxPageSize: 50 },
142
145
  },
143
- insightForeignReportDownload: {
146
+ "insight.foreign-report.download": {
144
147
  key: "insight.foreign-report.download",
145
148
  method: "GET",
146
149
  path: "/application/open-insight/foreign-report/download/file",
147
150
  kind: "download",
148
151
  description: "Download foreign report",
149
152
  },
150
- insightAnnouncementList: {
153
+ "insight.announcement.list": {
151
154
  key: "insight.announcement.list",
152
155
  method: "POST",
153
156
  path: "/application/open-insight/announcement/getList",
@@ -155,91 +158,122 @@ export const ENDPOINTS = {
155
158
  description: "List announcements",
156
159
  pagination: { enabled: true, maxPageSize: 50 },
157
160
  },
158
- insightAnnouncementDownload: {
161
+ "insight.announcement.download": {
159
162
  key: "insight.announcement.download",
160
163
  method: "GET",
161
164
  path: "/application/open-insight/announcement/download/file",
162
165
  kind: "download",
163
166
  description: "Download announcement file",
164
167
  },
165
- quoteDayKline: {
168
+ // ─── quote ───
169
+ "quote.day-kline": {
166
170
  key: "quote.day-kline",
167
171
  method: "POST",
168
172
  path: "/application/open-quote/kline/daily",
169
173
  kind: "json",
170
174
  description: "Query A-share daily kline (SH/SZ/BJ)",
171
175
  },
172
- quoteDayKlineHk: {
176
+ "quote.day-kline-hk": {
173
177
  key: "quote.day-kline-hk",
174
178
  method: "POST",
175
179
  path: "/application/open-quote/kline-hk/daily",
176
180
  kind: "json",
177
181
  description: "Query HK stock daily kline (HK)",
178
182
  },
179
- fundamentalIncomeStatement: {
183
+ "quote.index-day-kline": {
184
+ key: "quote.index-day-kline",
185
+ method: "POST",
186
+ path: "/application/open-quote/index/kline/daily",
187
+ kind: "json",
188
+ description: "Query SH/SZ/BJ index daily kline",
189
+ },
190
+ "quote.minute-kline": {
191
+ key: "quote.minute-kline",
192
+ method: "POST",
193
+ path: "/application/open-quote/kline/minute",
194
+ kind: "json",
195
+ description: "Query A-share minute kline (SH/SZ/BJ)",
196
+ },
197
+ // ─── fundamental ───
198
+ "fundamental.income-statement": {
180
199
  key: "fundamental.income-statement",
181
200
  method: "POST",
182
201
  path: "/application/open-fundamental/financial-report/income-statement/accumulated",
183
202
  kind: "json",
184
203
  description: "Query income statement (accumulated)",
185
204
  },
186
- fundamentalBalanceSheet: {
205
+ "fundamental.income-statement-quarterly": {
206
+ key: "fundamental.income-statement-quarterly",
207
+ method: "POST",
208
+ path: "/application/open-fundamental/financial-report/income-statement/quarterly",
209
+ kind: "json",
210
+ description: "Query income statement (quarterly)",
211
+ },
212
+ "fundamental.balance-sheet": {
187
213
  key: "fundamental.balance-sheet",
188
214
  method: "POST",
189
215
  path: "/application/open-fundamental/financial-report/balance-sheet/accumulated",
190
216
  kind: "json",
191
217
  description: "Query balance sheet (accumulated)",
192
218
  },
193
- fundamentalCashFlow: {
219
+ "fundamental.cash-flow": {
194
220
  key: "fundamental.cash-flow",
195
221
  method: "POST",
196
222
  path: "/application/open-fundamental/financial-report/cash-flow-statement/accumulated",
197
223
  kind: "json",
198
224
  description: "Query cash flow statement (accumulated)",
199
225
  },
200
- fundamentalMainBusiness: {
201
- key: "fundamental.main-business",
226
+ "fundamental.cash-flow-quarterly": {
227
+ key: "fundamental.cash-flow-quarterly",
202
228
  method: "POST",
203
- path: "/application/open-fundamental/main-business",
229
+ path: "/application/open-fundamental/financial-report/cash-flow-statement/quarterly",
204
230
  kind: "json",
205
- description: "Query main business composition",
231
+ description: "Query cash flow statement (quarterly)",
206
232
  },
207
- fundamentalEarningForecast: {
208
- key: "fundamental.earning-forecast",
233
+ "fundamental.main-business": {
234
+ key: "fundamental.main-business",
209
235
  method: "POST",
210
- path: "/application/open-fundamental/earning-forecast",
236
+ path: "/application/open-fundamental/main-business",
211
237
  kind: "json",
212
- description: "Query earning forecast (consensus estimates)",
238
+ description: "Query main business composition",
213
239
  },
214
- fundamentalValuationAnalysis: {
240
+ "fundamental.valuation-analysis": {
215
241
  key: "fundamental.valuation-analysis",
216
242
  method: "POST",
217
243
  path: "/application/open-fundamental/valuation-analysis",
218
244
  kind: "json",
219
245
  description: "Query valuation analysis",
220
246
  },
221
- fundamentalTopHolders: {
247
+ "fundamental.top-holders": {
222
248
  key: "fundamental.top-holders",
223
249
  method: "POST",
224
250
  path: "/application/open-fundamental/capital-structure/top-holders",
225
251
  kind: "json",
226
252
  description: "Query top holders (top10 / top10 float)",
227
253
  },
228
- aiKnowledgeBatch: {
254
+ "fundamental.earning-forecast": {
255
+ key: "fundamental.earning-forecast",
256
+ method: "POST",
257
+ path: "/application/open-fundamental/earning-forecast",
258
+ kind: "json",
259
+ description: "Query earning forecast (consensus estimates)",
260
+ },
261
+ // ─── ai ───
262
+ "ai.knowledge-batch": {
229
263
  key: "ai.knowledge-batch",
230
264
  method: "POST",
231
265
  path: "/application/open-data/ai/search/knowledge/batch",
232
266
  kind: "json",
233
267
  description: "Batch knowledge search",
234
268
  },
235
- aiKnowledgeResource: {
269
+ "ai.knowledge-resource.download": {
236
270
  key: "ai.knowledge-resource.download",
237
271
  method: "GET",
238
272
  path: "/application/open-data/ai/resource/download",
239
273
  kind: "download",
240
274
  description: "Download knowledge resource",
241
275
  },
242
- aiSecurityClue: {
276
+ "ai.security-clue.list": {
243
277
  key: "ai.security-clue.list",
244
278
  method: "POST",
245
279
  path: "/application/open-ai/security-clue/getList",
@@ -247,56 +281,56 @@ export const ENDPOINTS = {
247
281
  description: "List security clues",
248
282
  pagination: { enabled: true, maxPageSize: 500 },
249
283
  },
250
- aiOnePager: {
284
+ "ai.one-pager": {
251
285
  key: "ai.one-pager",
252
286
  method: "POST",
253
287
  path: "/application/open-ai/agent/one-pager",
254
288
  kind: "json",
255
289
  description: "Generate one pager",
256
290
  },
257
- aiInvestmentLogic: {
291
+ "ai.investment-logic": {
258
292
  key: "ai.investment-logic",
259
293
  method: "POST",
260
294
  path: "/application/open-ai/agent/investment-logic",
261
295
  kind: "json",
262
296
  description: "Generate investment logic",
263
297
  },
264
- aiPeerComparison: {
298
+ "ai.peer-comparison": {
265
299
  key: "ai.peer-comparison",
266
300
  method: "POST",
267
301
  path: "/application/open-ai/agent/peer-comparison",
268
302
  kind: "json",
269
303
  description: "Generate peer comparison",
270
304
  },
271
- aiEarningsReviewGetId: {
305
+ "ai.earnings-review.get-id": {
272
306
  key: "ai.earnings-review.get-id",
273
307
  method: "POST",
274
308
  path: "/application/open-ai/agent/earnings-review-getid",
275
309
  kind: "json",
276
310
  description: "Get earnings review ID",
277
311
  },
278
- aiEarningsReviewGetContent: {
312
+ "ai.earnings-review.get-content": {
279
313
  key: "ai.earnings-review.get-content",
280
314
  method: "POST",
281
315
  path: "/application/open-ai/agent/earnings-review-getcontent",
282
316
  kind: "json",
283
317
  description: "Get earnings review content",
284
318
  },
285
- aiThemeTracking: {
319
+ "ai.theme-tracking": {
286
320
  key: "ai.theme-tracking",
287
321
  method: "POST",
288
322
  path: "/application/open-ai/agent/theme-tracking",
289
323
  kind: "json",
290
324
  description: "Get theme tracking daily report",
291
325
  },
292
- aiResearchOutline: {
326
+ "ai.research-outline": {
293
327
  key: "ai.research-outline",
294
328
  method: "POST",
295
329
  path: "/application/open-ai/agent/research-outline",
296
330
  kind: "json",
297
331
  description: "Get company research outline",
298
332
  },
299
- aiHotTopic: {
333
+ "ai.hot-topic": {
300
334
  key: "ai.hot-topic",
301
335
  method: "POST",
302
336
  path: "/application/open-ai/hot-topic/getList",
@@ -304,56 +338,36 @@ export const ENDPOINTS = {
304
338
  description: "List hot topic reports",
305
339
  pagination: { enabled: true, maxPageSize: 20 },
306
340
  },
307
- aiManagementDiscussAnnouncement: {
341
+ "ai.management-discuss-announcement": {
308
342
  key: "ai.management-discuss-announcement",
309
343
  method: "POST",
310
344
  path: "/application/open-ai/management-discuss/from-announcement",
311
345
  kind: "json",
312
346
  description: "Management discussion from financial reports (half-year/annual)",
313
347
  },
314
- aiManagementDiscussEarningsCall: {
348
+ "ai.management-discuss-earnings-call": {
315
349
  key: "ai.management-discuss-earnings-call",
316
350
  method: "POST",
317
351
  path: "/application/open-ai/management-discuss/from-earningsCall",
318
352
  kind: "json",
319
353
  description: "Management discussion from earnings calls",
320
354
  },
321
- aiViewpointDebateGetId: {
355
+ "ai.viewpoint-debate.get-id": {
322
356
  key: "ai.viewpoint-debate.get-id",
323
357
  method: "POST",
324
358
  path: "/application/open-ai/agent/viewpoint-debate-getid",
325
359
  kind: "json",
326
360
  description: "Get viewpoint debate ID",
327
361
  },
328
- aiViewpointDebateGetContent: {
362
+ "ai.viewpoint-debate.get-content": {
329
363
  key: "ai.viewpoint-debate.get-content",
330
364
  method: "POST",
331
365
  path: "/application/open-ai/agent/viewpoint-debate-getcontent",
332
366
  kind: "json",
333
367
  description: "Get viewpoint debate content",
334
368
  },
335
- quoteMinuteKline: {
336
- key: "quote.minute-kline",
337
- method: "POST",
338
- path: "/application/open-quote/kline/minute",
339
- kind: "json",
340
- description: "Query A-share minute kline (SH/SZ/BJ)",
341
- },
342
- fundamentalIncomeStatementQuarterly: {
343
- key: "fundamental.income-statement-quarterly",
344
- method: "POST",
345
- path: "/application/open-fundamental/financial-report/income-statement/quarterly",
346
- kind: "json",
347
- description: "Query income statement (quarterly)",
348
- },
349
- fundamentalCashFlowQuarterly: {
350
- key: "fundamental.cash-flow-quarterly",
351
- method: "POST",
352
- path: "/application/open-fundamental/financial-report/cash-flow-statement/quarterly",
353
- kind: "json",
354
- description: "Query cash flow statement (quarterly)",
355
- },
356
- vaultDriveList: {
369
+ // ─── vault ───
370
+ "vault.drive.list": {
357
371
  key: "vault.drive.list",
358
372
  method: "POST",
359
373
  path: "/application/open-vault/drive/getList",
@@ -361,14 +375,14 @@ export const ENDPOINTS = {
361
375
  description: "List vault drive files",
362
376
  pagination: { enabled: true, maxPageSize: 50 },
363
377
  },
364
- vaultDriveDownload: {
378
+ "vault.drive.download": {
365
379
  key: "vault.drive.download",
366
380
  method: "GET",
367
381
  path: "/application/open-vault/drive/download/file",
368
382
  kind: "download",
369
383
  description: "Download vault drive file",
370
384
  },
371
- vaultRecordList: {
385
+ "vault.record.list": {
372
386
  key: "vault.record.list",
373
387
  method: "POST",
374
388
  path: "/application/open-vault/record/getList",
@@ -376,14 +390,14 @@ export const ENDPOINTS = {
376
390
  description: "List voice recording transcriptions",
377
391
  pagination: { enabled: true, maxPageSize: 50 },
378
392
  },
379
- vaultRecordDownload: {
393
+ "vault.record.download": {
380
394
  key: "vault.record.download",
381
395
  method: "GET",
382
396
  path: "/application/open-vault/record/download/file",
383
397
  kind: "download",
384
398
  description: "Download voice recording transcription file",
385
399
  },
386
- vaultMyConferenceList: {
400
+ "vault.my-conference.list": {
387
401
  key: "vault.my-conference.list",
388
402
  method: "POST",
389
403
  path: "/application/open-vault/my-conference/getList",
@@ -391,15 +405,26 @@ export const ENDPOINTS = {
391
405
  description: "List my conferences",
392
406
  pagination: { enabled: true, maxPageSize: 50 },
393
407
  },
394
- vaultMyConferenceDownload: {
408
+ "vault.my-conference.download": {
395
409
  key: "vault.my-conference.download",
396
410
  method: "GET",
397
411
  path: "/application/open-vault/my-conference/download/file",
398
412
  kind: "download",
399
413
  description: "Download my conference resource",
400
414
  },
415
+ "vault.wechat-message.list": {
416
+ key: "vault.wechat-message.list",
417
+ method: "POST",
418
+ path: "/application/open-vault/wechatgroupmsg/list",
419
+ kind: "json",
420
+ description: "List WeChat group messages",
421
+ pagination: { enabled: true, maxPageSize: 50 },
422
+ },
423
+ "vault.wechat-chatroom.list": {
424
+ key: "vault.wechat-chatroom.list",
425
+ method: "POST",
426
+ path: "/application/open-vault/wechatgroupmsg/chatroomId",
427
+ kind: "json",
428
+ description: "List WeChat group chatroom IDs",
429
+ },
401
430
  };
402
- export const ENDPOINT_REGISTRY = Object.values(ENDPOINTS).reduce((accumulator, endpoint) => {
403
- accumulator[endpoint.key] = endpoint;
404
- return accumulator;
405
- }, {});
@@ -24,5 +24,10 @@ export function normalizeRows(value) {
24
24
  const hasMeta = Object.keys(meta).length > 0;
25
25
  return hasMeta ? { ...meta, list } : list;
26
26
  }
27
+ if (Array.isArray(record.chatRoomList)) {
28
+ const { chatRoomList, ...meta } = record;
29
+ const hasMeta = Object.keys(meta).length > 0;
30
+ return hasMeta ? { ...meta, list: chatRoomList } : chatRoomList;
31
+ }
27
32
  return value;
28
33
  }
@@ -1,2 +1,2 @@
1
1
  // Auto-generated — DO NOT EDIT
2
- export const CLI_VERSION = "0.10.10";
2
+ export const CLI_VERSION = "0.11.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.10.10",
3
+ "version": "0.11.1",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {