gangtise-openapi-cli 0.50.0 → 0.52.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.
Files changed (43) hide show
  1. package/README.md +94 -49
  2. package/dist/src/cli.js +29 -8
  3. package/dist/src/commands/ai.js +27 -12
  4. package/dist/src/commands/alternative.js +2 -2
  5. package/dist/src/commands/bond.js +4 -4
  6. package/dist/src/commands/fund.js +1 -1
  7. package/dist/src/commands/fundamental.js +11 -11
  8. package/dist/src/commands/indicator.js +5 -5
  9. package/dist/src/commands/insight.js +38 -17
  10. package/dist/src/commands/quote.js +6 -6
  11. package/dist/src/commands/raw.js +3 -3
  12. package/dist/src/commands/reference.js +35 -3
  13. package/dist/src/commands/shared.js +20 -8
  14. package/dist/src/commands/tool.js +9 -4
  15. package/dist/src/commands/update.js +11 -0
  16. package/dist/src/commands/vault.js +17 -16
  17. package/dist/src/core/client.js +21 -4
  18. package/dist/src/core/download.js +12 -3
  19. package/dist/src/core/driveUpload.js +6 -2
  20. package/dist/src/core/dryRun.js +68 -0
  21. package/dist/src/core/endpoints.js +87 -6
  22. package/dist/src/core/errors.js +2 -2
  23. package/dist/src/core/etfComponents.js +65 -8
  24. package/dist/src/core/exitStatus.js +4 -0
  25. package/dist/src/core/fileParse.js +10 -3
  26. package/dist/src/core/printer.js +39 -7
  27. package/dist/src/core/statePaths.js +41 -0
  28. package/dist/src/core/transport.js +7 -0
  29. package/gangtise-openapi/SKILL.md +43 -156
  30. package/gangtise-openapi/references/billing.md +142 -0
  31. package/gangtise-openapi/references/commands/ai.md +26 -0
  32. package/gangtise-openapi/references/commands/fund.md +3 -3
  33. package/gangtise-openapi/references/commands/fundamental.md +2 -1
  34. package/gangtise-openapi/references/commands/indicator.md +106 -15
  35. package/gangtise-openapi/references/commands/insight.md +31 -6
  36. package/gangtise-openapi/references/commands/reference-and-lookup.md +42 -4
  37. package/gangtise-openapi/references/commands/tool.md +2 -2
  38. package/gangtise-openapi/references/commands/vault.md +26 -4
  39. package/gangtise-openapi/references/errors.md +3 -3
  40. package/gangtise-openapi/references/examples.md +3 -3
  41. package/gangtise-openapi/references/lookup-ids.md +13 -0
  42. package/gangtise-openapi/references/response-schema.md +8 -2
  43. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  # 错误码、退出码与常见困境自救
2
2
 
3
3
  > 主文件 `SKILL.md` 只保留最高频的几个码;这里是全表。
4
- > **退出码语义**:`0` 完整成功(含合法空结果)/ `3` 有数据但不完整(`partial: true`)/ `4` 导出的数据完整,但 `--output` 已被另一次导出替换(见下文「退出码 4」)/ `1` 硬失败/ `130` / `143` / `129` 被 Ctrl-C / `kill` / 终端断开中断(进程以该信号结束;本次导出的暂存文件已删除;中断前已发出的请求服务端照常处理并计费)。
4
+ > **退出码语义**:`0` 完整成功(含合法空结果)/ `3` 有数据但不完整(`partial: true`)/ `4` 导出的数据完整,但 `--output` 已被另一次导出替换(见下文「退出码 4」)/ `1` 硬失败(请求可能已发出、可能已计费)/ `2` 发请求前就被拒:未知选项、取值不合法、缺必选项或 `--yes`、`--output` 是目录、未配凭证——没有发出任何请求,不计费,改了重跑即可(同类报错若发生在已经发过请求之后,例如按条计费的列表先取了 total 才被额度保护拦下,仍是 `1`)/ `130` / `143` / `129` 被 Ctrl-C / `kill` / 终端断开中断(进程以该信号结束;本次导出的暂存文件已删除;中断前已发出的请求服务端照常处理并计费)。
5
5
  > 报错行末尾的 `[trace <id>]` 是 Gangtise 支持定位问题的唯一凭据,**报障时带上它**。
