gangtise-openapi-cli 0.41.0 → 0.42.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 (38) hide show
  1. package/README.md +48 -50
  2. package/dist/src/cli.js +23 -1131
  3. package/dist/src/commands/ai.js +155 -0
  4. package/dist/src/commands/alternative.js +56 -0
  5. package/dist/src/commands/auth.js +37 -0
  6. package/dist/src/commands/bond.js +76 -0
  7. package/dist/src/commands/fundamental.js +137 -0
  8. package/dist/src/commands/indicator.js +134 -0
  9. package/dist/src/commands/insight.js +337 -0
  10. package/dist/src/commands/quote.js +147 -0
  11. package/dist/src/commands/raw.js +49 -0
  12. package/dist/src/commands/reference.js +58 -0
  13. package/dist/src/commands/shared.js +145 -0
  14. package/dist/src/commands/tool.js +55 -0
  15. package/dist/src/commands/vault.js +203 -0
  16. package/dist/src/core/args.js +7 -4
  17. package/dist/src/core/asyncContent.js +32 -19
  18. package/dist/src/core/client.js +11 -4
  19. package/dist/src/core/config.js +16 -3
  20. package/dist/src/core/endpoints.js +3 -0
  21. package/dist/src/core/exitStatus.js +17 -0
  22. package/dist/src/core/fileParse.js +3 -20
  23. package/dist/src/core/opinionDetail.js +39 -0
  24. package/dist/src/core/output.js +18 -4
  25. package/dist/src/core/printer.js +7 -8
  26. package/dist/src/core/rowSink.js +19 -7
  27. package/dist/src/core/transport.js +4 -3
  28. package/dist/src/version.js +1 -1
  29. package/gangtise-openapi/SKILL.md +5 -5
  30. package/gangtise-openapi/references/commands/ai.md +1 -1
  31. package/gangtise-openapi/references/commands/fundamental.md +3 -1
  32. package/gangtise-openapi/references/commands/indicator.md +2 -2
  33. package/gangtise-openapi/references/commands/quote.md +7 -10
  34. package/gangtise-openapi/references/errors.md +8 -5
  35. package/gangtise-openapi/references/examples.md +2 -2
  36. package/gangtise-openapi/references/fields.md +9 -7
  37. package/gangtise-openapi/references/response-schema.md +1 -1
  38. package/package.json +2 -2
package/README.md CHANGED
@@ -6,16 +6,20 @@
6
6
 
7
7
  README 仅列最近 5 个版本摘要:
8
8
 
9
+ - **v0.42.0 — 2026-09-25**:① **数值参数只收十进制写法**:`--size 0x10`、`--size 1e3`、`--limit 5.0` 这类写法发请求前报错并点名参数(此前会被换算成 16 / 1000 / 5 照常发出);数字列表类参数逐项要求整数。**脚本里用了这类写法的,请改成普通整数。** ② **接管道时保留退出码**:`gangtise … | head` 提前关掉读端时,以已判定的退出码(`3` / `4`)结束,此前一律 `0`;脚本用 `set -o pipefail` 即可看到。③ **`GANGTISE_TIMEOUT_MS` 只收整数毫秒**:低于 1 秒回退默认、高于 1 小时按 1 小时,所写数值没有按原样生效时 stderr 提示一次。④ 观点 `detail` 与估值分析的返回结构与约定不符时报错并附 trace,不再按空结果处理。⑤ `fundamental valuation-analysis` 的 `--field` 不含数值列、接口返回 0 行时,stderr 说明原因。⑥ 性能:大批量导出按块写盘;自动翻页时单个慢页对其余页的拖累更小;`GANGTISE_PAGE_CONCURRENCY` 设到 16 以上时并发随之增加。
10
+
11
+ - **v0.41.1 — 2026-09-24**:① **`quote index-day-kline --security all` 改为直接报错**:该接口对 `all` 返回空结果、不报错,与「当天无数据」无法区分;报错信息写明原因与替代写法。指数日 K 请用 `quote day-kline` 逐个传代码;该接口的返回字段与 `day-kline` 相同、不含指数名称,名称用 `reference securities-search --keyword <指数代码> --category index` 返回的 `gtsName`。② **`fundamental valuation-analysis` 长区间不再被静默截断**:序列逐自然日一行(含周末),默认只取最近 2000 行,区间更长时开头会缺失——现在撞满即标 `partial`、退出码 3,并提示把 `--limit` 设到不小于区间天数(权限窗口内的十年约 3700 行);首行恰好就是 `--start-date` 时说明没丢,不标。起点早于账号回溯下界时该接口从下界起返回、不报错,CLI 在 stderr 提示首行晚于 `--start-date`。③ **估值分析 `--field` 不再可能错列**:CLI 发请求前对字段去重并去掉 `tradeDate`(它总在第一列返回)。旧版在 `--field` 同时含 `tradeDate`(或重复字段)与不存在的字段名时,会输出整体右移一列的数据且退出 0,**用过这类组合的估值结果请重跑**。④ 依赖 `undici` 升至 7.29.1(安全更新)。⑤ 文档:`fundamental valuation-analysis` 的 `--field` 至少要含一个数值列(`value` 等),只传 `tradeDate` 或只传不存在的名字时接口返回 0 行、不报错;`references/errors.md` 的退出码摘要补上 `4`。⑥ **Skill 安装命令改为可重复执行**:目标目录已存在时直接 `cp -r`,新版会被复制进嵌套的 `gangtise-openapi/gangtise-openapi/`、已安装的副本仍是旧版;这样更新过的,按「AI Agent Skill」段的新命令重新执行一次即可。
12
+
9
13
  - **v0.41.0 — 2026-09-24**:① **观点列表改走 v2,省积分**:`insight opinion list` / `foreign-opinion list` 默认只返回摘要(`brief`,外资另有 `briefTranslate`,取正文前 200 字),**1 积分/条**;要正文用新增的 `insight opinion detail --chief-opinion-id` / `foreign-opinion detail --foreign-opinion-id`(**30 积分/条**,按返回条数计;ID 可一次传多个,CLI 按 20 个一批自动拆分;没返回正文的 ID 列在 `missingIds`、中途某批失败时未取的 ID 列在 `unfetchedIds`,两种情况都以退出码 3 结束)。想像以前一样列表直接带正文,加 `--with-content`(30 积分/条,返回旧版结构:内资正文在 `contentList.content`;与 `detail` 一样超时不自动重发)。② **题材画像与成分股改走 v2**:`alternative concept-info` / `concept-securities` **50 积分/次**;v2 不含催化事件 `keyEvents`、重点个股标识 `isKey`、纳入理由 `inclusionReason`,需要这几列加 `--full`(500 积分/次)。③ **云盘管理 9 个命令,全部免费**:`vault drive-folder-list`(浏览目录)/ `drive-upload` / `drive-create-folder` / `drive-rename` / `drive-move-file` / `drive-move-folder` / `drive-copy`(把文件复制到另一空间:我的云盘 ↔ 租户云盘)/ `drive-delete-file` / `drive-delete-folder`。两个删除**需 `--yes`**,删文件夹会连同其中全部子文件夹与文件一起删除且不可恢复;云盘允许同名,上传 / 新建 / 复制每跑一次就多一份,这三个与两个删除**超时不自动重发**。④ **新增 `bond` 族 12 个命令,0.4 积分起**:`basic-info`(静态档案)/ `issuer-info` / `daily-quote` / `valuation`(上清所估值)/ `cash-flow` / `announcement` / `issuance-detail` / `rating-overview` / `rating-change`(债项评级变动)/ `issuer-rating-change` / `issuance-plan` / `exercise-notice`。多数按次计费;`rating-overview` 按条、`rating-change` 按有数据的债券只数、`issuer-rating-change` 按发行人计。`--security` **只收标准债券代码**(`019742.SH` / `220205.IB`),简称与拼音整批拒绝(`120001`),先用 `reference securities-search` 换代码;`--field` 写错字段名同样整批拒绝(`100003`),不会静默丢列。**整族超时不自动重发**——计费接口重发会重复扣费,偶发 5xx / 超时请自行重跑。🔴 **`bond announcement` 需手动翻页**:本族唯一分页的接口且**不返回 `total`**,`--page-no` 从 1 起逐页递增直到某页为空。⑤ **`insight highlight list` 会议线索**(会议核心要点信息流;🔴 **5 积分/条,务必带 `--size`**,省略会拉全量;`content` 是 HTML 片段,`--research-area` 不认申万码;按偏移量最多能翻到第 10000 条,超出部分请缩短时间范围分段取)。⑥ **`tool web-search` 联网搜索**(1 积分/次,零结果不扣):`--site` 定向站点、`--min-tier` 收信源等级、`--freshness` 收时效、`--include-content` 取正文(此时 `--size` ≤5)。⚠️ **排序是「信源等级 → 发布日期 → 相关性」,首条不等于最相关**;`publishTime` 判不出时为 `null`,`--freshness` 会把这批一并滤掉,做时点判断别用 `indexTime`。⑦ **常量接口新增 9 个分类**:`fundType` / `fundBondType` / `bondType` / `interestRateType` / `interestFrequency` / `absUnderlyingAssetType` / `ratingType` / `exchange` / `nationalEconomicIndustry`。⑧ **取数前注意几处取值**:`bond issuer-info` 的评级列混合境内外口径,做信用比较一并取 `ratingAgency`;评级值可能带 `sf` / `pi` 后缀;`bond daily-quote` / `valuation` / `issuance-plan` 的 `--start-date` 早于可回溯下界时整批返回 `110003`,把起点移进窗口再查。逐条见 `gangtise-openapi/references/commands/bond.md`。
