@dshtrading/connector-jin10 0.3.0 → 0.4.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.
@@ -0,0 +1,8 @@
1
+ import { Config } from "./plugin.js";
2
+ import { Context } from "@deepseek-ai/cordis";
3
+ //#region src/global-plugin.d.ts
4
+ declare const name = "dsh-trading-global-connector-jin10";
5
+ declare const inject: string[];
6
+ declare function apply(ctx: Context, config?: Partial<Config>): void;
7
+ //#endregion
8
+ export { Config, apply, inject, name };
@@ -0,0 +1,17 @@
1
+ import { TRADING_GLOBAL_MARKET_DATA_KEY, createJin10GlobalMarketDataService } from "./market-data.js";
2
+ import "./mcp.js";
3
+ import { Config, createJin10Service } from "./plugin.js";
4
+ //#region src/global-plugin.ts
5
+ const name = "dsh-trading-global-connector-jin10";
6
+ const inject = [];
7
+ function apply(ctx, config) {
8
+ if (config?.enabled === false) return;
9
+ const service = createJin10GlobalMarketDataService(createJin10Service(ctx, {
10
+ endpoint: config?.endpoint ?? "https://mcp.jin10.com/mcp",
11
+ tokenRef: config?.tokenRef ?? "JIN10_MCP_TOKEN",
12
+ timeoutMs: config?.timeoutMs ?? 15e3
13
+ }));
14
+ ctx.reflect.provide(TRADING_GLOBAL_MARKET_DATA_KEY, service);
15
+ }
16
+ //#endregion
17
+ export { Config, apply, inject, name };
package/lib/index.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, Jin10McpOptions, McpContentPart, McpResourceDescriptor, McpToolDescriptor, McpToolResult, parseMcpBody } from "./mcp.js";
2
2
  import { Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Instrument, Jin10Kline, Jin10NewsItem, Jin10NewsPage, Jin10Quote, flashTitle, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes } from "./parse.js";
3
3
  import { JIN10_HEAT_LEVELS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10FlashItem, Jin10HeatLevel, Jin10HotFlashOptions, fetchJin10HotFlash, isJin10HeatLevel, parseWebFlashItems } from "./web-flash.js";
4
+ import { JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, Jin10RateEntry, fetchJin10Rates, parseWebRates } from "./web-rates.js";
4
5
  import { FLASH_PAGE_SIZE, INSTRUMENT_CACHE_TTL_MS, Jin10PageOptions, Jin10Service, SEARCH_FLASH_MAX } from "./service.js";
5
6
  import { Config, apply, inject, name } from "./plugin.js";