6
6
 
7
7
  ## 错误码怎么读
@@ -16,7 +16,7 @@
16
16
  | `999999` | 系统错误。`indicator`(EDE)的「无数据」不用此码(无数据是保留行列的占位单元格 `null`,见 `commands/indicator.md`;代码或参数名写错报 `100003`、缺必填参数报 `100001`,都会点名),所以这个码基本只剩真故障 | 普通端点自动重试 ×2;🔴 贵档与 `indicator` 端点不重试 | 确认参数无误仍报此码即服务端故障 |
17
17
  | `410110` | **异步生成中**(HTTP 400,旧码)。新码 `140001`,CLI 两码都认 | 轮询视为 pending | 继续等 |
18
18
  | `410111` | **异步生成失败**(HTTP 400,旧码)。新码 `140002`,CLI 两码都认 | 终态 | **不重试**,换参数 |
19
- | `130002` | 资源不存在——下载类的常见码:`reportId` 不存在 / 非数字多归此码。另有更具体的 `130003`(资源未生成 / 无附件);`--file-type` 写错由 CLI 在本地报错、不发请求。`vault stock-note-update` 传了不存在或不属于本人的笔记 ID 也报此码(`stock-note-delete` 不报,这类 ID 计入 `successList`) | — | 确认 ID 有效且本账号可见(笔记 ID 用 `vault stock-note-list` 核对);换 `--file-type` 或换一篇验证 |
19
+ | `130002` | 资源不存在——下载类的常见码:`reportId` 不存在 / 非数字多归此码。另有更具体的 `130003`(资源未生成 / 无附件;`vault wechat-message-download` 收到它是消息不存在、无权访问或文件已不可用,不区分原因、重试不会变)与 `130005`(`vault wechat-message-download`:该消息是 text / url,没有文件);`--file-type` 写错由 CLI 在本地报错、不发请求。`vault stock-note-update` 传了不存在或不属于本人的笔记 ID 也报此码(`stock-note-delete` 不报,这类 ID 计入 `successList`) | — | 确认 ID 有效且本账号可见(笔记 ID 用 `vault stock-note-list` 核对);换 `--file-type` 或换一篇验证 |
20
20
  | `130001` | 数据未找到,或**该指标无权限**(`indicator` 内层失败会带具体 msg 如"指标无权限") | — | 检查查询条件与指标权限 |
21
21
  | `100001` | 缺必填参数——**msg 带字段名**(「缺少必填参数: reportId」) | — | 按 msg 指的字段补上 |
22
22
  | `110001` / `110002` | 日期格式错(msg 带字段名)/ 起晚于止。⚠️ **服务端对多种格式做宽松解析**(`2026/07/01`、`20260701`、`07/01/2026` 都能被接受),所以「没报 110001」不等于「格式被按你的意思理解了」 | — | 按参数名:`--*-date` 用 `YYYY-MM-DD`、`--*-time` 用 `YYYY-MM-DD HH:mm:ss`;`ai knowledge-batch` 的 --start-time/--end-time 收时间戳或 datetime,CLI 统一转 13 位毫秒 |
@@ -138,6 +138,6 @@
138
138
 
139
139
  **同一公司既是股票又是 DR** → `securities-search` 默认返回所有分类 → 加 `--category stock` 收敛。
140
140
 
141
- **`--category stock` / `fund` 的结果里出现 `category: bond`** → 可转债不受 `--category` 约束、按简称查时常排第一(如「甬金」→ `113636.SH 甬金转债`) → 只取 `category` 等于所查类别的行;查股票可改用公司全称,查基金换更具体的基金简称。债券代码传给基金命令返回空结果、不报错,传给股票行情 / 财报报 `120001`。
141
+ **按简称查股票,第一条是 `category: bond`** → 没带 `--category`,同名可转债排在了正股前面(如「甬金」→ `113636.SH 甬金转债`) → 加 `--category stock`。债券代码传给基金命令返回空结果、不报错,传给股票行情 / 财报报 `120001`。
142
142
 
