yamchart 0.8.6 → 0.8.8
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/{advisor-54JBE2EV.js → advisor-IJBW56F5.js} +3 -3
- package/dist/agent-2DFNL2UB.js +8 -0
- package/dist/{chunk-GLCEDWGH.js → chunk-232AMQ5T.js} +2 -2
- package/dist/{chunk-NCPWAWIM.js → chunk-34ZVFILD.js} +3 -3
- package/dist/chunk-77U26A7F.js +677 -0
- package/dist/chunk-77U26A7F.js.map +1 -0
- package/dist/{chunk-YMQ4PWVJ.js → chunk-B5ZLCKNF.js} +2 -2
- package/dist/{chunk-C7A7TKSY.js → chunk-D3ELUYYE.js} +26 -3
- package/dist/chunk-D3ELUYYE.js.map +1 -0
- package/dist/{connection-utils-MXEF6X7K.js → connection-utils-ZLSV5OLQ.js} +3 -3
- package/dist/{describe-XKLBZEWG.js → describe-VO4CEYL2.js} +4 -4
- package/dist/{dev-Z2R2DBWO.js → dev-JUA73B6D.js} +534 -46
- package/dist/dev-JUA73B6D.js.map +1 -0
- package/dist/{dist-LJR7TAW4.js → dist-PINRLZVT.js} +4 -2
- package/dist/index.js +20 -20
- package/dist/public/assets/{EventManagement-D4H5tTvO.js → EventManagement-DQY1Sic0.js} +2 -2
- package/dist/public/assets/ExplorePage-C9M-fQ3Y.js +1 -0
- package/dist/public/assets/{LoginPage-DMhioiI7.js → LoginPage-XYLwfbfw.js} +1 -1
- package/dist/public/assets/PublicViewer-CZJYS0wF.js +1 -0
- package/dist/public/assets/{SetupWizard-CZTQ6YDE.js → SetupWizard-fle7FC4b.js} +1 -1
- package/dist/public/assets/{ShareManagement-BFm5OVCy.js → ShareManagement-b3j4jzn3.js} +1 -1
- package/dist/public/assets/{UserManagement-BbbEGHYl.js → UserManagement-DwZ-AaqI.js} +1 -1
- package/dist/public/assets/{index-B_fusLA_.css → index-CRcgti3B.css} +1 -1
- package/dist/public/assets/index-m_Jm3sB1.js +188 -0
- package/dist/public/assets/{index.es-D6Nmj80H.js → index.es-Bd2YVqtj.js} +1 -1
- package/dist/public/assets/{jspdf.es.min-Cm41KBzd.js → jspdf.es.min-CpRfbJ_H.js} +3 -3
- package/dist/public/index.html +2 -2
- package/dist/{query-MXMFI5TB.js → query-PXJMSDKR.js} +3 -3
- package/dist/{sample-HDPYNAKS.js → sample-M24H3M73.js} +3 -3
- package/dist/{search-6CPEPJTI.js → search-UCJS7X5D.js} +4 -4
- package/dist/{source-resolver-PCASPRSD.js → source-resolver-RXNB7A64.js} +4 -4
- package/dist/source-resolver-RXNB7A64.js.map +1 -0
- package/dist/{sync-warehouse-XC7YYZKC.js → sync-warehouse-S75DWVTG.js} +3 -3
- package/dist/{tables-26PNVZIC.js → tables-W3M3JDJO.js} +4 -4
- package/dist/templates/default/docs/yamchart-reference.md +56 -0
- package/dist/templates/default/yamchart.yaml +3 -0
- package/dist/{test-APA44AIF.js → test-67AXD5PI.js} +3 -3
- package/package.json +4 -3
- package/dist/chunk-C7A7TKSY.js.map +0 -1
- package/dist/dev-Z2R2DBWO.js.map +0 -1
- package/dist/public/assets/PublicViewer-B9JKXczX.js +0 -1
- package/dist/public/assets/index-h1PV1M6v.js +0 -187
- /package/dist/{advisor-54JBE2EV.js.map → advisor-IJBW56F5.js.map} +0 -0
- /package/dist/{connection-utils-MXEF6X7K.js.map → agent-2DFNL2UB.js.map} +0 -0
- /package/dist/{chunk-GLCEDWGH.js.map → chunk-232AMQ5T.js.map} +0 -0
- /package/dist/{chunk-NCPWAWIM.js.map → chunk-34ZVFILD.js.map} +0 -0
- /package/dist/{chunk-YMQ4PWVJ.js.map → chunk-B5ZLCKNF.js.map} +0 -0
- /package/dist/{dist-LJR7TAW4.js.map → connection-utils-ZLSV5OLQ.js.map} +0 -0
- /package/dist/{describe-XKLBZEWG.js.map → describe-VO4CEYL2.js.map} +0 -0
- /package/dist/{source-resolver-PCASPRSD.js.map → dist-PINRLZVT.js.map} +0 -0
- /package/dist/{query-MXMFI5TB.js.map → query-PXJMSDKR.js.map} +0 -0
- /package/dist/{sample-HDPYNAKS.js.map → sample-M24H3M73.js.map} +0 -0
- /package/dist/{search-6CPEPJTI.js.map → search-UCJS7X5D.js.map} +0 -0
- /package/dist/{sync-warehouse-XC7YYZKC.js.map → sync-warehouse-S75DWVTG.js.map} +0 -0
- /package/dist/{tables-26PNVZIC.js.map → tables-W3M3JDJO.js.map} +0 -0
- /package/dist/{test-APA44AIF.js.map → test-67AXD5PI.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadEnvFile,
|
|
3
3
|
validateProject
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-232AMQ5T.js";
|
|
5
5
|
import {
|
|
6
6
|
box,
|
|
7
7
|
detail,
|
|
@@ -23,7 +23,11 @@ import {
|
|
|
23
23
|
SemanticQuerySchema,
|
|
24
24
|
deepMerge,
|
|
25
25
|
resolveProjectConfig
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-D3ELUYYE.js";
|
|
27
|
+
import {
|
|
28
|
+
StreamingChatAgent,
|
|
29
|
+
filterCatalogEntries
|
|
30
|
+
} from "./chunk-77U26A7F.js";
|
|
27
31
|
import {
|
|
28
32
|
AuthDatabase,
|
|
29
33
|
generateSessionToken,
|
|
@@ -63,7 +67,7 @@ import {
|
|
|
63
67
|
import "./chunk-DGUM43GV.js";
|
|
64
68
|
|
|
65
69
|
// src/commands/dev.ts
|
|
66
|
-
import { resolve } from "path";
|
|
70
|
+
import { resolve as resolve2 } from "path";
|
|
67
71
|
import { homedir } from "os";
|
|
68
72
|
|
|
69
73
|
// ../server/dist/server.js
|
|
@@ -76,6 +80,257 @@ import { readFile, readdir, access } from "fs/promises";
|
|
|
76
80
|
import { join, extname, relative, dirname } from "path";
|
|
77
81
|
import { parse as parseYaml } from "yaml";
|
|
78
82
|
import { watch } from "chokidar";
|
|
83
|
+
|
|
84
|
+
// ../../packages/chat/dist/registry.js
|
|
85
|
+
import { parse } from "yaml";
|
|
86
|
+
|
|
87
|
+
// ../../packages/chat/dist/agents/dashboard-analyst.js
|
|
88
|
+
var DASHBOARD_ANALYST = {
|
|
89
|
+
name: "dashboard-analyst",
|
|
90
|
+
title: "Dashboard Analyst",
|
|
91
|
+
description: "Summarizes dashboards, explains trends, answers data questions, and can apply filters to the dashboard.",
|
|
92
|
+
systemPrompt: `You are an AI dashboard analyst for a business intelligence platform.
|
|
93
|
+
|
|
94
|
+
Your job is to help users understand their data by:
|
|
95
|
+
- Summarizing what a dashboard or chart shows
|
|
96
|
+
- Explaining trends, outliers, and patterns in the data
|
|
97
|
+
- Answering questions about metrics and KPIs
|
|
98
|
+
- Suggesting and applying filters to explore data
|
|
99
|
+
- Running ad-hoc SQL to explore data beyond existing charts
|
|
100
|
+
|
|
101
|
+
## Rules
|
|
102
|
+
- Be concise. Dashboard users want quick answers, not essays.
|
|
103
|
+
- Use numbers and percentages when discussing data.
|
|
104
|
+
- When you query data, summarize the key findings \u2014 don't dump raw rows.
|
|
105
|
+
- If asked about a trend, explain the direction, magnitude, and possible causes.
|
|
106
|
+
- When suggesting filters, explain what you expect to see.
|
|
107
|
+
- Use the apply_filter tool when the user asks to filter or drill down.
|
|
108
|
+
- If the existing charts don't have the data needed, use run_sql to query the database directly.
|
|
109
|
+
- Use call_agent to delegate to specialized agents when you need expertise you don't have.
|
|
110
|
+
- Use suggest_actions to offer follow-up exploration or save options after answering.
|
|
111
|
+
- If you don't have enough data to answer, say so and suggest what to query.
|
|
112
|
+
|
|
113
|
+
## Data Visualization in Responses
|
|
114
|
+
When you have tabular data to share, use these markdown code fences:
|
|
115
|
+
|
|
116
|
+
For charts (line, bar, pie, scatter):
|
|
117
|
+
\`\`\`chart
|
|
118
|
+
{"type":"line","data":[{"date":"2025-01-01","value":100},...],"x":"date","y":"value","title":"Optional Title"}
|
|
119
|
+
\`\`\`
|
|
120
|
+
|
|
121
|
+
For data tables:
|
|
122
|
+
\`\`\`data
|
|
123
|
+
{"columns":[{"name":"date","type":"date"},{"name":"value","type":"number"}],"rows":[{"date":"2025-01-01","value":100},...]}
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
Choose charts for trends and comparisons, tables for detailed breakdowns. Keep data concise \u2014 summarize large result sets.`,
|
|
127
|
+
tools: ["query_model", "get_chart_config", "get_dashboard_summary", "apply_filter", "compare_periods", "run_sql", "call_agent", "get_catalog_tables", "suggest_actions", "save_model", "save_chart", "add_to_dashboard"],
|
|
128
|
+
builtIn: true
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// ../../packages/chat/dist/agents/sql-explorer.js
|
|
132
|
+
var SQL_EXPLORER = {
|
|
133
|
+
name: "sql-explorer",
|
|
134
|
+
title: "SQL Explorer",
|
|
135
|
+
description: "Runs ad-hoc SQL queries against the connected database for deep data exploration and period comparisons.",
|
|
136
|
+
systemPrompt: `You are a SQL expert helping users explore their data warehouse.
|
|
137
|
+
|
|
138
|
+
Your job is to:
|
|
139
|
+
- Write and execute SQL queries to answer user questions
|
|
140
|
+
- Compare data across time periods
|
|
141
|
+
- Find specific records or aggregations
|
|
142
|
+
- Explain query results clearly
|
|
143
|
+
|
|
144
|
+
## Rules
|
|
145
|
+
- Always LIMIT your queries (default: 50 rows) to avoid large payloads.
|
|
146
|
+
- Use clear column aliases so results are readable.
|
|
147
|
+
- When comparing periods, use the compare_periods tool for models, or write explicit SQL for ad-hoc comparisons.
|
|
148
|
+
- Explain what your query does before showing results.
|
|
149
|
+
- If a query fails, explain the error and try a corrected version.
|
|
150
|
+
- Never run destructive queries (INSERT, UPDATE, DELETE, DROP, etc.).
|
|
151
|
+
|
|
152
|
+
## Data Visualization in Responses
|
|
153
|
+
When you have tabular data to share, use these markdown code fences:
|
|
154
|
+
|
|
155
|
+
For charts (line, bar, pie, scatter):
|
|
156
|
+
\`\`\`chart
|
|
157
|
+
{"type":"line","data":[{"date":"2025-01-01","value":100},...],"x":"date","y":"value","title":"Optional Title"}
|
|
158
|
+
\`\`\`
|
|
159
|
+
|
|
160
|
+
For data tables:
|
|
161
|
+
\`\`\`data
|
|
162
|
+
{"columns":[{"name":"date","type":"date"},{"name":"value","type":"number"}],"rows":[{"date":"2025-01-01","value":100},...]}
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
Choose charts for trends and comparisons, tables for detailed breakdowns. Keep data concise \u2014 summarize large result sets.`,
|
|
166
|
+
tools: ["query_model", "run_sql", "compare_periods", "get_chart_config", "call_agent", "get_catalog_tables", "suggest_actions", "save_model", "save_chart"],
|
|
167
|
+
builtIn: true
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// ../../packages/chat/dist/agents/data-explorer.js
|
|
171
|
+
var DATA_EXPLORER = {
|
|
172
|
+
name: "data-explorer",
|
|
173
|
+
title: "Data Explorer",
|
|
174
|
+
description: "Open-ended data exploration, visualization, and dashboard building.",
|
|
175
|
+
systemPrompt: `You are an AI data explorer for a business intelligence platform.
|
|
176
|
+
|
|
177
|
+
Your job is to help users explore their data warehouse, build visualizations, and create dashboards \u2014 starting from curiosity and ending with saved, reusable charts.
|
|
178
|
+
|
|
179
|
+
## Discovery First
|
|
180
|
+
- Always start with get_catalog_tables to understand what data is available before writing SQL.
|
|
181
|
+
- Prefer querying named models (query_model) over raw SQL when a model already exists.
|
|
182
|
+
- When no model exists, use run_sql to explore \u2014 then offer to save the query as a model.
|
|
183
|
+
|
|
184
|
+
## Rules
|
|
185
|
+
- All SQL must be read-only (SELECT only). Never run INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, or CREATE.
|
|
186
|
+
- Always LIMIT queries to 50 rows by default. Use LIMIT explicitly.
|
|
187
|
+
- Use clear column aliases so results are readable.
|
|
188
|
+
- When a query fails, explain the error and try a corrected version.
|
|
189
|
+
- Explain what you're querying and why before showing results.
|
|
190
|
+
|
|
191
|
+
## Proactive Visualization
|
|
192
|
+
After retrieving data, always visualize it \u2014 don't just dump raw rows. Choose the right form:
|
|
193
|
+
- Trends over time \u2192 line chart
|
|
194
|
+
- Comparisons across categories \u2192 bar chart
|
|
195
|
+
- Part-to-whole \u2192 pie chart
|
|
196
|
+
- Single key metric \u2192 show as bold text or KPI
|
|
197
|
+
- Detailed breakdowns \u2192 data table
|
|
198
|
+
|
|
199
|
+
For charts (line, bar, pie, scatter):
|
|
200
|
+
\`\`\`chart
|
|
201
|
+
{"type":"line","data":[{"date":"2025-01-01","value":100},...],"x":"date","y":"value","title":"Optional Title"}
|
|
202
|
+
\`\`\`
|
|
203
|
+
|
|
204
|
+
For data tables:
|
|
205
|
+
\`\`\`data
|
|
206
|
+
{"columns":[{"name":"date","type":"date"},{"name":"value","type":"number"}],"rows":[{"date":"2025-01-01","value":100},...]}
|
|
207
|
+
\`\`\`
|
|
208
|
+
|
|
209
|
+
Keep visualizations concise \u2014 summarize large result sets rather than showing every row.
|
|
210
|
+
|
|
211
|
+
## Saving Work
|
|
212
|
+
When a user wants to keep a query or chart:
|
|
213
|
+
1. Use save_model to create a reusable SQL model file.
|
|
214
|
+
2. Use save_chart to create a chart YAML referencing that model.
|
|
215
|
+
3. Use create_dashboard to assemble saved charts into a new dashboard.
|
|
216
|
+
4. After saving, use suggest_actions to offer navigation or further exploration.
|
|
217
|
+
|
|
218
|
+
## Suggesting Next Steps
|
|
219
|
+
Always use suggest_actions after answering a question to offer natural follow-up options:
|
|
220
|
+
- Explore related dimensions or time periods
|
|
221
|
+
- Save the current query as a model
|
|
222
|
+
- Create a chart from the data
|
|
223
|
+
- Add the chart to a dashboard
|
|
224
|
+
|
|
225
|
+
## Collaboration
|
|
226
|
+
Use call_agent to delegate to specialized agents when needed:
|
|
227
|
+
- Dashboard Analyst for questions about existing dashboards
|
|
228
|
+
- SQL Explorer for complex multi-step SQL investigations`,
|
|
229
|
+
tools: ["run_sql", "query_model", "get_catalog_tables", "compare_periods", "save_model", "save_chart", "create_dashboard", "suggest_actions", "call_agent"],
|
|
230
|
+
builtIn: true
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// ../../packages/chat/dist/registry.js
|
|
234
|
+
var AgentRegistry = class {
|
|
235
|
+
agents = /* @__PURE__ */ new Map();
|
|
236
|
+
constructor() {
|
|
237
|
+
this.agents.set(DASHBOARD_ANALYST.name, DASHBOARD_ANALYST);
|
|
238
|
+
this.agents.set(SQL_EXPLORER.name, SQL_EXPLORER);
|
|
239
|
+
this.agents.set(DATA_EXPLORER.name, DATA_EXPLORER);
|
|
240
|
+
}
|
|
241
|
+
getAgent(name) {
|
|
242
|
+
return this.agents.get(name);
|
|
243
|
+
}
|
|
244
|
+
listAgents() {
|
|
245
|
+
return Array.from(this.agents.values());
|
|
246
|
+
}
|
|
247
|
+
registerAgent(config) {
|
|
248
|
+
this.agents.set(config.name, config);
|
|
249
|
+
}
|
|
250
|
+
loadFromYaml(yamlContent, filePath, onWarning) {
|
|
251
|
+
try {
|
|
252
|
+
const raw = parse(yamlContent);
|
|
253
|
+
if (!raw || typeof raw !== "object") {
|
|
254
|
+
onWarning?.(`Skipping ${filePath}: not a valid YAML object`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (!raw.name || typeof raw.name !== "string") {
|
|
258
|
+
onWarning?.(`Skipping ${filePath}: missing required "name" field`);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (!raw.description || typeof raw.description !== "string") {
|
|
262
|
+
onWarning?.(`Skipping ${filePath}: missing required "description" field`);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (!raw.system_prompt || typeof raw.system_prompt !== "string") {
|
|
266
|
+
onWarning?.(`Skipping ${filePath}: missing required "system_prompt" field`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const config = {
|
|
270
|
+
name: raw.name,
|
|
271
|
+
title: raw.title ?? raw.name,
|
|
272
|
+
description: raw.description,
|
|
273
|
+
systemPrompt: raw.system_prompt,
|
|
274
|
+
tools: Array.isArray(raw.tools) ? raw.tools.filter((t) => typeof t === "string") : [],
|
|
275
|
+
builtIn: false,
|
|
276
|
+
model: typeof raw.model === "string" ? raw.model : void 0,
|
|
277
|
+
models: Array.isArray(raw.models) ? raw.models.filter((m) => typeof m === "string") : void 0
|
|
278
|
+
};
|
|
279
|
+
this.agents.set(config.name, config);
|
|
280
|
+
} catch (err) {
|
|
281
|
+
onWarning?.(`Skipping ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
clearProjectAgents() {
|
|
285
|
+
for (const [name, config] of this.agents) {
|
|
286
|
+
if (!config.builtIn)
|
|
287
|
+
this.agents.delete(name);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// ../../packages/chat/dist/router.js
|
|
293
|
+
var SQL_PATTERNS = [
|
|
294
|
+
/\bselect\b.*\bfrom\b/i,
|
|
295
|
+
/\brun\s+(a\s+)?query\b/i,
|
|
296
|
+
/\bwrite\s+(a\s+)?query\b/i,
|
|
297
|
+
/\bshow\s+(me\s+)?the\s+sql\b/i,
|
|
298
|
+
/\bexecute\s+sql\b/i,
|
|
299
|
+
/\bjoin\b.*\btable/i
|
|
300
|
+
];
|
|
301
|
+
var DEFAULT_AGENT = "dashboard-analyst";
|
|
302
|
+
var RouterAgent = class {
|
|
303
|
+
registry;
|
|
304
|
+
constructor(registry) {
|
|
305
|
+
this.registry = registry;
|
|
306
|
+
}
|
|
307
|
+
selectAgent(message, context, explicitAgent) {
|
|
308
|
+
if (explicitAgent) {
|
|
309
|
+
const agent = this.registry.getAgent(explicitAgent);
|
|
310
|
+
if (agent)
|
|
311
|
+
return agent;
|
|
312
|
+
}
|
|
313
|
+
if (context?.type === "explore") {
|
|
314
|
+
return this.registry.getAgent("data-explorer") || this.registry.getAgent(DEFAULT_AGENT);
|
|
315
|
+
}
|
|
316
|
+
if (SQL_PATTERNS.some((pattern) => pattern.test(message))) {
|
|
317
|
+
const sqlExplorer = this.registry.getAgent("sql-explorer");
|
|
318
|
+
if (sqlExplorer)
|
|
319
|
+
return sqlExplorer;
|
|
320
|
+
}
|
|
321
|
+
return this.registry.getAgent(DEFAULT_AGENT);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// ../../packages/chat/dist/stream.js
|
|
326
|
+
function formatSSEEvent(event) {
|
|
327
|
+
return `event: ${event.type}
|
|
328
|
+
data: ${JSON.stringify(event.data)}
|
|
329
|
+
|
|
330
|
+
`;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ../server/dist/services/config-loader.js
|
|
79
334
|
var ConfigLoader = class {
|
|
80
335
|
projectDir;
|
|
81
336
|
project = null;
|
|
@@ -92,6 +347,7 @@ var ConfigLoader = class {
|
|
|
92
347
|
validationErrors = /* @__PURE__ */ new Map();
|
|
93
348
|
watcher = null;
|
|
94
349
|
onChangeCallbacks = [];
|
|
350
|
+
agentRegistry = new AgentRegistry();
|
|
95
351
|
env;
|
|
96
352
|
constructor(projectDir, env) {
|
|
97
353
|
this.projectDir = projectDir;
|
|
@@ -116,6 +372,7 @@ var ConfigLoader = class {
|
|
|
116
372
|
await this.loadDashboards();
|
|
117
373
|
await this.loadSchedules();
|
|
118
374
|
await this.loadEvents();
|
|
375
|
+
await this.loadAgents();
|
|
119
376
|
}
|
|
120
377
|
async loadProject() {
|
|
121
378
|
const projectPath = join(this.projectDir, "yamchart.yaml");
|
|
@@ -321,6 +578,20 @@ var ConfigLoader = class {
|
|
|
321
578
|
console.warn(`Invalid events.yaml: ${result.error.message}`);
|
|
322
579
|
}
|
|
323
580
|
}
|
|
581
|
+
async loadAgents() {
|
|
582
|
+
const agentsDir = join(this.projectDir, "agents");
|
|
583
|
+
this.agentRegistry.clearProjectAgents();
|
|
584
|
+
try {
|
|
585
|
+
const files = await readdir(agentsDir);
|
|
586
|
+
for (const file of files.filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"))) {
|
|
587
|
+
const content = await readFile(join(agentsDir, file), "utf-8");
|
|
588
|
+
this.agentRegistry.loadFromYaml(content, `agents/${file}`, (msg) => {
|
|
589
|
+
console.warn(msg);
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
} catch {
|
|
593
|
+
}
|
|
594
|
+
}
|
|
324
595
|
startWatching() {
|
|
325
596
|
if (this.watcher)
|
|
326
597
|
return;
|
|
@@ -332,7 +603,8 @@ var ConfigLoader = class {
|
|
|
332
603
|
join(this.projectDir, "models"),
|
|
333
604
|
join(this.projectDir, "dashboards"),
|
|
334
605
|
join(this.projectDir, "schedules"),
|
|
335
|
-
join(this.projectDir, "events.yaml")
|
|
606
|
+
join(this.projectDir, "events.yaml"),
|
|
607
|
+
join(this.projectDir, "agents")
|
|
336
608
|
];
|
|
337
609
|
this.watcher = watch(watchPaths, {
|
|
338
610
|
ignored: /(^|[\/\\])\../,
|
|
@@ -453,6 +725,9 @@ Fix: run "ulimit -n 10240" before starting yamchart dev, or add it to your shell
|
|
|
453
725
|
getValidationErrors() {
|
|
454
726
|
return this.validationErrors;
|
|
455
727
|
}
|
|
728
|
+
getAgentRegistry() {
|
|
729
|
+
return this.agentRegistry;
|
|
730
|
+
}
|
|
456
731
|
};
|
|
457
732
|
|
|
458
733
|
// ../server/dist/services/cache.js
|
|
@@ -1485,8 +1760,8 @@ async function semanticRoutes(fastify, options) {
|
|
|
1485
1760
|
});
|
|
1486
1761
|
}
|
|
1487
1762
|
const { writeFileSync, mkdirSync } = await import("fs");
|
|
1488
|
-
const { join:
|
|
1489
|
-
const fullPath =
|
|
1763
|
+
const { join: join9, dirname: dirname3 } = await import("path");
|
|
1764
|
+
const fullPath = join9(projectDir, filePath);
|
|
1490
1765
|
mkdirSync(dirname3(fullPath), { recursive: true });
|
|
1491
1766
|
writeFileSync(fullPath, sql, "utf-8");
|
|
1492
1767
|
return { saved: true, path: filePath };
|
|
@@ -1599,7 +1874,7 @@ var SlackNotifier = class {
|
|
|
1599
1874
|
let response = await fetch(webhookUrl, options);
|
|
1600
1875
|
if (!response.ok) {
|
|
1601
1876
|
if (this.retryDelayMs > 0) {
|
|
1602
|
-
await new Promise((
|
|
1877
|
+
await new Promise((resolve3) => setTimeout(resolve3, this.retryDelayMs));
|
|
1603
1878
|
}
|
|
1604
1879
|
response = await fetch(webhookUrl, options);
|
|
1605
1880
|
if (!response.ok) {
|
|
@@ -1858,11 +2133,11 @@ function __rest(s, e) {
|
|
|
1858
2133
|
}
|
|
1859
2134
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1860
2135
|
function adopt(value) {
|
|
1861
|
-
return value instanceof P ? value : new P(function(
|
|
1862
|
-
|
|
2136
|
+
return value instanceof P ? value : new P(function(resolve3) {
|
|
2137
|
+
resolve3(value);
|
|
1863
2138
|
});
|
|
1864
2139
|
}
|
|
1865
|
-
return new (P || (P = Promise))(function(
|
|
2140
|
+
return new (P || (P = Promise))(function(resolve3, reject) {
|
|
1866
2141
|
function fulfilled(value) {
|
|
1867
2142
|
try {
|
|
1868
2143
|
step(generator.next(value));
|
|
@@ -1878,7 +2153,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
1878
2153
|
}
|
|
1879
2154
|
}
|
|
1880
2155
|
function step(result) {
|
|
1881
|
-
result.done ?
|
|
2156
|
+
result.done ? resolve3(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
1882
2157
|
}
|
|
1883
2158
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1884
2159
|
});
|
|
@@ -4409,15 +4684,15 @@ var RealtimeChannel = class _RealtimeChannel {
|
|
|
4409
4684
|
}
|
|
4410
4685
|
}
|
|
4411
4686
|
} else {
|
|
4412
|
-
return new Promise((
|
|
4687
|
+
return new Promise((resolve3) => {
|
|
4413
4688
|
var _a2, _b2, _c;
|
|
4414
4689
|
const push = this._push(args.type, args, opts.timeout || this.timeout);
|
|
4415
4690
|
if (args.type === "broadcast" && !((_c = (_b2 = (_a2 = this.params) === null || _a2 === void 0 ? void 0 : _a2.config) === null || _b2 === void 0 ? void 0 : _b2.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
|
|
4416
|
-
|
|
4691
|
+
resolve3("ok");
|
|
4417
4692
|
}
|
|
4418
|
-
push.receive("ok", () =>
|
|
4419
|
-
push.receive("error", () =>
|
|
4420
|
-
push.receive("timeout", () =>
|
|
4693
|
+
push.receive("ok", () => resolve3("ok"));
|
|
4694
|
+
push.receive("error", () => resolve3("error"));
|
|
4695
|
+
push.receive("timeout", () => resolve3("timed out"));
|
|
4421
4696
|
});
|
|
4422
4697
|
}
|
|
4423
4698
|
}
|
|
@@ -4445,16 +4720,16 @@ var RealtimeChannel = class _RealtimeChannel {
|
|
|
4445
4720
|
};
|
|
4446
4721
|
this.joinPush.destroy();
|
|
4447
4722
|
let leavePush = null;
|
|
4448
|
-
return new Promise((
|
|
4723
|
+
return new Promise((resolve3) => {
|
|
4449
4724
|
leavePush = new Push(this, CHANNEL_EVENTS.leave, {}, timeout);
|
|
4450
4725
|
leavePush.receive("ok", () => {
|
|
4451
4726
|
onClose();
|
|
4452
|
-
|
|
4727
|
+
resolve3("ok");
|
|
4453
4728
|
}).receive("timeout", () => {
|
|
4454
4729
|
onClose();
|
|
4455
|
-
|
|
4730
|
+
resolve3("timed out");
|
|
4456
4731
|
}).receive("error", () => {
|
|
4457
|
-
|
|
4732
|
+
resolve3("error");
|
|
4458
4733
|
});
|
|
4459
4734
|
leavePush.send();
|
|
4460
4735
|
if (!this._canPush()) {
|
|
@@ -4533,8 +4808,8 @@ var RealtimeChannel = class _RealtimeChannel {
|
|
|
4533
4808
|
_trigger(type, payload, ref) {
|
|
4534
4809
|
var _a, _b;
|
|
4535
4810
|
const typeLower = type.toLocaleLowerCase();
|
|
4536
|
-
const { close, error: error2, leave, join:
|
|
4537
|
-
const events = [close, error2, leave,
|
|
4811
|
+
const { close, error: error2, leave, join: join9 } = CHANNEL_EVENTS;
|
|
4812
|
+
const events = [close, error2, leave, join9];
|
|
4538
4813
|
if (ref && events.indexOf(typeLower) >= 0 && ref !== this._joinRef()) {
|
|
4539
4814
|
return;
|
|
4540
4815
|
}
|
|
@@ -6150,7 +6425,7 @@ var _getRequestParams = (method, options, parameters, body) => {
|
|
|
6150
6425
|
return _objectSpread2(_objectSpread2({}, params), parameters);
|
|
6151
6426
|
};
|
|
6152
6427
|
async function _handleRequest(fetcher, method, url, options, parameters, body, namespace) {
|
|
6153
|
-
return new Promise((
|
|
6428
|
+
return new Promise((resolve3, reject) => {
|
|
6154
6429
|
fetcher(url, _getRequestParams(method, options, parameters, body)).then((result) => {
|
|
6155
6430
|
if (!result.ok) throw result;
|
|
6156
6431
|
if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result;
|
|
@@ -6160,7 +6435,7 @@ async function _handleRequest(fetcher, method, url, options, parameters, body, n
|
|
|
6160
6435
|
if (!contentType || !contentType.includes("application/json")) return {};
|
|
6161
6436
|
}
|
|
6162
6437
|
return result.json();
|
|
6163
|
-
}).then((data) =>
|
|
6438
|
+
}).then((data) => resolve3(data)).catch((error2) => handleError(error2, reject, options, namespace));
|
|
6164
6439
|
});
|
|
6165
6440
|
}
|
|
6166
6441
|
function createFetchApi(namespace = "storage") {
|
|
@@ -13914,6 +14189,12 @@ async function publicRoutes(fastify, options) {
|
|
|
13914
14189
|
}
|
|
13915
14190
|
|
|
13916
14191
|
// ../server/dist/routes/chat.js
|
|
14192
|
+
import { resolve, join as join6 } from "path";
|
|
14193
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
14194
|
+
function isChatEnabled(configLoader) {
|
|
14195
|
+
const project = configLoader.getProject();
|
|
14196
|
+
return !!(project?.features?.chat && process.env.ANTHROPIC_API_KEY);
|
|
14197
|
+
}
|
|
13917
14198
|
async function chatRoutes(fastify, options) {
|
|
13918
14199
|
const { configLoader, queryService } = options;
|
|
13919
14200
|
fastify.post("/api/chat/generate-text", async (request, reply) => {
|
|
@@ -14052,6 +14333,210 @@ async function chatRoutes(fastify, options) {
|
|
|
14052
14333
|
return reply.status(500).send({ error: message });
|
|
14053
14334
|
}
|
|
14054
14335
|
});
|
|
14336
|
+
fastify.get("/api/chat/agents", async (request, reply) => {
|
|
14337
|
+
if (!isChatEnabled(configLoader)) {
|
|
14338
|
+
return reply.code(404).send({ error: "Chat not enabled" });
|
|
14339
|
+
}
|
|
14340
|
+
const registry = configLoader.getAgentRegistry();
|
|
14341
|
+
const agents = registry.listAgents().map((a) => ({
|
|
14342
|
+
name: a.name,
|
|
14343
|
+
title: a.title,
|
|
14344
|
+
description: a.description,
|
|
14345
|
+
builtIn: a.builtIn
|
|
14346
|
+
}));
|
|
14347
|
+
return agents;
|
|
14348
|
+
});
|
|
14349
|
+
fastify.post("/api/chat/stream", async (request, reply) => {
|
|
14350
|
+
if (!isChatEnabled(configLoader)) {
|
|
14351
|
+
return reply.code(404).send({ error: "Chat not enabled" });
|
|
14352
|
+
}
|
|
14353
|
+
const body = request.body;
|
|
14354
|
+
if (!body.message) {
|
|
14355
|
+
return reply.code(400).send({ error: "message is required" });
|
|
14356
|
+
}
|
|
14357
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
14358
|
+
const registry = configLoader.getAgentRegistry();
|
|
14359
|
+
const router = new RouterAgent(registry);
|
|
14360
|
+
const chatContext = body.context ?? { type: "general" };
|
|
14361
|
+
const agentConfig = router.selectAgent(body.message, chatContext, body.agent);
|
|
14362
|
+
reply.raw.writeHead(200, {
|
|
14363
|
+
"Content-Type": "text/event-stream",
|
|
14364
|
+
"Cache-Control": "no-cache",
|
|
14365
|
+
Connection: "keep-alive"
|
|
14366
|
+
});
|
|
14367
|
+
const emitEvent = (event) => {
|
|
14368
|
+
reply.raw.write(formatSSEEvent(event));
|
|
14369
|
+
};
|
|
14370
|
+
emitEvent({ type: "agent_selected", data: { name: agentConfig.name, title: agentConfig.title } });
|
|
14371
|
+
const project = configLoader.getProject();
|
|
14372
|
+
const toolContext = {
|
|
14373
|
+
configLoader: {
|
|
14374
|
+
getChartByName: (name) => configLoader.getChartByName(name),
|
|
14375
|
+
getDashboardByName: (name) => configLoader.getDashboardByName(name),
|
|
14376
|
+
getDashboards: () => configLoader.getDashboards(),
|
|
14377
|
+
getCharts: () => configLoader.getCharts(),
|
|
14378
|
+
getModels: () => configLoader.getModels?.() ?? [],
|
|
14379
|
+
getProject: () => configLoader.getProject(),
|
|
14380
|
+
load: () => configLoader.load()
|
|
14381
|
+
},
|
|
14382
|
+
queryService: {
|
|
14383
|
+
executeChart: (chart, params, userCtx) => queryService.executeChart(chart, params, userCtx),
|
|
14384
|
+
executeRawSql: (sql) => queryService.executeRawSql(sql)
|
|
14385
|
+
},
|
|
14386
|
+
projectDir: options.projectDir,
|
|
14387
|
+
catalogPath: resolve(options.projectDir, ".yamchart", "catalog.json"),
|
|
14388
|
+
agentRegistry: configLoader.getAgentRegistry(),
|
|
14389
|
+
userContext: request.user ? { id: request.user.id, email: request.user.email, role: request.user.role } : void 0,
|
|
14390
|
+
emitEvent,
|
|
14391
|
+
chatContext,
|
|
14392
|
+
catalogFilter: project?.catalog?.include
|
|
14393
|
+
};
|
|
14394
|
+
let systemPrompt = agentConfig.systemPrompt;
|
|
14395
|
+
if (chatContext.type === "dashboard" && chatContext.name) {
|
|
14396
|
+
const dashboard = configLoader.getDashboardByName(chatContext.name);
|
|
14397
|
+
if (dashboard) {
|
|
14398
|
+
const chartRefs = [];
|
|
14399
|
+
const extractRefs = (layout) => {
|
|
14400
|
+
for (const row of layout.rows ?? []) {
|
|
14401
|
+
for (const widget of row.widgets ?? []) {
|
|
14402
|
+
if (widget.type === "chart" && widget.ref)
|
|
14403
|
+
chartRefs.push(widget.ref);
|
|
14404
|
+
}
|
|
14405
|
+
}
|
|
14406
|
+
};
|
|
14407
|
+
if (dashboard.layout)
|
|
14408
|
+
extractRefs(dashboard.layout);
|
|
14409
|
+
if (dashboard.tabs) {
|
|
14410
|
+
for (const tab of dashboard.tabs) {
|
|
14411
|
+
if (tab.layout)
|
|
14412
|
+
extractRefs(tab.layout);
|
|
14413
|
+
}
|
|
14414
|
+
}
|
|
14415
|
+
const chartDetails = [];
|
|
14416
|
+
for (const ref of chartRefs) {
|
|
14417
|
+
const chart = configLoader.getChartByName(ref);
|
|
14418
|
+
if (!chart)
|
|
14419
|
+
continue;
|
|
14420
|
+
const model = chart.source?.model ? `, model: "${chart.source.model}"` : "";
|
|
14421
|
+
const params = chart.parameters?.length ? `, params: [${chart.parameters.map((p) => `${p.name}(${p.type})`).join(", ")}]` : "";
|
|
14422
|
+
chartDetails.push(` - "${ref}" (${chart.chart?.type ?? "unknown"}${model}${params}): ${chart.title ?? ref}`);
|
|
14423
|
+
}
|
|
14424
|
+
const filters = dashboard.filters?.length ? `
|
|
14425
|
+
Dashboard filters: ${dashboard.filters.map((f) => `${f.name}(${f.type}, default: ${f.default ?? "none"})`).join(", ")}` : "";
|
|
14426
|
+
systemPrompt += `
|
|
14427
|
+
|
|
14428
|
+
The user is viewing the "${dashboard.title ?? dashboard.name}" dashboard (id: "${dashboard.name}").${filters}
|
|
14429
|
+
Charts on this dashboard:
|
|
14430
|
+
${chartDetails.join("\n")}
|
|
14431
|
+
|
|
14432
|
+
IMPORTANT: When using query_model, pass the chart name (e.g. "${chartRefs[0] ?? "chart-name"}") \u2014 NOT the model name. The chart name is what appears before the parentheses above.`;
|
|
14433
|
+
}
|
|
14434
|
+
} else if (chatContext.type === "chart" && chatContext.name) {
|
|
14435
|
+
const chart = configLoader.getChartByName(chatContext.name);
|
|
14436
|
+
if (chart) {
|
|
14437
|
+
const model = chart.source?.model ? ` Model: "${chart.source.model}".` : "";
|
|
14438
|
+
const params = chart.parameters?.length ? ` Parameters: ${chart.parameters.map((p) => `${p.name}(${p.type})`).join(", ")}.` : "";
|
|
14439
|
+
systemPrompt += `
|
|
14440
|
+
|
|
14441
|
+
The user is viewing the "${chart.title ?? chart.name}" chart (id: "${chart.name}", type: ${chart.chart?.type}).${model}${params}`;
|
|
14442
|
+
}
|
|
14443
|
+
} else if (chatContext.type === "explore") {
|
|
14444
|
+
const catalogPath = join6(options.projectDir, ".yamchart", "catalog.json");
|
|
14445
|
+
const tableLines = [];
|
|
14446
|
+
try {
|
|
14447
|
+
const catalogData = JSON.parse(await readFile3(catalogPath, "utf-8"));
|
|
14448
|
+
const filteredModels = filterCatalogEntries(catalogData.models ?? [], project?.catalog?.include);
|
|
14449
|
+
for (const entry of filteredModels) {
|
|
14450
|
+
const fullName = entry.table ?? entry.name;
|
|
14451
|
+
const cols = (entry.columns ?? []).map((c) => c.name).join(", ");
|
|
14452
|
+
const colSuffix = cols ? ` (${entry.columns?.length} columns: ${cols})` : "";
|
|
14453
|
+
tableLines.push(`- ${fullName}${colSuffix}`);
|
|
14454
|
+
}
|
|
14455
|
+
} catch {
|
|
14456
|
+
}
|
|
14457
|
+
const configModels = configLoader.getModels?.() ?? [];
|
|
14458
|
+
const modelLines = configModels.map((m) => m.metadata.description ? `- ${m.metadata.name}: ${m.metadata.description}` : `- ${m.metadata.name}`);
|
|
14459
|
+
if (tableLines.length === 0 && modelLines.length === 0) {
|
|
14460
|
+
systemPrompt += "\n\nNo catalog data available. Use get_catalog_tables or run_sql to discover tables.";
|
|
14461
|
+
} else {
|
|
14462
|
+
const parts = ["\n"];
|
|
14463
|
+
if (tableLines.length > 0) {
|
|
14464
|
+
parts.push("## Available Tables", ...tableLines);
|
|
14465
|
+
}
|
|
14466
|
+
if (modelLines.length > 0) {
|
|
14467
|
+
if (parts.length > 1)
|
|
14468
|
+
parts.push("");
|
|
14469
|
+
parts.push("## Available Models", ...modelLines);
|
|
14470
|
+
}
|
|
14471
|
+
systemPrompt += parts.join("\n");
|
|
14472
|
+
}
|
|
14473
|
+
}
|
|
14474
|
+
const messages = [];
|
|
14475
|
+
for (const msg of body.history ?? []) {
|
|
14476
|
+
messages.push({ role: msg.role, content: msg.content });
|
|
14477
|
+
}
|
|
14478
|
+
messages.push({ role: "user", content: body.message });
|
|
14479
|
+
try {
|
|
14480
|
+
const agent = new StreamingChatAgent(agentConfig, apiKey);
|
|
14481
|
+
await agent.run(systemPrompt, messages, toolContext, emitEvent);
|
|
14482
|
+
} catch (err) {
|
|
14483
|
+
emitEvent({
|
|
14484
|
+
type: "error",
|
|
14485
|
+
data: { message: err instanceof Error ? err.message : "Stream failed" }
|
|
14486
|
+
});
|
|
14487
|
+
}
|
|
14488
|
+
reply.raw.end();
|
|
14489
|
+
});
|
|
14490
|
+
}
|
|
14491
|
+
|
|
14492
|
+
// ../server/dist/routes/catalog.js
|
|
14493
|
+
import { join as join7 } from "path";
|
|
14494
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
14495
|
+
async function catalogRoutes(fastify, options) {
|
|
14496
|
+
const { configLoader, projectDir } = options;
|
|
14497
|
+
fastify.get("/api/catalog/summary", async (_request2, reply) => {
|
|
14498
|
+
const connections = configLoader.getConnections().map((c) => ({
|
|
14499
|
+
name: c.name,
|
|
14500
|
+
type: c.type
|
|
14501
|
+
}));
|
|
14502
|
+
const configModels = configLoader.getModels().map((m) => ({
|
|
14503
|
+
name: m.metadata.name,
|
|
14504
|
+
description: m.metadata.description
|
|
14505
|
+
}));
|
|
14506
|
+
const catalogPath = join7(projectDir, ".yamchart", "catalog.json");
|
|
14507
|
+
let tables = [];
|
|
14508
|
+
try {
|
|
14509
|
+
const catalogData = JSON.parse(await readFile4(catalogPath, "utf-8"));
|
|
14510
|
+
const allCatalogModels = catalogData.models ?? [];
|
|
14511
|
+
const project = configLoader.getProject();
|
|
14512
|
+
const catalogModels = filterCatalogEntries(allCatalogModels, project?.catalog?.include);
|
|
14513
|
+
tables = catalogModels.map((m) => {
|
|
14514
|
+
const fullName = m.table ?? m.name ?? "";
|
|
14515
|
+
const parts = fullName.split(".");
|
|
14516
|
+
const tableName = parts[parts.length - 1] ?? fullName;
|
|
14517
|
+
const schema = parts.length > 1 ? parts.slice(0, -1).join(".") : void 0;
|
|
14518
|
+
const columns = (m.columns ?? []).map((c) => ({
|
|
14519
|
+
name: c.name,
|
|
14520
|
+
type: c.data_type
|
|
14521
|
+
}));
|
|
14522
|
+
return {
|
|
14523
|
+
name: tableName,
|
|
14524
|
+
...schema ? { schema } : {},
|
|
14525
|
+
connection: m.connection ?? (connections[0]?.name ?? "default"),
|
|
14526
|
+
columnCount: columns.length,
|
|
14527
|
+
columns
|
|
14528
|
+
};
|
|
14529
|
+
});
|
|
14530
|
+
} catch {
|
|
14531
|
+
}
|
|
14532
|
+
return reply.send({
|
|
14533
|
+
connections,
|
|
14534
|
+
tables,
|
|
14535
|
+
models: configModels,
|
|
14536
|
+
tableCount: tables.length,
|
|
14537
|
+
modelCount: configModels.length
|
|
14538
|
+
});
|
|
14539
|
+
});
|
|
14055
14540
|
}
|
|
14056
14541
|
|
|
14057
14542
|
// ../server/dist/routes/events.js
|
|
@@ -14093,18 +14578,18 @@ data: ${data}
|
|
|
14093
14578
|
}
|
|
14094
14579
|
|
|
14095
14580
|
// ../server/dist/server.js
|
|
14096
|
-
import { join as
|
|
14581
|
+
import { join as join8, dirname as dirname2 } from "path";
|
|
14097
14582
|
import { fileURLToPath } from "url";
|
|
14098
|
-
import { access as access2, readFile as
|
|
14583
|
+
import { access as access2, readFile as readFile5 } from "fs/promises";
|
|
14099
14584
|
import { watch as fsWatch } from "fs";
|
|
14100
14585
|
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
14101
|
-
var packageJsonPath =
|
|
14102
|
-
var packageJson = JSON.parse(await
|
|
14586
|
+
var packageJsonPath = join8(__dirname, "..", "package.json");
|
|
14587
|
+
var packageJson = JSON.parse(await readFile5(packageJsonPath, "utf-8"));
|
|
14103
14588
|
var VERSION = packageJson.version;
|
|
14104
14589
|
async function enrichRefsFromCatalog(projectDir, refs) {
|
|
14105
14590
|
try {
|
|
14106
|
-
const catalogPath =
|
|
14107
|
-
const catalogData = JSON.parse(await
|
|
14591
|
+
const catalogPath = join8(projectDir, ".yamchart", "catalog.json");
|
|
14592
|
+
const catalogData = JSON.parse(await readFile5(catalogPath, "utf-8"));
|
|
14108
14593
|
for (const model of catalogData.models ?? []) {
|
|
14109
14594
|
if (model.name && model.table) {
|
|
14110
14595
|
refs[model.name] = model.table;
|
|
@@ -14114,7 +14599,7 @@ async function enrichRefsFromCatalog(projectDir, refs) {
|
|
|
14114
14599
|
}
|
|
14115
14600
|
}
|
|
14116
14601
|
async function createServer(options) {
|
|
14117
|
-
const { projectDir, port = 3001, host = "0.0.0.0", watch: watch2 = false, serveStatic = process.env.NODE_ENV === "production", staticDir =
|
|
14602
|
+
const { projectDir, port = 3001, host = "0.0.0.0", watch: watch2 = false, serveStatic = process.env.NODE_ENV === "production", staticDir = join8(__dirname, "public"), auth } = options;
|
|
14118
14603
|
if (auth) {
|
|
14119
14604
|
initAuthServer(auth.supabaseUrl, auth.supabaseServiceKey);
|
|
14120
14605
|
}
|
|
@@ -14248,6 +14733,7 @@ async function createServer(options) {
|
|
|
14248
14733
|
await protectedRoutes.register(chartEventsRoutes, { configLoader, projectDir });
|
|
14249
14734
|
await protectedRoutes.register(dashboardRoutes, { configLoader, gitService, projectDir, queryService });
|
|
14250
14735
|
await protectedRoutes.register(chatRoutes, { configLoader, queryService, projectDir });
|
|
14736
|
+
await protectedRoutes.register(catalogRoutes, { configLoader, projectDir });
|
|
14251
14737
|
});
|
|
14252
14738
|
} else if (authDb) {
|
|
14253
14739
|
const localMiddleware = createLocalAuthMiddleware(authDb);
|
|
@@ -14258,6 +14744,7 @@ async function createServer(options) {
|
|
|
14258
14744
|
await protectedRoutes.register(chartEventsRoutes, { configLoader, projectDir });
|
|
14259
14745
|
await protectedRoutes.register(dashboardRoutes, { configLoader, gitService, projectDir, queryService });
|
|
14260
14746
|
await protectedRoutes.register(chatRoutes, { configLoader, queryService, projectDir });
|
|
14747
|
+
await protectedRoutes.register(catalogRoutes, { configLoader, projectDir });
|
|
14261
14748
|
await protectedRoutes.register(sharesRoutes, { authDb });
|
|
14262
14749
|
});
|
|
14263
14750
|
} else {
|
|
@@ -14266,8 +14753,9 @@ async function createServer(options) {
|
|
|
14266
14753
|
await fastify.register(chartEventsRoutes, { configLoader, projectDir });
|
|
14267
14754
|
await fastify.register(dashboardRoutes, { configLoader, gitService, projectDir, queryService });
|
|
14268
14755
|
await fastify.register(chatRoutes, { configLoader, queryService, projectDir });
|
|
14756
|
+
await fastify.register(catalogRoutes, { configLoader, projectDir });
|
|
14269
14757
|
}
|
|
14270
|
-
const assetsDir =
|
|
14758
|
+
const assetsDir = join8(projectDir, "assets");
|
|
14271
14759
|
try {
|
|
14272
14760
|
await access2(assetsDir);
|
|
14273
14761
|
await fastify.register(fastifyStatic, {
|
|
@@ -14278,10 +14766,10 @@ async function createServer(options) {
|
|
|
14278
14766
|
} catch {
|
|
14279
14767
|
}
|
|
14280
14768
|
if (project.theme?.customCss) {
|
|
14281
|
-
const cssPath =
|
|
14769
|
+
const cssPath = join8(projectDir, project.theme.customCss);
|
|
14282
14770
|
fastify.get("/api/theme/custom.css", async (_request2, reply) => {
|
|
14283
14771
|
try {
|
|
14284
|
-
const content = await
|
|
14772
|
+
const content = await readFile5(cssPath, "utf-8");
|
|
14285
14773
|
return reply.type("text/css").send(content);
|
|
14286
14774
|
} catch {
|
|
14287
14775
|
return reply.status(404).send("");
|
|
@@ -14337,7 +14825,7 @@ async function createServer(options) {
|
|
|
14337
14825
|
fastify.log.info(`Semantic model rebuilt: ${semanticService.getModel()?.entities.length ?? 0} entities`);
|
|
14338
14826
|
broadcastConfigChange();
|
|
14339
14827
|
});
|
|
14340
|
-
const catalogPath =
|
|
14828
|
+
const catalogPath = join8(projectDir, ".yamchart", "catalog.json");
|
|
14341
14829
|
try {
|
|
14342
14830
|
catalogWatcher = fsWatch(catalogPath, () => {
|
|
14343
14831
|
semanticService.buildFromDisk();
|
|
@@ -14402,15 +14890,15 @@ async function runDevServer(projectDir, options) {
|
|
|
14402
14890
|
let localAuth;
|
|
14403
14891
|
try {
|
|
14404
14892
|
const { readFileSync: readFileSync2 } = await import("fs");
|
|
14405
|
-
const { parse } = await import("yaml");
|
|
14406
|
-
const { resolveProjectConfig: resolveProjectConfig2, deepMerge: deepMerge3 } = await import("./dist-
|
|
14407
|
-
const raw = readFileSync2(
|
|
14408
|
-
const rawConfig =
|
|
14893
|
+
const { parse: parse2 } = await import("yaml");
|
|
14894
|
+
const { resolveProjectConfig: resolveProjectConfig2, deepMerge: deepMerge3 } = await import("./dist-PINRLZVT.js");
|
|
14895
|
+
const raw = readFileSync2(resolve2(projectDir, "yamchart.yaml"), "utf-8");
|
|
14896
|
+
const rawConfig = parse2(raw);
|
|
14409
14897
|
const resolvedEnv = options.env || process.env.YAMCHART_ENV || void 0;
|
|
14410
14898
|
let projectConfig = resolveProjectConfig2(rawConfig, resolvedEnv);
|
|
14411
14899
|
try {
|
|
14412
|
-
const localRaw = readFileSync2(
|
|
14413
|
-
const localOverrides =
|
|
14900
|
+
const localRaw = readFileSync2(resolve2(projectDir, "yamchart.local.yaml"), "utf-8");
|
|
14901
|
+
const localOverrides = parse2(localRaw);
|
|
14414
14902
|
if (localOverrides && typeof localOverrides === "object") {
|
|
14415
14903
|
projectConfig = deepMerge3(projectConfig, localOverrides);
|
|
14416
14904
|
}
|
|
@@ -14419,16 +14907,16 @@ async function runDevServer(projectDir, options) {
|
|
|
14419
14907
|
if (projectConfig?.auth?.enabled) {
|
|
14420
14908
|
localAuth = {
|
|
14421
14909
|
enabled: true,
|
|
14422
|
-
dbPath: projectConfig.auth.db_path ?
|
|
14910
|
+
dbPath: projectConfig.auth.db_path ? resolve2(projectConfig.auth.db_path.replace(/^~/, homedir())) : resolve2(homedir(), ".yamchart", "auth.db"),
|
|
14423
14911
|
sessionTtlMs: projectConfig.auth.session_ttl ? parseTtl(projectConfig.auth.session_ttl) : 30 * 24 * 60 * 60 * 1e3
|
|
14424
14912
|
};
|
|
14425
14913
|
}
|
|
14426
|
-
const connectionDir =
|
|
14914
|
+
const connectionDir = resolve2(projectDir, "connections");
|
|
14427
14915
|
const targetConn = process.env.YAMCHART_CONNECTION || projectConfig?.defaults?.connection;
|
|
14428
14916
|
if (targetConn) {
|
|
14429
14917
|
try {
|
|
14430
|
-
const connRaw = readFileSync2(
|
|
14431
|
-
const connConfig =
|
|
14918
|
+
const connRaw = readFileSync2(resolve2(connectionDir, `${targetConn}.yaml`), "utf-8");
|
|
14919
|
+
const connConfig = parse2(connRaw);
|
|
14432
14920
|
if (connConfig?.auth?.type === "externalbrowser") {
|
|
14433
14921
|
usesBrowserAuth = true;
|
|
14434
14922
|
}
|
|
@@ -14495,4 +14983,4 @@ async function runDevServer(projectDir, options) {
|
|
|
14495
14983
|
export {
|
|
14496
14984
|
runDevServer
|
|
14497
14985
|
};
|
|
14498
|
-
//# sourceMappingURL=dev-
|
|
14986
|
+
//# sourceMappingURL=dev-JUA73B6D.js.map
|