@363045841yyt/klinechart-core 0.8.2 → 0.8.4

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 (115) hide show
  1. package/dist/controllers/createChartController.d.ts +1 -1
  2. package/dist/controllers/createChartController.d.ts.map +1 -1
  3. package/dist/controllers/createChartController.js +34 -1
  4. package/dist/controllers/createChartController.js.map +1 -1
  5. package/dist/controllers/index.d.ts +1 -0
  6. package/dist/controllers/index.d.ts.map +1 -1
  7. package/dist/controllers/index.js +1 -0
  8. package/dist/controllers/index.js.map +1 -1
  9. package/dist/controllers/types.d.ts +17 -1
  10. package/dist/controllers/types.d.ts.map +1 -1
  11. package/dist/data-fetchers/baostock.d.ts +9 -2
  12. package/dist/data-fetchers/baostock.d.ts.map +1 -1
  13. package/dist/data-fetchers/baostock.js +78 -9
  14. package/dist/data-fetchers/baostock.js.map +1 -1
  15. package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts +13 -0
  16. package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -0
  17. package/dist/data-fetchers/fetcherDefinitionRegistry.js +36 -0
  18. package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -0
  19. package/dist/data-fetchers/gotdx.d.ts +9 -2
  20. package/dist/data-fetchers/gotdx.d.ts.map +1 -1
  21. package/dist/data-fetchers/gotdx.js +72 -5
  22. package/dist/data-fetchers/gotdx.js.map +1 -1
  23. package/dist/data-fetchers/hundred-mock.d.ts +9 -2
  24. package/dist/data-fetchers/hundred-mock.d.ts.map +1 -1
  25. package/dist/data-fetchers/hundred-mock.js +66 -4
  26. package/dist/data-fetchers/hundred-mock.js.map +1 -1
  27. package/dist/data-fetchers/index.d.ts +7 -5
  28. package/dist/data-fetchers/index.d.ts.map +1 -1
  29. package/dist/data-fetchers/index.js +6 -5
  30. package/dist/data-fetchers/index.js.map +1 -1
  31. package/dist/data-fetchers/router.d.ts.map +1 -1
  32. package/dist/data-fetchers/router.js +14 -18
  33. package/dist/data-fetchers/router.js.map +1 -1
  34. package/dist/data-fetchers/thousand-mock.d.ts +9 -2
  35. package/dist/data-fetchers/thousand-mock.d.ts.map +1 -1
  36. package/dist/data-fetchers/thousand-mock.js +66 -4
  37. package/dist/data-fetchers/thousand-mock.js.map +1 -1
  38. package/dist/data-fetchers/tradingview.d.ts +9 -2
  39. package/dist/data-fetchers/tradingview.d.ts.map +1 -1
  40. package/dist/data-fetchers/tradingview.js +73 -9
  41. package/dist/data-fetchers/tradingview.js.map +1 -1
  42. package/dist/data-fetchers/types.d.ts +21 -0
  43. package/dist/data-fetchers/types.d.ts.map +1 -0
  44. package/dist/data-fetchers/types.js +2 -0
  45. package/dist/data-fetchers/types.js.map +1 -0
  46. package/dist/engine/indicators/registerBuiltins.d.ts +2 -40
  47. package/dist/engine/indicators/registerBuiltins.d.ts.map +1 -1
  48. package/dist/engine/indicators/registerBuiltins.js +55 -42
  49. package/dist/engine/indicators/registerBuiltins.js.map +1 -1
  50. package/dist/engine/renderers/Indicator/ichimoku.d.ts.map +1 -1
  51. package/dist/engine/renderers/Indicator/ichimoku.js +8 -5
  52. package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
  53. package/dist/engine/renderers/Indicator/index.d.ts +0 -39
  54. package/dist/engine/renderers/Indicator/index.d.ts.map +1 -1
  55. package/dist/engine/renderers/Indicator/index.js +0 -78
  56. package/dist/engine/renderers/Indicator/index.js.map +1 -1
  57. package/dist/engine/renderers/Indicator/indicatorCatalog.d.ts +1 -3
  58. package/dist/engine/renderers/Indicator/indicatorCatalog.d.ts.map +1 -1
  59. package/dist/engine/renderers/Indicator/indicatorCatalog.js +27 -17
  60. package/dist/engine/renderers/Indicator/indicatorCatalog.js.map +1 -1
  61. package/dist/engine/renderers/Indicator/sar.d.ts.map +1 -1
  62. package/dist/engine/renderers/Indicator/sar.js +3 -3
  63. package/dist/engine/renderers/Indicator/sar.js.map +1 -1
  64. package/dist/engine/renderers/Indicator/supertrend.d.ts.map +1 -1
  65. package/dist/engine/renderers/Indicator/supertrend.js +3 -3
  66. package/dist/engine/renderers/Indicator/supertrend.js.map +1 -1
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +1 -0
  70. package/dist/index.js.map +1 -1
  71. package/dist/mcp/chartBridge.d.ts +47 -0
  72. package/dist/mcp/chartBridge.d.ts.map +1 -0
  73. package/dist/mcp/chartBridge.js +167 -0
  74. package/dist/mcp/chartBridge.js.map +1 -0
  75. package/dist/mcp/index.d.ts +3 -0
  76. package/dist/mcp/index.d.ts.map +1 -0
  77. package/dist/mcp/index.js +2 -0
  78. package/dist/mcp/index.js.map +1 -0
  79. package/dist/mcp/types.d.ts +17 -0
  80. package/dist/mcp/types.d.ts.map +1 -0
  81. package/dist/mcp/types.js +2 -0
  82. package/dist/mcp/types.js.map +1 -0
  83. package/dist/version.d.ts +1 -1
  84. package/dist/version.js +1 -1
  85. package/package.json +1 -1
  86. package/src/controllers/createChartController.ts +38 -1
  87. package/src/controllers/index.ts +1 -0
  88. package/src/controllers/types.ts +10 -1
  89. package/src/data-fetchers/__tests__/fetcherRegistry.test.ts +192 -0
  90. package/src/data-fetchers/baostock.ts +54 -22
  91. package/src/data-fetchers/fetcherDefinitionRegistry.ts +50 -0
  92. package/src/data-fetchers/gotdx.ts +28 -6
  93. package/src/data-fetchers/hundred-mock.ts +21 -4
  94. package/src/data-fetchers/index.ts +19 -5
  95. package/src/data-fetchers/router.ts +27 -18
  96. package/src/data-fetchers/thousand-mock.ts +21 -4
  97. package/src/data-fetchers/tradingview.ts +30 -11
  98. package/src/data-fetchers/types.ts +27 -0
  99. package/src/engine/__tests__/chart.dpr.test.ts +6 -1
  100. package/src/engine/indicators/__tests__/chartIndicatorManager.test.ts +6 -1
  101. package/src/engine/indicators/__tests__/registerBuiltins.test.ts +6 -2
  102. package/src/engine/indicators/__tests__/scheduler.test.ts +8 -3
  103. package/src/engine/indicators/__tests__/stateComposer.test.ts +6 -2
  104. package/src/engine/indicators/registerBuiltins.ts +58 -42
  105. package/src/engine/renderers/Indicator/__tests__/createSubIndicatorRenderer.test.ts +6 -2
  106. package/src/engine/renderers/Indicator/ichimoku.ts +10 -4
  107. package/src/engine/renderers/Indicator/index.ts +0 -92
  108. package/src/engine/renderers/Indicator/indicatorCatalog.ts +28 -19
  109. package/src/engine/renderers/Indicator/sar.ts +3 -3
  110. package/src/engine/renderers/Indicator/supertrend.ts +3 -4
  111. package/src/index.ts +1 -0
  112. package/src/mcp/chartBridge.ts +220 -0
  113. package/src/mcp/index.ts +2 -0
  114. package/src/mcp/types.ts +19 -0
  115. package/src/version.ts +1 -1
