toad-eye 2.9.2 → 2.11.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.
Files changed (40) hide show
  1. package/README.md +1 -1
  2. package/dist/alerts/channels.js +4 -1
  3. package/dist/alerts/conditions.js +3 -2
  4. package/dist/alerts/grafana.js +1 -0
  5. package/dist/alerts/manager.js +2 -0
  6. package/dist/cli.js +76 -8
  7. package/dist/core/console-exporter.d.ts +17 -0
  8. package/dist/core/console-exporter.js +55 -0
  9. package/dist/core/metrics.d.ts +1 -0
  10. package/dist/core/metrics.js +12 -0
  11. package/dist/core/span-end-processor.js +1 -1
  12. package/dist/core/spans.d.ts +4 -0
  13. package/dist/core/spans.js +21 -1
  14. package/dist/core/tracer.js +27 -16
  15. package/dist/instrumentations/create.js +0 -1
  16. package/dist/instrumentations/mcp.d.ts +5 -1
  17. package/dist/instrumentations/mcp.js +15 -6
  18. package/dist/mcp/client.d.ts +5 -1
  19. package/dist/mcp/client.js +29 -6
  20. package/dist/mcp/index.d.ts +1 -0
  21. package/dist/mcp/index.js +1 -0
  22. package/dist/mcp/metrics.d.ts +1 -0
  23. package/dist/mcp/metrics.js +11 -0
  24. package/dist/mcp/middleware.js +14 -4
  25. package/dist/types/config.d.ts +2 -0
  26. package/dist/types/metrics.d.ts +2 -0
  27. package/dist/types/metrics.js +3 -0
  28. package/package.json +1 -1
  29. package/templates/docker-compose.yml +4 -4
  30. package/templates/grafana/dashboards/agent-workflow.json +32 -47
  31. package/templates/grafana/dashboards/cost-breakdown.json +14 -7
  32. package/templates/grafana/dashboards/error-drilldown.json +12 -6
  33. package/templates/grafana/dashboards/finops-attribution.json +39 -8
  34. package/templates/grafana/dashboards/latency-analysis.json +8 -4
  35. package/templates/grafana/dashboards/llm-overview.json +22 -11
  36. package/templates/grafana/dashboards/mcp-analytics.json +177 -43
  37. package/templates/grafana/dashboards/mcp-e2e.json +198 -51
  38. package/templates/grafana/dashboards/mcp-server.json +46 -9
  39. package/templates/grafana/dashboards/model-comparison.json +10 -5
  40. package/templates/grafana/dashboards/provider-health.json +15 -8
@@ -33,6 +33,15 @@ function truncate(value, maxBytes) {
33
33
  return value;
34
34
  return value.slice(0, maxBytes) + "...[truncated]";
35
35
  }
