grain-tools 0.10.7 → 0.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -274,7 +274,7 @@ settings JSON by hand.
274
274
  | `grain.alwaysRunInNewTab` | `false` | Always open query results in a new tab |
275
275
  | `grain.mcpEnabled` | `false` | Serve the local MCP surface for agent access. Off means `/mcp` is not registered (404) |
276
276
  | `grain.mcpSafeMode` | `true` | Restrict MCP query execution to read-only statements |
277
- | `grain.telemetry.enabled` | `false` | Opt in to anonymous product telemetry |
277
+ | `grain.telemetry.enabled` | `true` | Anonymous product telemetry; follows your VS Code telemetry setting |
278
278
  | `grain.telemetryHost` | `https://us.i.posthog.com` | Advanced PostHog-compatible telemetry endpoint |
279
279
 
280
280
  Legacy connection settings such as `sqlPreview.host`, `sqlPreview.port`,
package/dist/web-app.html CHANGED
@@ -1,14 +1,14 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Grain — Workbench</title>
6
+ <title>Grain</title>
7
7
  <meta name="theme-color" content="#1e1e1e" />
8
8
  <link
9
9
  rel="icon"
10
- type="image/svg+xml"
11
- href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%23007acc'/%3E%3Cpath fill='white' d='M3.75 3A1.75 1.75 0 0 0 2 4.75v6.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0 0 14 11.25v-6.5A1.75 1.75 0 0 0 12.25 3h-8.5ZM3.5 7.75v3.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5H3.5ZM12.5 6.25H3.5V4.75c0-.138.112-.25.25-.25h8.5a.25.25 0 0 1 .25.25v1.5Z'/%3E%3C/svg%3E"
10
+ type="image/png"
11
+ href="data:image/png;base64,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"
12
12
  />
13
13
  <script type="module" crossorigin>var _a2, _b2, _c2;