143
143
  **`sector-constituents` 返回 0 条** → sectorId 不对(题材 conceptId 与板块 sectorId 是两套 ID,不通用)→ 先 `reference sector-search --keyword <名>` 拿 `sectorId` 重试。
@@ -137,7 +137,7 @@
137
137
  1. 路由 → insight research list;公司名不在速查表
138
138
  2. 先调 reference securities-search:
139
139
  gangtise reference securities-search --keyword 蔚蓝生物 --category stock --top 3 --format json
140
- 取第一条 category 为 stock 的 gtsCode = "603739.SH"(按简称查时同名可转债可能排在前面)
140
+ 取第一条 category 为 stock 的 gtsCode = "603739.SH"
141
141
  3. 拼正式查询:
142
142
  gangtise insight research list --security 603739.SH --rank-type 2 \
143
143
  --start-time "<今天-7天> 00:00:00" --end-time "<今天> 23:59:59" --format json
@@ -284,8 +284,8 @@
284
284
  - --rank-type 1 在有 keyword 时按相关度挑条目;要最新就用 --rank-type 2 --search-type 2
285
285
  (--search-type 2 = 全文,只扩大 --rank-type 2 的候选池,不改变 --rank-type 1 取回哪些条目)
286
286
  - 筛选项比 summary 少:没有 --source / --institution / --participant-role
287
- 3. 🔴 别拉全量再本地按类别/市场分组——categoryList / conceptList / marketList 这几个标签字段稀疏,
288
- 是否有值随记录和查法而变(用该字段过滤时回填率更高,详见 insight.md)。要分组就让服务端筛:
287
+ 3. 🔴 别拉全量再本地按类别/市场分组——不按 --category / --market 筛时 categoryList 为空,
288
+ marketList 不含 aShares / usChinaConcept(详见 insight.md)。要分组就让服务端筛:
289
289
  gangtise insight pamirs-summary list --category industryAnalysis --market aShares --size 50
290
290
  4. 下载(省略 --output 自动用标题命名):
291
291
  gangtise insight pamirs-summary download --summary-id 5863771 --file-type 2
@@ -70,6 +70,19 @@
70
70
 
71
71
  ---
72
72
 
73
+ ## GICS 一级行业(insight overseas-opinion --industry 参数)
74
+
75
+ 只用于 `insight overseas-opinion list --industry`;申万码、中信码在这里报 `100005`。`reference constant-list --category gicsIndustry` 返回同一套 ID。
76
+
77
+ | ID | 行业 | ID | 行业 | ID | 行业 |
78
+ |----|------|----|------|----|------|
79
+ | 107700001 | 能源 | 107700002 | 原材料 | 107700003 | 工业 |
80
+ | 107700004 | 非日常生活消费品 | 107700005 | 日常消费品 | 107700006 | 医疗保健 |
81
+ | 107700007 | 金融 | 107700008 | 信息技术 | 107700009 | 通讯业务 |
82
+ | 107700010 | 公用事业 | 107700011 | 房地产 | | |
83
+
84
+ ---
85
+
73
86
  ## 常用券商(--broker 参数)
74
87
 
75
88
  完整列表用 `lookup broker-org list`
@@ -25,7 +25,7 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
25
25
  | insight opinion detail | `{total, list}`;缺失时另有 `missingIds` / `unfetchedIds` / `unfetchedError` + `partial` | `list[]` 同 list 的字段 + `content`(正文全文) |
26
26
  | insight summary list | `{list, total}` | `list[].summaryId` / `list[].title` / `list[].publishTime` |
27
27
  | insight summary download | 文件路径(stdout) | — |
