gangtise-openapi-cli 0.12.0 → 0.13.0

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
@@ -4,6 +4,20 @@
4
4
 
5
5
  ## Changelog
6
6
 
7
+ ### v0.13.0 — 2026-05-15
8
+
9
+ **新增接口**
10
+ - `fundamental income-statement-hk / balance-sheet-hk / cash-flow-hk` — 港股三大报表(中国会计准则)
11
+ - `alternative edb-search` — 行业指标列表搜索(按关键词匹配指标名称,返回 indicatorId 等元信息)
12
+ - `alternative edb-data` — 行业指标时序数据(批量按 indicatorId 拉取时间序列,最多 10 个指标)
13
+ - `vault stock-pool-list` — 查询用户自选股股票池列表(poolId / poolName)
14
+ - `vault stock-pool-stocks` — 查询股票池证券明细(支持 `--pool-id all` 全量查询)
15
+
16
+ **接口变更**
17
+ - `fundamental income-statement / balance-sheet / cash-flow / income-statement-quarterly / cash-flow-quarterly` 名称调整为 A股报表(路径不变)
18
+ - `ai management-discuss-announcement` `--dimension` 新增 `all` 选项,返回报告中完整的管理层讨论内容(内容可能较长)
19
+ - `vault wechat-message-list` 新增 `--security <code>` 参数(按证券代码过滤),返回结果增加 `securityList` 字段
20
+
7
21
  ### v0.12.0 — 2026-05-10
8
22
 
9
23
  **性能 / 架构**
@@ -111,10 +125,19 @@ Skill 目录结构:
111
125
 
112
126
  ```
113
127
  gangtise-openapi/
114
- ├── SKILL.md # 主 skill 文件(命令参考、参数枚举、使用规则)
128
+ ├── SKILL.md # 主 skill 文件(必备规则、速查表、按需引用 references)
115
129
  └── references/
116
- ├── fields.md # 字段中英文对照速查表
117
- └── lookup-ids.md # 常用 ID 速查表(行业/券商/机构/公告分类等)
130
+ ├── commands/ # 按命令组拆分的详细参数文档(agent 按需 Read)
131
+ │ ├── ai.md # AI 能力命令(one-pager / earnings-review / viewpoint-debate 等)
132
+ │ ├── fundamental.md # 财务数据命令(三大报表 / 估值 / 盈利预测 / 股东)
133
+ │ ├── insight.md # 投研内容命令(研报 / 观点 / 纪要 / 公告 / 外资)
134
+ │ ├── quote.md # 行情命令(A股/港股/指数 K 线)
135
+ │ ├── reference-and-lookup.md # GTS Code 搜索与枚举速查
136
+ │ └── vault.md # 云盘/录音/会议/群消息
137
+ ├── examples.md # 典型场景的端到端示例
138
+ ├── fields.md # K线/财务字段中英文对照速查表
139
+ ├── lookup-ids.md # 常用 ID 速查表(行业/券商/机构/公告分类等)
140
+ └── response-schema.md # 各接口响应字段说明
118
141
  ```
119
142
 
120
143
  安装:
package/dist/src/cli.js CHANGED
@@ -303,6 +303,9 @@ addFinancialReport("income-statement-quarterly", "fundamental.income-statement-q
303
303
  addFinancialReport("balance-sheet", "fundamental.balance-sheet");
304
304
  addFinancialReport("cash-flow", "fundamental.cash-flow");
305
305
  addFinancialReport("cash-flow-quarterly", "fundamental.cash-flow-quarterly", "Period: q1/q2/q3/q4/latest");
306
+ addFinancialReport("income-statement-hk", "fundamental.income-statement-hk", "Period: q1/h1/q3/h2/nsd/annual/latest");
307
+ addFinancialReport("balance-sheet-hk", "fundamental.balance-sheet-hk", "Period: q1/h1/q3/h2/nsd/annual/latest");
308
+ addFinancialReport("cash-flow-hk", "fundamental.cash-flow-hk", "Period: q1/h1/q3/h2/nsd/annual/latest");
306
309
  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) => {
307
310
  const client = await createClient();
308
311
  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);
@@ -412,7 +415,7 @@ ai.command("hot-topic").option("--from <number>", "Starting offset", "0").option
412
415
  withCloseReading: options.withCloseReading === false ? undefined : true,
413
416
  }), parseOutputFormat(options.format), options.output);
414
417
  });