14
14
  (function polyfill() {
@@ -12549,10 +12549,15 @@ function useWebSession() {
12549
12549
  async function bootstrapLocalSession(location, history) {
12550
12550
  const params = new URLSearchParams(location.hash.replace(/^#/, ""));
12551
12551
  const capability = params.get("launch");
12552
- if (!capability) {
12553
- return "no-capability";
12552
+ const rawView = params.get("view");
12553
+ let view = void 0;
12554
+ if (rawView === "connections" || rawView === "connections-add") {
12555
+ view = rawView;
12554
12556
  }
12555
12557
  history.replaceState({}, "", `${location.pathname}${location.search}`);
12558
+ if (!capability) {
12559
+ return { session: "no-capability", view };
12560
+ }
12556
12561
  try {
12557
12562
  const response = await fetch(LOCAL_EXCHANGE_PATH, {
12558
12563
  method: "POST",
@@ -12563,11 +12568,11 @@ async function bootstrapLocalSession(location, history) {
12563
12568
  body: JSON.stringify({ capability })
12564
12569
  });
12565
12570
  if (response.status === 204) {
12566
- return "ok";
12571
+ return { session: "ok", view };
12567
12572
  }
12568
- return "failed";
12573
+ return { session: "failed", view };
12569
12574
  } catch {
12570
- return "failed";
12575
+ return { session: "failed", view };
12571
12576
  }
12572
12577
  }
12573
12578
  async function authorizedFetch(input, init2) {
@@ -14323,10 +14328,10 @@ function ReauthorizeNotice({
14323
14328
  reason
14324
14329
  }) {
14325
14330
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth", role: "alert", children: [
14326
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: reason === "unreachable" ? "Grain is no longer answering at this address" : "Grain needs to authorize this page again" }),
14331
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: reason === "unreachable" ? "Grain is no longer answering at this address" : reason === "expired-link" ? "This link has already been used" : "Open this workspace from your terminal" }),
14327
14332
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
14328
- reason === "expired-link" && "This authorization link had already been used, or it expired.",
14329
- reason === "no-session" && "This page is no longer authorized. Grain restarts, a new tab, and a session left open for a while all end up here.",
14333
+ reason === "expired-link" && "An authorization link works once, and only for a short while.",
14334
+ reason === "no-session" && "A workspace session is short-lived. A new tab, a restart, or a session left open for a while all end up here.",
14330
14335
  reason === "unreachable" && "The service stopped, or it came back on a different port. This page cannot find it again on its own."
14331
14336
  ] }),
14332
14337
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
@@ -151572,7 +151577,8 @@ function TabContextMenu({
151572
151577
  const LandingScreen = ({
151573
151578
  onNewConnection,
151574
151579
  onNewQueryFile,
151575
- onManageConnections
151580
+ onManageConnections,
151581
+ onTryDemo
151576
151582
  }) => {
151577
151583
  const { sendMessage, callServerTool, isReady } = useHostContext();
151578
151584
  const {
@@ -151629,6 +151635,13 @@ const LandingScreen = ({
151629
151635
  openSettingsPanel("connections");
151630
151636
  }
151631
151637
  };
151638
+ const handleTryDemo = () => {
151639
+ if (onTryDemo) {
151640
+ onTryDemo();
151641
+ } else {
151642
+ sendMessage("openDemo");
151643
+ }
151644
+ };
151632
151645
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-landing", role: "region", "aria-label": "Grain Welcome and Quick Actions", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-card", children: [
151633
151646
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-header", children: [
151634
151647
  /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "sp-landing-title", children: [
@@ -151695,6 +151708,19 @@ const LandingScreen = ({
151695
151708
  "Create Connection"
151696
151709
  ]
151697
151710
  }
151711
+ ),
151712
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
151713
+ "button",
151714
+ {
151715
+ type: "button",
151716
+ className: "sp-btn sp-landing-btn",
151717
+ onClick: handleTryDemo,
151718
+ "aria-label": "Try the Grain demo",
151719
+ children: [
151720
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CodeIcon, { size: 14 }),
151721
+ "Try the Demo"
151722
+ ]
151723
+ }
151698
151724
  )
151699
151725
  ] }),
151700
151726
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-footer", children: [
@@ -152597,7 +152623,7 @@ const SIDEBAR_MIN_WIDTH = 160;
152597
152623
  const SIDEBAR_MAX_WIDTH = 400;
152598
152624
  const SIDEBAR_AUTO_COLLAPSE_QUERY = "(max-width: 640px)";
152599
152625
  const SIDEBAR_WIDTH_STORAGE_KEY = "sql-preview:web-sidebar-width";
152600
- function WebApp() {
152626
+ function WebApp({ viewHint }) {
152601
152627
  const { onMessage, isReady, sendMessage } = useHostContext();
152602
152628
  const session = useWebSession();
152603
152629
  const {
@@ -152607,7 +152633,8 @@ function WebApp() {
152607
152633
  setActiveTab,
152608
152634
  setTheme,
152609
152635
  projectionSessionId,
152610
- setProjectionSession
152636
+ setProjectionSession,
152637
+ openSettingsPanel
152611
152638
  } = useAppStore();
152612
152639
  const [sessions, setSessions] = reactExports.useState([]);
152613
152640
  const [monitorOpen, setMonitorOpen] = reactExports.useState(true);
@@ -152622,6 +152649,14 @@ function WebApp() {
152622
152649
  var _a3;
152623
152650
  (_a3 = sidebarRef.current) == null ? void 0 : _a3.style.setProperty("--sp-web-sidebar-width", `${sidebarWidth}px`);
152624
152651
  }, [sidebarWidth, monitorOpen]);
152652
+ const hasAppliedHint = reactExports.useRef(false);
152653
+ reactExports.useEffect(() => {
152654
+ if (hasAppliedHint.current || !viewHint) {
152655
+ return;
152656
+ }
152657
+ hasAppliedHint.current = true;
152658
+ openSettingsPanel("connections", viewHint === "connections-add");
152659
+ }, [viewHint, openSettingsPanel]);
152625
152660
  reactExports.useEffect(() => {
152626
152661
  const mediaQuery = window.matchMedia(SIDEBAR_AUTO_COLLAPSE_QUERY);
152627
152662
  const handleChange = (e2) => {
@@ -152964,14 +152999,14 @@ function WebApp() {
152964
152999
  }
152965
153000
  async function bootstrap() {
152966
153001
  const result = await bootstrapLocalSession(window.location, window.history);
152967
- if (result === "failed") {
153002
+ if (result.session === "failed") {
152968
153003
  ReactDOM.createRoot(document.getElementById("root")).render(
152969
153004
  /* @__PURE__ */ jsxRuntimeExports.jsx(React$2.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ReauthorizeNotice, { reason: "expired-link" }) })
152970
153005
  );
152971
153006
  return;
152972
153007
  }
152973
153008
  ReactDOM.createRoot(document.getElementById("root")).render(
152974
- /* @__PURE__ */ jsxRuntimeExports.jsx(React$2.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(WebHostProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(WebApp, {}) }) })
153009
+ /* @__PURE__ */ jsxRuntimeExports.jsx(React$2.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(WebHostProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(WebApp, { viewHint: result.view }) }) })
152975
153010
  );
152976
153011
  }
152977
153012
  bootstrap();</script>