10
14
 
11
15
  - **v0.40.1 — 2026-09-19**:**文档修正,无代码变更**。① **字段名写错时两族接口的表现完全不同,现在写明了**:`quote realtime` / `day-kline` / `minute-kline` / `fund-flow` 是**字段名和值一起消失**(列数与值数始终对得上,CLI 标 `partial` + `missingFields`、退出码 3);`fundamental main-business` / `valuation-analysis` 是**字段名照请求回显、行里少一个值**(`fieldList` 比行长,按下标对位会让缺口之后每个值都贴到错误的表头上,CLI 因此直接报错退出 1)。对照表在 `gangtise-openapi/references/fields.md` 顶部。② 订正 `references/commands/fundamental.md` 里一处把这两族说反的类比。**两族都不报错**,所以 `--field` 的字段名要以 `fields.md` 为准,不确定就别传(不传即返回全部字段)。
12
16
 
13
- - **v0.40.0 — 2026-09-19**:① **自选股股票池可增删改**:新增 `vault stock-pool-create` / `stock-pool-rename` / `stock-pool-add-stock` / `stock-pool-remove-stock` / `stock-pool-delete` 五个命令,全部免费、只操作本账号数据。**这是本 CLI 仅有的写操作**——`stock-pool-delete` 会连带移除池内全部关注关系且不可恢复,必须显式加 `--yes`(不加则直接报错、不发请求;个股的投资笔记不受影响)。加 / 删自选与删池是**逐条处理**的:单条失败(如证券代码不存在)服务端仍返回成功信封、明细放在 `failList`,CLI 检测到后在 stderr 点名、标 `partial`、**退出码 3**,批量脚本按退出码判断即可。池名上限 10 个字符、不可与已有池重名(分别返回 `230007` / `230006`),每账号最多 30 个池(`230003`);证券代码大小写敏感且要带市场后缀,`600519.sh` / `700.HK` 这类会进 `failList` 而不是报错。**`raw call` 打这些端点时规则完全相同**——`raw call vault.stock-pool.delete` 一样要 `--yes`,逐条失败一样退出 3。② **`indicator time-series` 的日期轴改为自动判定**:不传 `--calendar-type` 时,CLI 先用免费的 `indicator search` 读各指标的 `parameterList`(去重后每个指标码各查一次,并发)——**全部是交易日类指标才按交易日取**(无非交易日空行,单元格也更省),只要有一个报告期类指标就按自然日取。这条很要紧:报告期末常落在非交易日(如 2024-03-31、2024-06-30 均为周日),按交易日取会让报告期类指标**整行全 `null`、退出码 0、不报错**。显式传了 `--calendar-type` 就完全按给的发。③ **`indicator` 截面 / 时序新增单次 30000 单元格上限**(截面 = 证券数 × 指标数,时序 = 序列数 × 日期数),超出报 `100006` 且不返回部分结果——按这个乘积拆批。⚠️ `--security` 传板块 ID 时服务端会展开成全部成分股,实际证券数远大于写进命令的条数。④ 🔴 **Token 缓存绑定签发它的凭证**:同一台机器上换掉 `GANGTISE_ACCESS_KEY` 后,只要上一个账号的 token 还没过期,此前会继续拿它发请求——取到的是**上一个账号**的数据;本版新增的股票池写命令若撞上,改的也会是上一个账号的池。现在凭证一换即重新登录。**`auth login` 报告的是接下来真正会用的身份**(新增 `source` 字段):设了 `GANGTISE_TOKEN` 就报那个注入的 token 并说明未登录,只有走 AK/SK 时才真的登录;返回的 `cache` 描述这次登录本身,缓存落盘失败也不会混进上一个账号。⑤ **`ai knowledge-batch --query` 整段送出**:此前按逗号拆,`--query "比较两家公司毛利率,并解释差异"` 会被拆成两个半句各查一次;多个问题仍用重复 `--query`。⑥ **异步任务的提交与查询都遵守 `--output` / `--format`**:`ai earnings-review` / `viewpoint-debate` 不加 `--wait` 的提交结果,以及 `*-check` 返回「还在生成中」时的 pending 结果,此前都直接打到 stdout——传了 `--output` 却拿到退出 0 加一个不存在的文件,而 pending 恰恰是轮询脚本最需要读的那个。⑦ 错误码:新增 `230003` / `230006` / `230007` 的处置提示;`100006` 的提示补上 EDE 单元格口径。⑧ 文档:分钟线加总对日线的口径更正——**个别历史交易日的分钟数据与日线不一致**,成交量 / 成交额统计一律以日线为准,**别把「Σ分钟 = 日线」写成校验条件**(详见 `gangtise-openapi/references/fields.md`)。
17
+ - **v0.40.0 — 2026-09-19**:① **自选股股票池可增删改**:新增 `vault stock-pool-create` / `stock-pool-rename` / `stock-pool-add-stock` / `stock-pool-remove-stock` / `stock-pool-delete` 五个命令,全部免费、只操作本账号数据。**这是本 CLI 首批写操作**——`stock-pool-delete` 会连带移除池内全部关注关系且不可恢复,必须显式加 `--yes`(不加则直接报错、不发请求;个股的投资笔记不受影响)。加 / 删自选与删池是**逐条处理**的:单条失败(如证券代码不存在)服务端仍返回成功信封、明细放在 `failList`,CLI 检测到后在 stderr 点名、标 `partial`、**退出码 3**,批量脚本按退出码判断即可。池名上限 10 个字符、不可与已有池重名(分别返回 `230007` / `230006`),每账号最多 30 个池(`230003`);证券代码大小写敏感且要带市场后缀,`600519.sh` / `700.HK` 这类会进 `failList` 而不是报错。**`raw call` 打这些端点时规则完全相同**——`raw call vault.stock-pool.delete` 一样要 `--yes`,逐条失败一样退出 3。② **`indicator time-series` 的日期轴改为自动判定**:不传 `--calendar-type` 时,CLI 先用免费的 `indicator search` 读各指标的 `parameterList`(去重后每个指标码各查一次,并发)——**全部是交易日类指标才按交易日取**(无非交易日空行,单元格也更省),只要有一个报告期类指标就按自然日取。这条很要紧:报告期末常落在非交易日(如 2024-03-31、2024-06-30 均为周日),按交易日取会让报告期类指标**整行全 `null`、退出码 0、不报错**。显式传了 `--calendar-type` 就完全按给的发。③ **`indicator` 截面 / 时序新增单次 30000 单元格上限**(截面 = 证券数 × 指标数,时序 = 序列数 × 日期数),超出报 `100006` 且不返回部分结果——按这个乘积拆批。⚠️ `--security` 传板块 ID 时服务端会展开成全部成分股,实际证券数远大于写进命令的条数。④ 🔴 **Token 缓存绑定签发它的凭证**:同一台机器上换掉 `GANGTISE_ACCESS_KEY` 后,只要上一个账号的 token 还没过期,此前会继续拿它发请求——取到的是**上一个账号**的数据;本版新增的股票池写命令若撞上,改的也会是上一个账号的池。现在凭证一换即重新登录。**`auth login` 报告的是接下来真正会用的身份**(新增 `source` 字段):设了 `GANGTISE_TOKEN` 就报那个注入的 token 并说明未登录,只有走 AK/SK 时才真的登录;返回的 `cache` 描述这次登录本身,缓存落盘失败也不会混进上一个账号。⑤ **`ai knowledge-batch --query` 整段送出**:此前按逗号拆,`--query "比较两家公司毛利率,并解释差异"` 会被拆成两个半句各查一次;多个问题仍用重复 `--query`。⑥ **异步任务的提交与查询都遵守 `--output` / `--format`**:`ai earnings-review` / `viewpoint-debate` 不加 `--wait` 的提交结果,以及 `*-check` 返回「还在生成中」时的 pending 结果,此前都直接打到 stdout——传了 `--output` 却拿到退出 0 加一个不存在的文件,而 pending 恰恰是轮询脚本最需要读的那个。⑦ 错误码:新增 `230003` / `230006` / `230007` 的处置提示;`100006` 的提示补上 EDE 单元格口径。⑧ 文档:分钟线加总对日线的口径更正——**个别历史交易日的分钟数据与日线不一致**,成交量 / 成交额统计一律以日线为准,**别把「Σ分钟 = 日线」写成校验条件**(详见 `gangtise-openapi/references/fields.md`)。
14
18
 