36
+ function redactValue(v, keys) {
37
+ if (Array.isArray(v)) {
38
+ return v.map((item) => redactValue(item, keys));
39
+ }
40
+ if (typeof v === "object" && v !== null) {
41
+ return redactObject(v, keys);
42
+ }
43
+ return v;
44
+ }
36
45
  function redactObject(obj, keys) {
37
46
  if (typeof obj !== "object" || obj === null)
38
47
  return {};
@@ -41,11 +50,8 @@ function redactObject(obj, keys) {
41
50
  if (keys.includes(k)) {
42
51
  result[k] = "[REDACTED]";
43
52
  }
44
- else if (typeof v === "object" && v !== null && !Array.isArray(v)) {
45
- result[k] = redactObject(v, keys);
46
- }
47
53
  else {
48
- result[k] = v;
54
+ result[k] = redactValue(v, keys);
49
55
  }
50
56
  }
51
57
  return result;
@@ -74,7 +80,11 @@ function redactObject(obj, keys) {
74
80
  * In stdio MCP transport, stdout IS the JSON-RPC channel —
75
81
  * any stray console.log or OTel diagnostic would crash the connection.
76
82
  */
83
+ let stdioSafe = false;
77
84
  function ensureStdioSafe() {
85
+ if (stdioSafe)
86
+ return;
87
+ stdioSafe = true;
78
88
  const stderrLogger = new DiagConsoleLogger();
79
89
  // Override the logger to use stderr-only methods
80
90
  const safeLogger = {
@@ -22,6 +22,8 @@ export interface SamplingConfig {
22
22
  export interface ToadEyeConfig {
23
23
  readonly serviceName: string;
24
24
  readonly endpoint?: string | undefined;
25
+ /** Output mode: "otlp" (default) sends to OTel Collector, "console" prints spans to stderr (no Docker needed). */
26
+ readonly output?: "otlp" | "console" | undefined;
25
27
  /** API key for toad-eye cloud. When set, transport switches to HTTPS cloud endpoint automatically. */
26
28
  readonly apiKey?: string | undefined;
27
29
  /** Custom cloud endpoint override. Defaults to https://cloud.toad-eye.dev. */
@@ -26,12 +26,14 @@ export declare const GEN_AI_METRICS: {
26
26
  readonly RESPONSE_LATENCY_PER_TOKEN: "gen_ai.toad_eye.response.latency_per_token";
27
27
  readonly CONTEXT_UTILIZATION: "gen_ai.toad_eye.context_utilization";
28
28
  readonly CONTEXT_BLOCKED: "gen_ai.toad_eye.context.blocked";
29
+ readonly THINKING_RATIO: "gen_ai.toad_eye.thinking.ratio";
29
30
  readonly MCP_TOOL_DURATION: "gen_ai.mcp.tool.duration";
30
31
  readonly MCP_TOOL_CALLS: "gen_ai.mcp.tool.calls";
31
32
  readonly MCP_TOOL_ERRORS: "gen_ai.mcp.tool.errors";
32
33
  readonly MCP_RESOURCE_READS: "gen_ai.mcp.resource.reads";
33
34
  readonly MCP_SESSION_ACTIVE: "gen_ai.mcp.session.active";
34
35
  readonly MCP_TOOL_CALLERS: "gen_ai.mcp.tool.callers";
36
+ readonly MCP_TOOL_HALLUCINATIONS: "gen_ai.mcp.tool.hallucinations";
35
37
  };
36
38
  /** @deprecated Use GEN_AI_METRICS instead. Kept for backward compatibility. */
37
39
  export declare const LLM_METRICS: {
@@ -33,6 +33,8 @@ export const GEN_AI_METRICS = {
33
33
  // Context utilization
34
34
  CONTEXT_UTILIZATION: "gen_ai.toad_eye.context_utilization",
35
35
  CONTEXT_BLOCKED: "gen_ai.toad_eye.context.blocked",
36
+ // Thinking/reasoning models
37
+ THINKING_RATIO: "gen_ai.toad_eye.thinking.ratio",
36
38
  // MCP metrics
37
39
  MCP_TOOL_DURATION: "gen_ai.mcp.tool.duration",
38
40
  MCP_TOOL_CALLS: "gen_ai.mcp.tool.calls",
@@ -40,6 +42,7 @@ export const GEN_AI_METRICS = {
40
42
  MCP_RESOURCE_READS: "gen_ai.mcp.resource.reads",
41
43
  MCP_SESSION_ACTIVE: "gen_ai.mcp.session.active",
42
44
  MCP_TOOL_CALLERS: "gen_ai.mcp.tool.callers",
45
+ MCP_TOOL_HALLUCINATIONS: "gen_ai.mcp.tool.hallucinations",
43
46
  };
44
47
  /** @deprecated Use GEN_AI_METRICS instead. Kept for backward compatibility. */
45
48
  export const LLM_METRICS = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toad-eye",
3
- "version": "2.9.2",
3
+ "version": "2.11.0",
4
4
  "description": "Observability for MCP servers and LLM applications — traces, metrics, dashboards. One-line instrumentation for OpenAI, Anthropic, Gemini, and MCP. Self-hosted with Grafana + Prometheus + Jaeger.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -4,7 +4,7 @@ services:
4
4
  volumes:
5
5
  - ./otel-collector.yml:/etc/otelcol-contrib/config.yaml
6
6
  ports:
7
- - "4318:4318"
7
+ - "${COLLECTOR_PORT:-4318}:4318"
8
8
  depends_on:
9
9
  - jaeger
10
10
  - prometheus
@@ -14,14 +14,14 @@ services:
14
14
  volumes:
15
15
  - ./prometheus.yml:/etc/prometheus/prometheus.yml
16
16
  ports:
17
- - "9090:9090"
17
+ - "${PROMETHEUS_PORT:-9090}:9090"
18
18
 
19
19
  jaeger:
20
20
  image: jaegertracing/all-in-one:1.58
21
21
  environment:
22
22
  - COLLECTOR_OTLP_ENABLED=true
23
23
  ports:
24
- - "16686:16686"
24
+ - "${JAEGER_PORT:-16686}:16686"
25
25
  - "4317:4317"
26
26
 
27
27
  grafana:
@@ -33,7 +33,7 @@ services:
33
33
  - GF_SECURITY_ADMIN_PASSWORD=admin
34
34
  - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/llm-overview.json
35
35
  ports:
36
- - "3100:3000"
36
+ - "${GRAFANA_PORT:-3100}:3000"
37
37
  depends_on:
38
38
  - prometheus
39
39
  - jaeger
@@ -46,7 +46,8 @@
46
46
  "value": 20
47
47
  }
48
48
  ]
49
- }
49
+ },
50
+ "noValue": "No data yet — run: npx toad-eye demo"
50
51
  },
51
52
  "overrides": []
52
53
  }
@@ -72,7 +73,8 @@
72
73
  ],
73
74
  "fieldConfig": {
74
75
  "defaults": {
75
- "unit": "short"
76
+ "unit": "short",
77
+ "noValue": "No data yet — run: npx toad-eye demo"
76
78
  },
77
79
  "overrides": []
78
80
  }
@@ -98,7 +100,8 @@
98
100
  ],