415
- ai.command("management-discuss-announcement").requiredOption("--report-date <date>", "Report date (yyyy-MM-dd, e.g. 2025-06-30)").requiredOption("--security-code <code>", "Security code (e.g. 000001.SZ)").addOption(new Option("--dimension <name>", "Discussion dimension").choices(["businessOperation", "financialPerformance", "developmentAndRisk"]).makeOptionMandatory()).option("--format <format>", "Output format", "json").option("--output <path>").action(async (options) => {
418
+ ai.command("management-discuss-announcement").requiredOption("--report-date <date>", "Report date (yyyy-MM-dd, e.g. 2025-06-30)").requiredOption("--security-code <code>", "Security code (e.g. 000001.SZ)").addOption(new Option("--dimension <name>", "Discussion dimension: businessOperation/financialPerformance/developmentAndRisk/all").choices(["businessOperation", "financialPerformance", "developmentAndRisk", "all"]).makeOptionMandatory()).option("--format <format>", "Output format", "json").option("--output <path>").action(async (options) => {
416
419
  const client = await createClient();
417
420
  await printData(await client.call("ai.management-discuss-announcement", {
418
421
  reportDate: options.reportDate,
@@ -499,7 +502,7 @@ vault.command("my-conference-download").requiredOption("--conference-id <id>").r
499
502
  resolveOutputPath: (result) => resolveTitle(client, result, "vault.my-conference.list", "conferenceId", options.conferenceId),
500
503
  });
501
504
  });
502
- 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) => {
505
+ 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("--security <code>", "Security code (e.g. 000001.SZ)", collectList, []).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) => {
503
506
  const client = await createClient();
504
507
  await printData(await client.call("vault.wechat-message.list", buildWechatMessageListBody(options)), parseOutputFormat(options.format), options.output);
505
508
  });
@@ -507,8 +510,42 @@ vault.command("wechat-chatroom-list").option("--from <number>", "Starting offset
507
510
  const client = await createClient();
508
511
  await printData(await client.call("vault.wechat-chatroom.list", buildWechatChatroomListBody(options)), parseOutputFormat(options.format), options.output);
509
512
  });
513
+ vault.command("stock-pool-list").option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
514
+ const client = await createClient();
515
+ await printData(await client.call("vault.stock-pool.list", {}), parseOutputFormat(options.format), options.output);
516
+ });
517
+ vault.command("stock-pool-stocks").option("--pool-id <id>", "Pool ID; repeat for multiple; use 'all' for all pools", collectList, ["all"]).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
518
+ const client = await createClient();
519
+ await printData(await client.call("vault.stock-pool.stocks", { poolIdList: options.poolId }), parseOutputFormat(options.format), options.output);
520
+ });
510
521
  program.addCommand(vault);
511
522
  program.addCommand(ai);