15
- - **v0.39.0 — 2026-09-12**:① **导出文件可核验**:`csv` / `jsonl` 的 `<文件>.meta.json` 增加数据文件的字节数 `bytes` 与内容哈希 `sha256`,转交或归档前 `shasum -a 256 <文件>` 比一下,就能确认这份元信息描述的是旁边这份数据。② **并发导出到同一 `--output` 不再互相掺混**:两个进程同时写同一路径时各写各的暂存文件,最终文件是其中某一次的完整产物(此前可能把两次的行混进一个文件、还报成功);收尾时回读比对哈希,文件已被另一次导出替换就在 stderr 说明并**退出码 4**——数据是完整的,只是那个位置上的文件不是本次产物(与退出码 3 同时发生时退出 3)。并发导出请给各自不同的 `--output`。③ **K 线分片合并的缺列护栏**:合并结果的列集取自第一个有数据的分片,只有靠后分片才返回的列放不下——现在标 `partial` + `droppedColumns`、退出码 3 并在 stderr 点名(此前静默丢弃),需要这些列就缩小日期区间单独拉。④ **`fundamental valuation-analysis` 的 `--skip-null` 与 `--field` 同用**:`--skip-null` 判的是 `value` 与 `percentileRank` 两列,`--field` 没点名它们时此前会把每一行都判成空、返回 `{total: 0, list: []}`(读起来像「这只票没有估值历史」);现在自动补取这两列做过滤,输出仍只给 `--field` 点名的列。⑤ `ai stock-summary` 单次上限由 5000 放宽到接口上限 **6000**,全 A 股可一次提交完。⑥ 文档:EDE 指标覆盖按当前实测更新——`finc_pe_ttm` / `finc_pb_mrq` 港股均有数。分钟线加总对日线的口径见 `gangtise-openapi/references/fields.md`。
16
- - **v0.38.0 — 2026-09-06**:① `quote realtime` / `day-kline` / `minute-kline` 支持**沪深 ETF**(`512800.SH`)与 **20 个全球指数**(`SPX.SPI` 标普500 / `N225.NKI` 日经225 / `HSI.HI` 恒生…,清单见 `gangtise-openapi/references/commands/quote.md`),代码直接传即可;全市场关键字 `aShares` 不含 ETF;全球指数 realtime 的 `volume` / `amount` / `amplitude` 与分钟 K 的 `volume` / `amount` 为 `null`,日 K 只有 `amount` 为 `null`;`tradeTime` 是交易所当地时间。② `quote realtime` 字段集:新增 `tradeStatus`(仅 A 股 / 港股个股有值),`turnoverRate` / `volumeRatio` 不返回,美股 `amount` 为 `null`。③ **缺列护栏**:`quote` 系带 `--field` 时,请求了但服务端没回的列(字段名写错或已下线,服务端不报错)标 `partial` + `missingFields`、退出码 3 并在 stderr 点名;`--field` 只回点名的列、不自动附带身份列(日 K 要自己写进 `securityCode` / `tradeDate`,分钟 K 是 `securityCode` / `tradeTime`,realtime 是 `securityCode`;`fund-flow` 会自动附带)。④ **列结构护栏**:K 线全市场分片合并按列名对齐各片;响应的 `fieldList` 有重名列、或数组行没有 `fieldList` 时报错退出 1,不按位置拍平;`quote` 单请求收到无 `list` 的载荷报错退出 1;全量翻页从末页起步时同样做 `total` 封顶探测;后续页 / 分片自带的 `partial` 保留到合并结果。⑤ `fundamental earning-forecast` 的 `roe` 单位为百分比(`35.6` = 35.6%)。⑥ ETF 有复权因子:day-kline `adjustFactor` 与 EDE `qte_adj_factor` 都覆盖。⑦ 文档:`SKILL.md` 精简为规则 + 路由 + 引用,错误码全表、不报错的坑、`screener` 缺列判据与困境自救集中在 `references/errors.md`。⑧ `quote minute-kline` 的 `--security` 可重复,逐只并发请求后按传入顺序合并;`quote day-kline` 显式多证券在「证券数 × 交易日数」超过 `--limit` 时自动逐只请求合并,撞上限的证券标 `partial` + `truncatedSecurities`。⑨ **大导出**:`--format jsonl` / `csv` 加 `--output` 时,翻页 / 分片 / 逐只结果按到达顺序逐批写盘,内存不随行数增长(csv 磁盘两遍);落盘时旁边生成 `<文件>.meta.json`(命令、数据行数、列、`complete` 与 `partial` 等完整性标记、抓取时间与时区、CLI 版本;密钥类字段脱敏),文件转交后仍可核验。⑩ `ai stock-summary` 单次最多 5000 只(更大的批次服务端返回空列表,CLI 本地拦截并提示分批)。⑪ A 股公告与 `ai knowledge-batch` 的 `--start-time` / `--end-time` 按**北京时间**换算成毫秒,与运行机器的时区无关。⑫ 省略 `--output` 的自动命名下载并发时各得其名、不互相覆盖;`raw call auth.login` 不需要环境里先有凭证。
17
19
  ### 历史里程碑
