grain-tools 0.10.16 → 0.10.17
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/connection-setup.html +79 -9
- package/dist/credential-page.html +54 -2
- package/dist/mcp-app.html +0 -21
- package/dist/web-app.html +407 -197
- package/out/server/standalone.js +327 -198
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/web-app.html
CHANGED
|
@@ -13780,21 +13780,15 @@ async function buildGuideHubState() {
|
|
|
13780
13780
|
}
|
|
13781
13781
|
const WEB_SESSION_KEY = "grain:web-session-id";
|
|
13782
13782
|
function resolveWebSessionId() {
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
13786
|
-
} catch {
|
|
13787
|
-
return `web-${crypto.randomUUID()}`;
|
|
13783
|
+
const stored = readStoredValue(WEB_SESSION_KEY);
|
|
13784
|
+
if (stored && /^web-[0-9a-f-]{36}$/.test(stored)) {
|
|
13785
|
+
return stored;
|
|
13788
13786
|
}
|
|
13789
13787
|
return `web-${crypto.randomUUID()}`;
|
|
13790
13788
|
}
|
|
13791
13789
|
const WEB_SESSION_ID = resolveWebSessionId();
|
|
13792
13790
|
function rememberWebSessionId() {
|
|
13793
|
-
|
|
13794
|
-
window.sessionStorage.setItem(WEB_SESSION_KEY, WEB_SESSION_ID);
|
|
13795
|
-
} catch {
|
|
13796
|
-
return;
|
|
13797
|
-
}
|
|
13791
|
+
writeStoredValue(WEB_SESSION_KEY, WEB_SESSION_ID);
|
|
13798
13792
|
}
|
|
13799
13793
|
function resolveProjectedTarget(tabId, payload) {
|
|
13800
13794
|
const parsed = tabId ? parseProjectedTabId(tabId) : void 0;
|
|
@@ -14051,6 +14045,8 @@ function useWebTabSync(options) {
|
|
|
14051
14045
|
remoteId: tab.id,
|
|
14052
14046
|
sessionDisplayName: session.displayName,
|
|
14053
14047
|
clientType: session.clientType,
|
|
14048
|
+
connectionId: tab.connectionId,
|
|
14049
|
+
connectionName: tab.connectionName,
|
|
14054
14050
|
isRemote: true,
|
|
14055
14051
|
preserveFocus
|
|
14056
14052
|
});
|
|
@@ -14068,6 +14064,8 @@ function useWebTabSync(options) {
|
|
|
14068
14064
|
remoteId: tab.id,
|
|
14069
14065
|
sessionDisplayName: session.displayName,
|
|
14070
14066
|
clientType: session.clientType,
|
|
14067
|
+
connectionId: tab.connectionId,
|
|
14068
|
+
connectionName: tab.connectionName,
|
|
14071
14069
|
isRemote: true,
|
|
14072
14070
|
preserveFocus
|
|
14073
14071
|
});
|
|
@@ -14088,6 +14086,8 @@ function useWebTabSync(options) {
|
|
|
14088
14086
|
remoteId: tab.id,
|
|
14089
14087
|
sessionDisplayName: session.displayName,
|
|
14090
14088
|
clientType: session.clientType,
|
|
14089
|
+
connectionId: detail.connectionId ?? tab.connectionId,
|
|
14090
|
+
connectionName: detail.connectionName ?? tab.connectionName,
|
|
14091
14091
|
isRemote: true
|
|
14092
14092
|
};
|
|
14093
14093
|
if (tab.status === "success") {
|
|
@@ -14164,7 +14164,7 @@ function useWebTabSync(options) {
|
|
|
14164
14164
|
dispatchLoading(session, tab, true);
|
|
14165
14165
|
}
|
|
14166
14166
|
} else if (tab.status === "success" || tab.status === "error" || !cached || cached.status !== tab.status) {
|
|
14167
|
-
const detailIsNeeded = tab.status === "success" && (!cached || !storeHasTab || cached.status !== tab.status || cached.rowCount !== tab.rowCount);
|
|
14167
|
+
const detailIsNeeded = tab.status === "success" && (!cached || !storeHasTab || cached.status !== tab.status || cached.rowCount !== tab.rowCount || cached.connectionId !== tab.connectionId);
|
|
14168
14168
|
const errorIsNeeded = tab.status === "error" && (!cached || !storeHasTab || cached.status !== "error");
|
|
14169
14169
|
if (detailIsNeeded || errorIsNeeded) {
|
|
14170
14170
|
await dispatchTabDetail(session, tab);
|
|
@@ -14175,7 +14175,8 @@ function useWebTabSync(options) {
|
|
|
14175
14175
|
remoteTabId: tab.id,
|
|
14176
14176
|
status: tab.status,
|
|
14177
14177
|
rowCount: tab.rowCount,
|
|
14178
|
-
title: tab.title
|
|
14178
|
+
title: tab.title,
|
|
14179
|
+
connectionId: tab.connectionId
|
|
14179
14180
|
});
|
|
14180
14181
|
}
|
|
14181
14182
|
})
|
|
@@ -14694,7 +14695,10 @@ function ConnectionSetupPage({
|
|
|
14694
14695
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Connection failed" }),
|
|
14695
14696
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: error })
|
|
14696
14697
|
] }),
|
|
14697
|
-
tested && !error && /* @__PURE__ */ jsxRuntimeExports.
|
|
14698
|
+
tested && !error && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", role: "status", children: [
|
|
14699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
14700
|
+
"Connection test successful."
|
|
14701
|
+
] }),
|
|
14698
14702
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-grid", children: [
|
|
14699
14703
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-field", children: [
|
|
14700
14704
|
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-type", children: "Database type" }),
|
|
@@ -14782,7 +14786,10 @@ function ConnectionSetupPage({
|
|
|
14782
14786
|
] })
|
|
14783
14787
|
] }),
|
|
14784
14788
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-footer", children: [
|
|
14785
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
14789
|
+
tested && !error ? /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", children: [
|
|
14790
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
14791
|
+
"Connection test successful."
|
|
14792
|
+
] }) : error ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "grain-connection-footer-error", children: error }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Grain will test the connection before saving it." }),
|
|
14786
14793
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-actions", children: [
|
|
14787
14794
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14788
14795
|
"button",
|
|
@@ -75125,7 +75132,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75125
75132
|
nativeTheme = false,
|
|
75126
75133
|
disableFilters = false,
|
|
75127
75134
|
autoSizeStrategy,
|
|
75128
|
-
fillWidth = false,
|
|
75129
75135
|
onCellDoubleClick
|
|
75130
75136
|
}, ref) {
|
|
75131
75137
|
const trackUi = useTrackUi();
|
|
@@ -75294,21 +75300,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75294
75300
|
}),
|
|
75295
75301
|
[data, getNodeValue, copyIncludesHeaders]
|
|
75296
75302
|
);
|
|
75297
|
-
const userResizedRef = reactExports.useRef(false);
|
|
75298
|
-
const fillSpareWidth = reactExports.useCallback((e2) => {
|
|
75299
|
-
if (userResizedRef.current) return;
|
|
75300
|
-
const body = e2.api.getHorizontalPixelRange?.();
|
|
75301
|
-
const columns = (e2.api.getAllDisplayedColumns?.() ?? []).filter((c) => !c.getPinned());
|
|
75302
|
-
if (!body || columns.length === 0) return;
|
|
75303
|
-
const used = columns.reduce((sum2, c) => sum2 + c.getActualWidth(), 0);
|
|
75304
|
-
if (used < body.right - body.left) e2.api.sizeColumnsToFit();
|
|
75305
|
-
}, []);
|
|
75306
|
-
const noteUserResize = reactExports.useCallback((e2) => {
|
|
75307
|
-
if (e2.source === "uiColumnResized" && e2.finished) userResizedRef.current = true;
|
|
75308
|
-
}, []);
|
|
75309
|
-
reactExports.useEffect(() => {
|
|
75310
|
-
userResizedRef.current = false;
|
|
75311
|
-
}, [data?.columns]);
|
|
75312
75303
|
const columnDefs = reactExports.useMemo(() => {
|
|
75313
75304
|
if (!data?.columns) return [];
|
|
75314
75305
|
const isInRange = (rowIndex, displayedColIndex) => {
|
|
@@ -75493,11 +75484,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75493
75484
|
onGridReady: (p) => {
|
|
75494
75485
|
apiRef.current = p.api;
|
|
75495
75486
|
},
|
|
75496
|
-
...fillWidth ? {
|
|
75497
|
-
onFirstDataRendered: fillSpareWidth,
|
|
75498
|
-
onGridSizeChanged: fillSpareWidth,
|
|
75499
|
-
onColumnResized: noteUserResize
|
|
75500
|
-
} : {},
|
|
75501
75487
|
rowData: data.rows,
|
|
75502
75488
|
columnDefs,
|
|
75503
75489
|
defaultColDef: {
|
|
@@ -152517,7 +152503,7 @@ function SidebarAddButton({ label, title, onClick }) {
|
|
|
152517
152503
|
}
|
|
152518
152504
|
);
|
|
152519
152505
|
}
|
|
152520
|
-
function SqlEditor({ value, onChange, onRun }) {
|
|
152506
|
+
function SqlEditor({ value, onChange, onRun, readOnly = false }) {
|
|
152521
152507
|
const frameRef = reactExports.useRef(null);
|
|
152522
152508
|
const gutterRef = reactExports.useRef(null);
|
|
152523
152509
|
const lineCount = value.split("\n").length;
|
|
@@ -152544,12 +152530,13 @@ function SqlEditor({ value, onChange, onRun }) {
|
|
|
152544
152530
|
spellCheck: false,
|
|
152545
152531
|
wrap: "off",
|
|
152546
152532
|
value,
|
|
152533
|
+
readOnly,
|
|
152547
152534
|
onChange: (event) => onChange(event.target.value),
|
|
152548
152535
|
onScroll: (event) => {
|
|
152549
152536
|
if (gutterRef.current) gutterRef.current.scrollTop = event.currentTarget.scrollTop;
|
|
152550
152537
|
},
|
|
152551
152538
|
onKeyDown: (event) => {
|
|
152552
|
-
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
152539
|
+
if (!readOnly && (event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
152553
152540
|
event.preventDefault();
|
|
152554
152541
|
onRun();
|
|
152555
152542
|
}
|
|
@@ -152558,12 +152545,199 @@ function SqlEditor({ value, onChange, onRun }) {
|
|
|
152558
152545
|
)
|
|
152559
152546
|
] });
|
|
152560
152547
|
}
|
|
152548
|
+
function displayQueryTitle(title, sql) {
|
|
152549
|
+
if (title.trim() && !/^Result \d+$/.test(title.trim())) return title;
|
|
152550
|
+
const line = sql.replace(/\/\*[\s\S]*?\*\//g, "").split("\n").map((part) => part.trim()).find((part) => part && !part.startsWith("--"))?.replace(/\s+/g, " ");
|
|
152551
|
+
if (!line) return title.trim() || "Query";
|
|
152552
|
+
return line.length > 40 ? `${line.slice(0, 40).trimEnd()}…` : line;
|
|
152553
|
+
}
|
|
152554
|
+
function resultText(result, fallback) {
|
|
152555
|
+
return result.content?.find((item) => item.type === "text")?.text ?? fallback;
|
|
152556
|
+
}
|
|
152557
|
+
function failed(result) {
|
|
152558
|
+
return Boolean(result.isError) || result.structuredContent?.["success"] === false;
|
|
152559
|
+
}
|
|
152560
|
+
function ConnectionPage({
|
|
152561
|
+
connection,
|
|
152562
|
+
onNewQuery,
|
|
152563
|
+
onEdit,
|
|
152564
|
+
onDeleted
|
|
152565
|
+
}) {
|
|
152566
|
+
const { callServerTool } = useHostContext();
|
|
152567
|
+
const [test, setTest] = reactExports.useState(null);
|
|
152568
|
+
const [confirmingDelete, setConfirmingDelete] = reactExports.useState(false);
|
|
152569
|
+
const [deleteError, setDeleteError] = reactExports.useState("");
|
|
152570
|
+
const label = connection.name ?? connection.id;
|
|
152571
|
+
const runTest = async () => {
|
|
152572
|
+
setTest({ kind: "testing" });
|
|
152573
|
+
try {
|
|
152574
|
+
const result = await callServerTool("test_connection", { connectionId: connection.id });
|
|
152575
|
+
setTest(
|
|
152576
|
+
failed(result) ? { kind: "failed", message: resultText(result, "Connection test failed") } : { kind: "passed" }
|
|
152577
|
+
);
|
|
152578
|
+
} catch (error) {
|
|
152579
|
+
setTest({
|
|
152580
|
+
kind: "failed",
|
|
152581
|
+
message: error instanceof Error ? error.message : "Connection test failed"
|
|
152582
|
+
});
|
|
152583
|
+
}
|
|
152584
|
+
};
|
|
152585
|
+
const confirmDelete = async () => {
|
|
152586
|
+
setDeleteError("");
|
|
152587
|
+
try {
|
|
152588
|
+
const result = await callServerTool("delete_connection", { connectionId: connection.id });
|
|
152589
|
+
if (failed(result)) throw new Error(resultText(result, "Could not delete connection"));
|
|
152590
|
+
onDeleted();
|
|
152591
|
+
} catch (error) {
|
|
152592
|
+
setDeleteError(error instanceof Error ? error.message : "Could not delete connection");
|
|
152593
|
+
}
|
|
152594
|
+
};
|
|
152595
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-detail", children: [
|
|
152596
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: label }),
|
|
152597
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
152598
|
+
connection.type ?? "Database",
|
|
152599
|
+
" ·",
|
|
152600
|
+
" ",
|
|
152601
|
+
connection.engineState === "ready" ? "Ready" : "Saved connection"
|
|
152602
|
+
] }),
|
|
152603
|
+
test?.kind === "testing" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { role: "status", children: "Testing…" }),
|
|
152604
|
+
test?.kind === "passed" && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "sp-web-connection-test-success", role: "status", children: [
|
|
152605
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
152606
|
+
"Connection test successful."
|
|
152607
|
+
] }),
|
|
152608
|
+
test?.kind === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-connection-test-error", role: "alert", children: test.message }),
|
|
152609
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-actions", children: [
|
|
152610
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152611
|
+
"button",
|
|
152612
|
+
{
|
|
152613
|
+
type: "button",
|
|
152614
|
+
className: "sp-web-primary-button",
|
|
152615
|
+
"aria-label": `New query for ${label}`,
|
|
152616
|
+
onClick: onNewQuery,
|
|
152617
|
+
children: "New query"
|
|
152618
|
+
}
|
|
152619
|
+
),
|
|
152620
|
+
!connection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-secondary-button", onClick: onEdit, children: "Edit" }),
|
|
152621
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-secondary-button", onClick: () => void runTest(), children: "Test" }),
|
|
152622
|
+
!connection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152623
|
+
"button",
|
|
152624
|
+
{
|
|
152625
|
+
type: "button",
|
|
152626
|
+
className: "sp-web-secondary-button",
|
|
152627
|
+
onClick: () => {
|
|
152628
|
+
setDeleteError("");
|
|
152629
|
+
setConfirmingDelete(true);
|
|
152630
|
+
},
|
|
152631
|
+
children: "Delete"
|
|
152632
|
+
}
|
|
152633
|
+
)
|
|
152634
|
+
] }),
|
|
152635
|
+
confirmingDelete && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-delete-confirm", children: [
|
|
152636
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
152637
|
+
"Delete '",
|
|
152638
|
+
label,
|
|
152639
|
+
"'? Its stored password is removed too."
|
|
152640
|
+
] }),
|
|
152641
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152642
|
+
"button",
|
|
152643
|
+
{
|
|
152644
|
+
type: "button",
|
|
152645
|
+
className: "sp-web-secondary-button",
|
|
152646
|
+
onClick: () => void confirmDelete(),
|
|
152647
|
+
children: "Delete"
|
|
152648
|
+
}
|
|
152649
|
+
),
|
|
152650
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152651
|
+
"button",
|
|
152652
|
+
{
|
|
152653
|
+
type: "button",
|
|
152654
|
+
className: "sp-web-secondary-button",
|
|
152655
|
+
onClick: () => {
|
|
152656
|
+
setConfirmingDelete(false);
|
|
152657
|
+
setDeleteError("");
|
|
152658
|
+
},
|
|
152659
|
+
children: "Cancel"
|
|
152660
|
+
}
|
|
152661
|
+
)
|
|
152662
|
+
] }),
|
|
152663
|
+
deleteError && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-connection-test-error", role: "alert", children: deleteError })
|
|
152664
|
+
] });
|
|
152665
|
+
}
|
|
152666
|
+
function AgentActivity({
|
|
152667
|
+
tabs,
|
|
152668
|
+
activeTabId,
|
|
152669
|
+
onSelect
|
|
152670
|
+
}) {
|
|
152671
|
+
const [collapsed, setCollapsed] = reactExports.useState([]);
|
|
152672
|
+
const sessions = Array.from(
|
|
152673
|
+
new Set(
|
|
152674
|
+
tabs.flatMap(
|
|
152675
|
+
(tab) => tab.sessionId && tab.sessionId !== WEB_SESSION_ID ? [tab.sessionId] : []
|
|
152676
|
+
)
|
|
152677
|
+
)
|
|
152678
|
+
);
|
|
152679
|
+
if (sessions.length === 0) return null;
|
|
152680
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152681
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-section-title", children: "Agent activity" }),
|
|
152682
|
+
sessions.map((sessionId) => {
|
|
152683
|
+
const sessionTabs = tabs.filter((tab) => tab.sessionId === sessionId);
|
|
152684
|
+
const name = sessionTabs[0]?.sessionDisplayName || sessionTabs[0]?.clientType || "Agent";
|
|
152685
|
+
const isCollapsed = collapsed.includes(sessionId);
|
|
152686
|
+
const groupId = `sp-web-agent-${sessionId.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
152687
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
152688
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152689
|
+
"button",
|
|
152690
|
+
{
|
|
152691
|
+
type: "button",
|
|
152692
|
+
className: "sp-web-agent-session-toggle",
|
|
152693
|
+
"aria-expanded": !isCollapsed,
|
|
152694
|
+
"aria-controls": groupId,
|
|
152695
|
+
onClick: () => setCollapsed(
|
|
152696
|
+
(current2) => isCollapsed ? current2.filter((id) => id !== sessionId) : [...current2, sessionId]
|
|
152697
|
+
),
|
|
152698
|
+
children: [
|
|
152699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: isCollapsed ? "▸" : "▾" }),
|
|
152700
|
+
" ",
|
|
152701
|
+
name
|
|
152702
|
+
]
|
|
152703
|
+
}
|
|
152704
|
+
),
|
|
152705
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: groupId, hidden: isCollapsed, children: sessionTabs.map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152706
|
+
"button",
|
|
152707
|
+
{
|
|
152708
|
+
type: "button",
|
|
152709
|
+
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
152710
|
+
"aria-pressed": activeTabId === tab.id,
|
|
152711
|
+
onClick: () => onSelect(tab.id),
|
|
152712
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: displayQueryTitle(tab.title, tab.sql) })
|
|
152713
|
+
},
|
|
152714
|
+
tab.id
|
|
152715
|
+
)) })
|
|
152716
|
+
] }, sessionId);
|
|
152717
|
+
})
|
|
152718
|
+
] });
|
|
152719
|
+
}
|
|
152720
|
+
function AgentQueryHeading({
|
|
152721
|
+
tab,
|
|
152722
|
+
connectionName
|
|
152723
|
+
}) {
|
|
152724
|
+
const ranAt = tab.result?.executedAt && new Date(tab.result.executedAt).toLocaleTimeString([], {
|
|
152725
|
+
hour: "2-digit",
|
|
152726
|
+
minute: "2-digit",
|
|
152727
|
+
hour12: false
|
|
152728
|
+
});
|
|
152729
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152730
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: displayQueryTitle(tab.title, tab.sql) }),
|
|
152731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-query-provenance", children: [tab.sessionDisplayName || tab.clientType, connectionName, ranAt].filter(Boolean).join(" · ") })
|
|
152732
|
+
] });
|
|
152733
|
+
}
|
|
152561
152734
|
const THEME_KEY = "grain:web-theme";
|
|
152562
152735
|
const SIDEBAR_DEFAULT_WIDTH = 220;
|
|
152563
152736
|
const SIDEBAR_MIN_WIDTH = 160;
|
|
152564
152737
|
const SIDEBAR_MAX_WIDTH = 400;
|
|
152565
152738
|
const SIDEBAR_AUTO_COLLAPSE_QUERY = "(max-width: 640px)";
|
|
152566
152739
|
const SIDEBAR_WIDTH_STORAGE_KEY = "sql-preview:web-sidebar-width";
|
|
152740
|
+
const CONNECTIONS_COLLAPSED_KEY = "grain:web-connections-collapsed";
|
|
152567
152741
|
function WebApp({ viewHint }) {
|
|
152568
152742
|
const { onMessage, isReady, sendMessage, callServerTool, track } = useHostContext();
|
|
152569
152743
|
const session = useWebSession();
|
|
@@ -152574,6 +152748,7 @@ function WebApp({ viewHint }) {
|
|
|
152574
152748
|
setActiveTab,
|
|
152575
152749
|
setTheme,
|
|
152576
152750
|
openSettingsPanel,
|
|
152751
|
+
closeSettingsPanel,
|
|
152577
152752
|
tabs,
|
|
152578
152753
|
activeTabId,
|
|
152579
152754
|
settingsPanelTab
|
|
@@ -152581,22 +152756,28 @@ function WebApp({ viewHint }) {
|
|
|
152581
152756
|
const [connections, setConnections] = reactExports.useState([]);
|
|
152582
152757
|
const [setupOpen, setSetupOpen] = reactExports.useState(false);
|
|
152583
152758
|
const [editingConnection, setEditingConnection] = reactExports.useState(null);
|
|
152584
|
-
const [
|
|
152759
|
+
const [connectionsCollapsed, setConnectionsCollapsed] = reactExports.useState(
|
|
152760
|
+
() => readStoredValue(CONNECTIONS_COLLAPSED_KEY) === "true"
|
|
152761
|
+
);
|
|
152585
152762
|
const [activeConnectionId, setActiveConnectionId] = reactExports.useState(null);
|
|
152586
|
-
const [connectionStatus, setConnectionStatus] = reactExports.useState({});
|
|
152587
152763
|
const [descriptions, setDescriptions] = reactExports.useState({});
|
|
152588
152764
|
const [queryConnections, setQueryConnections] = reactExports.useState({});
|
|
152589
152765
|
const [closedQueries, setClosedQueries] = reactExports.useState([]);
|
|
152590
152766
|
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
152591
152767
|
const localConnection = connections.find((connection) => connection.id === "built-in-duckdb");
|
|
152592
|
-
const
|
|
152768
|
+
const isAgentTab = Boolean(activeTab?.sessionId && activeTab.sessionId !== WEB_SESSION_ID);
|
|
152769
|
+
const selectedConnectionId = activeTab ? isAgentTab ? activeTab.connectionId ?? "" : queryConnections[activeTab.id] ?? localConnection?.id ?? connections[0]?.id ?? "" : "";
|
|
152770
|
+
const activeConnectionName = activeTab ? activeTab.connectionName ?? connections.find((connection) => connection.id === activeTab.connectionId)?.name ?? (activeTab.connectionId === "unknown" ? void 0 : activeTab.connectionId) : void 0;
|
|
152593
152771
|
reactExports.useEffect(() => {
|
|
152594
152772
|
if (isReady) track?.("ui_state_shown", { state: "workspace_ready" });
|
|
152595
152773
|
}, [isReady, track]);
|
|
152596
|
-
const newQuery = (connectionId = "built-in-duckdb") => {
|
|
152774
|
+
const newQuery = (connectionId = "built-in-duckdb", sql = "SELECT 42;") => {
|
|
152775
|
+
setSetupOpen(false);
|
|
152776
|
+
setEditingConnection(null);
|
|
152777
|
+
closeSettingsPanel();
|
|
152597
152778
|
const remoteId = crypto.randomUUID();
|
|
152598
152779
|
const id = addTab(
|
|
152599
|
-
|
|
152780
|
+
sql,
|
|
152600
152781
|
createProjectedTabId(WEB_SESSION_ID, remoteId),
|
|
152601
152782
|
tabs.some((tab) => tab.title === "Untitled query") ? `Untitled query ${tabs.filter((tab) => tab.title.startsWith("Untitled query")).length + 1}` : "Untitled query",
|
|
152602
152783
|
void 0,
|
|
@@ -152605,26 +152786,14 @@ function WebApp({ viewHint }) {
|
|
|
152605
152786
|
setQueryConnections((current2) => ({ ...current2, [id]: connectionId }));
|
|
152606
152787
|
setActiveConnectionId(null);
|
|
152607
152788
|
};
|
|
152608
|
-
const
|
|
152609
|
-
|
|
152610
|
-
|
|
152611
|
-
|
|
152612
|
-
|
|
152613
|
-
|
|
152614
|
-
try {
|
|
152615
|
-
const result = await callServerTool("test_connection", { connectionId: id });
|
|
152616
|
-
const message = result.content?.find((item) => item.type === "text")?.text ?? "Connection test failed";
|
|
152617
|
-
setConnectionStatus((current2) => ({
|
|
152618
|
-
...current2,
|
|
152619
|
-
[id]: result.isError || result.structuredContent?.["success"] === false ? message : "Connected"
|
|
152620
|
-
}));
|
|
152621
|
-
} catch (error) {
|
|
152622
|
-
setConnectionStatus((current2) => ({
|
|
152623
|
-
...current2,
|
|
152624
|
-
[id]: error instanceof Error ? error.message : "Connection test failed"
|
|
152625
|
-
}));
|
|
152626
|
-
}
|
|
152789
|
+
const showQuery = (tabId) => {
|
|
152790
|
+
setSetupOpen(false);
|
|
152791
|
+
setEditingConnection(null);
|
|
152792
|
+
closeSettingsPanel();
|
|
152793
|
+
setActiveConnectionId(null);
|
|
152794
|
+
setActiveTab(tabId);
|
|
152627
152795
|
};
|
|
152796
|
+
const openConnection = (id) => setActiveConnectionId(id);
|
|
152628
152797
|
const closeQuery = (id) => {
|
|
152629
152798
|
const tab = tabs.find((item) => item.id === id);
|
|
152630
152799
|
if (tab) {
|
|
@@ -152634,7 +152803,7 @@ function WebApp({ viewHint }) {
|
|
|
152634
152803
|
sql: tab.sql,
|
|
152635
152804
|
title: tab.title,
|
|
152636
152805
|
description: descriptions[id] ?? "",
|
|
152637
|
-
connectionId: queryConnections[id] ?? "built-in-duckdb"
|
|
152806
|
+
connectionId: tab.sessionId && tab.sessionId !== WEB_SESSION_ID ? tab.connectionId ?? "" : queryConnections[id] ?? "built-in-duckdb"
|
|
152638
152807
|
}
|
|
152639
152808
|
]);
|
|
152640
152809
|
if (tab.result || tab.isLoading) {
|
|
@@ -152661,7 +152830,7 @@ function WebApp({ viewHint }) {
|
|
|
152661
152830
|
const runQuery = async () => {
|
|
152662
152831
|
if (!activeTab || !activeTab.sql.trim() || !selectedConnectionId || activeTab.isLoading) return;
|
|
152663
152832
|
const { id, sql, title } = activeTab;
|
|
152664
|
-
updateTab(id, { isLoading: true, error: null, cancelled: false });
|
|
152833
|
+
updateTab(id, { isLoading: true, error: null, result: null, cancelled: false });
|
|
152665
152834
|
try {
|
|
152666
152835
|
const result = await callServerTool("run_query", {
|
|
152667
152836
|
sql,
|
|
@@ -152827,6 +152996,8 @@ function WebApp({ viewHint }) {
|
|
|
152827
152996
|
remoteId: msg.remoteId,
|
|
152828
152997
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152829
152998
|
clientType: msg.clientType,
|
|
152999
|
+
connectionId: msg.connectionId,
|
|
153000
|
+
connectionName: msg.connectionName,
|
|
152830
153001
|
isRemote: msg.isRemote
|
|
152831
153002
|
},
|
|
152832
153003
|
!msg.preserveFocus
|
|
@@ -152848,6 +153019,8 @@ function WebApp({ viewHint }) {
|
|
|
152848
153019
|
remoteId: msg.remoteId,
|
|
152849
153020
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152850
153021
|
clientType: msg.clientType,
|
|
153022
|
+
connectionId: msg.connectionId,
|
|
153023
|
+
connectionName: msg.connectionName,
|
|
152851
153024
|
isRemote: msg.isRemote
|
|
152852
153025
|
},
|
|
152853
153026
|
!msg.preserveFocus
|
|
@@ -152860,6 +153033,8 @@ function WebApp({ viewHint }) {
|
|
|
152860
153033
|
remoteId: msg.remoteId,
|
|
152861
153034
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152862
153035
|
clientType: msg.clientType,
|
|
153036
|
+
connectionId: msg.connectionId,
|
|
153037
|
+
connectionName: msg.connectionName,
|
|
152863
153038
|
isRemote: msg.isRemote
|
|
152864
153039
|
});
|
|
152865
153040
|
if (!msg.preserveFocus || !currentActiveId) {
|
|
@@ -152878,6 +153053,8 @@ function WebApp({ viewHint }) {
|
|
|
152878
153053
|
remoteId: msg.remoteId,
|
|
152879
153054
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152880
153055
|
clientType: msg.clientType,
|
|
153056
|
+
connectionId: msg.connectionId,
|
|
153057
|
+
connectionName: msg.connectionName,
|
|
152881
153058
|
isRemote: msg.isRemote
|
|
152882
153059
|
},
|
|
152883
153060
|
false
|
|
@@ -152890,6 +153067,8 @@ function WebApp({ viewHint }) {
|
|
|
152890
153067
|
remoteId: msg.remoteId,
|
|
152891
153068
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152892
153069
|
clientType: msg.clientType,
|
|
153070
|
+
connectionId: msg.connectionId,
|
|
153071
|
+
connectionName: msg.connectionName,
|
|
152893
153072
|
isRemote: msg.isRemote,
|
|
152894
153073
|
result: {
|
|
152895
153074
|
query: msg.data.query,
|
|
@@ -152897,7 +153076,7 @@ function WebApp({ viewHint }) {
|
|
|
152897
153076
|
rows: msg.data.rows,
|
|
152898
153077
|
rowCount: msg.data.totalRowsInFirstBatch ?? msg.data.rows.length,
|
|
152899
153078
|
executionTime: msg.data.executionTimeMs,
|
|
152900
|
-
connection: "
|
|
153079
|
+
connection: msg.connectionName ?? msg.connectionId ?? "Connection unknown",
|
|
152901
153080
|
wasTruncated: msg.data.wasTruncated,
|
|
152902
153081
|
executedAt: msg.data.executedAt
|
|
152903
153082
|
}
|
|
@@ -152915,6 +153094,8 @@ function WebApp({ viewHint }) {
|
|
|
152915
153094
|
remoteId: msg.remoteId,
|
|
152916
153095
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152917
153096
|
clientType: msg.clientType,
|
|
153097
|
+
connectionId: msg.connectionId,
|
|
153098
|
+
connectionName: msg.connectionName,
|
|
152918
153099
|
isRemote: msg.isRemote
|
|
152919
153100
|
},
|
|
152920
153101
|
false
|
|
@@ -152927,6 +153108,8 @@ function WebApp({ viewHint }) {
|
|
|
152927
153108
|
remoteId: msg.remoteId,
|
|
152928
153109
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152929
153110
|
clientType: msg.clientType,
|
|
153111
|
+
connectionId: msg.connectionId,
|
|
153112
|
+
connectionName: msg.connectionName,
|
|
152930
153113
|
isRemote: msg.isRemote
|
|
152931
153114
|
});
|
|
152932
153115
|
break;
|
|
@@ -153034,7 +153217,25 @@ function WebApp({ viewHint }) {
|
|
|
153034
153217
|
] }),
|
|
153035
153218
|
monitorOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { ref: sidebarRef, className: "sp-web-sidebar", "aria-label": "Workspace navigation", children: [
|
|
153036
153219
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-header", children: [
|
|
153037
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153220
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153221
|
+
"button",
|
|
153222
|
+
{
|
|
153223
|
+
type: "button",
|
|
153224
|
+
className: "sp-web-sidebar-title sp-web-section-toggle",
|
|
153225
|
+
"aria-expanded": !connectionsCollapsed,
|
|
153226
|
+
"aria-controls": "sp-web-connections",
|
|
153227
|
+
onClick: () => {
|
|
153228
|
+
setConnectionsCollapsed((current2) => {
|
|
153229
|
+
writeStoredValue(CONNECTIONS_COLLAPSED_KEY, String(!current2));
|
|
153230
|
+
return !current2;
|
|
153231
|
+
});
|
|
153232
|
+
},
|
|
153233
|
+
children: [
|
|
153234
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: connectionsCollapsed ? "▸" : "▾" }),
|
|
153235
|
+
" Connections"
|
|
153236
|
+
]
|
|
153237
|
+
}
|
|
153238
|
+
),
|
|
153038
153239
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153039
153240
|
SidebarAddButton,
|
|
153040
153241
|
{
|
|
@@ -153068,63 +153269,55 @@ function WebApp({ viewHint }) {
|
|
|
153068
153269
|
"aria-valuemax": SIDEBAR_MAX_WIDTH
|
|
153069
153270
|
}
|
|
153070
153271
|
),
|
|
153071
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153072
|
-
"
|
|
153272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153273
|
+
"div",
|
|
153073
153274
|
{
|
|
153074
|
-
|
|
153075
|
-
className: "sp-web-connection-
|
|
153076
|
-
|
|
153077
|
-
children:
|
|
153078
|
-
|
|
153079
|
-
|
|
153080
|
-
|
|
153081
|
-
|
|
153082
|
-
|
|
153083
|
-
|
|
153084
|
-
|
|
153085
|
-
|
|
153086
|
-
|
|
153087
|
-
|
|
153088
|
-
|
|
153089
|
-
|
|
153090
|
-
|
|
153275
|
+
id: "sp-web-connections",
|
|
153276
|
+
className: "sp-web-connection-list",
|
|
153277
|
+
hidden: connectionsCollapsed,
|
|
153278
|
+
children: connections.length ? connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153279
|
+
"button",
|
|
153280
|
+
{
|
|
153281
|
+
type: "button",
|
|
153282
|
+
className: "sp-web-connection-item",
|
|
153283
|
+
"aria-current": activeConnectionId === connection.id ? "page" : void 0,
|
|
153284
|
+
onClick: () => openConnection(connection.id),
|
|
153285
|
+
children: [
|
|
153286
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DatabaseIcon, { size: 15 }) }),
|
|
153287
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-web-connection-label", children: [
|
|
153288
|
+
connection.name ?? connection.id,
|
|
153289
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: connection.type })
|
|
153290
|
+
] }),
|
|
153291
|
+
connection.engineState === "ready" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153292
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-dot", "aria-hidden": "true" }),
|
|
153293
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-visually-hidden", children: "Ready" })
|
|
153294
|
+
] })
|
|
153295
|
+
]
|
|
153296
|
+
},
|
|
153297
|
+
connection.id
|
|
153298
|
+
)) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-sidebar-helper", children: "No connections yet." })
|
|
153299
|
+
}
|
|
153300
|
+
),
|
|
153091
153301
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-section-title", children: [
|
|
153092
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "
|
|
153302
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "My queries" }),
|
|
153093
153303
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarAddButton, { label: "Add query", title: "New query", onClick: () => newQuery() })
|
|
153094
153304
|
] }),
|
|
153095
153305
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-session-list", children: [
|
|
153096
153306
|
closedQueries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: reopenQuery, children: "Reopen closed query" }),
|
|
153097
|
-
tabs.filter((tab) => tab.sessionId === WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153098
|
-
"button",
|
|
153099
|
-
{
|
|
153100
|
-
type: "button",
|
|
153101
|
-
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
153102
|
-
"aria-pressed": activeTabId === tab.id,
|
|
153103
|
-
onClick: () => {
|
|
153104
|
-
setActiveTab(tab.id);
|
|
153105
|
-
setActiveConnectionId(null);
|
|
153106
|
-
},
|
|
153107
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: tab.title })
|
|
153108
|
-
},
|
|
153109
|
-
tab.id
|
|
153110
|
-
)),
|
|
153111
|
-
tabs.some((tab) => tab.sessionId !== WEB_SESSION_ID) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-meta sp-web-agent-heading", children: "Other sessions" }),
|
|
153112
|
-
tabs.filter((tab) => tab.sessionId !== WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153307
|
+
tabs.filter((tab) => !tab.sessionId || tab.sessionId === WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153113
153308
|
"button",
|
|
153114
153309
|
{
|
|
153115
153310
|
type: "button",
|
|
153116
153311
|
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
153117
153312
|
"aria-pressed": activeTabId === tab.id,
|
|
153118
|
-
onClick: () =>
|
|
153119
|
-
|
|
153120
|
-
setActiveConnectionId(null);
|
|
153121
|
-
},
|
|
153122
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: tab.title })
|
|
153313
|
+
onClick: () => showQuery(tab.id),
|
|
153314
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: displayQueryTitle(tab.title, tab.sql) })
|
|
153123
153315
|
},
|
|
153124
153316
|
tab.id
|
|
153125
153317
|
)),
|
|
153126
153318
|
tabs.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-empty-sessions", children: "No queries yet." })
|
|
153127
153319
|
] }),
|
|
153320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentActivity, { tabs, activeTabId, onSelect: showQuery }),
|
|
153128
153321
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-footer", children: "⌂ All work stays on this computer." })
|
|
153129
153322
|
] }),
|
|
153130
153323
|
setupOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-main", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -153161,41 +153354,6 @@ function WebApp({ viewHint }) {
|
|
|
153161
153354
|
) }),
|
|
153162
153355
|
!settingsPanelTab && (activeTab || activeConnectionId) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-workspace", children: [
|
|
153163
153356
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-tabs", role: "tablist", "aria-label": "Open tabs", children: [
|
|
153164
|
-
openConnectionIds.map((id) => {
|
|
153165
|
-
const connection = connections.find((item) => item.id === id);
|
|
153166
|
-
if (!connection) return null;
|
|
153167
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153168
|
-
"div",
|
|
153169
|
-
{
|
|
153170
|
-
className: `sp-web-query-tab${activeConnectionId === id ? " active" : ""}`,
|
|
153171
|
-
children: [
|
|
153172
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153173
|
-
"button",
|
|
153174
|
-
{
|
|
153175
|
-
type: "button",
|
|
153176
|
-
role: "tab",
|
|
153177
|
-
"aria-selected": activeConnectionId === id,
|
|
153178
|
-
onClick: () => setActiveConnectionId(id),
|
|
153179
|
-
children: connection.name ?? id
|
|
153180
|
-
}
|
|
153181
|
-
),
|
|
153182
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153183
|
-
"button",
|
|
153184
|
-
{
|
|
153185
|
-
type: "button",
|
|
153186
|
-
"aria-label": `Close ${connection.name ?? id} tab`,
|
|
153187
|
-
onClick: () => {
|
|
153188
|
-
setOpenConnectionIds((current2) => current2.filter((item) => item !== id));
|
|
153189
|
-
if (activeConnectionId === id) setActiveConnectionId(null);
|
|
153190
|
-
},
|
|
153191
|
-
children: "×"
|
|
153192
|
-
}
|
|
153193
|
-
)
|
|
153194
|
-
]
|
|
153195
|
-
},
|
|
153196
|
-
`connection-${id}`
|
|
153197
|
-
);
|
|
153198
|
-
}),
|
|
153199
153357
|
tabs.map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153200
153358
|
"div",
|
|
153201
153359
|
{
|
|
@@ -153207,18 +153365,15 @@ function WebApp({ viewHint }) {
|
|
|
153207
153365
|
type: "button",
|
|
153208
153366
|
role: "tab",
|
|
153209
153367
|
"aria-selected": tab.id === activeTabId && !activeConnectionId,
|
|
153210
|
-
onClick: () =>
|
|
153211
|
-
|
|
153212
|
-
setActiveConnectionId(null);
|
|
153213
|
-
},
|
|
153214
|
-
children: tab.title
|
|
153368
|
+
onClick: () => showQuery(tab.id),
|
|
153369
|
+
children: displayQueryTitle(tab.title, tab.sql)
|
|
153215
153370
|
}
|
|
153216
153371
|
),
|
|
153217
153372
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153218
153373
|
"button",
|
|
153219
153374
|
{
|
|
153220
153375
|
type: "button",
|
|
153221
|
-
"aria-label": `Close ${tab.title} tab`,
|
|
153376
|
+
"aria-label": `Close ${displayQueryTitle(tab.title, tab.sql)} tab`,
|
|
153222
153377
|
onClick: () => closeQuery(tab.id),
|
|
153223
153378
|
children: "×"
|
|
153224
153379
|
}
|
|
@@ -153242,51 +153397,39 @@ function WebApp({ viewHint }) {
|
|
|
153242
153397
|
activeConnectionId ? (() => {
|
|
153243
153398
|
const connection = connections.find((item) => item.id === activeConnectionId);
|
|
153244
153399
|
if (!connection) return null;
|
|
153245
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
153246
|
-
|
|
153247
|
-
|
|
153248
|
-
connection
|
|
153249
|
-
|
|
153250
|
-
|
|
153251
|
-
|
|
153252
|
-
|
|
153253
|
-
|
|
153254
|
-
|
|
153255
|
-
|
|
153256
|
-
|
|
153257
|
-
|
|
153258
|
-
|
|
153259
|
-
|
|
153260
|
-
|
|
153261
|
-
|
|
153262
|
-
|
|
153263
|
-
|
|
153264
|
-
|
|
153265
|
-
|
|
153266
|
-
|
|
153267
|
-
|
|
153268
|
-
|
|
153269
|
-
onClick: () => {
|
|
153270
|
-
setEditingConnection(connection);
|
|
153271
|
-
setSetupOpen(true);
|
|
153272
|
-
},
|
|
153273
|
-
children: "Edit"
|
|
153274
|
-
}
|
|
153275
|
-
),
|
|
153276
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153277
|
-
"button",
|
|
153278
|
-
{
|
|
153279
|
-
type: "button",
|
|
153280
|
-
className: "sp-web-secondary-button",
|
|
153281
|
-
onClick: () => void testConnection(connection.id),
|
|
153282
|
-
children: "Test"
|
|
153283
|
-
}
|
|
153284
|
-
)
|
|
153285
|
-
] })
|
|
153286
|
-
] });
|
|
153400
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153401
|
+
ConnectionPage,
|
|
153402
|
+
{
|
|
153403
|
+
connection,
|
|
153404
|
+
onNewQuery: () => newQuery(connection.id),
|
|
153405
|
+
onEdit: () => {
|
|
153406
|
+
setEditingConnection(connection);
|
|
153407
|
+
setSetupOpen(true);
|
|
153408
|
+
},
|
|
153409
|
+
onDeleted: () => {
|
|
153410
|
+
setActiveConnectionId(null);
|
|
153411
|
+
setQueryConnections(
|
|
153412
|
+
(current2) => Object.fromEntries(
|
|
153413
|
+
Object.entries(current2).map(([tabId, id]) => [
|
|
153414
|
+
tabId,
|
|
153415
|
+
id === connection.id ? "built-in-duckdb" : id
|
|
153416
|
+
])
|
|
153417
|
+
)
|
|
153418
|
+
);
|
|
153419
|
+
void fetchConnections();
|
|
153420
|
+
}
|
|
153421
|
+
},
|
|
153422
|
+
connection.id
|
|
153423
|
+
);
|
|
153287
153424
|
})() : activeTab && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153288
153425
|
" ",
|
|
153289
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-query-heading", children: isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153427
|
+
AgentQueryHeading,
|
|
153428
|
+
{
|
|
153429
|
+
tab: activeTab,
|
|
153430
|
+
connectionName: activeConnectionName
|
|
153431
|
+
}
|
|
153432
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153290
153433
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153291
153434
|
"input",
|
|
153292
153435
|
{
|
|
@@ -153308,9 +153451,9 @@ function WebApp({ viewHint }) {
|
|
|
153308
153451
|
rows: 1
|
|
153309
153452
|
}
|
|
153310
153453
|
)
|
|
153311
|
-
] }),
|
|
153454
|
+
] }) }),
|
|
153312
153455
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-toolbar", children: [
|
|
153313
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("
|
|
153456
|
+
isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-readonly", children: activeConnectionName ?? "Connection unknown" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153314
153457
|
"select",
|
|
153315
153458
|
{
|
|
153316
153459
|
"aria-label": "Query connection",
|
|
@@ -153319,10 +153462,24 @@ function WebApp({ viewHint }) {
|
|
|
153319
153462
|
...current2,
|
|
153320
153463
|
[activeTab.id]: event.target.value
|
|
153321
153464
|
})),
|
|
153322
|
-
children:
|
|
153465
|
+
children: [
|
|
153466
|
+
!selectedConnectionId && /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Choose connection" }),
|
|
153467
|
+
selectedConnectionId && !connections.some(
|
|
153468
|
+
(connection) => connection.id === selectedConnectionId
|
|
153469
|
+
) && /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: selectedConnectionId, children: selectedConnectionId }),
|
|
153470
|
+
connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connection.id, children: connection.name ?? connection.id }, connection.id))
|
|
153471
|
+
]
|
|
153323
153472
|
}
|
|
153324
153473
|
) }),
|
|
153325
|
-
|
|
153474
|
+
isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153475
|
+
"button",
|
|
153476
|
+
{
|
|
153477
|
+
type: "button",
|
|
153478
|
+
className: "sp-web-secondary-button",
|
|
153479
|
+
onClick: () => newQuery(activeTab.connectionId ?? "", activeTab.sql),
|
|
153480
|
+
children: "Open as my query"
|
|
153481
|
+
}
|
|
153482
|
+
) : activeTab.isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153326
153483
|
"button",
|
|
153327
153484
|
{
|
|
153328
153485
|
type: "button",
|
|
@@ -153350,7 +153507,8 @@ function WebApp({ viewHint }) {
|
|
|
153350
153507
|
{
|
|
153351
153508
|
value: activeTab.sql,
|
|
153352
153509
|
onChange: (sql) => updateTab(activeTab.id, { sql }),
|
|
153353
|
-
onRun: () => void runQuery()
|
|
153510
|
+
onRun: () => void runQuery(),
|
|
153511
|
+
readOnly: isAgentTab
|
|
153354
153512
|
}
|
|
153355
153513
|
)
|
|
153356
153514
|
] })
|
|
@@ -153528,11 +153686,18 @@ bootstrap();</script>
|
|
|
153528
153686
|
margin: 5px 0 0;
|
|
153529
153687
|
}
|
|
153530
153688
|
.grain-connection-success {
|
|
153531
|
-
color: var(--
|
|
153532
|
-
|
|
153689
|
+
color: var(--vscode-testing-iconPassed, var(--sp-success));
|
|
153690
|
+
border: 1px solid var(--vscode-testing-iconPassed, var(--sp-success));
|
|
153691
|
+
background: color-mix(in srgb, var(--sp-success) 8%, var(--grain-surface));
|
|
153533
153692
|
padding: 10px 14px;
|
|
153534
153693
|
border-radius: var(--grain-radius-sm);
|
|
153535
153694
|
}
|
|
153695
|
+
.grain-connection-footer .grain-connection-success {
|
|
153696
|
+
color: var(--vscode-testing-iconPassed, var(--sp-success));
|
|
153697
|
+
}
|
|
153698
|
+
.grain-connection-footer-error {
|
|
153699
|
+
color: var(--vscode-errorForeground, var(--sp-error));
|
|
153700
|
+
}
|
|
153536
153701
|
.grain-connection-page :is(button, input, select, summary):focus-visible {
|
|
153537
153702
|
outline: 2px solid var(--grain-accent);
|
|
153538
153703
|
outline-offset: 2px;
|
|
@@ -166390,6 +166555,31 @@ body {
|
|
|
166390
166555
|
.sp-web-sidebar-header .sp-web-sidebar-title {
|
|
166391
166556
|
flex: 1;
|
|
166392
166557
|
}
|
|
166558
|
+
.sp-web-section-toggle,
|
|
166559
|
+
.sp-web-agent-session-toggle {
|
|
166560
|
+
border: 0;
|
|
166561
|
+
background: transparent;
|
|
166562
|
+
color: var(--grain-ink);
|
|
166563
|
+
font: inherit;
|
|
166564
|
+
text-align: left;
|
|
166565
|
+
cursor: pointer;
|
|
166566
|
+
}
|
|
166567
|
+
.sp-web-section-toggle {
|
|
166568
|
+
padding: 0;
|
|
166569
|
+
}
|
|
166570
|
+
.sp-web-agent-session-toggle {
|
|
166571
|
+
width: 100%;
|
|
166572
|
+
padding: 7px 9px;
|
|
166573
|
+
color: var(--grain-ink-muted);
|
|
166574
|
+
font-size: 11px;
|
|
166575
|
+
}
|
|
166576
|
+
.sp-web-section-toggle:focus-visible,
|
|
166577
|
+
.sp-web-agent-session-toggle:focus-visible {
|
|
166578
|
+
outline: 1px solid var(--grain-accent);
|
|
166579
|
+
}
|
|
166580
|
+
[aria-current='page'].sp-web-connection-item {
|
|
166581
|
+
background: var(--grain-surface-raised);
|
|
166582
|
+
}
|
|
166393
166583
|
.sp-web-section-add,
|
|
166394
166584
|
.sp-web-sidebar-close {
|
|
166395
166585
|
display: inline-flex;
|
|
@@ -166581,6 +166771,14 @@ body {
|
|
|
166581
166771
|
gap: 4px;
|
|
166582
166772
|
padding: 18px 24px 14px;
|
|
166583
166773
|
}
|
|
166774
|
+
.sp-web-query-heading h1 {
|
|
166775
|
+
margin: 0;
|
|
166776
|
+
font-size: 22px;
|
|
166777
|
+
}
|
|
166778
|
+
.sp-web-query-provenance {
|
|
166779
|
+
color: var(--grain-ink-muted);
|
|
166780
|
+
font-size: 11px;
|
|
166781
|
+
}
|
|
166584
166782
|
.sp-web-query-heading input,
|
|
166585
166783
|
.sp-web-query-heading textarea {
|
|
166586
166784
|
width: 100%;
|
|
@@ -166796,6 +166994,18 @@ body {
|
|
|
166796
166994
|
.sp-web-connection-detail p {
|
|
166797
166995
|
color: var(--grain-ink-muted);
|
|
166798
166996
|
}
|
|
166997
|
+
.sp-web-connection-detail .sp-web-connection-test-success {
|
|
166998
|
+
color: var(--vscode-testing-iconPassed, var(--sp-success));
|
|
166999
|
+
}
|
|
167000
|
+
.sp-web-connection-detail .sp-web-connection-test-error {
|
|
167001
|
+
color: var(--vscode-errorForeground, var(--sp-error));
|
|
167002
|
+
}
|
|
167003
|
+
.sp-web-connection-delete-confirm {
|
|
167004
|
+
margin-top: 16px;
|
|
167005
|
+
}
|
|
167006
|
+
.sp-web-connection-delete-confirm p {
|
|
167007
|
+
color: var(--grain-ink);
|
|
167008
|
+
}
|
|
166799
167009
|
.sp-web-connection-actions {
|
|
166800
167010
|
display: flex;
|
|
166801
167011
|
gap: 8px;
|