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.
@@ -12745,7 +12745,10 @@ function ConnectionSetupPage({
12745
12745
  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Connection failed" }),
12746
12746
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: error })
12747
12747
  ] }),
12748
- tested && !error && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "grain-connection-success", role: "status", children: "Connection test successful." }),
12748
+ tested && !error && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", role: "status", children: [
12749
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
12750
+ "Connection test successful."
12751
+ ] }),
12749
12752
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-grid", children: [
12750
12753
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-field", children: [
12751
12754
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-type", children: "Database type" }),
@@ -12833,7 +12836,10 @@ function ConnectionSetupPage({
12833
12836
  ] })
12834
12837
  ] }),
12835
12838
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-footer", children: [
12836
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Grain will test the connection before saving it." }),
12839
+ tested && !error ? /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", children: [
12840
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
12841
+ "Connection test successful."
12842
+ ] }) : 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." }),
12837
12843
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-actions", children: [
12838
12844
  /* @__PURE__ */ jsxRuntimeExports.jsx(
12839
12845
  "button",
@@ -12940,7 +12946,12 @@ function ConnectionSetupApp() {
12940
12946
  if (saved)
12941
12947
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "grain-setup-state", role: "status", children: [
12942
12948
  /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: "Saved." }),
12943
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Go back to your agent — it will retry." })
12949
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Go back to your agent, and it will retry." }),
12950
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-setup-workspace", children: [
12951
+ "To run queries yourself, run ",
12952
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "grain ui" }),
12953
+ " in a terminal to open the Grain workspace (Beta). The workspace is in beta and may be unstable."
12954
+ ] })
12944
12955
  ] });
12945
12956
  if (!state || !actions)
12946
12957
  return /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "grain-setup-state", role: "status", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: message }) });