28
- | insight pamirs-summary list | `{list, total}` | `list[].summaryId` / `list[].title` / `list[].brief` / `list[].summaryTime`(纪要生成时间)/ `list[].publishTime`(发布时间)/ `list[].securityList[]{securityCode, securityName}` / `list[].researchAreaList[]{researchAreaId, researchAreaName}` / `list[].conceptList[]{conceptId, conceptName}` / `list[].categoryList` / `list[].marketList`。⚠️ `conceptList` / `categoryList` / `marketList` 三个标签字段**稀疏,且是否有值随记录和查法而变**:不带筛选时经常整条为空,用 `--category` 或 `--market` 任一过滤时回填率明显更高(这两个字段绑定,一起有或一起没有)。所以**别拉全量再本地分组**(会漏记录),也**别据此断言某条记录没有该属性**(为空只说明这次没回填)。详见 `commands/insight.md` |
28
+ | insight pamirs-summary list | `{list, total}` | `list[].summaryId` / `list[].title` / `list[].brief` / `list[].summaryTime`(纪要生成时间)/ `list[].publishTime`(发布时间)/ `list[].securityList[]{securityCode, securityName}` / `list[].researchAreaList[]{researchAreaId, researchAreaName}` / `list[].conceptList[]{conceptId, conceptName}` / `list[].categoryList` / `list[].marketList`。⚠️ `categoryList` / `marketList` **只在按 `--category` 或 `--market` 筛选时返回完整**:其余查法下 `categoryList` 为空、`marketList` 不含 `aShares` / `usChinaConcept`。所以**别拉全量再按这两个字段本地分组**(A 股、中概股归属会整批缺失),也**别据此断言某条记录没有该属性**。`conceptList` 不随查法变。详见 `commands/insight.md` |
29
29
  | insight pamirs-summary download | 文件路径(stdout) | — |
30
30
  | insight roadshow / site-visit / strategy / forum list | `{list, total}` | 各自的 ID:`list[].roadshowId` / `siteVisitId` / `strategyMeetingId` / `forumId`;`list[].title` / `list[].startTime` / `list[].endTime`(举办时间)/ `list[].publishTime`(首次收录时间,可为 `null`)/ `list[].location`;路演、调研、策略会另有 `list[].institutionList[]{institutionId, institutionName}`(论坛没有) |
31
31
  | insight research list | `{list, total}` | `list[].reportId` / `list[].title` / `list[].brief`(全文摘要) / `list[].publishTime` / `list[].publisher.brokerName` / `list[].securityList[].rating` |
@@ -42,6 +42,8 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
42
42
  | insight foreign-opinion detail | 同 opinion detail | `list[]` 同 list 的字段 + `content`(原文)/ `contentTranslate`(中文译文) |
43
43
  | insight independent-opinion list | `{list, total}` | `list[].independentOpinionId` / `list[].titleTranslate` / `list[].briefTranslate` / `list[].publishTime` / `list[].analyst.analystName` |
44
44
  | insight independent-opinion download | 文件路径(stdout) | — |
45
+ | insight overseas-opinion list | `{list, total}` | `list[].overseasOpinionId`(`detail` 用)/ `list[].accountId` / `list[].accountName` / `list[].publishTime` / `list[].originalFlag`(1 原创 / 0 转发)/ `list[].categoryList[]`(类别,可多个、可为空数组)/ `list[].brief` / `list[].briefTranslate` / `list[].forwardPost{accountName, publishTime, brief, briefTranslate}`(原创为 `null`)/ `list[].industryList[]{industryId, industryName}` / `list[].securityList[]{securityCode, securityName}` / `list[].regionList[]{regionCode, regionName}` |
46
+ | insight overseas-opinion detail | 同 opinion detail | `list[]` 同 list 的字段,以 `content`(原文)/ `contentTranslate`(中文译文)代替 `brief` / `briefTranslate`(`forwardPost` 内同) |
45
47
  | insight official-account list | `{list, total}` | `list[].articleId` / `list[].accountName` / `list[].title` / `list[].publishTime` / `list[].articleCategory` / `list[].summary` / `list[].industryList[].industryName` / `list[].conceptList[].conceptName` / `list[].securityList[].securityCode` |
46
48
  | insight official-account download | 文件路径(stdout) | — |