99
101
  "fieldConfig": {
100
102
  "defaults": {
101
- "unit": "short"
103
+ "unit": "short",
104
+ "noValue": "No data yet — run: npx toad-eye demo"
102
105
  },
103
106
  "overrides": []
104
107
  }
@@ -118,13 +121,14 @@
118
121
  },
119
122
  "targets": [
120
123
  {
121
- "expr": "count(count by (gen_ai_agent_tool_name) (gen_ai_agent_tool_usage_total))",
124
+ "expr": "count(count by (gen_ai_tool_name) (gen_ai_agent_tool_usage_total))",
122
125
  "refId": "A"
123
126
  }
124
127
  ],
125
128
  "fieldConfig": {
126
129
  "defaults": {
127
- "unit": "short"
130
+ "unit": "short",
131
+ "noValue": "No data yet — run: npx toad-eye demo"
128
132
  },
129
133
  "overrides": []
130
134
  }
@@ -157,6 +161,11 @@
157
161
  "values": ["value", "percent"]
158
162
  },
159
163
  "pieType": "donut"
164
+ },
165
+ "fieldConfig": {
166
+ "defaults": {
167
+ "noValue": "No data yet — run: npx toad-eye demo"
168
+ }
160
169
  }
161
170
  },
162
171
  {
@@ -175,11 +184,16 @@
175
184
  },
176
185
  "targets": [
177
186
  {
178
- "expr": "sort_desc(sum by (gen_ai_agent_tool_name) (gen_ai_agent_tool_usage_total))",
179
- "legendFormat": "{{gen_ai_agent_tool_name}}",
187
+ "expr": "sort_desc(sum by (gen_ai_tool_name) (gen_ai_agent_tool_usage_total))",
188
+ "legendFormat": "{{gen_ai_tool_name}}",
180
189
  "refId": "A"
181
190
  }
182
- ]
191
+ ],
192
+ "fieldConfig": {
193
+ "defaults": {
194
+ "noValue": "No data yet — run: npx toad-eye demo"
195
+ }
196
+ }
183
197
  },
184
198
  {
185
199
  "title": "Steps per Query Over Time",
@@ -211,7 +225,8 @@
211
225
  "unit": "short",
212
226
  "custom": {
213
227
  "fillOpacity": 10
214
- }
228
+ },
229
+ "noValue": "No data yet — run: npx toad-eye demo"
215
230
  },
216
231
  "overrides": []
217
232
  }
@@ -231,8 +246,8 @@
231
246
  },
232
247
  "targets": [
233
248
  {
234
- "expr": "sum by (gen_ai_agent_tool_name) (rate(gen_ai_agent_tool_usage_total[5m]))",
235
- "legendFormat": "{{gen_ai_agent_tool_name}}",
249
+ "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_agent_tool_usage_total[5m]))",
250
+ "legendFormat": "{{gen_ai_tool_name}}",
236
251
  "refId": "A"
237
252
  }
238
253
  ],
@@ -244,7 +259,8 @@
244
259
  "stacking": {
245
260
  "mode": "normal"
246
261
  }
247
- }
262
+ },
263
+ "noValue": "No data yet — run: npx toad-eye demo"
248
264
  },
249
265
  "overrides": []
250
266
  }
@@ -274,7 +290,8 @@
274
290
  "defaults": {
275
291
  "custom": {
276
292
  "fillOpacity": 80
277
- }
293
+ },
294
+ "noValue": "No data yet — run: npx toad-eye demo"
278
295
  },