18
20
 
21
+ - **v0.39.0**:`csv` / `jsonl` 导出的元信息加上字节数与 `sha256`,转交前可核验;并发导出到同一 `--output` 不再互相掺混,文件被另一次导出替换时退出码 4。
22
+ - **v0.38.0**:`quote realtime` / `day-kline` / `minute-kline` 支持沪深 ETF 与 20 个全球指数,代码直接传即可。
19
23
  - **v0.37.0**:下载的「智能文件命名」改为默认只读缓存,缓存未命中不再自动回查 list 接口(省下按条计费的开销),要中文文件名加 `--resolve-title`。
20
24
  - **v0.36.0**:日期写法放宽为三种「年在前」格式(「年在后」仍拒收,接口会按美式解析导致差半年),`indicator screener` 支持无日期指标。
21
25
  - **v0.29.0**:新增财报日历与 PDF 解析工具,群消息补 `quoteMsg`,并加强大整数 ID 与高积分调用防护。
@@ -70,21 +74,21 @@ export GANGTISE_TOKEN="Bearer xxx"
70
74
  # 性能/调试可选项
71
75
  export GANGTISE_PAGE_CONCURRENCY=5 # 翻页/分片并发数(默认 5,上限 32;非法值回退默认)
72
76
  export GANGTISE_VERBOSE=1 # 打印每个请求的耗时与字节数
73
- export GANGTISE_TIMEOUT_MS=30000 # 请求超时(默认 30s)
77
+ export GANGTISE_TIMEOUT_MS=30000 # 请求超时,整数毫秒(默认 30s;上限 1 小时;低于 1 秒或写法非法时用默认值;未按所写数值生效时在 stderr 提示)。one-pager 等生成类命令至少 120 秒、上传类至少 300 秒,设得更短不生效
74
78
  export GANGTISE_TOKEN_CACHE_PATH=... # 覆盖 token 缓存路径(默认 ~/.config/gangtise/token.json)
75
79
  ```
76
80
 
77
- 如果没有 `GANGTISE_TOKEN`,CLI 会自动调用 token 接口并缓存到本地(`~/.config/gangtise/token.json`,权限 0600)。Token 失效(`0000001008` / `999002`)时会自动重新登录并重试一次;凭证本身错(`999011`)不重试,直接报错让你查环境变量。
81
+ 如果没有 `GANGTISE_TOKEN`,CLI 会自动调用 token 接口并缓存到本地(`~/.config/gangtise/token.json`,权限 0600)。服务端判定 Token 失效时会自动重新登录并重试一次;凭证本身错(AK/SK 不匹配)不重试,直接报错让你查环境变量。
78
82
 
79
83
 
80
84
  ## AI Agent Skill
81
85
 
82
86
  本项目包含 Skill 定义(`gangtise-openapi/SKILL.md`),可让 AI agent 自动调用 `gangtise` CLI 完成投研数据查询。支持以下 AI 编程助手:
83
87
 
84
- - [Claude Code](https://claude.ai/claude-code) — `~/.claude/skills/`
88
+ - [Claude Code](https://claude.com/product/claude-code) — `~/.claude/skills/`
85
89
  - [Codex](https://github.com/openai/codex) — `~/.codex/skills/`
86
90
  - [OpenClaw](https://github.com/openclaw/openclaw) — `~/.openclaw/workspace/skills/`
87
- - [Hermes](https://github.com/nicepkg/hermes) — `~/.hermes/skills/`
91
+ - [Hermes](https://github.com/NousResearch/hermes-agent) — `~/.hermes/skills/`
88
92
 
89
93
  Skill 目录结构:
90
94
 
@@ -93,50 +97,40 @@ gangtise-openapi/
93
97
  ├── SKILL.md # 主 skill 文件(必备规则、速查表、按需引用 references)
94
98
  └── references/
95
99
  ├── commands/ # 按命令组拆分的详细参数文档(agent 按需 Read)
96
- │ ├── ai.md # AI 能力命令(one-pager / earnings-review / viewpoint-debate 等)
97
- │ ├── alternative.md # 行业指标数据库(EDB search / EDB data)
98
- │ ├── fundamental.md # 财务数据命令(A股/港股三大报表 / 估值 / 盈利预测 / 股东)
100
+ │ ├── ai.md # AI 能力(知识库 / 个股线索与看点 / 一页通等生成类 / 业绩点评与观点 PK 异步任务 / 热点 / 管理层讨论)
101
+ │ ├── alternative.md # 行业指标数据库 EDB(search / data)+ 题材指数画像与成分股
102
+ │ ├── bond.md # 债券(基本资料 / 发行人 / 行情与估值 / 兑付 / 公告 / 发行 / 评级 / 行权)
103
+ │ ├── fundamental.md # 财务数据(A股/港股/美股三大报表 / 主营 / 估值 / 盈利预测 / 股东)
99
104
  │ ├── indicator.md # 证券级数据指标 EDE(search / 截面 / 时序 / 条件选股)
100
- │ ├── insight.md # 投研内容命令(研报 / 观点 / 纪要 / 公告 / 外资)
101
- │ ├── quote.md # 行情命令(A股/港股/指数 K 线)
102
- │ ├── reference-and-lookup.md # GTS Code 搜索与枚举速查
103
- │ ├── tool.md # PDF 解析(file-parse)
104
- │ └── vault.md # 云盘/录音/会议/群消息/股票池
105
- ├── errors.md # 错误码全表、不报错的坑、退出码 3 的判读、Troubleshooting
105
+ │ ├── insight.md # 投研内容(研报 / 观点 / 纪要 / 公告 / 外资 / 财报日历 / 会议线索 / 公众号 / QA / 研报图表)
106
+ │ ├── quote.md # 行情(A股/港股/美股/ETF/各类指数的日 K、分钟 K、实时行情、资金流向)
107
+ │ ├── reference-and-lookup.md # 证券 / 首席 / 机构 / 公众号 / 题材 / 板块 ID 搜索与常量速查
108
+ │ ├── tool.md # PDF 解析(file-parse)/ 联网搜索(web-search)
109
+ │ └── vault.md # 云盘(含目录与文件管理)/ 录音 / 会议 / 群消息 / 股票池
110
+ ├── errors.md # 错误码全表、不报错的坑、退出码 3 / 4 的判读、Troubleshooting
106
111
  ├── examples.md # 典型场景的端到端示例
107
- ├── fields.md # K线/财务字段中英文对照速查表
112
+ ├── fields.md # 行情 / 财务 / 估值等字段中英文对照速查表
108
113
  ├── lookup-ids.md # 常用 ID 速查表(行业/券商/机构/公告分类等)
109
114
  └── response-schema.md # 各接口响应字段说明
110
115
  ```