6
7
  import { Jin10Error, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
7
8
  import { TRADING_FLASH_FEED_KEY, createJin10FlashFeed } from "./flash-service.js";
9
+ import { MACRO_CALENDAR_MAX, TRADING_MACRO_FEED_KEY, createJin10MacroFeed } from "./macro-service.js";
8
10
  import { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, TICKER_POLL_MS, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, createJin10GlobalMarketDataService, resolveIntervalMinutes, tickerFromQuote } from "./market-data.js";
11
+ import { JIN10_REGIONS, Jin10Region, regionOfFlagUrl, regionOfTitle } from "./regions.js";
9
12
  import { createJin10Tools } from "./tools.js";
10
- export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Error, Jin10FlashItem, Jin10HeatLevel, Jin10HotFlashOptions, Jin10Instrument, Jin10Kline, Jin10McpClient, Jin10McpOptions, Jin10NewsItem, Jin10NewsPage, Jin10PageOptions, Jin10Quote, Jin10Service, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, McpContentPart, McpResourceDescriptor, McpToolDescriptor, McpToolResult, SEARCH_FLASH_MAX, TICKER_POLL_MS, TOKEN_HINT, TRADING_FLASH_FEED_KEY, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, apply, codeForUpstreamMessage, createJin10FlashFeed, createJin10GlobalMarketDataService, createJin10Tools, fetchJin10HotFlash, flashTitle, inject, isJin10HeatLevel, name, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseMcpBody, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes, parseWebFlashItems, resolveIntervalMinutes, tickerFromQuote };
13
+ export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, JIN10_REGIONS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Error, Jin10FlashItem, Jin10HeatLevel, Jin10HotFlashOptions, Jin10Instrument, Jin10Kline, Jin10McpClient, Jin10McpOptions, Jin10NewsItem, Jin10NewsPage, Jin10PageOptions, Jin10Quote, Jin10RateEntry, Jin10Region, Jin10Service, MACRO_CALENDAR_MAX, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, McpContentPart, McpResourceDescriptor, McpToolDescriptor, McpToolResult, SEARCH_FLASH_MAX, TICKER_POLL_MS, TOKEN_HINT, TRADING_FLASH_FEED_KEY, TRADING_GLOBAL_MARKET_DATA_KEY, TRADING_MACRO_FEED_KEY, aggregateKlines, apply, codeForUpstreamMessage, createJin10FlashFeed, createJin10GlobalMarketDataService, createJin10MacroFeed, createJin10Tools, fetchJin10HotFlash, fetchJin10Rates, flashTitle, inject, isJin10HeatLevel, name, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseMcpBody, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes, parseWebFlashItems, parseWebRates, regionOfFlagUrl, regionOfTitle, resolveIntervalMinutes, tickerFromQuote };
package/lib/index.js CHANGED
@@ -1,10 +1,13 @@
1
1
  import { Jin10Error, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
2
+ import { JIN10_REGIONS, regionOfFlagUrl, regionOfTitle } from "./regions.js";
2
3
  import { flashTitle, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes } from "./parse.js";
3
4
  import { JIN10_HEAT_LEVELS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, fetchJin10HotFlash, isJin10HeatLevel, parseWebFlashItems } from "./web-flash.js";
4
5
  import { TRADING_FLASH_FEED_KEY, createJin10FlashFeed } from "./flash-service.js";
6
+ import { MACRO_CALENDAR_MAX, TRADING_MACRO_FEED_KEY, createJin10MacroFeed } from "./macro-service.js";
5
7
  import { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, TICKER_POLL_MS, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, createJin10GlobalMarketDataService, resolveIntervalMinutes, tickerFromQuote } from "./market-data.js";
6
8
  import { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, parseMcpBody } from "./mcp.js";
9
+ import { JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, fetchJin10Rates, parseWebRates } from "./web-rates.js";
7
10
  import { FLASH_PAGE_SIZE, INSTRUMENT_CACHE_TTL_MS, Jin10Service, SEARCH_FLASH_MAX } from "./service.js";
8
11
  import { createJin10Tools } from "./tools.js";
9
12
  import { Config, apply, inject, name } from "./plugin.js";
10
- export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10Error, Jin10McpClient, Jin10Service, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, SEARCH_FLASH_MAX, TICKER_POLL_MS, TOKEN_HINT, TRADING_FLASH_FEED_KEY, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, apply, codeForUpstreamMessage, createJin10FlashFeed, createJin10GlobalMarketDataService, createJin10Tools, fetchJin10HotFlash, flashTitle, inject, isJin10HeatLevel, name, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseMcpBody, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes, parseWebFlashItems, resolveIntervalMinutes, tickerFromQuote };
13
+ export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, JIN10_REGIONS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10Error, Jin10McpClient, Jin10Service, MACRO_CALENDAR_MAX, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, SEARCH_FLASH_MAX, TICKER_POLL_MS, TOKEN_HINT, TRADING_FLASH_FEED_KEY, TRADING_GLOBAL_MARKET_DATA_KEY, TRADING_MACRO_FEED_KEY, aggregateKlines, apply, codeForUpstreamMessage, createJin10FlashFeed, createJin10GlobalMarketDataService, createJin10MacroFeed, createJin10Tools, fetchJin10HotFlash, fetchJin10Rates, flashTitle, inject, isJin10HeatLevel, name, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseMcpBody, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes, parseWebFlashItems, parseWebRates, regionOfFlagUrl, regionOfTitle, resolveIntervalMinutes, tickerFromQuote };
@@ -0,0 +1,10 @@
1
+ import { Jin10Service } from "./service.js";
2
+ import { MacroFeedService } from "@dshtrading/api";
3
+ //#region src/macro-service.d.ts
4
+ declare const TRADING_MACRO_FEED_KEY = "tradingMacroFeed";
5
+ /** 日历全周截尾上限(上游一页即整周;桥侧同值校验。整周实测已到 254 条,250 会裁掉周尾)。 */
6
+ declare const MACRO_CALENDAR_MAX = 400;
7
+ /** 宏观/利率源实现(桥与工具面共用同一 Jin10Service)。 */
8
+ declare function createJin10MacroFeed(feed: Jin10Service): MacroFeedService;
9
+ //#endregion
10
+ export { MACRO_CALENDAR_MAX, TRADING_MACRO_FEED_KEY, createJin10MacroFeed };
@@ -0,0 +1,19 @@
1
+ //#region src/macro-service.ts
2
+ const TRADING_MACRO_FEED_KEY = "tradingMacroFeed";
3
+ /** 日历全周截尾上限(上游一页即整周;桥侧同值校验。整周实测已到 254 条,250 会裁掉周尾)。 */
4
+ const MACRO_CALENDAR_MAX = 400;
5
+ /** 宏观/利率源实现(桥与工具面共用同一 Jin10Service)。 */
6
+ function createJin10MacroFeed(feed) {
7
+ return {
8
+ /** 当周经济日历(MCP list_calendar;地区已按标题前缀推断)。 */
9
+ async listCalendar(limit) {
10
+ return feed.listCalendar(limit);
11
+ },
12
+ /** 央行最新利率(网页版接口全量,客户端按地区过滤)。 */
13
+ async listRates() {
14
+ return feed.listRates();
15
+ }
16
+ };
17
+ }
18
+ //#endregion
19
+ export { MACRO_CALENDAR_MAX, TRADING_MACRO_FEED_KEY, createJin10MacroFeed };
package/lib/parse.d.ts CHANGED
@@ -24,6 +24,8 @@ interface Jin10CalendarEntry {
24
24
  publishedAt: string;
25
25
  star: number;
26
26
  title: string;
27
+ /** 地区(标题前缀推断,见 regions.ts;未识别 = 空串——GUI 地区过滤用)。 */
28
+ region: string;
27
29
  previous?: string;
28
30
  consensus?: string;
29
31
  actual?: string;
package/lib/parse.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Jin10Error } from "./errors.js";
2
+ import { regionOfTitle } from "./regions.js";
2
3
  //#region src/parse.ts