279
296
  "overrides": []
280
297
  }
@@ -283,45 +300,13 @@
283
300
  "schemaVersion": 39,
284
301
  "tags": ["toad-eye", "agent"],
285
302
  "templating": {
286
- "list": [
287
- {
288
- "name": "service",
289
- "type": "query",
290
- "datasource": {
291
- "type": "prometheus",
292
- "uid": "prometheus"
293
- },
294
- "query": "label_values(gen_ai_client_requests_total, job)",
295
- "includeAll": true,
296
- "allValue": ".*",
297
- "current": {
298
- "text": "All",
299
- "value": "$__all"
300
- },
301
- "multi": true
302
- },
303
- {
304
- "name": "tool",
305
- "type": "query",
306
- "datasource": {
307
- "type": "prometheus",
308
- "uid": "prometheus"
309
- },
310
- "query": "label_values(gen_ai_agent_tool_usage_total, gen_ai_agent_tool_name)",
311
- "includeAll": true,
312
- "multi": true,
313
- "current": {
314
- "text": "All",
315
- "value": "$__all"
316
- },
317
- "regex": ""
318
- }
319
- ]
303
+ "list": []
320
304
  },
321
305
  "time": {
322
306
  "from": "now-6h",
323
307
  "to": "now"
324
308
  },
309
+ "refresh": "30s",
325
310
  "timepicker": {},
326
311
  "timezone": "utc",
327
312
  "title": "toad-eye / Agent Workflow",
@@ -45,7 +45,8 @@
45
45
  "value": 500
46
46
  }
47
47
  ]
48
- }
48
+ },
49
+ "noValue": "No data yet — run: npx toad-eye demo"
49
50
  },
50
51
  "overrides": []
51
52
  }
@@ -87,7 +88,8 @@
87
88
  "value": 50
88
89
  }
89
90
  ]
90
- }
91
+ },
92
+ "noValue": "No data yet — run: npx toad-eye demo"
91
93
  },
92
94
  "overrides": []
93
95
  }
@@ -129,7 +131,8 @@
129
131
  "value": 1000
130
132
  }
131
133
  ]
132
- }
134
+ },
135
+ "noValue": "No data yet — run: npx toad-eye demo"
133
136
  },
134
137
  "overrides": []
135
138
  }
@@ -164,7 +167,8 @@
164
167
  "stacking": {
165
168
  "mode": "normal"
166
169
  }
167
- }
170
+ },
171
+ "noValue": "No data yet — run: npx toad-eye demo"
168
172
  },
169
173
  "overrides": []
170
174
  }
@@ -199,7 +203,8 @@
199
203
  "stacking": {
200
204
  "mode": "normal"
201
205
  }
202
- }
206
+ },
207
+ "noValue": "No data yet — run: npx toad-eye demo"
203
208
  },
204
209
  "overrides": []
205
210
  }
@@ -231,7 +236,8 @@
231
236
  "drawStyle": "line",
232
237
  "fillOpacity": 15,
233
238
  "lineWidth": 2
234
- }
239
+ },
240
+ "noValue": "No data yet — run: npx toad-eye demo"
235
241
  },
236
242
  "overrides": []
237
243
  }
@@ -263,7 +269,8 @@
263
269
  "drawStyle": "line",
264
270
  "fillOpacity": 15,
265
271
  "lineWidth": 2
266
- }
272
+ },
273
+ "noValue": "No data yet — run: npx toad-eye demo"
267
274
  },
268
275
  "overrides": []
269
276
  }
@@ -45,7 +45,8 @@
45
45
  "value": 100
46
46
  }
47
47
  ]
48
- }
48
+ },
49
+ "noValue": "No data yet — run: npx toad-eye demo"
49
50
  },
50
51
  "overrides": []
51
52
  }
@@ -87,7 +88,8 @@
87
88
  "value": 20
88
89
  }
89
90
  ]
90
- }
91
+ },
92
+ "noValue": "No data yet — run: npx toad-eye demo"
91
93
  },
92
94
  "overrides": []
93
95
  }
@@ -129,7 +131,8 @@
129
131
  "value": 50
130
132
  }
131
133
  ]
132
- }
134
+ },
135
+ "noValue": "No data yet — run: npx toad-eye demo"
133
136
  },
134
137
  "overrides": []
135
138
  }
@@ -161,7 +164,8 @@
161
164
  "drawStyle": "line",