@@ -12949,13 +12960,11 @@ function ConnectionSetupApp() {
12949
12960
  {
12950
12961
  value: {
12951
12962
  mode: "standalone",
12952
- sendMessage: () => {
12953
- },
12963
+ sendMessage: () => void 0,
12954
12964
  callServerTool: async () => {
12955
12965
  throw new Error("Unavailable");
12956
12966
  },
12957
- onMessage: () => () => {
12958
- },
12967
+ onMessage: () => () => void 0,
12959
12968
  isReady: true
12960
12969
  },
12961
12970
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -13129,11 +13138,18 @@ clientExports.createRoot(document.getElementById("root")).render(/* @__PURE__ */
13129
13138
  margin: 5px 0 0;
13130
13139
  }
13131
13140
  .grain-connection-success {
13132
- color: var(--grain-ink);
13133
- background: var(--grain-surface);
13141
+ color: var(--vscode-testing-iconPassed, var(--sp-success));
13142
+ border: 1px solid var(--vscode-testing-iconPassed, var(--sp-success));
13143
+ background: color-mix(in srgb, var(--sp-success) 8%, var(--grain-surface));
13134
13144
  padding: 10px 14px;
13135
13145
  border-radius: var(--grain-radius-sm);
13136
13146
  }
13147
+ .grain-connection-footer .grain-connection-success {
13148
+ color: var(--vscode-testing-iconPassed, var(--sp-success));
13149
+ }
13150
+ .grain-connection-footer-error {
13151
+ color: var(--vscode-errorForeground, var(--sp-error));
13152
+ }
13137
13153
  .grain-connection-page :is(button, input, select, summary):focus-visible {
13138
13154
  outline: 2px solid var(--grain-accent);
13139
13155
  outline-offset: 2px;
@@ -17468,6 +17484,31 @@ body {
17468
17484
  .sp-web-sidebar-header .sp-web-sidebar-title {
17469
17485
  flex: 1;
17470
17486
  }
17487
+ .sp-web-section-toggle,
17488
+ .sp-web-agent-session-toggle {
17489
+ border: 0;
17490
+ background: transparent;
17491
+ color: var(--grain-ink);
17492
+ font: inherit;
17493
+ text-align: left;
17494
+ cursor: pointer;
17495
+ }
17496
+ .sp-web-section-toggle {
17497
+ padding: 0;
17498
+ }
17499
+ .sp-web-agent-session-toggle {
17500
+ width: 100%;
17501
+ padding: 7px 9px;
17502
+ color: var(--grain-ink-muted);
17503
+ font-size: 11px;
17504
+ }
17505
+ .sp-web-section-toggle:focus-visible,
17506
+ .sp-web-agent-session-toggle:focus-visible {
17507
+ outline: 1px solid var(--grain-accent);
17508
+ }
17509
+ [aria-current='page'].sp-web-connection-item {
17510
+ background: var(--grain-surface-raised);
17511
+ }
17471
17512
  .sp-web-section-add,
17472
17513
  .sp-web-sidebar-close {
17473
17514
  display: inline-flex;
@@ -17659,6 +17700,14 @@ body {
17659
17700
  gap: 4px;
17660
17701
  padding: 18px 24px 14px;
17661
17702
  }
17703
+ .sp-web-query-heading h1 {
17704
+ margin: 0;
17705
+ font-size: 22px;
17706
+ }
17707
+ .sp-web-query-provenance {
17708
+ color: var(--grain-ink-muted);
17709
+ font-size: 11px;
17710
+ }
17662
17711
  .sp-web-query-heading input,
17663
17712
  .sp-web-query-heading textarea {
17664
17713
  width: 100%;
@@ -17874,6 +17923,18 @@ body {
17874
17923
  .sp-web-connection-detail p {
17875
17924
  color: var(--grain-ink-muted);
17876
17925
  }
17926
+ .sp-web-connection-detail .sp-web-connection-test-success {
17927
+ color: var(--vscode-testing-iconPassed, var(--sp-success));
17928
+ }
17929
+ .sp-web-connection-detail .sp-web-connection-test-error {
17930
+ color: var(--vscode-errorForeground, var(--sp-error));
17931
+ }
17932
+ .sp-web-connection-delete-confirm {
17933
+ margin-top: 16px;
17934
+ }
17935
+ .sp-web-connection-delete-confirm p {
17936
+ color: var(--grain-ink);
17937
+ }
17877
17938
  .sp-web-connection-actions {
17878
17939
  display: flex;
17879
17940
  gap: 8px;
@@ -17913,6 +17974,15 @@ body {
17913
17974
  .grain-connection-readonly {
17914
17975
  grid-template-columns: 1fr;
17915
17976
  }
17977
+ }
17978
+
17979
+ .grain-setup-workspace {
17980
+ color: var(--grain-ink-muted);
17981
+ font-size: 13px;
17982
+ }
17983
+
17984
+ .grain-setup-workspace code {
17985
+ font-family: var(--grain-font-mono);
17916
17986
  }</style>
17917
17987
  </head>
17918
17988
  <body>
@@ -4351,6 +4351,31 @@ body {
4351
4351
  .sp-web-sidebar-header .sp-web-sidebar-title {
4352
4352
  flex: 1;
4353
4353
  }
4354
+ .sp-web-section-toggle,
4355
+ .sp-web-agent-session-toggle {
4356
+ border: 0;
4357
+ background: transparent;
4358
+ color: var(--grain-ink);
4359
+ font: inherit;
4360
+ text-align: left;
4361
+ cursor: pointer;
4362
+ }
4363
+ .sp-web-section-toggle {
4364
+ padding: 0;
4365
+ }
4366
+ .sp-web-agent-session-toggle {
4367
+ width: 100%;
4368
+ padding: 7px 9px;
4369
+ color: var(--grain-ink-muted);
4370
+ font-size: 11px;
4371
+ }
4372
+ .sp-web-section-toggle:focus-visible,
4373
+ .sp-web-agent-session-toggle:focus-visible {
4374
+ outline: 1px solid var(--grain-accent);
4375
+ }
4376
+ [aria-current='page'].sp-web-connection-item {
4377
+ background: var(--grain-surface-raised);
4378
+ }
4354
4379
  .sp-web-section-add,
4355
4380
  .sp-web-sidebar-close {
4356
4381
  display: inline-flex;
@@ -4542,6 +4567,14 @@ body {
4542
4567
  gap: 4px;
4543
4568
  padding: 18px 24px 14px;
4544
4569
  }
4570
+ .sp-web-query-heading h1 {
4571
+ margin: 0;
4572
+ font-size: 22px;
4573
+ }
4574
+ .sp-web-query-provenance {
4575
+ color: var(--grain-ink-muted);
4576
+ font-size: 11px;
4577
+ }
4545
4578
  .sp-web-query-heading input,
4546
4579
  .sp-web-query-heading textarea {
4547
4580
  width: 100%;
@@ -4757,6 +4790,18 @@ body {
4757
4790
  .sp-web-connection-detail p {
4758
4791
  color: var(--grain-ink-muted);
4759
4792
  }
4793
+ .sp-web-connection-detail .sp-web-connection-test-success {
4794
+ color: var(--vscode-testing-iconPassed, var(--sp-success));
4795
+ }
4796
+ .sp-web-connection-detail .sp-web-connection-test-error {
4797
+ color: var(--vscode-errorForeground, var(--sp-error));
4798
+ }
4799
+ .sp-web-connection-delete-confirm {
4800
+ margin-top: 16px;
4801
+ }
4802
+ .sp-web-connection-delete-confirm p {
4803
+ color: var(--grain-ink);
4804
+ }
4760
4805
  .sp-web-connection-actions {
4761
4806
  display: flex;
4762
4807
  gap: 8px;
@@ -4917,11 +4962,18 @@ body {
4917
4962
  margin: 5px 0 0;
4918
4963
  }
4919
4964
  .grain-connection-success {
4920
- color: var(--grain-ink);
4921
- background: var(--grain-surface);
4965
+ color: var(--vscode-testing-iconPassed, var(--sp-success));
4966
+ border: 1px solid var(--vscode-testing-iconPassed, var(--sp-success));
4967
+ background: color-mix(in srgb, var(--sp-success) 8%, var(--grain-surface));
4922
4968
  padding: 10px 14px;
4923
4969
  border-radius: var(--grain-radius-sm);
4924
4970
  }
4971
+ .grain-connection-footer .grain-connection-success {
4972
+ color: var(--vscode-testing-iconPassed, var(--sp-success));
4973
+ }
4974
+ .grain-connection-footer-error {
4975
+ color: var(--vscode-errorForeground, var(--sp-error));
4976
+ }
4925
4977
  .grain-connection-page :is(button, input, select, summary):focus-visible {
4926
4978
  outline: 2px solid var(--grain-accent);
4927
4979
  outline-offset: 2px;
@@ -0,0 +1,31 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Grain Results</title>
7
+ <style>
8
+ body { margin: 0; padding: 12px; color: var(--vscode-foreground, #222); font: 13px var(--vscode-font-family, sans-serif); }
9
+ button { font: inherit; }
10
+ .row { margin: 0 0 8px; }
11
+ #columns { overflow-wrap: anywhere; }
12
+ #error { color: var(--vscode-errorForeground, #b00); }
13
+ #grid { width: 100%; height: 480px; border: 0; }
14
+ label { display: inline-flex; gap: 6px; align-items: center; }
15
+ </style>
16
+ <script type="module" crossorigin>(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))s(t);new MutationObserver(t=>{for(const r of t)if(r.type==="childList")for(const u of r.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&s(u)}).observe(document,{childList:!0,subtree:!0});function n(t){const r={};return t.integrity&&(r.integrity=t.integrity),t.referrerPolicy&&(r.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?r.credentials="include":t.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function s(t){if(t.ep)return;t.ep=!0;const r=n(t);fetch(t.href,r)}})();const l=new Map;let O=0,c,m=!1,i,f="",d=!1;function p(o,e={}){const n=++O;return new Promise(s=>{l.set(n,s),window.parent.postMessage({jsonrpc:"2.0",id:n,method:o,params:e},"*"),window.setTimeout(()=>{l.get(n)&&(l.delete(n),s({jsonrpc:"2.0",id:n,error:{message:"The host did not respond"}}))},1e4)})}function a(o){const e=document.querySelector("#error");e&&(e.textContent=o)}function y(o){const e=document.querySelector("#open");e&&(e.textContent=o)}function h(o){c?.contentWindow?.postMessage(o,"*")}function v(){!i||!m||h({jsonrpc:"2.0",method:"ui/notifications/tool-result",params:{structuredContent:i}})}window.addEventListener("message",o=>{const e=o.data;if(!(!e||e.jsonrpc!=="2.0")){if(o.source===c?.contentWindow){if(e.id!==void 0){const n=`frame-${String(e.id)}`;l.set(n,s=>{c?.contentWindow?.postMessage({...s,id:e.id},"*")}),window.parent.postMessage({...e,id:n},"*")}else window.parent.postMessage(e,"*"),e.method==="ui/notifications/initialized"&&(m=!0,v());return}if(e.id!==void 0&&l.has(e.id)){l.get(e.id)?.(e),l.delete(e.id);return}typeof e.method=="string"&&e.method.startsWith("ui/notifications/")&&(e.method==="ui/notifications/tool-result"?C(e.params):h(e))}});function C(o){if(!o||!o.structuredContent||typeof o.structuredContent!="object")return;i=o.structuredContent,v();const n=i.route==="editor",s=document.querySelector("#toggle-wrap");s&&(s.hidden=!n),y(n?"Open in Grain":"Open in workspace"),f=typeof i.cardPreferenceKey=="string"?i.cardPreferenceKey:"";const t=document.querySelector("#title"),r=document.querySelector("#count"),u=document.querySelector("#columns"),g=document.querySelector("#status");t&&(t.textContent=String(i.title||i.tabId||"Query result")),r&&(r.textContent=`${Number(i.rowCount??0).toLocaleString()} rows`),u&&(u.textContent=`Columns: ${(i.columns||[]).map(S=>S.name||"").join(", ")||"none"}`),g&&(g.textContent=`Status: ${i.status||"unknown"}`);try{d=f?window.localStorage.getItem(f)==="on":!1}catch{d=!1}const w=document.querySelector("#toggle");w&&(w.checked=d),(!n||d)&&b()}async function b(){if(c||!i)return;a("");const o=await p("resources/read",{uri:"ui://sql-preview/results-grid-full"}),n=o.result?.contents?.find(s=>typeof s.text=="string")?.text;if(o.error||!n){const s=i.route==="editor";a(s?"The full results view is unavailable. Open in Grain to see the result.":"The full results view is unavailable. Open in workspace to see the result."),y(s?"Open in Grain":"Open in workspace");return}c=document.createElement("iframe"),m=!1,c.id="grid",c.title="Full query results",c.srcdoc=n,document.body.append(c),document.querySelector("#card")?.classList.add("expanded")}document.querySelector("#open")?.addEventListener("click",async()=>{if(!i?.sessionId||!i.tabId){a("This result cannot be opened yet.");return}const o=i.route==="editor"?"open_in_grain":"open_in_workspace",e=await p("tools/call",{name:"open_result_view",arguments:{sessionId:i.sessionId,tabId:i.tabId,button:o}}),n=e.result,t=(n?.content||[]).map(u=>u.text).filter(Boolean).join(`
17
+ `),r=n?.structuredContent?.url||t.match(/https?:\/\/[^\s)]+/)?.[0];if(r){if(!(await p("ui/open-link",{url:r})).error){a(t&&t!==r?t:"Opened the result workspace.");return}p("tools/call",{name:"record_ui_event",arguments:{event:"mcp_result_view_opened",button:o}}).catch(()=>{}),a(`${t||"Open this result in your browser:"}
18
+ ${r}`);return}t&&a(t),e.error&&a(`${o==="open_in_grain"?"Open in Grain":"Open in workspace"} is not available yet.`)});document.querySelector("#toggle")?.addEventListener("change",o=>{d=o.currentTarget.checked;try{f&&window.localStorage.setItem(f,d?"on":"off")}catch{d=o.currentTarget.checked}d?b():(c?.remove(),c=void 0,document.querySelector("#card")?.classList.remove("expanded"))});p("ui/initialize",{appInfo:{name:"Grain Results Card",version:"1.0.0"},appCapabilities:{},protocolVersion:"2025-11-25"}).then(()=>window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/initialized"},"*"));</script>
19
+ </head>
20
+ <body>
21
+ <main id="card">
22
+ <h2 id="title" class="row">Query result</h2>
23
+ <div id="count" class="row"></div>
24
+ <div id="columns" class="row"></div>
25
+ <div id="status" class="row"></div>
26
+ <div class="row"><button id="open">Open in Grain</button></div>
27
+ <label id="toggle-wrap"><input id="toggle" type="checkbox">Show in chat</label>
28
+ <div id="error" role="status" aria-live="polite"></div>
29
+ </main>
30
+ </body>
31
+ </html>
package/dist/mcp-app.html CHANGED
@@ -12521,6 +12521,72 @@ function BaseHostProvider({
12521
12521
  }) {
12522
12522
  return /* @__PURE__ */ jsxRuntimeExports.jsx(HostContext.Provider, { value, children });
12523
12523
  }
12524
+ function useWorkspaceResultTarget() {
12525
+ const [targets, setTargets] = reactExports.useState({});
12526
+ const [resetToken, setResetToken] = reactExports.useState(0);
12527
+ const remember = reactExports.useCallback((tabId, structured) => {
12528
+ setResetToken((current) => current + 1);
12529
+ const sessionId = structured?.["sessionId"];
12530
+ const resultTabId = structured?.["tabId"];
12531
+ if (structured?.["route"] === "chat" && typeof sessionId === "string" && typeof resultTabId === "string") {
12532
+ setTargets((current) => ({ ...current, [tabId]: { sessionId, tabId: resultTabId } }));
12533
+ }
12534
+ }, []);
12535
+ return { targetForTab: (tabId) => targets[tabId], remember, resetToken };
12536
+ }
12537
+ function WorkspaceResultAction({
12538
+ target,
12539
+ resetToken,
12540
+ callServerTool,
12541
+ sendMessage
12542
+ }) {
12543
+ const [linkError, setLinkError] = reactExports.useState("");
12544
+ reactExports.useEffect(() => setLinkError(""), [resetToken]);
12545
+ const openWorkspace = async () => {
12546
+ if (!target) {
12547
+ return;
12548
+ }
12549
+ setLinkError("");
12550
+ try {
12551
+ const response = await callServerTool("open_result_view", {
12552
+ ...target,
12553
+ button: "open_in_workspace"
12554
+ });
12555
+ const structured = response.structuredContent;
12556
+ if (typeof structured?.url === "string") {
12557
+ try {
12558
+ await sendMessage("openLink", { url: structured.url });
12559
+ } catch {
12560
+ void callServerTool("record_ui_event", {
12561
+ event: "mcp_result_view_opened",
12562
+ button: "open_in_workspace"
12563
+ }).catch(() => void 0);
12564
+ setLinkError(structured.url);
12565
+ }
12566
+ } else if (structured?.openedInEditor === true) {
12567
+ setLinkError("Opened the result in Grain.");
12568
+ } else {
12569
+ throw new Error("The workspace link is unavailable");
12570
+ }
12571
+ } catch {
12572
+ setLinkError("Could not open this result in the workspace.");
12573
+ }
12574
+ };
12575
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
12576
+ target && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: () => void openWorkspace(), children: "Open in workspace" }),
12577
+ linkError && /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-error-bar", role: "status", "aria-live": "polite", children: linkError })
12578
+ ] });
12579
+ }
12580
+ function copyResultToClipboard(result, copyText) {
12581
+ if (!result || result.rows.length === 0) {
12582
+ return;
12583
+ }
12584
+ const header = result.columns.map((column) => column.name).join(" ");
12585
+ const rows = result.rows.map(
12586
+ (row) => result.columns.map((_, index) => String(row[index] ?? "")).join(" ")
12587
+ );
12588
+ copyText([header, ...rows].join("\n"));
12589
+ }
12524
12590
  const createStoreImpl = (createState) => {
12525
12591
  let state;
12526
12592
  const listeners = /* @__PURE__ */ new Set();
@@ -73210,7 +73276,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
73210
73276
  nativeTheme = false,
73211
73277
  disableFilters = false,
73212
73278
  autoSizeStrategy,
73213
- fillWidth = false,
73214
73279
  onCellDoubleClick
73215
73280
  }, ref) {
73216
73281
  const trackUi = useTrackUi();
@@ -73379,21 +73444,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
73379
73444
  }),
73380
73445
  [data, getNodeValue, copyIncludesHeaders]
73381
73446
  );
73382
- const userResizedRef = reactExports.useRef(false);
73383
- const fillSpareWidth = reactExports.useCallback((e2) => {
73384
- if (userResizedRef.current) return;
73385
- const body = e2.api.getHorizontalPixelRange?.();
73386
- const columns = (e2.api.getAllDisplayedColumns?.() ?? []).filter((c) => !c.getPinned());
73387
- if (!body || columns.length === 0) return;
73388
- const used = columns.reduce((sum2, c) => sum2 + c.getActualWidth(), 0);
73389
- if (used < body.right - body.left) e2.api.sizeColumnsToFit();
73390
- }, []);
73391
- const noteUserResize = reactExports.useCallback((e2) => {
73392
- if (e2.source === "uiColumnResized" && e2.finished) userResizedRef.current = true;
73393
- }, []);
73394
- reactExports.useEffect(() => {
73395
- userResizedRef.current = false;
73396
- }, [data?.columns]);
73397
73447
  const columnDefs = reactExports.useMemo(() => {
73398
73448
  if (!data?.columns) return [];
73399
73449
  const isInRange = (rowIndex, displayedColIndex) => {
@@ -73578,11 +73628,6 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
73578
73628
  onGridReady: (p2) => {
73579
73629
  apiRef.current = p2.api;
73580
73630
  },
73581
- ...fillWidth ? {
73582
- onFirstDataRendered: fillSpareWidth,
73583
- onGridSizeChanged: fillSpareWidth,
73584
- onColumnResized: noteUserResize
73585
- } : {},
73586
73631
  rowData: data.rows,
73587
73632
  columnDefs,
73588
73633
  defaultColDef: {
@@ -147891,6 +147936,7 @@ function App() {
147891
147936
  updateTab
147892
147937
  } = useAppStore();
147893
147938
  const [isAppMode, setIsAppMode] = reactExports.useState(true);
147939
+ const { targetForTab, remember, resetToken } = useWorkspaceResultTarget();
147894
147940
  const hasReceivedToolCall = reactExports.useRef(false);
147895
147941
  const hasFallbackFired = reactExports.useRef(false);
147896
147942
  const gridRef = reactExports.useRef(null);
@@ -148005,6 +148051,7 @@ function App() {
148005
148051
  const structured = params?.structuredContent && typeof params.structuredContent === "object" ? params.structuredContent : void 0;
148006
148052
  const resultSql = entry?.sql ?? (typeof rawCallKey === "string" ? rawCallKey : typeof structured?.["query"] === "string" ? structured["query"] : "");
148007
148053
  const tabId = entry?.tabId ?? createTab(resultSql, false);
148054
+ remember(tabId, structured);
148008
148055
  setIsAppMode(true);
148009
148056
  if (params?.isError) {
148010
148057
  const text = params.content?.find((c) => c.type === "text")?.text;
@@ -148230,14 +148277,8 @@ function App() {
148230
148277
  copyTextSafe(csvString);
148231
148278
  }
148232
148279
  };
148233
- const handleCopy = () => {
148234
- if (!result || result.rows.length === 0) return;
148235
- const header = result.columns.map((c) => c.name).join(" ");
148236
- const tsvRows = result.rows.map(
148237
- (row) => result.columns.map((_, i2) => String(row[i2] ?? "")).join(" ")
148238
- );
148239
- copyTextSafe([header, ...tsvRows].join("\n"));
148240
- };
148280
+ const workspaceTarget = targetForTab(activeTab?.id ?? "");
148281
+ const handleCopy = () => copyResultToClipboard(result, copyTextSafe);
148241
148282
  if (!isReady || !activeTab)
148242
148283
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { display: "flex", justifyContent: "center", padding: "40px" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spinner" }) });
148243
148284
  const showTabs = tabs.length > 1 || !isAppMode;
@@ -148297,7 +148338,8 @@ function App() {
148297
148338
  result && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-row-count", children: [
148298
148339
  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: result.rowCount ?? result.rows.length }),
148299
148340
  " rows"
148300
- ] })
148341
+ ] }),
148342
+ result && /* @__PURE__ */ jsxRuntimeExports.jsx(WorkspaceResultAction, { target: workspaceTarget, resetToken, callServerTool, sendMessage })
148301
148343
  ] }),
148302
148344
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-result-header-right", children: result && result.rows.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
148303
148345
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: handleCopy, "aria-label": "Copy results", children: "Copy" }),
@@ -161960,11 +162002,15 @@ function MCPHostProvider({ children }) {
161960
162002
  };
161961
162003
  }
161962
162004
  });
161963
- const sendMessage = reactExports.useCallback((command, payload) => {
162005
+ const sendMessage = reactExports.useCallback(async (command, payload) => {
161964
162006
  if (!appRef.current) return;
161965
162007
  switch (command) {
161966
162008
  case "openLink":
161967
- if (appRef.current.openLink) appRef.current.openLink(payload);
162009
+ if (appRef.current.openLink) {
162010
+ await appRef.current.openLink(payload);
162011
+ } else {
162012
+ throw new Error("The host cannot open links");
162013
+ }
161968
162014
  break;
161969
162015
  default:
161970
162016
  console.warn("[MCPHost] Unknown command sent:", command);