@@ -0,0 +1,220 @@
1
+ import type { ToolCall, ToolResult, ControllerDescription, ToolCallHandler } from './types'
2
+
3
+ export interface ChartBridgeOptions {
4
+ wsUrl: string
5
+ onToolCall: ToolCallHandler
6
+ sessionId?: string
7
+ autoReconnect?: boolean
8
+ reconnectDelay?: number
9
+ heartbeatInterval?: number
10
+ wsImpl?: new (url: string) => WebSocket
11
+ }
12
+
13
+ export type ChartBridgeEvent =
14
+ | 'connected'
15
+ | 'disconnected'
16
+ | 'error'
17
+ | 'stateChanged'
18
+
19
+ type MessageHandler = (...args: unknown[]) => void
20
+
21
+ export class ChartBridge {
22
+ readonly sessionId: string
23
+ private readonly autoReconnect: boolean
24
+ private readonly reconnectDelay: number
25
+ private readonly heartbeatInterval: number
26
+ private readonly onToolCall: ToolCallHandler
27
+
28
+ private readonly wsImpl: new (url: string) => WebSocket
29
+ private ws: WebSocket | null = null
30
+ private reconnectTimer: ReturnType<typeof setTimeout> | null = null
31
+ private heartbeatTimer: ReturnType<typeof setInterval> | null = null
32
+ private destroyed = false
33
+
34
+ private listeners = new Map<ChartBridgeEvent, Set<MessageHandler>>()
35
+
36
+ onConnected?: () => void
37
+ onDisconnected?: () => void
38
+ onError?: (err: Error) => void
39
+ onStateChange?: () => void
40
+
41
+ constructor(options: ChartBridgeOptions) {
42
+ this.sessionId = options.sessionId ?? crypto.randomUUID()
43
+ this.autoReconnect = options.autoReconnect ?? true
44
+ this.reconnectDelay = options.reconnectDelay ?? 3000
45
+ this.heartbeatInterval = options.heartbeatInterval ?? 30_000
46
+ this.onToolCall = options.onToolCall
47
+ this.wsImpl = options.wsImpl ?? WebSocket
48
+ this.wsUrl = options.wsUrl
49
+ }
50
+
51
+ private wsUrl: string
52
+
53
+ async connect(): Promise<void> {
54
+ if (this.destroyed) return
55
+ this.disconnect()
56
+
57
+ return new Promise((resolve, reject) => {
58
+ try {
59
+ const ws = new this.wsImpl(this.wsUrl)
60
+
61
+ ws.onopen = () => {
62
+ this.ws = ws
63
+ console.info(
64
+ `[ChartBridge] WS opened → sending register (sessionId=${this.sessionId})`,
65
+ )
66
+ ws.send(JSON.stringify({ type: 'register', sessionId: this.sessionId }))
67
+ this.startHeartbeat()
68
+ this.onConnected?.()
69
+ this.emit('connected')
70
+ resolve()
71
+ }
72
+
73
+ ws.onmessage = (event: MessageEvent) => {
74
+ let msg: Record<string, unknown>
75
+ try {
76
+ msg = JSON.parse(event.data as string)
77
+ } catch {
78
+ return
79
+ }
80
+ this.handleMessage(msg)
81
+ }
82
+
83
+ ws.onclose = () => {
84
+ console.warn(
85
+ `[ChartBridge] WS closed, autoReconnect=${this.autoReconnect}`,
86
+ )
87
+ this.ws = null
88
+ this.stopHeartbeat()
89
+ this.onDisconnected?.()
90
+ this.emit('disconnected')
91
+ if (this.autoReconnect && !this.destroyed) {
92
+ this.scheduleReconnect()
93
+ }
94
+ }
95
+
96
+ ws.onerror = () => {
97
+ console.error(`[ChartBridge] WS error — connection failed`)
98
+ const err = new Error('WebSocket connection failed')
99
+ this.onError?.(err)
100
+ this.emit('error', err)
101
+ reject(err)
102
+ }
103
+ } catch (err) {
104
+ reject(err)
105
+ }
106
+ })
107
+ }
108
+
109
+ disconnect(): void {
110
+ this.ws?.close()
111
+ this.ws = null
112
+ this.cancelReconnect()
113
+ this.stopHeartbeat()
114
+ }
115
+
116
+ destroy(): void {
117
+ this.destroyed = true
118
+ this.disconnect()
119
+ this.listeners.clear()
120
+ }
121
+
122
+ private handleMessage(msg: Record<string, unknown>): void {
123
+ switch (msg.type) {
124
+ case 'registered':
125
+ break
126
+
127
+ case 'tool:call': {
128
+ const call = msg.call as ToolCall
129
+ const requestId = msg.requestId as string
130
+ this.dispatchToolCall(requestId, call)
131
+ break
132
+ }
133
+
134
+ case 'ping': {
135
+ this.ws?.send(JSON.stringify({ type: 'pong' }))
136
+ break
137
+ }
138
+ }
139
+ }
140
+
141
+ private async dispatchToolCall(requestId: string, call: ToolCall): Promise<void> {
142
+ const result = await this.onToolCall(call)
143
+ this.sendResult(requestId, result)
144
+
145
+ if (this.onStateChange) {
146
+ this.onStateChange()
147
+ }
148
+ this.emit('stateChanged')
149
+ }
150
+
151
+ private sendResult(requestId: string, result: ToolResult): void {
152
+ this.ws?.send(
153
+ JSON.stringify({
154
+ type: 'tool:result',
155
+ requestId,
156
+ result,
157
+ }),
158
+ )
159
+ }
160
+
161
+ sendStateUpdate(
162
+ descriptions: Record<string, ControllerDescription>,
163
+ ): void {
164
+ this.ws?.send(
165
+ JSON.stringify({
166
+ type: 'state:update',
167
+ sessionId: this.sessionId,
168
+ descriptions,
169
+ }),
170
+ )
171
+ }
172
+
173
+ private startHeartbeat(): void {
174
+ this.stopHeartbeat()
175
+ this.heartbeatTimer = setInterval(() => {
176
+ if (this.ws?.readyState === 1) {
177
+ this.ws.send(JSON.stringify({ type: 'ping' }))
178
+ }
179
+ }, this.heartbeatInterval)
180
+ }
181
+
182
+ private stopHeartbeat(): void {
183
+ if (this.heartbeatTimer !== null) {
184
+ clearInterval(this.heartbeatTimer)
185
+ this.heartbeatTimer = null
186
+ }
187
+ }
188
+
189
+ private scheduleReconnect(): void {
190
+ this.cancelReconnect()
191
+ this.reconnectTimer = setTimeout(() => {
192
+ if (!this.destroyed) {
193
+ this.connect()
194
+ }
195
+ }, this.reconnectDelay)
196
+ }
197
+
198
+ private cancelReconnect(): void {
199
+ if (this.reconnectTimer !== null) {
200
+ clearTimeout(this.reconnectTimer)
201
+ this.reconnectTimer = null
202
+ }
203
+ }
204
+
205
+ private emit(event: ChartBridgeEvent, ...args: unknown[]): void {
206
+ this.listeners.get(event)?.forEach((fn) => fn(...args))
207
+ }
208
+
209
+ on(event: ChartBridgeEvent, handler: MessageHandler): () => void {
210
+ if (!this.listeners.has(event)) {
211
+ this.listeners.set(event, new Set())
212
+ }
213
+ this.listeners.get(event)!.add(handler)
214
+ return () => this.listeners.get(event)?.delete(handler)
215
+ }
216
+
217
+ off(event: ChartBridgeEvent, handler: MessageHandler): void {
218
+ this.listeners.get(event)?.delete(handler)
219
+ }
220
+ }
@@ -0,0 +1,2 @@
1
+ export { ChartBridge, type ChartBridgeOptions, type ChartBridgeEvent } from './chartBridge'
2
+ export type { ToolCall, ToolResult, ControllerDescription, ToolCallHandler } from './types'
@@ -0,0 +1,19 @@
1
+ export interface ToolCall {
2
+ name: string
3
+ input: Record<string, unknown>
4
+ }
5
+
6
+ export interface ToolResult {
7
+ success: boolean
8
+ error?: string
9
+ data?: unknown
10
+ }
11
+
12
+ export type ToolCallHandler = (call: ToolCall) => ToolResult | Promise<ToolResult>
13
+
14
+ export interface ControllerDescription {
15
+ controllerId: string
16
+ summary: string
17
+ facts: Readonly<Record<string, string | number | boolean | null>>
18
+ warnings?: ReadonlyArray<string>
19
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.8.2"
1
+ export const VERSION = "0.8.4"