162
165
  "fillOpacity": 15,
163
166
  "lineWidth": 2
164
- }
167
+ },
168
+ "noValue": "No data yet — run: npx toad-eye demo"
165
169
  },
166
170
  "overrides": []
167
171
  }
@@ -193,7 +197,8 @@
193
197
  "drawStyle": "line",
194
198
  "fillOpacity": 15,
195
199
  "lineWidth": 2
196
- }
200
+ },
201
+ "noValue": "No data yet — run: npx toad-eye demo"
197
202
  },
198
203
  "overrides": []
199
204
  }
@@ -233,7 +238,8 @@
233
238
  "stacking": {
234
239
  "mode": "normal"
235
240
  }
236
- }
241
+ },
242
+ "noValue": "No data yet — run: npx toad-eye demo"
237
243
  },
238
244
  "overrides": []
239
245
  }
@@ -45,7 +45,8 @@
45
45
  "value": 500
46
46
  }
47
47
  ]
48
- }
48
+ },
49
+ "noValue": "No data yet — run: npx toad-eye demo"
49
50
  },
50
51
  "overrides": []
51
52
  }
@@ -88,7 +89,8 @@
88
89
  "value": 1000
89
90
  }
90
91
  ]
91
- }
92
+ },
93
+ "noValue": "No data yet — run: npx toad-eye demo"
92
94
  },
93
95
  "overrides": []
94
96
  }
@@ -114,7 +116,8 @@
114
116
  ],
115
117
  "fieldConfig": {
116
118
  "defaults": {
117
- "unit": "short"
119
+ "unit": "short",
120
+ "noValue": "No data yet — run: npx toad-eye demo"
118
121
  },
119
122
  "overrides": []
120
123
  }
@@ -141,7 +144,8 @@
141
144
  "fieldConfig": {
142
145
  "defaults": {
143
146
  "unit": "currencyUSD",
144
- "decimals": 4
147
+ "decimals": 4,
148
+ "noValue": "No data yet — run: npx toad-eye demo"
145
149
  },
146
150
  "overrides": []
147
151
  }
@@ -173,6 +177,11 @@
173
177
  "values": ["value", "percent"]
174
178
  },
175
179
  "pieType": "donut"
180
+ },
181
+ "fieldConfig": {
182
+ "defaults": {
183
+ "noValue": "No data yet — run: npx toad-eye demo"
184
+ }
176
185
  }
177
186
  },
178
187
  {
@@ -197,6 +206,11 @@
197
206
  ],
198
207
  "options": {
199
208
  "stacking": "normal"
209
+ },
210
+ "fieldConfig": {
211
+ "defaults": {
212
+ "noValue": "No data yet — run: npx toad-eye demo"
213
+ }
200
214
  }
201
215
  },
202
216
  {
@@ -230,7 +244,12 @@
230
244
  }
231
245
  }
232
246
  }
233
- ]
247
+ ],
248
+ "fieldConfig": {
249
+ "defaults": {
250
+ "noValue": "No data yet — run: npx toad-eye demo"
251
+ }
252
+ }
234
253
  },
235
254
  {
236
255
  "title": "Top 10 Users by Cost",
@@ -263,7 +282,12 @@
263
282
  }
264
283
  }
265
284
  }
266
- ]
285
+ ],
286
+ "fieldConfig": {
287
+ "defaults": {
288
+ "noValue": "No data yet — run: npx toad-eye demo"
289
+ }
290
+ }
267
291
  },
268
292
  {
269
293
  "title": "Daily Cost Trend (by Team)",
@@ -298,7 +322,8 @@
298
322
  "stacking": {
299
323
  "mode": "normal"
300
324
  }
301
- }
325
+ },
326
+ "noValue": "No data yet — run: npx toad-eye demo"
302
327
  },
303
328
  "overrides": []
304
329
  }
@@ -342,7 +367,12 @@
342
367
  }
343
368
  }
344
369
  }
345
- ]
370
+ ],
371
+ "fieldConfig": {
372
+ "defaults": {
373
+ "noValue": "No data yet — run: npx toad-eye demo"
374
+ }
375
+ }
346
376
  }
347
377
  ],
348
378
  "schemaVersion": 39,
@@ -419,6 +449,7 @@
419
449
  "from": "now-7d",
420
450
  "to": "now"
421
451
  },
452
+ "refresh": "1m",
422
453
  "timepicker": {},
423
454
  "timezone": "utc",
424
455
  "title": "toad-eye / FinOps Attribution",