3
4
  /** 快讯标题:【标题】正文 → 取括号内;无括号 → 首段文本截断(正文绝不下发)。 */
4
5
  function flashTitle(content, maxLength = 120) {
@@ -139,6 +140,7 @@ function parseCalendar(data, limit) {
139
140
  publishedAt,
140
141
  star: star ?? 0,
141
142
  title,
143
+ region: regionOfTitle(title),
142
144
  ...previous !== void 0 ? { previous } : {},
143
145
  ...consensus !== void 0 ? { consensus } : {},
144
146
  ...actual !== void 0 ? { actual } : {},
package/lib/plugin.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { TRADING_FLASH_FEED_KEY, createJin10FlashFeed } from "./flash-service.js";
2
+ import { TRADING_MACRO_FEED_KEY, createJin10MacroFeed } from "./macro-service.js";
2
3
  import { DEFAULT_ENDPOINT, DEFAULT_TIMEOUT_MS, Jin10McpClient } from "./mcp.js";
3
4
  import { Jin10Service } from "./service.js";
4
5
  import { createJin10Tools } from "./tools.js";
@@ -32,6 +33,7 @@ function apply(ctx, config) {
32
33
  if (!config.enabled) return;
33
34
  const service = createJin10Service(ctx, config);
34
35
  ctx.reflect.provide(TRADING_FLASH_FEED_KEY, createJin10FlashFeed(service));
36
+ ctx.reflect.provide(TRADING_MACRO_FEED_KEY, createJin10MacroFeed(service));
35
37
  const tools = ctx.tools;
36
38
  for (const tool of createJin10Tools(service)) if (tools.get(tool.name) === void 0) tools.register(tool);
37
39
  }
@@ -0,0 +1,22 @@
1
+ //#region src/regions.d.ts
2
+ /**
3
+ * 金十地区词汇(2026-09-15,宏观/利率数据面的地区归属推断)。
4
+ *
5
+ * 两条推断路径(spikes/impl-jin10-macro-rates/EVIDENCE.md):
6
+ * - 日历条目:MCP list_calendar 无 country 字段,但标题一律以地区名开头
7
+ * (「日本8月外汇储备(亿美元)」),按前缀匹配;
8
+ * - 央行利率:flagImgUrl 文件名即地区名(`…/flag/美国.png`)。
9
+ * 词汇表是封闭小集合(实测 indicator_list 字典 33 个 country 取值的母集);
10
+ * 匹配一律按**长度降序**(「中国香港」「中国台湾」「印度尼西亚」不会被
11
+ * 「中国」「印度」截胡——手写顺序不算数,见 2026-09-15 评审 M4)。未命中
12
+ * 返回空串(= 仅「全部」视图可见),绝不猜。
13
+ */
14
+ /** 地区词汇(封闭集合;匹配顺序由长度降序推导,与书写顺序无关)。 */
15
+ declare const JIN10_REGIONS: readonly ["美国", "中国", "日本", "欧元区", "德国", "法国", "英国", "中国香港", "中国台湾", "韩国", "新加坡", "澳大利亚", "加拿大", "瑞士", "印度尼西亚", "印度", "意大利", "西班牙", "印尼", "俄罗斯", "巴西", "墨西哥", "南非", "新西兰", "土耳其", "瑞典", "挪威", "丹麦", "波兰", "匈牙利", "捷克", "乌克兰", "以色列", "菲律宾", "泰国", "马来西亚", "越南", "沙特", "智利", "哥伦比亚", "尼日利亚", "罗马尼亚", "全球", "OECD"];
16
+ type Jin10Region = (typeof JIN10_REGIONS)[number];
17
+ /** 日历标题 → 地区(前缀命中;未命中 = 空串)。 */
18
+ declare function regionOfTitle(title: string): string;
19
+ /** 利率 flagImgUrl → 地区(取文件名去扩展名,别名归一;空串 = 无法识别)。 */
20
+ declare function regionOfFlagUrl(flagUrl: string): string;
21
+ //#endregion
22
+ export { JIN10_REGIONS, Jin10Region, regionOfFlagUrl, regionOfTitle };
package/lib/regions.js ADDED
@@ -0,0 +1,79 @@
1
+ //#region src/regions.ts
2
+ /**
3
+ * 金十地区词汇(2026-09-15,宏观/利率数据面的地区归属推断)。
4
+ *
5
+ * 两条推断路径(spikes/impl-jin10-macro-rates/EVIDENCE.md):
6
+ * - 日历条目:MCP list_calendar 无 country 字段,但标题一律以地区名开头
7
+ * (「日本8月外汇储备(亿美元)」),按前缀匹配;
8
+ * - 央行利率:flagImgUrl 文件名即地区名(`…/flag/美国.png`)。
9
+ * 词汇表是封闭小集合(实测 indicator_list 字典 33 个 country 取值的母集);
10
+ * 匹配一律按**长度降序**(「中国香港」「中国台湾」「印度尼西亚」不会被
11
+ * 「中国」「印度」截胡——手写顺序不算数,见 2026-09-15 评审 M4)。未命中
12
+ * 返回空串(= 仅「全部」视图可见),绝不猜。
13
+ */
14
+ /** 地区词汇(封闭集合;匹配顺序由长度降序推导,与书写顺序无关)。 */
15
+ const JIN10_REGIONS = [
16
+ "美国",
17
+ "中国",
18
+ "日本",
19
+ "欧元区",
20
+ "德国",
21
+ "法国",
22
+ "英国",
23
+ "中国香港",
24
+ "中国台湾",
25
+ "韩国",
26
+ "新加坡",
27
+ "澳大利亚",
28
+ "加拿大",
29
+ "瑞士",
30
+ "印度尼西亚",
31
+ "印度",
32
+ "意大利",
33
+ "西班牙",
34
+ "印尼",
35
+ "俄罗斯",
36
+ "巴西",
37
+ "墨西哥",
38
+ "南非",
39
+ "新西兰",
40
+ "土耳其",
41
+ "瑞典",
42
+ "挪威",
43
+ "丹麦",
44
+ "波兰",
45
+ "匈牙利",
46
+ "捷克",
47
+ "乌克兰",
48
+ "以色列",
49
+ "菲律宾",
50
+ "泰国",
51
+ "马来西亚",
52
+ "越南",
53
+ "沙特",
54
+ "智利",
55
+ "哥伦比亚",
56
+ "尼日利亚",
57
+ "罗马尼亚",
58
+ "全球",
59
+ "OECD"
60
+ ];
61
+ /** 上游同义写法 → 规范地区名(两条推断路径共用,同一国家只有一个标签)。 */
62
+ const REGION_ALIASES = { "印尼": "印度尼西亚" };
63
+ /** 匹配顺序:长名在前(前缀匹配的唯一要求;书写顺序不参与语义)。 */
64
+ const MATCH_ORDER = [...JIN10_REGIONS].sort((a, b) => b.length - a.length);
65
+ function canonical(region) {
66
+ return REGION_ALIASES[region] ?? region;
67
+ }
68
+ /** 日历标题 → 地区(前缀命中;未命中 = 空串)。 */
69
+ function regionOfTitle(title) {
70
+ for (const region of MATCH_ORDER) if (title.startsWith(region)) return canonical(region);
71
+ return "";
72
+ }
73
+ /** 利率 flagImgUrl → 地区(取文件名去扩展名,别名归一;空串 = 无法识别)。 */
74
+ function regionOfFlagUrl(flagUrl) {
75
+ const base = (flagUrl.trim().split("/").pop() ?? "").replace(/\.[a-zA-Z]+$/, "");
76
+ return base.length > 0 ? canonical(base) : "";
77
+ }
78
+ //#endregion
79
+ export { JIN10_REGIONS, regionOfFlagUrl, regionOfTitle };
package/lib/service.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Jin10McpClient } from "./mcp.js";
2
2
  import { Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Instrument, Jin10Kline, Jin10NewsItem, Jin10NewsPage, Jin10Quote } from "./parse.js";
3
3
  import { Jin10FlashItem, Jin10HeatLevel } from "./web-flash.js";
4
+ import { Jin10RateEntry } from "./web-rates.js";
4
5
  //#region src/service.d.ts
5
6
  /** 快讯/资讯单页上限(上游 list_* 每页 20 条;search_flash 一次性最多 150 条且不可翻页)。 */
6
7
  declare const FLASH_PAGE_SIZE = 20;
@@ -39,6 +40,8 @@ declare class Jin10Service {
39
40
  getArticle(id: string): Promise<Jin10ArticleDetail>;
40
41
  /** 本周财经日历(周一~周日;上游一次返回整周)。 */
41
42
  listCalendar(limit?: number): Promise<Jin10CalendarEntry[]>;
43
+ /** 央行最新利率(网页版接口,30 家全量;地区按 flag 名推断)。 */
44
+ listRates(): Promise<Jin10RateEntry[]>;
42
45
  /** 品种名册(quote://codes 资源);query 按代码或中文名过滤。 */
43
46
  listInstruments(query?: string): Promise<Jin10Instrument[]>;
44
47
  getQuote(code: string): Promise<Jin10Quote>;
package/lib/service.js CHANGED
@@ -2,6 +2,7 @@ import { Jin10Error } from "./errors.js";
2
2
  import { parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseKlines, parseNewsPage, parseQuote, parseQuoteCodes } from "./parse.js";
3
3
  import { fetchJin10HotFlash } from "./web-flash.js";
4
4
  import "./mcp.js";
5
+ import { fetchJin10Rates } from "./web-rates.js";
5
6
  //#region src/service.ts
6
7
  /**
7
8
  * 取数层:把 MCP 工具名(list_flash / search_flash / list_news / search_news / get_news /
@@ -68,6 +69,10 @@ var Jin10Service = class {
68
69
  async listCalendar(limit) {
69
70
  return parseCalendar(await this.client.callToolData("list_calendar", {}), limit);
70
71
  }
72
+ /** 央行最新利率(网页版接口,30 家全量;地区按 flag 名推断)。 */
73
+ async listRates() {
74
+ return fetchJin10Rates(this.webFetch, { timeoutMs: this.webTimeoutMs });
75
+ }
71
76
  /** 品种名册(quote://codes 资源);query 按代码或中文名过滤。 */
72
77
  async listInstruments(query) {
73
78
  const items = await this.instrumentCatalog();
@@ -0,0 +1,23 @@
1
+ //#region src/web-rates.d.ts
2
+ declare const JIN10_RATES_ENDPOINT = "https://e0430d16720e4211b5e072c26205c890.z3c.jin10.com/web/interest_rates";
3
+ /** 网页版日历客户端 x-app-id / x-version(bundle 内常量,请求原样复刻)。 */
4
+ declare const JIN10_RATES_APP_ID = "sKKYe29sFuJaeOCJ";
5
+ declare const JIN10_RATES_X_VERSION = "2.0";
6
+ /** 央行最新利率条目(地区由 flagImgUrl 文件名推断,未识别 = 空串)。 */
7
+ interface Jin10RateEntry {
8
+ readonly region: string;
9
+ readonly bankName: string;
10
+ /** 最新利率(上游原样字符串)。 */
11
+ readonly rate: string;
12
+ /** 公布日(上游原样 YYYY-MM-DD)。 */
13
+ readonly publishedAt: string;
14
+ /** 所属指标名(如「美联储利率决定(上限)」;部分央行上游缺省)。 */
15
+ readonly indicatorName?: string;
16
+ }
17
+ /** 网页版条目 → Jin10RateEntry(缺央行名/利率/公布日的残条丢弃,绝不编数)。 */
18
+ declare function parseWebRates(payload: unknown): Jin10RateEntry[];
19
+ declare function fetchJin10Rates(fetchImpl: typeof globalThis.fetch, config: {
20
+ timeoutMs: number;
21
+ }): Promise<Jin10RateEntry[]>;
22
+ //#endregion
23
+ export { JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, Jin10RateEntry, fetchJin10Rates, parseWebRates };
@@ -0,0 +1,84 @@
1
+ import { Jin10Error } from "./errors.js";
2
+ import { regionOfFlagUrl } from "./regions.js";
3
+ //#region src/web-rates.ts
4
+ /**
5
+ * 金十网页版「央行利率」取数(2026-09-15)。
6
+ *
7
+ * 官方 MCP 没有利率读数工具,而金十日历网页版(rili.jin10.com)有全量 30 家
8
+ * 央行最新利率接口。本模块复刻网页版实际请求(bundle getInterestRate 逆向 +
9
+ * 真实网络复核,见 spikes/impl-jin10-macro-rates/EVIDENCE.md):
10
+ *
11
+ * GET https://e0430d16720e4211b5e072c26205c890.z3c.jin10.com/web/interest_rates
12
+ * headers: x-app-id: sKKYe29sFuJaeOCJ, x-version: 2.0
13
+ * 响应 : { status: 200, message, data: { list: [{ id, bankName, flagImgUrl,
14
+ * interestRate, publishTime, fromIndicatorId?, fromIndicatorName? }], updated_at } }
15
+ *
16
+ * 与热度快讯(web-flash.ts)同款边界:非官方 MCP 契约的网页版公开接口,仅用于
17
+ * GUI 读数;利率是数值元数据,无正文再分发问题。interestRate 保留上游原样字符串
18
+ * ("2.5"/"0"),不做数值化——展示诚实优先。
19
+ */
20
+ const JIN10_RATES_ENDPOINT = "https://e0430d16720e4211b5e072c26205c890.z3c.jin10.com/web/interest_rates";
21
+ /** 网页版日历客户端 x-app-id / x-version(bundle 内常量,请求原样复刻)。 */
22
+ const JIN10_RATES_APP_ID = "sKKYe29sFuJaeOCJ";
23
+ const JIN10_RATES_X_VERSION = "2.0";
24
+ function isRecord(value) {
25
+ return typeof value === "object" && value !== null && !Array.isArray(value);
26
+ }
27
+ function text(value) {
28
+ if (typeof value !== "string") return void 0;
29
+ const trimmed = value.trim();
30
+ return trimmed.length > 0 ? trimmed : void 0;
31
+ }
32
+ /** 网页版条目 → Jin10RateEntry(缺央行名/利率/公布日的残条丢弃,绝不编数)。 */
33
+ function parseWebRates(payload) {
34
+ if (!isRecord(payload)) throw new Jin10Error("TRADING_EXCHANGE_ERROR", "jin10 rates: unexpected payload (expected an object)");
35
+ if (payload.status !== 200) {
36
+ const message = typeof payload.message === "string" && payload.message.length > 0 ? payload.message : "unknown upstream error";
37
+ throw new Jin10Error("TRADING_EXCHANGE_ERROR", `jin10 rates: upstream status ${String(payload.status)} — ${message}`);
38
+ }
39
+ const list = (isRecord(payload.data) ? payload.data : void 0)?.list;
40
+ if (!Array.isArray(list)) throw new Jin10Error("TRADING_EXCHANGE_ERROR", "jin10 rates: unexpected payload (expected data.list[])");
41
+ const items = [];
42
+ for (const raw of list) {
43
+ if (!isRecord(raw)) continue;
44
+ const bankName = text(raw.bankName);
45
+ const rate = text(raw.interestRate);
46
+ const publishedAt = text(raw.publishTime);
47
+ if (bankName === void 0 || rate === void 0 || publishedAt === void 0) continue;
48
+ const region = typeof raw.flagImgUrl === "string" ? regionOfFlagUrl(raw.flagImgUrl) : "";
49
+ const indicatorName = text(raw.fromIndicatorName);
50
+ items.push({
51
+ region,
52
+ bankName,
53
+ rate,
54
+ publishedAt,
55
+ ...indicatorName !== void 0 ? { indicatorName } : {}
56
+ });
57
+ }
58
+ return items;
59
+ }
60
+ async function fetchJin10Rates(fetchImpl, config) {
61
+ const response = await fetchImpl(JIN10_RATES_ENDPOINT, {
62
+ headers: {
63
+ accept: "application/json",
64
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36",
65
+ "x-app-id": JIN10_RATES_APP_ID,
66
+ "x-version": "2.0",
67
+ referer: "https://rili.jin10.com/"
68
+ },
69
+ signal: AbortSignal.timeout(config.timeoutMs)
70
+ });
71
+ if (!response.ok) {
72
+ const body = await response.text().catch(() => "");
73
+ throw new Jin10Error("TRADING_EXCHANGE_ERROR", `jin10 rates: HTTP ${response.status}${body ? ` — ${body.slice(0, 160)}` : ""}`);
74
+ }
75
+ let parsed;
76
+ try {
77
+ parsed = JSON.parse(await response.text());
78
+ } catch {
79
+ throw new Jin10Error("TRADING_EXCHANGE_ERROR", "jin10 rates: upstream returned non-JSON body");
80
+ }
81
+ return parseWebRates(parsed);
82
+ }
83
+ //#endregion
84
+ export { JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, fetchJin10Rates, parseWebRates };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dshtrading/connector-jin10",
3
3
  "description": "金十数据 MCP 连接器:把 mcp.jin10.com 的行情/快讯/资讯/财经日历封装成本仓的连接器(市场无关,host 面工具行)",
4
- "version": "0.3.0",
4
+ "version": "0.4.1",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "./lib/index.d.ts",
@@ -14,6 +14,10 @@
14
14
  "types": "./lib/dataplane.d.ts",
15
15
  "default": "./lib/dataplane.js"
16
16
  },
17
+ "./global-plugin": {
18
+ "types": "./lib/global-plugin.d.ts",
19
+ "default": "./lib/global-plugin.js"
20
+ },
17
21
  "./package.json": "./package.json"
18
22
  },
19
23
  "files": [
@@ -21,7 +25,7 @@
21
25
  ],
22
26
  "license": "PolyForm-Noncommercial-1.0.0",
23
27
  "dependencies": {
24
- "@dshtrading/api": "^0.3.0"
28
+ "@dshtrading/api": "^0.4.1"
25
29
  },
26
30
  "peerDependencies": {
27
31
  "@deepseek-ai/cordis": ">=4.0.0",