111
116
 
112
- 安装(skill 目录随 npm 包分发,`npm install -g` 之后即可从全局安装位置复制):
117
+ 安装(skill 目录随 npm 包分发,`npm install -g` 之后即可从全局安装位置复制)。首次安装与版本更新都执行这一段,只保留你在用的助手那一行:
113
118
 
114
119
  ```bash
115
120
  SKILL_SRC="$(npm root -g)/gangtise-openapi-cli/gangtise-openapi"
116
121
 
117
- # Claude Code
118
- cp -r "$SKILL_SRC" ~/.claude/skills/gangtise-openapi
119
-
120
- # Codex
121
- cp -r "$SKILL_SRC" ~/.codex/skills/gangtise-openapi
122
+ # 先删旧副本再复制:目标目录已存在时直接 cp -r 会复制进嵌套的 gangtise-openapi/gangtise-openapi/,旧版原样留着
123
+ install_skill() { rm -rf "$1/gangtise-openapi" && mkdir -p "$1" && cp -R "$SKILL_SRC" "$1/gangtise-openapi"; }
122
124
 
123
- # OpenClaw
124
- cp -r "$SKILL_SRC" ~/.openclaw/workspace/skills/gangtise-openapi
125
-
126
- # Hermes
127
- cp -r "$SKILL_SRC" ~/.hermes/skills/gangtise-openapi
125
+ install_skill ~/.claude/skills # Claude Code
126
+ install_skill ~/.codex/skills # Codex
127
+ install_skill ~/.openclaw/workspace/skills # OpenClaw
128
+ install_skill ~/.hermes/skills # Hermes
128
129
  ```
129
130
 
130
- > 从仓库 clone 开发时,把 `$SKILL_SRC` 换成仓库内的 `gangtise-openapi` 目录即可。
131
+ > 从仓库 clone 开发时,把 `$SKILL_SRC` 换成仓库内 `gangtise-openapi` 目录的绝对路径即可。
131
132
 
132
- > **版本更新**:每次 CLI 发版时,`gangtise-openapi/SKILL.md` 的 `version` 字段会自动同步。更新 CLI 后,请将项目中的 `gangtise-openapi/` 目录重新复制到对应的 skills 目录覆盖更新:
133
- >
134
- > ```bash
135
- > # 示例:更新 Claude Code 的 skill
136
- > cp -r gangtise-openapi ~/.claude/skills/gangtise-openapi
137
- > ```
138
- >
139
- > 可通过查看 SKILL.md 头部的 `version` 字段确认当前版本。
133
+ > **版本更新**:`SKILL.md` 头部的 `version` 字段与 CLI 版本一致。`npm update -g gangtise-openapi-cli` 之后重新执行上面这段,再看已安装副本的 `version` 是否与 `gangtise --version` 相同。对已安装副本做过的本地修改会被覆盖。
140
134
 
141
135
  安装后,可以用自然语言触发,例如:
142
136
  - "帮我查今天所有的研报"
@@ -179,7 +173,7 @@ cp -r "$SKILL_SRC" ~/.hermes/skills/gangtise-openapi
179
173
  | | `sector-constituents` | 板块成分股查询 |
180
174
  | **Quote** | `day-kline` | 历史日K线——A股/港股/美股个股 + 沪深 ETF + 交易所/概念/行业指数 + 20 个全球指数,可混查 |
181
175
  | | `day-kline-hk` / `day-kline-us` | ⚠️ 已下线,能力并入 `day-kline`(接口仍可调,但不校验证券代码) |
182
- | | `index-day-kline` | ⚠️ 已下线,能力并入 `day-kline`;但仍是取「全部沪深京指数」(`--security all`)和拿指数名称(`securityName`)的唯一方式 |
176
+ | | `index-day-kline` | ⚠️ 已下线,能力并入 `day-kline`(返回字段相同);只收明确的指数代码,`--security all` 会被 CLI 拒绝 |
183
177
  | | `minute-kline` | 分钟K线——沪深A股 / ETF + 各类指数含全球指数(`--security` 可重复,逐只并发合并) |
184
178
  | | `realtime` | 实时行情快照——A股/港股/美股个股 + 沪深 ETF + 各类指数含全球指数 |
185
179
  | | `fund-flow` | A股个股日资金流向(沪深京;小/中/大/特大单 + 主力净流入) |
@@ -239,7 +233,8 @@ cp -r "$SKILL_SRC" ~/.hermes/skills/gangtise-openapi
239
233
  | | `concept-securities` | 题材指数成分股(按分组;50 积分/次,`--full` 另含重点个股标识与纳入理由 500 积分/次) |
240
234
  | **Tool** | `file-parse` / `file-parse-check` | PDF 解析为 Markdown + 图片(异步,返回 ZIP) |
241
235
  | | `web-search` | 联网搜索(公开互联网定向检索,信源分级 T0–T3,可选返回正文;1 积分/次) |
242
- | **Raw** | `call` | 原始接口调用(可访问任意 JSON / download endpoint;upload 型的 `tool.file-parse.submit` / `vault.drive.upload` 需走 `tool file-parse` / `vault drive-upload`,raw 带不了文件) |
236
+ | **Raw** | `list` | 列出全部 endpoint key(供 `raw call` 使用) |
237
+ | | `call` | 原始接口调用(可访问任意 JSON / download endpoint;upload 型的 `tool.file-parse.submit` / `vault.drive.upload` 需走 `tool file-parse` / `vault drive-upload`,raw 带不了文件) |
243
238
 
244
239
  ## 命令概览
245
240
 
@@ -288,10 +283,10 @@ gangtise ai knowledge-batch --query 比亚迪 --query 最近热门概念
288
283
  ## 性能特性
289
284
 
290
285
  - **并发翻页**:自动翻页接口的首页拿到 `total` 后,剩余页用 `Promise.all` 并发拉取(默认并发数 5,可通过 `GANGTISE_PAGE_CONCURRENCY` 调整)。20 页查询从串行 ~10s 降到 ~2s。
