@trilogy-data/trilogy-studio-components 0.1.26 → 0.1.28
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/AssetAutoImporter-C_7Ms9xe.js +403 -0
- package/dist/{ChatCreatorModal-CL-jBnc3.js → ChatCreatorModal-Cd40SvdM.js} +3 -3
- package/dist/{ChatModelSelect-Do-VRUFc.js → ChatModelSelect-Cz7axWjP.js} +1 -1
- package/dist/{CodeBlock-PT4no49I.js → CodeBlock-Dj-GfTbW.js} +4 -4
- package/dist/{CommunityModels-Cmro0hV3.js → CommunityModels-lX2RhHCG.js} +7 -7
- package/dist/{ConnectionErrorPopup-FSs7U-Yl.js → ConnectionErrorPopup-7vpqgF0s.js} +1 -1
- package/dist/{ConnectionView-COnTTuA4.js → ConnectionView-CZ06qjjE.js} +49 -49
- package/dist/{CreateEditorFromDatasourcePopup-snOh1d5h.js → CreateEditorFromDatasourcePopup-DwA938kf.js} +4 -4
- package/dist/{Dashboard-BH9ZwMVJ.js → Dashboard-CQsIqWZC.js} +276 -280
- package/dist/{DashboardImportSelector-DQSvu9T-.js → DashboardImportSelector-CkqH52FX.js} +2 -2
- package/dist/{DashboardMobile-BUPtdN2V.js → DashboardMobile-DWFlel5p.js} +39 -39
- package/dist/{DrilldownPane-CBs5ZojS.js → DrilldownPane-BheRHJMs.js} +5 -7
- package/dist/{Editor-DQsYpkwl.js → Editor-DQ66Vp6v.js} +105 -103
- package/dist/{ErrorMessage-XMn_08gJ.js → ErrorMessage-D5JeF3Iz.js} +4 -4
- package/dist/{GlobalChatPanel-DhnOaige.js → GlobalChatPanel-B_s3COHE.js} +20 -21
- package/dist/{IDE-HLa8vybk.js → IDE-4-Jg6gsM.js} +200 -203
- package/dist/{JobsView-B97HBoIE.js → JobsView-B5NWDUgP.js} +13 -14
- package/dist/{LLMChat-CxJcPLEG.js → LLMChat-eKgEc-I3.js} +3 -3
- package/dist/{LLMView-C1MUf0c2.js → LLMView-CdTwMLVV.js} +23 -23
- package/dist/{LoadingView-s1uznGwG.js → LoadingView-Bu3wLJ7J.js} +2 -2
- package/dist/{MarkdownRenderer-BNDuEyG-.js → MarkdownRenderer-B6lqdkgc.js} +531 -430
- package/dist/{MobileIDE-BpqXoaMR.js → MobileIDE-CZlg20oa.js} +179 -182
- package/dist/{ModelCard-BhN25jaV.js → ModelCard-Bs_d7Jis.js} +12 -13
- package/dist/{ModelView-DUDA_PtZ.js → ModelView-BP5yyecx.js} +7 -7
- package/dist/PageLoading-DKFeqkmK.js +5937 -0
- package/dist/{ResultComponent-CAn_r3BL.js → ResultComponent-BaDheojB.js} +8 -8
- package/dist/{Results-BJtlwebY.js → Results-CrpHB101.js} +17 -19
- package/dist/{StatusIcon-BylPx2EO.js → StatusIcon-Clfyy-Yn.js} +2 -2
- package/dist/{StoreTokenModal-zCSYhfrw.js → StoreTokenModal-CO5hXMs3.js} +2 -2
- package/dist/{SymbolsPane-KYSwN9Sv.js → SymbolsPane-XFVErDFb.js} +6 -3
- package/dist/{TrilogyEmbedProvider-WA_dlv9e.js → TrilogyEmbedProvider-D3h0gYnX.js} +9 -9
- package/dist/{TutorialPage-NRcee6Dx.js → TutorialPage-CMcTYDOV.js} +27 -28
- package/dist/{VegaLiteChart-D1slfOUY.js → VegaLiteChart-DX_LbF3g.js} +12131 -10947
- package/dist/{WelcomePage-D5mU2x1L.js → WelcomePage-B6E35FUa.js} +5 -5
- package/dist/{embedTheme-Bub46ILG.js → _plugin-vue_export-helper-f9Rw-Il4.js} +14 -6
- package/dist/assets/{css.worker-9aDGcEUy.js → css.worker-niORQtzO.js} +14 -14
- package/dist/assets/{html.worker-D2LKDpnG.js → html.worker-CO5LvJpF.js} +17 -17
- package/dist/assets/json.worker-BezHzWUV.js +58 -0
- package/dist/assets/{ts.worker-Bz0-EaKK.js → ts.worker-CYhxGg0r.js} +107 -107
- package/dist/{results-DTgAKr5j.js → base-DuKnVD-A.js} +216 -45
- package/dist/components/FeedbackBanner.vue.d.ts +4 -0
- package/dist/components/FeedbackBanner.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardCreatorIcon.vue.d.ts +54 -0
- package/dist/components/dashboard/DashboardCreatorIcon.vue.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardProvenance.vue.d.ts +30 -0
- package/dist/components/dashboard/DashboardProvenance.vue.d.ts.map +1 -0
- package/dist/components/dashboard/ReportLayout.vue.d.ts +19 -0
- package/dist/components/dashboard/ReportLayout.vue.d.ts.map +1 -0
- package/dist/components/editor/Editor.vue.d.ts +3 -3
- package/dist/components/editor/EditorCreatorIcon.vue.d.ts +62 -0
- package/dist/components/editor/EditorCreatorIcon.vue.d.ts.map +1 -0
- package/dist/components/editor/ValidationComponent.vue.d.ts +50 -0
- package/dist/components/editor/ValidationComponent.vue.d.ts.map +1 -0
- package/dist/components/model/ModelCard.vue.d.ts +3 -3
- package/dist/components/sidebar/LLMConnectionList.vue.d.ts.map +1 -1
- package/dist/components/sidebar/Sidebar.vue.d.ts.map +1 -1
- package/dist/components/tutorial/TutorialPrompt.vue.d.ts +3 -3
- package/dist/components/tutorial/TutorialPrompt.vue.d.ts.map +1 -1
- package/dist/{remoteWorker-Dkv3TJ0j.js → connections-CWH3zwH2.js} +4544 -4126
- package/dist/connections.js +3 -4
- package/dist/{cssMode-D4Rzr1Cu.js → cssMode-zpO2ap2B.js} +5 -6
- package/dist/dashboard.js +28 -31
- package/dist/dashboards/dashboardQueryExecutor.d.ts +9 -0
- package/dist/dashboards/dashboardQueryExecutor.d.ts.map +1 -1
- package/dist/{dist-CXoL8kXK.js → dist-1z5KURzS.js} +55 -50
- package/dist/{dist-DKkuvbPb.js → dist-Bv3D2p5A.js} +20 -18
- package/dist/{editor.main-Cl8i7rHY.js → editor.main-BQh6DxDB.js} +33 -33
- package/dist/{editorRefinementRuntime-DoP9P5J2.js → editorStore-CiWH_nGN.js} +1692 -575
- package/dist/embed.js +2 -2
- package/dist/{freemarker2-fW5NBILf.js → freemarker2-DQBqlEXc.js} +1 -1
- package/dist/{globalChatRuntime-DWZxeS57.js → globalChatRuntime-DAERmOdu.js} +16 -16
- package/dist/{handlebars-dG4w8UUY.js → handlebars-tgYxaM70.js} +1 -1
- package/dist/{helpers-BLQAgX3C.js → helpers-C2pARJoZ.js} +34 -35
- package/dist/{html-1Dq70BdU.js → html-jJahD3Mi.js} +1 -1
- package/dist/{htmlMode--IQmLBeh.js → htmlMode-BA1-8l2e.js} +5 -6
- package/dist/{javascript-CTzBM4sF.js → javascript-Cypfo7va.js} +1 -1
- package/dist/{jsonMode-DzeJjIEH.js → jsonMode-xJye8PWS.js} +25 -25
- package/dist/{liquid-DlHThiki.js → liquid-BGDrv5da.js} +1 -1
- package/dist/llm/data/prompts.d.ts +1 -1
- package/dist/llm/data/prompts.d.ts.map +1 -1
- package/dist/llm/data/trilogySyntax.generated.d.ts +3 -3
- package/dist/llm/data/trilogySyntax.generated.d.ts.map +1 -1
- package/dist/llm-Wf4Etiu9.js +18493 -0
- package/dist/llm.js +2 -3
- package/dist/{localStorage-D9uyOFEO.js → localStorage-C3xms-ab.js} +40 -43
- package/dist/{lspLanguageFeatures-Cdfs3EKq.js → lspLanguageFeatures-V3e_p9oN.js} +32 -32
- package/dist/{mdx-fn3g4PH5.js → mdx-BUR1aImW.js} +1 -1
- package/dist/monaco.js +4 -4
- package/dist/{python-CCVj0pFt.js → python-YLkl0pc6.js} +1 -1
- package/dist/{razor-Cj3flYnk.js → razor-BP8TRMDY.js} +1 -1
- package/dist/{reconcile-Dyf4UZmj.js → reconcile-BH_ReGDR.js} +1 -1
- package/dist/{remoteStoreSync-Z-yjlYtI.js → remoteStoreSync-B0K8QScO.js} +3 -3
- package/dist/{rolldown-runtime-Dqa2HsxW.js → rolldown-runtime-B0aSnxlc.js} +2 -2
- package/dist/static/test_import.vue.d.ts +4 -0
- package/dist/static/test_import.vue.d.ts.map +1 -0
- package/dist/stores-DTGQZ4_B.js +2612 -0
- package/dist/stores.js +4 -7
- package/dist/trilogy-studio-components.css +1 -1
- package/dist/{tsMode-GI4xMYAl.js → tsMode-BH9HS_sH.js} +64 -66
- package/dist/{typescript-CPibXi3J.js → typescript-BM-ynfk9.js} +1 -1
- package/dist/{useChatWithTools-B0HZ_DVh.js → useChatWithTools-BSrzJtYI.js} +11 -11
- package/dist/{useDashboard-CdSnPe_6.js → useDashboard-CGeIdDuX.js} +1014 -1022
- package/dist/{tabulator_esm-CxLvGDp8.js → useGlobalChatPanel-D9kMZLeF.js} +1729 -711
- package/dist/{useResizableDialog-B0ePSts4.js → useResizableDialog-Cs90WJdF.js} +2 -2
- package/dist/views/ModelView.vue.d.ts +6 -6
- package/dist/views/ModelView.vue.d.ts.map +1 -1
- package/dist/views/TutorialPage.vue.d.ts +9 -9
- package/dist/views/TutorialPage.vue.d.ts.map +1 -1
- package/dist/views.js +192 -194
- package/dist/{vocabulary-CKLGILtR.js → vocabulary-DQK5jB7m.js} +3 -1
- package/dist/{editor.api2-ClD5pp8H.js → workers-B9Eybl-M.js} +16252 -15926
- package/dist/{xml-BNyphceI.js → xml-M5WFPSpA.js} +1 -1
- package/dist/{yaml-DE5Vz0PH.js → yaml-CEeFwjz9.js} +1 -1
- package/package.json +29 -20
- package/dist/AssetAutoImporter-CBzvBaOt.js +0 -405
- package/dist/DashboardCreatorInline-CDU7kLy3.js +0 -129
- package/dist/DataTable-DoRDynP1.js +0 -365
- package/dist/EditorCreatorInline-D6_y1H_h.js +0 -125
- package/dist/LoadingButton-OH3frQuO.js +0 -138
- package/dist/ModalDialog-D1EOG4rl.js +0 -42
- package/dist/ModelCreator-CCdC7EXt.js +0 -253
- package/dist/PageLoading-BzniJM0C.js +0 -2669
- package/dist/Tooltip-Dihir4zs.js +0 -103
- package/dist/_plugin-vue_export-helper-B3ysoDQm.js +0 -8
- package/dist/assets/json.worker-CJ5MmO5Q.js +0 -58
- package/dist/base-C8IuZWqY.js +0 -164
- package/dist/connectionHistoryStorage-DKJHiKJY.js +0 -111
- package/dist/connectionHistoryStore-DQeBvStZ.js +0 -61
- package/dist/connections-CJSb1TZl.js +0 -229
- package/dist/constants-DgFEYN2b.js +0 -7
- package/dist/dashboardStore-ppM6nGks.js +0 -641
- package/dist/demoSetup-mwa-RDC6.js +0 -2942
- package/dist/editorRefinementToolExecutor-CVY3FA7k.js +0 -4624
- package/dist/editorStore-BhhmXbi-.js +0 -1019
- package/dist/formatting-BbJ5ICgh.js +0 -6
- package/dist/llm-BBOVWb-F.js +0 -11967
- package/dist/llmStore-DJM2JhzY.js +0 -153
- package/dist/monaco.contribution-ikesdolO.js +0 -128
- package/dist/stores-BT9hTLny.js +0 -1708
- package/dist/trilogy-BroD2Qmp.js +0 -4
- package/dist/urlStore-52HG6lsX.js +0 -55
- package/dist/useGlobalChatPanel-D_0luajQ.js +0 -85
- package/dist/useIsMobile-CNpUQAvk.js +0 -8
- package/dist/usePrismHighlight-DVyDiDAL.js +0 -183
- package/dist/workers-Br7ThUKL.js +0 -47
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { $
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { defineStore as
|
|
1
|
+
import { s as e, u as t } from "./base-DuKnVD-A.js";
|
|
2
|
+
import { $ as n, $t as r, B as i, Bt as a, Ft as o, H as s, J as c, Lt as l, Q as u, Qt as d, R as f, Rt as p, St as m, W as h, a as g, an as ee, at as te, c as ne, cn as _, ct as re, dt as ie, en as ae, ft as oe, gn as se, hn as ce, ht as le, i as ue, in as de, k as v, l as fe, ln as pe, mt as me, n as he, nn as ge, o as _e, on as ve, ot as ye, pt as be, r as xe, rn as Se, s as Ce, st as we, t as Te, tn as Ee, tt as De, ut as Oe, xt as ke, y, z as Ae, zt as je } from "./llm-Wf4Etiu9.js";
|
|
3
|
+
import { a as Me, c as Ne, f as Pe, l as Fe, n as Ie, o as Le, u as Re } from "./connections-CWH3zwH2.js";
|
|
4
|
+
import { reactive as ze } from "vue";
|
|
5
|
+
import { defineStore as b } from "pinia";
|
|
6
6
|
//#region editors/fileTypes.ts
|
|
7
|
-
var
|
|
7
|
+
var Be = (e) => {
|
|
8
8
|
let t = e.lastIndexOf(".");
|
|
9
9
|
return t === -1 ? "" : e.slice(t).toLowerCase();
|
|
10
|
-
},
|
|
10
|
+
}, Ve = (e) => {
|
|
11
11
|
switch (e) {
|
|
12
12
|
case "sql": return ".sql";
|
|
13
13
|
case "python": return ".py";
|
|
@@ -15,11 +15,11 @@ var T = (e) => {
|
|
|
15
15
|
case "csv": return ".csv";
|
|
16
16
|
default: return ".preql";
|
|
17
17
|
}
|
|
18
|
-
},
|
|
18
|
+
}, x = (e, t) => {
|
|
19
19
|
let n = e.trim();
|
|
20
|
-
return !n || /\.(preql|sql|csv|py|md|markdown|txt)$/i.test(n) ? n : `${n}${
|
|
21
|
-
},
|
|
22
|
-
switch (
|
|
20
|
+
return !n || /\.(preql|sql|csv|py|md|markdown|txt)$/i.test(n) ? n : `${n}${Ve(t)}`;
|
|
21
|
+
}, S = (e) => {
|
|
22
|
+
switch (Be(e)) {
|
|
23
23
|
case ".preql": return "preql";
|
|
24
24
|
case ".sql": return "sql";
|
|
25
25
|
case ".py": return "python";
|
|
@@ -29,7 +29,7 @@ var T = (e) => {
|
|
|
29
29
|
case ".csv": return "csv";
|
|
30
30
|
default: return null;
|
|
31
31
|
}
|
|
32
|
-
},
|
|
32
|
+
}, He = (e) => {
|
|
33
33
|
switch (e) {
|
|
34
34
|
case "sql":
|
|
35
35
|
case "csv": return "sql";
|
|
@@ -37,23 +37,23 @@ var T = (e) => {
|
|
|
37
37
|
case "markdown": return "markdown";
|
|
38
38
|
default: return "trilogy";
|
|
39
39
|
}
|
|
40
|
-
},
|
|
41
|
-
let t =
|
|
40
|
+
}, C = (e) => e === "trilogy" || e === "preql", Ue = (e) => C(e), We = (e) => C(e), Ge = (e) => C(e), Ke = (e) => C(e) || e === "sql", qe = (e) => e !== "python" && e !== "markdown" && e !== "csv", Je = (e) => {
|
|
41
|
+
let t = Be(e);
|
|
42
42
|
return t !== ".py" && t !== ".md" && t !== ".csv";
|
|
43
|
-
},
|
|
43
|
+
}, w = /* @__PURE__ */ function(e) {
|
|
44
44
|
return e.SOURCE = "source", e.STARTUP_SCRIPT = "startup_script", e;
|
|
45
45
|
}({});
|
|
46
|
-
function
|
|
47
|
-
return
|
|
48
|
-
name:
|
|
46
|
+
function Ye(t) {
|
|
47
|
+
return t.storage === "remote" ? e({
|
|
48
|
+
name: t.connection,
|
|
49
49
|
storage: "remote",
|
|
50
|
-
remoteStoreId:
|
|
51
|
-
}) :
|
|
52
|
-
name:
|
|
50
|
+
remoteStoreId: t.remoteStoreId || null
|
|
51
|
+
}) : e({
|
|
52
|
+
name: t.connection,
|
|
53
53
|
storage: "local"
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
-
var
|
|
56
|
+
var Xe = class e {
|
|
57
57
|
id;
|
|
58
58
|
name;
|
|
59
59
|
type;
|
|
@@ -93,35 +93,35 @@ var Ie = class t {
|
|
|
93
93
|
default: return "SELECT 1;";
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
constructor({ id:
|
|
97
|
-
this.id =
|
|
96
|
+
constructor({ id: e, name: n, type: r, connection: i, storage: a, contents: o = null, tags: s = null, remoteStoreId: c = null, remotePath: l = null, remoteOriginalPath: u = null, remotePersisted: d = !1 }) {
|
|
97
|
+
this.id = e, this.name = a === "remote" ? x(n, r) : n, this.type = S(this.name) ?? r, this.syntax = this.type === "python" ? "python" : "preql", this.connection = i, this.connectionId = Ye({
|
|
98
98
|
connection: i,
|
|
99
99
|
storage: a,
|
|
100
100
|
remoteStoreId: c
|
|
101
|
-
}), this.results = new
|
|
101
|
+
}), this.results = new t(/* @__PURE__ */ new Map(), []), this.contents = o || this.defaultContents(r), this.loading = !1, this.error = null, this.duration = null, this.status_code = 200, this.generated_sql = null, this.executed_contents = null, this.storage = a, this.tags = s || [], this.startTime = null, this.cancelCallback = null, this.changed = !0, this.deleted = !1, this.chartFromStatement = !1, this.chartStatementWarnings = [], this.chartLayers = null, this.completionSymbols = [], this.remoteStoreId = c, this.remotePath = a === "remote" ? x(l || this.name, r) : l, this.remoteOriginalPath = u, this.remotePersisted = d;
|
|
102
102
|
}
|
|
103
103
|
getAutocomplete(e) {
|
|
104
104
|
return this.completionSymbols.filter((t) => t.label.startsWith(e));
|
|
105
105
|
}
|
|
106
|
-
setError(
|
|
107
|
-
this.error =
|
|
106
|
+
setError(e) {
|
|
107
|
+
this.error = e, e && (this.results = new t(/* @__PURE__ */ new Map(), []), this.changed = !0);
|
|
108
108
|
}
|
|
109
109
|
setContent(e) {
|
|
110
110
|
this.contents !== e && (this.contents = e, this.changed = !0);
|
|
111
111
|
}
|
|
112
112
|
setName(e) {
|
|
113
|
-
let t = this.storage === "remote" ?
|
|
113
|
+
let t = this.storage === "remote" ? x(e, this.type) : e;
|
|
114
114
|
if (this.name === t) return;
|
|
115
115
|
if (this.changed = !0, this.storage === "remote") {
|
|
116
116
|
let e = this.remotePath || this.name;
|
|
117
117
|
!this.remoteOriginalPath && this.remotePersisted && e !== t && (this.remoteOriginalPath = e), this.remotePath = t;
|
|
118
118
|
}
|
|
119
119
|
this.name = t;
|
|
120
|
-
let n =
|
|
120
|
+
let n = S(this.name);
|
|
121
121
|
n && this.type !== n && (this.type = n);
|
|
122
122
|
}
|
|
123
123
|
setConnection(e) {
|
|
124
|
-
this.connection !== e && (this.connection = e, this.connectionId =
|
|
124
|
+
this.connection !== e && (this.connection = e, this.connectionId = Ye({
|
|
125
125
|
connection: e,
|
|
126
126
|
storage: this.storage,
|
|
127
127
|
remoteStoreId: this.remoteStoreId
|
|
@@ -177,7 +177,7 @@ var Ie = class t {
|
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
static fromJSON(n) {
|
|
180
|
-
let r = typeof n == "string" ? JSON.parse(n) : n, i = new
|
|
180
|
+
let r = typeof n == "string" ? JSON.parse(n) : n, i = new e({
|
|
181
181
|
id: r.id || r.name || "",
|
|
182
182
|
name: r.name || "",
|
|
183
183
|
type: r.type || "trilogy",
|
|
@@ -189,12 +189,12 @@ var Ie = class t {
|
|
|
189
189
|
remoteOriginalPath: r.remoteOriginalPath || null,
|
|
190
190
|
remotePersisted: r.remotePersisted || !1
|
|
191
191
|
});
|
|
192
|
-
return i.syntax = r.syntax || "preql", i.results = r.results ?
|
|
192
|
+
return i.syntax = r.syntax || "preql", i.results = r.results ? t.fromJSON(r.results) : new t(/* @__PURE__ */ new Map(), []), i.loading = r.loading || !1, i.error = r.error || null, i.status_code = r.status_code || 200, i.duration = r.duration || null, i.generated_sql = r.generated_sql || null, i.executed_contents = r.executed_contents || null, i.changed = !1, i.tags = r.tags ? r.tags.map((e) => Object.values(w).includes(e) ? e : null).filter((e) => e !== null) : [], i.chartConfig = r.chartConfig || void 0, i.remoteStoreId = r.remoteStoreId || null, i.remotePath = r.remotePath || null, i.remoteOriginalPath = r.remoteOriginalPath || null, i.remotePersisted = r.remotePersisted || !1, i;
|
|
193
193
|
}
|
|
194
194
|
};
|
|
195
195
|
//#endregion
|
|
196
196
|
//#region editors/helpers.ts
|
|
197
|
-
function
|
|
197
|
+
function Ze(e, t, n, r) {
|
|
198
198
|
let i = [], a = /* @__PURE__ */ new Set(), o = e.reduce((e, t) => (e[t.id] = t, e), {}), s = Object.values(t).sort((e, t) => {
|
|
199
199
|
let n = e.storage.localeCompare(t.storage);
|
|
200
200
|
if (n !== 0) return n;
|
|
@@ -301,18 +301,921 @@ function Le(e, t, n, r) {
|
|
|
301
301
|
}), i;
|
|
302
302
|
}
|
|
303
303
|
//#endregion
|
|
304
|
-
//#region
|
|
305
|
-
var
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
//#region stores/modelStore.ts
|
|
305
|
+
var T = b("models", {
|
|
306
|
+
state: () => ({ models: {} }),
|
|
307
|
+
getters: {
|
|
308
|
+
modelList: (e) => Object.keys(e.models).map((t) => e.models[t]),
|
|
309
|
+
unsavedModels: (e) => Object.values(e.models).filter((e) => e.changed).length
|
|
310
|
+
},
|
|
311
|
+
actions: {
|
|
312
|
+
newModelConfig(e, t = !1) {
|
|
313
|
+
let n = new ce({
|
|
314
|
+
name: e,
|
|
315
|
+
storage: "local",
|
|
316
|
+
sources: [],
|
|
317
|
+
description: ""
|
|
318
|
+
});
|
|
319
|
+
if (e in this.models && !t) throw Error(`ModelConfig with ${e} already exists.`);
|
|
320
|
+
return this.models[n.name] = n, n;
|
|
321
|
+
},
|
|
322
|
+
addModelConfig(e) {
|
|
323
|
+
this.models[e.name] = e;
|
|
324
|
+
},
|
|
325
|
+
removeModelConfig(e) {
|
|
326
|
+
if (this.models[e]) L().connectionList.forEach((t) => {
|
|
327
|
+
t.model === e && (t.model = null, t.changed = !0);
|
|
328
|
+
}), delete this.models[e];
|
|
329
|
+
else throw Error(`ModelConfig with name "${e}" not found.`);
|
|
330
|
+
},
|
|
331
|
+
updateModelName(e, t) {
|
|
332
|
+
e !== t && (console.log(`Renaming model from ${e} to ${t}`), L().connectionList.forEach((n) => {
|
|
333
|
+
n.model === e && (n.model = t, n.changed = !0);
|
|
334
|
+
}), this.models[t] = this.models[e], this.models[t].name = t, this.models[t].changed = !0, delete this.models[e]);
|
|
335
|
+
},
|
|
336
|
+
addEditorAsModelSource(e, t) {
|
|
337
|
+
this.addModelConfigSource(e, new se(t.id, t.name, [], []));
|
|
338
|
+
},
|
|
339
|
+
addModelConfigSource(e, t) {
|
|
340
|
+
if (this.models[e]) this.models[e].sources.push(t);
|
|
341
|
+
else throw Error(`ModelConfig with name "${e}" not found.`);
|
|
342
|
+
},
|
|
343
|
+
removeModelConfigSource(e, t) {
|
|
344
|
+
if (this.models[e]) {
|
|
345
|
+
let n = this.models[e];
|
|
346
|
+
n.sources = n.sources.filter((e) => e.alias !== t);
|
|
347
|
+
} else throw Error(`ModelConfig with name "${e}" not found.`);
|
|
348
|
+
},
|
|
349
|
+
setModelConfigParseResults(e, t) {
|
|
350
|
+
if (this.models[e]) {
|
|
351
|
+
let n = this.models[e];
|
|
352
|
+
n.setParseResults(t), n.sources = [...n.sources], this.models = { ...this.models };
|
|
353
|
+
} else throw Error(`ModelConfig with name "${e}" not found.`);
|
|
354
|
+
},
|
|
355
|
+
setModelParseError(e, t) {
|
|
356
|
+
if (this.models[e]) this.models[e].setParseError(t), this.models = { ...this.models };
|
|
357
|
+
else throw Error(`ModelConfig with name "${e}" not found.`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}), Qe = class {
|
|
361
|
+
type;
|
|
362
|
+
constructor() {
|
|
363
|
+
this.type = "abstract";
|
|
364
|
+
}
|
|
365
|
+
async saveProjects(e) {}
|
|
366
|
+
async loadProjects() {
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
369
|
+
async deleteProject(e) {}
|
|
370
|
+
async clearProjects() {}
|
|
371
|
+
}, $e = (e) => new Promise((t) => setTimeout(t, e)), et = /* @__PURE__ */ new Set(), tt = /* @__PURE__ */ new Set(), nt = (e) => {
|
|
372
|
+
if (et.has(e)) return !0;
|
|
373
|
+
let t = e;
|
|
374
|
+
e.includes("://") || (t = `http://${e}`);
|
|
375
|
+
try {
|
|
376
|
+
let e = new URL(t), n = e.host, r = e.hostname;
|
|
377
|
+
if (tt.has(n) || tt.has(r)) return !0;
|
|
378
|
+
} catch {}
|
|
379
|
+
return !1;
|
|
380
|
+
}, E = async (e, t, n = 5, r = 1e3) => {
|
|
381
|
+
if (nt(e)) throw Error(`Cannot connect to ${e} - blocked by Content Security Policy. This URL is not allowed by the browser's security settings.`);
|
|
382
|
+
let i = 0, a = r;
|
|
383
|
+
for (;;) try {
|
|
384
|
+
let r = await fetch(e, t);
|
|
385
|
+
if (r.status === 429 && i < n) {
|
|
386
|
+
let e = r.headers.get("Retry-After"), t = e ? parseInt(e) * 1e3 : a;
|
|
387
|
+
console.log(`Rate limited. Retrying after ${t}ms (Attempt ${i + 1}/${n})`), await $e(t), a = a * 2 * (.8 + Math.random() * .4), i++;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
return r;
|
|
391
|
+
} catch (t) {
|
|
392
|
+
if (nt(e)) throw Error(`Cannot connect to ${e} - blocked by Content Security Policy. This URL is not allowed by the browser's security settings.`);
|
|
393
|
+
let r = t instanceof Error ? t.message : String(t);
|
|
394
|
+
if (t instanceof TypeError || r.includes("Failed to fetch") || r.includes("NetworkError") || r.includes("ERR_CONNECTION_REFUSED") || r.includes("Load failed") || r.includes("network connection was lost") || r.includes("Could not connect to the server") || r.includes("fetch failed") || i >= n) throw t;
|
|
395
|
+
console.log(`Network error, retrying after ${a}ms (Attempt ${i + 1}/${n})`), await $e(a), a = a * 2 * (.8 + Math.random() * .4), i++;
|
|
396
|
+
}
|
|
397
|
+
}, rt = (e, t, n, r, i) => e.filter((e) => {
|
|
398
|
+
let a = e.name.toLowerCase().includes(t.toLowerCase()), o = !n || e.engine === n, s = !0;
|
|
399
|
+
if (r !== "all") {
|
|
400
|
+
let t = i(e.name);
|
|
401
|
+
s = r === "imported" && t || r === "not-imported" && !t;
|
|
402
|
+
}
|
|
403
|
+
return a && o && s;
|
|
404
|
+
}), it = (e) => {
|
|
405
|
+
switch (e) {
|
|
406
|
+
case "bigquery": return "new-bigquery-oauth";
|
|
407
|
+
case "duckdb": return "new-duckdb";
|
|
408
|
+
default: return `new-${e}`;
|
|
409
|
+
}
|
|
410
|
+
}, at = (e) => {
|
|
411
|
+
let t = /* @__PURE__ */ new Set();
|
|
412
|
+
return e.forEach((e) => {
|
|
413
|
+
e.engine && t.add(e.engine);
|
|
414
|
+
}), Array.from(t).sort();
|
|
415
|
+
}, ot = (e) => {
|
|
416
|
+
if (e) return { headers: { "X-Trilogy-Token": e } };
|
|
417
|
+
}, st = async (e) => {
|
|
418
|
+
let t = await E(`${e.baseUrl}/index.json`, ot(e.token));
|
|
419
|
+
if (!t.ok) throw Error(`Failed to fetch store index: ${t.status} ${t.statusText}`);
|
|
420
|
+
return t.json();
|
|
421
|
+
}, ct = async (e) => {
|
|
422
|
+
let t = null, n = [];
|
|
423
|
+
try {
|
|
424
|
+
let t = (await st(e)).models.map(async (t) => {
|
|
425
|
+
try {
|
|
426
|
+
let n = await E(t.url, ot(e.token));
|
|
427
|
+
if (!n.ok) return console.warn(`Failed to fetch model ${t.name}: ${n.statusText}`), null;
|
|
428
|
+
let r = await n.json();
|
|
429
|
+
return r.downloadUrl = t.url, r.store = e, r;
|
|
430
|
+
} catch (e) {
|
|
431
|
+
return console.warn(`Error fetching model ${t.name}:`, e), null;
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
n = (await Promise.all(t)).filter((e) => e !== null);
|
|
435
|
+
} catch (e) {
|
|
436
|
+
t = e instanceof Error ? e.message : "Error fetching store data", console.error("Error fetching from generic store:", e);
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
files: n,
|
|
440
|
+
error: t
|
|
441
|
+
};
|
|
442
|
+
}, lt = (e, t) => {
|
|
443
|
+
try {
|
|
444
|
+
return new URL(e, t).toString();
|
|
445
|
+
} catch {
|
|
446
|
+
return e;
|
|
447
|
+
}
|
|
448
|
+
}, ut = (e, t) => {
|
|
449
|
+
if (!e || typeof e != "object") throw Error("Store index is not a JSON object");
|
|
450
|
+
let n = e, r;
|
|
451
|
+
if (Array.isArray(n.models)) r = n.models;
|
|
452
|
+
else if (Array.isArray(n.files)) r = n.files.filter((e) => typeof e.filename == "string" && e.filename.endsWith(".json")).map((e) => ({
|
|
453
|
+
name: e.name || e.filename.replace(/\.json$/, ""),
|
|
454
|
+
url: e.filename,
|
|
455
|
+
engine: e.engine,
|
|
456
|
+
description: e.description,
|
|
457
|
+
tags: e.tags
|
|
458
|
+
}));
|
|
459
|
+
else throw Error("Store index has neither `models` nor `files`");
|
|
460
|
+
return {
|
|
461
|
+
name: typeof n.name == "string" ? n.name : void 0,
|
|
462
|
+
updated_at: typeof n.updated_at == "string" ? n.updated_at : void 0,
|
|
463
|
+
generation: typeof n.generation == "number" ? n.generation : void 0,
|
|
464
|
+
models: r.filter((e) => e && typeof e.url == "string").map((e) => ({
|
|
465
|
+
...e,
|
|
466
|
+
url: lt(e.url, t)
|
|
467
|
+
}))
|
|
468
|
+
};
|
|
469
|
+
}, dt = (e, t) => (Array.isArray(e.components) && (e.components = e.components.map((e) => ({
|
|
470
|
+
...e,
|
|
471
|
+
url: lt(e.url, t)
|
|
472
|
+
}))), e), ft = (e) => `${e.baseUrl.replace(/\/$/, "")}/index.json`, pt = async (e) => {
|
|
473
|
+
let t = null, n = [];
|
|
474
|
+
try {
|
|
475
|
+
let t = ft(e), r = await E(t);
|
|
476
|
+
if (!r.ok) throw Error(`Failed to fetch store index: ${r.status} ${r.statusText}`);
|
|
477
|
+
let i = ut(await r.json(), t).models.map(async (t) => {
|
|
478
|
+
let n = await E(t.url);
|
|
479
|
+
if (!n.ok) throw Error(`Error fetching model ${t.name}: ${n.statusText}`);
|
|
480
|
+
let r = dt(await n.json(), t.url);
|
|
481
|
+
return r.downloadUrl = t.url, r.store = e, r;
|
|
482
|
+
});
|
|
483
|
+
n = await Promise.all(i);
|
|
484
|
+
} catch (e) {
|
|
485
|
+
t = e instanceof Error ? e.message : "Error fetching files", console.error("Error fetching from static store:", e);
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
files: n,
|
|
489
|
+
error: t
|
|
490
|
+
};
|
|
491
|
+
}, mt = async (e) => e.type === "static" ? pt(e) : ct(e), ht = async (e, t) => {
|
|
492
|
+
let n = {}, r = {};
|
|
493
|
+
return await Promise.all(e.map(async (e) => {
|
|
494
|
+
try {
|
|
495
|
+
let { files: i, error: a } = await mt(e);
|
|
496
|
+
n[e.id] = i, a && (r[e.id] = a), t && t(e.id, {
|
|
497
|
+
files: i,
|
|
498
|
+
error: a
|
|
499
|
+
});
|
|
500
|
+
} catch (i) {
|
|
501
|
+
let a = i instanceof Error ? i.message : "Unknown error";
|
|
502
|
+
r[e.id] = a, n[e.id] = [], t && t(e.id, {
|
|
503
|
+
files: [],
|
|
504
|
+
error: a
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
})), {
|
|
508
|
+
filesByStore: n,
|
|
509
|
+
errors: r
|
|
510
|
+
};
|
|
511
|
+
}, gt = {
|
|
512
|
+
stale: 3,
|
|
513
|
+
unknown: 2,
|
|
514
|
+
fresh: 1
|
|
515
|
+
}, D = (e) => gt[e] ?? 0, _t = (e) => e.observed_watermarks.reduce((e, t) => e ? t.probed_at > e.probed_at ? t : e : t, null), vt = (e) => {
|
|
516
|
+
let t = e.datasources.reduce((e, t) => !e || D(t.status) > D(e) ? t.status : e, null);
|
|
517
|
+
return t && D(t) > D(e.status) ? t : e.status;
|
|
518
|
+
}, yt = (e) => e.partition_by.map((e) => e.column), bt = (e) => {
|
|
519
|
+
let t = Object.entries(e.values).map(([e, t]) => `${e}=${t ?? "—"}`);
|
|
520
|
+
return t.length ? t.join(", ") : e.partition_id;
|
|
521
|
+
}, xt = (e) => {
|
|
522
|
+
let t = {
|
|
523
|
+
total: e.partitions.length,
|
|
524
|
+
fresh: 0,
|
|
525
|
+
stale: 0,
|
|
526
|
+
unknown: 0,
|
|
527
|
+
missing: 0,
|
|
528
|
+
rowCount: null,
|
|
529
|
+
complete: e.partitions_complete
|
|
530
|
+
};
|
|
531
|
+
return e.partitions.forEach((e) => {
|
|
532
|
+
e.status === "fresh" ? t.fresh += 1 : e.status === "stale" ? t.stale += 1 : t.unknown += 1, e.expected && !e.observed && (t.missing += 1), typeof e.row_count == "number" && (t.rowCount = (t.rowCount ?? 0) + e.row_count);
|
|
533
|
+
}), t;
|
|
534
|
+
}, St = (e) => [...e].sort((e, t) => {
|
|
535
|
+
let n = D(t.status) - D(e.status);
|
|
536
|
+
if (n !== 0) return n;
|
|
537
|
+
let r = Number(!e.observed) - Number(!t.observed);
|
|
538
|
+
return r === 0 ? e.partition_id.localeCompare(t.partition_id) : -r;
|
|
539
|
+
}), Ct = (e) => [...e].sort((e, t) => {
|
|
540
|
+
let n = D(vt(t)) - D(vt(e));
|
|
541
|
+
return n === 0 ? e.address.localeCompare(t.address) : n;
|
|
542
|
+
}), wt = "::", Tt = (e, t) => `${e}${wt}${t || "."}`, Et = (e) => {
|
|
543
|
+
let t = e.indexOf(wt);
|
|
544
|
+
return t === -1 ? null : {
|
|
545
|
+
storeId: e.slice(0, t),
|
|
546
|
+
target: e.slice(t + 2)
|
|
547
|
+
};
|
|
548
|
+
}, O = (e) => e || ".", Dt = (e, t) => {
|
|
549
|
+
let n = O(e), r = O(t);
|
|
550
|
+
return n === r || n === "." || r.startsWith(`${n}/`);
|
|
551
|
+
}, Ot = class extends Error {
|
|
552
|
+
status;
|
|
553
|
+
constructor(e, t) {
|
|
554
|
+
super(e), this.name = "JobsServiceError", this.status = t;
|
|
555
|
+
}
|
|
556
|
+
}, k = (e, t = {}) => {
|
|
557
|
+
let n = new Headers(t.headers);
|
|
558
|
+
return e && n.set("X-Trilogy-Token", e), {
|
|
559
|
+
...t,
|
|
560
|
+
headers: n
|
|
561
|
+
};
|
|
562
|
+
}, kt = (e) => e.split("/").filter(Boolean).map((e) => encodeURIComponent(e)).join("/"), A = async (e, t) => {
|
|
563
|
+
if (e.ok) return e;
|
|
564
|
+
let n = "";
|
|
565
|
+
try {
|
|
566
|
+
if ((e.headers.get("content-type") || "").includes("application/json")) {
|
|
567
|
+
let t = await e.json();
|
|
568
|
+
n = typeof t?.detail == "string" ? t.detail : typeof t?.message == "string" ? t.message : JSON.stringify(t);
|
|
569
|
+
} else n = await e.text();
|
|
570
|
+
} catch {
|
|
571
|
+
n = "";
|
|
572
|
+
}
|
|
573
|
+
throw new Ot(n || t, e.status);
|
|
574
|
+
}, At = async (e) => {
|
|
575
|
+
let t = await fetch(`${e.baseUrl}/files`, k(e.token, { method: "GET" }));
|
|
576
|
+
return await A(t, `Failed to fetch files for ${e.name}`), t.json();
|
|
577
|
+
}, jt = async (e, t) => {
|
|
578
|
+
let n = kt(t), r = await fetch(`${e.baseUrl}/files/${n}`, k(e.token, { method: "GET" }));
|
|
579
|
+
return await A(r, `Failed to fetch ${t}`), r.text();
|
|
580
|
+
}, Mt = async (e, t, n) => {
|
|
581
|
+
let r = await fetch(`${e.baseUrl}/files`, k(e.token, {
|
|
582
|
+
method: "POST",
|
|
583
|
+
headers: { "Content-Type": "application/json" },
|
|
584
|
+
body: JSON.stringify({
|
|
585
|
+
path: t,
|
|
586
|
+
content: n
|
|
587
|
+
})
|
|
588
|
+
}));
|
|
589
|
+
if (r.status === 409) {
|
|
590
|
+
await Nt(e, t, n);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
await A(r, `Failed to create ${t}`);
|
|
594
|
+
}, Nt = async (e, t, n) => {
|
|
595
|
+
let r = await fetch(`${e.baseUrl}/files/${kt(t)}`, k(e.token, {
|
|
596
|
+
method: "PUT",
|
|
597
|
+
headers: { "Content-Type": "application/json" },
|
|
598
|
+
body: JSON.stringify({ content: n })
|
|
599
|
+
}));
|
|
600
|
+
if (r.status === 404) {
|
|
601
|
+
await A(await fetch(`${e.baseUrl}/files`, k(e.token, {
|
|
602
|
+
method: "POST",
|
|
603
|
+
headers: { "Content-Type": "application/json" },
|
|
604
|
+
body: JSON.stringify({
|
|
605
|
+
path: t,
|
|
606
|
+
content: n
|
|
607
|
+
})
|
|
608
|
+
})), `Failed to update ${t}`);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
await A(r, `Failed to update ${t}`);
|
|
612
|
+
}, Pt = async (e, t) => {
|
|
613
|
+
let n = await fetch(`${e.baseUrl}/files/${kt(t)}`, k(e.token, { method: "DELETE" }));
|
|
614
|
+
n.status !== 404 && await A(n, `Failed to delete ${t}`);
|
|
615
|
+
}, Ft = async (e, t, n = !1) => {
|
|
616
|
+
let r = new URLSearchParams({ target: O(t) });
|
|
617
|
+
n && r.set("refresh", "true");
|
|
618
|
+
let i = await fetch(`${e.baseUrl}/state?${r.toString()}`, k(e.token, { method: "GET" }));
|
|
619
|
+
await A(i, `Failed to fetch state for ${O(t)}`);
|
|
620
|
+
let a = i.headers.get("X-Trilogy-Cached");
|
|
621
|
+
return {
|
|
622
|
+
snapshot: await i.json(),
|
|
623
|
+
cached: a === null ? null : a.toLowerCase() === "true",
|
|
624
|
+
computedAt: i.headers.get("X-Trilogy-Computed-At")
|
|
625
|
+
};
|
|
626
|
+
}, It = async (e, t, n) => {
|
|
627
|
+
let r = await fetch(`${e.baseUrl}/${t}`, k(e.token, {
|
|
628
|
+
method: "POST",
|
|
629
|
+
headers: { "Content-Type": "application/json" },
|
|
630
|
+
body: JSON.stringify({ target: n })
|
|
631
|
+
}));
|
|
632
|
+
return await A(r, `Failed to ${t} ${n}`), r.json();
|
|
633
|
+
}, Lt = async (e, t) => {
|
|
634
|
+
let n = await fetch(`${e.baseUrl}/jobs/${t}`, k(e.token, { method: "GET" }));
|
|
635
|
+
return await A(n, `Failed to fetch job ${t}`), n.json();
|
|
636
|
+
}, Rt = async (e, t) => {
|
|
637
|
+
let n = await fetch(`${e.baseUrl}/jobs/${t}/cancel`, k(e.token, { method: "POST" }));
|
|
638
|
+
return await A(n, `Failed to cancel job ${t}`), n.json();
|
|
639
|
+
}, zt = (e) => e.trim().replace(/[\\/:*?"<>|]+/g, "-").replace(/\s+/g, " "), j = (e) => e.replace(/\/$/, ""), M = (e) => j(e).replace(/^https?:\/\//, "").replace(/\//g, "-"), N = (e) => {
|
|
640
|
+
try {
|
|
641
|
+
let t = new URL(j(e));
|
|
642
|
+
return zt(t.hostname + (t.port ? `:${t.port}` : "") || t.host || e);
|
|
643
|
+
} catch {
|
|
644
|
+
return zt(j(e));
|
|
645
|
+
}
|
|
646
|
+
}, Bt = (e, t, n) => {
|
|
647
|
+
let r = j(e.trim());
|
|
648
|
+
return {
|
|
649
|
+
type: "generic",
|
|
650
|
+
id: M(r),
|
|
651
|
+
name: t || N(r),
|
|
652
|
+
baseUrl: r,
|
|
653
|
+
token: n || void 0
|
|
654
|
+
};
|
|
655
|
+
}, Vt = (e) => zt(e.name || N(e.baseUrl)), Ht = (e) => `${Vt(e)}-connection`, Ut = (e) => Vt(e), Wt = (e) => e.replace(/\.[^.]+$/, ""), Gt = (e) => e.flatMap((e) => e.files.map((t) => e.directory ? `${e.directory}/${t}` : t)), Kt = class extends Qe {
|
|
656
|
+
type;
|
|
657
|
+
communityStore;
|
|
658
|
+
constructor(e) {
|
|
659
|
+
super(), this.communityStore = e, this.type = "remote";
|
|
660
|
+
}
|
|
661
|
+
getGenericStores() {
|
|
662
|
+
return this.communityStore.stores.filter((e) => e.type === "generic");
|
|
663
|
+
}
|
|
664
|
+
getStoreById(e) {
|
|
665
|
+
return this.getGenericStores().find((t) => t.id === e) || null;
|
|
666
|
+
}
|
|
667
|
+
buildEditorId(e, t) {
|
|
668
|
+
return `remote:${e.id}:${encodeURIComponent(t)}`;
|
|
669
|
+
}
|
|
670
|
+
async detectEngineForFallback(e) {
|
|
671
|
+
try {
|
|
672
|
+
return (await mt(e)).files[0]?.engine || "duck_db";
|
|
673
|
+
} catch {
|
|
674
|
+
return "duck_db";
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
buildRuntimeConnection(e, t, n, r, i) {
|
|
678
|
+
let a = r?.options || {}, o;
|
|
679
|
+
switch (r?.type) {
|
|
680
|
+
case "duckdb":
|
|
681
|
+
case "duck_db":
|
|
682
|
+
o = new Re(t, n);
|
|
683
|
+
break;
|
|
684
|
+
case "sqlite":
|
|
685
|
+
o = new Le(t, n);
|
|
686
|
+
break;
|
|
687
|
+
case "motherduck":
|
|
688
|
+
o = new Pe(t, "", n);
|
|
689
|
+
break;
|
|
690
|
+
case "bigquery":
|
|
691
|
+
o = new Fe(t, a.projectId || "", n);
|
|
692
|
+
break;
|
|
693
|
+
case "snowflake":
|
|
694
|
+
o = new Ne(t, {
|
|
695
|
+
account: a.account || "",
|
|
696
|
+
username: a.username || "",
|
|
697
|
+
privateKey: "",
|
|
698
|
+
warehouse: a.warehouse || "",
|
|
699
|
+
role: a.role,
|
|
700
|
+
database: a.database,
|
|
701
|
+
schema: a.schema
|
|
702
|
+
}, n);
|
|
703
|
+
break;
|
|
704
|
+
default: return r?.type && console.warn(`Remote store "${e.name}" advertised unknown connection type "${r.type}". Falling back to browse-only RemoteProjectConnection.`), new Me(t, e.id, i, n);
|
|
705
|
+
}
|
|
706
|
+
return o.remoteStoreId = e.id, o.storage = "remote", o.recomputeId(), o.model = n, o;
|
|
707
|
+
}
|
|
708
|
+
async loadStore(e) {
|
|
709
|
+
let t = this.getStoreById(e);
|
|
710
|
+
if (!t) return {
|
|
711
|
+
editors: {},
|
|
712
|
+
connections: {},
|
|
713
|
+
models: {}
|
|
714
|
+
};
|
|
715
|
+
let n = {
|
|
716
|
+
editors: {},
|
|
717
|
+
connections: {},
|
|
718
|
+
models: {}
|
|
719
|
+
}, [r, i] = await Promise.all([st(t).catch((e) => (console.warn(`Failed to fetch /index.json for store "${t.name}":`, e), null)), At(t)]), a = r?.connection ?? null, o = Ht(t), s = Ut(t), c = new Set(r?.startup_scripts ?? []), l = Gt(i.directories), u = l.filter((e) => S(e) !== null);
|
|
720
|
+
(await Promise.all(u.map(async (e) => ({
|
|
721
|
+
path: e,
|
|
722
|
+
content: await jt(t, e)
|
|
723
|
+
})))).forEach(({ path: e, content: r }) => {
|
|
724
|
+
let i = S(e);
|
|
725
|
+
if (!i) return;
|
|
726
|
+
let a = [];
|
|
727
|
+
Ge(i) && a.push(w.SOURCE), c.has(e) && a.push(w.STARTUP_SCRIPT);
|
|
728
|
+
let s = ze(new Xe({
|
|
729
|
+
id: this.buildEditorId(t, e),
|
|
730
|
+
name: e,
|
|
731
|
+
type: i,
|
|
732
|
+
connection: o,
|
|
733
|
+
storage: "remote",
|
|
734
|
+
contents: r,
|
|
735
|
+
tags: a,
|
|
736
|
+
remoteStoreId: t.id,
|
|
737
|
+
remotePath: e,
|
|
738
|
+
remotePersisted: !0
|
|
739
|
+
}));
|
|
740
|
+
s.changed = !1, n.editors[s.id] = s;
|
|
741
|
+
});
|
|
742
|
+
let d;
|
|
743
|
+
if (a && a.type) d = this.buildRuntimeConnection(t, o, s, a, a.type);
|
|
744
|
+
else {
|
|
745
|
+
let e = await this.detectEngineForFallback(t);
|
|
746
|
+
e && e !== "duck_db" && e !== "duckdb" && console.warn(`Remote store "${t.name}" did not declare a runtime connection but its model engine is "${e}". Queries will not run until /index.json includes a connection block.`), d = new Me(o, t.id, e, s);
|
|
747
|
+
}
|
|
748
|
+
let f = ze(d);
|
|
749
|
+
f.changed = !1, n.connections[o] = f;
|
|
750
|
+
let p = ze(new ce({
|
|
751
|
+
name: s,
|
|
752
|
+
storage: "remote",
|
|
753
|
+
description: `${Vt(t)} remote project`,
|
|
754
|
+
sources: l.filter((e) => Be(e) === ".preql").map((e) => new se(this.buildEditorId(t, e), Wt(e), [], []))
|
|
755
|
+
}));
|
|
756
|
+
return p.changed = !1, n.models[p.name] = p, n;
|
|
757
|
+
}
|
|
758
|
+
async saveEditor(e) {
|
|
759
|
+
await this.saveEditors([e]);
|
|
760
|
+
}
|
|
761
|
+
async saveEditors(e) {
|
|
762
|
+
for (let t of e) {
|
|
763
|
+
if (!t.remoteStoreId) continue;
|
|
764
|
+
let e = this.getStoreById(t.remoteStoreId);
|
|
765
|
+
if (!e) continue;
|
|
766
|
+
let n = t.remotePath || t.name, r = t.remoteOriginalPath;
|
|
767
|
+
if (t.deleted) {
|
|
768
|
+
(t.remotePersisted || r) && await Pt(e, r || n), t.changed = !1;
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
t.changed &&= (r && r !== n ? (await Mt(e, n, t.contents), await Pt(e, r)) : t.remotePersisted ? await Nt(e, n, t.contents) : await Mt(e, n, t.contents), t.remotePath = n, t.remoteOriginalPath = null, t.remotePersisted = !0, !1);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
async loadEditors() {
|
|
775
|
+
let e = {}, t = this.getGenericStores();
|
|
776
|
+
return await Promise.allSettled(t.map(async (t) => {
|
|
777
|
+
Object.assign(e, (await this.loadStore(t.id)).editors);
|
|
778
|
+
})), e;
|
|
779
|
+
}
|
|
780
|
+
async deleteEditor(e) {}
|
|
781
|
+
async clearEditors() {}
|
|
782
|
+
async saveConnections(e) {
|
|
783
|
+
e.forEach((e) => {
|
|
784
|
+
e.changed = !1;
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
async loadConnections() {
|
|
788
|
+
let e = {}, t = this.getGenericStores();
|
|
789
|
+
return await Promise.allSettled(t.map(async (t) => {
|
|
790
|
+
Object.assign(e, (await this.loadStore(t.id)).connections);
|
|
791
|
+
})), e;
|
|
792
|
+
}
|
|
793
|
+
async deleteConnection(e) {}
|
|
794
|
+
async loadModelConfig() {
|
|
795
|
+
let e = {}, t = this.getGenericStores();
|
|
796
|
+
return await Promise.allSettled(t.map(async (t) => {
|
|
797
|
+
Object.assign(e, (await this.loadStore(t.id)).models);
|
|
798
|
+
})), e;
|
|
799
|
+
}
|
|
800
|
+
async saveModelConfig(e) {
|
|
801
|
+
e.forEach((e) => {
|
|
802
|
+
e.changed = !1;
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
clearModelConfig() {}
|
|
806
|
+
async saveLLMConnections(e) {}
|
|
807
|
+
async loadLLMConnections() {
|
|
808
|
+
return {};
|
|
809
|
+
}
|
|
810
|
+
async deleteLLMConnection(e) {}
|
|
811
|
+
async saveDashboards(e) {}
|
|
812
|
+
async loadDashboards() {
|
|
813
|
+
return {};
|
|
814
|
+
}
|
|
815
|
+
async deleteDashboard(e) {}
|
|
816
|
+
async clearDashboards() {}
|
|
817
|
+
async saveChats(e) {}
|
|
818
|
+
async loadChats() {
|
|
819
|
+
return {};
|
|
820
|
+
}
|
|
821
|
+
async deleteChat(e) {}
|
|
822
|
+
async clearChats() {}
|
|
823
|
+
}, P = {
|
|
824
|
+
type: "static",
|
|
825
|
+
id: "trilogy-data-trilogy-public-models-main",
|
|
826
|
+
name: "Trilogy Public Models",
|
|
827
|
+
baseUrl: "https://trilogy-data.github.io/trilogy-public-models/studio",
|
|
828
|
+
origin: {
|
|
829
|
+
kind: "github",
|
|
830
|
+
owner: "trilogy-data",
|
|
831
|
+
repo: "trilogy-public-models",
|
|
832
|
+
branch: "main"
|
|
833
|
+
}
|
|
834
|
+
}, qt = "trilogy-data", Jt = "trilogy-public-models", Yt = (e, t, n) => e === qt && t === Jt ? `https://${qt}.github.io/${Jt}/studio` : `https://raw.githubusercontent.com/${e}/${t}/${n}/studio`, Xt = (e, t, n) => `${e}-${t}-${n}`, Zt = (e, t, n, r) => {
|
|
835
|
+
let i = {
|
|
836
|
+
kind: "github",
|
|
837
|
+
owner: e,
|
|
838
|
+
repo: t,
|
|
839
|
+
branch: n
|
|
840
|
+
};
|
|
841
|
+
return {
|
|
842
|
+
type: "static",
|
|
843
|
+
id: Xt(e, t, n),
|
|
844
|
+
name: r || `${e}/${t}`,
|
|
845
|
+
baseUrl: Yt(e, t, n),
|
|
846
|
+
origin: i
|
|
847
|
+
};
|
|
848
|
+
}, Qt = (e, t) => {
|
|
849
|
+
let n = j(e.trim());
|
|
850
|
+
return {
|
|
851
|
+
type: "static",
|
|
852
|
+
id: M(n),
|
|
853
|
+
name: t || N(n),
|
|
854
|
+
baseUrl: n
|
|
855
|
+
};
|
|
856
|
+
}, $t = (e) => {
|
|
857
|
+
if (!e || typeof e != "object") return null;
|
|
858
|
+
let t = e;
|
|
859
|
+
if (t.type === "github") {
|
|
860
|
+
let e = Zt(t.owner, t.repo, t.branch, t.name);
|
|
861
|
+
return {
|
|
862
|
+
...e,
|
|
863
|
+
id: t.id || e.id
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
return t.type === "static" || t.type === "generic" ? t : null;
|
|
867
|
+
}, en = (e) => {
|
|
868
|
+
if (e.type === "static" && e.origin?.kind === "github") return `${e.origin.owner}/${e.origin.repo}@${e.origin.branch}`;
|
|
869
|
+
try {
|
|
870
|
+
return new URL(e.baseUrl).host;
|
|
871
|
+
} catch {
|
|
872
|
+
return e.baseUrl;
|
|
873
|
+
}
|
|
874
|
+
}, tn = "trilogy-community-stores", nn = (e) => {
|
|
875
|
+
let t = new URLSearchParams(window.location.search), n = t.get("store"), r = t.get("token");
|
|
876
|
+
if (!n || !r) return;
|
|
877
|
+
let i = j(n), a = e.find((e) => e.type === "generic" && j(e.baseUrl) === i);
|
|
878
|
+
a && !a.token && (a.token = r);
|
|
879
|
+
}, rn = (e) => {
|
|
880
|
+
let t = new URLSearchParams(window.location.search), n = t.get("store");
|
|
881
|
+
if (!n || t.get("kind") !== "static") return null;
|
|
882
|
+
let r;
|
|
883
|
+
try {
|
|
884
|
+
let e = new URL(n);
|
|
885
|
+
if (e.protocol !== "https:" && e.protocol !== "http:") return null;
|
|
886
|
+
r = Qt(n);
|
|
887
|
+
} catch {
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
return e.some((e) => e.id === r.id || j(e.baseUrl) === r.baseUrl) ? null : r;
|
|
891
|
+
}, an = b("communityApi", {
|
|
892
|
+
state: () => ({
|
|
893
|
+
stores: [P],
|
|
894
|
+
filesByStore: {},
|
|
895
|
+
errors: {},
|
|
896
|
+
storeStatus: { [P.id]: "idle" },
|
|
897
|
+
loading: !1,
|
|
898
|
+
showAddStoreModal: !1,
|
|
899
|
+
addingStore: !1
|
|
900
|
+
}),
|
|
901
|
+
getters: {
|
|
902
|
+
allFiles: (e) => {
|
|
903
|
+
let t = [];
|
|
904
|
+
return Object.values(e.filesByStore).forEach((e) => {
|
|
905
|
+
t.push(...e);
|
|
906
|
+
}), t;
|
|
907
|
+
},
|
|
908
|
+
availableEngines: (e) => {
|
|
909
|
+
let t = [];
|
|
910
|
+
return Object.values(e.filesByStore).forEach((e) => {
|
|
911
|
+
t.push(...e);
|
|
912
|
+
}), at(t);
|
|
913
|
+
},
|
|
914
|
+
hasErrors: (e) => Object.keys(e.errors).length > 0,
|
|
915
|
+
errorList: (e) => Object.entries(e.errors).map(([t, n]) => ({
|
|
916
|
+
root: t,
|
|
917
|
+
name: e.stores.find((e) => e.id === t)?.name || t,
|
|
918
|
+
error: n
|
|
919
|
+
}))
|
|
920
|
+
},
|
|
921
|
+
actions: {
|
|
922
|
+
loadStoresFromStorage() {
|
|
923
|
+
try {
|
|
924
|
+
let e = localStorage.getItem(tn), t = !1;
|
|
925
|
+
if (e) {
|
|
926
|
+
let n = JSON.parse(e), r = Array.isArray(n) ? n : [], i = r.map((e) => $t(e)).filter((e) => e !== null);
|
|
927
|
+
t = r.length !== i.length || r.some((e) => e?.type === "github");
|
|
928
|
+
let a = new Map(this.stores.map((e) => [e.id, e])), o = [P, ...i.map((e) => {
|
|
929
|
+
let t = a.get(e.id);
|
|
930
|
+
if (!t || t.type !== e.type) return e;
|
|
931
|
+
if (e.type === "generic") {
|
|
932
|
+
let n = t.type === "generic" ? t : null;
|
|
933
|
+
return {
|
|
934
|
+
...e,
|
|
935
|
+
...t,
|
|
936
|
+
token: n?.token || e.token
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
return {
|
|
940
|
+
...e,
|
|
941
|
+
...t
|
|
942
|
+
};
|
|
943
|
+
})].filter((e, t, n) => t === n.findIndex((t) => t.id === e.id));
|
|
944
|
+
nn(o), this.stores = o, o.forEach((e) => {
|
|
945
|
+
this.storeStatus[e.id] || (this.storeStatus[e.id] = "idle");
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
e || nn(this.stores);
|
|
949
|
+
let n = rn(this.stores);
|
|
950
|
+
n && (this.stores.push(n), this.storeStatus[n.id] = "idle", t = !0), t && this.saveStoresToStorage();
|
|
951
|
+
} catch (e) {
|
|
952
|
+
console.error("Error loading stores from localStorage:", e);
|
|
953
|
+
}
|
|
954
|
+
},
|
|
955
|
+
saveStoresToStorage() {
|
|
956
|
+
try {
|
|
957
|
+
let e = this.stores.filter((e) => e.id !== P.id);
|
|
958
|
+
localStorage.setItem(tn, JSON.stringify(e));
|
|
959
|
+
} catch (e) {
|
|
960
|
+
console.error("Error saving stores to localStorage:", e);
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
async fetchAllFiles() {
|
|
964
|
+
this.loading = !0;
|
|
965
|
+
for (let e of this.stores) this.storeStatus[e.id] = "idle";
|
|
966
|
+
try {
|
|
967
|
+
console.log(`Fetching community model files from ${this.stores.map((e) => e.id).join(", ")}...`);
|
|
968
|
+
let e = await ht(this.stores, (e, t) => {
|
|
969
|
+
this.filesByStore[e] = t.files, t.error ? (this.errors[e] = t.error, this.storeStatus[e] = "failed") : this.storeStatus[e] = "connected", console.log(`Store ${e} completed: ${t.error ? "failed" : "success"}`);
|
|
970
|
+
});
|
|
971
|
+
console.log("All stores fetched:", e);
|
|
972
|
+
} catch (e) {
|
|
973
|
+
console.error("Error fetching all model files:", e), this.errors = { general: e instanceof Error ? e.message : "Unknown error" };
|
|
974
|
+
} finally {
|
|
975
|
+
this.loading = !1;
|
|
976
|
+
}
|
|
977
|
+
},
|
|
978
|
+
async refreshData() {
|
|
979
|
+
await this.fetchAllFiles();
|
|
980
|
+
},
|
|
981
|
+
async fetchStoreFiles(e) {
|
|
982
|
+
let t = this.stores.find((t) => t.id === e);
|
|
983
|
+
if (t) {
|
|
984
|
+
this.loading = !0, this.storeStatus[e] = "idle";
|
|
985
|
+
try {
|
|
986
|
+
let n = await mt(t);
|
|
987
|
+
this.filesByStore[e] = n.files, n.error ? (this.errors[e] = n.error, this.storeStatus[e] = "failed") : (delete this.errors[e], this.storeStatus[e] = "connected");
|
|
988
|
+
} finally {
|
|
989
|
+
this.loading = !1;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
filteredFiles(e, t, n, r, i = null) {
|
|
994
|
+
let a = (e) => e in r.models, o = this.allFiles;
|
|
995
|
+
return i && (o = this.filesByStore[i]), o ? rt(o, e, t, n, a) : [];
|
|
996
|
+
},
|
|
997
|
+
getFilesByStore(e) {
|
|
998
|
+
return this.filesByStore[e] || [];
|
|
999
|
+
},
|
|
1000
|
+
async initialize() {
|
|
1001
|
+
this.loadStoresFromStorage(), await this.fetchAllFiles();
|
|
1002
|
+
},
|
|
1003
|
+
async addStore(e) {
|
|
1004
|
+
if (!e.baseUrl) throw Error("Base URL is required");
|
|
1005
|
+
if (e.baseUrl = j(e.baseUrl), e.id = e.id || M(e.baseUrl), e.name = e.name || N(e.baseUrl), this.stores.some((t) => t.id === e.id)) throw Error("This store is already added");
|
|
1006
|
+
this.addingStore = !0;
|
|
1007
|
+
try {
|
|
1008
|
+
return this.stores.push(e), this.saveStoresToStorage(), await this.fetchAllFiles(), !0;
|
|
1009
|
+
} catch (t) {
|
|
1010
|
+
console.error("Error adding store:", t);
|
|
1011
|
+
let n = this.stores.findIndex((t) => t.id === e.id);
|
|
1012
|
+
throw n > -1 && this.stores.splice(n, 1), t;
|
|
1013
|
+
} finally {
|
|
1014
|
+
this.addingStore = !1;
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
removeStore(e) {
|
|
1018
|
+
let t = this.stores.findIndex((t) => t.id === e);
|
|
1019
|
+
t > -1 && (this.stores.splice(t, 1), delete this.filesByStore[e], delete this.errors[e], this.saveStoresToStorage());
|
|
1020
|
+
},
|
|
1021
|
+
updateStoreToken(e, t) {
|
|
1022
|
+
let n = this.stores.find((t) => t.id === e);
|
|
1023
|
+
n && n.type === "generic" && (n.token = t || void 0, this.saveStoresToStorage());
|
|
1024
|
+
},
|
|
1025
|
+
openAddStoreModal() {
|
|
1026
|
+
this.showAddStoreModal = !0;
|
|
1027
|
+
},
|
|
1028
|
+
closeAddStoreModal() {
|
|
1029
|
+
this.showAddStoreModal = !1;
|
|
1030
|
+
},
|
|
1031
|
+
clearErrors() {
|
|
1032
|
+
this.errors = {};
|
|
1033
|
+
},
|
|
1034
|
+
clearStoreError(e) {
|
|
1035
|
+
delete this.errors[e], this.storeStatus[e] = "idle";
|
|
1036
|
+
},
|
|
1037
|
+
getStoreStatus(e) {
|
|
1038
|
+
return this.storeStatus[e] || "idle";
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}), on = /* @__PURE__ */ new Map();
|
|
1042
|
+
async function sn(e) {
|
|
1043
|
+
let t = T();
|
|
1044
|
+
if (t.models[e]) return !0;
|
|
1045
|
+
let n = on.get(e);
|
|
1046
|
+
if (n) return n;
|
|
1047
|
+
let r = an();
|
|
1048
|
+
r.stores.length <= 1 && r.loadStoresFromStorage();
|
|
1049
|
+
let i = r.stores.find((t) => t.type === "generic" && Ut(t) === e);
|
|
1050
|
+
if (!i) return !1;
|
|
1051
|
+
let a = (async () => {
|
|
1052
|
+
try {
|
|
1053
|
+
let n = await new Kt(r).loadStore(i.id), a = $();
|
|
1054
|
+
for (let e of Object.values(n.editors)) a.editors[e.id] || a.addEditor(e);
|
|
1055
|
+
for (let e of Object.values(n.models)) t.models[e.name] || t.addModelConfig(e);
|
|
1056
|
+
return !!t.models[e];
|
|
1057
|
+
} catch (t) {
|
|
1058
|
+
return console.warn(`Failed to rehydrate remote model "${e}":`, t), !1;
|
|
1059
|
+
} finally {
|
|
1060
|
+
on.delete(e);
|
|
1061
|
+
}
|
|
1062
|
+
})();
|
|
1063
|
+
return on.set(e, a), a;
|
|
1064
|
+
}
|
|
1065
|
+
//#endregion
|
|
1066
|
+
//#region stores/connectionStore.ts
|
|
1067
|
+
var F = /* @__PURE__ */ new Map(), I = 6e4;
|
|
1068
|
+
async function cn(e) {
|
|
1069
|
+
let t = $().getConnectionEditors(e.id, [w.STARTUP_SCRIPT]);
|
|
1070
|
+
await Promise.all(t.map(async (t) => {
|
|
1071
|
+
console.log(`running startup script ${t.name}`);
|
|
1072
|
+
try {
|
|
1073
|
+
await e.runScript(t.contents);
|
|
1074
|
+
} catch (n) {
|
|
1075
|
+
let r = t.remotePath || t.name, i = n instanceof Error ? n.message : String(n);
|
|
1076
|
+
throw Error(`Startup script "${r}" failed on connection "${e.name}":\n${i}`, { cause: n });
|
|
1077
|
+
}
|
|
1078
|
+
}));
|
|
1079
|
+
}
|
|
1080
|
+
function ln(e) {
|
|
1081
|
+
if (e.model && !T().models[e.model]) return sn(e.model);
|
|
1082
|
+
}
|
|
1083
|
+
var un = [
|
|
1084
|
+
{
|
|
1085
|
+
label: "DuckDB",
|
|
1086
|
+
value: "duckdb"
|
|
1087
|
+
},
|
|
1088
|
+
{
|
|
1089
|
+
label: "BigQuery (OAuth)",
|
|
1090
|
+
value: "bigquery-oauth"
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
label: "BigQuery (Service Account)",
|
|
1094
|
+
value: "bigquery"
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
label: "Snowflake (Key Pair Auth)",
|
|
1098
|
+
value: "snowflake"
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
label: "SQLite",
|
|
1102
|
+
value: "sqlite"
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
label: "MotherDuck (Token)",
|
|
1106
|
+
value: "motherduck"
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
label: "DuckDB (Native)",
|
|
1110
|
+
value: "remote-worker-duckdb"
|
|
1111
|
+
}
|
|
1112
|
+
], L = b("connections", {
|
|
1113
|
+
state: () => ({ connections: {} }),
|
|
1114
|
+
getters: {
|
|
1115
|
+
connectionList: (e) => Object.keys(e.connections).map((t) => e.connections[t]),
|
|
1116
|
+
unsavedConnections: (e) => Object.values(e.connections).filter((e) => e.changed).length,
|
|
1117
|
+
connectionByName: (e) => (t) => {
|
|
1118
|
+
let n = Object.values(e.connections).filter((e) => e.name === t);
|
|
1119
|
+
if (n.length !== 0) return n.find((e) => e.storage !== "remote") || n[0];
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
actions: {
|
|
1123
|
+
addConnection(e) {
|
|
1124
|
+
return this.connections[e.id] = e, e;
|
|
1125
|
+
},
|
|
1126
|
+
async connectConnection(e) {
|
|
1127
|
+
if (!this.connections[e]) throw Error(`Connection with id "${e}" not found.`);
|
|
1128
|
+
let t = `connect:${e}`;
|
|
1129
|
+
if (F.has(t)) return F.get(t);
|
|
1130
|
+
let n = new Promise((e, t) => {
|
|
1131
|
+
setTimeout(() => t(/* @__PURE__ */ Error(`Connection timed out after ${I / 1e3} seconds`)), I);
|
|
1132
|
+
}), r = Promise.race([(async () => {
|
|
1133
|
+
let t = ln(this.connections[e]);
|
|
1134
|
+
t && await t, await this.connections[e].reset(), await cn(this.connections[e]);
|
|
1135
|
+
})(), n]).catch((t) => {
|
|
1136
|
+
throw this.connections[e]?.setError?.(t instanceof Error ? t.message : String(t)), t;
|
|
1137
|
+
}).finally(() => {
|
|
1138
|
+
F.delete(t);
|
|
1139
|
+
});
|
|
1140
|
+
return F.set(t, r), r;
|
|
1141
|
+
},
|
|
1142
|
+
async resetConnection(e) {
|
|
1143
|
+
if (!this.connections[e]) throw Error(`Connection with id "${e}" not found.`);
|
|
1144
|
+
let t = `reset:${e}`;
|
|
1145
|
+
if (F.has(t)) return F.get(t);
|
|
1146
|
+
let n = new Promise((e, t) => {
|
|
1147
|
+
setTimeout(() => t(/* @__PURE__ */ Error(`Reset operation timed out after ${I / 1e3} seconds`)), I);
|
|
1148
|
+
}), r = ln(this.connections[e]), i = (r ? r.then(() => this.connections[e].reset()) : this.connections[e].reset()).then(() => cn(this.connections[e])), a = Promise.race([i, n]).catch((t) => {
|
|
1149
|
+
throw this.connections[e]?.setError?.(t instanceof Error ? t.message : String(t)), t;
|
|
1150
|
+
}).finally(() => {
|
|
1151
|
+
F.delete(t);
|
|
1152
|
+
});
|
|
1153
|
+
return F.set(t, a), a;
|
|
1154
|
+
},
|
|
1155
|
+
deleteConnection(e) {
|
|
1156
|
+
this.connections[e] && this.connections[e].delete();
|
|
1157
|
+
},
|
|
1158
|
+
purgeDeletedConnections() {
|
|
1159
|
+
for (let e of Object.keys(this.connections)) this.connections[e].deleted && delete this.connections[e];
|
|
1160
|
+
},
|
|
1161
|
+
connectionStateToStatus(e) {
|
|
1162
|
+
return e ? e.error ? "failed" : e.running ? "running" : e.connected ? "connected" : "disabled" : "disabled";
|
|
1163
|
+
},
|
|
1164
|
+
getConnectionSources(e) {
|
|
1165
|
+
let t = this.connections[e], n = T(), r = $();
|
|
1166
|
+
if (!t || !t.model) return [];
|
|
1167
|
+
let i = n.models[t.model];
|
|
1168
|
+
return i ? i.sources.map((e) => ({
|
|
1169
|
+
alias: e.alias,
|
|
1170
|
+
contents: r.editors[e.editor] ? r.editors[e.editor].contents : ""
|
|
1171
|
+
})) : (console.warn(`Connection "${t.name}" references model "${t.model}", which is not loaded; running with no model sources.`), []);
|
|
1172
|
+
},
|
|
1173
|
+
newConnection(t, n, r) {
|
|
1174
|
+
let i = e({
|
|
1175
|
+
name: t,
|
|
1176
|
+
storage: "local"
|
|
1177
|
+
});
|
|
1178
|
+
if (this.connections[i]) throw Error(`Connection with name "${t}" already exists.`);
|
|
1179
|
+
let a;
|
|
1180
|
+
if (n === "duckdb") a = new Re(t);
|
|
1181
|
+
else if (n === "sqlite") a = new Le(t);
|
|
1182
|
+
else if (n === "bigquery-oauth") a = new Fe(t, r.projectId);
|
|
1183
|
+
else if (n === "bigquery") a = new Fe(t, r.projectId);
|
|
1184
|
+
else if (n === "snowflake") a = new Ne(t, {
|
|
1185
|
+
account: r.account,
|
|
1186
|
+
username: r.username,
|
|
1187
|
+
privateKey: r.privateKey,
|
|
1188
|
+
warehouse: r.warehouse,
|
|
1189
|
+
role: r.role,
|
|
1190
|
+
database: r.database,
|
|
1191
|
+
schema: r.schema
|
|
1192
|
+
});
|
|
1193
|
+
else if (n === "motherduck") a = new Pe(t, r.mdToken, r.saveCredential);
|
|
1194
|
+
else if (n === "remote-worker-duckdb") a = new Ie(t, {
|
|
1195
|
+
driver: "duckdb",
|
|
1196
|
+
config: r.config ?? {},
|
|
1197
|
+
queryType: "duckdb"
|
|
1198
|
+
});
|
|
1199
|
+
else throw Error(`Connection type "${n}" not found.`);
|
|
1200
|
+
if (this.connections[a.id] = a, r.model) a.model = r.model;
|
|
1201
|
+
else {
|
|
1202
|
+
let e = T();
|
|
1203
|
+
a.model = e.newModelConfig(t).name;
|
|
1204
|
+
}
|
|
1205
|
+
return a;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}), dn = ["architect", "analyst"], fn = "You are an ANALYST subchat. Your job is to answer the overseer's question — run queries, build charts, surface findings.\n\nWhen done, call return_to_user with a summary written for the person reading the analysis, not for another engineer. Unless your task gives contradicting instructions:\n- Lead with the story in the data: the key insights, what they mean, and any caveats that change how they should be read (data gaps, small samples, definitional quirks).\n- Keep technical details — queries run, tables used, methodology, tool mechanics — out of the top summary. Put anything worth keeping in a short \"Technical notes\" section at the bottom.\n- Focus on the data and the narrative, not the how.", pn = "You are the OVERSEER of a Trilogy Explorer workspace. Your job is to coordinate work — never to query data directly.\n\nORCHESTRATION RULES:\n- You delegate work to two kinds of subchat: 'architect' (sets up data models from raw files — registers tables, defines Trilogy concepts) and 'analyst' (runs queries, builds charts, produces dashboards).\n- You have NO direct query tools. Always delegate via spawn_subchat.\n- Subchats run asynchronously. spawn_subchat returns immediately with a subchat id and 'running' status. When the subchat finishes, its summary appears in your conversation as a system-injected message and you'll be re-invoked to react.\n- You may follow up with a running OR finished subchat via send_to_subchat — useful for clarifying questions or asking it to extend its work.\n- list_subchats gives you the current snapshot at any time (also visible in the prompt above).\n- When you've handled the user's request and have nothing more to delegate or report, call return_to_user with a concise summary.\n\nDELEGATION GUIDELINES:\n- Architect subchats: use for \"set up a model\", \"load these files\", \"define concepts for X\", schema work.\n- Prefer to keep subchats scoped to a specific goal; only reuse a subchat when the new request overlaps with the existing work.\n- Analyst subchats: use for \"show me revenue trend\", \"build a dashboard\", \"what does the data look like\", any question that produces results or visuals.\n- Give subchats a complete, self-contained task description — they don't see your conversation with the user. Include any relevant file names, connection names, or constraints.\n\nREPORTS (analytical memos):\n- When the user asks for a \"report\", \"memo\", \"writeup\", \"analysis\", or anything that should produce a source-backed narrative deliverable rather than a free-form interactive board, use the create_report tool. This creates a new report-mode dashboard in the active project and queues an initial prompt for the report's dedicated authoring agent.\n- After create_report returns, tell the user the report is open in the sidebar; the dashboard chat panel attached to that report does the authoring and renders the executive memo + claim sections live as the agent works.\n- Do NOT delegate report authoring to an analyst subchat — analysts produce dashboards, the report agent produces narrative memos with provenance and confidence.\n";
|
|
1209
|
+
function mn(e) {
|
|
1210
|
+
let t = e.lastMessage ? ` — "${hn(e.lastMessage, 120)}"` : "";
|
|
308
1211
|
return ` - ${e.id} [${e.kind}] (${e.status})${t}`;
|
|
309
1212
|
}
|
|
310
|
-
function
|
|
1213
|
+
function hn(e, t) {
|
|
311
1214
|
return e.length <= t ? e : e.slice(0, t - 1) + "…";
|
|
312
1215
|
}
|
|
313
|
-
function
|
|
314
|
-
let { projectName: t, projectDescription: n, subchats: r, availableConnections: i, availableEditors: a, instructionsOverride: o } = e, s = r.length > 0 ? `ACTIVE SUBCHATS:\n${r.map(
|
|
315
|
-
return `${o?.trim() ||
|
|
1216
|
+
function gn(e) {
|
|
1217
|
+
let { projectName: t, projectDescription: n, subchats: r, availableConnections: i, availableEditors: a, instructionsOverride: o } = e, s = r.length > 0 ? `ACTIVE SUBCHATS:\n${r.map(mn).join("\n")}` : "No subchats spawned yet.", c = a.length > 0 ? `Attached files: ${a.join(", ")}` : "No files attached yet.";
|
|
1218
|
+
return `${o?.trim() || pn}
|
|
316
1219
|
|
|
317
1220
|
${`WORKSPACE: ${t || "unnamed"}${n ? `\n${n}` : ""}
|
|
318
1221
|
|
|
@@ -322,7 +1225,7 @@ DATA CONNECTIONS: ${i.length > 0 ? i.join(", ") : "none configured"}
|
|
|
322
1225
|
${s}`}
|
|
323
1226
|
`;
|
|
324
1227
|
}
|
|
325
|
-
var
|
|
1228
|
+
var _n = [
|
|
326
1229
|
{
|
|
327
1230
|
name: "spawn_subchat",
|
|
328
1231
|
description: "Delegate work to a new subchat. Returns immediately with the subchat's id; the subchat runs asynchronously and its summary is injected back into your conversation when it terminates. Use 'architect' for data model setup, 'analyst' for queries / analysis / charts.",
|
|
@@ -331,7 +1234,7 @@ var We = [
|
|
|
331
1234
|
properties: {
|
|
332
1235
|
kind: {
|
|
333
1236
|
type: "string",
|
|
334
|
-
enum:
|
|
1237
|
+
enum: dn,
|
|
335
1238
|
description: "'architect' for data model / schema work; 'analyst' for queries, analysis, and charts."
|
|
336
1239
|
},
|
|
337
1240
|
task: {
|
|
@@ -415,21 +1318,21 @@ var We = [
|
|
|
415
1318
|
required: ["subchat_id"]
|
|
416
1319
|
}
|
|
417
1320
|
},
|
|
418
|
-
|
|
1321
|
+
we
|
|
419
1322
|
];
|
|
420
1323
|
//#endregion
|
|
421
1324
|
//#region llm/dashboardAgentTools.ts
|
|
422
|
-
function
|
|
1325
|
+
function R(e, t) {
|
|
423
1326
|
return {
|
|
424
1327
|
type: "string",
|
|
425
1328
|
enum: e.map((e) => e.value),
|
|
426
1329
|
description: `${t} ${e.map((e) => `"${e.value}": ${e.hint}`).join(" ")}`
|
|
427
1330
|
};
|
|
428
1331
|
}
|
|
429
|
-
var
|
|
1332
|
+
var vn = Object.fromEntries(ee.map((e) => [e.key, {
|
|
430
1333
|
type: "string",
|
|
431
1334
|
description: `${e.label} color — ${e.hint} Accepts a hex string ("#101820"), rgb()/rgba()/hsl(), or a CSS color name. Pass an empty string to clear it back to the inherited theme color. Omit to leave it as-is.`
|
|
432
|
-
}])),
|
|
1335
|
+
}])), yn = [
|
|
433
1336
|
{
|
|
434
1337
|
name: "get_dashboard_state",
|
|
435
1338
|
description: "Re-read the current state of the dashboard: title, description, active data connection, active data source, item list, and (in report mode) section structure. The dashboard state in your starting context is a snapshot from the beginning of the conversation and does NOT update as you work — call this after making changes, or whenever you are unsure whether your view is current. Pass item_id to read just one item instead of the whole dashboard.",
|
|
@@ -465,7 +1368,7 @@ var Ge = Object.fromEntries(d.map((e) => [e.key, {
|
|
|
465
1368
|
},
|
|
466
1369
|
{
|
|
467
1370
|
name: "add_dashboard_item",
|
|
468
|
-
description: `Add a new item to the dashboard grid. Supports chart, table, markdown, filter, and freeform types. For charts and tables, provide a Trilogy query as content. For markdown items you can ALSO supply a 'query' to drive dynamic data — the query results are then available to the markdown via {field} template substitutions (see system prompt for full templating syntax). For freeform items, put the Trilogy query in 'content' and the widget markup in 'html' — the query and the rendering are authored separately, and the widget never issues queries of its own. ${
|
|
1371
|
+
description: `Add a new item to the dashboard grid. Supports chart, table, markdown, filter, and freeform types. For charts and tables, provide a Trilogy query as content. For markdown items you can ALSO supply a 'query' to drive dynamic data — the query results are then available to the markdown via {field} template substitutions (see system prompt for full templating syntax). For freeform items, put the Trilogy query in 'content' and the widget markup in 'html' — the query and the rendering are authored separately, and the widget never issues queries of its own. ${oe}`,
|
|
469
1372
|
input_schema: {
|
|
470
1373
|
type: "object",
|
|
471
1374
|
properties: {
|
|
@@ -497,7 +1400,7 @@ var Ge = Object.fromEntries(d.map((e) => [e.key, {
|
|
|
497
1400
|
description: "Optional Trilogy query for MARKDOWN items only. When provided, the query is executed and its result rows are bound to the markdown template — you can reference fields with {field}, {data[N].field}, formats like {revenue:,.2f}, fallbacks like {field || \"N/A\"}, and loops {{#each data}}...{{/each}}. Ignored for non-markdown types."
|
|
498
1401
|
},
|
|
499
1402
|
chartConfig: {
|
|
500
|
-
...
|
|
1403
|
+
...be,
|
|
501
1404
|
description: "Chart configuration (only for chart type). If omitted, chart type is auto-detected from the data."
|
|
502
1405
|
},
|
|
503
1406
|
width: {
|
|
@@ -550,7 +1453,7 @@ var Ge = Object.fromEntries(d.map((e) => [e.key, {
|
|
|
550
1453
|
description: "Change the item type"
|
|
551
1454
|
},
|
|
552
1455
|
chartConfig: {
|
|
553
|
-
...
|
|
1456
|
+
...be,
|
|
554
1457
|
description: "New chart configuration (for chart items)"
|
|
555
1458
|
}
|
|
556
1459
|
},
|
|
@@ -644,15 +1547,15 @@ var Ge = Object.fromEntries(d.map((e) => [e.key, {
|
|
|
644
1547
|
input_schema: {
|
|
645
1548
|
type: "object",
|
|
646
1549
|
properties: {
|
|
647
|
-
preset:
|
|
648
|
-
corners:
|
|
649
|
-
density:
|
|
650
|
-
elevation:
|
|
1550
|
+
preset: R(de, "Baseline look. Sets corners, density, elevation, and border treatment together; the individual fields below override whatever it chose."),
|
|
1551
|
+
corners: R(r, "Card corner rounding."),
|
|
1552
|
+
density: R(Ee, "Gutter width and padding. Denser fits more panels per screen; spacious suits fewer, larger panels."),
|
|
1553
|
+
elevation: R(Se, "Card drop shadow."),
|
|
651
1554
|
mobileCards: {
|
|
652
1555
|
type: "boolean",
|
|
653
1556
|
description: "Keep the card treatment on narrow viewports. Default false, which flattens panels to the page background below 768px — the right choice for most dashboards, since cards on a phone waste horizontal space."
|
|
654
1557
|
},
|
|
655
|
-
...
|
|
1558
|
+
...vn,
|
|
656
1559
|
reset: {
|
|
657
1560
|
type: "boolean",
|
|
658
1561
|
description: "Clear the entire theme and go back to the app default, which follows the user's light/dark setting. Use this when the user says \"undo the styling\" or \"back to normal\". When true, every other field is ignored."
|
|
@@ -709,9 +1612,9 @@ var Ge = Object.fromEntries(d.map((e) => [e.key, {
|
|
|
709
1612
|
required: []
|
|
710
1613
|
}
|
|
711
1614
|
},
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
],
|
|
1615
|
+
me,
|
|
1616
|
+
we
|
|
1617
|
+
], bn = [
|
|
715
1618
|
{
|
|
716
1619
|
name: "set_executive_memo",
|
|
717
1620
|
description: "Create or update the executive memo at the top of the report. Exactly one memo per report. The six fields ARE the memo — they map to the headline / verdict / magnitude / cause / action / confidence rubric. Pass `query` to bind live values into the prose via {field} templating. Calling this when a memo already exists updates it in place.",
|
|
@@ -842,7 +1745,7 @@ var Ge = Object.fromEntries(d.map((e) => [e.key, {
|
|
|
842
1745
|
];
|
|
843
1746
|
//#endregion
|
|
844
1747
|
//#region llm/dashboardAgentPrompt.ts
|
|
845
|
-
function
|
|
1748
|
+
function xn(e) {
|
|
846
1749
|
let { dashboard: t, dataConnectionName: n, activeImports: r = [], isDataConnectionActive: i = !0, itemId: a } = e, o = Object.entries(t.gridItems);
|
|
847
1750
|
if (a) {
|
|
848
1751
|
let e = t.gridItems[a];
|
|
@@ -850,27 +1753,27 @@ function qe(e) {
|
|
|
850
1753
|
let e = o.map(([e]) => e).join(", ");
|
|
851
1754
|
return `Item "${a}" not found on this dashboard.${e ? ` Known item IDs: ${e}` : " The dashboard is empty."}`;
|
|
852
1755
|
}
|
|
853
|
-
return `CURRENT STATE OF ITEM [${a}]:\n${
|
|
1756
|
+
return `CURRENT STATE OF ITEM [${a}]:\n${Sn(a, e)}`;
|
|
854
1757
|
}
|
|
855
|
-
let s = n ? `ACTIVE DATA CONNECTION: ${n}${n && !i ? " (NOT CONNECTED - use connect_data_connection tool to connect before running queries)" : ""}` : "ACTIVE DATA CONNECTION: none selected. Ask the user which connection to use.", c = r.length > 0 ? `ACTIVE DATA SOURCE: ${r[0].name} (this is the import the dashboard itself uses — changing it via select_active_import will affect every existing item on the next refresh)` : "ACTIVE DATA SOURCE: none selected. Use select_active_import to select a data source, or list_available_imports to see what is available.", l = o.length > 0 ? `CURRENT DASHBOARD ITEMS (${o.length}):\n${o.map(([e, t]) =>
|
|
1758
|
+
let s = n ? `ACTIVE DATA CONNECTION: ${n}${n && !i ? " (NOT CONNECTED - use connect_data_connection tool to connect before running queries)" : ""}` : "ACTIVE DATA CONNECTION: none selected. Ask the user which connection to use.", c = r.length > 0 ? `ACTIVE DATA SOURCE: ${r[0].name} (this is the import the dashboard itself uses — changing it via select_active_import will affect every existing item on the next refresh)` : "ACTIVE DATA SOURCE: none selected. Use select_active_import to select a data source, or list_available_imports to see what is available.", l = o.length > 0 ? `CURRENT DASHBOARD ITEMS (${o.length}):\n${o.map(([e, t]) => Sn(e, t)).join("\n")}` : "The dashboard is currently empty.", u = t.layoutType === "report" ? `\n${Cn(t)}` : "";
|
|
856
1759
|
return `DASHBOARD: "${t.name}"${t.description ? `\nDESCRIPTION: ${t.description}` : ""}
|
|
857
1760
|
${s}
|
|
858
1761
|
${c}
|
|
859
|
-
THEME: ${
|
|
1762
|
+
THEME: ${_(t.theme)}${u}
|
|
860
1763
|
|
|
861
1764
|
${l}`;
|
|
862
1765
|
}
|
|
863
|
-
function
|
|
1766
|
+
function Sn(e, t) {
|
|
864
1767
|
let n = typeof t.content == "string" ? t.content.substring(0, 80) : t.content?.markdown?.substring(0, 80) || "";
|
|
865
1768
|
return `- [${e}] ${t.type}: "${t.name}" — ${n}${n.length >= 80 ? "..." : ""}`;
|
|
866
1769
|
}
|
|
867
|
-
function
|
|
868
|
-
let t = Object.values(e.gridItems), n = t.filter((e) => e.type ===
|
|
1770
|
+
function Cn(e) {
|
|
1771
|
+
let t = Object.values(e.gridItems), n = t.filter((e) => e.type === o.MEMO).length, r = t.filter((e) => e.type === o.CLAIM).length, i = t.filter((e) => e.type === o.APPENDIX_HEADER).length;
|
|
869
1772
|
return `CURRENT REPORT STRUCTURE: ${n} memo / ${r} claim section${r === 1 ? "" : "s"} / ${i} appendix divider${i === 1 ? "" : "s"}.`;
|
|
870
1773
|
}
|
|
871
|
-
function
|
|
872
|
-
let { dashboard: t, availableConnections: n, availableConcepts: r, availableImportsForConnection: i = [] } = e, a = r && r.length > 0 ? `\n\nAVAILABLE FIELDS FOR QUERIES:\n${
|
|
873
|
-
return `${s ?
|
|
1774
|
+
function wn(e) {
|
|
1775
|
+
let { dashboard: t, availableConnections: n, availableConcepts: r, availableImportsForConnection: i = [] } = e, a = r && r.length > 0 ? `\n\nAVAILABLE FIELDS FOR QUERIES:\n${le(r)}` : "", o = i.length > 0 ? `\n\nAVAILABLE DATA SOURCES:\n${i.map((e) => `- ${e.name}`).join("\n")}` : "", s = t.layoutType === "report";
|
|
1776
|
+
return `${s ? En() : ""}You are a dashboard assistant with full control over a live ${s ? "report (a single-column analytical memo)" : "dashboard"}. The user can see changes you make in real time.
|
|
874
1777
|
|
|
875
1778
|
${s ? "This is a REPORT, not a free-form dashboard. Reports render top-to-bottom as a single narrative column. Use the report tools (set_executive_memo, add_claim_section, add_appendix_header) to author structure; use add_dashboard_item only for evidence (charts, tables, markdown). The grid x/y/w/h still drives ordering — y determines vertical position; x and w are mostly cosmetic in report mode." : "You have tools to add, update, remove, and reposition items on the dashboard grid. The grid is 20 columns wide. Items can be charts, tables, markdown blocks, filters, or freeform custom-HTML widgets."}
|
|
876
1779
|
|
|
@@ -880,7 +1783,7 @@ The current dashboard title, items, active connection, and active data source ar
|
|
|
880
1783
|
AVAILABLE DATA CONNECTIONS: ${n.length > 0 ? n.join(", ") : "None configured"}${o}
|
|
881
1784
|
|
|
882
1785
|
TRILOGY LANGUAGE REFERENCE:
|
|
883
|
-
${
|
|
1786
|
+
${m}
|
|
884
1787
|
${a}
|
|
885
1788
|
|
|
886
1789
|
IMPORTANT GUIDELINES:
|
|
@@ -946,7 +1849,7 @@ Example loop over top products:
|
|
|
946
1849
|
|
|
947
1850
|
When the user asks for a "summary card", "KPI tile", "headline metric", or any narrative text that should reflect live data, prefer a markdown item with a query over hardcoded numbers.
|
|
948
1851
|
|
|
949
|
-
${
|
|
1852
|
+
${Tn()}
|
|
950
1853
|
|
|
951
1854
|
VALIDATION BEFORE HANDOFF:
|
|
952
1855
|
- Once you believe the dashboard is complete, call capture_dashboard_screenshot to render it as a PNG and review the actual visual layout.
|
|
@@ -958,76 +1861,76 @@ VALIDATION BEFORE HANDOFF:
|
|
|
958
1861
|
COMPLETING YOUR RESPONSE:
|
|
959
1862
|
- When you have finished addressing the user's request — and have validated the result via capture_dashboard_screenshot — call return_to_user with a brief summary.
|
|
960
1863
|
- Never end a turn with plain text only — you must always call a tool. return_to_user is always your final tool call.
|
|
961
|
-
${s ?
|
|
1864
|
+
${s ? Dn() : ""}`;
|
|
962
1865
|
}
|
|
963
|
-
function
|
|
1866
|
+
function Tn() {
|
|
964
1867
|
return "FREEFORM WIDGETS (custom HTML):\nWhen the built-in chart types genuinely cannot express what the user asked for — a bespoke layout, a custom interaction, a visual metaphor specific to their domain — add an item of type \"freeform\". Prefer a chart or table when one fits: they are themed, accessible, and maintained. Reach for a widget when they don't.\n\nAuthoring a widget is TWO separate artifacts, passed as two fields:\n- `content`: the Trilogy query. Written exactly like a chart query, and subject to the same rules (full field paths, LIMIT, no GROUP BY). Global filters and cross-filters apply to it automatically.\n- `html`: the markup that renders the query's rows. You never write queries inside the widget — the widget cannot issue them.\n\nThe widget runs inside a sandboxed iframe. Available to it:\n- `trilogy.subscribe(fn)` — fn is called immediately and on every change with `{ status, columns, rows, rowCount, truncated, filters, error }`. `status` is 'loading' | 'ready' | 'error'; `columns` is `[{ name, type, address }]`; `rows` is an array of plain objects keyed by column name.\n- `trilogy.ready()` — REQUIRED. Call it once the first render completes. A widget that never calls ready() is reported as broken after a few seconds.\n- `trilogy.filters.eq(field, value)` — cross-filter the rest of the dashboard, exactly like clicking a chart mark. Pass the column name as it appears in `rows` (e.g. `'product.name'`); the host resolves it to the underlying concept. A field the dashboard doesn't expose is ignored.\n- `trilogy.filters.set(map)` / `.append(map)` / `.clear()` — map is `{ field: { op: 'eq' | 'in' | 'range' | 'is_null', value } }`.\n- `trilogy.refresh()` — re-run the backing query.\n- `trilogy.resize(px)` — request a taller frame.\n- `trilogy.theme` — `{ mode, vars }` where mode is 'light' or 'dark'. See the theme contract below.\n\nTHEME CONTRACT (read this before writing any CSS):\nNEVER hardcode a color, background, or font in a widget. The dashboard runs in light OR dark mode, the user can switch at any time, and a widget with baked-in colors is illegible in the other mode. Every color you need is already injected as a CSS variable on `:root` inside the frame, and they are re-pushed when the user switches mode:\n- `--widget-bg` — page background. The frame is transparent over the dashboard card by default; only set a background if you need a distinct surface.\n- `--widget-surface` — a raised/inset surface (cards, table headers, wells).\n- `--widget-text` — primary text. `--widget-text-muted` — secondary/labels/axis text.\n- `--widget-border` — borders and dividers. `--widget-border-light` — subtler dividers.\n- `--widget-accent` — accent/primary. `--widget-accent-rgb` — the same color as \"r, g, b\" for `rgba(var(--widget-accent-rgb), 0.12)` tints.\n- `--widget-positive` / `--widget-negative` — good/bad, up/down, profit/loss.\n- `--widget-series-1` … `--widget-series-6` — categorical palette for multi-series charts. Use these in order; do not invent your own.\n- `--widget-font`, `--widget-font-size` — already applied to `body`; inherit rather than restating.\n\nRules:\n1. Use `var(--widget-*)` for EVERY color. No hex literals, no `rgb()` literals, no named colors, no `background: white`, no `color: #333`.\n2. For translucent fills use `rgba(var(--widget-accent-rgb), 0.12)` — never a hardcoded rgba.\n3. Do not set `background` on `body` or `html`. The frame is transparent so the widget sits on the dashboard card; painting your own background is what makes a widget look like a pasted-in rectangle.\n4. If you truly need a mode-specific value, branch on `trilogy.theme.mode` inside `subscribe` — do not assume dark.\n5. Test your reasoning against both modes before finishing: would every piece of text still be readable if the background flipped?\n\nSandbox limits — code that violates these silently fails:\n- No network. `fetch`, XHR, WebSockets, and remote images are blocked. All data comes from the query.\n- No storage. `localStorage`, `sessionStorage`, and cookies are unavailable.\n- No access to the host page, no popups, no forms, no top-level navigation.\n- Libraries may be loaded from cdn.jsdelivr.net, unpkg.com, esm.sh, or cdnjs.cloudflare.com. Pin exact versions. Prefer plain DOM — it always works and loads instantly.\n\nWidget authoring rules:\n1. Handle every status. Render something sensible while `status === 'loading'` and when `rows` is empty; never assume data has arrived on first call.\n2. Read column names from `columns`, or use the names your own query selected — do not hardcode names you did not select.\n3. Build DOM with `textContent`/`createElement` rather than string concatenation into `innerHTML`. Row values are data you do not control, and a value containing markup will otherwise break the layout.\n4. Keep it self-contained: one `<style>`, one `<script>`, no build step.\n5. Call `trilogy.ready()` at the end of the initial render, not inside the subscribe callback's data branch.\n6. Every color comes from the theme contract above. A widget that hardcodes colors is a defect, not a style preference.\n\nMinimal shape:\n content:\n SELECT product.name, product.revenue ORDER BY product.revenue DESC LIMIT 10;\n html:\n <style>\n .row { padding: 6px 8px; border-bottom: 1px solid var(--widget-border-light); cursor: pointer; }\n .row:hover { background: rgba(var(--widget-accent-rgb), 0.08); }\n .name { color: var(--widget-text); }\n .value { color: var(--widget-text-muted); font-variant-numeric: tabular-nums; }\n .empty { color: var(--widget-text-muted); padding: 12px; }\n </style>\n <div id=\"root\"></div>\n <script>\n var root = document.getElementById('root');\n trilogy.subscribe(function (state) {\n if (!state.rows.length) {\n root.innerHTML = '';\n var empty = document.createElement('div');\n empty.className = 'empty';\n empty.textContent = state.status === 'loading' ? 'Loading…' : 'No data';\n root.appendChild(empty);\n return;\n }\n root.innerHTML = '';\n state.rows.forEach(function (row) {\n var el = document.createElement('div');\n el.className = 'row';\n var name = document.createElement('span');\n name.className = 'name';\n name.textContent = row['product.name'];\n var value = document.createElement('span');\n value.className = 'value';\n value.textContent = ' — ' + row['product.revenue'];\n el.appendChild(name);\n el.appendChild(value);\n el.onclick = function () { trilogy.filters.eq('product.name', row['product.name']); };\n root.appendChild(el);\n });\n });\n trilogy.ready();\n <\/script>";
|
|
965
1868
|
}
|
|
966
|
-
function
|
|
1869
|
+
function En() {
|
|
967
1870
|
return "# REPORT AUTHORING MODE\n\nYou are authoring a source-backed analytical memo, not an interactive dashboard. The reader is a busy decision-maker who wants the answer, the evidence, and the honest caveats — in that order.\n\nPRINCIPLES (non-negotiable):\n1. Make the claim. A great agent makes a claim, shows the evidence, exposes uncertainty, and lets the human interrogate it. Do NOT defer to the reader to make the call themselves by laying out raw charts.\n2. Executive memo first. One memo at the top: headline / verdict / magnitude / cause / action / confidence. Use set_executive_memo. Aim for one screen — the reader should not need to scroll to get the answer.\n3. Narrative sections, not dashboard tiles. Each claim is its own section. Do NOT title sections \"Revenue Chart\" or \"Conversion Analysis\" — those are table-of-contents entries, not insights. Title them with the claim itself.\n4. Charts serve the argument. Each claim has exactly the visual evidence needed to support it — no more. Add a chart RIGHT AFTER its claim section so the report renderer pairs them visually.\n5. Caveats are mandatory on every claim. State what the data does NOT prove. If you cannot articulate a caveat, the claim is probably overconfident.\n6. Drilldown comes after the answer, not before. Interactivity belongs below the verdict — never use it as the primary communication layer.\n7. Tables go in the appendix. Use add_appendix_header before adding detail tables; never put a giant table above a claim.\n8. Provenance is the price of authorship. Every claim must have a query, filters, and a confidence level. Use get_provenance to audit your own evidence chain before handing off. If you can't justify a number, do not state it.\n\n";
|
|
968
1871
|
}
|
|
969
|
-
function
|
|
1872
|
+
function Dn() {
|
|
970
1873
|
return "\n\nREPORT AUTHORING WORKFLOW:\n1. Start with set_executive_memo. All six fields are required. Pick a verdict (\"good\" / \"bad\" / \"mixed\" / \"inconclusive\") — pick \"inconclusive\" only when the data genuinely cannot decide. Pick a confidence (\"high\" / \"medium\" / \"low\") and explain the rationale. Bind a query if your magnitude/cause/action want live numbers.\n2. For each point you want to make, call add_claim_section with the claim sentence (and caveat, drilldown). Then immediately call add_dashboard_item with type='chart' (or 'table') for the evidence — the renderer pairs adjacent blocks. Keep one claim per section.\n3. When you have detail tables or methodology, call add_appendix_header once, then add_dashboard_item for each appendix block. Anything added after the divider renders as appendix content.\n4. Audit before handing off: call get_provenance on at least your memo and each claim section. Confirm queries, filters, and confidence are sane.\n5. Capture a screenshot to review visual rendering (capture_dashboard_screenshot).\n6. Call return_to_user with a one-paragraph summary highlighting the verdict and your confidence.\n\nANTI-PATTERNS (don't):\n- A wall of charts with no claims. That is the defensive design we are explicitly avoiding.\n- A claim without a chart, OR a chart without a claim. They come in pairs.\n- \"Tabs\" or interactivity-driven analysis. Reports are read top-to-bottom. Use drilldown text on claims when the reader needs to investigate further.\n- Memos with vague verdicts (\"worth investigating\", \"needs more analysis\"). Pick a side; lower the confidence if you are unsure.\n";
|
|
971
1874
|
}
|
|
972
1875
|
//#endregion
|
|
973
1876
|
//#region dashboards/connectionResolution.ts
|
|
974
|
-
function
|
|
1877
|
+
function On(e, t) {
|
|
975
1878
|
if (!e) return "";
|
|
976
1879
|
let { connection: n = "", connectionId: r = "" } = e;
|
|
977
1880
|
return r && t.connections[r] ? r : (n ? t.connectionByName(n)?.id : void 0) || r || n;
|
|
978
1881
|
}
|
|
979
|
-
function
|
|
1882
|
+
function kn(e, t) {
|
|
980
1883
|
let n = 0;
|
|
981
1884
|
for (let r of e) {
|
|
982
1885
|
if (r.connectionId && t.connections[r.connectionId] || !r.connection) continue;
|
|
983
1886
|
let e = t.connectionByName(r.connection) || t.connections[r.connection];
|
|
984
|
-
e && (r.connectionId
|
|
1887
|
+
e && (r.connectionId !== e.id || r.connection !== e.name) && (r.connectionId = e.id, r.connection = e.name, r.changed = !0, n += 1);
|
|
985
1888
|
}
|
|
986
1889
|
return n;
|
|
987
1890
|
}
|
|
988
1891
|
//#endregion
|
|
989
1892
|
//#region dashboards/freeform/types.ts
|
|
990
|
-
var
|
|
1893
|
+
var An = 262144, jn = 2e4, Mn = 8e3, Nn = 4e3, Pn = [
|
|
991
1894
|
"https://cdn.jsdelivr.net",
|
|
992
1895
|
"https://unpkg.com",
|
|
993
1896
|
"https://esm.sh",
|
|
994
1897
|
"https://cdnjs.cloudflare.com"
|
|
995
|
-
],
|
|
1898
|
+
], Fn = "trilogy-freeform-hello";
|
|
996
1899
|
//#endregion
|
|
997
1900
|
//#region dashboards/provenance.ts
|
|
998
|
-
function
|
|
999
|
-
let
|
|
1000
|
-
|
|
1901
|
+
function In(e, t, n) {
|
|
1902
|
+
let r = l(t), i = Array.isArray(n.imports) && n.imports.length > 0 ? n.imports[0] : void 0, s = [];
|
|
1903
|
+
n.filter && s.push({
|
|
1001
1904
|
source: "global",
|
|
1002
|
-
expression:
|
|
1905
|
+
expression: n.filter
|
|
1003
1906
|
});
|
|
1004
|
-
for (let e of t.filters || [])
|
|
1907
|
+
for (let e of t.filters || []) s.push({
|
|
1005
1908
|
source: e.source,
|
|
1006
1909
|
expression: e.value,
|
|
1007
1910
|
parameters: e.parameters
|
|
1008
1911
|
});
|
|
1009
|
-
let u, d, f
|
|
1010
|
-
|
|
1011
|
-
let m = !
|
|
1912
|
+
let c, u, d, f;
|
|
1913
|
+
a(t.content) ? (c = t.content.confidence, u = t.content.confidenceRationale) : p(t.content) && (d = t.content.caveat, f = t.content.drilldown);
|
|
1914
|
+
let m = !r && t.type !== o.CHART && t.type !== o.TABLE && !(je(t.content) && t.content.query);
|
|
1012
1915
|
return {
|
|
1013
1916
|
itemId: e,
|
|
1014
1917
|
type: t.type,
|
|
1015
1918
|
name: t.name,
|
|
1016
|
-
query:
|
|
1017
|
-
dataSource:
|
|
1018
|
-
freshness:
|
|
1019
|
-
filters:
|
|
1919
|
+
query: r,
|
|
1920
|
+
dataSource: i?.name,
|
|
1921
|
+
freshness: n.updatedAt,
|
|
1922
|
+
filters: s,
|
|
1020
1923
|
parameters: t.parameters,
|
|
1021
|
-
confidence:
|
|
1022
|
-
confidenceRationale:
|
|
1023
|
-
caveat:
|
|
1024
|
-
drilldown:
|
|
1924
|
+
confidence: c,
|
|
1925
|
+
confidenceRationale: u,
|
|
1926
|
+
caveat: d,
|
|
1927
|
+
drilldown: f,
|
|
1025
1928
|
rowCount: t.results?.data?.length,
|
|
1026
1929
|
error: t.error ?? null,
|
|
1027
1930
|
noQuery: m
|
|
1028
1931
|
};
|
|
1029
1932
|
}
|
|
1030
|
-
function
|
|
1933
|
+
function Ln(e) {
|
|
1031
1934
|
let t = [];
|
|
1032
1935
|
if (t.push(`# Provenance for "${e.name}" [${e.itemId}] (${e.type})`), t.push(""), e.dataSource && t.push(`- Data source: ${e.dataSource}`), t.push(`- Last updated: ${e.freshness.toISOString()}`), e.confidence && t.push(`- Confidence: ${e.confidence}${e.confidenceRationale ? ` — ${e.confidenceRationale}` : ""}`), e.rowCount !== void 0 && t.push(`- Rows returned: ${e.rowCount}`), e.error && t.push(`- Last error: ${e.error}`), e.caveat && t.push(`- Caveat: ${e.caveat}`), e.drilldown && t.push(`- Next drilldown: ${e.drilldown}`), e.filters.length > 0) {
|
|
1033
1936
|
t.push("- Filters:");
|
|
@@ -1042,14 +1945,14 @@ function ct(e) {
|
|
|
1042
1945
|
}
|
|
1043
1946
|
//#endregion
|
|
1044
1947
|
//#region llm/dashboardToolExecutor.ts
|
|
1045
|
-
function
|
|
1046
|
-
return !e || !e.trim() ? "Freeform items require `html` — the widget markup. Author the query in `content` and the markup in `html`." : e.length > 262144 ? `Widget html is ${e.length} characters; the limit is ${
|
|
1948
|
+
function Rn(e) {
|
|
1949
|
+
return !e || !e.trim() ? "Freeform items require `html` — the widget markup. Author the query in `content` and the markup in `html`." : e.length > 262144 ? `Widget html is ${e.length} characters; the limit is ${An}. Simplify the widget or move logic into fewer, denser helpers.` : null;
|
|
1047
1950
|
}
|
|
1048
|
-
var
|
|
1951
|
+
var zn = { heatmap: {
|
|
1049
1952
|
xField: 25,
|
|
1050
1953
|
yField: 25
|
|
1051
1954
|
} };
|
|
1052
|
-
function
|
|
1955
|
+
function Bn(e) {
|
|
1053
1956
|
if (e == null) return null;
|
|
1054
1957
|
if (typeof e == "object") {
|
|
1055
1958
|
let t = e;
|
|
@@ -1057,15 +1960,15 @@ function dt(e) {
|
|
|
1057
1960
|
}
|
|
1058
1961
|
return String(e);
|
|
1059
1962
|
}
|
|
1060
|
-
function
|
|
1963
|
+
function Vn(e, t) {
|
|
1061
1964
|
let n = /* @__PURE__ */ new Set();
|
|
1062
1965
|
for (let r of e) {
|
|
1063
|
-
let e =
|
|
1966
|
+
let e = Bn(r[t]);
|
|
1064
1967
|
e !== null && n.add(e);
|
|
1065
1968
|
}
|
|
1066
1969
|
return n.size;
|
|
1067
1970
|
}
|
|
1068
|
-
var
|
|
1971
|
+
var Hn = class {
|
|
1069
1972
|
deps;
|
|
1070
1973
|
constructor(e) {
|
|
1071
1974
|
this.deps = e;
|
|
@@ -1074,7 +1977,7 @@ var pt = class {
|
|
|
1074
1977
|
return this.deps.dashboardStore.dashboards[this.deps.dashboardId] || null;
|
|
1075
1978
|
}
|
|
1076
1979
|
get connectionName() {
|
|
1077
|
-
return
|
|
1980
|
+
return On(this.dashboard, this.deps.connectionStore);
|
|
1078
1981
|
}
|
|
1079
1982
|
async executeToolCall(e, t) {
|
|
1080
1983
|
switch (e) {
|
|
@@ -1119,7 +2022,7 @@ var pt = class {
|
|
|
1119
2022
|
let n = this.deps.connectionStore?.connections[this.connectionName];
|
|
1120
2023
|
return {
|
|
1121
2024
|
success: !0,
|
|
1122
|
-
message:
|
|
2025
|
+
message: xn({
|
|
1123
2026
|
dashboard: t,
|
|
1124
2027
|
dataConnectionName: t.connection,
|
|
1125
2028
|
activeImports: this.deps.getActiveImports(),
|
|
@@ -1140,8 +2043,8 @@ var pt = class {
|
|
|
1140
2043
|
message: "The dashboard is empty. No items to list."
|
|
1141
2044
|
};
|
|
1142
2045
|
let n = new Map(e.layout.map((e) => [e.i, e])), r = t.map(([e, t]) => {
|
|
1143
|
-
let r = n.get(e), i = typeof t.content == "object" && t.content !== null, a = i ? t.content : null,
|
|
1144
|
-
return `- [${e}] ${t.type}: "${t.name}" ${
|
|
2046
|
+
let r = n.get(e), i = typeof t.content == "object" && t.content !== null, a = i ? t.content : null, s = t.type === o.FREEFORM && i ? t.content : null, c = s ? `${s.html.length} chars of widget html` : i ? a?.markdown?.substring(0, 120) || "" : t.content.substring(0, 120), l = r ? `(x=${r.x}, y=${r.y}, w=${r.w}, h=${r.h})` : "", u = s?.query || a?.query, d = u ? `\n Query: ${u.substring(0, 120)}${u.length >= 120 ? "..." : ""}` : "";
|
|
2047
|
+
return `- [${e}] ${t.type}: "${t.name}" ${l}\n Content: ${c}${c.length >= 120 ? "..." : ""}${d}`;
|
|
1145
2048
|
});
|
|
1146
2049
|
return {
|
|
1147
2050
|
success: !0,
|
|
@@ -1159,12 +2062,12 @@ var pt = class {
|
|
|
1159
2062
|
success: !1,
|
|
1160
2063
|
error: `Item "${e}" not found. Use list_dashboard_items to see available items.`
|
|
1161
2064
|
};
|
|
1162
|
-
let r = t.layout.find((t) => t.i === e), i = typeof n.content == "object" && n.content !== null, a = i ? n.content : null,
|
|
2065
|
+
let r = t.layout.find((t) => t.i === e), i = typeof n.content == "object" && n.content !== null, a = i ? n.content : null, s = n.type === o.FREEFORM && i ? n.content : null, c = {
|
|
1163
2066
|
id: e,
|
|
1164
2067
|
type: n.type,
|
|
1165
2068
|
name: n.name,
|
|
1166
|
-
content:
|
|
1167
|
-
query:
|
|
2069
|
+
content: s ? s.query : i ? a?.markdown || "" : n.content,
|
|
2070
|
+
query: s?.query || a?.query || null,
|
|
1168
2071
|
chartConfig: n.chartConfig || null,
|
|
1169
2072
|
position: r ? {
|
|
1170
2073
|
x: r.x,
|
|
@@ -1175,16 +2078,16 @@ var pt = class {
|
|
|
1175
2078
|
loading: n.loading || !1,
|
|
1176
2079
|
error: n.error || null
|
|
1177
2080
|
};
|
|
1178
|
-
if (
|
|
1179
|
-
let e = typeof n.results.toJSON == "function" ? n.results.toJSON() : n.results, { head: t, totalRows: r, cutCount: i } =
|
|
1180
|
-
i > 0 ? (
|
|
2081
|
+
if (s && (c.html = s.html), n.results) {
|
|
2082
|
+
let e = typeof n.results.toJSON == "function" ? n.results.toJSON() : n.results, { head: t, totalRows: r, cutCount: i } = De(e);
|
|
2083
|
+
i > 0 ? (c.resultPreview = {
|
|
1181
2084
|
...e,
|
|
1182
2085
|
data: t
|
|
1183
|
-
},
|
|
2086
|
+
}, c.resultTruncated = `Showing first ${t.length} of ${r} rows`) : c.results = e;
|
|
1184
2087
|
}
|
|
1185
2088
|
return {
|
|
1186
2089
|
success: !0,
|
|
1187
|
-
message: JSON.stringify(
|
|
2090
|
+
message: JSON.stringify(c, null, 2)
|
|
1188
2091
|
};
|
|
1189
2092
|
}
|
|
1190
2093
|
async validateChartConfigAfterQuery(e, t, n) {
|
|
@@ -1196,7 +2099,7 @@ var pt = class {
|
|
|
1196
2099
|
let o = v(a.data, a.headers, n);
|
|
1197
2100
|
if (o.valid) return null;
|
|
1198
2101
|
let s = o.suggestedConfig;
|
|
1199
|
-
return s && s.chartType && this.deps.dashboardStore.updateItemChartConfig(this.deps.dashboardId, e, s), `Auto-corrected to default configuration.\n${
|
|
2102
|
+
return s && s.chartType && this.deps.dashboardStore.updateItemChartConfig(this.deps.dashboardId, e, s), `Auto-corrected to default configuration.\n${y(o)}`;
|
|
1200
2103
|
} catch {
|
|
1201
2104
|
return null;
|
|
1202
2105
|
}
|
|
@@ -1223,34 +2126,34 @@ var pt = class {
|
|
|
1223
2126
|
success: !1,
|
|
1224
2127
|
error: "Content is required."
|
|
1225
2128
|
};
|
|
1226
|
-
let i = n, a = typeof e.query == "string" ? e.query : "",
|
|
1227
|
-
if (
|
|
1228
|
-
let e =
|
|
2129
|
+
let i = n, a = typeof e.query == "string" ? e.query : "", s = i === o.MARKDOWN && a.length > 0, c = i === o.FREEFORM, l = typeof e.html == "string" ? e.html : "";
|
|
2130
|
+
if (c) {
|
|
2131
|
+
let e = Rn(l);
|
|
1229
2132
|
if (e) return {
|
|
1230
2133
|
success: !1,
|
|
1231
2134
|
error: e
|
|
1232
2135
|
};
|
|
1233
2136
|
}
|
|
1234
|
-
let u = e.width || (i ===
|
|
1235
|
-
if (
|
|
2137
|
+
let u = e.width || (i === o.MARKDOWN ? 20 : 10), d = e.height || (i === o.MARKDOWN ? s ? 6 : 4 : 8), f = e.name || n.charAt(0).toUpperCase() + n.slice(1), p = t.layout.reduce((e, t) => Math.max(e, t.y + t.h), 0), m = this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId, i, 0, p, u, d, r, f);
|
|
2138
|
+
if (s) {
|
|
1236
2139
|
let e = {
|
|
1237
2140
|
markdown: r,
|
|
1238
2141
|
query: a
|
|
1239
2142
|
};
|
|
1240
2143
|
this.deps.dashboardStore.updateMultipleItemProperties(this.deps.dashboardId, m, { content: e });
|
|
1241
2144
|
}
|
|
1242
|
-
if (
|
|
2145
|
+
if (c) {
|
|
1243
2146
|
let e = {
|
|
1244
|
-
html:
|
|
2147
|
+
html: l,
|
|
1245
2148
|
query: r
|
|
1246
2149
|
};
|
|
1247
2150
|
this.deps.dashboardStore.updateMultipleItemProperties(this.deps.dashboardId, m, { content: e });
|
|
1248
2151
|
}
|
|
1249
|
-
e.chartConfig && i ===
|
|
2152
|
+
e.chartConfig && i === o.CHART && this.deps.dashboardStore.updateItemChartConfig(this.deps.dashboardId, m, e.chartConfig);
|
|
1250
2153
|
let h;
|
|
1251
|
-
(i ===
|
|
1252
|
-
let g = `Added ${n} item "${f}" (ID: ${m}) at position (0, ${p}, ${u}x${d}).${
|
|
1253
|
-
if (e.chartConfig && i ===
|
|
2154
|
+
(i === o.CHART || i === o.TABLE || c || s) && (h = this.deps.refreshItem(m));
|
|
2155
|
+
let g = `Added ${n} item "${f}" (ID: ${m}) at position (0, ${p}, ${u}x${d}).${s ? " Markdown is bound to query results for dynamic data." : ""}${c ? " The widget receives this query’s rows via window.trilogy." : ""}`;
|
|
2156
|
+
if (e.chartConfig && i === o.CHART && h) {
|
|
1254
2157
|
let t = await this.validateChartConfigAfterQuery(m, h, e.chartConfig);
|
|
1255
2158
|
if (t) return {
|
|
1256
2159
|
success: !1,
|
|
@@ -1273,9 +2176,9 @@ var pt = class {
|
|
|
1273
2176
|
success: !1,
|
|
1274
2177
|
error: `Item "${n}" not found. Use list_dashboard_items to see available items.`
|
|
1275
2178
|
};
|
|
1276
|
-
let r = [], i = t.gridItems[n], a = e.type || i.type,
|
|
1277
|
-
if (a ===
|
|
1278
|
-
let t = i.content, a = typeof t == "string" ? "" : t?.html || "", o = typeof t == "string" ? t : t?.query || "", s = e.html === void 0 ? a : e.html, c = e.content === void 0 ? o : e.content, l =
|
|
2179
|
+
let r = [], i = t.gridItems[n], a = e.type || i.type, s = a === o.MARKDOWN;
|
|
2180
|
+
if (a === o.FREEFORM && (e.content !== void 0 || e.html !== void 0)) {
|
|
2181
|
+
let t = i.content, a = typeof t == "string" ? "" : t?.html || "", o = typeof t == "string" ? t : t?.query || "", s = e.html === void 0 ? a : e.html, c = e.content === void 0 ? o : e.content, l = Rn(s);
|
|
1279
2182
|
if (l) return {
|
|
1280
2183
|
success: !1,
|
|
1281
2184
|
error: l
|
|
@@ -1284,7 +2187,7 @@ var pt = class {
|
|
|
1284
2187
|
html: s,
|
|
1285
2188
|
query: c
|
|
1286
2189
|
} }), e.content !== void 0 && r.push("content"), e.html !== void 0 && r.push("html");
|
|
1287
|
-
} else if (
|
|
2190
|
+
} else if (s && (e.content !== void 0 || e.query !== void 0)) {
|
|
1288
2191
|
let t = i.content, a = typeof t == "string" ? t : t?.markdown || "", o = typeof t == "string" ? "" : t?.query || "", s = e.content === void 0 ? a : e.content, c = e.query === void 0 ? o : e.query, l = c ? {
|
|
1289
2192
|
markdown: s,
|
|
1290
2193
|
query: c
|
|
@@ -1295,25 +2198,25 @@ var pt = class {
|
|
|
1295
2198
|
success: !0,
|
|
1296
2199
|
message: `No updates provided for item "${n}".`
|
|
1297
2200
|
};
|
|
1298
|
-
let
|
|
1299
|
-
(r.includes("content") || r.includes("type") || r.includes("query")) && u && (
|
|
2201
|
+
let c = t.gridItems[n], l, u = c.type === o.CHART || c.type === o.TABLE || c.type === o.FREEFORM || c.type === o.MARKDOWN && typeof c.content == "object" && !!c.content.query;
|
|
2202
|
+
(r.includes("content") || r.includes("type") || r.includes("query")) && u && (l = this.deps.refreshItem(n));
|
|
1300
2203
|
let d = `Updated item "${n}": ${r.join(", ")}.`;
|
|
1301
|
-
if (r.includes("chartConfig") &&
|
|
1302
|
-
if (
|
|
1303
|
-
let t = await this.validateChartConfigAfterQuery(n,
|
|
2204
|
+
if (r.includes("chartConfig") && c.type === o.CHART) {
|
|
2205
|
+
if (l) {
|
|
2206
|
+
let t = await this.validateChartConfigAfterQuery(n, l, e.chartConfig);
|
|
1304
2207
|
if (t) return {
|
|
1305
2208
|
success: !1,
|
|
1306
2209
|
error: `${d}\n\nHowever, the chart configuration is invalid:\n${t}`
|
|
1307
2210
|
};
|
|
1308
|
-
} else if (
|
|
1309
|
-
let t =
|
|
2211
|
+
} else if (c.results) {
|
|
2212
|
+
let t = c.results;
|
|
1310
2213
|
if (t.headers) {
|
|
1311
2214
|
let r = v(t.data, t.headers, e.chartConfig);
|
|
1312
2215
|
if (!r.valid) {
|
|
1313
2216
|
let e = r.suggestedConfig;
|
|
1314
2217
|
return e && e.chartType && this.deps.dashboardStore.updateItemChartConfig(this.deps.dashboardId, n, e), {
|
|
1315
2218
|
success: !1,
|
|
1316
|
-
error: `${d}\n\nAuto-corrected to default configuration.\n${
|
|
2219
|
+
error: `${d}\n\nAuto-corrected to default configuration.\n${y(r)}`
|
|
1317
2220
|
};
|
|
1318
2221
|
}
|
|
1319
2222
|
}
|
|
@@ -1373,7 +2276,7 @@ var pt = class {
|
|
|
1373
2276
|
itemCount: Object.keys(e.gridItems).length,
|
|
1374
2277
|
imports: e.imports,
|
|
1375
2278
|
filter: e.filter,
|
|
1376
|
-
theme:
|
|
2279
|
+
theme: _(e.theme),
|
|
1377
2280
|
createdAt: e.createdAt,
|
|
1378
2281
|
updatedAt: e.updatedAt
|
|
1379
2282
|
};
|
|
@@ -1397,8 +2300,8 @@ var pt = class {
|
|
|
1397
2300
|
};
|
|
1398
2301
|
}
|
|
1399
2302
|
setDashboardTheme(e) {
|
|
1400
|
-
let
|
|
1401
|
-
if (!
|
|
2303
|
+
let t = this.dashboard;
|
|
2304
|
+
if (!t) return {
|
|
1402
2305
|
success: !1,
|
|
1403
2306
|
error: "Dashboard not found."
|
|
1404
2307
|
};
|
|
@@ -1406,20 +2309,20 @@ var pt = class {
|
|
|
1406
2309
|
success: !0,
|
|
1407
2310
|
message: "Dashboard theme cleared. It now inherits the app light/dark styling."
|
|
1408
2311
|
};
|
|
1409
|
-
let
|
|
1410
|
-
["preset",
|
|
1411
|
-
["corners",
|
|
1412
|
-
["density",
|
|
1413
|
-
["elevation",
|
|
2312
|
+
let n = {}, r = [], i = [
|
|
2313
|
+
["preset", ve],
|
|
2314
|
+
["corners", d],
|
|
2315
|
+
["density", ae],
|
|
2316
|
+
["elevation", ge]
|
|
1414
2317
|
];
|
|
1415
|
-
for (let [t,
|
|
1416
|
-
let
|
|
1417
|
-
if (
|
|
1418
|
-
if (!
|
|
2318
|
+
for (let [t, a] of i) {
|
|
2319
|
+
let i = e[t];
|
|
2320
|
+
if (i != null) {
|
|
2321
|
+
if (!a.includes(i)) return {
|
|
1419
2322
|
success: !1,
|
|
1420
|
-
error: `Invalid ${t} "${
|
|
2323
|
+
error: `Invalid ${t} "${i}". Must be one of: ${a.join(", ")}.`
|
|
1421
2324
|
};
|
|
1422
|
-
|
|
2325
|
+
n[t] = i, r.push(`${t}=${i}`);
|
|
1423
2326
|
}
|
|
1424
2327
|
}
|
|
1425
2328
|
if (e.mobileCards !== void 0 && e.mobileCards !== null) {
|
|
@@ -1427,32 +2330,32 @@ var pt = class {
|
|
|
1427
2330
|
success: !1,
|
|
1428
2331
|
error: "mobileCards must be true or false."
|
|
1429
2332
|
};
|
|
1430
|
-
|
|
2333
|
+
n.mobileCards = e.mobileCards, r.push(`mobileCards=${e.mobileCards}`);
|
|
1431
2334
|
}
|
|
1432
|
-
for (let t of
|
|
1433
|
-
let
|
|
1434
|
-
if (
|
|
1435
|
-
if (typeof
|
|
2335
|
+
for (let t of ee) {
|
|
2336
|
+
let i = e[t.key];
|
|
2337
|
+
if (i != null) {
|
|
2338
|
+
if (typeof i != "string") return {
|
|
1436
2339
|
success: !1,
|
|
1437
2340
|
error: `${t.key} must be a color string.`
|
|
1438
2341
|
};
|
|
1439
|
-
if (
|
|
1440
|
-
|
|
2342
|
+
if (i.trim() === "") {
|
|
2343
|
+
n[t.key] = void 0, r.push(`${t.key} cleared`);
|
|
1441
2344
|
continue;
|
|
1442
2345
|
}
|
|
1443
|
-
if (!
|
|
2346
|
+
if (!pe(i)) return {
|
|
1444
2347
|
success: !1,
|
|
1445
|
-
error: `Invalid ${t.key} "${
|
|
2348
|
+
error: `Invalid ${t.key} "${i}". Use a hex string ("#101820"), rgb()/rgba()/hsl(), or a CSS color name.`
|
|
1446
2349
|
};
|
|
1447
|
-
|
|
2350
|
+
n[t.key] = i.trim(), r.push(`${t.key}=${i.trim()}`);
|
|
1448
2351
|
}
|
|
1449
2352
|
}
|
|
1450
|
-
return
|
|
2353
|
+
return r.length === 0 ? {
|
|
1451
2354
|
success: !0,
|
|
1452
|
-
message: `No theme changes provided. Current theme: ${
|
|
1453
|
-
} : (this.deps.dashboardStore.setDashboardTheme(this.deps.dashboardId,
|
|
2355
|
+
message: `No theme changes provided. Current theme: ${_(t.theme)}. Pass reset=true to clear it.`
|
|
2356
|
+
} : (this.deps.dashboardStore.setDashboardTheme(this.deps.dashboardId, n), {
|
|
1454
2357
|
success: !0,
|
|
1455
|
-
message: `Theme updated (${
|
|
2358
|
+
message: `Theme updated (${r.join(", ")}). Full theme is now: ${_(this.dashboard?.theme)}. Call capture_dashboard_screenshot to confirm it reads well — custom colors override the app palette, so check contrast rather than assuming it.`
|
|
1456
2359
|
});
|
|
1457
2360
|
}
|
|
1458
2361
|
getChartAxisThresholdWarnings() {
|
|
@@ -1460,17 +2363,17 @@ var pt = class {
|
|
|
1460
2363
|
if (!e) return [];
|
|
1461
2364
|
let t = [];
|
|
1462
2365
|
for (let [n, r] of Object.entries(e.gridItems)) {
|
|
1463
|
-
if (r.type !==
|
|
1464
|
-
let i =
|
|
2366
|
+
if (r.type !== o.CHART || !r.chartConfig || !r.results) continue;
|
|
2367
|
+
let i = zn[r.chartConfig.chartType];
|
|
1465
2368
|
if (!i) continue;
|
|
1466
|
-
let a = r.results.data,
|
|
2369
|
+
let a = r.results.data, s = e.layout.find((e) => e.i === n), c = r.name || "(untitled)";
|
|
1467
2370
|
for (let e of ["xField", "yField"]) {
|
|
1468
|
-
let
|
|
1469
|
-
if (!
|
|
1470
|
-
let u =
|
|
1471
|
-
if (u <=
|
|
1472
|
-
let d = e === "xField" ? "x-axis" : "y-axis", f =
|
|
1473
|
-
t.push(`- [${n}] ${r.chartConfig.chartType} "${
|
|
2371
|
+
let o = i[e], l = r.chartConfig[e];
|
|
2372
|
+
if (!o || !l) continue;
|
|
2373
|
+
let u = Vn(a, l);
|
|
2374
|
+
if (u <= o) continue;
|
|
2375
|
+
let d = e === "xField" ? "x-axis" : "y-axis", f = s ? ` Current size: w=${s.w}, h=${s.h}.` : "";
|
|
2376
|
+
t.push(`- [${n}] ${r.chartConfig.chartType} "${c}": ${d} field "${l}" has ${u} distinct values, exceeding the recommended limit of ${o}.${f}`);
|
|
1474
2377
|
}
|
|
1475
2378
|
}
|
|
1476
2379
|
return t;
|
|
@@ -1517,9 +2420,9 @@ var pt = class {
|
|
|
1517
2420
|
success: !1,
|
|
1518
2421
|
error: "No connection name specified and no dashboard connection set."
|
|
1519
2422
|
};
|
|
1520
|
-
let r = this.deps.getActiveImports(), i = await
|
|
2423
|
+
let r = this.deps.getActiveImports(), i = await g(this.deps.queryExecutionService, this.deps.connectionStore, this.deps.editorStore, n, e, r);
|
|
1521
2424
|
if (!i.success) return i;
|
|
1522
|
-
let { queryResult: a } = i, o = typeof a.results.toJSON == "function" ? a.results.toJSON() : a.results, { head: s, totalRows: c, cutCount: l } =
|
|
2425
|
+
let { queryResult: a } = i, o = typeof a.results.toJSON == "function" ? a.results.toJSON() : a.results, { head: s, totalRows: c, cutCount: l } = De(o), u;
|
|
1523
2426
|
return l > 0 ? (u = JSON.stringify({
|
|
1524
2427
|
...o,
|
|
1525
2428
|
data: s
|
|
@@ -1538,22 +2441,22 @@ var pt = class {
|
|
|
1538
2441
|
};
|
|
1539
2442
|
}
|
|
1540
2443
|
async selectActiveImport(e) {
|
|
1541
|
-
return
|
|
2444
|
+
return fe(e, this.importAccessor, {
|
|
1542
2445
|
connectionStore: this.deps.connectionStore,
|
|
1543
2446
|
editorStore: this.deps.editorStore,
|
|
1544
2447
|
queryExecutionService: this.deps.queryExecutionService
|
|
1545
2448
|
}, this.deps.editorStore, this.deps.connectionStore);
|
|
1546
2449
|
}
|
|
1547
2450
|
listAvailableImports() {
|
|
1548
|
-
return
|
|
2451
|
+
return ne(this.importAccessor, this.deps.editorStore, this.deps.connectionStore);
|
|
1549
2452
|
}
|
|
1550
2453
|
async connectDataConnection(e) {
|
|
1551
|
-
return
|
|
2454
|
+
return ue(this.deps.connectionStore, e);
|
|
1552
2455
|
}
|
|
1553
2456
|
findMemoItemId() {
|
|
1554
2457
|
let e = this.dashboard;
|
|
1555
2458
|
if (!e) return null;
|
|
1556
|
-
for (let [t, n] of Object.entries(e.gridItems)) if (n.type ===
|
|
2459
|
+
for (let [t, n] of Object.entries(e.gridItems)) if (n.type === o.MEMO) return t;
|
|
1557
2460
|
return null;
|
|
1558
2461
|
}
|
|
1559
2462
|
async setExecutiveMemo(e) {
|
|
@@ -1604,7 +2507,7 @@ var pt = class {
|
|
|
1604
2507
|
return i ? (this.deps.dashboardStore.updateMultipleItemProperties(this.deps.dashboardId, i, {
|
|
1605
2508
|
content: r,
|
|
1606
2509
|
name: r.headline.slice(0, 80) || "Executive Memo"
|
|
1607
|
-
}), a = i) : (a = this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId,
|
|
2510
|
+
}), a = i) : (a = this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId, o.MEMO, 0, 0, 20, 8, "", r.headline.slice(0, 80) || "Executive Memo"), this.deps.dashboardStore.updateMultipleItemProperties(this.deps.dashboardId, a, { content: r })), r.query && this.deps.refreshItem(a), {
|
|
1608
2511
|
success: !0,
|
|
1609
2512
|
message: i ? `Updated executive memo (id ${a}). Verdict: ${t} · confidence: ${n}.` : `Added executive memo (id ${a}). Verdict: ${t} · confidence: ${n}.`
|
|
1610
2513
|
};
|
|
@@ -1625,7 +2528,7 @@ var pt = class {
|
|
|
1625
2528
|
caveat: typeof e.caveat == "string" ? e.caveat : void 0,
|
|
1626
2529
|
drilldown: typeof e.drilldown == "string" ? e.drilldown : void 0,
|
|
1627
2530
|
query: typeof e.query == "string" && e.query.trim() ? e.query : void 0
|
|
1628
|
-
}, r = n.heading || t.slice(0, 80), i = this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId,
|
|
2531
|
+
}, r = n.heading || t.slice(0, 80), i = this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId, o.CLAIM, 0, 0, 20, 4, "", r);
|
|
1629
2532
|
return this.deps.dashboardStore.updateMultipleItemProperties(this.deps.dashboardId, i, { content: n }), n.query && this.deps.refreshItem(i), {
|
|
1630
2533
|
success: !0,
|
|
1631
2534
|
message: `Added claim section (id ${i}). Pair this claim with an evidence chart by calling add_dashboard_item next; the report renderer keeps adjacent blocks visually together.`
|
|
@@ -1637,14 +2540,14 @@ var pt = class {
|
|
|
1637
2540
|
success: !1,
|
|
1638
2541
|
error: "Dashboard not found."
|
|
1639
2542
|
};
|
|
1640
|
-
for (let [e, n] of Object.entries(t.gridItems)) if (n.type ===
|
|
2543
|
+
for (let [e, n] of Object.entries(t.gridItems)) if (n.type === o.APPENDIX_HEADER) return {
|
|
1641
2544
|
success: !1,
|
|
1642
2545
|
error: `Appendix header already exists (id ${e}). A report should have at most one.`
|
|
1643
2546
|
};
|
|
1644
2547
|
let n = typeof e.label == "string" && e.label.trim() ? e.label.trim() : "Appendix";
|
|
1645
2548
|
return {
|
|
1646
2549
|
success: !0,
|
|
1647
|
-
message: `Added appendix divider (id ${this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId,
|
|
2550
|
+
message: `Added appendix divider (id ${this.deps.dashboardStore.addItemToDashboard(this.deps.dashboardId, o.APPENDIX_HEADER, 0, 0, 20, 1, "", n)}, label "${n}"). Subsequent items added to the report are rendered as appendix content.`
|
|
1648
2551
|
};
|
|
1649
2552
|
}
|
|
1650
2553
|
setReportLayout(e) {
|
|
@@ -1668,7 +2571,7 @@ var pt = class {
|
|
|
1668
2571
|
let n = t.gridItems[e];
|
|
1669
2572
|
return n ? {
|
|
1670
2573
|
success: !0,
|
|
1671
|
-
message:
|
|
2574
|
+
message: Ln(In(e, n, t))
|
|
1672
2575
|
} : {
|
|
1673
2576
|
success: !1,
|
|
1674
2577
|
error: `Item "${e}" not found. Use list_dashboard_items to see available items.`
|
|
@@ -1677,9 +2580,9 @@ var pt = class {
|
|
|
1677
2580
|
};
|
|
1678
2581
|
//#endregion
|
|
1679
2582
|
//#region dashboards/itemData.ts
|
|
1680
|
-
function
|
|
2583
|
+
function Un(e) {
|
|
1681
2584
|
return {
|
|
1682
|
-
type:
|
|
2585
|
+
type: o.CHART,
|
|
1683
2586
|
content: "",
|
|
1684
2587
|
structured_content: {
|
|
1685
2588
|
markdown: "",
|
|
@@ -1695,28 +2598,28 @@ function N(e) {
|
|
|
1695
2598
|
hasDrilldown: !1
|
|
1696
2599
|
};
|
|
1697
2600
|
}
|
|
1698
|
-
function
|
|
2601
|
+
function Wn(e, t) {
|
|
1699
2602
|
return e.imports.map((e) => ({
|
|
1700
2603
|
alias: e.name,
|
|
1701
2604
|
contents: t.editors[e.id]?.contents || t.editors[e.name]?.contents || ""
|
|
1702
2605
|
}));
|
|
1703
2606
|
}
|
|
1704
|
-
function
|
|
2607
|
+
function Gn(e) {
|
|
1705
2608
|
return e && typeof e == "object" && typeof e.markdown == "string" && typeof e.query == "string";
|
|
1706
2609
|
}
|
|
1707
|
-
function
|
|
2610
|
+
function Kn(e) {
|
|
1708
2611
|
return e && typeof e == "object" && "headline" in e && "verdict" in e;
|
|
1709
2612
|
}
|
|
1710
|
-
function
|
|
2613
|
+
function qn(e) {
|
|
1711
2614
|
return e && typeof e == "object" && "claim" in e && !("headline" in e);
|
|
1712
2615
|
}
|
|
1713
|
-
function
|
|
2616
|
+
function Jn(e) {
|
|
1714
2617
|
return e && typeof e == "object" && typeof e.html == "string";
|
|
1715
2618
|
}
|
|
1716
|
-
function
|
|
2619
|
+
function Yn(e, t, n) {
|
|
1717
2620
|
let r = e.gridItems[t];
|
|
1718
2621
|
if (!r) return {
|
|
1719
|
-
...
|
|
2622
|
+
...Un(t),
|
|
1720
2623
|
imports: e.imports,
|
|
1721
2624
|
connectionName: e.connection || ""
|
|
1722
2625
|
};
|
|
@@ -1725,27 +2628,27 @@ function vt(e, t, n) {
|
|
|
1725
2628
|
value: e.filter,
|
|
1726
2629
|
source: "global"
|
|
1727
2630
|
}, ...i]));
|
|
1728
|
-
let o = !1, s =
|
|
2631
|
+
let o = !1, s = Gn(r.content) ? r.content : Kn(r.content) || qn(r.content) || Jn(r.content) ? {
|
|
1729
2632
|
markdown: "",
|
|
1730
2633
|
query: r.content.query || ""
|
|
1731
2634
|
} : {
|
|
1732
2635
|
markdown: r.type === "markdown" ? r.content : "",
|
|
1733
2636
|
query: r.type === "markdown" ? "" : r.content
|
|
1734
2637
|
};
|
|
1735
|
-
r.drilldown && (o = !0, s =
|
|
2638
|
+
r.drilldown && (o = !0, s = Gn(r.drilldown) ? r.drilldown : {
|
|
1736
2639
|
markdown: r.type === "markdown" ? r.drilldown : "",
|
|
1737
2640
|
query: r.type === "markdown" ? "" : r.drilldown
|
|
1738
2641
|
});
|
|
1739
2642
|
let c = r.chartConfig;
|
|
1740
2643
|
o && (c = r.drilldownChartConfig || void 0);
|
|
1741
2644
|
let l = "";
|
|
1742
|
-
return typeof r.content == "string" ? l = r.content :
|
|
2645
|
+
return typeof r.content == "string" ? l = r.content : Gn(r.content) && (l = r.content.markdown), {
|
|
1743
2646
|
type: r.type,
|
|
1744
2647
|
content: l,
|
|
1745
2648
|
structured_content: s,
|
|
1746
|
-
memoData:
|
|
1747
|
-
claimData:
|
|
1748
|
-
freeformData:
|
|
2649
|
+
memoData: Kn(r.content) ? r.content : void 0,
|
|
2650
|
+
claimData: qn(r.content) ? r.content : void 0,
|
|
2651
|
+
freeformData: Jn(r.content) ? r.content : void 0,
|
|
1749
2652
|
name: r.name,
|
|
1750
2653
|
allowCrossFilter: r.allowCrossFilter !== !1,
|
|
1751
2654
|
width: r.width || 0,
|
|
@@ -1766,7 +2669,7 @@ function vt(e, t, n) {
|
|
|
1766
2669
|
hasDrilldown: o
|
|
1767
2670
|
};
|
|
1768
2671
|
}
|
|
1769
|
-
function
|
|
2672
|
+
function Xn(e, t, n, r) {
|
|
1770
2673
|
let i = {};
|
|
1771
2674
|
r.name && (i.name = r.name), r.chartConfig && (i.chartConfig = r.chartConfig), r.content && (i.content = r.content), r.dimensions && (i.layoutDimensions = {
|
|
1772
2675
|
w: r.dimensions.width,
|
|
@@ -1775,13 +2678,13 @@ function yt(e, t, n, r) {
|
|
|
1775
2678
|
}
|
|
1776
2679
|
//#endregion
|
|
1777
2680
|
//#region llm/dashboardAgentRuntime.ts
|
|
1778
|
-
function
|
|
2681
|
+
function Zn(e, t, n) {
|
|
1779
2682
|
let r = e.chatId;
|
|
1780
2683
|
if (r) {
|
|
1781
2684
|
let e = t.chats[r];
|
|
1782
2685
|
if (e && !e.deleted) return r;
|
|
1783
2686
|
}
|
|
1784
|
-
let i = new
|
|
2687
|
+
let i = new f({
|
|
1785
2688
|
name: `Dashboard: ${e.name}`,
|
|
1786
2689
|
llmConnectionName: n.activeConnection || "",
|
|
1787
2690
|
dataConnectionName: e.connection || "",
|
|
@@ -1790,49 +2693,49 @@ function bt(e, t, n) {
|
|
|
1790
2693
|
});
|
|
1791
2694
|
return t.addChat(i), e.setChatId(i.id), i.id;
|
|
1792
2695
|
}
|
|
1793
|
-
function
|
|
1794
|
-
return e.layoutType === "report" ? [...
|
|
2696
|
+
function Qn(e) {
|
|
2697
|
+
return e.layoutType === "report" ? [...yn, ...bn] : yn;
|
|
1795
2698
|
}
|
|
1796
|
-
function
|
|
2699
|
+
function z(e) {
|
|
1797
2700
|
return (e.imports || []).map((e) => ({
|
|
1798
2701
|
id: e.id,
|
|
1799
2702
|
name: e.name,
|
|
1800
2703
|
alias: e.alias || ""
|
|
1801
2704
|
}));
|
|
1802
2705
|
}
|
|
1803
|
-
function
|
|
2706
|
+
function $n(e, t, n) {
|
|
1804
2707
|
let r = t ? Object.values(t.connections).map((e) => e.name) : [], i = e.connectionId && t?.connections[e.connectionId] || (e.connection ? t?.connectionByName(e.connection) : void 0);
|
|
1805
|
-
return
|
|
2708
|
+
return wn({
|
|
1806
2709
|
dashboard: e,
|
|
1807
2710
|
availableConnections: r,
|
|
1808
|
-
availableImportsForConnection: n && i ? Object.values(n.editors).filter((e) => !e.deleted &&
|
|
2711
|
+
availableImportsForConnection: n && i ? Object.values(n.editors).filter((e) => !e.deleted && C(e.type) && e.connectionId === i.id).sort((e, t) => e.name.localeCompare(t.name)).map((e) => ({
|
|
1809
2712
|
id: e.id,
|
|
1810
2713
|
name: e.name.replace(/\//g, "."),
|
|
1811
2714
|
alias: ""
|
|
1812
2715
|
})) : []
|
|
1813
2716
|
});
|
|
1814
2717
|
}
|
|
1815
|
-
function
|
|
2718
|
+
function er(e, t) {
|
|
1816
2719
|
let n = e.connectionId && t?.connections[e.connectionId] || (e.connection ? t?.connectionByName(e.connection) : void 0);
|
|
1817
|
-
return
|
|
2720
|
+
return xn({
|
|
1818
2721
|
dashboard: e,
|
|
1819
2722
|
dataConnectionName: e.connection,
|
|
1820
|
-
activeImports:
|
|
2723
|
+
activeImports: z(e),
|
|
1821
2724
|
isDataConnectionActive: n?.connected ?? !1
|
|
1822
2725
|
});
|
|
1823
2726
|
}
|
|
1824
|
-
function
|
|
2727
|
+
function tr(e, t, n) {
|
|
1825
2728
|
let r = null;
|
|
1826
2729
|
return () => {
|
|
1827
2730
|
let i = e();
|
|
1828
|
-
return i ? (r === null && (r =
|
|
2731
|
+
return i ? (r === null && (r = er(i, t)), `${$n(i, t, n)}
|
|
1829
2732
|
|
|
1830
2733
|
DASHBOARD STATE AT THE START OF THIS CONVERSATION (snapshot — call get_dashboard_state for current state):
|
|
1831
2734
|
${r}`) : "";
|
|
1832
2735
|
};
|
|
1833
2736
|
}
|
|
1834
|
-
function
|
|
1835
|
-
let { dashboardStore: n, connectionStore: r, editorStore: i, queryExecutionService: a } = t, o = n.dashboards[e], s =
|
|
2737
|
+
function nr(e, t) {
|
|
2738
|
+
let { dashboardStore: n, connectionStore: r, editorStore: i, queryExecutionService: a } = t, o = n.dashboards[e], s = On(o, r);
|
|
1836
2739
|
return n.getOrCreateQueryExecutor(e, {
|
|
1837
2740
|
queryExecutionService: a,
|
|
1838
2741
|
connectionName: s,
|
|
@@ -1840,14 +2743,14 @@ function Tt(e, t) {
|
|
|
1840
2743
|
getDashboardData: (e) => n.dashboards[e],
|
|
1841
2744
|
getItemData: (e, t) => {
|
|
1842
2745
|
let r = n.dashboards[t];
|
|
1843
|
-
return r ?
|
|
2746
|
+
return r ? Yn(r, e, { rootContent: Wn(r, i) }) : Un(e);
|
|
1844
2747
|
},
|
|
1845
|
-
setItemData: (e, t, r) =>
|
|
2748
|
+
setItemData: (e, t, r) => Xn(n, t, e, r)
|
|
1846
2749
|
});
|
|
1847
2750
|
}
|
|
1848
|
-
function
|
|
2751
|
+
function rr(e, t) {
|
|
1849
2752
|
let { dashboardStore: n, connectionStore: r, editorStore: i, queryExecutionService: a } = t;
|
|
1850
|
-
return new
|
|
2753
|
+
return new Hn({
|
|
1851
2754
|
dashboardStore: n,
|
|
1852
2755
|
connectionStore: r,
|
|
1853
2756
|
editorStore: i,
|
|
@@ -1855,7 +2758,7 @@ function Et(e, t) {
|
|
|
1855
2758
|
dashboardId: e,
|
|
1856
2759
|
getActiveImports: () => {
|
|
1857
2760
|
let t = n.dashboards[e];
|
|
1858
|
-
return t ?
|
|
2761
|
+
return t ? z(t) : [];
|
|
1859
2762
|
},
|
|
1860
2763
|
setActiveImports: (t) => {
|
|
1861
2764
|
n.updateDashboardImports(e, t.map((e) => ({
|
|
@@ -1864,11 +2767,11 @@ function Et(e, t) {
|
|
|
1864
2767
|
alias: e.alias
|
|
1865
2768
|
})));
|
|
1866
2769
|
},
|
|
1867
|
-
getDashboardQueryExecutor: () =>
|
|
2770
|
+
getDashboardQueryExecutor: () => nr(e, t),
|
|
1868
2771
|
refreshItem: () => void 0
|
|
1869
2772
|
});
|
|
1870
2773
|
}
|
|
1871
|
-
var
|
|
2774
|
+
var ir = /* @__PURE__ */ new Set([
|
|
1872
2775
|
"add_dashboard_item",
|
|
1873
2776
|
"update_dashboard_item",
|
|
1874
2777
|
"remove_dashboard_item",
|
|
@@ -1879,23 +2782,23 @@ var Dt = /* @__PURE__ */ new Set([
|
|
|
1879
2782
|
"add_claim_section",
|
|
1880
2783
|
"add_appendix_header",
|
|
1881
2784
|
"set_report_layout"
|
|
1882
|
-
]),
|
|
1883
|
-
async function
|
|
2785
|
+
]), ar = /* @__PURE__ */ new Set();
|
|
2786
|
+
async function or(e) {
|
|
1884
2787
|
let { dashboard: t, chatId: n, chatStore: r, dashboardStore: i, setActiveDashboard: a } = e;
|
|
1885
2788
|
if (t.parentDashboardId) return t.id;
|
|
1886
2789
|
let o = `${n}:${t.id}`;
|
|
1887
|
-
if (
|
|
2790
|
+
if (ar.has(o)) return t.id;
|
|
1888
2791
|
let s = r.chats[n];
|
|
1889
|
-
if (s?.sourceRefId === t.id && s?.messages.some((e) => e.executedToolCalls?.some((e) =>
|
|
2792
|
+
if (s?.sourceRefId === t.id && s?.messages.some((e) => e.executedToolCalls?.some((e) => ir.has(e.name) && e.result?.success)) || Object.keys(t.gridItems).length === 0) return ar.add(o), t.id;
|
|
1890
2793
|
let c = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19).replace(/:/g, "");
|
|
1891
2794
|
try {
|
|
1892
2795
|
let e = i.forkDashboard(t.id, `chat-${c}`);
|
|
1893
|
-
return s && s.sourceRefId === t.id && (t.setChatId(null), e.setChatId(n), s.sourceRefId = e.id, s.changed = !0),
|
|
2796
|
+
return s && s.sourceRefId === t.id && (t.setChatId(null), e.setChatId(n), s.sourceRefId = e.id, s.changed = !0), ar.add(`${n}:${e.id}`), a?.(e.id), e.id;
|
|
1894
2797
|
} catch (e) {
|
|
1895
2798
|
return console.error("Failed to auto-fork dashboard for chat mutation:", e), t.id;
|
|
1896
2799
|
}
|
|
1897
2800
|
}
|
|
1898
|
-
async function
|
|
2801
|
+
async function sr(e) {
|
|
1899
2802
|
let { chatStore: t, chatId: n, toolExecutor: r, imports: i } = e, a = t.chats[n];
|
|
1900
2803
|
if (!a || a.messages.length > 0 || i.length === 0) return;
|
|
1901
2804
|
let o = i[0], s;
|
|
@@ -1910,7 +2813,7 @@ async function kt(e) {
|
|
|
1910
2813
|
id: c,
|
|
1911
2814
|
name: "select_active_import",
|
|
1912
2815
|
input: { import_name: o.name }
|
|
1913
|
-
},
|
|
2816
|
+
}, d = {
|
|
1914
2817
|
id: c,
|
|
1915
2818
|
name: "select_active_import",
|
|
1916
2819
|
input: { import_name: o.name },
|
|
@@ -1918,43 +2821,43 @@ async function kt(e) {
|
|
|
1918
2821
|
success: !0,
|
|
1919
2822
|
message: s.message
|
|
1920
2823
|
}
|
|
1921
|
-
},
|
|
2824
|
+
}, f = {
|
|
1922
2825
|
toolCallId: c,
|
|
1923
2826
|
toolName: "select_active_import",
|
|
1924
|
-
result:
|
|
2827
|
+
result: u(s)
|
|
1925
2828
|
};
|
|
1926
2829
|
t.addMessageToChat(n, {
|
|
1927
2830
|
role: "assistant",
|
|
1928
2831
|
content: `Inspecting the selected data source "${o.name}" so I know what fields are available.`,
|
|
1929
2832
|
toolCalls: [l],
|
|
1930
|
-
executedToolCalls: [
|
|
2833
|
+
executedToolCalls: [d]
|
|
1931
2834
|
}), t.addMessageToChat(n, {
|
|
1932
2835
|
role: "user",
|
|
1933
2836
|
content: "",
|
|
1934
|
-
toolResults: [
|
|
2837
|
+
toolResults: [f],
|
|
1935
2838
|
hidden: !0
|
|
1936
2839
|
});
|
|
1937
2840
|
}
|
|
1938
|
-
async function
|
|
2841
|
+
async function cr(e) {
|
|
1939
2842
|
let { dashboardId: t, prompt: n, stores: r, deps: i } = e, a = r.dashboardStore.dashboards[t];
|
|
1940
2843
|
if (!a) throw Error(`Dashboard ${t} not found`);
|
|
1941
|
-
let o =
|
|
1942
|
-
return await
|
|
2844
|
+
let o = Zn(a, r.chatStore, r.llmConnectionStore), s = rr(t, r);
|
|
2845
|
+
return await sr({
|
|
1943
2846
|
chatStore: r.chatStore,
|
|
1944
2847
|
chatId: o,
|
|
1945
2848
|
toolExecutor: s,
|
|
1946
|
-
imports:
|
|
2849
|
+
imports: z(a)
|
|
1947
2850
|
}), r.chatStore.executeMessage(o, n, i, { overrides: {
|
|
1948
|
-
tools:
|
|
2851
|
+
tools: Qn(a),
|
|
1949
2852
|
executeToolCall: (e, t) => s.executeToolCall(e, t),
|
|
1950
|
-
buildSystemPrompt:
|
|
2853
|
+
buildSystemPrompt: tr(() => r.dashboardStore.dashboards[t], r.connectionStore, r.editorStore)
|
|
1951
2854
|
} }).catch((e) => {
|
|
1952
2855
|
console.error(`Headless dashboard agent run for ${t} failed`, e);
|
|
1953
2856
|
}), o;
|
|
1954
2857
|
}
|
|
1955
2858
|
//#endregion
|
|
1956
2859
|
//#region llm/overseerToolExecutor.ts
|
|
1957
|
-
var
|
|
2860
|
+
var lr = class {
|
|
1958
2861
|
chatStore;
|
|
1959
2862
|
projectStore;
|
|
1960
2863
|
overseerChatId;
|
|
@@ -1986,9 +2889,9 @@ var jt = class {
|
|
|
1986
2889
|
}
|
|
1987
2890
|
}
|
|
1988
2891
|
spawnSubchat(e, t, n) {
|
|
1989
|
-
if (!
|
|
2892
|
+
if (!dn.includes(e)) return {
|
|
1990
2893
|
success: !1,
|
|
1991
|
-
error: `Invalid kind '${e}'. Must be one of: ${
|
|
2894
|
+
error: `Invalid kind '${e}'. Must be one of: ${dn.join(", ")}`
|
|
1992
2895
|
};
|
|
1993
2896
|
if (!t || typeof t != "string") return {
|
|
1994
2897
|
success: !1,
|
|
@@ -2004,7 +2907,7 @@ var jt = class {
|
|
|
2004
2907
|
success: !1,
|
|
2005
2908
|
error: "Overseer chat not found"
|
|
2006
2909
|
};
|
|
2007
|
-
let a = this.projectStore.projects[r], o = a?.dataConnectionId || i.dataConnectionId, s = i.dataConnectionName, c = this.chatStore.newChat(i.llmConnectionName, s, n ||
|
|
2910
|
+
let a = this.projectStore.projects[r], o = a?.dataConnectionId || i.dataConnectionId, s = i.dataConnectionName, c = this.chatStore.newChat(i.llmConnectionName, s, n || ur(e, t), o);
|
|
2008
2911
|
return c.kind = e, c.parentChatId = this.overseerChatId, c.parentProjectId = r, c.changed = !0, this.projectStore.addSubchatToProject(r, c.id), this.chatStore.executeMessage(c.id, t, this.deps).catch((e) => {
|
|
2009
2912
|
console.error(`Subchat ${c.id} failed`, e);
|
|
2010
2913
|
}), {
|
|
@@ -2097,7 +3000,7 @@ var jt = class {
|
|
|
2097
3000
|
};
|
|
2098
3001
|
let i = this.chatStore.isChatExecuting(e) ? "still running" : "idle / finished";
|
|
2099
3002
|
try {
|
|
2100
|
-
let n = await
|
|
3003
|
+
let n = await te(r, t, "peek");
|
|
2101
3004
|
return {
|
|
2102
3005
|
success: !0,
|
|
2103
3006
|
message: `Peek of ${e} (${t.kind}, ${i}):\n\n${n}`
|
|
@@ -2149,7 +3052,7 @@ var jt = class {
|
|
|
2149
3052
|
}
|
|
2150
3053
|
this.projectStore.addDashboardToProject(i, o.id);
|
|
2151
3054
|
try {
|
|
2152
|
-
|
|
3055
|
+
cr({
|
|
2153
3056
|
dashboardId: o.id,
|
|
2154
3057
|
prompt: r,
|
|
2155
3058
|
stores: {
|
|
@@ -2195,7 +3098,7 @@ var jt = class {
|
|
|
2195
3098
|
for (let e of t.subchatIds) {
|
|
2196
3099
|
let t = this.chatStore.chats[e];
|
|
2197
3100
|
if (!t) continue;
|
|
2198
|
-
let n = this.chatStore.isChatExecuting(e) ? "running" : "idle", i = t.messages[t.messages.length - 1], a = i ?
|
|
3101
|
+
let n = this.chatStore.isChatExecuting(e) ? "running" : "idle", i = t.messages[t.messages.length - 1], a = i ? dr(i.content || "", 80) : "";
|
|
2199
3102
|
r.push(` - ${e} [${t.kind}] (${n}) "${t.name}" — last: ${a}`);
|
|
2200
3103
|
}
|
|
2201
3104
|
return {
|
|
@@ -2204,15 +3107,15 @@ var jt = class {
|
|
|
2204
3107
|
};
|
|
2205
3108
|
}
|
|
2206
3109
|
};
|
|
2207
|
-
function
|
|
2208
|
-
return `${e}: ${
|
|
3110
|
+
function ur(e, t) {
|
|
3111
|
+
return `${e}: ${dr(t.split(/\s+/).slice(0, 6).join(" "), 50)}`;
|
|
2209
3112
|
}
|
|
2210
|
-
function
|
|
3113
|
+
function dr(e, t) {
|
|
2211
3114
|
return e.length <= t ? e : e.slice(0, t - 1) + "…";
|
|
2212
3115
|
}
|
|
2213
3116
|
//#endregion
|
|
2214
3117
|
//#region llm/architectToolExecutor.ts
|
|
2215
|
-
var
|
|
3118
|
+
var fr = class {
|
|
2216
3119
|
chatStore;
|
|
2217
3120
|
projectStore;
|
|
2218
3121
|
editorStore;
|
|
@@ -2286,7 +3189,7 @@ var Pt = class {
|
|
|
2286
3189
|
success: !1,
|
|
2287
3190
|
error: `File "${e}" not found in project.`
|
|
2288
3191
|
};
|
|
2289
|
-
let n =
|
|
3192
|
+
let n = _r(t.contents);
|
|
2290
3193
|
return {
|
|
2291
3194
|
success: !0,
|
|
2292
3195
|
message: `Contents of ${e} (${t.type}, ${t.contents.length} bytes):\n\n${n}`
|
|
@@ -2301,7 +3204,7 @@ var Pt = class {
|
|
|
2301
3204
|
success: !1,
|
|
2302
3205
|
error: "content is required"
|
|
2303
3206
|
};
|
|
2304
|
-
let r =
|
|
3207
|
+
let r = hr(t);
|
|
2305
3208
|
if (!r) return {
|
|
2306
3209
|
success: !1,
|
|
2307
3210
|
error: `type must be 'trilogy' or 'sql' (got ${JSON.stringify(t)}).`
|
|
@@ -2311,7 +3214,7 @@ var Pt = class {
|
|
|
2311
3214
|
success: !1,
|
|
2312
3215
|
error: "No project context."
|
|
2313
3216
|
};
|
|
2314
|
-
let a =
|
|
3217
|
+
let a = gr(e, r);
|
|
2315
3218
|
if (this.findEditorByName(a)) return {
|
|
2316
3219
|
success: !1,
|
|
2317
3220
|
error: `File "${a}" already exists. Use update_file to modify.`
|
|
@@ -2337,14 +3240,14 @@ var Pt = class {
|
|
|
2337
3240
|
success: !1,
|
|
2338
3241
|
error: `File "${e}" not found. Use create_file to add it.`
|
|
2339
3242
|
};
|
|
2340
|
-
let r =
|
|
3243
|
+
let r = S(e) || n.type;
|
|
2341
3244
|
if (r !== "preql" && r !== "trilogy" && r !== "sql") return {
|
|
2342
3245
|
success: !1,
|
|
2343
3246
|
error: `update_file handles .preql and .sql files; ${e} is ${r}.`
|
|
2344
3247
|
};
|
|
2345
3248
|
n.contents = t, n.changed = !0;
|
|
2346
3249
|
let i = r === "preql" || r === "trilogy", a = i ? `\n${await this.validateContent(e, t)}` : "", o = "";
|
|
2347
|
-
if (n.tags.includes(
|
|
3250
|
+
if (n.tags.includes(w.STARTUP_SCRIPT)) {
|
|
2348
3251
|
let e = this.connection;
|
|
2349
3252
|
if (e) try {
|
|
2350
3253
|
await this.connectionStore.connectConnection(e.id), o = `\nRe-ran startup against ${e.name}.`;
|
|
@@ -2373,11 +3276,11 @@ var Pt = class {
|
|
|
2373
3276
|
success: !1,
|
|
2374
3277
|
error: `File "${e}" not found in project.`
|
|
2375
3278
|
};
|
|
2376
|
-
if (n === "none") return r.removeTag(
|
|
3279
|
+
if (n === "none") return r.removeTag(w.STARTUP_SCRIPT), {
|
|
2377
3280
|
success: !0,
|
|
2378
3281
|
message: `Cleared purpose tags on ${e}.`
|
|
2379
3282
|
};
|
|
2380
|
-
r.addTag(
|
|
3283
|
+
r.addTag(w.STARTUP_SCRIPT);
|
|
2381
3284
|
let i = this.connection;
|
|
2382
3285
|
if (!i) return {
|
|
2383
3286
|
success: !0,
|
|
@@ -2475,12 +3378,12 @@ var Pt = class {
|
|
|
2475
3378
|
error: `Could not connect to ${t.name}: ${e instanceof Error ? e.message : String(e)}`
|
|
2476
3379
|
};
|
|
2477
3380
|
}
|
|
2478
|
-
let n = await
|
|
3381
|
+
let n = await g(this.queryExecutionService, this.connectionStore, this.editorStore, t.name, e);
|
|
2479
3382
|
if (!("queryResult" in n)) return n;
|
|
2480
3383
|
let r = n.queryResult;
|
|
2481
3384
|
return {
|
|
2482
3385
|
success: !0,
|
|
2483
|
-
message:
|
|
3386
|
+
message: vr(r),
|
|
2484
3387
|
executionTime: r.executionTime,
|
|
2485
3388
|
generatedSql: r.generatedSql,
|
|
2486
3389
|
query: e
|
|
@@ -2493,7 +3396,7 @@ var Pt = class {
|
|
|
2493
3396
|
text: "select 1;",
|
|
2494
3397
|
editorType: "trilogy",
|
|
2495
3398
|
imports: [],
|
|
2496
|
-
extraContent: [...
|
|
3399
|
+
extraContent: [...xe(this.connectionStore, this.editorStore, n.id), {
|
|
2497
3400
|
alias: e.replace(/\.preql$/, ""),
|
|
2498
3401
|
contents: t
|
|
2499
3402
|
}],
|
|
@@ -2517,8 +3420,8 @@ var Pt = class {
|
|
|
2517
3420
|
return `Validation threw: ${e instanceof Error ? e.message : String(e)}`;
|
|
2518
3421
|
}
|
|
2519
3422
|
}
|
|
2520
|
-
},
|
|
2521
|
-
function
|
|
3423
|
+
}, pr = 4e3, mr = pr * 2;
|
|
3424
|
+
function hr(e) {
|
|
2522
3425
|
switch (typeof e == "string" ? e.toLowerCase() : "") {
|
|
2523
3426
|
case "trilogy":
|
|
2524
3427
|
case "preql": return "preql";
|
|
@@ -2526,15 +3429,15 @@ function It(e) {
|
|
|
2526
3429
|
default: return null;
|
|
2527
3430
|
}
|
|
2528
3431
|
}
|
|
2529
|
-
function
|
|
3432
|
+
function gr(e, t) {
|
|
2530
3433
|
return t === "preql" ? e.endsWith(".preql") || e.endsWith(".trilogy") ? e : `${e}.preql` : e.endsWith(".sql") ? e : `${e}.sql`;
|
|
2531
3434
|
}
|
|
2532
|
-
function
|
|
2533
|
-
if (e.length <=
|
|
2534
|
-
let t = e.slice(0,
|
|
2535
|
-
return `${t}\n<redacted ${e.length -
|
|
3435
|
+
function _r(e) {
|
|
3436
|
+
if (e.length <= mr) return e;
|
|
3437
|
+
let t = e.slice(0, pr), n = e.slice(-4e3);
|
|
3438
|
+
return `${t}\n<redacted ${e.length - pr * 2} chars>\n${n}`;
|
|
2536
3439
|
}
|
|
2537
|
-
function
|
|
3440
|
+
function vr(e) {
|
|
2538
3441
|
let t = e.generatedSql ? `\nGenerated SQL:\n${e.generatedSql}\n` : "", n = e.results?.data || [], r = e.results?.headers ? Array.from(e.results.headers.keys()) : [], i = n.slice(0, 10);
|
|
2539
3442
|
return [
|
|
2540
3443
|
`Query OK — ${n.length} rows in ${e.executionTime}ms.`,
|
|
@@ -2545,7 +3448,7 @@ function zt(e) {
|
|
|
2545
3448
|
}
|
|
2546
3449
|
//#endregion
|
|
2547
3450
|
//#region llm/registry/toolRegistry.ts
|
|
2548
|
-
var
|
|
3451
|
+
var yr = {
|
|
2549
3452
|
chat: [
|
|
2550
3453
|
"data",
|
|
2551
3454
|
"artifacts",
|
|
@@ -2580,7 +3483,7 @@ var Bt = {
|
|
|
2580
3483
|
"docs",
|
|
2581
3484
|
"base"
|
|
2582
3485
|
]
|
|
2583
|
-
},
|
|
3486
|
+
}, br = class {
|
|
2584
3487
|
tools = /* @__PURE__ */ new Map();
|
|
2585
3488
|
toolsetCache = /* @__PURE__ */ new Map();
|
|
2586
3489
|
register(e) {
|
|
@@ -2591,7 +3494,7 @@ var Bt = {
|
|
|
2591
3494
|
e.forEach((e) => this.register(e));
|
|
2592
3495
|
}
|
|
2593
3496
|
toolsForContext(e) {
|
|
2594
|
-
let t =
|
|
3497
|
+
let t = yr[e];
|
|
2595
3498
|
if (!t) throw Error(`Unknown toolset context '${e}'`);
|
|
2596
3499
|
let n = new Set(t);
|
|
2597
3500
|
return [...this.tools.values()].filter((e) => n.has(e.pack));
|
|
@@ -2604,7 +3507,7 @@ var Bt = {
|
|
|
2604
3507
|
return this.toolsForContext(e).map((e) => e.definition.name);
|
|
2605
3508
|
}
|
|
2606
3509
|
createExecutor(e, t, n) {
|
|
2607
|
-
let r = new Set(
|
|
3510
|
+
let r = new Set(yr[e]), i = {
|
|
2608
3511
|
runtime: t,
|
|
2609
3512
|
session: n
|
|
2610
3513
|
};
|
|
@@ -2631,7 +3534,7 @@ var Bt = {
|
|
|
2631
3534
|
}
|
|
2632
3535
|
} };
|
|
2633
3536
|
}
|
|
2634
|
-
},
|
|
3537
|
+
}, xr = class {
|
|
2635
3538
|
queryExecutionService;
|
|
2636
3539
|
connectionStore;
|
|
2637
3540
|
chatStore;
|
|
@@ -2672,45 +3575,45 @@ var Bt = {
|
|
|
2672
3575
|
}
|
|
2673
3576
|
}
|
|
2674
3577
|
async executeTrilogyQuery(e, t, n, r) {
|
|
2675
|
-
let
|
|
2676
|
-
if (!
|
|
2677
|
-
let { queryResult:
|
|
3578
|
+
let a = this.resolvedChat?.imports || [], o = await g(this.queryExecutionService, this.connectionStore, this.editorStore, t, e, a);
|
|
3579
|
+
if (!o.success) return o;
|
|
3580
|
+
let { queryResult: s } = o, c = r, l = null;
|
|
2678
3581
|
if (r && n === "chart") {
|
|
2679
|
-
let e =
|
|
3582
|
+
let e = s.results;
|
|
2680
3583
|
if (e && e.headers) {
|
|
2681
3584
|
let t = v(e.data, e.headers, r);
|
|
2682
|
-
t.valid || (
|
|
3585
|
+
t.valid || (c = t.suggestedConfig, l = `Auto-corrected to default configuration.\n${y(t)}`);
|
|
2683
3586
|
}
|
|
2684
3587
|
}
|
|
2685
|
-
let
|
|
2686
|
-
id:
|
|
3588
|
+
let u = i(), d = {
|
|
3589
|
+
id: u,
|
|
2687
3590
|
type: n,
|
|
2688
|
-
data:
|
|
3591
|
+
data: s.results,
|
|
2689
3592
|
config: {
|
|
2690
3593
|
query: e,
|
|
2691
3594
|
connectionName: t,
|
|
2692
|
-
generatedSql:
|
|
2693
|
-
executionTime:
|
|
2694
|
-
resultSize:
|
|
2695
|
-
columnCount:
|
|
2696
|
-
...
|
|
3595
|
+
generatedSql: s.generatedSql,
|
|
3596
|
+
executionTime: s.executionTime,
|
|
3597
|
+
resultSize: s.resultSize,
|
|
3598
|
+
columnCount: s.columnCount,
|
|
3599
|
+
...c && { chartConfig: c }
|
|
2697
3600
|
}
|
|
2698
3601
|
};
|
|
2699
|
-
return
|
|
3602
|
+
return l ? {
|
|
2700
3603
|
success: !1,
|
|
2701
|
-
error:
|
|
2702
|
-
artifact:
|
|
2703
|
-
artifactId:
|
|
2704
|
-
executionTime:
|
|
3604
|
+
error: l,
|
|
3605
|
+
artifact: d,
|
|
3606
|
+
artifactId: u,
|
|
3607
|
+
executionTime: s.executionTime,
|
|
2705
3608
|
query: e,
|
|
2706
|
-
generatedSql:
|
|
3609
|
+
generatedSql: s.generatedSql
|
|
2707
3610
|
} : {
|
|
2708
3611
|
success: !0,
|
|
2709
|
-
artifact:
|
|
2710
|
-
artifactId:
|
|
2711
|
-
executionTime:
|
|
3612
|
+
artifact: d,
|
|
3613
|
+
artifactId: u,
|
|
3614
|
+
executionTime: s.executionTime,
|
|
2712
3615
|
query: e,
|
|
2713
|
-
generatedSql:
|
|
3616
|
+
generatedSql: s.generatedSql
|
|
2714
3617
|
};
|
|
2715
3618
|
}
|
|
2716
3619
|
async validateQuery(e, t) {
|
|
@@ -2726,7 +3629,7 @@ var Bt = {
|
|
|
2726
3629
|
let r = this.resolvedChat?.imports || [], i = r.map((e) => ({
|
|
2727
3630
|
name: e.name,
|
|
2728
3631
|
alias: e.alias || ""
|
|
2729
|
-
})), a =
|
|
3632
|
+
})), a = xe(this.connectionStore, this.editorStore, t, r), o = {
|
|
2730
3633
|
text: e.trim(),
|
|
2731
3634
|
editorType: "trilogy",
|
|
2732
3635
|
imports: i,
|
|
@@ -2769,20 +3672,20 @@ var Bt = {
|
|
|
2769
3672
|
return !this.resolvedChatId || !this.editorStore ? {
|
|
2770
3673
|
success: !1,
|
|
2771
3674
|
error: "No active chat or editor store not available"
|
|
2772
|
-
} :
|
|
3675
|
+
} : fe(e, this.importAccessor, {
|
|
2773
3676
|
connectionStore: this.connectionStore,
|
|
2774
3677
|
editorStore: this.editorStore,
|
|
2775
3678
|
queryExecutionService: this.queryExecutionService
|
|
2776
3679
|
}, this.editorStore, this.connectionStore);
|
|
2777
3680
|
}
|
|
2778
3681
|
listAvailableImports() {
|
|
2779
|
-
return
|
|
3682
|
+
return ne(this.importAccessor, this.editorStore, this.connectionStore);
|
|
2780
3683
|
}
|
|
2781
3684
|
getAvailableImports(e) {
|
|
2782
|
-
return
|
|
3685
|
+
return Ce(this.editorStore, e, this.connectionStore);
|
|
2783
3686
|
}
|
|
2784
3687
|
async connectDataConnection(e) {
|
|
2785
|
-
return
|
|
3688
|
+
return ue(this.connectionStore, e, { onConnected: (e) => {
|
|
2786
3689
|
if (this.resolvedChatId && this.chatStore) {
|
|
2787
3690
|
let t = this.connectionStore.connectionByName(e);
|
|
2788
3691
|
this.chatStore.updateChatDataConnection(this.resolvedChatId, e, t?.id || "");
|
|
@@ -2794,7 +3697,7 @@ var Bt = {
|
|
|
2794
3697
|
success: !1,
|
|
2795
3698
|
error: "Markdown content is required and must be a non-empty string"
|
|
2796
3699
|
};
|
|
2797
|
-
let
|
|
3700
|
+
let a = i(), o = null;
|
|
2798
3701
|
if (n && n.trim()) {
|
|
2799
3702
|
if (r ||= this.resolvedChat?.dataConnectionName || "", !r) return {
|
|
2800
3703
|
success: !1,
|
|
@@ -2805,25 +3708,25 @@ var Bt = {
|
|
|
2805
3708
|
success: !1,
|
|
2806
3709
|
error: `Query execution failed: ${e.error}`
|
|
2807
3710
|
};
|
|
2808
|
-
|
|
3711
|
+
o = e.artifact?.data || null;
|
|
2809
3712
|
}
|
|
2810
3713
|
return {
|
|
2811
3714
|
success: !0,
|
|
2812
3715
|
artifact: {
|
|
2813
|
-
id:
|
|
3716
|
+
id: a,
|
|
2814
3717
|
type: "markdown",
|
|
2815
3718
|
data: {
|
|
2816
3719
|
markdown: e,
|
|
2817
3720
|
query: n || "",
|
|
2818
|
-
queryResults:
|
|
3721
|
+
queryResults: o
|
|
2819
3722
|
},
|
|
2820
3723
|
config: {
|
|
2821
3724
|
title: t || "Markdown",
|
|
2822
3725
|
connectionName: r || ""
|
|
2823
3726
|
}
|
|
2824
3727
|
},
|
|
2825
|
-
artifactId:
|
|
2826
|
-
message: `Created markdown artifact "${t || "Markdown"}" (ID: ${
|
|
3728
|
+
artifactId: a,
|
|
3729
|
+
message: `Created markdown artifact "${t || "Markdown"}" (ID: ${a}).`
|
|
2827
3730
|
};
|
|
2828
3731
|
}
|
|
2829
3732
|
listArtifacts() {
|
|
@@ -2864,7 +3767,7 @@ var Bt = {
|
|
|
2864
3767
|
};
|
|
2865
3768
|
if (n.config && (r.config = { ...n.config }), n.type === "markdown") r.markdown = n.data?.markdown || "", r.query = n.data?.query || "", r.hasQueryResults = !!n.data?.queryResults;
|
|
2866
3769
|
else if (n.data) {
|
|
2867
|
-
let e = typeof n.data.toJSON == "function" ? n.data.toJSON() : n.data, { head: t, tail: i, totalRows: a, cutCount: o } =
|
|
3770
|
+
let e = typeof n.data.toJSON == "function" ? n.data.toJSON() : n.data, { head: t, tail: i, totalRows: a, cutCount: o } = De(e);
|
|
2868
3771
|
o > 0 ? (r.data = {
|
|
2869
3772
|
...e,
|
|
2870
3773
|
data: t
|
|
@@ -2885,7 +3788,7 @@ var Bt = {
|
|
|
2885
3788
|
return i ? i.type !== "results" && i.type !== "chart" ? {
|
|
2886
3789
|
success: !1,
|
|
2887
3790
|
error: `Artifact "${e}" does not contain tabular data (type: ${i.type}). Only results and chart artifacts support row fetching.`
|
|
2888
|
-
} :
|
|
3791
|
+
} : _e(e, i.data, t, n) : {
|
|
2889
3792
|
success: !1,
|
|
2890
3793
|
error: `Artifact "${e}" not found. Use list_artifacts to see available artifacts.`
|
|
2891
3794
|
};
|
|
@@ -2919,7 +3822,7 @@ var Bt = {
|
|
|
2919
3822
|
chartConfig: t
|
|
2920
3823
|
}, i.updatedAt = /* @__PURE__ */ new Date(), i.changed = !0, {
|
|
2921
3824
|
success: !1,
|
|
2922
|
-
error: `Auto-corrected artifact "${e}" chart config to default configuration.\n` +
|
|
3825
|
+
error: `Auto-corrected artifact "${e}" chart config to default configuration.\n` + y(n)
|
|
2923
3826
|
};
|
|
2924
3827
|
}
|
|
2925
3828
|
}
|
|
@@ -2983,13 +3886,13 @@ var Bt = {
|
|
|
2983
3886
|
message: r.length > 0 ? `Hidden ${i.length} artifact(s). Not found: ${r.join(", ")}. Hidden artifacts remain accessible to you via list_artifacts and can be restored by the user.` : `Hidden ${i.length} artifact(s). They remain accessible via list_artifacts and can be restored by the user.`
|
|
2984
3887
|
};
|
|
2985
3888
|
}
|
|
2986
|
-
},
|
|
3889
|
+
}, Sr = [
|
|
2987
3890
|
"run_trilogy_query",
|
|
2988
3891
|
"chart_trilogy_query",
|
|
2989
3892
|
"select_active_import",
|
|
2990
3893
|
"list_available_imports",
|
|
2991
3894
|
"connect_data_connection"
|
|
2992
|
-
],
|
|
3895
|
+
], Cr = [
|
|
2993
3896
|
"create_markdown",
|
|
2994
3897
|
"list_artifacts",
|
|
2995
3898
|
"get_artifact",
|
|
@@ -2997,35 +3900,35 @@ var Bt = {
|
|
|
2997
3900
|
"update_artifact",
|
|
2998
3901
|
"hide_artifact",
|
|
2999
3902
|
"reorder_artifacts"
|
|
3000
|
-
],
|
|
3001
|
-
function
|
|
3002
|
-
let t =
|
|
3903
|
+
], wr = ["return_to_user"];
|
|
3904
|
+
function Tr(e) {
|
|
3905
|
+
let t = ye.find((t) => t.name === e);
|
|
3003
3906
|
if (!t) throw Error(`CHAT_TOOLS is missing expected tool '${e}'`);
|
|
3004
3907
|
return t;
|
|
3005
3908
|
}
|
|
3006
|
-
function
|
|
3909
|
+
function Er(e) {
|
|
3007
3910
|
let t = "chatToolExecutor", n = e.session.cache.get(t);
|
|
3008
|
-
return n || (n = new
|
|
3911
|
+
return n || (n = new xr(e.runtime.queryExecutionService, e.runtime.connectionStore, e.runtime.chatStore, e.runtime.editorStore, e.session.chatId), e.session.cache.set(t, n)), n;
|
|
3009
3912
|
}
|
|
3010
|
-
function
|
|
3913
|
+
function Dr(e, t) {
|
|
3011
3914
|
return e.map((e) => ({
|
|
3012
|
-
definition:
|
|
3915
|
+
definition: Tr(e),
|
|
3013
3916
|
pack: t,
|
|
3014
|
-
execute: (t, n) =>
|
|
3917
|
+
execute: (t, n) => Er(n).executeToolCall(e, t)
|
|
3015
3918
|
}));
|
|
3016
3919
|
}
|
|
3017
|
-
function
|
|
3018
|
-
return
|
|
3920
|
+
function Or() {
|
|
3921
|
+
return Dr(Sr, "data");
|
|
3019
3922
|
}
|
|
3020
|
-
function
|
|
3021
|
-
return
|
|
3923
|
+
function kr() {
|
|
3924
|
+
return Dr(Cr, "artifacts");
|
|
3022
3925
|
}
|
|
3023
|
-
function
|
|
3024
|
-
return
|
|
3926
|
+
function Ar() {
|
|
3927
|
+
return Dr(wr, "base");
|
|
3025
3928
|
}
|
|
3026
3929
|
//#endregion
|
|
3027
3930
|
//#region llm/registry/packs/navigationPack.ts
|
|
3028
|
-
var
|
|
3931
|
+
var jr = [
|
|
3029
3932
|
"editors",
|
|
3030
3933
|
"connections",
|
|
3031
3934
|
"dashboard",
|
|
@@ -3042,19 +3945,19 @@ function B(e) {
|
|
|
3042
3945
|
hint: "App navigation is not available in this embedding context."
|
|
3043
3946
|
};
|
|
3044
3947
|
}
|
|
3045
|
-
function
|
|
3948
|
+
function Mr(e, t) {
|
|
3046
3949
|
let n = e.runtime.dashboardStore;
|
|
3047
3950
|
if (!n) return null;
|
|
3048
3951
|
let r = Object.prototype.hasOwnProperty.call(n.dashboards, t) ? n.dashboards[t] : void 0;
|
|
3049
3952
|
return r && !r.deleted ? r : Object.values(n.dashboards).find((e) => e.name === t && !e.deleted) || null;
|
|
3050
3953
|
}
|
|
3051
|
-
function
|
|
3954
|
+
function Nr(e, t) {
|
|
3052
3955
|
let n = e.runtime.editorStore, r = Object.prototype.hasOwnProperty.call(n.editors, t) ? n.editors[t] : void 0;
|
|
3053
3956
|
if (r && !r.deleted) return r;
|
|
3054
3957
|
let i = n.getEditorByName(t);
|
|
3055
3958
|
return i && !i.deleted ? i : null;
|
|
3056
3959
|
}
|
|
3057
|
-
async function
|
|
3960
|
+
async function Pr(e) {
|
|
3058
3961
|
let t = e.runtime.navigation, n = [];
|
|
3059
3962
|
n.push(`Active screen: ${t.activeScreen.value || "welcome"}`);
|
|
3060
3963
|
let r = t.tabs.value;
|
|
@@ -3079,7 +3982,7 @@ async function $t(e) {
|
|
|
3079
3982
|
message: n.join("\n")
|
|
3080
3983
|
};
|
|
3081
3984
|
}
|
|
3082
|
-
function
|
|
3985
|
+
function Fr() {
|
|
3083
3986
|
return [
|
|
3084
3987
|
{
|
|
3085
3988
|
pack: "navigation",
|
|
@@ -3092,7 +3995,7 @@ function en() {
|
|
|
3092
3995
|
properties: {}
|
|
3093
3996
|
}
|
|
3094
3997
|
},
|
|
3095
|
-
execute: (e, t) =>
|
|
3998
|
+
execute: (e, t) => Pr(t)
|
|
3096
3999
|
},
|
|
3097
4000
|
{
|
|
3098
4001
|
pack: "navigation",
|
|
@@ -3104,7 +4007,7 @@ function en() {
|
|
|
3104
4007
|
type: "object",
|
|
3105
4008
|
properties: { screen: {
|
|
3106
4009
|
type: "string",
|
|
3107
|
-
enum: [...
|
|
4010
|
+
enum: [...jr],
|
|
3108
4011
|
description: "The screen to navigate to"
|
|
3109
4012
|
} },
|
|
3110
4013
|
required: ["screen"]
|
|
@@ -3112,9 +4015,9 @@ function en() {
|
|
|
3112
4015
|
},
|
|
3113
4016
|
execute: async (e, t) => {
|
|
3114
4017
|
let n = e.screen;
|
|
3115
|
-
if (!
|
|
4018
|
+
if (!jr.includes(n)) return {
|
|
3116
4019
|
success: !1,
|
|
3117
|
-
error: `Unknown screen "${e.screen}". Valid screens: ${
|
|
4020
|
+
error: `Unknown screen "${e.screen}". Valid screens: ${jr.join(", ")}`
|
|
3118
4021
|
};
|
|
3119
4022
|
let r = t.runtime.navigation;
|
|
3120
4023
|
return r.setActiveScreen(n), r.setActiveSidebarScreen(n), {
|
|
@@ -3143,7 +4046,7 @@ function en() {
|
|
|
3143
4046
|
success: !1,
|
|
3144
4047
|
error: "Dashboard store is not available in this context."
|
|
3145
4048
|
};
|
|
3146
|
-
let n =
|
|
4049
|
+
let n = Mr(t, String(e.dashboard_ref ?? ""));
|
|
3147
4050
|
if (!n) {
|
|
3148
4051
|
let n = Object.values(t.runtime.dashboardStore.dashboards).filter((e) => !e.deleted).map((e) => `"${e.name}"`).join(", ");
|
|
3149
4052
|
return {
|
|
@@ -3173,7 +4076,7 @@ function en() {
|
|
|
3173
4076
|
}
|
|
3174
4077
|
},
|
|
3175
4078
|
execute: async (e, t) => {
|
|
3176
|
-
let n =
|
|
4079
|
+
let n = Nr(t, String(e.editor_ref ?? ""));
|
|
3177
4080
|
return n ? (t.runtime.navigation.setActiveEditor(n.id), {
|
|
3178
4081
|
success: !0,
|
|
3179
4082
|
message: `Opened editor "${n.name}" (id ${n.id}, type ${n.type}).`
|
|
@@ -3187,24 +4090,24 @@ function en() {
|
|
|
3187
4090
|
}
|
|
3188
4091
|
//#endregion
|
|
3189
4092
|
//#region llm/registry/packs/editorPack.ts
|
|
3190
|
-
var
|
|
4093
|
+
var Ir = 4e4;
|
|
3191
4094
|
function V(e, t) {
|
|
3192
4095
|
let n = e.runtime.editorStore, r = Object.prototype.hasOwnProperty.call(n.editors, t) ? n.editors[t] : void 0;
|
|
3193
4096
|
if (r && !r.deleted) return r;
|
|
3194
4097
|
let i = n.getEditorByName(t);
|
|
3195
4098
|
return i && !i.deleted ? i : null;
|
|
3196
4099
|
}
|
|
3197
|
-
function
|
|
4100
|
+
function Lr(e) {
|
|
3198
4101
|
let t = (e.contents || "").split("\n").length;
|
|
3199
4102
|
return `- "${e.name}" (id ${e.id}, type ${e.type}, connection ${e.connection}, ${t} lines${e.tags.length ? `, tags: ${e.tags.join(",")}` : ""})`;
|
|
3200
4103
|
}
|
|
3201
|
-
function
|
|
3202
|
-
return e.storage === "remote" ?
|
|
4104
|
+
function Rr(e, t) {
|
|
4105
|
+
return e.storage === "remote" ? x(t, e.type) : t;
|
|
3203
4106
|
}
|
|
3204
|
-
function
|
|
4107
|
+
function zr(e, t, n) {
|
|
3205
4108
|
return Object.values(e.runtime.editorStore.editors).find((e) => !e.deleted && e.id !== t.id && e.connectionId === t.connectionId && e.name === n) || null;
|
|
3206
4109
|
}
|
|
3207
|
-
function
|
|
4110
|
+
function Br(e, t, n, r) {
|
|
3208
4111
|
let i = 0;
|
|
3209
4112
|
for (let a of Object.values(e.runtime.modelStore?.models || {})) a.sources.some((e) => e.editor === t) && (n === "rename" ? a.updateModelSourceName(t, r || "") : a.removeModelSourceSimple(t), i += 1);
|
|
3210
4113
|
return i;
|
|
@@ -3224,10 +4127,10 @@ async function H(e, t = !1) {
|
|
|
3224
4127
|
suffix: r ? " The change is marked for autosave." : " The change was saved."
|
|
3225
4128
|
};
|
|
3226
4129
|
}
|
|
3227
|
-
function
|
|
4130
|
+
function Vr(e, t) {
|
|
3228
4131
|
return e > 0 ? ` The editor source was ${t} in ${e} model${e === 1 ? "" : "s"}.` : "";
|
|
3229
4132
|
}
|
|
3230
|
-
async function
|
|
4133
|
+
async function Hr(e, t) {
|
|
3231
4134
|
let n = e.runtime.connectionStore, r = n.connections[t.connectionId] || n.connectionByName(t.connection);
|
|
3232
4135
|
if (!r) return {
|
|
3233
4136
|
success: !1,
|
|
@@ -3241,15 +4144,15 @@ async function cn(e, t) {
|
|
|
3241
4144
|
success: !1,
|
|
3242
4145
|
error: `Editor "${t.name}" is empty.`
|
|
3243
4146
|
};
|
|
3244
|
-
let
|
|
4147
|
+
let a = {
|
|
3245
4148
|
text: t.contents,
|
|
3246
4149
|
editorType: t.type === "sql" ? "sql" : "trilogy",
|
|
3247
4150
|
imports: [],
|
|
3248
4151
|
currentFilename: t.name,
|
|
3249
|
-
extraContent:
|
|
4152
|
+
extraContent: xe(n, e.runtime.editorStore, r.id)
|
|
3250
4153
|
};
|
|
3251
4154
|
try {
|
|
3252
|
-
let n = await (await e.runtime.queryExecutionService.executeQuery(r.id,
|
|
4155
|
+
let n = await (await e.runtime.queryExecutionService.executeQuery(r.id, a)).resultPromise;
|
|
3253
4156
|
if (!n.success) return {
|
|
3254
4157
|
success: !1,
|
|
3255
4158
|
error: n.error || "Query execution failed",
|
|
@@ -3261,8 +4164,8 @@ async function cn(e, t) {
|
|
|
3261
4164
|
error: "Query returned no results"
|
|
3262
4165
|
};
|
|
3263
4166
|
t.chartConfig && t.results?.headers && t.results.headers.size > 0 && JSON.stringify(Array.from(t.results.headers.keys())) !== JSON.stringify(Array.from(n.results.headers.keys())) && t.setChartConfig(null), e.runtime.editorStore.setEditorResults(t.id, n.results), t.executed_contents = t.contents, n.generatedSql && (t.generated_sql = n.generatedSql), typeof n.executionTime == "number" && (t.duration = n.executionTime);
|
|
3264
|
-
let
|
|
3265
|
-
id:
|
|
4167
|
+
let o = {
|
|
4168
|
+
id: i(),
|
|
3266
4169
|
type: "results",
|
|
3267
4170
|
data: n.results,
|
|
3268
4171
|
config: {
|
|
@@ -3277,8 +4180,8 @@ async function cn(e, t) {
|
|
|
3277
4180
|
};
|
|
3278
4181
|
return {
|
|
3279
4182
|
success: !0,
|
|
3280
|
-
artifact:
|
|
3281
|
-
artifactId:
|
|
4183
|
+
artifact: o,
|
|
4184
|
+
artifactId: o.id,
|
|
3282
4185
|
executionTime: n.executionTime,
|
|
3283
4186
|
generatedSql: n.generatedSql
|
|
3284
4187
|
};
|
|
@@ -3289,7 +4192,7 @@ async function cn(e, t) {
|
|
|
3289
4192
|
};
|
|
3290
4193
|
}
|
|
3291
4194
|
}
|
|
3292
|
-
function
|
|
4195
|
+
function Ur() {
|
|
3293
4196
|
return [
|
|
3294
4197
|
{
|
|
3295
4198
|
pack: "editor",
|
|
@@ -3315,7 +4218,7 @@ function ln() {
|
|
|
3315
4218
|
message: e.connection ? `No editors found for connection "${e.connection}".` : "No editors exist yet. Use create_editor to make one."
|
|
3316
4219
|
} : {
|
|
3317
4220
|
success: !0,
|
|
3318
|
-
message: `${n.length} editor(s):\n${n.sort((e, t) => e.name.localeCompare(t.name)).map(
|
|
4221
|
+
message: `${n.length} editor(s):\n${n.sort((e, t) => e.name.localeCompare(t.name)).map(Lr).join("\n")}`
|
|
3319
4222
|
};
|
|
3320
4223
|
}
|
|
3321
4224
|
},
|
|
@@ -3339,7 +4242,7 @@ function ln() {
|
|
|
3339
4242
|
success: !1,
|
|
3340
4243
|
error: `Editor "${e.editor_ref}" not found. Use list_editors to see available editors.`
|
|
3341
4244
|
};
|
|
3342
|
-
let r = n.contents || "", i = r.split("\n").length, a = r.length >
|
|
4245
|
+
let r = n.contents || "", i = r.split("\n").length, a = r.length > Ir ? `${r.slice(0, Ir)}\n...(truncated at ${Ir} of ${r.length} characters)` : r;
|
|
3343
4246
|
return {
|
|
3344
4247
|
success: !0,
|
|
3345
4248
|
message: `Editor "${n.name}" (id ${n.id}, type ${n.type}, ${i} lines):\n\n${a}`
|
|
@@ -3435,19 +4338,19 @@ function ln() {
|
|
|
3435
4338
|
success: !1,
|
|
3436
4339
|
error: "New editor name cannot be empty."
|
|
3437
4340
|
};
|
|
3438
|
-
let i =
|
|
4341
|
+
let i = Rr(n, r), a = zr(t, n, i);
|
|
3439
4342
|
if (a) return {
|
|
3440
4343
|
success: !1,
|
|
3441
4344
|
error: `An editor named "${i}" already exists on connection "${n.connection}" (id ${a.id}).`
|
|
3442
4345
|
};
|
|
3443
4346
|
let o = n.name;
|
|
3444
4347
|
t.runtime.editorStore.updateEditorName(n.id, r);
|
|
3445
|
-
let s =
|
|
4348
|
+
let s = Br(t, n.id, "rename", n.name);
|
|
3446
4349
|
t.runtime.navigation?.updateTabName("editors", null, n.id);
|
|
3447
4350
|
let c = await H(t, s > 0);
|
|
3448
4351
|
return c.success ? {
|
|
3449
4352
|
success: !0,
|
|
3450
|
-
message: `Renamed editor "${o}" to "${n.name}" (id ${n.id}).${
|
|
4353
|
+
message: `Renamed editor "${o}" to "${n.name}" (id ${n.id}).${Vr(s, "renamed")}${c.suffix}`
|
|
3451
4354
|
} : c;
|
|
3452
4355
|
}
|
|
3453
4356
|
},
|
|
@@ -3525,12 +4428,12 @@ function ln() {
|
|
|
3525
4428
|
error: `Editor "${n.name}" is currently running. Wait for it to finish or cancel it before deleting.`
|
|
3526
4429
|
};
|
|
3527
4430
|
n.delete();
|
|
3528
|
-
let r =
|
|
4431
|
+
let r = Br(t, n.id, "delete");
|
|
3529
4432
|
t.runtime.navigation?.closeTab(null, n.id);
|
|
3530
4433
|
let i = await H(t, r > 0);
|
|
3531
4434
|
return i.success ? {
|
|
3532
4435
|
success: !0,
|
|
3533
|
-
message: `Deleted editor "${n.name}" (id ${n.id}).${
|
|
4436
|
+
message: `Deleted editor "${n.name}" (id ${n.id}).${Vr(r, "removed")}${i.suffix}`
|
|
3534
4437
|
} : i;
|
|
3535
4438
|
}
|
|
3536
4439
|
},
|
|
@@ -3550,7 +4453,7 @@ function ln() {
|
|
|
3550
4453
|
},
|
|
3551
4454
|
execute: async (e, t) => {
|
|
3552
4455
|
let n = V(t, String(e.editor_ref ?? ""));
|
|
3553
|
-
return n ?
|
|
4456
|
+
return n ? Hr(t, n) : {
|
|
3554
4457
|
success: !1,
|
|
3555
4458
|
error: `Editor "${e.editor_ref}" not found. Use list_editors to see available editors.`
|
|
3556
4459
|
};
|
|
@@ -3576,13 +4479,13 @@ function ln() {
|
|
|
3576
4479
|
required: ["query", "connection"]
|
|
3577
4480
|
}
|
|
3578
4481
|
},
|
|
3579
|
-
execute: (e, t) =>
|
|
4482
|
+
execute: (e, t) => Er(t).validateQuery(String(e.query ?? ""), String(e.connection ?? ""))
|
|
3580
4483
|
}
|
|
3581
4484
|
];
|
|
3582
4485
|
}
|
|
3583
4486
|
//#endregion
|
|
3584
4487
|
//#region llm/registry/packs/dashboardPack.ts
|
|
3585
|
-
var
|
|
4488
|
+
var Wr = [
|
|
3586
4489
|
"get_dashboard_state",
|
|
3587
4490
|
"list_dashboard_items",
|
|
3588
4491
|
"get_dashboard_item",
|
|
@@ -3596,7 +4499,7 @@ var un = [
|
|
|
3596
4499
|
"set_dashboard_theme",
|
|
3597
4500
|
"capture_dashboard_screenshot"
|
|
3598
4501
|
];
|
|
3599
|
-
function
|
|
4502
|
+
function Gr(e) {
|
|
3600
4503
|
return {
|
|
3601
4504
|
...e,
|
|
3602
4505
|
input_schema: {
|
|
@@ -3611,10 +4514,10 @@ function dn(e) {
|
|
|
3611
4514
|
}
|
|
3612
4515
|
};
|
|
3613
4516
|
}
|
|
3614
|
-
function
|
|
4517
|
+
function Kr(e, t) {
|
|
3615
4518
|
return t || e.runtime.screenBridge?.dashboard?.dashboardId || e.runtime.navigation?.activeDashboard.value || "";
|
|
3616
4519
|
}
|
|
3617
|
-
function
|
|
4520
|
+
function qr(e, t) {
|
|
3618
4521
|
let n = `dashboardExecutor:${t}`, r = e.session.cache.get(n);
|
|
3619
4522
|
if (r) return r;
|
|
3620
4523
|
let { dashboardStore: i, connectionStore: a, editorStore: o, chatStore: s, queryExecutionService: c } = e.runtime;
|
|
@@ -3630,7 +4533,7 @@ function pn(e, t) {
|
|
|
3630
4533
|
queryExecutionService: c,
|
|
3631
4534
|
llmConnectionStore: e.runtime.llmConnectionStore
|
|
3632
4535
|
};
|
|
3633
|
-
return r = new
|
|
4536
|
+
return r = new Hn({
|
|
3634
4537
|
dashboardStore: i,
|
|
3635
4538
|
connectionStore: a,
|
|
3636
4539
|
editorStore: o,
|
|
@@ -3638,7 +4541,7 @@ function pn(e, t) {
|
|
|
3638
4541
|
dashboardId: t,
|
|
3639
4542
|
getActiveImports: () => {
|
|
3640
4543
|
let e = i.dashboards[t];
|
|
3641
|
-
return e ?
|
|
4544
|
+
return e ? z(e) : [];
|
|
3642
4545
|
},
|
|
3643
4546
|
setActiveImports: (e) => {
|
|
3644
4547
|
i.updateDashboardImports(t, e.map((e) => ({
|
|
@@ -3649,7 +4552,7 @@ function pn(e, t) {
|
|
|
3649
4552
|
},
|
|
3650
4553
|
getDashboardQueryExecutor: () => {
|
|
3651
4554
|
let e = l();
|
|
3652
|
-
return e ? e.getDashboardQueryExecutor() ?? null :
|
|
4555
|
+
return e ? e.getDashboardQueryExecutor() ?? null : nr(t, u);
|
|
3653
4556
|
},
|
|
3654
4557
|
refreshItem: (e) => l()?.refreshItem(e) ?? void 0,
|
|
3655
4558
|
captureDashboardImage: async () => {
|
|
@@ -3659,13 +4562,13 @@ function pn(e, t) {
|
|
|
3659
4562
|
}
|
|
3660
4563
|
}), e.session.cache.set(n, r), r;
|
|
3661
4564
|
}
|
|
3662
|
-
async function
|
|
4565
|
+
async function Jr(e, t, n) {
|
|
3663
4566
|
let { dashboard_id: r, ...i } = t;
|
|
3664
4567
|
if (!n.runtime.dashboardStore) return {
|
|
3665
4568
|
success: !1,
|
|
3666
4569
|
error: "Dashboard store is not available in this context."
|
|
3667
4570
|
};
|
|
3668
|
-
let a =
|
|
4571
|
+
let a = Kr(n, r ? String(r) : void 0);
|
|
3669
4572
|
if (!a) return {
|
|
3670
4573
|
success: !1,
|
|
3671
4574
|
error: "No dashboard is currently in view. Pass dashboard_id, or use open_dashboard / list_dashboards first."
|
|
@@ -3674,23 +4577,23 @@ async function mn(e, t, n) {
|
|
|
3674
4577
|
return !o || o.deleted ? {
|
|
3675
4578
|
success: !1,
|
|
3676
4579
|
error: `Dashboard "${a}" not found.`
|
|
3677
|
-
} : (
|
|
4580
|
+
} : (ir.has(e) && (a = await or({
|
|
3678
4581
|
dashboard: o,
|
|
3679
4582
|
chatId: n.session.chatId,
|
|
3680
4583
|
chatStore: n.runtime.chatStore,
|
|
3681
4584
|
dashboardStore: n.runtime.dashboardStore,
|
|
3682
4585
|
setActiveDashboard: n.runtime.navigation ? (e) => n.runtime.navigation.setActiveDashboard(e) : void 0
|
|
3683
|
-
})),
|
|
4586
|
+
})), qr(n, a).executeToolCall(e, i));
|
|
3684
4587
|
}
|
|
3685
|
-
function
|
|
4588
|
+
function Yr() {
|
|
3686
4589
|
return [
|
|
3687
|
-
...
|
|
3688
|
-
let t =
|
|
4590
|
+
...Wr.map((e) => {
|
|
4591
|
+
let t = yn.find((t) => t.name === e);
|
|
3689
4592
|
if (!t) throw Error(`DASHBOARD_TOOLS is missing expected tool '${e}'`);
|
|
3690
4593
|
return {
|
|
3691
|
-
definition:
|
|
4594
|
+
definition: Gr(t),
|
|
3692
4595
|
pack: "dashboard",
|
|
3693
|
-
execute: (t, n) =>
|
|
4596
|
+
execute: (t, n) => Jr(e, t, n)
|
|
3694
4597
|
};
|
|
3695
4598
|
}),
|
|
3696
4599
|
{
|
|
@@ -3790,7 +4693,7 @@ function hn() {
|
|
|
3790
4693
|
hint: "No dashboard is mounted on screen. Use open_dashboard first, then retry."
|
|
3791
4694
|
},
|
|
3792
4695
|
execute: async (e, t) => {
|
|
3793
|
-
let n = t.runtime.screenBridge?.dashboard, r =
|
|
4696
|
+
let n = t.runtime.screenBridge?.dashboard, r = Kr(t, e.dashboard_id ? String(e.dashboard_id) : void 0);
|
|
3794
4697
|
if (!n || n.dashboardId !== r) return {
|
|
3795
4698
|
success: !1,
|
|
3796
4699
|
error: `Dashboard "${r}" is not the one on screen. Use open_dashboard first.`
|
|
@@ -3805,8 +4708,115 @@ function hn() {
|
|
|
3805
4708
|
];
|
|
3806
4709
|
}
|
|
3807
4710
|
//#endregion
|
|
3808
|
-
//#region
|
|
3809
|
-
var
|
|
4711
|
+
//#region data/connectionHistoryStorage.ts
|
|
4712
|
+
var Xr = 100, Zr = class {
|
|
4713
|
+
dbName;
|
|
4714
|
+
storeName;
|
|
4715
|
+
db;
|
|
4716
|
+
constructor() {
|
|
4717
|
+
this.dbName = "sqlEditorDB", this.storeName = "queryHistory", this.db = null, this._initDB();
|
|
4718
|
+
}
|
|
4719
|
+
async _initDB() {
|
|
4720
|
+
return new Promise((e, t) => {
|
|
4721
|
+
let n = indexedDB.open(this.dbName, 1);
|
|
4722
|
+
n.onerror = (e) => {
|
|
4723
|
+
console.error("Error opening IndexedDB:", e.target.error), t(e.target.error);
|
|
4724
|
+
}, n.onupgradeneeded = (e) => {
|
|
4725
|
+
let t = e.target.result;
|
|
4726
|
+
if (!t.objectStoreNames.contains(this.storeName)) {
|
|
4727
|
+
let e = t.createObjectStore(this.storeName, {
|
|
4728
|
+
keyPath: "id",
|
|
4729
|
+
autoIncrement: !0
|
|
4730
|
+
});
|
|
4731
|
+
e.createIndex("connectionName", "connectionName", { unique: !1 }), e.createIndex("timestamp", "timestamp", { unique: !1 });
|
|
4732
|
+
}
|
|
4733
|
+
}, n.onsuccess = (t) => {
|
|
4734
|
+
this.db = t.target.result, e();
|
|
4735
|
+
};
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
async addQuery(e, t) {
|
|
4739
|
+
this.db || await this._initDB();
|
|
4740
|
+
let n = {
|
|
4741
|
+
connectionName: e,
|
|
4742
|
+
query: t.query,
|
|
4743
|
+
generatedQuery: t.generatedQuery || null,
|
|
4744
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4745
|
+
executionTime: t.executionTime,
|
|
4746
|
+
status: t.status,
|
|
4747
|
+
errorMessage: t.errorMessage || null,
|
|
4748
|
+
resultSize: t.resultSize || 0,
|
|
4749
|
+
resultColumns: t.resultColumns || 0
|
|
4750
|
+
};
|
|
4751
|
+
return new Promise((t, r) => {
|
|
4752
|
+
if (!this.db) {
|
|
4753
|
+
r(/* @__PURE__ */ Error("Database not initialized"));
|
|
4754
|
+
return;
|
|
4755
|
+
}
|
|
4756
|
+
let i = this.db.transaction([this.storeName], "readwrite").objectStore(this.storeName).add(n);
|
|
4757
|
+
i.onsuccess = () => {
|
|
4758
|
+
this._enforceHistorySizeLimit(e).then(() => t(i.result)).catch(r);
|
|
4759
|
+
}, i.onerror = (e) => {
|
|
4760
|
+
console.error("Error adding query to history:", e.target.error), r(e.target.error);
|
|
4761
|
+
};
|
|
4762
|
+
});
|
|
4763
|
+
}
|
|
4764
|
+
async getQueriesForConnection(e, t = Xr) {
|
|
4765
|
+
return this.db || await this._initDB(), new Promise((n, r) => {
|
|
4766
|
+
if (!this.db) {
|
|
4767
|
+
r(/* @__PURE__ */ Error("Database not initialized"));
|
|
4768
|
+
return;
|
|
4769
|
+
}
|
|
4770
|
+
let i = this.db.transaction([this.storeName], "readonly").objectStore(this.storeName).index("connectionName").openCursor(IDBKeyRange.only(e), "prev"), a = [];
|
|
4771
|
+
i.onsuccess = (e) => {
|
|
4772
|
+
let r = e.target.result;
|
|
4773
|
+
r && a.length < t ? (a.push(r.value), r.continue()) : n(a);
|
|
4774
|
+
}, i.onerror = (e) => {
|
|
4775
|
+
console.error("Error retrieving query history:", e.target.error), r(e.target.error);
|
|
4776
|
+
};
|
|
4777
|
+
});
|
|
4778
|
+
}
|
|
4779
|
+
async clearConnectionHistory(e) {
|
|
4780
|
+
return this.db || await this._initDB(), new Promise((t, n) => {
|
|
4781
|
+
if (!this.db) {
|
|
4782
|
+
n(/* @__PURE__ */ Error("Database not initialized"));
|
|
4783
|
+
return;
|
|
4784
|
+
}
|
|
4785
|
+
let r = this.db.transaction([this.storeName], "readwrite").objectStore(this.storeName).index("connectionName").openCursor(IDBKeyRange.only(e));
|
|
4786
|
+
r.onsuccess = (e) => {
|
|
4787
|
+
let n = e.target.result;
|
|
4788
|
+
n ? (n.delete(), n.continue()) : t();
|
|
4789
|
+
}, r.onerror = (e) => {
|
|
4790
|
+
console.error("Error clearing history:", e.target.error), n(e.target.error);
|
|
4791
|
+
};
|
|
4792
|
+
});
|
|
4793
|
+
}
|
|
4794
|
+
async _enforceHistorySizeLimit(e) {
|
|
4795
|
+
return new Promise((t, n) => {
|
|
4796
|
+
if (!this.db) {
|
|
4797
|
+
n(/* @__PURE__ */ Error("Database not initialized"));
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
let r = this.db.transaction([this.storeName], "readwrite").objectStore(this.storeName).index("connectionName"), i = r.count(IDBKeyRange.only(e));
|
|
4801
|
+
i.onsuccess = () => {
|
|
4802
|
+
let a = i.result;
|
|
4803
|
+
if (a <= Xr) {
|
|
4804
|
+
t();
|
|
4805
|
+
return;
|
|
4806
|
+
}
|
|
4807
|
+
let o = a - Xr, s = r.openCursor(IDBKeyRange.only(e)), c = 0;
|
|
4808
|
+
s.onsuccess = (e) => {
|
|
4809
|
+
let n = e.target.result;
|
|
4810
|
+
n && c < o ? (n.delete(), c++, n.continue()) : t();
|
|
4811
|
+
}, s.onerror = (e) => {
|
|
4812
|
+
console.error("Error trimming history:", e.target.error), n(e.target.error);
|
|
4813
|
+
};
|
|
4814
|
+
}, i.onerror = (e) => {
|
|
4815
|
+
console.error("Error counting history records:", e.target.error), n(e.target.error);
|
|
4816
|
+
};
|
|
4817
|
+
});
|
|
4818
|
+
}
|
|
4819
|
+
}, Qr = 2e3, $r = 120, ei = 300;
|
|
3810
4820
|
function U(e) {
|
|
3811
4821
|
return e.runtime.jobsStore ? { available: !0 } : {
|
|
3812
4822
|
available: !1,
|
|
@@ -3816,8 +4826,8 @@ function U(e) {
|
|
|
3816
4826
|
function W(e) {
|
|
3817
4827
|
return `job ${e.job_id}: ${e.operation} "${e.target}" — status ${e.status}${e.error ? `, error: ${e.error}` : ""}${e.pollingState && e.pollingState !== "ok" ? ` (polling ${e.pollingState})` : ""}`;
|
|
3818
4828
|
}
|
|
3819
|
-
var
|
|
3820
|
-
function
|
|
4829
|
+
var ti = null, ni = () => (ti ||= new Zr(), ti);
|
|
4830
|
+
function ri() {
|
|
3821
4831
|
return [
|
|
3822
4832
|
{
|
|
3823
4833
|
pack: "jobs",
|
|
@@ -3972,14 +4982,14 @@ function xn() {
|
|
|
3972
4982
|
},
|
|
3973
4983
|
timeout_seconds: {
|
|
3974
4984
|
type: "number",
|
|
3975
|
-
description: `Max seconds to wait (default ${
|
|
4985
|
+
description: `Max seconds to wait (default ${$r}, max ${ei})`
|
|
3976
4986
|
}
|
|
3977
4987
|
},
|
|
3978
4988
|
required: ["store_id", "job_id"]
|
|
3979
4989
|
}
|
|
3980
4990
|
},
|
|
3981
4991
|
execute: async (e, t) => {
|
|
3982
|
-
let n = t.runtime.jobsStore, r = String(e.store_id), i = String(e.job_id), a = Math.min(
|
|
4992
|
+
let n = t.runtime.jobsStore, r = String(e.store_id), i = String(e.job_id), a = Math.min(ei, Math.max(1, Number(e.timeout_seconds) || $r)), o = Date.now() + a * 1e3, s = () => n.getStoreJobs(r).find((e) => e.job_id === i), c = s();
|
|
3983
4993
|
if (!c) return {
|
|
3984
4994
|
success: !1,
|
|
3985
4995
|
error: `Job ${i} not found in store ${r}.`
|
|
@@ -3989,7 +4999,7 @@ function xn() {
|
|
|
3989
4999
|
success: !1,
|
|
3990
5000
|
error: `Stopped waiting: ${W(c)}. ${c.pollingError || ""}`.trim()
|
|
3991
5001
|
};
|
|
3992
|
-
await new Promise((e) => setTimeout(e,
|
|
5002
|
+
await new Promise((e) => setTimeout(e, Qr)), c = s();
|
|
3993
5003
|
}
|
|
3994
5004
|
return c ? c.status === "running" ? {
|
|
3995
5005
|
success: !1,
|
|
@@ -4111,7 +5121,7 @@ function xn() {
|
|
|
4111
5121
|
execute: async (e, t) => {
|
|
4112
5122
|
let n = Math.max(1, Math.floor(Number(e.limit) || 10));
|
|
4113
5123
|
try {
|
|
4114
|
-
let t = await
|
|
5124
|
+
let t = await ni().getQueriesForConnection(String(e.connection));
|
|
4115
5125
|
return t.length ? {
|
|
4116
5126
|
success: !0,
|
|
4117
5127
|
message: t.slice(0, n).map((e) => {
|
|
@@ -4155,7 +5165,7 @@ var G = class {
|
|
|
4155
5165
|
constructor(e, t) {
|
|
4156
5166
|
this.title = e, this.articles = t;
|
|
4157
5167
|
}
|
|
4158
|
-
},
|
|
5168
|
+
}, ii = new K("Dashboards", [
|
|
4159
5169
|
new G("Purpose", "Trilogy is designed as a data consumption language, and one of the fastest ways to expore data is through visualization. The dashboarding system in Trilogy Studio is designed to be streamlined but powerful. The semantic model means that default selections can be tailored and rich."),
|
|
4160
5170
|
new G("Purpose", "It aspires to be good out of the box, with progressive disclosure of capability. It is designed to be extensible and feature requests are welcome."),
|
|
4161
5171
|
new G("Purpose", "We`ll use the demo model you set up in the first tutorial. If you haven`t done that yet, go back and run through the imports. Make sure you have a model and connection read to go below."),
|
|
@@ -4171,7 +5181,7 @@ var G = class {
|
|
|
4171
5181
|
new G("Purpose", "You can only crossfilter if fields exist on all charts. It's best to define anything you want to filter on in the base dashboard file, and avoid aliasing base fields.", "tip"),
|
|
4172
5182
|
new G("Purpose", "To fix the formatting of fields, ensure they have the appropriate types and traits in the model. For example, marking a year as a year type will make line charts eligible. See the model tutorial for more details. ", "tip"),
|
|
4173
5183
|
new G("Purpose", "For missing features [such as chart types] or other issues, please open an issue on the <a href=\"https://github.com/trilogy-data/trilogy-studio-core/issues\" target=\"_blank\">studio GitHub repo</a>.")
|
|
4174
|
-
], "Dashboard Tutorial"),
|
|
5184
|
+
], "Dashboard Tutorial"), ai = new K("Model Tutorial", [
|
|
4175
5185
|
new G("Purpose", "The prior two tutorials cover how to query data and create dashboards. Both of those rely on the foundational concept of Trilogy - the model."),
|
|
4176
5186
|
new G("Purpose", "A model is simply a collection of editors that have been marked as sources. Any source can be imported by name into another editor, or multiple times under different aliases. Composition of models is how more complex models are built."),
|
|
4177
5187
|
new G("Purpose", "The core aspects of models are concepts and datasources. Concepts represent the abstract logical model of the data, while datasources represent physical instantiations of it."),
|
|
@@ -4226,7 +5236,7 @@ var G = class {
|
|
|
4226
5236
|
new G("Purpose", "If you get any errors, double check names and that you have set the iris file as a source. If you get a \"no such table\" error, make sure you have run the startup script to create the table. \n ", "tip"),
|
|
4227
5237
|
new G("Purpose", "Make sure your file looks like the above. Now create a new trilogy editor by clicking the orange document icon by your connection. Copy the below code and run it! \n "),
|
|
4228
5238
|
new G("Further Reading", "Go to the model page under the trilogy reference section.\n ")
|
|
4229
|
-
], "Model Tutorial"),
|
|
5239
|
+
], "Model Tutorial"), oi = new K("Welcome", [
|
|
4230
5240
|
new G("Purpose", "Trilogy is a semantic-powered SQL - familiar SQL syntax that operates on a typed semantic layer, instead of tables. It should feel like SQL, but faster and more expressive. You can read more about the language in the Trilogy reference section."),
|
|
4231
5241
|
new G("Purpose", "Trilogy Studio is intended as an accessible demonstration of core language features, which would otherwise have a high barrier to experimentation. It is open source and feature requests and contributions are welcome."),
|
|
4232
5242
|
new G("Purpose", "In the rest of this tutorial, we will walk you through a demo-model - based on the TPC-H dataset - to get started. This will give you a feel for how Trilogy works and how you can use it to query data."),
|
|
@@ -4275,7 +5285,7 @@ var G = class {
|
|
|
4275
5285
|
new G("Purpose", "Thats the basics! You know how to run queries in an editor, how to import a model, and how to connect to a datasource.", "tip"),
|
|
4276
5286
|
new G("Purpose", "For the last query, could you figure out how to visualize the data? Editors support inline visualization for rapid introspection; to create more complicated visuals, check out the dashboarding tutorial up next.", "tip"),
|
|
4277
5287
|
new G("Purpose", "Feel free to explore from here. A good place to start is clicking on the editors icon in the left nav and exploring the pre-populated demo editors, which show more functionality. Alternatively, poke more around the docs!")
|
|
4278
|
-
], "Welcome and Query Tutorial"),
|
|
5288
|
+
], "Welcome and Query Tutorial"), si = new K("LLM Tutorial", [
|
|
4279
5289
|
new G("Connections", "LLMs can optionally be used to enhance the studio experience. The LLM screen is accessible on the left-hand nav and provides some basic validation that your LLM will work. LLMs is not required, but we aim to make the best use of them when available."),
|
|
4280
5290
|
new G("Connections", "Gemini has had some of the best results, but any lightweight fast model works well to build scaffolding quickly. You will need to QA answers.", "tip"),
|
|
4281
5291
|
new G("Connections", "Core LLM use cases are -query generation from natural language, dashboard generation from natural language, dashboard filtering with natural language, Feature requests welcome! To add an LLM, you will need an appropriate API key. Currently, we support OpenAI, Anthropic, and Google, but adding more is straightforward."),
|
|
@@ -4814,17 +5824,17 @@ var G = class {
|
|
|
4814
5824
|
outputPurpose: "Depends on first argument",
|
|
4815
5825
|
example: "SELECT SUM(revenue) AS total_revenue, GROUP SUM(revenue) BY product_category AS revenue_by_category, customer_id;"
|
|
4816
5826
|
} })
|
|
4817
|
-
]),
|
|
4818
|
-
if (
|
|
4819
|
-
var
|
|
4820
|
-
J.paragraphs[
|
|
4821
|
-
|
|
4822
|
-
...J.paragraphs.slice(
|
|
4823
|
-
]),
|
|
5827
|
+
]), ci = J.paragraphs.findIndex((e) => e.title === "Aggregate Functions"), li = J.paragraphs.findIndex((e) => e.title === "Date/Time Functions");
|
|
5828
|
+
if (ci < 0 || li < 0) throw Error("Built-in function documentation sections are incomplete");
|
|
5829
|
+
var ui = J.paragraphs[1], di = new K("Aggregate Functions", [
|
|
5830
|
+
J.paragraphs[ci],
|
|
5831
|
+
ui,
|
|
5832
|
+
...J.paragraphs.slice(ci + 1, li)
|
|
5833
|
+
]), fi = new K("Functions", [
|
|
4824
5834
|
new G("Trilogy Built-in Functions", "Trilogy provides built-in scalar functions for transforming and manipulating individual values. They are categorized into date/time, string, numeric, collection, and utility functions. Aggregate functions, which summarize groups of rows, are documented separately."),
|
|
4825
|
-
|
|
4826
|
-
...J.paragraphs.slice(
|
|
4827
|
-
]),
|
|
5835
|
+
ui,
|
|
5836
|
+
...J.paragraphs.slice(li)
|
|
5837
|
+
]), pi = new K("Window Functions", [
|
|
4828
5838
|
new G("Trilogy Built-in Functions", "Window functions are a set of built-in functions in the Trilogy query language that allow you to perform calculations across a set of rows related to the current row. These functions are essential for data analysis, reporting, and complex aggregations."),
|
|
4829
5839
|
new G("Function Usage & Concepts", "Each function definition includes its input requirements and output characteristics. Key information includes:\n <ul>\n <li><b>Input Types:</b> The allowed data types for each argument.</li>\n <li><b>Output Type:</b> The data type of the value returned by the function.</li>\n <li><b>Output Purpose:</b> Describes the conceptual role of the output.\n <ul>\n <li><b>PROPERTY:</b> Represents an attribute derived from existing data, typically associated with the grain of the input(s). Example: <code>UPPER(name)</code>.</li>\n <li><b>METRIC:</b> Represents a calculated value that summarizes data across rows, respecting the query's grouping. Example: <code>SUM(revenue)</code>.</li>\n <li><b>KEY:</b> Represents an identifier or a dimension used for joining or grouping, often changing the grain of the data. Example: <code>UNNEST(tags)</code>.</li>\n <li><b>CONSTANT:</b> Represents a fixed value, independent of the input data rows. Example: <code>CURRENT_DATE()</code>.</li>\n </ul>\n </li>\n </ul>"),
|
|
4830
5840
|
new G("RANK", "Computes the rank of each row within its partition, with ties receiving the same rank. The rank starts at 1 for the first row in each partition.", "function", { function: {
|
|
@@ -4845,7 +5855,7 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
4845
5855
|
outputPurpose: "PROPERTY",
|
|
4846
5856
|
example: "lead repo.license by license_repo_count desc;"
|
|
4847
5857
|
} })
|
|
4848
|
-
]),
|
|
5858
|
+
]), mi = new K("Modeling", [
|
|
4849
5859
|
new G("What is a Model?", "Models are the heart of Trilogy's semantic layer. They provide a structured, logical representation of data that can evolve independently of the underlying physical model. A model ist just a collection of Trilogy .preql files available for import. In Trilogy Studio, these are editors that have been marked as `sources`. These sources define the concepts, properties, and data retrieval logic for your domain."),
|
|
4850
5860
|
new G("Purpose and Benefits", "Models enable several key benefits:\n <ul>\n <li><strong>Abstraction:</strong> Define data logically using concepts (like 'customer' or 'order') independent of physical table names or structures.</li>\n <li><strong>Reusability:</strong> Define concepts and logic once in a model source and import them into any number of queries, reports, or other models.</li>\n <li><strong>Maintainability:</strong> If your database schema changes (e.g., table or column rename), you only need to update the corresponding datasource mapping in the model. Queries relying on the logical concepts remain unchanged.</li>\n <li><strong>Consistency:</strong> Ensures everyone querying the data uses the same definitions, metrics, and relationships.</li>\n <li><strong>Governance:</strong> Provides a centralized place to manage data definitions, access rules (via datasources), and metadata (types, traits).</li>\n </ul>", null, null),
|
|
4851
5861
|
new G("Core Components", "Models have two core components: Concepts and Datasources. These are defined within Trilogy editors marked as model sources.", "section"),
|
|
@@ -4868,7 +5878,7 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
4868
5878
|
new G("Model Parsing and Validation", "Models are parsed and validated to ensure correctness and build the metadata necessary for queries and tooling. This typically happens automatically when a query referencing the model is run. You can also trigger parsing manually (e.g., via a 'Parse Model' button in the UI). Parsing checks syntax, type consistency, and resolves imports. Errors found during parsing will be reported, often linking back to the specific editor and line number causing the issue.", "subsection", null),
|
|
4869
5879
|
new G("Standard Library", "Trilogy includes a standard library, typically available under the `std` namespace (e.g., `import std;` or `import std.math;`). This library provides common functions, operators, and useful metadata traits (like geo-location, currency, etc.).", "subsection", null),
|
|
4870
5880
|
new G("Tip: Standard Library", "Review the documentation for the standard library (`std`) to discover always-available functions and traits you can use in your models and queries.", "tip", null)
|
|
4871
|
-
], "Modeling"),
|
|
5881
|
+
], "Modeling"), hi = new q("Trilogy Reference", [
|
|
4872
5882
|
new K("Overview/Goals", [
|
|
4873
5883
|
new G("Introduction", "Trilogy is a new, SQL-derived language that compiles to SQL. Trilogy Studio provides you with both native Trilogy and SQL editors, allowing you to query your data in a way that is more expressive and easier to maintain than traditional SQL."),
|
|
4874
5884
|
new G("Introduction", "Trilogy aspires to simplify hard parts of SQL, keep and enhance the good, incentivize the best, and add modern reusability, type-checking, and ergonomics. It should be approachable to query by someone that knows only SQL, and easy to model for someone familiar with SQL or Python."),
|
|
@@ -4944,9 +5954,9 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
4944
5954
|
new G("Example", "SELECT\n order_date,\n order_year,\n SUM(total_spent) AS total_revenue;", "code"),
|
|
4945
5955
|
new G("What Is a Grain?", "This query would aggregate revenue to the grain of order_date, as order year is a property of order date.")
|
|
4946
5956
|
]),
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
5957
|
+
fi,
|
|
5958
|
+
di,
|
|
5959
|
+
pi,
|
|
4950
5960
|
new K("Custom Functions", [
|
|
4951
5961
|
new G("Defining Functions", "Custom functions can be used to extend the language with reusable code macros. Functions are defined using the def keyword and have a list of arguments and are mapped to an expression. Any argument alias will be locally scoped within the function, but external concepts can be referenced as well."),
|
|
4952
5962
|
new G("Defining Functions", "This function will multiple the input concept by itself and then by whatever the value of the global scale_factor is. Note the @ - custom functions references require the @ prefix."),
|
|
@@ -4954,8 +5964,8 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
4954
5964
|
new G("Defining Functions", "Functions may have optional defaults by adding an `= value` after the argument name."),
|
|
4955
5965
|
new G("Example", "def pretty_percent(x, digits=2) -> round(x*100, digits)::string || '%';\n\nconst number<-.4555;\n\nSELECT\n number,\n @pretty_percent(number) AS percent,\n @pretty_percent(number, 3) AS three_percent\n;", "code")
|
|
4956
5966
|
]),
|
|
4957
|
-
|
|
4958
|
-
]),
|
|
5967
|
+
mi
|
|
5968
|
+
]), gi = new q("Terms of Service", [new K("Terms of Service", [
|
|
4959
5969
|
new G("Last Updated", "February 22, 2025"),
|
|
4960
5970
|
new G("Service Description", "Trilogy Studio (referred to as \"IDE\" henceforth) enables users to interact with public data or data in databases they own. The IDE communicates with non-user services only to do basic telemetry and preprocessing of Trilogy code using the default language server (if a local one is not configured). The primary purpose of this preprocessing is to generate SQL to be returned to the browser for execution.", "section"),
|
|
4961
5971
|
new G("Data Privacy and Security", "No Data Collection: We do not collect, store, or process any of your data or database contents, beyond metadata provided in the model definition. All database interactions occur directly between your browser and your database through client-side JavaScript.", "section"),
|
|
@@ -4972,7 +5982,7 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
4972
5982
|
new G("Termination", "You may stop using the IDE at any time.", "section"),
|
|
4973
5983
|
new G("Contact", "For questions about these terms, please create an issue on the github repository <a href='https://github.com/trilogy-data/trilogy-studio-core'>here</a>.", "section"),
|
|
4974
5984
|
new G("Agreement", "By using the IDE, you agree to these terms and conditions.", "conclusion")
|
|
4975
|
-
])]),
|
|
5985
|
+
])]), _i = new K("Startup Scripts", [
|
|
4976
5986
|
new G("Connection Setup", "Startup scripts prepare a connection before you use it, for example by creating tables, loading data, or applying session settings. Once enabled on a SQL editor, they run automatically whenever that connection connects or resets. No separate run-on-connect setting is needed. This does not make the connection itself connect automatically when Studio opens."),
|
|
4977
5987
|
new G("Configure a Startup Script", "<ol>\n <li>Create or choose a connection in the Connections sidebar.</li>\n <li>Create a SQL editor associated with that connection and give it a descriptive name, such as <code>setup/load_sales.sql</code>.</li>\n <li>Write and test the setup SQL for your database.</li>\n <li>Enable <strong>Startup</strong> in the editor toolbar (the tooltip reads “Run this script on connection startup”).</li>\n <li>Save the editor and connection so the configuration is available after reloading Studio.</li>\n <li>Connect to run its startup scripts. If already connected, save your work, reload Studio, and reconnect to apply the setup.</li>\n </ol>"),
|
|
4978
5988
|
new G("Example: Prepare a DuckDB Table", "For a DuckDB connection, the following SQL creates a small table that other editors can query. CREATE OR REPLACE makes it safe to rerun when reconnecting or resetting. Use the equivalent repeatable setup syntax for your database."),
|
|
@@ -4981,12 +5991,12 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
4981
5991
|
new G("Multiple Scripts and Dependencies", "Separate startup scripts are launched in parallel, with no guaranteed execution order. Put dependent SQL statements in one script, in the order they need to run, using a database that supports multi-statement scripts. Design setup to be repeatable: use CREATE OR REPLACE or IF NOT EXISTS where appropriate, and avoid inserts that duplicate data on each reconnect.", "tip"),
|
|
4982
5992
|
new G("Diagnosing a Failure", "If a startup script fails, the connection is marked failed and the connection error popup identifies the script name (or remote file path), the connection, and the original database error. Open the named SQL editor, fix the SQL or the referenced data access, save it, and reconnect. For example, Startup script \"setup/load_sales.sql\" failed on connection \"analytics\" is followed by the database’s explanation. Other scripts may already have run; a startup failure does not roll back the entire group."),
|
|
4983
5993
|
new G("Disable a Startup Script", "Open the SQL editor, turn off Startup, and save. Future connections and resets will skip that script. Disabling it does not undo SQL that already ran, such as creating a table or loading data.")
|
|
4984
|
-
]),
|
|
5994
|
+
]), vi = [
|
|
4985
5995
|
new q("Studio", [
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
5996
|
+
oi,
|
|
5997
|
+
ii,
|
|
5998
|
+
ai,
|
|
5999
|
+
si,
|
|
4990
6000
|
new K("Functionality", [
|
|
4991
6001
|
new G("Tip", "Trilogy Studio is a statically hosted website that uses a mix of precompiled scripts and dynamic imports for some connections to reduce bundle size."),
|
|
4992
6002
|
new G("Tip", "For Trilogy specific features, the studio relies on a pseudo-language server (there is a proper LSP available for vs-code, used in the vs-code extension, as well). By default this will use a cloud-hosted backend but studio can be configured to use a local address as well. "),
|
|
@@ -5004,7 +6014,7 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
5004
6014
|
new G("ConnectionList", "", "connections"),
|
|
5005
6015
|
new G("Startup Scripts", "To prepare a connection automatically on connect or reset, enable Startup on a SQL editor associated with it. See Studio → Startup Scripts for setup instructions, examples, and troubleshooting.")
|
|
5006
6016
|
]),
|
|
5007
|
-
|
|
6017
|
+
_i,
|
|
5008
6018
|
new K("Scheduling", [new G("Scheduling", "Scheduling dashboards/scripts is a future feature. Please upvote this github issue: <a href=\"https://github.com/trilogy-data/trilogy-studio-core/issues/75\" target=\"_blank\">Scheduling</a>.")])
|
|
5009
6019
|
]),
|
|
5010
6020
|
new q("Supported Databases", [
|
|
@@ -5022,7 +6032,7 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
5022
6032
|
new K("BigQuery", [new G("BigQuery", "BigQuery is supported through OAuth authentication using your Google identity. If you wish to use a service key file, please upvote this GitHub issue: <a href=\"https://github.com/trilogy-data/trilogy-studio-core/issues/33\" target=\"_blank\">BQ Service Account Support</a>.")]),
|
|
5023
6033
|
new K("Snowflake", [new G("Snowflake", "Snowflake is supported with private key authentication. Read more at this link: <a href=\"https://docs.snowflake.com/en/user-guide/key-pair-auth\" target=\"_blank\">Snowflake Private Key Pairs</a>. Configure your Snowflake user with the public key, then provide the private key when connecting. Use caution when choosing whether to save this credential.")])
|
|
5024
6034
|
]),
|
|
5025
|
-
|
|
6035
|
+
hi,
|
|
5026
6036
|
new q("Privacy And Data", [
|
|
5027
6037
|
new K("Privacy Policy", [
|
|
5028
6038
|
new G("Last Updated", "February 22, 2025"),
|
|
@@ -5050,8 +6060,8 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
5050
6060
|
new K("Snowflake", [new G("Google Account", "Trilogy Studio supports private key authentication for Snowflake. You will need to provide the private key to connect after configuring your user with the public key portion in Snowflake directly. The rest of the authentication header can be derived from this.")]),
|
|
5051
6061
|
new K("Telemetry Details", [new G("Telemetry", "<a href=\"https://www.goatcounter.com/\">GoatCounter</a> is used to collect anonymized\n statistics about usage in the studio, such as feature usage. No uniquely identifying information is collected, though the system type, browser, screensize and country are recorded. You can disable telemetry in the settings menu.")])
|
|
5052
6062
|
]),
|
|
5053
|
-
|
|
5054
|
-
],
|
|
6063
|
+
gi
|
|
6064
|
+
], yi = /* @__PURE__ */ new Set([
|
|
5055
6065
|
"editors",
|
|
5056
6066
|
"connections",
|
|
5057
6067
|
"llm-connections",
|
|
@@ -5061,27 +6071,27 @@ var Dn = J.paragraphs[1], On = new K("Aggregate Functions", [
|
|
|
5061
6071
|
"editor-validator",
|
|
5062
6072
|
"connection-validator",
|
|
5063
6073
|
"model-validator"
|
|
5064
|
-
]),
|
|
5065
|
-
function
|
|
6074
|
+
]), bi = /* @__PURE__ */ new Set(["Trilogy Reference"]), Y = "Trilogy Language", xi = "Example: ";
|
|
6075
|
+
function Si(e) {
|
|
5066
6076
|
return e.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
5067
6077
|
}
|
|
5068
|
-
function
|
|
5069
|
-
let t =
|
|
6078
|
+
function Ci(e) {
|
|
6079
|
+
let t = Si(e.content || ""), n = e.data?.function;
|
|
5070
6080
|
return n && (t = [
|
|
5071
6081
|
t,
|
|
5072
6082
|
`Inputs: ${n.inputTypes.join(", ")}. Output: ${n.outputType} (${n.outputPurpose}).`,
|
|
5073
6083
|
`Example: ${n.example}`
|
|
5074
6084
|
].filter(Boolean).join(" ")), t;
|
|
5075
6085
|
}
|
|
5076
|
-
var
|
|
5077
|
-
function
|
|
5078
|
-
if (
|
|
6086
|
+
var wi = null;
|
|
6087
|
+
function Ti() {
|
|
6088
|
+
if (wi) return wi;
|
|
5079
6089
|
let e = [];
|
|
5080
|
-
for (let t of
|
|
5081
|
-
let n =
|
|
6090
|
+
for (let t of vi) {
|
|
6091
|
+
let n = bi.has(t.title);
|
|
5082
6092
|
for (let r of t.articles) for (let i of r.paragraphs) {
|
|
5083
|
-
if (i.type &&
|
|
5084
|
-
let a =
|
|
6093
|
+
if (i.type && yi.has(i.type)) continue;
|
|
6094
|
+
let a = Ci(i);
|
|
5085
6095
|
a && e.push({
|
|
5086
6096
|
id: `${t.title}/${r.title}/${i.title}`,
|
|
5087
6097
|
nodeTitle: t.title,
|
|
@@ -5092,37 +6102,37 @@ function Hn() {
|
|
|
5092
6102
|
});
|
|
5093
6103
|
}
|
|
5094
6104
|
}
|
|
5095
|
-
let t =
|
|
6105
|
+
let t = m.split(/^(?=#{1,3} )/m);
|
|
5096
6106
|
for (let n of t) {
|
|
5097
6107
|
let t = n.match(/^#{1,3} (.+)/);
|
|
5098
6108
|
if (!t) continue;
|
|
5099
6109
|
let r = t[1].trim(), i = n.slice(t[0].length).trim();
|
|
5100
6110
|
i && e.push({
|
|
5101
|
-
id: `${
|
|
5102
|
-
nodeTitle:
|
|
6111
|
+
id: `${Y}/Syntax Reference/${r}`,
|
|
6112
|
+
nodeTitle: Y,
|
|
5103
6113
|
articleTitle: "Syntax Reference",
|
|
5104
6114
|
paragraphTitle: r,
|
|
5105
6115
|
content: i,
|
|
5106
6116
|
kind: "language"
|
|
5107
6117
|
});
|
|
5108
6118
|
}
|
|
5109
|
-
for (let t of
|
|
5110
|
-
id: `${
|
|
5111
|
-
nodeTitle:
|
|
5112
|
-
articleTitle: `${
|
|
6119
|
+
for (let t of ke) t.body?.trim() && e.push({
|
|
6120
|
+
id: `${Y}/${xi}${t.name}/${t.title}`,
|
|
6121
|
+
nodeTitle: Y,
|
|
6122
|
+
articleTitle: `${xi}${t.name}`,
|
|
5113
6123
|
paragraphTitle: t.title,
|
|
5114
6124
|
content: `${t.summary}
|
|
5115
6125
|
|
|
5116
6126
|
${t.body.trim()}`,
|
|
5117
6127
|
kind: "language"
|
|
5118
6128
|
});
|
|
5119
|
-
return
|
|
6129
|
+
return wi = e, e;
|
|
5120
6130
|
}
|
|
5121
|
-
function
|
|
6131
|
+
function X(e) {
|
|
5122
6132
|
return e.toLowerCase().split(/[^a-z0-9_]+/).filter((e) => e.length > 1);
|
|
5123
6133
|
}
|
|
5124
|
-
function
|
|
5125
|
-
let n =
|
|
6134
|
+
function Ei(e, t) {
|
|
6135
|
+
let n = X(e.paragraphTitle), r = X(e.articleTitle), i = e.content.toLowerCase(), a = X(e.content), o = 0;
|
|
5126
6136
|
for (let e of t) {
|
|
5127
6137
|
n.includes(e) ? o += 3 : e.length >= 4 && n.some((t) => t.startsWith(e)) && (o += 1.5), r.includes(e) && (o += 2);
|
|
5128
6138
|
let t = a.filter((t) => t === e).length;
|
|
@@ -5130,29 +6140,29 @@ function Un(e, t) {
|
|
|
5130
6140
|
}
|
|
5131
6141
|
return o / Math.log(Math.max(e.content.length, 50));
|
|
5132
6142
|
}
|
|
5133
|
-
function
|
|
6143
|
+
function Di(e, t) {
|
|
5134
6144
|
let n = e.content.toLowerCase(), r = -1;
|
|
5135
6145
|
for (let e of t) if (r = n.indexOf(e), r >= 0) break;
|
|
5136
6146
|
r < 0 && (r = 0);
|
|
5137
6147
|
let i = Math.max(0, r - 80), a = Math.min(e.content.length, r + 160);
|
|
5138
6148
|
return `${i > 0 ? "…" : ""}${e.content.slice(i, a)}${a < e.content.length ? "…" : ""}`;
|
|
5139
6149
|
}
|
|
5140
|
-
function
|
|
5141
|
-
let n =
|
|
6150
|
+
function Oi(e, t = {}) {
|
|
6151
|
+
let n = X(e);
|
|
5142
6152
|
if (n.length === 0) return [];
|
|
5143
6153
|
let r = t.limit ?? 5;
|
|
5144
|
-
return
|
|
6154
|
+
return Ti().filter((e) => !t.kind || e.kind === t.kind).map((e) => ({
|
|
5145
6155
|
entry: e,
|
|
5146
|
-
score:
|
|
6156
|
+
score: Ei(e, n)
|
|
5147
6157
|
})).filter((e) => e.score > 0).sort((e, t) => t.score - e.score).slice(0, r).map((e) => ({
|
|
5148
6158
|
...e,
|
|
5149
|
-
snippet:
|
|
6159
|
+
snippet: Di(e.entry, n)
|
|
5150
6160
|
}));
|
|
5151
6161
|
}
|
|
5152
|
-
function
|
|
6162
|
+
function ki(e) {
|
|
5153
6163
|
let [t, n] = e.split("/");
|
|
5154
6164
|
if (!t || !n) return null;
|
|
5155
|
-
let r =
|
|
6165
|
+
let r = Ti().filter((e) => e.nodeTitle === t && e.articleTitle === n);
|
|
5156
6166
|
return r.length === 0 ? null : {
|
|
5157
6167
|
id: `${t}/${n}`,
|
|
5158
6168
|
nodeTitle: t,
|
|
@@ -5165,7 +6175,7 @@ function Kn(e) {
|
|
|
5165
6175
|
}
|
|
5166
6176
|
//#endregion
|
|
5167
6177
|
//#region llm/registry/packs/docsPack.ts
|
|
5168
|
-
function
|
|
6178
|
+
function Ai() {
|
|
5169
6179
|
return [
|
|
5170
6180
|
{
|
|
5171
6181
|
pack: "docs",
|
|
@@ -5197,7 +6207,7 @@ function qn() {
|
|
|
5197
6207
|
}
|
|
5198
6208
|
},
|
|
5199
6209
|
execute: async (e) => {
|
|
5200
|
-
let t =
|
|
6210
|
+
let t = Oi(String(e.query ?? ""), {
|
|
5201
6211
|
limit: Number(e.limit) || 5,
|
|
5202
6212
|
kind: e.kind
|
|
5203
6213
|
});
|
|
@@ -5225,7 +6235,7 @@ function qn() {
|
|
|
5225
6235
|
}
|
|
5226
6236
|
},
|
|
5227
6237
|
execute: async (e) => {
|
|
5228
|
-
let t =
|
|
6238
|
+
let t = ki(String(e.doc_id ?? ""));
|
|
5229
6239
|
return t ? {
|
|
5230
6240
|
success: !0,
|
|
5231
6241
|
message: `${t.nodeTitle} > ${t.articleTitle}\n\n${t.paragraphs.map((e) => `## ${e.title}\n${e.content}`).join("\n\n")}`
|
|
@@ -5254,7 +6264,7 @@ function qn() {
|
|
|
5254
6264
|
hint: "App navigation is not available in this embedding context."
|
|
5255
6265
|
},
|
|
5256
6266
|
execute: async (e, t) => {
|
|
5257
|
-
let n =
|
|
6267
|
+
let n = ki(String(e.doc_id ?? ""));
|
|
5258
6268
|
if (!n) return {
|
|
5259
6269
|
success: !1,
|
|
5260
6270
|
error: `Documentation "${e.doc_id}" not found. Use search_docs to find valid ids.`
|
|
@@ -5274,7 +6284,7 @@ function qn() {
|
|
|
5274
6284
|
}
|
|
5275
6285
|
//#endregion
|
|
5276
6286
|
//#region llm/registry/packs/contextPack.ts
|
|
5277
|
-
function
|
|
6287
|
+
function ji() {
|
|
5278
6288
|
return [{
|
|
5279
6289
|
pack: "context",
|
|
5280
6290
|
definition: {
|
|
@@ -5297,20 +6307,20 @@ function Jn() {
|
|
|
5297
6307
|
}
|
|
5298
6308
|
//#endregion
|
|
5299
6309
|
//#region llm/registry/index.ts
|
|
5300
|
-
function
|
|
5301
|
-
let e = new
|
|
5302
|
-
return e.registerAll(
|
|
6310
|
+
function Mi() {
|
|
6311
|
+
let e = new br();
|
|
6312
|
+
return e.registerAll(Or()), e.registerAll(kr()), e.registerAll(Fr()), e.registerAll(Ur()), e.registerAll(Yr()), e.registerAll(ri()), e.registerAll(Ai()), e.registerAll(ji()), e.registerAll(Ar()), e;
|
|
5303
6313
|
}
|
|
5304
|
-
var
|
|
5305
|
-
function
|
|
5306
|
-
return
|
|
6314
|
+
var Ni = null;
|
|
6315
|
+
function Pi() {
|
|
6316
|
+
return Ni ||= Mi(), Ni;
|
|
5307
6317
|
}
|
|
5308
6318
|
//#endregion
|
|
5309
6319
|
//#region llm/architectAgentPrompt.ts
|
|
5310
|
-
function
|
|
6320
|
+
function Fi(e) {
|
|
5311
6321
|
return ` - ${e.name} (${e.type}, ${e.size} bytes)`;
|
|
5312
6322
|
}
|
|
5313
|
-
function
|
|
6323
|
+
function Ii() {
|
|
5314
6324
|
return `You are an ARCHITECT subchat. Your job is to build a Trilogy data model from the raw files attached to this project. The user does not see this conversation — your overseer does. Work autonomously; when finished, call return_to_user with a brief summary.
|
|
5315
6325
|
|
|
5316
6326
|
TYPICAL WORKFLOW:
|
|
@@ -5325,7 +6335,7 @@ TYPICAL WORKFLOW:
|
|
|
5325
6335
|
6. return_to_user with a list of the files created and any caveats.
|
|
5326
6336
|
|
|
5327
6337
|
TRILOGY LANGUAGE REFERENCE:
|
|
5328
|
-
${
|
|
6338
|
+
${m}
|
|
5329
6339
|
|
|
5330
6340
|
OPERATIONAL GUIDELINES:
|
|
5331
6341
|
- One .preql file per logical entity (one per CSV is a good default).
|
|
@@ -5334,15 +6344,15 @@ OPERATIONAL GUIDELINES:
|
|
|
5334
6344
|
- Don't return until at least one file validates cleanly and a smoke query succeeds, OR you've exhausted reasonable attempts and need to report blockers.
|
|
5335
6345
|
- Errors from the resolver are authoritative — read them carefully; don't guess fixes.`;
|
|
5336
6346
|
}
|
|
5337
|
-
function
|
|
5338
|
-
let t = e.files.length > 0 ? `FILES IN THIS PROJECT:\n${e.files.map(
|
|
5339
|
-
return `${e.instructionsOverride?.trim() ||
|
|
6347
|
+
function Li(e) {
|
|
6348
|
+
let t = e.files.length > 0 ? `FILES IN THIS PROJECT:\n${e.files.map(Fi).join("\n")}` : "No files in this project yet.", n = e.dataConnectionName ? `DATA CONNECTION: ${e.dataConnectionName}${e.isDataConnectionActive ? "" : " (not yet connected — first run_trilogy_query will boot it)"}` : "No data connection bound.";
|
|
6349
|
+
return `${e.instructionsOverride?.trim() || Ii()}
|
|
5340
6350
|
|
|
5341
6351
|
${t}
|
|
5342
6352
|
${n}
|
|
5343
6353
|
`;
|
|
5344
6354
|
}
|
|
5345
|
-
var
|
|
6355
|
+
var Ri = [
|
|
5346
6356
|
{
|
|
5347
6357
|
name: "list_project_files",
|
|
5348
6358
|
description: "List every file attached to the current project: name, type (preql / csv / sql / markdown / etc.), size in bytes.",
|
|
@@ -5482,12 +6492,12 @@ var tr = [
|
|
|
5482
6492
|
required: ["query"]
|
|
5483
6493
|
}
|
|
5484
6494
|
},
|
|
5485
|
-
|
|
5486
|
-
],
|
|
5487
|
-
function
|
|
5488
|
-
|
|
6495
|
+
we
|
|
6496
|
+
], zi = [];
|
|
6497
|
+
function Bi(e) {
|
|
6498
|
+
zi.push(e);
|
|
5489
6499
|
}
|
|
5490
|
-
var
|
|
6500
|
+
var Vi = b("chats", {
|
|
5491
6501
|
state: () => ({
|
|
5492
6502
|
chats: {},
|
|
5493
6503
|
activeChatId: "",
|
|
@@ -5507,11 +6517,11 @@ var ir = Ee("chats", {
|
|
|
5507
6517
|
},
|
|
5508
6518
|
actions: {
|
|
5509
6519
|
newChat(e, t = "", n, r = "", i = {}) {
|
|
5510
|
-
let a = new
|
|
6520
|
+
let a = new f({
|
|
5511
6521
|
llmConnectionName: e,
|
|
5512
6522
|
dataConnectionName: t,
|
|
5513
6523
|
dataConnectionId: r,
|
|
5514
|
-
name: n ||
|
|
6524
|
+
name: n || Ae()
|
|
5515
6525
|
});
|
|
5516
6526
|
return this.chats[a.id] = a, i.activate !== !1 && (this.activeChatId = a.id), a;
|
|
5517
6527
|
},
|
|
@@ -5519,7 +6529,7 @@ var ir = Ee("chats", {
|
|
|
5519
6529
|
this.chats[e.id] = e;
|
|
5520
6530
|
},
|
|
5521
6531
|
removeChat(e) {
|
|
5522
|
-
this.chats[e] && (this.chats[e].deleted = !0, this.chats[e].changed = !0, this.activeChatId === e && (this.activeChatId = ""),
|
|
6532
|
+
this.chats[e] && (this.chats[e].deleted = !0, this.chats[e].changed = !0, this.activeChatId === e && (this.activeChatId = ""), zi.forEach((t) => {
|
|
5523
6533
|
try {
|
|
5524
6534
|
t(e);
|
|
5525
6535
|
} catch (e) {
|
|
@@ -5565,7 +6575,7 @@ var ir = Ee("chats", {
|
|
|
5565
6575
|
},
|
|
5566
6576
|
loadChats(e) {
|
|
5567
6577
|
Object.entries(e).forEach(([e, t]) => {
|
|
5568
|
-
this.chats[e] =
|
|
6578
|
+
this.chats[e] = f.fromSerialized(t);
|
|
5569
6579
|
});
|
|
5570
6580
|
},
|
|
5571
6581
|
serializeChats() {
|
|
@@ -5596,7 +6606,7 @@ var ir = Ee("chats", {
|
|
|
5596
6606
|
},
|
|
5597
6607
|
pauseExecution(e) {
|
|
5598
6608
|
let t = this.chatExecutions[e];
|
|
5599
|
-
|
|
6609
|
+
t && t.isLoading && (t.paused = !0);
|
|
5600
6610
|
},
|
|
5601
6611
|
resumeExecution(e) {
|
|
5602
6612
|
let t = this.chatExecutions[e];
|
|
@@ -5626,37 +6636,37 @@ var ir = Ee("chats", {
|
|
|
5626
6636
|
clearExecution(e) {
|
|
5627
6637
|
delete this.chatExecutions[e];
|
|
5628
6638
|
},
|
|
5629
|
-
async executeMessage(e, t,
|
|
5630
|
-
let
|
|
5631
|
-
if (!
|
|
5632
|
-
let { llmConnectionStore:
|
|
5633
|
-
if (!
|
|
6639
|
+
async executeMessage(e, t, r, i = {}) {
|
|
6640
|
+
let a = this.chats[e];
|
|
6641
|
+
if (!a) return { response: "Chat not found." };
|
|
6642
|
+
let { llmConnectionStore: o, connectionStore: s, queryExecutionService: l, editorStore: u } = r, d = a.llmConnectionName || o.activeConnection;
|
|
6643
|
+
if (!d) return this.addMessageToChat(e, {
|
|
5634
6644
|
role: "user",
|
|
5635
6645
|
content: t,
|
|
5636
|
-
hidden:
|
|
6646
|
+
hidden: i.hiddenUserMessage ?? !1
|
|
5637
6647
|
}), this.addMessageToChat(e, {
|
|
5638
6648
|
role: "assistant",
|
|
5639
6649
|
content: "Error: No LLM connection available. Please configure an LLM provider first.",
|
|
5640
6650
|
error: !0
|
|
5641
6651
|
}), { response: "No LLM connection available. Please configure an LLM provider first." };
|
|
5642
|
-
let
|
|
5643
|
-
|
|
5644
|
-
let
|
|
6652
|
+
let f = o.connections[d];
|
|
6653
|
+
f && await c(f, a), this.startExecution(e);
|
|
6654
|
+
let p = this.chatExecutions[e], m = () => this.chatExecutions[e] === p, h = p?.abortController?.signal, g = !1;
|
|
5645
6655
|
this.addMessageToChat(e, {
|
|
5646
6656
|
role: "user",
|
|
5647
6657
|
content: t,
|
|
5648
|
-
hidden:
|
|
6658
|
+
hidden: i.hiddenUserMessage ?? !1
|
|
5649
6659
|
});
|
|
5650
6660
|
try {
|
|
5651
|
-
let
|
|
5652
|
-
let
|
|
6661
|
+
let c = { generateCompletion: async (t, n, r) => {
|
|
6662
|
+
let i = {
|
|
5653
6663
|
...n,
|
|
5654
|
-
signal:
|
|
6664
|
+
signal: h,
|
|
5655
6665
|
onRateLimitBackoff: (t, n) => {
|
|
5656
6666
|
this.setRateLimitBackoff(e, t, n);
|
|
5657
6667
|
}
|
|
5658
|
-
}, s = await
|
|
5659
|
-
return this.clearRateLimitBackoff(e), s.usage && (
|
|
6668
|
+
}, s = await o.generateCompletion(t, i, r);
|
|
6669
|
+
return this.clearRateLimitBackoff(e), s.usage && (a.lastContextTokens = s.usage.promptTokens + (s.usage.cacheCreationTokens ?? 0) + (s.usage.cacheReadTokens ?? 0), a.changed = !0), s;
|
|
5660
6670
|
} }, f = {
|
|
5661
6671
|
addMessage: (t) => {
|
|
5662
6672
|
this.addMessageToChat(e, t);
|
|
@@ -5669,32 +6679,32 @@ var ir = Ee("chats", {
|
|
|
5669
6679
|
hidden: !1
|
|
5670
6680
|
});
|
|
5671
6681
|
},
|
|
5672
|
-
getMessages: () =>
|
|
5673
|
-
}, p =
|
|
5674
|
-
if (!
|
|
5675
|
-
let t = new
|
|
6682
|
+
getMessages: () => a.getLLMMessages()
|
|
6683
|
+
}, p = i.overrides ? { getToolExecutor: () => ({ executeToolCall: i.overrides.executeToolCall }) } : a.kind === "overseer" ? (() => {
|
|
6684
|
+
if (!r.projectStore) throw Error("Overseer chats require deps.projectStore");
|
|
6685
|
+
let t = new lr(this, r.projectStore, e, r, r.dashboardStore);
|
|
5676
6686
|
return { getToolExecutor: () => t };
|
|
5677
|
-
})() :
|
|
5678
|
-
if (!
|
|
5679
|
-
let t = new
|
|
6687
|
+
})() : a.kind === "architect" ? (() => {
|
|
6688
|
+
if (!r.projectStore) throw Error("Architect subchats require deps.projectStore");
|
|
6689
|
+
let t = new fr(this, r.projectStore, u, s, l, e);
|
|
5680
6690
|
return { getToolExecutor: () => t };
|
|
5681
6691
|
})() : (() => {
|
|
5682
|
-
let t =
|
|
5683
|
-
connectionStore:
|
|
5684
|
-
editorStore:
|
|
6692
|
+
let t = Pi().createExecutor("chat", {
|
|
6693
|
+
connectionStore: s,
|
|
6694
|
+
editorStore: u,
|
|
5685
6695
|
chatStore: this,
|
|
5686
|
-
queryExecutionService:
|
|
5687
|
-
...
|
|
6696
|
+
queryExecutionService: l,
|
|
6697
|
+
...r.dashboardStore ? { dashboardStore: r.dashboardStore } : {}
|
|
5688
6698
|
}, {
|
|
5689
6699
|
chatId: e,
|
|
5690
6700
|
cache: /* @__PURE__ */ new Map()
|
|
5691
|
-
}),
|
|
5692
|
-
if (
|
|
5693
|
-
let a = { executeToolCall: async (e,
|
|
5694
|
-
let
|
|
5695
|
-
if (!
|
|
6701
|
+
}), n = new Map((i.extraTools ?? []).map((e) => [e.definition.name, e]));
|
|
6702
|
+
if (n.size === 0) return { getToolExecutor: () => t };
|
|
6703
|
+
let a = { executeToolCall: async (e, r) => {
|
|
6704
|
+
let i = n.get(e);
|
|
6705
|
+
if (!i) return t.executeToolCall(e, r);
|
|
5696
6706
|
try {
|
|
5697
|
-
return await
|
|
6707
|
+
return await i.execute(r);
|
|
5698
6708
|
} catch (t) {
|
|
5699
6709
|
return {
|
|
5700
6710
|
success: !1,
|
|
@@ -5703,24 +6713,24 @@ var ir = Ee("chats", {
|
|
|
5703
6713
|
}
|
|
5704
6714
|
} };
|
|
5705
6715
|
return { getToolExecutor: () => a };
|
|
5706
|
-
})(),
|
|
6716
|
+
})(), m = {
|
|
5707
6717
|
setActiveToolName: (t) => this.setActiveToolName(e, t),
|
|
5708
|
-
checkAborted: () =>
|
|
6718
|
+
checkAborted: () => h?.aborted ?? !1,
|
|
5709
6719
|
isPaused: () => this.chatExecutions[e]?.paused ?? !1
|
|
5710
|
-
}, ee =
|
|
5711
|
-
t.triggersSymbolRefresh &&
|
|
5712
|
-
};
|
|
5713
|
-
|
|
5714
|
-
tools:
|
|
5715
|
-
maxIterations:
|
|
5716
|
-
noToolCallReminder:
|
|
5717
|
-
terminateOnNoToolCall:
|
|
6720
|
+
}, ee = i.overrides ? i.overrides.buildSystemPrompt : () => this.buildSystemPrompt(e, r, i.disabledTools), te = i.overrides ? void 0 : async (e, t) => {
|
|
6721
|
+
t.triggersSymbolRefresh && i.onSymbolsRefresh && await i.onSymbolsRefresh();
|
|
6722
|
+
}, ne = i.overrides ? i.overrides.tools : a.kind === "overseer" ? _n : a.kind === "architect" ? Ri : ie(Oe(Pi().getToolsetForContext("chat"), i.disabledTools), i.extraTools);
|
|
6723
|
+
g = !!(await n(t, d, c, f, p, m, {
|
|
6724
|
+
tools: ne,
|
|
6725
|
+
maxIterations: i.overrides?.maxIterations ?? 50,
|
|
6726
|
+
noToolCallReminder: i.overrides?.noToolCallReminder ?? "You must call a tool to proceed. If you are finished, call return_to_user with a summary of what was done. Do not respond with text only.",
|
|
6727
|
+
terminateOnNoToolCall: i.overrides?.terminateOnNoToolCall,
|
|
5718
6728
|
buildSystemPrompt: ee,
|
|
5719
6729
|
onToolResult: te
|
|
5720
6730
|
})).stopped;
|
|
5721
6731
|
} catch (t) {
|
|
5722
|
-
if (t instanceof DOMException && t.name === "AbortError" ||
|
|
5723
|
-
|
|
6732
|
+
if (t instanceof DOMException && t.name === "AbortError" || h?.aborted) {
|
|
6733
|
+
g = !0, m() && this.completeExecution(e);
|
|
5724
6734
|
return;
|
|
5725
6735
|
}
|
|
5726
6736
|
let n = t instanceof Error ? t.message : "An unknown error occurred";
|
|
@@ -5728,11 +6738,11 @@ var ir = Ee("chats", {
|
|
|
5728
6738
|
role: "assistant",
|
|
5729
6739
|
content: `Error: ${n}`,
|
|
5730
6740
|
error: !0
|
|
5731
|
-
}),
|
|
6741
|
+
}), m() && this.completeExecution(e, n);
|
|
5732
6742
|
} finally {
|
|
5733
|
-
|
|
6743
|
+
m() && p.isLoading && this.completeExecution(e);
|
|
5734
6744
|
}
|
|
5735
|
-
|
|
6745
|
+
!g && m() && (this.handleSubchatCompletion(e, r).catch((e) => console.error("handleSubchatCompletion failed", e)), this.drainPendingInjections(e, r).catch((e) => console.error("drainPendingInjections failed", e)));
|
|
5736
6746
|
},
|
|
5737
6747
|
async handleSubchatCompletion(e, t) {
|
|
5738
6748
|
let n = this.chats[e];
|
|
@@ -5741,7 +6751,7 @@ var ir = Ee("chats", {
|
|
|
5741
6751
|
if (!r) return;
|
|
5742
6752
|
let i = t.llmConnectionStore.connections[n.llmConnectionName] ?? t.llmConnectionStore.connections[r.llmConnectionName] ?? null, a;
|
|
5743
6753
|
if (i) try {
|
|
5744
|
-
a = await
|
|
6754
|
+
a = await te(i, n, "completion");
|
|
5745
6755
|
} catch (e) {
|
|
5746
6756
|
console.error("subchat summarization failed; falling back", e), a = n.messages[n.messages.length - 1]?.content?.trim() || "(no summary available — subchat finished but the auto-summary call failed)";
|
|
5747
6757
|
}
|
|
@@ -5764,7 +6774,7 @@ var ir = Ee("chats", {
|
|
|
5764
6774
|
id: e.id,
|
|
5765
6775
|
name: e.name.replace(/\//g, "."),
|
|
5766
6776
|
alias: ""
|
|
5767
|
-
})) : [], d =
|
|
6777
|
+
})) : [], d = re({
|
|
5768
6778
|
dataConnectionName: o,
|
|
5769
6779
|
availableConnections: s,
|
|
5770
6780
|
availableConcepts: [],
|
|
@@ -5775,7 +6785,7 @@ var ir = Ee("chats", {
|
|
|
5775
6785
|
});
|
|
5776
6786
|
if (r.kind === "analyst") {
|
|
5777
6787
|
let e = r.parentProjectId || t.projectStore?.activeProjectId || "";
|
|
5778
|
-
return `${(e ? t.projectStore?.projects[e] : null)?.promptOverrides.analyst?.trim() ||
|
|
6788
|
+
return `${(e ? t.projectStore?.projects[e] : null)?.promptOverrides.analyst?.trim() || fn}\n\n${d}`;
|
|
5779
6789
|
}
|
|
5780
6790
|
return d;
|
|
5781
6791
|
},
|
|
@@ -5787,7 +6797,7 @@ var ir = Ee("chats", {
|
|
|
5787
6797
|
type: e.type,
|
|
5788
6798
|
size: (e.contents || "").length
|
|
5789
6799
|
})) : [], o = i?.dataConnectionId && t.connectionStore.connections[i.dataConnectionId] || null;
|
|
5790
|
-
return
|
|
6800
|
+
return Li({
|
|
5791
6801
|
projectName: i?.name,
|
|
5792
6802
|
projectDescription: i?.description,
|
|
5793
6803
|
files: a,
|
|
@@ -5811,7 +6821,7 @@ var ir = Ee("chats", {
|
|
|
5811
6821
|
});
|
|
5812
6822
|
}
|
|
5813
6823
|
let s = a ? a.editorIds.map((e) => i?.editors[e]?.name).filter((e) => !!e) : [];
|
|
5814
|
-
return
|
|
6824
|
+
return gn({
|
|
5815
6825
|
projectName: a?.name,
|
|
5816
6826
|
projectDescription: a?.description,
|
|
5817
6827
|
subchats: o,
|
|
@@ -5824,14 +6834,14 @@ var ir = Ee("chats", {
|
|
|
5824
6834
|
});
|
|
5825
6835
|
//#endregion
|
|
5826
6836
|
//#region llm/editorRefinementRuntime.ts
|
|
5827
|
-
function
|
|
5828
|
-
let { editorStore: n, chatStore: r, llmConnectionStore: i } = t, a = n.editors[e],
|
|
5829
|
-
if (!a || !
|
|
5830
|
-
if (
|
|
5831
|
-
let e = r.chats[
|
|
5832
|
-
if (e && !e.deleted) return
|
|
5833
|
-
}
|
|
5834
|
-
let
|
|
6837
|
+
function Hi(e, t) {
|
|
6838
|
+
let { editorStore: n, chatStore: r, llmConnectionStore: i } = t, a = n.editors[e], o = a?.refinementSession;
|
|
6839
|
+
if (!a || !o) return null;
|
|
6840
|
+
if (o.refinementChatId) {
|
|
6841
|
+
let e = r.chats[o.refinementChatId];
|
|
6842
|
+
if (e && !e.deleted) return o.refinementChatId;
|
|
6843
|
+
}
|
|
6844
|
+
let s = new f({
|
|
5835
6845
|
name: `Refine: ${a.name}`,
|
|
5836
6846
|
llmConnectionName: i.activeConnection || "",
|
|
5837
6847
|
dataConnectionName: a.connection,
|
|
@@ -5839,29 +6849,29 @@ function ar(e, t) {
|
|
|
5839
6849
|
sourceRefId: e,
|
|
5840
6850
|
storage: "ephemeral"
|
|
5841
6851
|
});
|
|
5842
|
-
return r.addChat(
|
|
6852
|
+
return r.addChat(s), n.updateRefinementSession(e, { refinementChatId: s.id }), s.id;
|
|
5843
6853
|
}
|
|
5844
|
-
var
|
|
5845
|
-
function
|
|
5846
|
-
let t =
|
|
5847
|
-
return t || (t =
|
|
6854
|
+
var Z = /* @__PURE__ */ new Map(), Q = /* @__PURE__ */ new Map();
|
|
6855
|
+
function Ui(e) {
|
|
6856
|
+
let t = Q.get(e);
|
|
6857
|
+
return t || (t = he(), Q.set(e, t)), t;
|
|
5848
6858
|
}
|
|
5849
|
-
|
|
5850
|
-
|
|
6859
|
+
Bi((e) => {
|
|
6860
|
+
Z.delete(e), Q.delete(e);
|
|
5851
6861
|
});
|
|
5852
|
-
function
|
|
5853
|
-
|
|
6862
|
+
function Wi(e) {
|
|
6863
|
+
Z.delete(e);
|
|
5854
6864
|
}
|
|
5855
|
-
async function
|
|
5856
|
-
let { editorId: t, message: n, stores: r, deps: i, callbacks: a = {} } = e, { editorStore: o, chatStore:
|
|
5857
|
-
if (!
|
|
5858
|
-
let
|
|
5859
|
-
if (!
|
|
5860
|
-
let
|
|
6865
|
+
async function Gi(e) {
|
|
6866
|
+
let { editorId: t, message: n, stores: r, deps: i, callbacks: a = {} } = e, { editorStore: o, chatStore: c } = r, l = o.editors[t];
|
|
6867
|
+
if (!l || !l.refinementSession) return;
|
|
6868
|
+
let u = Hi(t, r);
|
|
6869
|
+
if (!u) return;
|
|
6870
|
+
let d = !1, f, p = () => {
|
|
5861
6871
|
let e = o.editors[t]?.refinementSession;
|
|
5862
6872
|
return e ? {
|
|
5863
|
-
editorType:
|
|
5864
|
-
connectionName:
|
|
6873
|
+
editorType: l.type,
|
|
6874
|
+
connectionName: l.connection,
|
|
5865
6875
|
editorContents: e.currentContent,
|
|
5866
6876
|
selectedText: e.selectedText,
|
|
5867
6877
|
selectionRange: e.selectionRange,
|
|
@@ -5885,13 +6895,13 @@ async function cr(e) {
|
|
|
5885
6895
|
o.updateRefinementSession(t, { currentChartConfig: e }), a.onChartConfigChange?.(e);
|
|
5886
6896
|
},
|
|
5887
6897
|
onFinish: (e) => {
|
|
5888
|
-
|
|
6898
|
+
d = !0, f = e;
|
|
5889
6899
|
},
|
|
5890
6900
|
onRunActiveEditorQuery: a.onRunActiveEditorQuery ? () => a.onRunActiveEditorQuery() : void 0,
|
|
5891
6901
|
getCurrentResults: () => o.editors[t]?.results ?? null
|
|
5892
6902
|
} : {
|
|
5893
|
-
editorType:
|
|
5894
|
-
connectionName:
|
|
6903
|
+
editorType: l.type,
|
|
6904
|
+
connectionName: l.connection,
|
|
5895
6905
|
editorContents: "",
|
|
5896
6906
|
selectedText: void 0,
|
|
5897
6907
|
selectionRange: void 0,
|
|
@@ -5901,32 +6911,139 @@ async function cr(e) {
|
|
|
5901
6911
|
onFinish: () => {}
|
|
5902
6912
|
};
|
|
5903
6913
|
};
|
|
5904
|
-
await
|
|
5905
|
-
tools:
|
|
5906
|
-
executeToolCall: (e, t) => new
|
|
6914
|
+
await c.executeMessage(u, n, i, { overrides: {
|
|
6915
|
+
tools: h(l.type),
|
|
6916
|
+
executeToolCall: (e, t) => new Te(i.queryExecutionService, i.connectionStore, p(), o, Ui(u)).executeToolCall(e, t),
|
|
5907
6917
|
buildSystemPrompt: () => {
|
|
5908
|
-
let e =
|
|
6918
|
+
let e = Z.get(u);
|
|
5909
6919
|
if (!e) {
|
|
5910
|
-
let n = o.editors[t]?.refinementSession
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
editorContents: n?.currentContent ?? c.contents,
|
|
6920
|
+
let n = o.editors[t]?.refinementSession, r = {
|
|
6921
|
+
editorType: l.type,
|
|
6922
|
+
connectionName: l.connection,
|
|
6923
|
+
editorContents: n?.currentContent ?? l.contents,
|
|
5915
6924
|
selectedText: n?.selectedText,
|
|
5916
6925
|
selectionRange: n?.selectionRange,
|
|
5917
6926
|
chartConfig: n?.currentChartConfig,
|
|
5918
|
-
completionSymbols:
|
|
5919
|
-
}
|
|
6927
|
+
completionSymbols: l.completionSymbols || []
|
|
6928
|
+
};
|
|
6929
|
+
e = s(r), Z.set(u, e);
|
|
5920
6930
|
}
|
|
5921
6931
|
return e;
|
|
5922
6932
|
},
|
|
5923
6933
|
maxIterations: 20,
|
|
5924
6934
|
noToolCallReminder: "You must call a tool to proceed. If you are finished with the requested changes, call request_close to wrap up the session. Do not respond with text only."
|
|
5925
|
-
} }),
|
|
6935
|
+
} }), d && o.editors[t]?.refinementSession && o.acceptRefinement(t, { onFinish: () => a.onFinish?.(f) });
|
|
5926
6936
|
}
|
|
5927
|
-
function
|
|
6937
|
+
function Ki(e, t) {
|
|
5928
6938
|
let n = t.editorStore.editors[e]?.refinementSession?.refinementChatId;
|
|
5929
|
-
n && (t.chatStore.isChatExecuting(n) && t.chatStore.stopExecution(n), t.chatStore.removeChat(n),
|
|
6939
|
+
n && (t.chatStore.isChatExecuting(n) && t.chatStore.stopExecution(n), t.chatStore.removeChat(n), Wi(n), Q.delete(n));
|
|
5930
6940
|
}
|
|
5931
6941
|
//#endregion
|
|
5932
|
-
|
|
6942
|
+
//#region stores/editorStore.ts
|
|
6943
|
+
var $ = b("editors", {
|
|
6944
|
+
state: () => ({
|
|
6945
|
+
editors: {},
|
|
6946
|
+
activeEditorName: "",
|
|
6947
|
+
activeEditorId: ""
|
|
6948
|
+
}),
|
|
6949
|
+
getters: {
|
|
6950
|
+
editorList: (e) => Object.keys(e.editors).map((t) => e.editors[t]),
|
|
6951
|
+
unsavedEditors: (e) => Object.values(e.editors).filter((e) => e.changed).length
|
|
6952
|
+
},
|
|
6953
|
+
actions: {
|
|
6954
|
+
newEditor(e, t, n, r, i = {}) {
|
|
6955
|
+
let a = L().connectionByName(n), o = i.storage || a?.storage || "local", s = i.remoteStoreId || o === "remote" && a?.remoteStoreId || null, c = o === "remote" ? x(e, t) : e, l = o === "remote" ? x(i.remotePath || c, t) : null, u = o === "remote" ? `remote:${s || "store"}:${encodeURIComponent(l || c)}` : c, d = u, f = 1;
|
|
6956
|
+
for (; this.editors[d];) d = `${u}#${f}`, f++;
|
|
6957
|
+
let p = new Xe({
|
|
6958
|
+
id: d,
|
|
6959
|
+
name: c,
|
|
6960
|
+
type: t,
|
|
6961
|
+
connection: n,
|
|
6962
|
+
storage: o,
|
|
6963
|
+
contents: r || "",
|
|
6964
|
+
remoteStoreId: s,
|
|
6965
|
+
remotePath: l || void 0,
|
|
6966
|
+
remotePersisted: i.remotePersisted || !1
|
|
6967
|
+
});
|
|
6968
|
+
return this.editors[p.id] = p, p;
|
|
6969
|
+
},
|
|
6970
|
+
addEditor(e) {
|
|
6971
|
+
this.editors[e.id] = e;
|
|
6972
|
+
},
|
|
6973
|
+
getEditorByName(e) {
|
|
6974
|
+
let t = Object.values(this.editors).filter((t) => t.name === e);
|
|
6975
|
+
return t.find((e) => !e.deleted) ?? t[0];
|
|
6976
|
+
},
|
|
6977
|
+
getConnectionEditors(e, t = []) {
|
|
6978
|
+
let n = Object.values(this.editors).filter((t) => t.connectionId === e);
|
|
6979
|
+
return t.length === 0 ? n : n.filter((e) => t.every((t) => e.tags.includes(t)));
|
|
6980
|
+
},
|
|
6981
|
+
updateEditorName(e, t) {
|
|
6982
|
+
this.editors[e].setName(t);
|
|
6983
|
+
},
|
|
6984
|
+
removeEditor(e) {
|
|
6985
|
+
if (this.editors[e]) this.editors[e].deleted = !0;
|
|
6986
|
+
else return !1;
|
|
6987
|
+
},
|
|
6988
|
+
setEditorScrollPosition(e, t) {
|
|
6989
|
+
if (this.editors[e]) this.editors[e].scrollPosition = t;
|
|
6990
|
+
else throw Error(`Editor with id "${e}" not found.`);
|
|
6991
|
+
},
|
|
6992
|
+
setEditorContents(e, t) {
|
|
6993
|
+
if (this.editors[e]) this.editors[e].setContent(t);
|
|
6994
|
+
else throw Error(`Editor with id "${e}" not found.`);
|
|
6995
|
+
},
|
|
6996
|
+
setEditorResults(e, t) {
|
|
6997
|
+
if (this.editors[e]) {
|
|
6998
|
+
let n = this.editors[e];
|
|
6999
|
+
n.results = t, n.setError(null);
|
|
7000
|
+
} else throw Error(`Editor with id "${e}" not found.`);
|
|
7001
|
+
},
|
|
7002
|
+
getCurrentEditorAutocomplete(e) {
|
|
7003
|
+
if (!this.activeEditorId) return [];
|
|
7004
|
+
let t = this.editors[this.activeEditorId];
|
|
7005
|
+
return e ? t.getAutocomplete(e) : [];
|
|
7006
|
+
},
|
|
7007
|
+
startRefinementSession(e, t = {}) {
|
|
7008
|
+
let n = this.editors[e];
|
|
7009
|
+
if (!n) return;
|
|
7010
|
+
let r = {
|
|
7011
|
+
messages: [],
|
|
7012
|
+
artifacts: [],
|
|
7013
|
+
originalContent: n.contents,
|
|
7014
|
+
originalChartConfig: n.chartConfig || void 0,
|
|
7015
|
+
currentContent: n.contents,
|
|
7016
|
+
currentChartConfig: n.chartConfig || void 0,
|
|
7017
|
+
selectedText: t.selectedText,
|
|
7018
|
+
selectionRange: t.selectionRange,
|
|
7019
|
+
wasLoading: !1
|
|
7020
|
+
};
|
|
7021
|
+
n.setRefinementSession(r);
|
|
7022
|
+
},
|
|
7023
|
+
updateRefinementSession(e, t) {
|
|
7024
|
+
let n = this.editors[e];
|
|
7025
|
+
n && n.refinementSession && n.setRefinementSession({
|
|
7026
|
+
...n.refinementSession,
|
|
7027
|
+
...t
|
|
7028
|
+
});
|
|
7029
|
+
},
|
|
7030
|
+
clearRefinementSession(e) {
|
|
7031
|
+
let t = this.editors[e];
|
|
7032
|
+
t && (Ki(e, {
|
|
7033
|
+
editorStore: this,
|
|
7034
|
+
chatStore: Vi()
|
|
7035
|
+
}), t.setRefinementSession(null));
|
|
7036
|
+
},
|
|
7037
|
+
discardRefinement(e, t) {
|
|
7038
|
+
let n = this.editors[e];
|
|
7039
|
+
if (!n?.refinementSession) return;
|
|
7040
|
+
let r = n.refinementSession;
|
|
7041
|
+
n.setContent(r.originalContent), t?.onContentChange?.(r.originalContent), r.originalChartConfig && (n.setChartConfig(r.originalChartConfig), t?.onChartConfigChange?.(r.originalChartConfig)), t?.onDiscard?.(), this.clearRefinementSession(e);
|
|
7042
|
+
},
|
|
7043
|
+
acceptRefinement(e, t) {
|
|
7044
|
+
t?.onFinish?.("Changes accepted"), this.clearRefinementSession(e);
|
|
7045
|
+
}
|
|
7046
|
+
}
|
|
7047
|
+
});
|
|
7048
|
+
//#endregion
|
|
7049
|
+
export { Ze as $, Ht as A, bt as B, an as C, P as D, en as E, At as F, Ct as G, Et as H, Lt as I, xt as J, St as K, Ft as L, j as M, Ot as N, Kt as O, Rt as P, T as Q, It as R, L as S, Qt as T, yt as U, _t as V, vt as W, it as X, dt as Y, Qe as Z, An as _, Pi as a, x as at, On as b, cr as c, We as ct, Wn as d, Ue as dt, Xe as et, Un as f, Nn as g, Mn as h, Vi as i, C as it, M as j, Bt as k, Xn as l, qe as lt, Fn as m, Gi as n, S as nt, vi as o, Je as ot, Pn as p, Dt as q, Bi as r, He as rt, Zr as s, Ke as st, $ as t, w as tt, Yn as u, Ge as ut, jn as v, Zt as w, un as x, kn as y, Tt as z };
|