echopai 2.5.0 → 2.6.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/dist/bin.js +119 -3
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -229,6 +229,66 @@ var OPERATIONS = {
|
|
|
229
229
|
additionalProperties: false
|
|
230
230
|
}
|
|
231
231
|
},
|
|
232
|
+
"announcements.search": {
|
|
233
|
+
cliKey: "announcements.search",
|
|
234
|
+
cliName: "announcements search",
|
|
235
|
+
method: "GET",
|
|
236
|
+
path: "/v1/announcements/search",
|
|
237
|
+
description: "公告混合搜索:名称 / 代码做结构化过滤 + 关键词 BM25 全文(ParadeDB jieba,覆盖 title / ai_summary / content_md 前 1500 字)。q 含 6 位代码或内嵌 A 股名 → 按代码精确过滤;残余或纯文本 → BM25 按相关度×时间衰减排序;纯代码/名称则按 published_at 倒序列出。需要 `announcements:read` scope。",
|
|
238
|
+
summary: "Hybrid search over A-share announcements",
|
|
239
|
+
positional: [],
|
|
240
|
+
outputDefault: "json",
|
|
241
|
+
pagination: "offset",
|
|
242
|
+
stream: false,
|
|
243
|
+
billable: true,
|
|
244
|
+
idempotencyRequired: false,
|
|
245
|
+
scopesAny: [
|
|
246
|
+
"announcements:read"
|
|
247
|
+
],
|
|
248
|
+
sideEffect: "read",
|
|
249
|
+
dryRunSupported: false,
|
|
250
|
+
inputSchema: {
|
|
251
|
+
type: "object",
|
|
252
|
+
properties: {
|
|
253
|
+
q: {
|
|
254
|
+
type: "string",
|
|
255
|
+
minLength: 1,
|
|
256
|
+
maxLength: 100,
|
|
257
|
+
description: '名称 / 代码 / 关键词,可混合(如 "新华医疗 回购"、"600587"、"回购")。',
|
|
258
|
+
example: "新华医疗 回购"
|
|
259
|
+
},
|
|
260
|
+
type: {
|
|
261
|
+
type: "string",
|
|
262
|
+
maxLength: 64,
|
|
263
|
+
description: "分类 slug 过滤(与 /v1/announcements/feed 同集合)。"
|
|
264
|
+
},
|
|
265
|
+
since_days: {
|
|
266
|
+
type: "integer",
|
|
267
|
+
minimum: 1,
|
|
268
|
+
maximum: 1825,
|
|
269
|
+
default: 90,
|
|
270
|
+
description: "回看天数(最多 5 年)。"
|
|
271
|
+
},
|
|
272
|
+
limit: {
|
|
273
|
+
type: "integer",
|
|
274
|
+
minimum: 1,
|
|
275
|
+
maximum: 200,
|
|
276
|
+
default: 50,
|
|
277
|
+
description: "Max items per page."
|
|
278
|
+
},
|
|
279
|
+
offset: {
|
|
280
|
+
type: "integer",
|
|
281
|
+
minimum: 0,
|
|
282
|
+
default: 0,
|
|
283
|
+
description: "Pagination offset (items to skip)."
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
additionalProperties: false,
|
|
287
|
+
required: [
|
|
288
|
+
"q"
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
},
|
|
232
292
|
"announcements.stock": {
|
|
233
293
|
cliKey: "announcements.stock",
|
|
234
294
|
cliName: "announcements stock",
|
|
@@ -2694,6 +2754,10 @@ function buildCommandTree(program, dispatch) {
|
|
|
2694
2754
|
const cmd = noun.command("feed");
|
|
2695
2755
|
attachOperation(cmd, OPERATIONS["announcements.feed"], dispatch);
|
|
2696
2756
|
}
|
|
2757
|
+
{
|
|
2758
|
+
const cmd = noun.command("search");
|
|
2759
|
+
attachOperation(cmd, OPERATIONS["announcements.search"], dispatch);
|
|
2760
|
+
}
|
|
2697
2761
|
{
|
|
2698
2762
|
const cmd = noun.command("stock");
|
|
2699
2763
|
attachOperation(cmd, OPERATIONS["announcements.stock"], dispatch);
|
|
@@ -4592,6 +4656,32 @@ function buildQueryString3(params, method) {
|
|
|
4592
4656
|
var CODE_RE = /^(SSE|SZSE|BSE|SH|SZ|BJ):[0-9]{6}$/;
|
|
4593
4657
|
var ISO_DATETIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/;
|
|
4594
4658
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4659
|
+
var announcementsSearchSpec = {
|
|
4660
|
+
name: "announcements_search",
|
|
4661
|
+
description: 'Hybrid search over A-share announcements (cninfo): mix Chinese company name / 6-digit code / free-text keyword in one query. Name or code → structured filter by stock; keyword → BM25 full-text (ParadeDB jieba over title + ai_summary + first 1500 chars of body), ranked by relevance × recency. Use when you DON\'T already have a canonical_code — e.g. "新华医疗 回购", "600587", or just "回购". For a known stock\'s full disclosure history prefer `announcements_stock`; for the market-wide recent feed prefer `announcements_feed`.',
|
|
4662
|
+
inputSchema: {
|
|
4663
|
+
q: z.string().min(1).max(100).describe('名称 / 代码 / 关键词,可混合(如 "新华医疗 回购"、"600587"、"回购")'),
|
|
4664
|
+
type: z.string().max(64).optional().describe("分类 slug 过滤(与 feed 同集合)"),
|
|
4665
|
+
since_days: z.number().int().min(1).max(1825).default(90).describe("回看天数(1-1825,默认 90)"),
|
|
4666
|
+
limit: z.number().int().min(1).max(200).default(50).describe("Max items (1-200, default 50)"),
|
|
4667
|
+
offset: z.number().int().min(0).default(0).describe("Pagination offset")
|
|
4668
|
+
},
|
|
4669
|
+
handler: async (args, ctx) => {
|
|
4670
|
+
const op = OPERATIONS["announcements.search"];
|
|
4671
|
+
if (!op)
|
|
4672
|
+
throw new Error("announcements.search op missing");
|
|
4673
|
+
const callArgs = {
|
|
4674
|
+
q: args.q,
|
|
4675
|
+
since_days: args.since_days,
|
|
4676
|
+
limit: args.limit,
|
|
4677
|
+
offset: args.offset
|
|
4678
|
+
};
|
|
4679
|
+
if (args.type)
|
|
4680
|
+
callArgs.type = args.type;
|
|
4681
|
+
return callOp(op, callArgs, ctx);
|
|
4682
|
+
},
|
|
4683
|
+
backingOps: ["announcements.search"]
|
|
4684
|
+
};
|
|
4595
4685
|
var announcementsFeedSpec = {
|
|
4596
4686
|
name: "announcements_feed",
|
|
4597
4687
|
description: "Recent A-share announcement feed (cninfo source, sorted by published_at desc). Filter by `type` slug (e.g. annual_report / equity_change / restructuring) or `since` lower bound. Use when surveying market-wide disclosures over a recent window — for a specific stock prefer `announcements_stock`.",
|
|
@@ -4668,7 +4758,27 @@ function clampInt(raw, min, max, fallback) {
|
|
|
4668
4758
|
return n;
|
|
4669
4759
|
}
|
|
4670
4760
|
function buildAnnouncementsCommand() {
|
|
4671
|
-
const cmd = new Command3("announcements").description("A-share announcements (cninfo) — recent feed, per-stock history, single-item detail.");
|
|
4761
|
+
const cmd = new Command3("announcements").description("A-share announcements (cninfo) — hybrid search, recent feed, per-stock history, single-item detail.");
|
|
4762
|
+
const search = cmd.command("search").description(announcementsSearchSpec.description);
|
|
4763
|
+
search.addOption(new Option2("--q <text>", "名称 / 代码 / 关键词,可混合").makeOptionMandatory(true));
|
|
4764
|
+
search.addOption(new Option2("--type <slug>", "Filter by 分类 slug"));
|
|
4765
|
+
search.addOption(new Option2("--since-days <n>", "Lookback window in days (1-1825)").default("90"));
|
|
4766
|
+
search.addOption(new Option2("--limit <n>", "Max items (1-200)").default("50"));
|
|
4767
|
+
search.addOption(new Option2("--offset <n>", "Pagination offset").default("0"));
|
|
4768
|
+
search.action(async (opts) => {
|
|
4769
|
+
if (!OPERATIONS["announcements.search"]) {
|
|
4770
|
+
emitVerbError("internal_error", "announcements.search missing", undefined, 2);
|
|
4771
|
+
}
|
|
4772
|
+
const args = {
|
|
4773
|
+
q: opts.q,
|
|
4774
|
+
since_days: clampInt(opts.sinceDays, 1, 1825, 90),
|
|
4775
|
+
limit: clampInt(opts.limit, 1, 200, 50),
|
|
4776
|
+
offset: Math.max(0, Math.floor(Number(opts.offset)) || 0)
|
|
4777
|
+
};
|
|
4778
|
+
if (opts.type)
|
|
4779
|
+
args.type = opts.type;
|
|
4780
|
+
await executeVerb(async (ctx) => announcementsSearchSpec.handler(args, ctx));
|
|
4781
|
+
});
|
|
4672
4782
|
const feed = cmd.command("feed").description(announcementsFeedSpec.description);
|
|
4673
4783
|
feed.addOption(new Option2("--type <slug>", "Filter by 分类 slug (annual_report, equity_change, ...)"));
|
|
4674
4784
|
feed.addOption(new Option2("--since <ISO-datetime>", "Lower bound published_at (RFC3339)"));
|
|
@@ -6209,11 +6319,11 @@ import { Command as Command17, Option as Option15 } from "commander";
|
|
|
6209
6319
|
import { z as z14 } from "zod";
|
|
6210
6320
|
var searchSpec = {
|
|
6211
6321
|
name: "search",
|
|
6212
|
-
description: "
|
|
6322
|
+
description: "Structured-first hybrid search across analyst views + news (views weighted higher per feedback_views_over_news). Three lanes — entity (company codes / names, analyst names), concept-graph hub (theme alias → concept → constituents & research), and ParadeDB BM25 full-text (jieba) — fused with RRF. Deterministic & explainable: no vector kNN, no LLM rerank. Best for theme/concept queries: 'CPO' brings out 光模块/光通信/光芯片; '减肥药' brings out 创新药; '智驾' brings out 智能驾驶. Use `news` or `views` instead if you need strict time-window listing.",
|
|
6213
6323
|
inputSchema: {
|
|
6214
6324
|
q: z14.string().min(1).max(200).describe("Free-text query (Chinese or English)"),
|
|
6215
6325
|
type: z14.enum(["news", "views", "all"]).default("all").describe("Search scope (views weighted higher in 'all')"),
|
|
6216
|
-
mode: z14.enum(["hybrid", "exact"]).default("hybrid").describe("hybrid =
|
|
6326
|
+
mode: z14.enum(["hybrid", "exact"]).default("hybrid").describe("hybrid = entity + concept-graph + BM25 fused; exact = BM25 keyword only"),
|
|
6217
6327
|
hours: z14.number().int().min(1).max(720).optional().describe("Lookback window in hours; omit for no time limit"),
|
|
6218
6328
|
limit: z14.number().int().min(1).max(50).default(20).describe("Max items returned")
|
|
6219
6329
|
},
|
|
@@ -6596,6 +6706,7 @@ var ALL_VERB_SPECS = [
|
|
|
6596
6706
|
viewsSpec,
|
|
6597
6707
|
reportSpec,
|
|
6598
6708
|
newsSpec,
|
|
6709
|
+
announcementsSearchSpec,
|
|
6599
6710
|
announcementsFeedSpec,
|
|
6600
6711
|
announcementsStockSpec,
|
|
6601
6712
|
announcementsDetailSpec,
|
|
@@ -7442,6 +7553,11 @@ var HELP = {
|
|
|
7442
7553
|
description: "A 股公告 feed,按 published_at 降序、同日按 cninfo source_id 降序。可按 type / since 过滤。需要 `announcements:read` scope。",
|
|
7443
7554
|
example: "echopai announcements feed"
|
|
7444
7555
|
},
|
|
7556
|
+
"announcements.search": {
|
|
7557
|
+
summary: "Hybrid search over A-share announcements",
|
|
7558
|
+
description: "公告混合搜索:名称 / 代码做结构化过滤 + 关键词 BM25 全文(ParadeDB jieba,覆盖 title / ai_summary / content_md 前 1500 字)。q 含 6 位代码或内嵌 A 股名 → 按代码精确过滤;残余或纯文本 → BM25 按相关度×时间衰减排序;纯代码/名称则按 published_at 倒序列出。需要 `announcements:read` scope。",
|
|
7559
|
+
example: "echopai announcements search --q 新华医疗 回购"
|
|
7560
|
+
},
|
|
7445
7561
|
"announcements.stock": {
|
|
7446
7562
|
summary: "List announcements for a specific A-share security",
|
|
7447
7563
|
description: "指定股票代码的公告列表(含历史窗口)。代码接受 6 位纯数字或 SSE:600519 / SZSE:000001 / BSE:430000 形式。需要 `announcements:read` scope。",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "echopai",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Command-line interface for the EchoPai Open Platform: stock-market data, news, analyst views, sentiment, signals, backtests.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://echopai.com",
|