291
- - **HTTP keep-alive**:所有请求复用同一个 `undici.Agent`(连接池 16),避免重复 TLS 握手。
286
+ - **HTTP keep-alive**:所有请求复用同一个 `undici.Agent`(连接池不少于 16,且不少于翻页并发数),避免重复 TLS 握手。
292
287
  - **流式下载**:指定 `--output` 时,二进制响应(PDF 等)直接 `pipeline` 到磁盘,不经过内存缓冲;50MB PDF 内存占用近乎为零。
293
- - **流式输出**:`--format jsonl` 或 `csv` 加 `--output <file>` 时,翻页 / 全市场分片 / 逐只请求的行**按到达顺序逐批写盘**,取数阶段不再持有整份结果,内存不随行数增长(80 万行导出常驻约 150 MB);csv 先落临时行文件、收尾时按列并集写表头再转成 csv(磁盘两遍、内存不变)。不足 1000 行的结果仍走原来的整体写出,文件字节与之前一致。任一只 / 页 / 片失败,命令退出时后台已无取数与写盘,不留 `.part`。
294
- - **导出元信息**:`csv` / `jsonl` 落盘时旁边生成 `<文件>.meta.json`——命令行、数据行数、列名、`complete`(与退出码一致:退出 3 即 `false`)、`total` / `partial` / `failedPages` / `failedShards` / `truncatedShards` / `droppedColumns` / `missingFields` 等全部完整性标记、抓取时间与时区、CLI 版本,以及数据文件的字节数 `bytes` 与内容哈希 `sha256`。命令行与结果里的 key / secret / token 类字段写成 `[redacted]`。元信息在数据文件发布之后才就位,导出失败不会留下新数据配旧元信息。**转交或归档前建议核一次**:`shasum -a 256 <文件>` 与元信息里的 `sha256` 相等,才说明这份元信息描述的就是旁边这份数据——两个进程同时导出到**同一个 `--output`** 时,最终文件一定是其中某一次的完整产物,但旁边的元信息有可能来自另一次,核哈希就能发现。**输的那一次自己也会报**:收尾时回读一次 `--output`,与本次写出的哈希不符就在 stderr 说明「这个文件不是本次命令的产物」并**退出码 4**。这两种格式的文件本身只有数据行,转交之后靠它核验是否完整;`json` 自带标记,不生成。
288
+ - **流式输出**:`--format jsonl` 或 `csv` 加 `--output <file>` 时,翻页 / 全市场分片 / 逐只请求的行**按到达顺序逐批写盘**,取数阶段不持有整份结果,内存不随行数增长(80 万行导出常驻约 150 MB);csv 先落临时行文件、收尾时按列并集写表头再转成 csv(磁盘两遍、内存不变)。不足 1000 行的结果一次整体写出。任一只 / 页 / 片失败,命令退出时后台已无取数与写盘,不留 `.part`。
289
+ - **导出元信息**:`csv` / `jsonl` 落盘时旁边生成 `<文件>.meta.json`——命令行、数据行数、列名、`complete`(写元信息时的判定:退出 3 即 `false`)、`total` / `partial` / `failedPages` / `failedShards` / `truncatedShards` / `droppedColumns` / `missingFields` 等全部完整性标记、抓取时间与时区、CLI 版本,以及数据文件的字节数 `bytes` 与内容哈希 `sha256`。命令行与结果里的 key / secret / token 类字段写成 `[redacted]`。元信息在数据文件发布之后才就位,导出失败不会留下新数据配旧元信息。**转交或归档前建议核一次**:`shasum -a 256 <文件>` 与元信息里的 `sha256` 相等,才说明这份元信息描述的就是旁边这份数据——两个进程同时导出到**同一个 `--output`** 时,最终文件一定是其中某一次的完整产物,但旁边的元信息有可能来自另一次,核哈希就能发现。**输的那一次自己也会报**:收尾时回读一次 `--output`,与本次写出的哈希不符就在 stderr 说明「这个文件不是本次命令的产物」并**退出码 4**。这两种格式的文件本身只有数据行,转交之后靠它核验是否完整;`json` 自带标记,不生成。
295
290
  - **自动重试**:5xx / 429 / `ECONNREFUSED` / `ECONNRESET` / `ETIMEDOUT` / `ENOTFOUND` / `EAI_AGAIN` / `UND_ERR_*`(undici 连接/超时类)/ `999999` 系统错误自动指数退避重试 2 次。**不重放的端点例外**(贵档:one-pager 等生成/提交类 + `tool file-parse` 提交 + 50/篇 的 summary / foreign-report / my-conference 下载 + 单价未公布但保守同档的 pamirs-summary 下载 + 题材 `concept-info` / `concept-securities`(含 `--full`);按次计费的 `bond` 全部 12 个命令与 `tool web-search`;按条计费的 `insight highlight list`、观点 `detail` 与 `list --with-content`;另加不计分但不可重复执行的 `vault stock-pool-create` 与云盘的上传 / 新建文件夹 / 复制 / 两个删除,共 44 个):5xx/超时不重放,仅连接失败、429 与 token 自愈重试。**两类端点各有各的理由**:贵档是**重放会重复扣分**——服务端可能已经执行并计费,重发按次计费的再扣一次,重发按篇/按条计费的会把已交付的行再计一次;不计分的那几个是**重放会造成副作用或把成功报成失败**——股票池名不允许重复,重发一个其实已经建成的请求,回来的是 `230006 股票池名称重复`;云盘允许同名,重发上传 / 新建 / 复制会多出一份;重发一个其实已经删掉的删除,回来的是「文件不存在」或 `130002`。**`indicator`(EDE)端点对 `999999` 不重试**——重放一次已计费的查询没有意义(EDE 无数据不用此码,而是保留行列的占位单元格 `null`;空表另表示整轴 code 未识别或参数名写错)。**终态码 `999011`(凭证无效)/ `140002`(终态失败:异步生成失败、参数错误或业务处理失败)在任何 HTTP 状态下都不重试**——凭证错不会因重试而变,`140002` 立即重发得到的还是同一结果。
296
291
 
297
292
  <!-- no-replay-endpoints
@@ -341,10 +336,10 @@ vault.drive.upload
341
336
  vault.my-conference.download
342
337
  vault.stock-pool.create
343
338
  -->
344
- - **Token 自愈**:调用返回 `0000001008` / `999002` 时自动强制刷新 Token 并重试一次。
339
+ - **Token 自愈**:服务端判定 Token 失效时自动强制刷新 Token 并重试一次。
345
340
  - **Token 缓存绑定账号**:缓存记录它是为哪组凭证 + 哪个 `GANGTISE_BASE_URL` 签发的(只存不可逆的指纹,不存 key 本身)。换了 `GANGTISE_ACCESS_KEY` 再跑,即使旧 token 还没过期也会重新登录,**不会拿上一个账号的身份去发请求**——这点在股票池那五个写命令上尤其要紧。
346
341
  - **`auth login` 报告的是「接下来真正会用的身份」**,返回体里的 `source` 说明它从哪来:`GANGTISE_TOKEN` 有值时是 `env-token`(那个 token 对所有命令优先,所以不联服务端、也不签发新的,并附一句提示);没有它、有 AK/SK 时是 `login`(每次都真的登录,不复用缓存);两者都没有才报错。返回的 `cache` 描述的就是这次登录的结果,缓存落盘失败也不会混进上一个账号的信息。
