gangtise-openapi-cli 0.9.0 → 0.10.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 +19 -1
- package/dist/src/cli.js +60 -13
- package/dist/src/core/endpoints.js +37 -0
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ export GANGTISE_TOKEN="Bearer xxx"
|
|
|
64
64
|
| | `income-statement-quarterly` / `cash-flow-quarterly` | 利润表/现金流量表(单季度) |
|
|
65
65
|
| | `main-business` | 主营构成(按地区/产品拆分) |
|
|
66
66
|
| | `valuation-analysis` | 估值分析 |
|
|
67
|
+
| | `earning-forecast` | 盈利预测(一致预期) |
|
|
67
68
|
| **AI** | `knowledge-batch` | 知识库批量检索 |
|
|
68
69
|
| | `knowledge-resource-download` | 知识资源下载 |
|
|
69
70
|
| | `security-clue` | 个股线索 |
|
|
@@ -78,6 +79,8 @@ export GANGTISE_TOKEN="Bearer xxx"
|
|
|
78
79
|
| | `management-discuss-earnings-call` | 管理层讨论-业绩会 |
|
|
79
80
|
| | `viewpoint-debate` / `viewpoint-debate-check` | 观点PK(异步) |
|
|
80
81
|
| **Vault** | `drive-list` / `drive-download` | 云盘文件列表与下载 |
|
|
82
|
+
| | `record-list` / `record-download` | 录音速记列表与下载 |
|
|
83
|
+
| | `my-conference-list` / `my-conference-download` | 我的会议列表与下载 |
|
|
81
84
|
| **Raw** | `call` | 原始接口调用(可访问任意 endpoint) |
|
|
82
85
|
|
|
83
86
|
## AI Agent Skill
|
|
@@ -165,6 +168,8 @@ gangtise ai knowledge-batch --query 比亚迪 --query 最近热门概念
|
|
|
165
168
|
- `insight announcement list`
|
|
166
169
|
- `ai security-clue`
|
|
167
170
|
- `vault drive-list`
|
|
171
|
+
- `vault record-list`
|
|
172
|
+
- `vault my-conference-list`
|
|
168
173
|
- `ai hot-topic`
|
|
169
174
|
|
|
170
175
|
规则:
|
|
@@ -174,7 +179,7 @@ gangtise ai knowledge-batch --query 比亚迪 --query 最近热门概念
|
|
|
174
179
|
|
|
175
180
|
## 智能文件命名
|
|
176
181
|
|
|
177
|
-
下载命令(`summary download`、`research download`、`foreign-report download`、`announcement download`、`vault drive-download`)省略 `--output` 时,自动使用真实标题作为文件名:
|
|
182
|
+
下载命令(`summary download`、`research download`、`foreign-report download`、`announcement download`、`vault drive-download`、`vault record-download`、`vault my-conference-download`)省略 `--output` 时,自动使用真实标题作为文件名:
|
|
178
183
|
|
|
179
184
|
1. **缓存优先** — 如果之前执行过对应的 `list` 命令,标题已缓存在 `~/.config/gangtise/title-cache.json`,直接使用,无额外 API 调用
|
|
180
185
|
2. **API 回查** — 缓存未命中时,自动查询最近 200 条记录匹配标题
|
|
@@ -253,6 +258,8 @@ gangtise fundamental main-business --security-code 600519.SH --breakdown region
|
|
|
253
258
|
# 多报告期:--period 可传多个值
|
|
254
259
|
gangtise fundamental main-business --security-code 600519.SH --breakdown product --period annual --period interim
|
|
255
260
|
gangtise fundamental valuation-analysis --security-code 600519.SH --indicator peTtm
|
|
261
|
+
# 盈利预测(一致预期)
|
|
262
|
+
gangtise fundamental earning-forecast --security-code 600519.SH --consensus netIncome --consensus eps --consensus pe
|
|
256
263
|
# 利润表(单季度)
|
|
257
264
|
gangtise fundamental income-statement-quarterly --security-code 600519.SH --fiscal-year 2025 --period q2 --field netProfit
|
|
258
265
|
# 现金流量表(单季度)
|
|
@@ -296,6 +303,16 @@ gangtise vault drive-list --keyword 部门文档 --space-type 1 --file-type 1
|
|
|
296
303
|
# 云盘下载:自动使用文件标题命名
|
|
297
304
|
gangtise vault drive-download --file-id 62130
|
|
298
305
|
# → 2028 全球智能危机 一份来自未来的金融史思想实验 .pdf
|
|
306
|
+
|
|
307
|
+
# 录音速记列表
|
|
308
|
+
gangtise vault record-list --keyword 晨会 --category upload --category mobile
|
|
309
|
+
# 录音速记下载(--content-type: original/asr/summary)
|
|
310
|
+
gangtise vault record-download --record-id 49412 --content-type summary
|
|
311
|
+
|
|
312
|
+
# 我的会议列表
|
|
313
|
+
gangtise vault my-conference-list --keyword AI --category earningsCall --institution C100000027
|
|
314
|
+
# 我的会议下载(--content-type: asr/summary)
|
|
315
|
+
gangtise vault my-conference-download --conference-id 43319 --content-type asr
|
|
299
316
|
```
|
|
300
317
|
|
|
301
318
|
### Raw
|
|
@@ -331,3 +348,4 @@ gangtise raw call insight.opinion.list --body '{"from":0,"size":120}'
|
|
|
331
348
|
| `999997` | 未开通接口权限 |
|
|
332
349
|
| `999999` | Gangtise 系统错误,请稍后重试 |
|
|
333
350
|
| `433007` | 不支持该数据源(`knowledge-resource-download` 需正确的 `resourceType + sourceId` 组合) |
|
|
351
|
+
| `430007` | 行情查询超出限制(日K线/分钟K线不传 `--security` 返回全市场,数据量过大;请指定证券代码或缩短日期范围) |
|
package/dist/src/cli.js
CHANGED
|
@@ -390,6 +390,10 @@ fundamental.command("valuation-analysis").requiredOption("--security-code <code>
|
|
|
390
390
|
const client = await createClient();
|
|
391
391
|
await printData(await client.call("fundamental.valuation-analysis", { securityCode: options.securityCode, indicator: options.indicator, startDate: options.startDate, endDate: options.endDate, limit: options.limit ? Number(options.limit) : undefined, fieldList: maybeArray(options.field) }), parseFormat(options.format), options.output);
|
|
392
392
|
});
|
|
393
|
+
fundamental.command("earning-forecast").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").option("--consensus <name>", "Consensus indicator: netIncome/netIncomeYoy/eps/pe/bps/pb/peg/roe/ps", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
|
|
394
|
+
const client = await createClient();
|
|
395
|
+
await printData(await client.call("fundamental.earning-forecast", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, consensusList: maybeArray(options.consensus) }), parseFormat(options.format), options.output);
|
|
396
|
+
});
|
|
393
397
|
program.addCommand(fundamental);
|
|
394
398
|
const ai = new Command("ai").description("AI APIs");
|
|
395
399
|
ai.command("knowledge-batch").requiredOption("--query <text>", "Query", collectList, []).option("--top <number>", "Top", "10").option("--resource-type <number>", "Resource type", collectNumberList, []).option("--knowledge-name <name>", "Knowledge name", collectList, []).option("--start-time <ms>").option("--end-time <ms>").option("--format <format>", "Output format", "json").option("--output <path>").action(async (options) => {
|
|
@@ -439,10 +443,17 @@ ai.command("earnings-review").requiredOption("--security-code <code>").requiredO
|
|
|
439
443
|
const delayMs = 15_000;
|
|
440
444
|
while (attempts < maxAttempts) {
|
|
441
445
|
attempts++;
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
+
try {
|
|
447
|
+
const contentResult = await client.call("ai.earnings-review.get-content", { dataId });
|
|
448
|
+
if (contentResult?.data?.content) {
|
|
449
|
+
await printData(contentResult.data, parseFormat(options.format), options.output);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
if (!(error instanceof ApiError && (error.code === "410110" || error.message?.includes("生成中")))) {
|
|
455
|
+
throw error;
|
|
456
|
+
}
|
|
446
457
|
}
|
|
447
458
|
if (attempts < maxAttempts) {
|
|
448
459
|
process.stderr.write(`Attempt ${attempts}/${maxAttempts}: content not ready, retrying in 15s...\n`);
|
|
@@ -531,10 +542,17 @@ ai.command("viewpoint-debate").requiredOption("--viewpoint <text>", "Viewpoint t
|
|
|
531
542
|
const delayMs = 15_000;
|
|
532
543
|
while (attempts < maxAttempts) {
|
|
533
544
|
attempts++;
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
545
|
+
try {
|
|
546
|
+
const contentResult = await client.call("ai.viewpoint-debate.get-content", { dataId });
|
|
547
|
+
if (contentResult?.data?.content) {
|
|
548
|
+
await printData(contentResult.data, parseFormat(options.format), options.output);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
catch (error) {
|
|
553
|
+
if (!(error instanceof ApiError && (error.code === "410110" || error.message?.includes("生成中")))) {
|
|
554
|
+
throw error;
|
|
555
|
+
}
|
|
538
556
|
}
|
|
539
557
|
if (attempts < maxAttempts) {
|
|
540
558
|
process.stderr.write(`Attempt ${attempts}/${maxAttempts}: content not ready, retrying in 15s...\n`);
|
|
@@ -546,12 +564,21 @@ ai.command("viewpoint-debate").requiredOption("--viewpoint <text>", "Viewpoint t
|
|
|
546
564
|
});
|
|
547
565
|
ai.command("viewpoint-debate-check").requiredOption("--data-id <id>", "dataId from viewpoint-debate").option("--format <format>", "Output format", "json").option("--output <path>").action(async (options) => {
|
|
548
566
|
const client = await createClient();
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
567
|
+
try {
|
|
568
|
+
const contentResult = await client.call("ai.viewpoint-debate.get-content", { dataId: options.dataId });
|
|
569
|
+
if (contentResult?.data?.content) {
|
|
570
|
+
await printData(contentResult.data, parseFormat(options.format), options.output);
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
process.stdout.write(`${JSON.stringify({ dataId: options.dataId, status: "pending", hint: "Content not ready yet, retry in ~2 minutes" })}\n`);
|
|
574
|
+
}
|
|
575
|
+
catch (error) {
|
|
576
|
+
if (error instanceof ApiError && (error.code === "410110" || error.message?.includes("生成中"))) {
|
|
577
|
+
process.stdout.write(`${JSON.stringify({ dataId: options.dataId, status: "pending", hint: "Content not ready yet, retry in ~2 minutes" })}\n`);
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
throw error;
|
|
553
581
|
}
|
|
554
|
-
process.stdout.write(`${JSON.stringify({ dataId: options.dataId, status: "pending", hint: "Content not ready yet, retry in ~2 minutes" })}\n`);
|
|
555
582
|
});
|
|
556
583
|
const vault = new Command("vault").description("Vault APIs");
|
|
557
584
|
vault.command("drive-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("--file-type <number>", "File type", collectNumberList, []).option("--space-type <number>", "Space type", collectNumberList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
|
|
@@ -564,6 +591,26 @@ vault.command("drive-download").requiredOption("--file-id <id>").option("--outpu
|
|
|
564
591
|
const title = options.output ? undefined : await resolveTitle(client, result, "vault.drive.list", "fileId", options.fileId);
|
|
565
592
|
await saveDownloadResult(result, `file-${options.fileId}`, options.output ?? title);
|
|
566
593
|
});
|
|
594
|
+
vault.command("record-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("--category <name>", "Recording type: upload/link/mobile/gtNote/pc/share", collectList, []).option("--space-type <number>", "Space type: 1=my records / 2=tenant records", collectNumberList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
|
|
595
|
+
const client = await createClient();
|
|
596
|
+
await printData(await client.call("vault.record.list", { from: Number(options.from), size: options.size === undefined ? undefined : Number(options.size), startTime: options.startTime, endTime: options.endTime, keyword: options.keyword, categoryList: maybeArray(options.category), spaceTypeList: options.spaceType.length ? options.spaceType : undefined }), parseFormat(options.format), options.output, { endpointKey: "vault.record.list", idField: "recordId" });
|
|
597
|
+
});
|
|
598
|
+
vault.command("record-download").requiredOption("--record-id <id>").requiredOption("--content-type <type>", "Content type: original/asr/summary").option("--output <path>").action(async (options) => {
|
|
599
|
+
const client = await createClient();
|
|
600
|
+
const result = await client.call("vault.record.download", undefined, { recordId: options.recordId, contentType: options.contentType });
|
|
601
|
+
const title = options.output ? undefined : await resolveTitle(client, result, "vault.record.list", "recordId", options.recordId);
|
|
602
|
+
await saveDownloadResult(result, `record-${options.recordId}`, options.output ?? title);
|
|
603
|
+
});
|
|
604
|
+
vault.command("my-conference-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("--research-area <id>", "Research area ID", collectList, []).option("--security <code>", "Security code", collectList, []).option("--institution <id>", "Institution ID", collectList, []).option("--category <name>", "Conference category: earningsCall/strategyMeeting/fundRoadshow/shareholdersMeeting/maMeeting/specialMeeting/companyAnalysis/industryAnalysis/other", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
|
|
605
|
+
const client = await createClient();
|
|
606
|
+
await printData(await client.call("vault.my-conference.list", { from: Number(options.from), size: options.size === undefined ? undefined : Number(options.size), startTime: options.startTime, endTime: options.endTime, keyword: options.keyword, researchAreaList: maybeArray(options.researchArea), securityList: maybeArray(options.security), institutionList: maybeArray(options.institution), categoryList: maybeArray(options.category) }), parseFormat(options.format), options.output, { endpointKey: "vault.my-conference.list", idField: "conferenceId" });
|
|
607
|
+
});
|
|
608
|
+
vault.command("my-conference-download").requiredOption("--conference-id <id>").requiredOption("--content-type <type>", "Content type: asr/summary").option("--output <path>").action(async (options) => {
|
|
609
|
+
const client = await createClient();
|
|
610
|
+
const result = await client.call("vault.my-conference.download", undefined, { conferenceId: options.conferenceId, contentType: options.contentType });
|
|
611
|
+
const title = options.output ? undefined : await resolveTitle(client, result, "vault.my-conference.list", "conferenceId", options.conferenceId);
|
|
612
|
+
await saveDownloadResult(result, `conference-${options.conferenceId}`, options.output ?? title);
|
|
613
|
+
});
|
|
567
614
|
program.addCommand(vault);
|
|
568
615
|
program.addCommand(ai);
|
|
569
616
|
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) => {
|
|
@@ -204,6 +204,13 @@ export const ENDPOINTS = {
|
|
|
204
204
|
kind: "json",
|
|
205
205
|
description: "Query main business composition",
|
|
206
206
|
},
|
|
207
|
+
fundamentalEarningForecast: {
|
|
208
|
+
key: "fundamental.earning-forecast",
|
|
209
|
+
method: "POST",
|
|
210
|
+
path: "/application/open-fundamental/earning-forecast",
|
|
211
|
+
kind: "json",
|
|
212
|
+
description: "Query earning forecast (consensus estimates)",
|
|
213
|
+
},
|
|
207
214
|
fundamentalValuationAnalysis: {
|
|
208
215
|
key: "fundamental.valuation-analysis",
|
|
209
216
|
method: "POST",
|
|
@@ -354,6 +361,36 @@ export const ENDPOINTS = {
|
|
|
354
361
|
kind: "download",
|
|
355
362
|
description: "Download vault drive file",
|
|
356
363
|
},
|
|
364
|
+
vaultRecordList: {
|
|
365
|
+
key: "vault.record.list",
|
|
366
|
+
method: "POST",
|
|
367
|
+
path: "/application/open-vault/record/getList",
|
|
368
|
+
kind: "json",
|
|
369
|
+
description: "List voice recording transcriptions",
|
|
370
|
+
pagination: { enabled: true, maxPageSize: 50 },
|
|
371
|
+
},
|
|
372
|
+
vaultRecordDownload: {
|
|
373
|
+
key: "vault.record.download",
|
|
374
|
+
method: "GET",
|
|
375
|
+
path: "/application/open-vault/record/download/file",
|
|
376
|
+
kind: "download",
|
|
377
|
+
description: "Download voice recording transcription file",
|
|
378
|
+
},
|
|
379
|
+
vaultMyConferenceList: {
|
|
380
|
+
key: "vault.my-conference.list",
|
|
381
|
+
method: "POST",
|
|
382
|
+
path: "/application/open-vault/my-conference/getList",
|
|
383
|
+
kind: "json",
|
|
384
|
+
description: "List my conferences",
|
|
385
|
+
pagination: { enabled: true, maxPageSize: 50 },
|
|
386
|
+
},
|
|
387
|
+
vaultMyConferenceDownload: {
|
|
388
|
+
key: "vault.my-conference.download",
|
|
389
|
+
method: "GET",
|
|
390
|
+
path: "/application/open-vault/my-conference/download/file",
|
|
391
|
+
kind: "download",
|
|
392
|
+
description: "Download my conference resource",
|
|
393
|
+
},
|
|
357
394
|
};
|
|
358
395
|
export const ENDPOINT_REGISTRY = Object.values(ENDPOINTS).reduce((accumulator, endpoint) => {
|
|
359
396
|
accumulator[endpoint.key] = endpoint;
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated — DO NOT EDIT
|
|
2
|
-
export const CLI_VERSION = "0.
|
|
2
|
+
export const CLI_VERSION = "0.10.1";
|