523
+ const alternative = new Command("alternative").description("Alternative data APIs");
524
+ alternative.command("edb-search").requiredOption("--keyword <text>", "Search keyword (e.g. '空调')").option("--limit <number>", "Max results (default: 100, max: 200)", "100").option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
525
+ const client = await createClient();
526
+ await printData(await client.call("alternative.edb-search", {
527
+ keyword: options.keyword,
528
+ limit: parseNumberOption(options.limit, "--limit", { integer: true, min: 1 }),
529
+ }), parseOutputFormat(options.format), options.output);
530
+ });
531
+ alternative.command("edb-data").option("--indicator-id <id>", "Indicator ID (repeat, max 10)", collectList, []).requiredOption("--start-date <date>", "Start date (yyyy-MM-dd)").requiredOption("--end-date <date>", "End date (yyyy-MM-dd)").option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
532
+ const client = await createClient();
533
+ const raw = await client.call("alternative.edb-data", {
534
+ indicatorIdList: options.indicatorId,
535
+ startDate: options.startDate,
536
+ endDate: options.endDate,
537
+ });
538
+ let data = raw;
539
+ if (raw && Array.isArray(raw.fieldList) && Array.isArray(raw.dataList)) {
540
+ const list = raw.dataList.map((row) => raw.fieldList.reduce((acc, field, i) => {
541
+ acc[field] = row[i];
542
+ return acc;
543
+ }, {}));
544
+ data = { list, total: list.length };
545
+ }
546
+ await printData(data, parseOutputFormat(options.format), options.output);
547
+ });
548
+ program.addCommand(alternative);
512
549
  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) => {
513
550
  const endpoint = ENDPOINTS[endpointKey];
514
551
  if (!endpoint) {
@@ -15,6 +15,7 @@ export function buildWechatMessageListBody(options) {
15
15
  startTime: options.startTime,
16
16
  endTime: options.endTime,
17
17
  keyword: options.keyword,
18
+ securityList: maybeArray(options.security),
18
19
  wechatGroupIdList: maybeArray(options.wechatGroupId),
19
20
  industryIdList: maybeArray(options.industry),
20
21
  categoryList: maybeArray(options.category),
@@ -246,35 +246,56 @@ export const ENDPOINTS = {
246
246
  method: "POST",
247
247
  path: "/application/open-fundamental/financial-report/income-statement/accumulated",
248
248
  kind: "json",
249
- description: "Query income statement (accumulated)",
249
+ description: "Query A-share income statement (accumulated)",
250
250
  },
251
251
  "fundamental.income-statement-quarterly": {
252
252
  key: "fundamental.income-statement-quarterly",
253
253
  method: "POST",
254
254
  path: "/application/open-fundamental/financial-report/income-statement/quarterly",
255
255
  kind: "json",
256
- description: "Query income statement (quarterly)",
256
+ description: "Query A-share income statement (quarterly)",
257
257
  },
258
258
  "fundamental.balance-sheet": {
259
259
  key: "fundamental.balance-sheet",
260
260
  method: "POST",
261
261
  path: "/application/open-fundamental/financial-report/balance-sheet/accumulated",
262
262
  kind: "json",
263
- description: "Query balance sheet (accumulated)",
263
+ description: "Query A-share balance sheet (accumulated)",
264
264
  },
265
265
  "fundamental.cash-flow": {
266
266
  key: "fundamental.cash-flow",
267
267
  method: "POST",
268
268
  path: "/application/open-fundamental/financial-report/cash-flow-statement/accumulated",
269
269
  kind: "json",
270
- description: "Query cash flow statement (accumulated)",
270
+ description: "Query A-share cash flow statement (accumulated)",
271
271
  },
272
272
  "fundamental.cash-flow-quarterly": {
273
273
  key: "fundamental.cash-flow-quarterly",
274
274
  method: "POST",
275
275
  path: "/application/open-fundamental/financial-report/cash-flow-statement/quarterly",
276
276
  kind: "json",
277
- description: "Query cash flow statement (quarterly)",
277
+ description: "Query A-share cash flow statement (quarterly)",
278
+ },
279
+ "fundamental.income-statement-hk": {
280
+ key: "fundamental.income-statement-hk",
281
+ method: "POST",
282
+ path: "/application/open-fundamental/financial-report/income-statement/hk",
283
+ kind: "json",
284
+ description: "Query HK income statement (China GAAP)",
285
+ },
286
+ "fundamental.balance-sheet-hk": {
287
+ key: "fundamental.balance-sheet-hk",
288
+ method: "POST",
289
+ path: "/application/open-fundamental/financial-report/balance-sheet/hk",
290
+ kind: "json",
291
+ description: "Query HK balance sheet (China GAAP)",
292
+ },
293
+ "fundamental.cash-flow-hk": {
294
+ key: "fundamental.cash-flow-hk",
295
+ method: "POST",
296
+ path: "/application/open-fundamental/financial-report/cash-flow-statement/hk",
297
+ kind: "json",
298
+ description: "Query HK cash flow statement (China GAAP)",
278
299
  },
279
300
  "fundamental.main-business": {
280
301
  key: "fundamental.main-business",
@@ -473,4 +494,33 @@ export const ENDPOINTS = {
473
494
  kind: "json",
474
495
  description: "List WeChat group chatroom IDs",
475
496
  },
497
+ "vault.stock-pool.list": {
498
+ key: "vault.stock-pool.list",
499
+ method: "POST",
500
+ path: "/application/open-vault/stock-pool/getPoolList",
501
+ kind: "json",
502
+ description: "List user stock pool IDs and names",
503
+ },
504
+ "vault.stock-pool.stocks": {
505
+ key: "vault.stock-pool.stocks",
506
+ method: "POST",
507
+ path: "/application/open-vault/stock-pool/getStockList",
508
+ kind: "json",
509
+ description: "List securities in stock pool(s)",
510
+ },
511
+ // ─── alternative ───
512
+ "alternative.edb-search": {
513
+ key: "alternative.edb-search",
514
+ method: "POST",
515
+ path: "/application/open-alternative/EDB/search",
516
+ kind: "json",
517
+ description: "Search industry indicator list by keyword",
518
+ },
519
+ "alternative.edb-data": {
520
+ key: "alternative.edb-data",
521
+ method: "POST",
522
+ path: "/application/open-alternative/EDB/getData",
523
+ kind: "json",
524
+ description: "Get industry indicator time-series data by indicator ID list",
525
+ },
476
526
  };
@@ -1,2 +1,2 @@
1
1
  // Auto-generated — DO NOT EDIT
2
- export const CLI_VERSION = "0.12.0";
2
+ export const CLI_VERSION = "0.13.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {