grain-tools 0.10.16 → 0.10.18
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-shell.html +31 -0
- package/dist/mcp-app.html +78 -32
- package/dist/web-app.html +460 -213
- package/out/server/standalone.js +2457 -1483
- package/package.json +2 -1
- package/server.json +2 -2
package/dist/web-app.html
CHANGED
|
@@ -12553,13 +12553,16 @@ async function bootstrapLocalSession(location, history) {
|
|
|
12553
12553
|
const params = new URLSearchParams(location.hash.replace(/^#/, ""));
|
|
12554
12554
|
const capability = params.get("launch");
|
|
12555
12555
|
const rawView = params.get("view");
|
|
12556
|
+
const sessionId = params.get("sessionId");
|
|
12557
|
+
const tabId = params.get("tabId");
|
|
12558
|
+
const result = sessionId && tabId ? { sessionId, tabId } : void 0;
|
|
12556
12559
|
let view = void 0;
|
|
12557
12560
|
if (rawView === "connections" || rawView === "connections-add") {
|
|
12558
12561
|
view = rawView;
|
|
12559
12562
|
}
|
|
12560
12563
|
history.replaceState({}, "", `${location.pathname}${location.search}`);
|
|
12561
12564
|
if (!capability) {
|
|
12562
|
-
return { session: "no-capability", view };
|
|
12565
|
+
return { session: "no-capability", view, result };
|
|
12563
12566
|
}
|
|
12564
12567
|
try {
|
|
12565
12568
|
const response = await fetch(LOCAL_EXCHANGE_PATH, {
|
|
@@ -12571,11 +12574,11 @@ async function bootstrapLocalSession(location, history) {
|
|
|
12571
12574
|
body: JSON.stringify({ capability })
|
|
12572
12575
|
});
|
|
12573
12576
|
if (response.status === 204) {
|
|
12574
|
-
return { session: "ok", view };
|
|
12577
|
+
return { session: "ok", view, result };
|
|
12575
12578
|
}
|
|
12576
|
-
return { session: "failed", view };
|
|
12579
|
+
return { session: "failed", view, result };
|
|
12577
12580
|
} catch {
|
|
12578
|
-
return { session: "failed", view };
|
|
12581
|
+
return { session: "failed", view, result };
|
|
12579
12582
|
}
|
|
12580
12583
|
}
|
|
12581
12584
|
async function authorizedFetch(input, init2) {
|
|
@@ -13065,6 +13068,10 @@ function useWebBootstrap() {
|
|
|
13065
13068
|
return unsubscribe;
|
|
13066
13069
|
}, []);
|
|
13067
13070
|
}
|
|
13071
|
+
const RESULT_ROUTING_SCHEMA = {
|
|
13072
|
+
events: ["mcp_result_routed", "mcp_result_view_opened"],
|
|
13073
|
+
flagKeys: ["results-card-routing"]
|
|
13074
|
+
};
|
|
13068
13075
|
const ALL_TOOLS = [
|
|
13069
13076
|
"list_connectors",
|
|
13070
13077
|
"run_query",
|
|
@@ -13087,7 +13094,8 @@ const ALL_TOOLS = [
|
|
|
13087
13094
|
"list_charts",
|
|
13088
13095
|
"ledger_stats",
|
|
13089
13096
|
"verify_ledger",
|
|
13090
|
-
"record_ui_event"
|
|
13097
|
+
"record_ui_event",
|
|
13098
|
+
"open_result_view"
|
|
13091
13099
|
];
|
|
13092
13100
|
const WEB_PROXIED_TOOLS = [
|
|
13093
13101
|
"list_connectors",
|
|
@@ -13110,6 +13118,7 @@ const TELEMETRY_EVENTS = [
|
|
|
13110
13118
|
"query_confirmation_shown",
|
|
13111
13119
|
"mcp_tool_invoked",
|
|
13112
13120
|
"mcp_resource_read",
|
|
13121
|
+
...RESULT_ROUTING_SCHEMA.events,
|
|
13113
13122
|
"daemon_crashed",
|
|
13114
13123
|
"service_lifecycle",
|
|
13115
13124
|
"mcp_http_error",
|
|
@@ -13584,6 +13593,7 @@ const TELEMETRY_FLAG_KEYS = [
|
|
|
13584
13593
|
"sql_preview_credential_required_signal",
|
|
13585
13594
|
"sql_preview_crash_diagnostics",
|
|
13586
13595
|
"sql_preview_mcp_surface",
|
|
13596
|
+
...RESULT_ROUTING_SCHEMA.flagKeys,
|
|
13587
13597
|
"unknown"
|
|
13588
13598
|
];
|
|
13589
13599
|
const TELEMETRY_ACQUISITION_CHANNELS = ["marketplace", "open_vsx", "cli"];
|
|
@@ -13780,21 +13790,15 @@ async function buildGuideHubState() {
|
|
|
13780
13790
|
}
|
|
13781
13791
|
const WEB_SESSION_KEY = "grain:web-session-id";
|
|
13782
13792
|
function resolveWebSessionId() {
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
13786
|
-
} catch {
|
|
13787
|
-
return `web-${crypto.randomUUID()}`;
|
|
13793
|
+
const stored = readStoredValue(WEB_SESSION_KEY);
|
|
13794
|
+
if (stored && /^web-[0-9a-f-]{36}$/.test(stored)) {
|
|
13795
|
+
return stored;
|
|
13788
13796
|
}
|
|
13789
13797
|
return `web-${crypto.randomUUID()}`;
|
|
13790
13798
|
}
|
|
13791
13799
|
const WEB_SESSION_ID = resolveWebSessionId();
|
|
13792
13800
|
function rememberWebSessionId() {
|
|
13793
|
-
|
|
13794
|
-
window.sessionStorage.setItem(WEB_SESSION_KEY, WEB_SESSION_ID);
|
|
13795
|
-
} catch {
|
|
13796
|
-
return;
|
|
13797
|
-
}
|
|
13801
|
+
writeStoredValue(WEB_SESSION_KEY, WEB_SESSION_ID);
|
|
13798
13802
|
}
|
|
13799
13803
|
function resolveProjectedTarget(tabId, payload) {
|
|
13800
13804
|
const parsed = tabId ? parseProjectedTabId(tabId) : void 0;
|
|
@@ -14051,6 +14055,8 @@ function useWebTabSync(options) {
|
|
|
14051
14055
|
remoteId: tab.id,
|
|
14052
14056
|
sessionDisplayName: session.displayName,
|
|
14053
14057
|
clientType: session.clientType,
|
|
14058
|
+
connectionId: tab.connectionId,
|
|
14059
|
+
connectionName: tab.connectionName,
|
|
14054
14060
|
isRemote: true,
|
|
14055
14061
|
preserveFocus
|
|
14056
14062
|
});
|
|
@@ -14068,6 +14074,8 @@ function useWebTabSync(options) {
|
|
|
14068
14074
|
remoteId: tab.id,
|
|
14069
14075
|
sessionDisplayName: session.displayName,
|
|
14070
14076
|
clientType: session.clientType,
|
|
14077
|
+
connectionId: tab.connectionId,
|
|
14078
|
+
connectionName: tab.connectionName,
|
|
14071
14079
|
isRemote: true,
|
|
14072
14080
|
preserveFocus
|
|
14073
14081
|
});
|
|
@@ -14088,6 +14096,8 @@ function useWebTabSync(options) {
|
|
|
14088
14096
|
remoteId: tab.id,
|
|
14089
14097
|
sessionDisplayName: session.displayName,
|
|
14090
14098
|
clientType: session.clientType,
|
|
14099
|
+
connectionId: detail.connectionId ?? tab.connectionId,
|
|
14100
|
+
connectionName: detail.connectionName ?? tab.connectionName,
|
|
14091
14101
|
isRemote: true
|
|
14092
14102
|
};
|
|
14093
14103
|
if (tab.status === "success") {
|
|
@@ -14164,7 +14174,7 @@ function useWebTabSync(options) {
|
|
|
14164
14174
|
dispatchLoading(session, tab, true);
|
|
14165
14175
|
}
|
|
14166
14176
|
} 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);
|
|
14177
|
+
const detailIsNeeded = tab.status === "success" && (!cached || !storeHasTab || cached.status !== tab.status || cached.rowCount !== tab.rowCount || cached.connectionId !== tab.connectionId);
|
|
14168
14178
|
const errorIsNeeded = tab.status === "error" && (!cached || !storeHasTab || cached.status !== "error");
|
|
14169
14179
|
if (detailIsNeeded || errorIsNeeded) {
|
|
14170
14180
|
await dispatchTabDetail(session, tab);
|
|
@@ -14175,7 +14185,8 @@ function useWebTabSync(options) {
|
|
|
14175
14185
|
remoteTabId: tab.id,
|
|
14176
14186
|
status: tab.status,
|
|
14177
14187
|
rowCount: tab.rowCount,
|
|
14178
|
-
title: tab.title
|
|
14188
|
+
title: tab.title,
|
|
14189
|
+
connectionId: tab.connectionId
|
|
14179
14190
|
});
|
|
14180
14191
|
}
|
|
14181
14192
|
})
|
|
@@ -14694,7 +14705,10 @@ function ConnectionSetupPage({
|
|
|
14694
14705
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Connection failed" }),
|
|
14695
14706
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: error })
|
|
14696
14707
|
] }),
|
|
14697
|
-
tested && !error && /* @__PURE__ */ jsxRuntimeExports.
|
|
14708
|
+
tested && !error && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", role: "status", children: [
|
|
14709
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
14710
|
+
"Connection test successful."
|
|
14711
|
+
] }),
|
|
14698
14712
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-grid", children: [
|
|
14699
14713
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-field", children: [
|
|
14700
14714
|
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-type", children: "Database type" }),
|
|
@@ -14782,7 +14796,10 @@ function ConnectionSetupPage({
|
|
|
14782
14796
|
] })
|
|
14783
14797
|
] }),
|
|
14784
14798
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-footer", children: [
|
|
14785
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
14799
|
+
tested && !error ? /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", children: [
|
|
14800
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
14801
|
+
"Connection test successful."
|
|
14802
|
+
] }) : 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
14803
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-actions", children: [
|
|
14787
14804
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14788
14805
|
"button",
|
|
@@ -75125,7 +75142,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75125
75142
|
nativeTheme = false,
|
|
75126
75143
|
disableFilters = false,
|
|
75127
75144
|
autoSizeStrategy,
|
|
75128
|
-
fillWidth = false,
|
|
75129
75145
|
onCellDoubleClick
|
|
75130
75146
|
}, ref) {
|
|
75131
75147
|
const trackUi = useTrackUi();
|
|
@@ -75294,21 +75310,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75294
75310
|
}),
|
|
75295
75311
|
[data, getNodeValue, copyIncludesHeaders]
|
|
75296
75312
|
);
|
|
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
75313
|
const columnDefs = reactExports.useMemo(() => {
|
|
75313
75314
|
if (!data?.columns) return [];
|
|
75314
75315
|
const isInRange = (rowIndex, displayedColIndex) => {
|
|
@@ -75493,11 +75494,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75493
75494
|
onGridReady: (p) => {
|
|
75494
75495
|
apiRef.current = p.api;
|
|
75495
75496
|
},
|
|
75496
|
-
...fillWidth ? {
|
|
75497
|
-
onFirstDataRendered: fillSpareWidth,
|
|
75498
|
-
onGridSizeChanged: fillSpareWidth,
|
|
75499
|
-
onColumnResized: noteUserResize
|
|
75500
|
-
} : {},
|
|
75501
75497
|
rowData: data.rows,
|
|
75502
75498
|
columnDefs,
|
|
75503
75499
|
defaultColDef: {
|
|
@@ -150368,7 +150364,8 @@ const TOOL_ENTRIES = {
|
|
|
150368
150364
|
ledger_stats: ["ledger", "Show ledger health and counts."],
|
|
150369
150365
|
verify_ledger: ["ledger", "Verify the ledger hash chain."],
|
|
150370
150366
|
list_sessions: ["sessions", "Show active MCP sessions and their tabs."],
|
|
150371
|
-
record_ui_event: null
|
|
150367
|
+
record_ui_event: null,
|
|
150368
|
+
open_result_view: null
|
|
150372
150369
|
};
|
|
150373
150370
|
const MCP_TOOL_GROUPS = GROUPS.map((group) => ({
|
|
150374
150371
|
label: group.label,
|
|
@@ -152517,7 +152514,7 @@ function SidebarAddButton({ label, title, onClick }) {
|
|
|
152517
152514
|
}
|
|
152518
152515
|
);
|
|
152519
152516
|
}
|
|
152520
|
-
function SqlEditor({ value, onChange, onRun }) {
|
|
152517
|
+
function SqlEditor({ value, onChange, onRun, readOnly = false }) {
|
|
152521
152518
|
const frameRef = reactExports.useRef(null);
|
|
152522
152519
|
const gutterRef = reactExports.useRef(null);
|
|
152523
152520
|
const lineCount = value.split("\n").length;
|
|
@@ -152544,12 +152541,13 @@ function SqlEditor({ value, onChange, onRun }) {
|
|
|
152544
152541
|
spellCheck: false,
|
|
152545
152542
|
wrap: "off",
|
|
152546
152543
|
value,
|
|
152544
|
+
readOnly,
|
|
152547
152545
|
onChange: (event) => onChange(event.target.value),
|
|
152548
152546
|
onScroll: (event) => {
|
|
152549
152547
|
if (gutterRef.current) gutterRef.current.scrollTop = event.currentTarget.scrollTop;
|
|
152550
152548
|
},
|
|
152551
152549
|
onKeyDown: (event) => {
|
|
152552
|
-
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
152550
|
+
if (!readOnly && (event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
152553
152551
|
event.preventDefault();
|
|
152554
152552
|
onRun();
|
|
152555
152553
|
}
|
|
@@ -152558,13 +152556,227 @@ function SqlEditor({ value, onChange, onRun }) {
|
|
|
152558
152556
|
)
|
|
152559
152557
|
] });
|
|
152560
152558
|
}
|
|
152559
|
+
function displayQueryTitle(title, sql) {
|
|
152560
|
+
if (title.trim() && !/^Result \d+$/.test(title.trim())) return title;
|
|
152561
|
+
const line = sql.replace(/\/\*[\s\S]*?\*\//g, "").split("\n").map((part) => part.trim()).find((part) => part && !part.startsWith("--"))?.replace(/\s+/g, " ");
|
|
152562
|
+
if (!line) return title.trim() || "Query";
|
|
152563
|
+
return line.length > 40 ? `${line.slice(0, 40).trimEnd()}…` : line;
|
|
152564
|
+
}
|
|
152565
|
+
function resultText(result, fallback) {
|
|
152566
|
+
return result.content?.find((item) => item.type === "text")?.text ?? fallback;
|
|
152567
|
+
}
|
|
152568
|
+
function failed(result) {
|
|
152569
|
+
return Boolean(result.isError) || result.structuredContent?.["success"] === false;
|
|
152570
|
+
}
|
|
152571
|
+
function ConnectionPage({
|
|
152572
|
+
connection,
|
|
152573
|
+
onNewQuery,
|
|
152574
|
+
onEdit,
|
|
152575
|
+
onDeleted
|
|
152576
|
+
}) {
|
|
152577
|
+
const { callServerTool } = useHostContext();
|
|
152578
|
+
const [test, setTest] = reactExports.useState(null);
|
|
152579
|
+
const [confirmingDelete, setConfirmingDelete] = reactExports.useState(false);
|
|
152580
|
+
const [deleteError, setDeleteError] = reactExports.useState("");
|
|
152581
|
+
const label = connection.name ?? connection.id;
|
|
152582
|
+
const runTest = async () => {
|
|
152583
|
+
setTest({ kind: "testing" });
|
|
152584
|
+
try {
|
|
152585
|
+
const result = await callServerTool("test_connection", { connectionId: connection.id });
|
|
152586
|
+
setTest(
|
|
152587
|
+
failed(result) ? { kind: "failed", message: resultText(result, "Connection test failed") } : { kind: "passed" }
|
|
152588
|
+
);
|
|
152589
|
+
} catch (error) {
|
|
152590
|
+
setTest({
|
|
152591
|
+
kind: "failed",
|
|
152592
|
+
message: error instanceof Error ? error.message : "Connection test failed"
|
|
152593
|
+
});
|
|
152594
|
+
}
|
|
152595
|
+
};
|
|
152596
|
+
const confirmDelete = async () => {
|
|
152597
|
+
setDeleteError("");
|
|
152598
|
+
try {
|
|
152599
|
+
const result = await callServerTool("delete_connection", { connectionId: connection.id });
|
|
152600
|
+
if (failed(result)) throw new Error(resultText(result, "Could not delete connection"));
|
|
152601
|
+
onDeleted();
|
|
152602
|
+
} catch (error) {
|
|
152603
|
+
setDeleteError(error instanceof Error ? error.message : "Could not delete connection");
|
|
152604
|
+
}
|
|
152605
|
+
};
|
|
152606
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-detail", children: [
|
|
152607
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: label }),
|
|
152608
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
152609
|
+
connection.type ?? "Database",
|
|
152610
|
+
" ·",
|
|
152611
|
+
" ",
|
|
152612
|
+
connection.engineState === "ready" ? "Ready" : "Saved connection"
|
|
152613
|
+
] }),
|
|
152614
|
+
test?.kind === "testing" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { role: "status", children: "Testing…" }),
|
|
152615
|
+
test?.kind === "passed" && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "sp-web-connection-test-success", role: "status", children: [
|
|
152616
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
152617
|
+
"Connection test successful."
|
|
152618
|
+
] }),
|
|
152619
|
+
test?.kind === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-connection-test-error", role: "alert", children: test.message }),
|
|
152620
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-actions", children: [
|
|
152621
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152622
|
+
"button",
|
|
152623
|
+
{
|
|
152624
|
+
type: "button",
|
|
152625
|
+
className: "sp-web-primary-button",
|
|
152626
|
+
"aria-label": `New query for ${label}`,
|
|
152627
|
+
onClick: onNewQuery,
|
|
152628
|
+
children: "New query"
|
|
152629
|
+
}
|
|
152630
|
+
),
|
|
152631
|
+
!connection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-secondary-button", onClick: onEdit, children: "Edit" }),
|
|
152632
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-secondary-button", onClick: () => void runTest(), children: "Test" }),
|
|
152633
|
+
!connection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152634
|
+
"button",
|
|
152635
|
+
{
|
|
152636
|
+
type: "button",
|
|
152637
|
+
className: "sp-web-secondary-button",
|
|
152638
|
+
onClick: () => {
|
|
152639
|
+
setDeleteError("");
|
|
152640
|
+
setConfirmingDelete(true);
|
|
152641
|
+
},
|
|
152642
|
+
children: "Delete"
|
|
152643
|
+
}
|
|
152644
|
+
)
|
|
152645
|
+
] }),
|
|
152646
|
+
confirmingDelete && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-delete-confirm", children: [
|
|
152647
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
152648
|
+
"Delete '",
|
|
152649
|
+
label,
|
|
152650
|
+
"'? Its stored password is removed too."
|
|
152651
|
+
] }),
|
|
152652
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152653
|
+
"button",
|
|
152654
|
+
{
|
|
152655
|
+
type: "button",
|
|
152656
|
+
className: "sp-web-secondary-button",
|
|
152657
|
+
onClick: () => void confirmDelete(),
|
|
152658
|
+
children: "Delete"
|
|
152659
|
+
}
|
|
152660
|
+
),
|
|
152661
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152662
|
+
"button",
|
|
152663
|
+
{
|
|
152664
|
+
type: "button",
|
|
152665
|
+
className: "sp-web-secondary-button",
|
|
152666
|
+
onClick: () => {
|
|
152667
|
+
setConfirmingDelete(false);
|
|
152668
|
+
setDeleteError("");
|
|
152669
|
+
},
|
|
152670
|
+
children: "Cancel"
|
|
152671
|
+
}
|
|
152672
|
+
)
|
|
152673
|
+
] }),
|
|
152674
|
+
deleteError && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-connection-test-error", role: "alert", children: deleteError })
|
|
152675
|
+
] });
|
|
152676
|
+
}
|
|
152677
|
+
function AgentActivity({
|
|
152678
|
+
tabs,
|
|
152679
|
+
activeTabId,
|
|
152680
|
+
onSelect
|
|
152681
|
+
}) {
|
|
152682
|
+
const [collapsed, setCollapsed] = reactExports.useState([]);
|
|
152683
|
+
const sessions = Array.from(
|
|
152684
|
+
new Set(
|
|
152685
|
+
tabs.flatMap(
|
|
152686
|
+
(tab) => tab.sessionId && tab.sessionId !== WEB_SESSION_ID ? [tab.sessionId] : []
|
|
152687
|
+
)
|
|
152688
|
+
)
|
|
152689
|
+
);
|
|
152690
|
+
if (sessions.length === 0) return null;
|
|
152691
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152692
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-section-title", children: "Agent activity" }),
|
|
152693
|
+
sessions.map((sessionId) => {
|
|
152694
|
+
const sessionTabs = tabs.filter((tab) => tab.sessionId === sessionId);
|
|
152695
|
+
const name = sessionTabs[0]?.sessionDisplayName || sessionTabs[0]?.clientType || "Agent";
|
|
152696
|
+
const isCollapsed = collapsed.includes(sessionId);
|
|
152697
|
+
const groupId = `sp-web-agent-${sessionId.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
152698
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
152699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152700
|
+
"button",
|
|
152701
|
+
{
|
|
152702
|
+
type: "button",
|
|
152703
|
+
className: "sp-web-agent-session-toggle",
|
|
152704
|
+
"aria-expanded": !isCollapsed,
|
|
152705
|
+
"aria-controls": groupId,
|
|
152706
|
+
onClick: () => setCollapsed(
|
|
152707
|
+
(current2) => isCollapsed ? current2.filter((id) => id !== sessionId) : [...current2, sessionId]
|
|
152708
|
+
),
|
|
152709
|
+
children: [
|
|
152710
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: isCollapsed ? "▸" : "▾" }),
|
|
152711
|
+
" ",
|
|
152712
|
+
name
|
|
152713
|
+
]
|
|
152714
|
+
}
|
|
152715
|
+
),
|
|
152716
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: groupId, hidden: isCollapsed, children: sessionTabs.map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152717
|
+
"button",
|
|
152718
|
+
{
|
|
152719
|
+
type: "button",
|
|
152720
|
+
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
152721
|
+
"aria-pressed": activeTabId === tab.id,
|
|
152722
|
+
onClick: () => onSelect(tab.id),
|
|
152723
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: displayQueryTitle(tab.title, tab.sql) })
|
|
152724
|
+
},
|
|
152725
|
+
tab.id
|
|
152726
|
+
)) })
|
|
152727
|
+
] }, sessionId);
|
|
152728
|
+
})
|
|
152729
|
+
] });
|
|
152730
|
+
}
|
|
152731
|
+
function AgentQueryHeading({
|
|
152732
|
+
tab,
|
|
152733
|
+
connectionName
|
|
152734
|
+
}) {
|
|
152735
|
+
const ranAt = tab.result?.executedAt && new Date(tab.result.executedAt).toLocaleTimeString([], {
|
|
152736
|
+
hour: "2-digit",
|
|
152737
|
+
minute: "2-digit",
|
|
152738
|
+
hour12: false
|
|
152739
|
+
});
|
|
152740
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152741
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: displayQueryTitle(tab.title, tab.sql) }),
|
|
152742
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-query-provenance", children: [tab.sessionDisplayName || tab.clientType, connectionName, ranAt].filter(Boolean).join(" · ") })
|
|
152743
|
+
] });
|
|
152744
|
+
}
|
|
152745
|
+
function useWebAppInitialTarget(isReady, viewHint, resultTarget, tabs, showQuery, openSettingsPanel) {
|
|
152746
|
+
const appliedHint = reactExports.useRef(false);
|
|
152747
|
+
const appliedTarget = reactExports.useRef(void 0);
|
|
152748
|
+
reactExports.useEffect(() => {
|
|
152749
|
+
if (appliedHint.current || !viewHint) {
|
|
152750
|
+
return;
|
|
152751
|
+
}
|
|
152752
|
+
appliedHint.current = true;
|
|
152753
|
+
openSettingsPanel("connections", viewHint === "connections-add");
|
|
152754
|
+
}, [viewHint, openSettingsPanel]);
|
|
152755
|
+
reactExports.useEffect(() => {
|
|
152756
|
+
if (!isReady || !resultTarget) {
|
|
152757
|
+
return;
|
|
152758
|
+
}
|
|
152759
|
+
const targetKey = `${resultTarget.sessionId}\0${resultTarget.tabId}`;
|
|
152760
|
+
if (appliedTarget.current === targetKey) {
|
|
152761
|
+
return;
|
|
152762
|
+
}
|
|
152763
|
+
const target = tabs.find(
|
|
152764
|
+
(tab) => tab.sessionId === resultTarget.sessionId && (tab.remoteId === resultTarget.tabId || tab.id === resultTarget.tabId)
|
|
152765
|
+
);
|
|
152766
|
+
if (target) {
|
|
152767
|
+
appliedTarget.current = targetKey;
|
|
152768
|
+
showQuery(target.id);
|
|
152769
|
+
}
|
|
152770
|
+
}, [isReady, resultTarget, tabs, showQuery]);
|
|
152771
|
+
}
|
|
152561
152772
|
const THEME_KEY = "grain:web-theme";
|
|
152562
152773
|
const SIDEBAR_DEFAULT_WIDTH = 220;
|
|
152563
152774
|
const SIDEBAR_MIN_WIDTH = 160;
|
|
152564
152775
|
const SIDEBAR_MAX_WIDTH = 400;
|
|
152565
152776
|
const SIDEBAR_AUTO_COLLAPSE_QUERY = "(max-width: 640px)";
|
|
152566
152777
|
const SIDEBAR_WIDTH_STORAGE_KEY = "sql-preview:web-sidebar-width";
|
|
152567
|
-
|
|
152778
|
+
const CONNECTIONS_COLLAPSED_KEY = "grain:web-connections-collapsed";
|
|
152779
|
+
function WebApp({ viewHint, resultTarget }) {
|
|
152568
152780
|
const { onMessage, isReady, sendMessage, callServerTool, track } = useHostContext();
|
|
152569
152781
|
const session = useWebSession();
|
|
152570
152782
|
const {
|
|
@@ -152574,6 +152786,7 @@ function WebApp({ viewHint }) {
|
|
|
152574
152786
|
setActiveTab,
|
|
152575
152787
|
setTheme,
|
|
152576
152788
|
openSettingsPanel,
|
|
152789
|
+
closeSettingsPanel,
|
|
152577
152790
|
tabs,
|
|
152578
152791
|
activeTabId,
|
|
152579
152792
|
settingsPanelTab
|
|
@@ -152581,22 +152794,28 @@ function WebApp({ viewHint }) {
|
|
|
152581
152794
|
const [connections, setConnections] = reactExports.useState([]);
|
|
152582
152795
|
const [setupOpen, setSetupOpen] = reactExports.useState(false);
|
|
152583
152796
|
const [editingConnection, setEditingConnection] = reactExports.useState(null);
|
|
152584
|
-
const [
|
|
152797
|
+
const [connectionsCollapsed, setConnectionsCollapsed] = reactExports.useState(
|
|
152798
|
+
() => readStoredValue(CONNECTIONS_COLLAPSED_KEY) === "true"
|
|
152799
|
+
);
|
|
152585
152800
|
const [activeConnectionId, setActiveConnectionId] = reactExports.useState(null);
|
|
152586
|
-
const [connectionStatus, setConnectionStatus] = reactExports.useState({});
|
|
152587
152801
|
const [descriptions, setDescriptions] = reactExports.useState({});
|
|
152588
152802
|
const [queryConnections, setQueryConnections] = reactExports.useState({});
|
|
152589
152803
|
const [closedQueries, setClosedQueries] = reactExports.useState([]);
|
|
152590
152804
|
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
152591
152805
|
const localConnection = connections.find((connection) => connection.id === "built-in-duckdb");
|
|
152592
|
-
const
|
|
152806
|
+
const isAgentTab = Boolean(activeTab?.sessionId && activeTab.sessionId !== WEB_SESSION_ID);
|
|
152807
|
+
const selectedConnectionId = activeTab ? isAgentTab ? activeTab.connectionId ?? "" : queryConnections[activeTab.id] ?? localConnection?.id ?? connections[0]?.id ?? "" : "";
|
|
152808
|
+
const activeConnectionName = activeTab ? activeTab.connectionName ?? connections.find((connection) => connection.id === activeTab.connectionId)?.name ?? (activeTab.connectionId === "unknown" ? void 0 : activeTab.connectionId) : void 0;
|
|
152593
152809
|
reactExports.useEffect(() => {
|
|
152594
152810
|
if (isReady) track?.("ui_state_shown", { state: "workspace_ready" });
|
|
152595
152811
|
}, [isReady, track]);
|
|
152596
|
-
const newQuery = (connectionId = "built-in-duckdb") => {
|
|
152812
|
+
const newQuery = (connectionId = "built-in-duckdb", sql = "SELECT 42;") => {
|
|
152813
|
+
setSetupOpen(false);
|
|
152814
|
+
setEditingConnection(null);
|
|
152815
|
+
closeSettingsPanel();
|
|
152597
152816
|
const remoteId = crypto.randomUUID();
|
|
152598
152817
|
const id = addTab(
|
|
152599
|
-
|
|
152818
|
+
sql,
|
|
152600
152819
|
createProjectedTabId(WEB_SESSION_ID, remoteId),
|
|
152601
152820
|
tabs.some((tab) => tab.title === "Untitled query") ? `Untitled query ${tabs.filter((tab) => tab.title.startsWith("Untitled query")).length + 1}` : "Untitled query",
|
|
152602
152821
|
void 0,
|
|
@@ -152605,26 +152824,14 @@ function WebApp({ viewHint }) {
|
|
|
152605
152824
|
setQueryConnections((current2) => ({ ...current2, [id]: connectionId }));
|
|
152606
152825
|
setActiveConnectionId(null);
|
|
152607
152826
|
};
|
|
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
|
-
}
|
|
152827
|
+
const showQuery = (tabId) => {
|
|
152828
|
+
setSetupOpen(false);
|
|
152829
|
+
setEditingConnection(null);
|
|
152830
|
+
closeSettingsPanel();
|
|
152831
|
+
setActiveConnectionId(null);
|
|
152832
|
+
setActiveTab(tabId);
|
|
152627
152833
|
};
|
|
152834
|
+
const openConnection = (id) => setActiveConnectionId(id);
|
|
152628
152835
|
const closeQuery = (id) => {
|
|
152629
152836
|
const tab = tabs.find((item) => item.id === id);
|
|
152630
152837
|
if (tab) {
|
|
@@ -152634,7 +152841,7 @@ function WebApp({ viewHint }) {
|
|
|
152634
152841
|
sql: tab.sql,
|
|
152635
152842
|
title: tab.title,
|
|
152636
152843
|
description: descriptions[id] ?? "",
|
|
152637
|
-
connectionId: queryConnections[id] ?? "built-in-duckdb"
|
|
152844
|
+
connectionId: tab.sessionId && tab.sessionId !== WEB_SESSION_ID ? tab.connectionId ?? "" : queryConnections[id] ?? "built-in-duckdb"
|
|
152638
152845
|
}
|
|
152639
152846
|
]);
|
|
152640
152847
|
if (tab.result || tab.isLoading) {
|
|
@@ -152661,7 +152868,7 @@ function WebApp({ viewHint }) {
|
|
|
152661
152868
|
const runQuery = async () => {
|
|
152662
152869
|
if (!activeTab || !activeTab.sql.trim() || !selectedConnectionId || activeTab.isLoading) return;
|
|
152663
152870
|
const { id, sql, title } = activeTab;
|
|
152664
|
-
updateTab(id, { isLoading: true, error: null, cancelled: false });
|
|
152871
|
+
updateTab(id, { isLoading: true, error: null, result: null, cancelled: false });
|
|
152665
152872
|
try {
|
|
152666
152873
|
const result = await callServerTool("run_query", {
|
|
152667
152874
|
sql,
|
|
@@ -152761,14 +152968,7 @@ function WebApp({ viewHint }) {
|
|
|
152761
152968
|
reactExports.useEffect(() => {
|
|
152762
152969
|
if (isReady) void fetchConnections();
|
|
152763
152970
|
}, [isReady, fetchConnections]);
|
|
152764
|
-
|
|
152765
|
-
reactExports.useEffect(() => {
|
|
152766
|
-
if (hasAppliedHint.current || !viewHint) {
|
|
152767
|
-
return;
|
|
152768
|
-
}
|
|
152769
|
-
hasAppliedHint.current = true;
|
|
152770
|
-
openSettingsPanel("connections", viewHint === "connections-add");
|
|
152771
|
-
}, [viewHint, openSettingsPanel]);
|
|
152971
|
+
useWebAppInitialTarget(isReady, viewHint, resultTarget, tabs, showQuery, openSettingsPanel);
|
|
152772
152972
|
reactExports.useEffect(() => {
|
|
152773
152973
|
const mediaQuery = window.matchMedia(SIDEBAR_AUTO_COLLAPSE_QUERY);
|
|
152774
152974
|
const handleChange = (e2) => {
|
|
@@ -152827,6 +153027,8 @@ function WebApp({ viewHint }) {
|
|
|
152827
153027
|
remoteId: msg.remoteId,
|
|
152828
153028
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152829
153029
|
clientType: msg.clientType,
|
|
153030
|
+
connectionId: msg.connectionId,
|
|
153031
|
+
connectionName: msg.connectionName,
|
|
152830
153032
|
isRemote: msg.isRemote
|
|
152831
153033
|
},
|
|
152832
153034
|
!msg.preserveFocus
|
|
@@ -152848,6 +153050,8 @@ function WebApp({ viewHint }) {
|
|
|
152848
153050
|
remoteId: msg.remoteId,
|
|
152849
153051
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152850
153052
|
clientType: msg.clientType,
|
|
153053
|
+
connectionId: msg.connectionId,
|
|
153054
|
+
connectionName: msg.connectionName,
|
|
152851
153055
|
isRemote: msg.isRemote
|
|
152852
153056
|
},
|
|
152853
153057
|
!msg.preserveFocus
|
|
@@ -152860,6 +153064,8 @@ function WebApp({ viewHint }) {
|
|
|
152860
153064
|
remoteId: msg.remoteId,
|
|
152861
153065
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152862
153066
|
clientType: msg.clientType,
|
|
153067
|
+
connectionId: msg.connectionId,
|
|
153068
|
+
connectionName: msg.connectionName,
|
|
152863
153069
|
isRemote: msg.isRemote
|
|
152864
153070
|
});
|
|
152865
153071
|
if (!msg.preserveFocus || !currentActiveId) {
|
|
@@ -152878,6 +153084,8 @@ function WebApp({ viewHint }) {
|
|
|
152878
153084
|
remoteId: msg.remoteId,
|
|
152879
153085
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152880
153086
|
clientType: msg.clientType,
|
|
153087
|
+
connectionId: msg.connectionId,
|
|
153088
|
+
connectionName: msg.connectionName,
|
|
152881
153089
|
isRemote: msg.isRemote
|
|
152882
153090
|
},
|
|
152883
153091
|
false
|
|
@@ -152890,6 +153098,8 @@ function WebApp({ viewHint }) {
|
|
|
152890
153098
|
remoteId: msg.remoteId,
|
|
152891
153099
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152892
153100
|
clientType: msg.clientType,
|
|
153101
|
+
connectionId: msg.connectionId,
|
|
153102
|
+
connectionName: msg.connectionName,
|
|
152893
153103
|
isRemote: msg.isRemote,
|
|
152894
153104
|
result: {
|
|
152895
153105
|
query: msg.data.query,
|
|
@@ -152897,7 +153107,7 @@ function WebApp({ viewHint }) {
|
|
|
152897
153107
|
rows: msg.data.rows,
|
|
152898
153108
|
rowCount: msg.data.totalRowsInFirstBatch ?? msg.data.rows.length,
|
|
152899
153109
|
executionTime: msg.data.executionTimeMs,
|
|
152900
|
-
connection: "
|
|
153110
|
+
connection: msg.connectionName ?? msg.connectionId ?? "Connection unknown",
|
|
152901
153111
|
wasTruncated: msg.data.wasTruncated,
|
|
152902
153112
|
executedAt: msg.data.executedAt
|
|
152903
153113
|
}
|
|
@@ -152915,6 +153125,8 @@ function WebApp({ viewHint }) {
|
|
|
152915
153125
|
remoteId: msg.remoteId,
|
|
152916
153126
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152917
153127
|
clientType: msg.clientType,
|
|
153128
|
+
connectionId: msg.connectionId,
|
|
153129
|
+
connectionName: msg.connectionName,
|
|
152918
153130
|
isRemote: msg.isRemote
|
|
152919
153131
|
},
|
|
152920
153132
|
false
|
|
@@ -152927,6 +153139,8 @@ function WebApp({ viewHint }) {
|
|
|
152927
153139
|
remoteId: msg.remoteId,
|
|
152928
153140
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152929
153141
|
clientType: msg.clientType,
|
|
153142
|
+
connectionId: msg.connectionId,
|
|
153143
|
+
connectionName: msg.connectionName,
|
|
152930
153144
|
isRemote: msg.isRemote
|
|
152931
153145
|
});
|
|
152932
153146
|
break;
|
|
@@ -153034,7 +153248,25 @@ function WebApp({ viewHint }) {
|
|
|
153034
153248
|
] }),
|
|
153035
153249
|
monitorOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { ref: sidebarRef, className: "sp-web-sidebar", "aria-label": "Workspace navigation", children: [
|
|
153036
153250
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-header", children: [
|
|
153037
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153251
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153252
|
+
"button",
|
|
153253
|
+
{
|
|
153254
|
+
type: "button",
|
|
153255
|
+
className: "sp-web-sidebar-title sp-web-section-toggle",
|
|
153256
|
+
"aria-expanded": !connectionsCollapsed,
|
|
153257
|
+
"aria-controls": "sp-web-connections",
|
|
153258
|
+
onClick: () => {
|
|
153259
|
+
setConnectionsCollapsed((current2) => {
|
|
153260
|
+
writeStoredValue(CONNECTIONS_COLLAPSED_KEY, String(!current2));
|
|
153261
|
+
return !current2;
|
|
153262
|
+
});
|
|
153263
|
+
},
|
|
153264
|
+
children: [
|
|
153265
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: connectionsCollapsed ? "▸" : "▾" }),
|
|
153266
|
+
" Connections"
|
|
153267
|
+
]
|
|
153268
|
+
}
|
|
153269
|
+
),
|
|
153038
153270
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153039
153271
|
SidebarAddButton,
|
|
153040
153272
|
{
|
|
@@ -153068,63 +153300,55 @@ function WebApp({ viewHint }) {
|
|
|
153068
153300
|
"aria-valuemax": SIDEBAR_MAX_WIDTH
|
|
153069
153301
|
}
|
|
153070
153302
|
),
|
|
153071
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153072
|
-
"
|
|
153303
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153304
|
+
"div",
|
|
153073
153305
|
{
|
|
153074
|
-
|
|
153075
|
-
className: "sp-web-connection-
|
|
153076
|
-
|
|
153077
|
-
children:
|
|
153078
|
-
|
|
153079
|
-
|
|
153080
|
-
|
|
153081
|
-
|
|
153082
|
-
|
|
153083
|
-
|
|
153084
|
-
|
|
153085
|
-
|
|
153086
|
-
|
|
153087
|
-
|
|
153088
|
-
|
|
153089
|
-
|
|
153090
|
-
|
|
153306
|
+
id: "sp-web-connections",
|
|
153307
|
+
className: "sp-web-connection-list",
|
|
153308
|
+
hidden: connectionsCollapsed,
|
|
153309
|
+
children: connections.length ? connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153310
|
+
"button",
|
|
153311
|
+
{
|
|
153312
|
+
type: "button",
|
|
153313
|
+
className: "sp-web-connection-item",
|
|
153314
|
+
"aria-current": activeConnectionId === connection.id ? "page" : void 0,
|
|
153315
|
+
onClick: () => openConnection(connection.id),
|
|
153316
|
+
children: [
|
|
153317
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DatabaseIcon, { size: 15 }) }),
|
|
153318
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-web-connection-label", children: [
|
|
153319
|
+
connection.name ?? connection.id,
|
|
153320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: connection.type })
|
|
153321
|
+
] }),
|
|
153322
|
+
connection.engineState === "ready" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153323
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-dot", "aria-hidden": "true" }),
|
|
153324
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-visually-hidden", children: "Ready" })
|
|
153325
|
+
] })
|
|
153326
|
+
]
|
|
153327
|
+
},
|
|
153328
|
+
connection.id
|
|
153329
|
+
)) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-sidebar-helper", children: "No connections yet." })
|
|
153330
|
+
}
|
|
153331
|
+
),
|
|
153091
153332
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-section-title", children: [
|
|
153092
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "
|
|
153333
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "My queries" }),
|
|
153093
153334
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarAddButton, { label: "Add query", title: "New query", onClick: () => newQuery() })
|
|
153094
153335
|
] }),
|
|
153095
153336
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-session-list", children: [
|
|
153096
153337
|
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(
|
|
153338
|
+
tabs.filter((tab) => !tab.sessionId || tab.sessionId === WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153098
153339
|
"button",
|
|
153099
153340
|
{
|
|
153100
153341
|
type: "button",
|
|
153101
153342
|
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
153102
153343
|
"aria-pressed": activeTabId === tab.id,
|
|
153103
|
-
onClick: () =>
|
|
153104
|
-
|
|
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(
|
|
153113
|
-
"button",
|
|
153114
|
-
{
|
|
153115
|
-
type: "button",
|
|
153116
|
-
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
153117
|
-
"aria-pressed": activeTabId === tab.id,
|
|
153118
|
-
onClick: () => {
|
|
153119
|
-
setActiveTab(tab.id);
|
|
153120
|
-
setActiveConnectionId(null);
|
|
153121
|
-
},
|
|
153122
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: tab.title })
|
|
153344
|
+
onClick: () => showQuery(tab.id),
|
|
153345
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: displayQueryTitle(tab.title, tab.sql) })
|
|
153123
153346
|
},
|
|
153124
153347
|
tab.id
|
|
153125
153348
|
)),
|
|
153126
153349
|
tabs.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-empty-sessions", children: "No queries yet." })
|
|
153127
153350
|
] }),
|
|
153351
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentActivity, { tabs, activeTabId, onSelect: showQuery }),
|
|
153128
153352
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-footer", children: "⌂ All work stays on this computer." })
|
|
153129
153353
|
] }),
|
|
153130
153354
|
setupOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-main", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -153161,41 +153385,6 @@ function WebApp({ viewHint }) {
|
|
|
153161
153385
|
) }),
|
|
153162
153386
|
!settingsPanelTab && (activeTab || activeConnectionId) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-workspace", children: [
|
|
153163
153387
|
/* @__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
153388
|
tabs.map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153200
153389
|
"div",
|
|
153201
153390
|
{
|
|
@@ -153207,18 +153396,15 @@ function WebApp({ viewHint }) {
|
|
|
153207
153396
|
type: "button",
|
|
153208
153397
|
role: "tab",
|
|
153209
153398
|
"aria-selected": tab.id === activeTabId && !activeConnectionId,
|
|
153210
|
-
onClick: () =>
|
|
153211
|
-
|
|
153212
|
-
setActiveConnectionId(null);
|
|
153213
|
-
},
|
|
153214
|
-
children: tab.title
|
|
153399
|
+
onClick: () => showQuery(tab.id),
|
|
153400
|
+
children: displayQueryTitle(tab.title, tab.sql)
|
|
153215
153401
|
}
|
|
153216
153402
|
),
|
|
153217
153403
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153218
153404
|
"button",
|
|
153219
153405
|
{
|
|
153220
153406
|
type: "button",
|
|
153221
|
-
"aria-label": `Close ${tab.title} tab`,
|
|
153407
|
+
"aria-label": `Close ${displayQueryTitle(tab.title, tab.sql)} tab`,
|
|
153222
153408
|
onClick: () => closeQuery(tab.id),
|
|
153223
153409
|
children: "×"
|
|
153224
153410
|
}
|
|
@@ -153242,51 +153428,39 @@ function WebApp({ viewHint }) {
|
|
|
153242
153428
|
activeConnectionId ? (() => {
|
|
153243
153429
|
const connection = connections.find((item) => item.id === activeConnectionId);
|
|
153244
153430
|
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
|
-
] });
|
|
153431
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153432
|
+
ConnectionPage,
|
|
153433
|
+
{
|
|
153434
|
+
connection,
|
|
153435
|
+
onNewQuery: () => newQuery(connection.id),
|
|
153436
|
+
onEdit: () => {
|
|
153437
|
+
setEditingConnection(connection);
|
|
153438
|
+
setSetupOpen(true);
|
|
153439
|
+
},
|
|
153440
|
+
onDeleted: () => {
|
|
153441
|
+
setActiveConnectionId(null);
|
|
153442
|
+
setQueryConnections(
|
|
153443
|
+
(current2) => Object.fromEntries(
|
|
153444
|
+
Object.entries(current2).map(([tabId, id]) => [
|
|
153445
|
+
tabId,
|
|
153446
|
+
id === connection.id ? "built-in-duckdb" : id
|
|
153447
|
+
])
|
|
153448
|
+
)
|
|
153449
|
+
);
|
|
153450
|
+
void fetchConnections();
|
|
153451
|
+
}
|
|
153452
|
+
},
|
|
153453
|
+
connection.id
|
|
153454
|
+
);
|
|
153287
153455
|
})() : activeTab && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153288
153456
|
" ",
|
|
153289
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153457
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-query-heading", children: isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153458
|
+
AgentQueryHeading,
|
|
153459
|
+
{
|
|
153460
|
+
tab: activeTab,
|
|
153461
|
+
connectionName: activeConnectionName
|
|
153462
|
+
}
|
|
153463
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153290
153464
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153291
153465
|
"input",
|
|
153292
153466
|
{
|
|
@@ -153308,9 +153482,9 @@ function WebApp({ viewHint }) {
|
|
|
153308
153482
|
rows: 1
|
|
153309
153483
|
}
|
|
153310
153484
|
)
|
|
153311
|
-
] }),
|
|
153485
|
+
] }) }),
|
|
153312
153486
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-toolbar", children: [
|
|
153313
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("
|
|
153487
|
+
isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-readonly", children: activeConnectionName ?? "Connection unknown" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153314
153488
|
"select",
|
|
153315
153489
|
{
|
|
153316
153490
|
"aria-label": "Query connection",
|
|
@@ -153319,10 +153493,24 @@ function WebApp({ viewHint }) {
|
|
|
153319
153493
|
...current2,
|
|
153320
153494
|
[activeTab.id]: event.target.value
|
|
153321
153495
|
})),
|
|
153322
|
-
children:
|
|
153496
|
+
children: [
|
|
153497
|
+
!selectedConnectionId && /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Choose connection" }),
|
|
153498
|
+
selectedConnectionId && !connections.some(
|
|
153499
|
+
(connection) => connection.id === selectedConnectionId
|
|
153500
|
+
) && /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: selectedConnectionId, children: selectedConnectionId }),
|
|
153501
|
+
connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connection.id, children: connection.name ?? connection.id }, connection.id))
|
|
153502
|
+
]
|
|
153323
153503
|
}
|
|
153324
153504
|
) }),
|
|
153325
|
-
|
|
153505
|
+
isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153506
|
+
"button",
|
|
153507
|
+
{
|
|
153508
|
+
type: "button",
|
|
153509
|
+
className: "sp-web-secondary-button",
|
|
153510
|
+
onClick: () => newQuery(activeTab.connectionId ?? "", activeTab.sql),
|
|
153511
|
+
children: "Open as my query"
|
|
153512
|
+
}
|
|
153513
|
+
) : activeTab.isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153326
153514
|
"button",
|
|
153327
153515
|
{
|
|
153328
153516
|
type: "button",
|
|
@@ -153350,7 +153538,8 @@ function WebApp({ viewHint }) {
|
|
|
153350
153538
|
{
|
|
153351
153539
|
value: activeTab.sql,
|
|
153352
153540
|
onChange: (sql) => updateTab(activeTab.id, { sql }),
|
|
153353
|
-
onRun: () => void runQuery()
|
|
153541
|
+
onRun: () => void runQuery(),
|
|
153542
|
+
readOnly: isAgentTab
|
|
153354
153543
|
}
|
|
153355
153544
|
)
|
|
153356
153545
|
] })
|
|
@@ -153369,7 +153558,13 @@ async function bootstrap() {
|
|
|
153369
153558
|
return;
|
|
153370
153559
|
}
|
|
153371
153560
|
ReactDOM$1.createRoot(document.getElementById("root")).render(
|
|
153372
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(React.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(WebHostProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153561
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(React.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(WebHostProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153562
|
+
WebApp,
|
|
153563
|
+
{
|
|
153564
|
+
viewHint: result.view,
|
|
153565
|
+
...result.result ? { resultTarget: result.result } : {}
|
|
153566
|
+
}
|
|
153567
|
+
) }) })
|
|
153373
153568
|
);
|
|
153374
153569
|
}
|
|
153375
153570
|
bootstrap();</script>
|
|
@@ -153528,11 +153723,18 @@ bootstrap();</script>
|
|
|
153528
153723
|
margin: 5px 0 0;
|
|
153529
153724
|
}
|
|
153530
153725
|
.grain-connection-success {
|
|
153531
|
-
color: var(--
|
|
153532
|
-
|
|
153726
|
+
color: var(--vscode-testing-iconPassed, var(--sp-success));
|
|
153727
|
+
border: 1px solid var(--vscode-testing-iconPassed, var(--sp-success));
|
|
153728
|
+
background: color-mix(in srgb, var(--sp-success) 8%, var(--grain-surface));
|
|
153533
153729
|
padding: 10px 14px;
|
|
153534
153730
|
border-radius: var(--grain-radius-sm);
|
|
153535
153731
|
}
|
|
153732
|
+
.grain-connection-footer .grain-connection-success {
|
|
153733
|
+
color: var(--vscode-testing-iconPassed, var(--sp-success));
|
|
153734
|
+
}
|
|
153735
|
+
.grain-connection-footer-error {
|
|
153736
|
+
color: var(--vscode-errorForeground, var(--sp-error));
|
|
153737
|
+
}
|
|
153536
153738
|
.grain-connection-page :is(button, input, select, summary):focus-visible {
|
|
153537
153739
|
outline: 2px solid var(--grain-accent);
|
|
153538
153740
|
outline-offset: 2px;
|
|
@@ -166390,6 +166592,31 @@ body {
|
|
|
166390
166592
|
.sp-web-sidebar-header .sp-web-sidebar-title {
|
|
166391
166593
|
flex: 1;
|
|
166392
166594
|
}
|
|
166595
|
+
.sp-web-section-toggle,
|
|
166596
|
+
.sp-web-agent-session-toggle {
|
|
166597
|
+
border: 0;
|
|
166598
|
+
background: transparent;
|
|
166599
|
+
color: var(--grain-ink);
|
|
166600
|
+
font: inherit;
|
|
166601
|
+
text-align: left;
|
|
166602
|
+
cursor: pointer;
|
|
166603
|
+
}
|
|
166604
|
+
.sp-web-section-toggle {
|
|
166605
|
+
padding: 0;
|
|
166606
|
+
}
|
|
166607
|
+
.sp-web-agent-session-toggle {
|
|
166608
|
+
width: 100%;
|
|
166609
|
+
padding: 7px 9px;
|
|
166610
|
+
color: var(--grain-ink-muted);
|
|
166611
|
+
font-size: 11px;
|
|
166612
|
+
}
|
|
166613
|
+
.sp-web-section-toggle:focus-visible,
|
|
166614
|
+
.sp-web-agent-session-toggle:focus-visible {
|
|
166615
|
+
outline: 1px solid var(--grain-accent);
|
|
166616
|
+
}
|
|
166617
|
+
[aria-current='page'].sp-web-connection-item {
|
|
166618
|
+
background: var(--grain-surface-raised);
|
|
166619
|
+
}
|
|
166393
166620
|
.sp-web-section-add,
|
|
166394
166621
|
.sp-web-sidebar-close {
|
|
166395
166622
|
display: inline-flex;
|
|
@@ -166581,6 +166808,14 @@ body {
|
|
|
166581
166808
|
gap: 4px;
|
|
166582
166809
|
padding: 18px 24px 14px;
|
|
166583
166810
|
}
|
|
166811
|
+
.sp-web-query-heading h1 {
|
|
166812
|
+
margin: 0;
|
|
166813
|
+
font-size: 22px;
|
|
166814
|
+
}
|
|
166815
|
+
.sp-web-query-provenance {
|
|
166816
|
+
color: var(--grain-ink-muted);
|
|
166817
|
+
font-size: 11px;
|
|
166818
|
+
}
|
|
166584
166819
|
.sp-web-query-heading input,
|
|
166585
166820
|
.sp-web-query-heading textarea {
|
|
166586
166821
|
width: 100%;
|
|
@@ -166796,6 +167031,18 @@ body {
|
|
|
166796
167031
|
.sp-web-connection-detail p {
|
|
166797
167032
|
color: var(--grain-ink-muted);
|
|
166798
167033
|
}
|
|
167034
|
+
.sp-web-connection-detail .sp-web-connection-test-success {
|
|
167035
|
+
color: var(--vscode-testing-iconPassed, var(--sp-success));
|
|
167036
|
+
}
|
|
167037
|
+
.sp-web-connection-detail .sp-web-connection-test-error {
|
|
167038
|
+
color: var(--vscode-errorForeground, var(--sp-error));
|
|
167039
|
+
}
|
|
167040
|
+
.sp-web-connection-delete-confirm {
|
|
167041
|
+
margin-top: 16px;
|
|
167042
|
+
}
|
|
167043
|
+
.sp-web-connection-delete-confirm p {
|
|
167044
|
+
color: var(--grain-ink);
|
|
167045
|
+
}
|
|
166799
167046
|
.sp-web-connection-actions {
|
|
166800
167047
|
display: flex;
|
|
166801
167048
|
gap: 8px;
|