@@ -45,7 +45,8 @@
45
45
  "drawStyle": "line",
46
46
  "fillOpacity": 15,
47
47
  "lineWidth": 2
48
- }
48
+ },
49
+ "noValue": "No data yet — run: npx toad-eye demo"
49
50
  },
50
51
  "overrides": []
51
52
  }
@@ -76,7 +77,8 @@
76
77
  "unit": "ms",
77
78
  "custom": {
78
79
  "fillOpacity": 50
79
- }
80
+ },
81
+ "noValue": "No data yet — run: npx toad-eye demo"
80
82
  },
81
83
  "overrides": []
82
84
  }
@@ -108,7 +110,8 @@
108
110
  "drawStyle": "line",
109
111
  "fillOpacity": 15,
110
112
  "lineWidth": 2
111
- }
113
+ },
114
+ "noValue": "No data yet — run: npx toad-eye demo"
112
115
  },
113
116
  "overrides": []
114
117
  }
@@ -140,7 +143,8 @@
140
143
  "drawStyle": "line",
141
144
  "fillOpacity": 15,
142
145
  "lineWidth": 2
143
- }
146
+ },
147
+ "noValue": "No data yet — run: npx toad-eye demo"
144
148
  },
145
149
  "overrides": []
146
150
  }
@@ -45,7 +45,8 @@
45
45
  "value": 10000
46
46
  }
47
47
  ]
48
- }
48
+ },
49
+ "noValue": "No data yet — run: npx toad-eye demo"
49
50
  },
50
51
  "overrides": []
51
52
  }
@@ -87,7 +88,8 @@
87
88
  "value": 20
88
89
  }
89
90
  ]
90
- }
91
+ },
92
+ "noValue": "No data yet — run: npx toad-eye demo"
91
93
  },
92
94
  "overrides": []
93
95
  }
@@ -129,7 +131,8 @@
129
131
  "value": 5000
130
132
  }
131
133
  ]
132
- }
134
+ },
135
+ "noValue": "No data yet — run: npx toad-eye demo"
133
136
  },
134
137
  "overrides": []
135
138
  }
@@ -171,7 +174,8 @@
171
174
  "value": 100
172
175
  }
173
176
  ]
174
- }
177
+ },
178
+ "noValue": "No data yet — run: npx toad-eye demo"
175
179
  },
176
180
  "overrides": []
177
181
  }
@@ -203,7 +207,8 @@
203
207
  "drawStyle": "line",
204
208
  "fillOpacity": 15,
205
209
  "lineWidth": 2
206
- }
210
+ },
211
+ "noValue": "No data yet — run: npx toad-eye demo"
207
212
  },
208
213
  "overrides": []
209
214
  }
@@ -238,7 +243,8 @@
238
243
  },
239
244
  "color": {
240
245
  "mode": "palette-classic"
241
- }
246
+ },
247
+ "noValue": "No data yet — run: npx toad-eye demo"
242
248
  },
243
249
  "overrides": []
244
250
  }
@@ -275,7 +281,8 @@
275
281
  "drawStyle": "line",
276
282
  "fillOpacity": 15,
277
283
  "lineWidth": 2
278
- }
284
+ },
285
+ "noValue": "No data yet — run: npx toad-eye demo"
279
286
  },
280
287
  "overrides": []
281
288
  }
@@ -307,7 +314,8 @@
307
314
  "drawStyle": "bars",
308
315
  "fillOpacity": 50,
309
316
  "lineWidth": 1
310
- }
317
+ },
318
+ "noValue": "No data yet — run: npx toad-eye demo"
311
319
  },
312
320
  "overrides": []
313
321
  }
@@ -349,7 +357,8 @@
349
357
  "value": 1000000
350
358
  }
351
359
  ]
352
- }
360
+ },
361
+ "noValue": "No data yet — run: npx toad-eye demo"
353
362
  },
354
363
  "overrides": []
355
364
  }
@@ -391,7 +400,8 @@
391
400
  "value": 10000
392
401
  }
393
402
  ]
394
- }
403
+ },
404
+ "noValue": "No data yet — run: npx toad-eye demo"
395
405
  },
396
406
  "overrides": []
397
407
  }
@@ -433,7 +443,8 @@
433
443
  "value": 100
434
444
  }
435
445
  ]
436
- }
446
+ },
447
+ "noValue": "No data yet — run: npx toad-eye demo"
437
448
  },
438
449
  "overrides": []
439
450
  }