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/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
- try {
13784
- const stored = window.sessionStorage.getItem(WEB_SESSION_KEY);
13785
- if (stored && /^web-[0-9a-f-]{36}$/.test(stored)) return stored;
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
- try {
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.jsx("p", { className: "grain-connection-success", role: "status", children: "Connection test successful." }),
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.jsx("p", { children: "Grain will test the connection before saving it." }),
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 [openConnectionIds, setOpenConnectionIds] = reactExports.useState([]);
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 selectedConnectionId = activeTab ? queryConnections[activeTab.id] ?? localConnection?.id ?? connections[0]?.id ?? "" : "";
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
- "SELECT 42;",
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 openConnection = (id) => {
152609
- setOpenConnectionIds((current2) => current2.includes(id) ? current2 : [...current2, id]);
152610
- setActiveConnectionId(id);
152611
- };
152612
- const testConnection = async (id) => {
152613
- setConnectionStatus((current2) => ({ ...current2, [id]: "Testing…" }));
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: "Web",
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.jsx("span", { className: "sp-web-sidebar-title", children: "Connections" }),
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("div", { className: "sp-web-connection-list", children: connections.length ? connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
153072
- "button",
153272
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
153273
+ "div",
153073
153274
  {
153074
- type: "button",
153075
- className: "sp-web-connection-item",
153076
- onClick: () => openConnection(connection.id),
153077
- children: [
153078
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DatabaseIcon, { size: 15 }) }),
153079
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-web-connection-label", children: [
153080
- connection.name ?? connection.id,
153081
- /* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: connection.type })
153082
- ] }),
153083
- connection.engineState === "ready" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
153084
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-dot", "aria-hidden": "true" }),
153085
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-visually-hidden", children: "Ready" })
153086
- ] })
153087
- ]
153088
- },
153089
- connection.id
153090
- )) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-sidebar-helper", children: "No connections yet." }) }),
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: "Queries" }),
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
- setActiveTab(tab.id);
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
- setActiveTab(tab.id);
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.jsxs("div", { className: "sp-web-connection-detail", children: [
153246
- /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: connection.name ?? connection.id }),
153247
- /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
153248
- connection.type ?? "Database",
153249
- " ·",
153250
- " ",
153251
- connectionStatus[connection.id] ?? (connection.engineState === "ready" ? "Ready" : "Saved connection")
153252
- ] }),
153253
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-actions", children: [
153254
- /* @__PURE__ */ jsxRuntimeExports.jsx(
153255
- "button",
153256
- {
153257
- type: "button",
153258
- className: "sp-web-primary-button",
153259
- "aria-label": `New query for ${connection.name ?? connection.id}`,
153260
- onClick: () => newQuery(connection.id),
153261
- children: "New query"
153262
- }
153263
- ),
153264
- !connection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx(
153265
- "button",
153266
- {
153267
- type: "button",
153268
- className: "sp-web-secondary-button",
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.jsxs("div", { className: "sp-web-query-heading", children: [
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("label", { children: /* @__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: connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connection.id, children: connection.name ?? connection.id }, connection.id))
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
- activeTab.isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(
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(--grain-ink);
153532
- background: var(--grain-surface);
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;