@forgecharts/sdk 1.3.9 → 1.3.10
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/index.js.map +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/react/index.js +888 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/internal.js +3145 -3045
- package/dist/react/internal.js.map +1 -1
- package/dist/react/shell/ManagedAppShell.d.ts.map +1 -1
- package/dist/react/shell/WatchlistDrawer.d.ts +8 -1
- package/dist/react/shell/WatchlistDrawer.d.ts.map +1 -1
- package/dist/react/shell/useWatchlistQuotes.d.ts +1 -1
- package/dist/react/shell/useWatchlistQuotes.d.ts.map +1 -1
- package/dist/react/shell/watchlistApi.d.ts +3 -0
- package/dist/react/shell/watchlistApi.d.ts.map +1 -1
- package/dist/react/workspace/ChartWorkspace.d.ts +15 -3
- package/dist/react/workspace/ChartWorkspace.d.ts.map +1 -1
- package/dist/server/index.d.ts +22 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1051 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/knowledge.d.ts +11 -0
- package/dist/server/knowledge.d.ts.map +1 -0
- package/dist/server/systemPrompt.d.ts +13 -0
- package/dist/server/systemPrompt.d.ts.map +1 -0
- package/dist/server/tools.d.ts +24 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/package.json +6 -1
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
// src/server/tools.ts
|
|
2
|
+
function getAgentTools() {
|
|
3
|
+
return [
|
|
4
|
+
// ─── Chart Navigation ──────────────────────────────────────────────
|
|
5
|
+
{
|
|
6
|
+
name: "chart_get_state",
|
|
7
|
+
description: "Get the current state of the chart including symbol, timeframe, type, and visible range.",
|
|
8
|
+
input_schema: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {},
|
|
11
|
+
required: []
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "chart_set_symbol",
|
|
16
|
+
description: 'Change the currently displayed symbol (ticker). For futures, use continuous notation (e.g., "CME:ES1!") or specific contracts (e.g., "CME:ESM2026"). Always include the exchange prefix for futures.',
|
|
17
|
+
input_schema: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
symbol: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: 'Symbol to display. Examples: "AAPL", "BTCUSD", "CME:ES1!" (continuous), "CME:ESM2026" (specific month)'
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
required: ["symbol"]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "contract_get_info",
|
|
30
|
+
description: "Get futures contract information for a symbol: whether it is continuous or specific, the current front-month contract, and a list of upcoming available contracts. Call this BEFORE switching futures symbols to help the user choose between continuous and specific contracts.",
|
|
31
|
+
input_schema: {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: {
|
|
34
|
+
symbol: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: 'Futures symbol to look up (e.g., "ES", "ES1!", "CME:ESM2026", "CL"). Defaults to the current chart symbol if omitted.'
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
required: []
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "chart_set_timeframe",
|
|
44
|
+
description: 'Change the chart timeframe (e.g., "1m", "5m", "1h", "1d").',
|
|
45
|
+
input_schema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: {
|
|
48
|
+
timeframe: { type: "string", description: "Timeframe identifier (1m, 5m, 15m, 1h, 4h, 1d, 1w, etc.)" }
|
|
49
|
+
},
|
|
50
|
+
required: ["timeframe"]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "chart_set_type",
|
|
55
|
+
description: "Change the chart type (candlestick, line, area, bar, etc.).",
|
|
56
|
+
input_schema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
type: { type: "string", description: "Chart type (candlestick, line, area, bar, renko, etc.)" }
|
|
60
|
+
},
|
|
61
|
+
required: ["type"]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "chart_scroll_to_date",
|
|
66
|
+
description: "Scroll the chart to a specific date/timestamp.",
|
|
67
|
+
input_schema: {
|
|
68
|
+
type: "object",
|
|
69
|
+
properties: {
|
|
70
|
+
timestamp: { type: "number", description: "Unix timestamp (seconds) to scroll to" }
|
|
71
|
+
},
|
|
72
|
+
required: ["timestamp"]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "chart_set_visible_range",
|
|
77
|
+
description: "Set the visible price range (Y-axis) on the chart.",
|
|
78
|
+
input_schema: {
|
|
79
|
+
type: "object",
|
|
80
|
+
properties: {
|
|
81
|
+
minPrice: { type: "number", description: "Minimum price to display" },
|
|
82
|
+
maxPrice: { type: "number", description: "Maximum price to display" }
|
|
83
|
+
},
|
|
84
|
+
required: ["minPrice", "maxPrice"]
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
// ─── Market Data ──────────────────────────────────────────────────
|
|
88
|
+
{
|
|
89
|
+
name: "data_get_bars",
|
|
90
|
+
description: "Fetch OHLCV bars for analysis. CRITICAL: Always call this BEFORE placing drawings to find exact price levels.",
|
|
91
|
+
input_schema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
symbol: { type: "string", description: "Symbol to fetch bars for" },
|
|
95
|
+
timeframe: { type: "string", description: "Timeframe (1m, 5m, 1h, 1d, etc.)" },
|
|
96
|
+
limit: {
|
|
97
|
+
type: "number",
|
|
98
|
+
description: "Number of bars to fetch (default 100)"
|
|
99
|
+
},
|
|
100
|
+
from: {
|
|
101
|
+
type: "number",
|
|
102
|
+
description: "Unix timestamp (seconds) to start from (optional)"
|
|
103
|
+
},
|
|
104
|
+
to: {
|
|
105
|
+
type: "number",
|
|
106
|
+
description: "Unix timestamp (seconds) to end at (optional)"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
required: ["symbol", "timeframe"]
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "data_get_realtime_quote",
|
|
114
|
+
description: "Get the current bid/ask/last price for a symbol.",
|
|
115
|
+
input_schema: {
|
|
116
|
+
type: "object",
|
|
117
|
+
properties: {
|
|
118
|
+
symbol: { type: "string", description: "Symbol to fetch quote for" }
|
|
119
|
+
},
|
|
120
|
+
required: ["symbol"]
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "data_get_session_ohlc",
|
|
125
|
+
description: "Get current session OHLC stats (open, high, low, last, settlement) for a symbol.",
|
|
126
|
+
input_schema: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
symbol: { type: "string", description: "Symbol to fetch session OHLC for (optional, uses current chart symbol if not provided)" }
|
|
130
|
+
},
|
|
131
|
+
required: []
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
// ─── Indicators ───────────────────────────────────────────────────
|
|
135
|
+
{
|
|
136
|
+
name: "indicator_list",
|
|
137
|
+
description: "List all indicators currently applied to the chart.",
|
|
138
|
+
input_schema: {
|
|
139
|
+
type: "object",
|
|
140
|
+
properties: {},
|
|
141
|
+
required: []
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "indicator_add",
|
|
146
|
+
description: 'Add a built-in technical indicator to the chart. ALWAYS prefer this over ForgeScript for standard indicators. Built-in types: "sma", "ema", "wma", "rsi", "macd", "bbands" (Bollinger Bands), "stochastic", "atr", "obv", "volume". Overlay indicators (sma, ema, wma, bbands) render on the price chart; non-overlay indicators (rsi, macd, stochastic, atr, obv, volume) get their own sub-pane. Built-in indicators include a full settings dialog (gear icon) for users to adjust parameters.',
|
|
147
|
+
input_schema: {
|
|
148
|
+
type: "object",
|
|
149
|
+
properties: {
|
|
150
|
+
type: { type: "string", description: "Indicator type in lowercase: ema, sma, wma, rsi, macd, bbands, stochastic, atr, obv, volume" },
|
|
151
|
+
params: {
|
|
152
|
+
type: "object",
|
|
153
|
+
description: 'Indicator parameters. Examples: {"period": 50} for EMA/SMA, {"period":20,"maType":"sma","source":"close","multiplier":2,"offset":0} for bbands (maType: "sma"|"ema"|"wma"; source: "close"|"open"|"high"|"low"|"hl2"|"hlc3"|"ohlc4"), {"fast":12,"slow":26,"signal":9} for MACD'
|
|
154
|
+
},
|
|
155
|
+
overlay: {
|
|
156
|
+
type: "boolean",
|
|
157
|
+
description: "Whether to render on the price chart (true) or in a separate sub-pane (false). Defaults are automatic per type \u2014 only set this to override the default placement."
|
|
158
|
+
},
|
|
159
|
+
visible: {
|
|
160
|
+
type: "boolean",
|
|
161
|
+
description: "Whether the indicator should be visible (default true)"
|
|
162
|
+
},
|
|
163
|
+
style: {
|
|
164
|
+
type: "object",
|
|
165
|
+
description: 'Optional visual style overrides. Keys: line1, line2, line3 (each with color, width, lineStyle: "solid"|"dashed"|"dotted", visible), fill1 (color, opacity 0-1, visible). Example for bbands: {"line1":{"color":"#ff0000"},"line2":{"color":"#00ff00","width":2},"fill1":{"opacity":0.15}}'
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
required: ["type"]
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "indicator_remove",
|
|
173
|
+
description: "Remove an indicator from the chart.",
|
|
174
|
+
input_schema: {
|
|
175
|
+
type: "object",
|
|
176
|
+
properties: {
|
|
177
|
+
indicatorId: { type: "string", description: "ID of the indicator to remove" }
|
|
178
|
+
},
|
|
179
|
+
required: ["indicatorId"]
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "indicator_update_params",
|
|
184
|
+
description: "Update parameters of an existing indicator.",
|
|
185
|
+
input_schema: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
indicatorId: { type: "string", description: "ID of the indicator" },
|
|
189
|
+
params: {
|
|
190
|
+
type: "object",
|
|
191
|
+
description: "New parameters to apply"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
required: ["indicatorId", "params"]
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: "indicator_set_visible",
|
|
199
|
+
description: "Show or hide an indicator.",
|
|
200
|
+
input_schema: {
|
|
201
|
+
type: "object",
|
|
202
|
+
properties: {
|
|
203
|
+
indicatorId: { type: "string", description: "ID of the indicator" },
|
|
204
|
+
visible: { type: "boolean", description: "Whether to show (true) or hide (false)" }
|
|
205
|
+
},
|
|
206
|
+
required: ["indicatorId", "visible"]
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "indicator_list_available",
|
|
211
|
+
description: "Return full registry of available indicator names and their parameter schemas.",
|
|
212
|
+
input_schema: {
|
|
213
|
+
type: "object",
|
|
214
|
+
properties: {},
|
|
215
|
+
required: []
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "indicator_get_values",
|
|
220
|
+
description: "Return computed output series values for a running indicator.",
|
|
221
|
+
input_schema: {
|
|
222
|
+
type: "object",
|
|
223
|
+
properties: {
|
|
224
|
+
indicatorId: { type: "string", description: "ID of the indicator" },
|
|
225
|
+
limit: { type: "number", description: "Maximum number of values to return (default 100)" }
|
|
226
|
+
},
|
|
227
|
+
required: ["indicatorId"]
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
// ─── Drawings ─────────────────────────────────────────────────────
|
|
231
|
+
{
|
|
232
|
+
name: "drawing_list",
|
|
233
|
+
description: "List all drawings on the chart (trend lines, support/resistance, annotations).",
|
|
234
|
+
input_schema: {
|
|
235
|
+
type: "object",
|
|
236
|
+
properties: {},
|
|
237
|
+
required: []
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: "drawing_add",
|
|
242
|
+
description: "Draw on the chart (trend line, horizontal line, rectangle, text annotation, fibonacci tools, etc.). Always fetch bars first with data_get_bars to find exact price levels.",
|
|
243
|
+
input_schema: {
|
|
244
|
+
type: "object",
|
|
245
|
+
properties: {
|
|
246
|
+
type: {
|
|
247
|
+
type: "string",
|
|
248
|
+
description: 'Drawing type: "trendline", "extended_line", "ray", "horizontal_ray", "horizontal_line", "vertical_line", "fibonacci_retracement", "fibonacci_extension", "fibonacci_fan", "pitchfork", "rectangle", "channel", "text_label", "arrow_up", "arrow_down", "price_label", "gann_fan", "regression_trend"'
|
|
249
|
+
},
|
|
250
|
+
p1: {
|
|
251
|
+
type: "object",
|
|
252
|
+
description: "First anchor point {time: unix_seconds, price: number}",
|
|
253
|
+
properties: {
|
|
254
|
+
time: { type: "number", description: "Unix timestamp (seconds)" },
|
|
255
|
+
price: { type: "number", description: "Price level" }
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
p2: {
|
|
259
|
+
type: "object",
|
|
260
|
+
description: "Second anchor point (optional for single-point types) {time: unix_seconds, price: number}",
|
|
261
|
+
properties: {
|
|
262
|
+
time: { type: "number", description: "Unix timestamp (seconds)" },
|
|
263
|
+
price: { type: "number", description: "Price level" }
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
p3: {
|
|
267
|
+
type: "object",
|
|
268
|
+
description: "Third anchor point (for pitchfork, fibonacci_extension, channel) {time: unix_seconds, price: number}",
|
|
269
|
+
properties: {
|
|
270
|
+
time: { type: "number", description: "Unix timestamp (seconds)" },
|
|
271
|
+
price: { type: "number", description: "Price level" }
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
text: {
|
|
275
|
+
type: "string",
|
|
276
|
+
description: "Text content for text_label and price_label types"
|
|
277
|
+
},
|
|
278
|
+
style: {
|
|
279
|
+
type: "object",
|
|
280
|
+
description: "Drawing style properties",
|
|
281
|
+
properties: {
|
|
282
|
+
color: { type: "string", description: 'Color in hex format (e.g., "#FF0000")' },
|
|
283
|
+
lineWidth: { type: "number", description: "Line width in pixels" },
|
|
284
|
+
lineStyle: { type: "string", description: 'Line style: "solid", "dashed", or "dotted"' },
|
|
285
|
+
fillColor: { type: "string", description: "Fill color in hex format (optional)" },
|
|
286
|
+
fillOpacity: { type: "number", description: "Fill opacity from 0 to 1 (optional)" },
|
|
287
|
+
showLabel: { type: "boolean", description: "Whether to show the label (optional)" }
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
required: ["type", "p1"]
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "drawing_remove",
|
|
296
|
+
description: "Remove a drawing from the chart.",
|
|
297
|
+
input_schema: {
|
|
298
|
+
type: "object",
|
|
299
|
+
properties: {
|
|
300
|
+
drawingId: { type: "string", description: "ID of the drawing to remove" }
|
|
301
|
+
},
|
|
302
|
+
required: ["drawingId"]
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: "drawing_update",
|
|
307
|
+
description: "Update properties of an existing drawing (move it, change color, etc.).",
|
|
308
|
+
input_schema: {
|
|
309
|
+
type: "object",
|
|
310
|
+
properties: {
|
|
311
|
+
drawingId: { type: "string", description: "ID of the drawing" },
|
|
312
|
+
points: {
|
|
313
|
+
type: "array",
|
|
314
|
+
description: "New points (optional)",
|
|
315
|
+
items: { type: "object" }
|
|
316
|
+
},
|
|
317
|
+
color: {
|
|
318
|
+
type: "string",
|
|
319
|
+
description: "New color in hex format (optional)"
|
|
320
|
+
},
|
|
321
|
+
label: {
|
|
322
|
+
type: "string",
|
|
323
|
+
description: "New label/text (optional)"
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
required: ["drawingId"]
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: "drawing_clear_all",
|
|
331
|
+
description: "DESTRUCTIVE: Remove all drawings from the chart.",
|
|
332
|
+
input_schema: {
|
|
333
|
+
type: "object",
|
|
334
|
+
properties: {},
|
|
335
|
+
required: []
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
name: "drawing_list_types",
|
|
340
|
+
description: "Return all supported drawing type identifiers.",
|
|
341
|
+
input_schema: {
|
|
342
|
+
type: "object",
|
|
343
|
+
properties: {},
|
|
344
|
+
required: []
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
// ─── ForgeScript ───────────────────────────────────────────────────
|
|
348
|
+
{
|
|
349
|
+
name: "script_list",
|
|
350
|
+
description: "List all ForgeScript custom indicators saved in the workspace. Returns an array of scripts with id, name, and created_at. Use the id field when calling script_delete or script_get_source.",
|
|
351
|
+
input_schema: {
|
|
352
|
+
type: "object",
|
|
353
|
+
properties: {},
|
|
354
|
+
required: []
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
name: "script_delete",
|
|
359
|
+
description: "Delete a ForgeScript indicator permanently. Always call script_list first to get the script id, then confirm with the user before deleting.",
|
|
360
|
+
input_schema: {
|
|
361
|
+
type: "object",
|
|
362
|
+
properties: {
|
|
363
|
+
scriptId: { type: "string", description: "UUID id of the script to delete (from script_list)" }
|
|
364
|
+
},
|
|
365
|
+
required: ["scriptId"]
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
name: "script_get_source",
|
|
370
|
+
description: "Get the source code of a ForgeScript indicator.",
|
|
371
|
+
input_schema: {
|
|
372
|
+
type: "object",
|
|
373
|
+
properties: {
|
|
374
|
+
scriptId: { type: "string", description: "ID of the script" }
|
|
375
|
+
},
|
|
376
|
+
required: ["scriptId"]
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
name: "script_create",
|
|
381
|
+
description: "Create a new ForgeScript indicator. Always validate before compiling. IMPORTANT: Every tuneable value (periods, thresholds, multipliers) MUST use input()/input.int()/input.float() with a descriptive title. Every plot colour MUST use input.color() so the user can customise it from the settings dialog. Never hard-code magic numbers or colours.",
|
|
382
|
+
input_schema: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties: {
|
|
385
|
+
name: { type: "string", description: "Name of the new script" },
|
|
386
|
+
source: { type: "string", description: "ForgeScript source code. Must include input() for all configurable parameters and input.color() for all plot colours." }
|
|
387
|
+
},
|
|
388
|
+
required: ["name", "source"]
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
name: "script_update_source",
|
|
393
|
+
description: "Update the source code of an existing ForgeScript indicator. Always validate before compiling. Ensure all tuneable values use input() and all plot colours use input.color().",
|
|
394
|
+
input_schema: {
|
|
395
|
+
type: "object",
|
|
396
|
+
properties: {
|
|
397
|
+
scriptId: { type: "string", description: "ID of the script" },
|
|
398
|
+
source: { type: "string", description: "New ForgeScript source code. Must include input() for all configurable parameters and input.color() for all plot colours." }
|
|
399
|
+
},
|
|
400
|
+
required: ["scriptId", "source"]
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
name: "script_validate",
|
|
405
|
+
description: "Validate ForgeScript source code for syntax and semantic errors. ALWAYS call this before script_compile_attach. Fix any errors and re-validate until clean.",
|
|
406
|
+
input_schema: {
|
|
407
|
+
type: "object",
|
|
408
|
+
properties: {
|
|
409
|
+
source: { type: "string", description: "ForgeScript source code to validate" }
|
|
410
|
+
},
|
|
411
|
+
required: ["source"]
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
name: "script_compile_attach",
|
|
416
|
+
description: "DESTRUCTIVE: Compile and attach a ForgeScript indicator to the chart. Always validate with script_validate first and fix all errors.",
|
|
417
|
+
input_schema: {
|
|
418
|
+
type: "object",
|
|
419
|
+
properties: {
|
|
420
|
+
scriptId: { type: "string", description: "ID of the script to compile and attach" }
|
|
421
|
+
},
|
|
422
|
+
required: ["scriptId"]
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
name: "script_detach",
|
|
427
|
+
description: "Remove a running script from the chart.",
|
|
428
|
+
input_schema: {
|
|
429
|
+
type: "object",
|
|
430
|
+
properties: {
|
|
431
|
+
scriptId: { type: "string", description: "ID of the script to detach" }
|
|
432
|
+
},
|
|
433
|
+
required: ["scriptId"]
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
name: "script_get_console",
|
|
438
|
+
description: "Return last N lines of script console output.",
|
|
439
|
+
input_schema: {
|
|
440
|
+
type: "object",
|
|
441
|
+
properties: {
|
|
442
|
+
scriptId: { type: "string", description: "ID of the script" },
|
|
443
|
+
limit: { type: "number", description: "Number of lines to return (default 50)" }
|
|
444
|
+
},
|
|
445
|
+
required: ["scriptId"]
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
// ─── Datasets ─────────────────────────────────────────────────────
|
|
449
|
+
{
|
|
450
|
+
name: "script_dataset_create",
|
|
451
|
+
description: 'Create a named dataset (table) for a script. The dataset defines typed columns that the user can later import data into. The implicit first column is always "time" (timestamptz). Use lowercase snake_case for dataset and column names.',
|
|
452
|
+
input_schema: {
|
|
453
|
+
type: "object",
|
|
454
|
+
properties: {
|
|
455
|
+
scriptId: { type: "string", description: "ID of the parent script" },
|
|
456
|
+
name: { type: "string", description: "Dataset name (lowercase snake_case, 1-64 chars)" },
|
|
457
|
+
columns: {
|
|
458
|
+
type: "array",
|
|
459
|
+
description: "Column definitions. Types: number, integer, text, boolean, date, timestamp, percentage, price.",
|
|
460
|
+
items: {
|
|
461
|
+
type: "object",
|
|
462
|
+
properties: {
|
|
463
|
+
name: { type: "string", description: "Column name (lowercase snake_case)" },
|
|
464
|
+
type: { type: "string", description: "Column type: number | integer | text | boolean | date | timestamp | percentage | price" },
|
|
465
|
+
nullable: { type: "boolean", description: "Whether the column allows null values (default true)" }
|
|
466
|
+
},
|
|
467
|
+
required: ["name", "type"]
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
required: ["scriptId", "name", "columns"]
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
name: "script_dataset_list",
|
|
476
|
+
description: "List all datasets defined for a script, including their columns, row counts, and ingest status.",
|
|
477
|
+
input_schema: {
|
|
478
|
+
type: "object",
|
|
479
|
+
properties: {
|
|
480
|
+
scriptId: { type: "string", description: "ID of the script" }
|
|
481
|
+
},
|
|
482
|
+
required: ["scriptId"]
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
// ─── Documentation ──────────────────────────────────────────────────
|
|
486
|
+
{
|
|
487
|
+
name: "script_docs_write",
|
|
488
|
+
description: "Write or update the Markdown documentation for a script. Include a summary of what the indicator does, how to use it, parameter descriptions, and any relevant notes. Called AFTER script_create and script_compile_attach to document the finished indicator.",
|
|
489
|
+
input_schema: {
|
|
490
|
+
type: "object",
|
|
491
|
+
properties: {
|
|
492
|
+
scriptId: { type: "string", description: "ID of the script" },
|
|
493
|
+
content: { type: "string", description: "Markdown documentation content. Should include: summary, description of what the indicator calculates, parameter table, usage tips, and examples." }
|
|
494
|
+
},
|
|
495
|
+
required: ["scriptId", "content"]
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
// ─── Visibility & Pricing ───────────────────────────────────────────
|
|
499
|
+
{
|
|
500
|
+
name: "script_set_visibility",
|
|
501
|
+
description: 'Set the visibility and pricing of a script. Use "private" for personal use, "public" to share freely, or "for_sale" to sell on the marketplace. When setting for_sale, sale_price (minimum $1.00) is required. Always ask the user which visibility they want before calling this tool.',
|
|
502
|
+
input_schema: {
|
|
503
|
+
type: "object",
|
|
504
|
+
properties: {
|
|
505
|
+
scriptId: { type: "string", description: "ID of the script" },
|
|
506
|
+
visibility: { type: "string", enum: ["private", "public", "for_sale"], description: "Visibility level" },
|
|
507
|
+
sale_price: { type: "number", description: "Price in USD (required and must be >= 1.00 when visibility is for_sale)" },
|
|
508
|
+
preview_pct: { type: "integer", description: "Percentage of source code visible to non-purchasers (0-100, default 0). Only relevant for for_sale scripts." }
|
|
509
|
+
},
|
|
510
|
+
required: ["scriptId", "visibility"]
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
// ─── Backtesting ──────────────────────────────────────────────────
|
|
514
|
+
{
|
|
515
|
+
name: "backtest_run",
|
|
516
|
+
description: "Execute a ForgeScript strategy against OHLCV bars. Returns performance metrics and trade log.",
|
|
517
|
+
input_schema: {
|
|
518
|
+
type: "object",
|
|
519
|
+
properties: {
|
|
520
|
+
scriptId: { type: "string", description: "ID of the strategy script to backtest" },
|
|
521
|
+
symbol: { type: "string", description: "Symbol to backtest on" },
|
|
522
|
+
timeframe: { type: "string", description: "Timeframe (1m, 5m, 1h, 1d, etc.)" },
|
|
523
|
+
from: { type: "number", description: "Start time as Unix timestamp (seconds)" },
|
|
524
|
+
to: { type: "number", description: "End time as Unix timestamp (seconds)" },
|
|
525
|
+
params: { type: "object", description: "Optional strategy parameters as key-value pairs" }
|
|
526
|
+
},
|
|
527
|
+
required: ["scriptId", "symbol", "timeframe", "from", "to"]
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "backtest_get_trades",
|
|
532
|
+
description: "Return individual trade log from last backtest.",
|
|
533
|
+
input_schema: {
|
|
534
|
+
type: "object",
|
|
535
|
+
properties: {},
|
|
536
|
+
required: []
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
name: "backtest_get_equity_curve",
|
|
541
|
+
description: "Return equity curve as time series from last backtest.",
|
|
542
|
+
input_schema: {
|
|
543
|
+
type: "object",
|
|
544
|
+
properties: {},
|
|
545
|
+
required: []
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
name: "backtest_plot_equity",
|
|
550
|
+
description: "Draw equity curve overlay on active chart.",
|
|
551
|
+
input_schema: {
|
|
552
|
+
type: "object",
|
|
553
|
+
properties: {
|
|
554
|
+
pane: { type: "string", description: 'Chart pane: "overlay" (on main chart) or "separate" (new pane, default)' }
|
|
555
|
+
},
|
|
556
|
+
required: []
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
// ─── Layout ───────────────────────────────────────────────────────
|
|
560
|
+
{
|
|
561
|
+
name: "layout_list",
|
|
562
|
+
description: "List all saved chart layouts in the workspace.",
|
|
563
|
+
input_schema: {
|
|
564
|
+
type: "object",
|
|
565
|
+
properties: {},
|
|
566
|
+
required: []
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
name: "layout_load",
|
|
571
|
+
description: "Load a saved layout (applies saved indicators, drawings, settings).",
|
|
572
|
+
input_schema: {
|
|
573
|
+
type: "object",
|
|
574
|
+
properties: {
|
|
575
|
+
layoutId: { type: "string", description: "ID of the layout to load" }
|
|
576
|
+
},
|
|
577
|
+
required: ["layoutId"]
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
name: "layout_save",
|
|
582
|
+
description: "DESTRUCTIVE: Save the current chart state as a named layout.",
|
|
583
|
+
input_schema: {
|
|
584
|
+
type: "object",
|
|
585
|
+
properties: {
|
|
586
|
+
name: { type: "string", description: "Name for the layout" }
|
|
587
|
+
},
|
|
588
|
+
required: ["name"]
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
name: "layout_delete",
|
|
593
|
+
description: "DESTRUCTIVE: Delete a saved layout.",
|
|
594
|
+
input_schema: {
|
|
595
|
+
type: "object",
|
|
596
|
+
properties: {
|
|
597
|
+
layoutId: { type: "string", description: "ID of the layout to delete" }
|
|
598
|
+
},
|
|
599
|
+
required: ["layoutId"]
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
// ─── Watchlist ────────────────────────────────────────────────────
|
|
603
|
+
{
|
|
604
|
+
name: "watchlist_get",
|
|
605
|
+
description: "Get the symbols in the watchlist.",
|
|
606
|
+
input_schema: {
|
|
607
|
+
type: "object",
|
|
608
|
+
properties: {},
|
|
609
|
+
required: []
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: "watchlist_add",
|
|
614
|
+
description: "Add a symbol to the watchlist.",
|
|
615
|
+
input_schema: {
|
|
616
|
+
type: "object",
|
|
617
|
+
properties: {
|
|
618
|
+
symbol: { type: "string", description: "Symbol to add" }
|
|
619
|
+
},
|
|
620
|
+
required: ["symbol"]
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
name: "watchlist_remove",
|
|
625
|
+
description: "Remove a symbol from the watchlist.",
|
|
626
|
+
input_schema: {
|
|
627
|
+
type: "object",
|
|
628
|
+
properties: {
|
|
629
|
+
symbol: { type: "string", description: "Symbol to remove" }
|
|
630
|
+
},
|
|
631
|
+
required: ["symbol"]
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
// ─── Trading (READ-ONLY) ──────────────────────────────────────────
|
|
635
|
+
{
|
|
636
|
+
name: "trading_get_positions",
|
|
637
|
+
description: "Get open trading positions. READ-ONLY: cannot modify or close positions. Must place orders manually in the UI.",
|
|
638
|
+
input_schema: {
|
|
639
|
+
type: "object",
|
|
640
|
+
properties: {},
|
|
641
|
+
required: []
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
name: "trading_get_orders",
|
|
646
|
+
description: "Get current trading orders (pending, filled, cancelled). READ-ONLY: cannot modify, cancel, or place orders. Must do this manually in the UI.",
|
|
647
|
+
input_schema: {
|
|
648
|
+
type: "object",
|
|
649
|
+
properties: {},
|
|
650
|
+
required: []
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
name: "trading_get_fills",
|
|
655
|
+
description: "Get execution fills (historical trades). READ-ONLY access only.",
|
|
656
|
+
input_schema: {
|
|
657
|
+
type: "object",
|
|
658
|
+
properties: {
|
|
659
|
+
limit: { type: "number", description: "Number of recent fills to fetch (default 50)" }
|
|
660
|
+
},
|
|
661
|
+
required: []
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
name: "trading_get_account_summary",
|
|
666
|
+
description: "Get account balance, buying power, P&L, and margin info. READ-ONLY access only.",
|
|
667
|
+
input_schema: {
|
|
668
|
+
type: "object",
|
|
669
|
+
properties: {},
|
|
670
|
+
required: []
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
];
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/server/knowledge.ts
|
|
677
|
+
var FORGESCRIPT_REFERENCE = `## ForgeScript Language Reference
|
|
678
|
+
|
|
679
|
+
ForgeScript is a domain-specific language for financial technical indicators.
|
|
680
|
+
It uses a bar-by-bar execution model with persistent series state.
|
|
681
|
+
|
|
682
|
+
### Data Series (always available)
|
|
683
|
+
open, high, low, close, volume, time, hl2, hlc3, ohlc4, bar_index
|
|
684
|
+
|
|
685
|
+
### Bar State
|
|
686
|
+
barstate.islast, barstate.isfirst, barstate.isconfirmed, barstate.isnew,
|
|
687
|
+
barstate.isrealtime (always false), barstate.ishistory (always true)
|
|
688
|
+
|
|
689
|
+
### Syntax
|
|
690
|
+
|
|
691
|
+
CRITICAL \u2014 Assignment vs Reassignment:
|
|
692
|
+
- First assignment MUST use = (equals sign): length = input(14)
|
|
693
|
+
- Reassignment of an existing variable uses := (colon-equals): length := length + 1
|
|
694
|
+
- NEVER use := to declare a variable for the first time \u2014 this is a runtime error
|
|
695
|
+
- var (init-once per symbol): var x = 0 (uses = for the initial declaration)
|
|
696
|
+
- varip (init-once per session): varip x = 0 (uses = for the initial declaration)
|
|
697
|
+
- if/else (using indented blocks)
|
|
698
|
+
- for i = start to end [by step] (indented block)
|
|
699
|
+
- while condition (indented block)
|
|
700
|
+
- Ternary: condition ? then : else
|
|
701
|
+
- Index lookback: series[n] \u2014 access n bars ago
|
|
702
|
+
- Named arguments: plot(val, title="EMA", color=#FF0000)
|
|
703
|
+
|
|
704
|
+
### Built-in Functions
|
|
705
|
+
|
|
706
|
+
#### Technical Analysis (flat or ta.* namespace)
|
|
707
|
+
sma, ema, wma, rma, rsi, stdev, atr, highest, lowest, change, mom,
|
|
708
|
+
crossover, crossunder, cross, macd, bb, stoch, obv, correlation,
|
|
709
|
+
dev, variance, cum, sum, valuewhen, barssince, pivothigh, pivotlow,
|
|
710
|
+
tr, swma, vwma, rising, falling
|
|
711
|
+
|
|
712
|
+
#### Math (flat or math.* namespace)
|
|
713
|
+
abs, max, min, round, floor, ceil, sqrt, log, exp, pow, sign,
|
|
714
|
+
sin, cos, tan, asin, acos, atan, todegrees, toradians, avg, sum, random, log10
|
|
715
|
+
|
|
716
|
+
#### Color
|
|
717
|
+
17 named constants: color.red, color.green, color.blue, color.white, color.black, color.yellow,
|
|
718
|
+
color.orange, color.purple, color.fuchsia, color.lime, color.maroon, color.navy, color.olive,
|
|
719
|
+
color.silver, color.teal, color.aqua, color.gray
|
|
720
|
+
color.new(baseColor, transparency) \u2014 transparency 0-100 (100=fully transparent)
|
|
721
|
+
color.rgb(r, g, b, transparency?) \u2014 values 0-255 for r/g/b
|
|
722
|
+
color.from_gradient(value, bottom_value, top_value, bottom_color, top_color) \u2014 linear interpolation
|
|
723
|
+
Hex literals: #RRGGBB or #RRGGBBAA
|
|
724
|
+
|
|
725
|
+
#### String
|
|
726
|
+
str.tostring(value), str.tonumber(value), str.format(template, args...),
|
|
727
|
+
str.length(s), str.trim(s), str.contains(s, sub), str.startswith(s, prefix),
|
|
728
|
+
str.substring(s, start, end), str.replace_all(s, target, replacement),
|
|
729
|
+
str.upper(s), str.lower(s), str.split(s, separator) \u2192 returns an array,
|
|
730
|
+
str.match(s, regex) \u2192 returns matched string or ""
|
|
731
|
+
|
|
732
|
+
#### Arrays
|
|
733
|
+
array.new_float(size, initial_value), array.new_int(size, initial_value),
|
|
734
|
+
array.new_string(size, initial_value), array.new_bool(size, initial_value),
|
|
735
|
+
array.from(val1, val2, ...) \u2014 create array from values
|
|
736
|
+
array.size(arr), array.get(arr, index), array.set(arr, index, value),
|
|
737
|
+
array.push(arr, value), array.pop(arr), array.remove(arr, index),
|
|
738
|
+
array.clear(arr), array.includes(arr, value), array.indexof(arr, value),
|
|
739
|
+
array.slice(arr, start, end), array.join(arr, separator),
|
|
740
|
+
array.sort(arr), array.reverse(arr),
|
|
741
|
+
array.avg(arr), array.sum(arr), array.min(arr), array.max(arr)
|
|
742
|
+
|
|
743
|
+
#### Tables (screen-positioned text panels)
|
|
744
|
+
table.new(position, columns, rows, bgcolor=, border_color=, border_width=, frame_color=, frame_width=) \u2014 returns table id
|
|
745
|
+
table.cell(table_id, column, row, text, text_color=, bgcolor=, text_size=, text_halign=, text_valign=)
|
|
746
|
+
table.clear(table_id, first_col, first_row, last_col?, last_row?) \u2014 remove one cell or a range of cells
|
|
747
|
+
table.delete(table_id) \u2014 remove the entire table
|
|
748
|
+
Position values: "top_right", "top_left", "bottom_right", "bottom_left", etc.
|
|
749
|
+
Alignment: text.align_left \u2192 "left", text.align_center \u2192 "center", text.align_right \u2192 "right"
|
|
750
|
+
text.align_top \u2192 "top", text.align_bottom \u2192 "bottom"
|
|
751
|
+
|
|
752
|
+
#### User-defined Functions
|
|
753
|
+
name(param1, param2) => expression
|
|
754
|
+
name(param1, param2) =>
|
|
755
|
+
statement1
|
|
756
|
+
statement2
|
|
757
|
+
result_expression
|
|
758
|
+
|
|
759
|
+
#### Output
|
|
760
|
+
plot(value, title=, color=, linewidth=, style=)
|
|
761
|
+
plotshape(condition, style=, location=, color=, text=, title=)
|
|
762
|
+
plotchar, plotarrow, hline(price), fill, bgcolor(color), barcolor(color)
|
|
763
|
+
|
|
764
|
+
#### Pine Enum Constants (pass through as strings)
|
|
765
|
+
shape.* \u2192 "circle", "triangleup", "arrowup", etc.
|
|
766
|
+
location.* \u2192 "abovebar", "belowbar", "top", "bottom", "absolute"
|
|
767
|
+
plot.style_* \u2192 "line", "histogram", "area", "columns"
|
|
768
|
+
position.* \u2192 "top_right", "top_left", "bottom_right", "bottom_left", etc.
|
|
769
|
+
size.* \u2192 "auto", "tiny", "small", "normal", "large", "huge"
|
|
770
|
+
text.align_* \u2192 "left", "center", "right", "top", "bottom"
|
|
771
|
+
|
|
772
|
+
#### Input Parameters (all variants fully supported \u2014 return the default value at runtime)
|
|
773
|
+
input(defval, title=)
|
|
774
|
+
input.int(defval, title?, minval?, maxval?, step?)
|
|
775
|
+
input.float(defval, title?, minval?, maxval?, step?)
|
|
776
|
+
input.bool(defval, title?)
|
|
777
|
+
input.string(defval, title?, options?)
|
|
778
|
+
input.color(defval, title?)
|
|
779
|
+
input.source(defval, title?)
|
|
780
|
+
input.text_area(defval, title?)
|
|
781
|
+
Extra named args like tooltip=, group=, inline=, confirm= are accepted and silently ignored.
|
|
782
|
+
Options lists in input.string/input.int are accepted and silently ignored (only the default value matters).
|
|
783
|
+
|
|
784
|
+
#### Utility
|
|
785
|
+
na, nz(value, replacement)
|
|
786
|
+
|
|
787
|
+
### NOT SUPPORTED (do NOT use these)
|
|
788
|
+
- strategy.*, alertcondition, alert
|
|
789
|
+
- label, line, box, matrix
|
|
790
|
+
- import/export/module/library
|
|
791
|
+
- Classes or OOP constructs
|
|
792
|
+
- Async/await, promises, callbacks
|
|
793
|
+
- File I/O, network requests
|
|
794
|
+
- request.security (stub only \u2014 returns 0)
|
|
795
|
+
`;
|
|
796
|
+
|
|
797
|
+
// src/server/systemPrompt.ts
|
|
798
|
+
function buildSystemPrompt(chartContext) {
|
|
799
|
+
const contextSection = formatChartContext(chartContext);
|
|
800
|
+
return `# ForgeCharts AI Assistant
|
|
801
|
+
|
|
802
|
+
You are the ForgeCharts AI Assistant, an expert in technical analysis, market microstructure, and custom indicator development using ForgeScript. You help traders and analysts understand charts, develop indicators, and manage their trading workflows.
|
|
803
|
+
|
|
804
|
+
## Core Operational Rules
|
|
805
|
+
|
|
806
|
+
### Drawing Rule (CRITICAL)
|
|
807
|
+
When asked to draw support/resistance, trend lines, or any price-based annotation:
|
|
808
|
+
1. ALWAYS call \`data_get_bars\` FIRST to fetch recent price data
|
|
809
|
+
2. Find the exact high/low/close prices from the returned bars
|
|
810
|
+
3. Use precise price levels from the data \u2014 NEVER estimate or guess prices
|
|
811
|
+
4. Only then call \`drawing_add\` with the exact timestamp and price coordinates
|
|
812
|
+
|
|
813
|
+
**Why:** Eyeballing prices leads to inaccurate analysis. Real price levels matter.
|
|
814
|
+
|
|
815
|
+
### Built-in Indicator Preference (CRITICAL)
|
|
816
|
+
When a user asks for a standard indicator (Bollinger Bands, EMA, SMA, RSI, MACD, Stochastic, ATR, OBV, Volume):
|
|
817
|
+
1. **ALWAYS use \`indicator_add\`** with the built-in type \u2014 NEVER create a ForgeScript for these
|
|
818
|
+
2. Built-in types: \`sma\`, \`ema\`, \`wma\`, \`rsi\`, \`macd\`, \`bbands\`, \`stochastic\`, \`atr\`, \`obv\`, \`volume\`
|
|
819
|
+
3. Built-in indicators have proper overlay placement, configurable settings dialogs, and optimised rendering
|
|
820
|
+
|
|
821
|
+
**Built-in indicator defaults:**
|
|
822
|
+
| Type | Overlay | Default Params |
|
|
823
|
+
|------|---------|---------------|
|
|
824
|
+
| \`sma\` | yes | period: 20 |
|
|
825
|
+
| \`ema\` | yes | period: 20 |
|
|
826
|
+
| \`wma\` | yes | period: 20 |
|
|
827
|
+
| \`bbands\` | yes | period: 20, maType: "sma", source: "close", multiplier: 2, offset: 0 |
|
|
828
|
+
| \`rsi\` | no | period: 14 |
|
|
829
|
+
| \`macd\` | no | fast: 12, slow: 26, signal: 9 |
|
|
830
|
+
| \`stochastic\` | no | kPeriod: 14, dPeriod: 3, smooth: 3 |
|
|
831
|
+
| \`atr\` | no | period: 14 |
|
|
832
|
+
| \`obv\` | no | (none) |
|
|
833
|
+
| \`volume\` | no | (none) |
|
|
834
|
+
|
|
835
|
+
Only use ForgeScript (\`script_create\` / \`script_compile_attach\`) for **custom** indicators that are NOT available as built-in types \u2014 for example, custom oscillators, multi-factor composites, or proprietary calculations.
|
|
836
|
+
|
|
837
|
+
### ForgeScript Rule (CRITICAL)
|
|
838
|
+
When developing or modifying ForgeScript indicators:
|
|
839
|
+
1. ALWAYS call \`script_validate\` first on your source code
|
|
840
|
+
2. Read the error message carefully if validation fails
|
|
841
|
+
3. Fix the error (check syntax, variable declarations, function names)
|
|
842
|
+
4. Call \`script_validate\` again until it passes (status = "clean")
|
|
843
|
+
5. Only then proceed to \`script_compile_attach\`
|
|
844
|
+
|
|
845
|
+
**Why:** Validation catches logic errors before wasting time compiling broken code.
|
|
846
|
+
|
|
847
|
+
### ForgeScript indicator() Syntax (CRITICAL)
|
|
848
|
+
Every script MUST start with \`indicator()\` using a **string literal** as the first argument:
|
|
849
|
+
\`\`\`
|
|
850
|
+
indicator("My Indicator Title", overlay=true)
|
|
851
|
+
\`\`\`
|
|
852
|
+
- The title MUST be a **string literal** in double quotes \u2014 NOT a variable or identifier
|
|
853
|
+
- WRONG: \`indicator(title)\`, \`indicator('title')\`, \`indicator(myTitle)\`
|
|
854
|
+
- CORRECT: \`indicator("MACD Custom", overlay=false)\`
|
|
855
|
+
|
|
856
|
+
### ForgeScript Configurable Inputs & Style (CRITICAL)
|
|
857
|
+
Every ForgeScript indicator MUST expose **all tuneable values** as \`input()\` declarations so users can adjust them via the settings dialog (gear icon). This includes:
|
|
858
|
+
|
|
859
|
+
1. **Numeric parameters** \u2014 use \`input()\`, \`input.int()\`, or \`input.float()\` with descriptive \`title\` and sensible \`minval\`/\`step\`:
|
|
860
|
+
\`\`\`
|
|
861
|
+
length = input.int(14, title="Length", minval=1)
|
|
862
|
+
mult = input.float(2.0, title="Multiplier", step=0.1, minval=0.1)
|
|
863
|
+
\`\`\`
|
|
864
|
+
2. **Source fields** \u2014 use \`input.source()\` or \`input(close, title="Source")\`:
|
|
865
|
+
\`\`\`
|
|
866
|
+
src = input(close, title="Source")
|
|
867
|
+
\`\`\`
|
|
868
|
+
3. **Line colours** \u2014 use \`input.color()\` and pass the result to \`plot()\` via the \`color\` argument:
|
|
869
|
+
\`\`\`
|
|
870
|
+
lineCol = input.color(#2196f3, title="Line Color")
|
|
871
|
+
plot(value, title="Signal", color=lineCol, linewidth=2)
|
|
872
|
+
\`\`\`
|
|
873
|
+
4. **Boolean toggles** \u2014 use \`input.bool()\` for optional features:
|
|
874
|
+
\`\`\`
|
|
875
|
+
showBand = input.bool(true, title="Show Fill")
|
|
876
|
+
\`\`\`
|
|
877
|
+
|
|
878
|
+
**Rules:**
|
|
879
|
+
- NEVER hard-code a magic number (period, length, multiplier, threshold) \u2014 always wrap it in \`input()\`
|
|
880
|
+
- NEVER hard-code a plot colour \u2014 always use \`input.color()\` so the user can customise it from settings
|
|
881
|
+
- Give every input a clear, user-friendly \`title\`
|
|
882
|
+
- Group related inputs together (lengths first, then style, then toggles)
|
|
883
|
+
- Use \`input.int()\` for whole-number params and \`input.float()\` for decimal params with appropriate \`step\`
|
|
884
|
+
|
|
885
|
+
**Example \u2014 correct pattern:**
|
|
886
|
+
\`\`\`
|
|
887
|
+
indicator("Custom RSI", overlay=false)
|
|
888
|
+
length = input.int(14, title="RSI Length", minval=1)
|
|
889
|
+
upper = input.int(70, title="Overbought Level", minval=50, maxval=100)
|
|
890
|
+
lower = input.int(30, title="Oversold Level", minval=0, maxval=50)
|
|
891
|
+
rsiColor = input.color(#7b1fa2, title="RSI Color")
|
|
892
|
+
obColor = input.color(#ef5350, title="Overbought Line Color")
|
|
893
|
+
osColor = input.color(#26a69a, title="Oversold Line Color")
|
|
894
|
+
|
|
895
|
+
rsiVal = ta.rsi(close, length)
|
|
896
|
+
plot(rsiVal, title="RSI", color=rsiColor, linewidth=2)
|
|
897
|
+
hline(upper, title="Overbought", color=obColor, linestyle="dashed")
|
|
898
|
+
hline(lower, title="Oversold", color=osColor, linestyle="dashed")
|
|
899
|
+
\`\`\`
|
|
900
|
+
|
|
901
|
+
**Why:** Without \`input()\` calls, the indicator has no settings for the user to adjust \u2014 it becomes a black box with no configurability.
|
|
902
|
+
|
|
903
|
+
### Updating an Existing Script (CRITICAL)
|
|
904
|
+
When the user asks you to modify a script that is already running on the chart:
|
|
905
|
+
1. Call \`script_update_source\` with the new code
|
|
906
|
+
2. Call \`script_validate\` to verify the new code
|
|
907
|
+
3. Call \`script_compile_attach\` \u2014 this will **automatically detach the old instance** before attaching the updated version
|
|
908
|
+
Do NOT call \`script_create\` to make a second copy. Do NOT manually call \`script_detach\` \u2014 \`script_compile_attach\` handles it.
|
|
909
|
+
|
|
910
|
+
### Script Publishing Workflow (CRITICAL)
|
|
911
|
+
After creating and compiling a ForgeScript indicator, ALWAYS complete these additional steps:
|
|
912
|
+
|
|
913
|
+
1. **Documentation** \u2014 Call \`script_docs_write\` with Markdown content that includes:
|
|
914
|
+
- A one-line summary of what the indicator does
|
|
915
|
+
- A description of how it works (the calculation logic)
|
|
916
|
+
- A parameter table listing every \`input()\` with its name, type, default, and description
|
|
917
|
+
- Usage tips and examples
|
|
918
|
+
**Why:** Scripts without documentation are unusable to other users and hard to maintain.
|
|
919
|
+
|
|
920
|
+
2. **Datasets** \u2014 If the indicator needs external data (e.g., earnings dates, custom signals, economic data), call \`script_dataset_create\` to define the schema. Each dataset:
|
|
921
|
+
- Has an implicit first column: \`time\` (timestamptz)
|
|
922
|
+
- Must use lowercase snake_case names
|
|
923
|
+
- Column types: \`number\`, \`integer\`, \`text\`, \`boolean\`, \`date\`, \`timestamp\`, \`percentage\`, \`price\`
|
|
924
|
+
The user can later import CSV/JSON data into the dataset to populate it.
|
|
925
|
+
**Only create datasets when the indicator genuinely requires external data** \u2014 most indicators operate on built-in OHLCV series and do not need a dataset.
|
|
926
|
+
|
|
927
|
+
3. **Visibility** \u2014 Ask the user how they want to share the script, then call \`script_set_visibility\`:
|
|
928
|
+
- \`private\` \u2014 only the owner can see/use it (default)
|
|
929
|
+
- \`public\` \u2014 any user can see and use it for free
|
|
930
|
+
- \`for_sale\` \u2014 listed on the marketplace at a set price (minimum $1.00). Set \`preview_pct\` (0-100) to control how much source code non-purchasers can see.
|
|
931
|
+
**Always ask before setting visibility** \u2014 never assume the user wants to publish or sell.
|
|
932
|
+
|
|
933
|
+
**Complete script creation flow:**
|
|
934
|
+
\`\`\`
|
|
935
|
+
script_create \u2192 script_validate \u2192 script_compile_attach
|
|
936
|
+
\u2192 script_docs_write (always)
|
|
937
|
+
\u2192 script_dataset_create (only if needed)
|
|
938
|
+
\u2192 script_set_visibility (ask user first)
|
|
939
|
+
\`\`\`
|
|
940
|
+
|
|
941
|
+
### Removing Indicators (IMPORTANT)
|
|
942
|
+
To remove an indicator from the chart, call \`indicator_remove\` with the \`indicatorId\` parameter. You can get indicator IDs from \`indicator_list\`.
|
|
943
|
+
|
|
944
|
+
### UI Automation (IMPORTANT)
|
|
945
|
+
The ForgeCharts platform responds to your tool calls by automatically showing the relevant UI panel. You DO have the ability to drive the interface:
|
|
946
|
+
|
|
947
|
+
- Calling \`watchlist_get\` or \`watchlist_add\` \u2192 **opens the Watchlist drawer**
|
|
948
|
+
- Calling \`indicator_list\` or \`indicator_add\` \u2192 **opens then auto-closes the Indicators dialog**
|
|
949
|
+
- Calling \`trading_get_positions\` \u2192 **opens the Positions tab** in the trading panel
|
|
950
|
+
- Calling \`trading_get_orders\` \u2192 **opens the Orders tab** in the trading panel
|
|
951
|
+
- Calling \`trading_get_fills\` \u2192 **opens the Fills tab** in the trading panel
|
|
952
|
+
- Calling \`script_create\` or \`script_update_source\` \u2192 **opens the Script editor** and types the code live
|
|
953
|
+
- Calling \`chart_set_timeframe\` \u2192 **switches the chart timeframe**
|
|
954
|
+
- Calling \`chart_set_symbol\` \u2192 **changes the chart symbol**
|
|
955
|
+
|
|
956
|
+
When a user asks to "show me the watchlist", "open the indicators", "show positions", etc. \u2014 call the appropriate tool. The UI will respond automatically.
|
|
957
|
+
|
|
958
|
+
### Futures Contract Rule (CRITICAL)
|
|
959
|
+
When a user asks to "open a contract", "switch to ES", "pull up crude", or any request involving a futures symbol:
|
|
960
|
+
1. Call \`contract_get_info\` to determine contract metadata for the symbol
|
|
961
|
+
2. If the symbol is a futures product, ALWAYS ask the user to choose:
|
|
962
|
+
- **Continuous contract** (e.g., CME:ES1!) \u2014 automatically rolls to the front month, provides seamless historical data
|
|
963
|
+
- **Specific monthly contract** (e.g., CME:ESU2026) \u2014 the exact current front-month contract with real expiry
|
|
964
|
+
3. Present both options clearly, including the exact contract name and month
|
|
965
|
+
4. Only call \`chart_set_symbol\` AFTER the user has chosen
|
|
966
|
+
5. Always include the exchange prefix for futures (e.g., "CME:ES1!", not just "ES1!")
|
|
967
|
+
|
|
968
|
+
**Example response:**
|
|
969
|
+
"ES is currently in the **September 2026 (ESU2026)** contract. Would you like me to open:
|
|
970
|
+
- **CME:ES1!** \u2014 the continuous contract (auto-rolls, seamless history)
|
|
971
|
+
- **CME:ESU2026** \u2014 the specific September 2026 contract
|
|
972
|
+
|
|
973
|
+
Which do you prefer?"
|
|
974
|
+
|
|
975
|
+
**Why:** Traders need to know exactly which contract they're viewing. Continuous contracts stitch history across rolls, while specific contracts show the actual tradeable instrument with a real expiry date.
|
|
976
|
+
|
|
977
|
+
The chart context includes \`contractInfo\` when the current symbol is a futures product \u2014 use it to report the active contract without needing an extra tool call.
|
|
978
|
+
|
|
979
|
+
### Trading Rule (CRITICAL)
|
|
980
|
+
You have READ-ONLY access to trading data. You CANNOT:
|
|
981
|
+
- Place new orders
|
|
982
|
+
- Modify existing orders
|
|
983
|
+
- Cancel orders
|
|
984
|
+
- Close or exit positions
|
|
985
|
+
- Execute any trading action
|
|
986
|
+
|
|
987
|
+
If asked to place, modify, or cancel an order:
|
|
988
|
+
1. Decline politely
|
|
989
|
+
2. Explain the limitation
|
|
990
|
+
3. Redirect to manual order entry in the UI
|
|
991
|
+
4. Optionally help analyze market conditions for their decision
|
|
992
|
+
|
|
993
|
+
**Example response:** "I can't place orders, but I can help you analyze the chart. Let me fetch bars around [level] to show you the support/resistance setup..."
|
|
994
|
+
|
|
995
|
+
### Tone & Communication
|
|
996
|
+
- **Concise:** Skip basic explanations unless directly asked "explain this to me"
|
|
997
|
+
- **Professional:** Use proper terminology (e.g., "confluence", "liquidity void", not "seems bullish")
|
|
998
|
+
- **Action-oriented:** Prefer "Call X to achieve Y" over lengthy theory
|
|
999
|
+
- **Context-aware:** Reference the current chart state (symbol, timeframe, indicators)
|
|
1000
|
+
|
|
1001
|
+
## Current Chart Context
|
|
1002
|
+
|
|
1003
|
+
${contextSection}
|
|
1004
|
+
|
|
1005
|
+
## ForgeScript Language Reference
|
|
1006
|
+
|
|
1007
|
+
${FORGESCRIPT_REFERENCE}
|
|
1008
|
+
|
|
1009
|
+
---
|
|
1010
|
+
|
|
1011
|
+
**End of System Prompt**
|
|
1012
|
+
`;
|
|
1013
|
+
}
|
|
1014
|
+
function formatChartContext(ctx) {
|
|
1015
|
+
const indicatorList = ctx.indicators.length > 0 ? ctx.indicators.map((ind) => ` - ${ind.name} (${ind.visible ? "visible" : "hidden"})`).join("\n") : " (none)";
|
|
1016
|
+
const drawingList = ctx.drawings.length > 0 ? ctx.drawings.map((drw) => ` - ${drw.type} [${drw.id}]`).join("\n") : " (none)";
|
|
1017
|
+
const barSummary = ctx.recentBars.length > 0 ? (() => {
|
|
1018
|
+
const closes = ctx.recentBars.map((b) => b.close);
|
|
1019
|
+
const high = Math.max(...closes);
|
|
1020
|
+
const low = Math.min(...closes);
|
|
1021
|
+
const latest = ctx.recentBars[ctx.recentBars.length - 1];
|
|
1022
|
+
return `${ctx.recentBars.length} bars loaded; latest close: ${latest.close}, range: ${low} to ${high}`;
|
|
1023
|
+
})() : "(no bars loaded)";
|
|
1024
|
+
const tradingStatus = ctx.tradingConnected ? `Connected, ${ctx.openPositionCount} open position(s)` : "Not connected";
|
|
1025
|
+
const contractLine = ctx.contractInfo ? `
|
|
1026
|
+
- Contract Type: **${ctx.contractInfo.isContinuous ? "Continuous" : "Specific Monthly"}** (product: ${ctx.contractInfo.product}, exchange: ${ctx.contractInfo.exchange})
|
|
1027
|
+
- Front-Month Contract: **${ctx.contractInfo.frontMonthContract}**
|
|
1028
|
+
- Continuous Symbol: **${ctx.contractInfo.continuousSymbol}**` : "";
|
|
1029
|
+
return `### Symbol & Viewport
|
|
1030
|
+
- Symbol: **${ctx.symbol}**
|
|
1031
|
+
- Timeframe: **${ctx.timeframe}**
|
|
1032
|
+
- Chart Type: **${ctx.chartType}**${contractLine}
|
|
1033
|
+
- Visible Range: ${ctx.visibleRange.from} to ${ctx.visibleRange.to} (bars)
|
|
1034
|
+
|
|
1035
|
+
### Recent Data
|
|
1036
|
+
- ${barSummary}
|
|
1037
|
+
|
|
1038
|
+
### Indicators
|
|
1039
|
+
${indicatorList}
|
|
1040
|
+
|
|
1041
|
+
### Drawings
|
|
1042
|
+
${drawingList}
|
|
1043
|
+
|
|
1044
|
+
### Trading Status
|
|
1045
|
+
- ${tradingStatus}
|
|
1046
|
+
`;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
export { FORGESCRIPT_REFERENCE, buildSystemPrompt, getAgentTools };
|
|
1050
|
+
//# sourceMappingURL=index.js.map
|
|
1051
|
+
//# sourceMappingURL=index.js.map
|