347
- - **K线/资金流向自动分片**:`quote day-kline --security aShares|hkStocks|usStocks`、`quote fund-flow --security aShares` 等全市场查询自动按日期切分(A股 K线/资金流向 1 天/片、美股 1 天/片、港股 2 天/片;已下线的 `day-kline-hk`/`day-kline-us`/`index-day-kline` 用 `all`,分别 2/1/15 天/片),并发执行后合并结果;按日分片自动跳过周六日。分片时如果用户未传 `--limit`,自动注入 `limit: 10000`(API 上限)避免默认 6000 截断。**显式多证券**的日 K 在「证券数 × 交易日数」超过 `--limit` 时自动逐只请求并按传入顺序合并(撞上限的证券标 `partial` + `truncatedSecurities`);`minute-kline` 的 `--security` 可重复,逐只并发请求后合并。
342
+ - **K线/资金流向自动分片**:`quote day-kline --security aShares|hkStocks|usStocks`、`quote fund-flow --security aShares` 等全市场查询自动按日期切分(A股 K线/资金流向 1 天/片、美股 1 天/片、港股 2 天/片;已下线的 `day-kline-hk`/`day-kline-us` 用 `all`,分别 2/1 天/片),并发执行后合并结果;按日分片自动跳过周六日。分片时如果用户未传 `--limit`,自动注入 `limit: 10000`(API 上限)避免默认 6000 截断。**显式多证券**的日 K 在「证券数 × 交易日数」超过 `--limit` 时自动逐只请求并按传入顺序合并(撞上限的证券标 `partial` + `truncatedSecurities`);`minute-kline` 的 `--security` 可重复,逐只并发请求后合并。
348
343
  - **Token 内存缓存**:Token 在进程内存中缓存,避免每次请求读盘。
349
344
  - **`--verbose`**:打印每个请求的方法、路径、状态码、耗时和响应大小到 stderr,方便定位慢查询。
350
345
 
@@ -384,7 +379,7 @@ vault.stock-pool.create
384
379
  - `--from` 必须是非负整数,`--size` 必须是正整数;非法数字会在本地直接报 `ValidationError`,不会继续请求 API
385
380
  - 安全上限:自动翻页最多 1000 页,防止异常循环
386
381
  - 部分页失败、或服务端实际返回行数与 `total` 矛盾(提前短页)时,不丢弃已取到的数据:结果带 `partial: true`(页失败时另有 `failedPages`;K线分片为 `failedShards`,只有部分分片返回、合并时放不下的列为 `droppedColumns`;`quote` 系带 `--field` 而服务端没回的列为 `missingFields`;`--format json` 可见),stderr 输出警告,**进程退出码为 3**(完整成功为 0)
387
- - **`indicator` 命令的退出码 3**(脚本按 `!= 0` 判失败的需留意):服务端整指标/整证券没返回时标 `partial` + `omittedIndicators` / `omittedSecurities` 并退出 3。这个分支很少触发——服务端对解析不了的代码直接报 `100003` 并点名是哪个(指标码拼错 →「指标 xxx 不存在」;证券后缀错,如美股写成 `AAPL.US` 而非 `AAPL.O` →「xxx 不是有效证券或者板块ID」),**无论同批有没有正确的代码都会报**,CLI 相应退出 1。真实的无数据/无覆盖仍是占位单元格 + 退出码 0。占位值统一是 `null`。⚠️ **报告期类指标(`is_*`)的时序上大部分行都是占位**(只有报告期末那几行是真值),`null` 虽被 Excel / pandas / SQL 的聚合跳过,**但行数不变**,手工「总和 ÷ 行数」仍会差几十倍;详见 skill 的 `references/commands/indicator.md`。**条件选股的缺列另有更严的一档**:把缺列的变量当作无法求值,若表达式(按 `&&`/`||` 的布尔结构)再无任何可成立的分支,则**退出码 1 且不输出**——那些行以「通过了该条件」的名义呈现,而条件根本无法证明被执行过。⚠️ 这一档以「服务端返回了命中行」为前提;**零命中时一律退出码 0**(没有行需要被质疑),所以空集不能直接当成「无标的符合条件」——另有两种成因产生**逐字相同**的输出:**日期没落在报告期末**(报告期类指标此时整批 `null`),或**该指标不覆盖这批证券**(如拿 A 股专属指标查港美股)。语义约定:`0` 完整成功(含合法空结果)/`3` 有数据但不完整/`4` 数据写出完整、但 `--output` 指向的文件在收尾期间被另一次写向同一路径的导出替换掉了(不是本次命令的产物,stderr 会说明并给出两边的 sha256 前缀;与 `3` 同时发生时退出 `3`)/`1` 硬失败
382
+ - **`indicator` 命令的退出码 3**(脚本按 `!= 0` 判失败的需留意):服务端整指标/整证券没返回时标 `partial` + `omittedIndicators` / `omittedSecurities` 并退出 3。这个分支很少触发——服务端对解析不了的代码直接报 `100003` 并点名是哪个(指标码拼错 →「指标 xxx 不存在」;证券后缀错,如美股写成 `AAPL.US` 而非 `AAPL.O` →「xxx 不是有效证券或者板块ID」),**无论同批有没有正确的代码都会报**,CLI 相应退出 1。真实的无数据/无覆盖仍是占位单元格 + 退出码 0。占位值统一是 `null`。⚠️ **报告期类指标(`is_*`)的时序上大部分行都是占位**(只有报告期末那几行是真值),`null` 虽被 Excel / pandas / SQL 的聚合跳过,**但行数不变**,手工「总和 ÷ 行数」仍会差几十倍;详见 skill 的 `references/commands/indicator.md`。**条件选股的缺列另有更严的一档**:把缺列的变量当作无法求值,若表达式(按 `&&`/`||` 的布尔结构)再无任何可成立的分支,则**退出码 1 且不输出**——那些行以「通过了该条件」的名义呈现,而条件根本无法证明被执行过。⚠️ 这一档以「服务端返回了命中行」为前提;**零命中时一律退出码 0**(没有行需要被质疑),所以空集不能直接当成「无标的符合条件」——另有两种成因产生**逐字相同**的输出:**日期没落在报告期末**(报告期类指标此时整批 `null`),或**该指标不覆盖这批证券**(如拿 A 股专属指标查港美股)。语义约定:`0` 完整成功(含合法空结果)/`3` 有数据但不完整/`4` 数据写出完整、但 `--output` 指向的文件在收尾期间被另一次写向同一路径的导出替换掉了(不是本次命令的产物,stderr 会说明并给出两边的 sha256 前缀;与 `3` 同时发生时退出 `3`)/`1` 硬失败。接 `| head` 等管道提前关掉读端时,退出码同样保留,脚本需 `set -o pipefail` 才看得到
388
383
  - **分页端点返回 `null` 也退出 3**:分页端点的正常响应是 `{total, list}`,真实的空结果是 `{total: 0, list: []}`。若响应体是 `null`,CLI 在 stderr 告警并**退出码 3**——只给告警的话,脚本无法区分「这个筛选确实没命中」和「这个筛选没生效」。机器格式(jsonl/csv)此时 **stdout 不输出任何字节**(不是空行),`--format json` 仍忠实打印 `null`。⚠️ 带 `--output` 时文件仍会被创建:csv 会写入 3 字节 UTF-8 BOM(Excel 兼容用),jsonl 为 0 字节(旁边的 `.meta.json` 标 `complete: false`)——**按文件大小判空的脚本要留意 csv 的这 3 个字节**。