47
49
  | insight qa list | `{list, total}` | `list[].source`(conference/interactive/survey)/ `list[].publishTime` / `list[].question` / `list[].answer` / `list[].member` / `list[].securityCode` / `list[].questionCategory[]` / `list[].answerImportant`(1/0) |
@@ -55,12 +57,14 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
55
57
  | reference securities-search | `{returnedCount, list}` | `list[].gtsCode` / `list[].gtsName` / `list[].category` / `list[].matchScore` / `list[].matchType` |
56
58
  | reference chiefs-search | `{returnedCount, list}` | `list[].chiefId` / `list[].chiefName` / `list[].institution` / `list[].team` / `list[].matchScore` |
57
59
  | reference institution-search | `{returnedCount, list}` | `list[].institutionId` / `list[].institutionName` / `list[].category` / `list[].usageScopes[{apiName, paramName}]` / `list[].matchScore` |
60
+ | reference overseas-account-search | `{list, total}` | `list[].accountId`(喂 `insight overseas-opinion list --account`)/ `list[].accountName` / `list[].accountIntroduction` / `list[].matchScore` |
58
61
  | reference official-account-search | `{returnedCount, list}` | `list[].accountId`(喂 `insight official-account list --account-id`)/ `list[].accountName` / `list[].category`(四类或 `null`)/ `list[].matchScore` |
59
62
  | reference constant-category | `{total, list}` | `list[].category` / `list[].categoryName` / `list[].structureType`(flat/tree) / `list[].maxLevel` / `list[].usageScopes[].apiName` / `.paramName` |
60
63
  | reference constant-list | `{category, structureType, maxLevel, constantCount, list}`(CLI 把 `constants` 规范化为 `list`) | `list[].constantId` / `list[].constantName` / `list[].level`;树形分类父节点含 `list[].children[]`(递归同构) |
61
64
  | reference concept-search | `{returnedCount, list}` | `list[].conceptId` / `list[].conceptName` / `list[].matchScore` |
62
65
  | reference sector-search | `{returnedCount, list}` | `list[].sectorId` / `list[].sectorName` / `list[].hierarchy`(层级路径) / `list[].matchScore` |
63
66
  | reference sector-constituents | `{total, list}` | `list[].gtsCode` / `list[].gtsName`;total=0 说明 sectorId 不对(先 sector-search 确认) |
67
+ | reference index-weight | `{total, list}`,不分页 | `list[].indexCode` / `indexName` / `tradeDate` / `securityCode` / `securityName` / `weight`(%);多个指数合在一个 `list`,按 `indexCode` 区分;total=0 多为日期不是月末交易日 |
64
68
  | quote day-kline(及已弃用的 day-kline-hk / day-kline-us / index-day-kline) | `{fieldList, list}` 或规范化后 `{list: [{...}]}` | `tradeDate` / `securityCode` / `open` / `close` / `pctChange` / `volume` / `amount`(全球指数为 `null`)/ `adjustFactor`(指数为 `null`,ETF 有值);四者字段相同,均不含指数名称 |
65
69
  | quote minute-kline | `{list: [{...}]}` | `tradeTime` / `open` / `close` / `volume` |
66
70
  | quote realtime | `{fieldList, list, total}` 或规范化后 `{list: [{...}]}` | `securityCode` / `exchange` / `tradeDate` / `tradeTime` / `tradeStatus` / `open` / `high` / `low` / `latestPrice` / `preClose` / `change` / `pctChange` / `volume` / `amount` / `amplitude`(共 15 个,**无 `close`、无市值、无 `turnoverRate` / `volumeRatio`**;美股 `amount`、全球指数 `volume` / `amount` / `amplitude` 为 `null`) |
@@ -78,6 +82,7 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
78
82
  | ai theme-tracking | `[{type, date, content}, ...]`(列表,每元素一份报告) | 遍历筛选 `type === "morning" / "night"`;某主题在该日期可能只有一种类型,或两种都没(空列表) |
79
83
  | ai hot-topic | `{list, total}` | `list[].title` / `list[].reportDate` / `list[].category` / `list[].topics[].topicTitle` / `list[].topics[].driverEvent` / `list[].topics[].investLogic` |