389
384
  - 🔴 **`total` 被服务端封顶时会标 `totalCapped` 并退出 3**:分页端点的 `total` 若被服务端封顶(返回一个固定上限而非真实条数),省略 `--size` 的全量拉取会**正好取满那个上限就停、且不报任何异常**——导出的文件是截断的却看不出来。全量拉取结束后会**多探一行**(`from = total`):探到数据就标 `partial` + `totalCapped` 并退出 3。判据不写死 10000,服务端改配置仍然有效;`total` 诚实时探针返回空、不产生计费。传了 `--size` 的有界请求不做此探测。
390
385
  - 分页结果中 `total` 字段会被保留(json 格式输出 `{total, list}`);其他格式下 stderr 输出 `Total: N, showing: M`(json 格式不输出该行)
@@ -559,8 +554,8 @@ gangtise quote day-kline --security 512800.SH --security SPX.SPI --security N225
559
554
  gangtise quote day-kline --security hkStocks --start-date 2026-04-01 --end-date 2026-04-10 --format json
560
555
  # 美股全市场(自动按 1 天/片分片)
561
556
  gangtise quote day-kline --security usStocks --start-date 2026-04-01 --end-date 2026-04-02 --field securityCode --field close --format json
562
- # 沪深京指数日K线
563
- 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
557
+ # 沪深京指数日K线(逐个传指数代码;要指数名称用 reference securities-search --category index)
558
+ gangtise quote 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
564
559
  # A股分钟K线
565
560
  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
566
561
  # 实时行情:三大市场混合查询
@@ -904,7 +899,8 @@ CLI 会在本地校验常见数值参数,避免把明显非法的请求发到
904
899
 
905
900
  - `--from`:非负整数
906
901
  - `--size` / `--limit` / `--top`:正整数
907
- - `--file-type` / `--resource-type` 以及数值型列表参数:有限数字
902
+ - `--file-type` / `--resource-type` 以及数值型列表参数:整数
903
+ - 数值一律按十进制写法解析:`0x10`、`1e3`、`5.0` 这类写法在发请求前拒绝,不会被悄悄换算成别的数
908
904
  - 所有 date 参数(`--start-date`/`--end-date`/`--date`/`--report-date`,含 Quote/Fundamental/AI/Alternative/Indicator):`YYYY-MM-DD`、`YYYY/MM/DD` 或 `YYYYMMDD`,统一归一成 `YYYY-MM-DD` 发出(年在后等歧义写法在发请求前拒绝,见下节)
909
905
  - 所有 `--start-time` / `--end-time`(Insight/Vault/AI 透传、`quote minute-kline`,以及 A 股公告 / `knowledge-batch` 两个转换端点):上述三种日期写法 + 可选的 `[ HH:mm[:ss]]`(秒可省、空格或 `T` 分隔),或 10/13 位 Unix 时间戳(同样归一日期部分、拒绝年在后写法)。两个转换端点把日期与时刻按**北京时间**换算成毫秒,与运行机器的时区无关
910
906
 
@@ -964,7 +960,7 @@ datetime 参数(`--start-time` / `--end-time`)同理,只归一日期部分
964
960
 
965
961
  > **错误码分两代并存**:服务端错误码分三层(`999xxx` 服务统一层 / `1xxxxx` 业务通用层 / `2xxxxx` 接口专有层),信封带 `errorType` 和 `traceId`。按「错误处理层」而不是按业务模块划分:参数校验层与路由层发新码(信封 `code` 是 JSON 数字且带 `errorType`),方法路由层、token 过滤器、以及异步生成状态仍发旧码(字符串、无 `errorType`)——这判断的是单条错误路径,不是整个接口;CLI 对两代都能识别。报错行会带 `[trace <id>]`,**报障时请带上它**。
966
962
  >
967
- > 其余码(`999003`–`999006`、`999012`–`999016`、`100002`、`210001`、`220001`、`230001`、`240002`、`240003`)未见触发,多被上面的兜底码接管,CLI 仍内置了对应提示。⚠️ 两个需要留意的行为:**枚举值拼错和分页越界在部分端点上会报 `100005`/`100006`、在另一些端点上被静默忽略**(后者按未传该筛选条件处理,结果看着正常但范围不对——CLI 对 `--search-type`/`--rank-type`/`--file-type` 等已知枚举本地拦截,未覆盖的自由字符串参数要自己核对);**`viewpoint-debate` 的敏感内容不会被提前拦截**,会扣满 50 积分再以 `410111` 失败。
963
+ > 表里没列的码(`999004`、`999007`–`999009`、`999015`、`100002`、`210001`、`220001`、`230001`、`240002`、`240003` 等)多被上面的兜底码接管,CLI 同样内置了对应提示,逐条说明见 skill 的 `references/errors.md`。⚠️ 两个需要留意的行为:**枚举值拼错和分页越界在部分端点上会报 `100005`/`100006`、在另一些端点上被静默忽略**(后者按未传该筛选条件处理,结果看着正常但范围不对——CLI 对 `--search-type`/`--rank-type`/`--file-type` 等已知枚举本地拦截,未覆盖的自由字符串参数要自己核对);**`viewpoint-debate` 的敏感内容不会被提前拦截**,会扣满 50 积分再以 `410111` 失败。
968
964
 
969
965
  ---
970
966
 
@@ -977,6 +973,8 @@ npm 发版通过 GitHub Actions Trusted Publishing 完成,不需要 `NPM_TOKEN
977
973
  ```bash
978
974
  npm version patch --no-git-tag-version
979
975
  npm run prepare
976
+ npm test && TZ=UTC npx vitest run # CI 是 UTC,两个时区都要过
977
+ npm audit --omit=dev --registry=https://registry.npmjs.org # 显式走官方源:默认源是 npmmirror 时审计请求会 404,报不出告警
980
978
  VERSION=$(node -p "require('./package.json').version")
981
979
  git commit -am "chore: release v$VERSION"
982
980
  git tag -a "v$VERSION" -m "v$VERSION" # 必须 annotated
@@ -984,4 +982,4 @@ git push origin main "v$VERSION" # 显式带 tag 名,不用 --follow-t
984
982
  git ls-remote --tags origin "v$VERSION" # 确认 tag 真的在远端
985
983
  ```
986
984
 
987
- 推送 `v*` tag 后,`.github/workflows/publish.yml` 会在 GitHub-hosted runner 上使用 OIDC 发布到 `https://registry.npmjs.org/`。也可以从 GitHub Actions 页面手动运行该 workflow。
985
+ 推送 `v*` tag 后,`.github/workflows/publish.yml` 会在 GitHub-hosted runner 上依次跑类型检查、测试和「打包 → 全局安装 → `gangtise --version` 等于 tag」冒烟,全部通过后使用 OIDC 发布到 `https://registry.npmjs.org/`,任一步失败都不发包。也可以从 GitHub Actions 页面手动运行该 workflow。