80
84
  | ai management-discuss-* | `{securityCode, reportDate, discussionDimension, content}` | `content` 为字符串(业绩会)或字符串数组(财报) |
85
+ | ai expert-intel | `{list, total}` | `list[].intelId` / `title` / `mainSecurity.securityCode` · `securityName` / `tagList[]`(纯文本)/ `content` / `publishTime` / `securityList[]` / `researchAreaList[].researchAreaName` / `conceptList[].conceptName` |
81
86
  | ai management-sentiment-indicator | `{list, total}`,一条 = 一只证券 × 一场业绩会 | `list[].securityCode` / `publishTime` / `sentimentResponsiveness` · `sentimentPolarity` · `sentimentConviction`(0–5)/ `qaCount` / `qaEvasionRatio` · `qaRiskRatio` · `qaUncertaintyRatio`(百分数)/ `questionCategoryList[]` / `source.sourceType` + `source.sourceId` |
82
87
  | ai management-sentiment-conclusion | `{list, total}`,粒度同上 | `list[].sentimentSummary.{overallSentiment, questionCategorySentiment, qaSentimentChange}` / `sentimentSignal.*Signal`(文本)/ `qaSentimentContrast[]` / `source` / `previousSource`(无可对比的上一场时为 `null`) |
83
88
  | ai management-sentiment-detail | `{list, total}`,一条 = 一条问答,不分页 | `list[].qaId` / `questionCategory` / `questionBrief` / `question` / `answer` / `qaResponsiveness` · `qaPolarity` · `qaConviction`(`5.0` / `2.5` / `0.0` 三档)/ 三组 `*Quote` + `*Reason` |
@@ -96,7 +101,8 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
96
101
  | vault record-download | 文件路径(stdout) | — |
97
102
  | vault my-conference-list | `{list, total}` | `list[].conferenceId` / `list[].title` / `list[].category` / `list[].institution.institutionName` / `list[].publishTime` |
98
103
  | vault my-conference-download | 文件路径(stdout) | — |
99
- | vault wechat-message-list | `{list, total}` | `list[].msgId` / `list[].content`(正文)/ `list[].url` / `list[].msgTime` / `list[].wechatGroupName` / `list[].speakerName` / `list[].category` / `list[].tagList[].tagCode` / `list[].securityList[].securityCode` / `list[].quoteMsg.quoteContent`(引用消息,无引用为 `null`)。**字段名是 `content` / `url`**,不是 `msgContent` / `contentUrl` |
104
+ | vault wechat-message-list | `{list, total}` | `list[].msgId` / `list[].content`(正文)/ `list[].url` / `list[].msgTime` / `list[].wechatGroupName` / `list[].speakerName` / `list[].category` / `list[].tagList[].tagCode` / `list[].securityList[].securityCode` / `list[].fileInfo.fileName` · `fileSize`(文档 / 图片 / 音频 / 视频消息,其他为 `null`)/ `list[].quoteMsg.quoteMsgId` · `quoteCategory` · `quoteContent` · `quoteFileInfo`(引用消息,无引用为 `null`)。**字段名是 `content` / `url`**,不是 `msgContent` / `contentUrl`;`msgId` 是长数字串,按字符串保存 |
105
+ | vault wechat-message-download | 文件路径(stdout) | — |
100
106
  | vault wechat-chatroom-list | `{list, total}` | `list[].chatroomName` / `list[].chatroomId` |
101
107
  | vault stock-pool-list | 数组 | `[].poolId`(后续命令的 `--pool-id`)/ `[].poolName` / `[].spaceType`(`1` 个人、`2` 租户;查明细时 `--space-type` 要与之一致) |
102
108
  | vault stock-pool-stocks | 数组 | `[].securityCode` / `[].securityName`。空池返回 `[]` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.50.0",
3
+ "version": "0.52.0",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "commander": "^14.0.0",
40
- "undici": "^7.30.1"
40
+ "undici": "^7.30.2"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^20.19.43",