grain-tools 0.10.15 → 0.10.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connection-setup.html +17991 -0
- package/dist/credential-page.html +5017 -0
- package/dist/mcp-app.html +46 -13
- package/dist/web-app.html +707 -258
- package/out/server/standalone.js +164578 -162783
- package/package.json +4 -2
- package/server.json +2 -2
package/dist/web-app.html
CHANGED
|
@@ -12820,7 +12820,7 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12820
12820
|
chartsEnabled: false,
|
|
12821
12821
|
mcpEnabled: false,
|
|
12822
12822
|
mcpEntitled: false,
|
|
12823
|
-
|
|
12823
|
+
grainServiceSetup: "registered",
|
|
12824
12824
|
mcpSafeMode: true,
|
|
12825
12825
|
activeConnectorType: null,
|
|
12826
12826
|
activeConnectionId: null,
|
|
@@ -12910,7 +12910,7 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12910
12910
|
"filterResultsByActiveFile",
|
|
12911
12911
|
"mcpEnabled",
|
|
12912
12912
|
"mcpEntitled",
|
|
12913
|
-
"
|
|
12913
|
+
"grainServiceSetup",
|
|
12914
12914
|
"mcpSafeMode",
|
|
12915
12915
|
"activeConnectorType",
|
|
12916
12916
|
"activeConnectionId",
|
|
@@ -13073,6 +13073,7 @@ const ALL_TOOLS = [
|
|
|
13073
13073
|
"list_connections",
|
|
13074
13074
|
"get_demo_dataset",
|
|
13075
13075
|
"save_connection",
|
|
13076
|
+
"create_connection_draft",
|
|
13076
13077
|
"request_connection_credentials",
|
|
13077
13078
|
"test_connection",
|
|
13078
13079
|
"delete_connection",
|
|
@@ -13170,6 +13171,7 @@ const TELEMETRY_CONNECTORS = [
|
|
|
13170
13171
|
];
|
|
13171
13172
|
const TELEMETRY_TOOL_NAMES = [...ALL_TOOLS, "unknown"];
|
|
13172
13173
|
const TELEMETRY_COMMAND_IDS = [
|
|
13174
|
+
"grain.setUpService",
|
|
13173
13175
|
"grain.showDaemonInfo",
|
|
13174
13176
|
"grain.mcp.restart",
|
|
13175
13177
|
"grain.mcp.testConnection",
|
|
@@ -13510,6 +13512,8 @@ const TELEMETRY_ERROR_IDS = [
|
|
|
13510
13512
|
* Not a database error: nothing was ever sent to a connector.
|
|
13511
13513
|
*/
|
|
13512
13514
|
"credential_required",
|
|
13515
|
+
"setup_required",
|
|
13516
|
+
"connection_draft_rejected",
|
|
13513
13517
|
/**
|
|
13514
13518
|
* The session holding this query's tab was evicted (SessionManager's maxSessions
|
|
13515
13519
|
* cap) while the query was still running, so the result had nowhere to land.
|
|
@@ -13774,7 +13778,18 @@ async function buildGuideHubState() {
|
|
|
13774
13778
|
return { ...DEFAULT_GUIDE_HUB_STATE, telemetryEnabled };
|
|
13775
13779
|
}
|
|
13776
13780
|
}
|
|
13777
|
-
const
|
|
13781
|
+
const WEB_SESSION_KEY = "grain:web-session-id";
|
|
13782
|
+
function resolveWebSessionId() {
|
|
13783
|
+
const stored = readStoredValue(WEB_SESSION_KEY);
|
|
13784
|
+
if (stored && /^web-[0-9a-f-]{36}$/.test(stored)) {
|
|
13785
|
+
return stored;
|
|
13786
|
+
}
|
|
13787
|
+
return `web-${crypto.randomUUID()}`;
|
|
13788
|
+
}
|
|
13789
|
+
const WEB_SESSION_ID = resolveWebSessionId();
|
|
13790
|
+
function rememberWebSessionId() {
|
|
13791
|
+
writeStoredValue(WEB_SESSION_KEY, WEB_SESSION_ID);
|
|
13792
|
+
}
|
|
13778
13793
|
function resolveProjectedTarget(tabId, payload) {
|
|
13779
13794
|
const parsed = tabId ? parseProjectedTabId(tabId) : void 0;
|
|
13780
13795
|
const tab = tabId ? useAppStore.getState().tabs.find((t) => t.id === tabId) : void 0;
|
|
@@ -14030,6 +14045,8 @@ function useWebTabSync(options) {
|
|
|
14030
14045
|
remoteId: tab.id,
|
|
14031
14046
|
sessionDisplayName: session.displayName,
|
|
14032
14047
|
clientType: session.clientType,
|
|
14048
|
+
connectionId: tab.connectionId,
|
|
14049
|
+
connectionName: tab.connectionName,
|
|
14033
14050
|
isRemote: true,
|
|
14034
14051
|
preserveFocus
|
|
14035
14052
|
});
|
|
@@ -14047,6 +14064,8 @@ function useWebTabSync(options) {
|
|
|
14047
14064
|
remoteId: tab.id,
|
|
14048
14065
|
sessionDisplayName: session.displayName,
|
|
14049
14066
|
clientType: session.clientType,
|
|
14067
|
+
connectionId: tab.connectionId,
|
|
14068
|
+
connectionName: tab.connectionName,
|
|
14050
14069
|
isRemote: true,
|
|
14051
14070
|
preserveFocus
|
|
14052
14071
|
});
|
|
@@ -14067,6 +14086,8 @@ function useWebTabSync(options) {
|
|
|
14067
14086
|
remoteId: tab.id,
|
|
14068
14087
|
sessionDisplayName: session.displayName,
|
|
14069
14088
|
clientType: session.clientType,
|
|
14089
|
+
connectionId: detail.connectionId ?? tab.connectionId,
|
|
14090
|
+
connectionName: detail.connectionName ?? tab.connectionName,
|
|
14070
14091
|
isRemote: true
|
|
14071
14092
|
};
|
|
14072
14093
|
if (tab.status === "success") {
|
|
@@ -14143,7 +14164,7 @@ function useWebTabSync(options) {
|
|
|
14143
14164
|
dispatchLoading(session, tab, true);
|
|
14144
14165
|
}
|
|
14145
14166
|
} else if (tab.status === "success" || tab.status === "error" || !cached || cached.status !== tab.status) {
|
|
14146
|
-
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);
|
|
14147
14168
|
const errorIsNeeded = tab.status === "error" && (!cached || !storeHasTab || cached.status !== "error");
|
|
14148
14169
|
if (detailIsNeeded || errorIsNeeded) {
|
|
14149
14170
|
await dispatchTabDetail(session, tab);
|
|
@@ -14154,7 +14175,8 @@ function useWebTabSync(options) {
|
|
|
14154
14175
|
remoteTabId: tab.id,
|
|
14155
14176
|
status: tab.status,
|
|
14156
14177
|
rowCount: tab.rowCount,
|
|
14157
|
-
title: tab.title
|
|
14178
|
+
title: tab.title,
|
|
14179
|
+
connectionId: tab.connectionId
|
|
14158
14180
|
});
|
|
14159
14181
|
}
|
|
14160
14182
|
})
|
|
@@ -14166,6 +14188,7 @@ function useWebTabSync(options) {
|
|
|
14166
14188
|
}
|
|
14167
14189
|
}
|
|
14168
14190
|
unreachableStreakRef.current = 0;
|
|
14191
|
+
rememberWebSessionId();
|
|
14169
14192
|
setDaemonStatus("connected");
|
|
14170
14193
|
setIsReady(true);
|
|
14171
14194
|
} catch (err) {
|
|
@@ -14214,7 +14237,8 @@ function useWebToolProxy() {
|
|
|
14214
14237
|
query: args.sql,
|
|
14215
14238
|
sessionId,
|
|
14216
14239
|
connectionId: args.connectionId,
|
|
14217
|
-
tabId: args.tabId
|
|
14240
|
+
tabId: args.tabId,
|
|
14241
|
+
title: args.title
|
|
14218
14242
|
});
|
|
14219
14243
|
if (!ok) {
|
|
14220
14244
|
throw new Error(data.error || "Query failed");
|
|
@@ -14330,29 +14354,29 @@ function ReauthorizeNotice({
|
|
|
14330
14354
|
const [copied, setCopied] = reactExports.useState(false);
|
|
14331
14355
|
const copyCommand = async () => {
|
|
14332
14356
|
try {
|
|
14333
|
-
await navigator.clipboard.writeText("grain
|
|
14357
|
+
await navigator.clipboard.writeText("grain ui");
|
|
14334
14358
|
setCopied(true);
|
|
14335
14359
|
} catch {
|
|
14336
14360
|
setCopied(false);
|
|
14337
14361
|
}
|
|
14338
14362
|
};
|
|
14339
14363
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth", role: "alert", children: [
|
|
14340
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: "Grain is running. Reconnect this browser tab." }),
|
|
14364
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: reason === "unreachable" ? "This tab lost its connection to Grain." : "Grain is running. Reconnect this browser tab." }),
|
|
14341
14365
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Run this command in your terminal to open your workspace again:" }),
|
|
14342
14366
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth-action", children: [
|
|
14343
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-web-reauth-command", children: "grain
|
|
14367
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-web-reauth-command", children: "grain ui" }),
|
|
14344
14368
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14345
14369
|
"button",
|
|
14346
14370
|
{
|
|
14347
14371
|
type: "button",
|
|
14348
14372
|
className: "sp-web-secondary-button",
|
|
14349
14373
|
onClick: () => void copyCommand(),
|
|
14350
|
-
"aria-label": "Copy grain
|
|
14374
|
+
"aria-label": "Copy grain ui",
|
|
14351
14375
|
children: copied ? "Copied" : "Copy"
|
|
14352
14376
|
}
|
|
14353
14377
|
)
|
|
14354
14378
|
] }),
|
|
14355
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-detail", children: reason === "expired-link" ? "This link has expired or was already used." : reason === "unreachable" ? "Grain may have restarted
|
|
14379
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-detail", children: reason === "expired-link" ? "This link has expired or was already used." : reason === "unreachable" ? "Grain may have stopped, or restarted on a different port. If it stopped, start it again first." : "This tab needs a fresh workspace link." })
|
|
14356
14380
|
] });
|
|
14357
14381
|
}
|
|
14358
14382
|
function isUpdateMarkerStatus(value) {
|
|
@@ -14472,7 +14496,10 @@ function fieldVisible(field, values) {
|
|
|
14472
14496
|
function ConnectionSetupPage({
|
|
14473
14497
|
onDone,
|
|
14474
14498
|
onCancel,
|
|
14475
|
-
initialConnection
|
|
14499
|
+
initialConnection,
|
|
14500
|
+
actions: actions2,
|
|
14501
|
+
mode = "full",
|
|
14502
|
+
canEditDetails = false
|
|
14476
14503
|
}) {
|
|
14477
14504
|
const { callServerTool, isReady } = useHostContext();
|
|
14478
14505
|
const [connectors, setConnectors] = reactExports.useState([]);
|
|
@@ -14489,20 +14516,20 @@ function ConnectionSetupPage({
|
|
|
14489
14516
|
initialConnection?.["id"] ?? `conn_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
14490
14517
|
)
|
|
14491
14518
|
);
|
|
14519
|
+
const [displayMode, setDisplayMode] = reactExports.useState(mode);
|
|
14492
14520
|
reactExports.useEffect(() => {
|
|
14493
|
-
if (!isReady) {
|
|
14521
|
+
if (!actions2 && !isReady) {
|
|
14494
14522
|
return;
|
|
14495
14523
|
}
|
|
14496
14524
|
let active = true;
|
|
14497
|
-
void callServerTool("list_connectors", {}).then((result) => {
|
|
14525
|
+
void (actions2 ? actions2.listConnectors() : callServerTool("list_connectors", {}).then((result) => {
|
|
14526
|
+
if (result.isError) throw new Error(toolMessage(result));
|
|
14527
|
+
return JSON.parse(toolMessage(result));
|
|
14528
|
+
})).then((result) => {
|
|
14498
14529
|
if (!active) {
|
|
14499
14530
|
return;
|
|
14500
14531
|
}
|
|
14501
|
-
|
|
14502
|
-
throw new Error(toolMessage(result));
|
|
14503
|
-
}
|
|
14504
|
-
const text = toolMessage(result);
|
|
14505
|
-
const listed = JSON.parse(text);
|
|
14532
|
+
const listed = result;
|
|
14506
14533
|
if (!Array.isArray(listed)) {
|
|
14507
14534
|
throw new Error("Connector list is unavailable.");
|
|
14508
14535
|
}
|
|
@@ -14524,7 +14551,7 @@ function ConnectionSetupPage({
|
|
|
14524
14551
|
return () => {
|
|
14525
14552
|
active = false;
|
|
14526
14553
|
};
|
|
14527
|
-
}, [callServerTool, isReady, initialConnection]);
|
|
14554
|
+
}, [callServerTool, isReady, initialConnection, actions2]);
|
|
14528
14555
|
const selected = connectors.find((connector) => connector.id === type);
|
|
14529
14556
|
const properties = selected?.schema?.properties ?? {};
|
|
14530
14557
|
const entries = Object.entries(properties).filter(([key, field]) => {
|
|
@@ -14549,6 +14576,11 @@ function ConnectionSetupPage({
|
|
|
14549
14576
|
...Object.fromEntries(entries.map(([key, field]) => [key, values[key] ?? field.default]))
|
|
14550
14577
|
});
|
|
14551
14578
|
const test = async () => {
|
|
14579
|
+
if (actions2) {
|
|
14580
|
+
await actions2.test(profile(), password || void 0);
|
|
14581
|
+
setTested(true);
|
|
14582
|
+
return true;
|
|
14583
|
+
}
|
|
14552
14584
|
const result = await callServerTool(
|
|
14553
14585
|
"test_connection",
|
|
14554
14586
|
initialConnection && !password ? { connectionId: draftId } : { type, connectionProfile: { ...profile(), ...password ? { password } : {} } }
|
|
@@ -14573,6 +14605,12 @@ function ConnectionSetupPage({
|
|
|
14573
14605
|
return;
|
|
14574
14606
|
}
|
|
14575
14607
|
const id = draftId;
|
|
14608
|
+
if (actions2) {
|
|
14609
|
+
await actions2.save(profile(), password || void 0);
|
|
14610
|
+
setPassword("");
|
|
14611
|
+
onDone(id);
|
|
14612
|
+
return;
|
|
14613
|
+
}
|
|
14576
14614
|
const saved = await callServerTool("save_connection", {
|
|
14577
14615
|
connectionProfile: { ...profile(), id }
|
|
14578
14616
|
});
|
|
@@ -14649,15 +14687,18 @@ function ConnectionSetupPage({
|
|
|
14649
14687
|
};
|
|
14650
14688
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "grain-connection-page", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-content", children: [
|
|
14651
14689
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-intro", children: [
|
|
14652
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: initialConnection ? "Edit connection" : "Connect a database" }),
|
|
14653
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Add a connection to start querying your data." })
|
|
14690
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: actions2 ? "Finish connection setup" : initialConnection ? "Edit connection" : "Connect a database" }),
|
|
14691
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: actions2 ? "Test and save this connection to continue." : "Add a connection to start querying your data." })
|
|
14654
14692
|
] }),
|
|
14655
14693
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
14656
14694
|
error && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-error", role: "alert", children: [
|
|
14657
14695
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Connection failed" }),
|
|
14658
14696
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: error })
|
|
14659
14697
|
] }),
|
|
14660
|
-
tested && !error && /* @__PURE__ */ jsxRuntimeExports.
|
|
14698
|
+
tested && !error && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", role: "status", children: [
|
|
14699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
14700
|
+
"Connection test successful."
|
|
14701
|
+
] }),
|
|
14661
14702
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-grid", children: [
|
|
14662
14703
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-field", children: [
|
|
14663
14704
|
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-type", children: "Database type" }),
|
|
@@ -14668,7 +14709,7 @@ function ConnectionSetupPage({
|
|
|
14668
14709
|
value: type,
|
|
14669
14710
|
onChange: (event) => selectType(event.target.value),
|
|
14670
14711
|
required: true,
|
|
14671
|
-
disabled: !isReady || busy !== null,
|
|
14712
|
+
disabled: (actions2 ? true : !isReady) || busy !== null,
|
|
14672
14713
|
children: [
|
|
14673
14714
|
!type && /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Choose a database" }),
|
|
14674
14715
|
connectors.map((connector) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connector.id, children: connector.displayName }, connector.id))
|
|
@@ -14685,20 +14726,36 @@ function ConnectionSetupPage({
|
|
|
14685
14726
|
value: name,
|
|
14686
14727
|
onChange: (event) => setName(event.target.value),
|
|
14687
14728
|
placeholder: "e.g. Analytics",
|
|
14688
|
-
required: true
|
|
14729
|
+
required: true,
|
|
14730
|
+
readOnly: Boolean(actions2)
|
|
14689
14731
|
}
|
|
14690
14732
|
)
|
|
14691
14733
|
] })
|
|
14692
14734
|
] }),
|
|
14735
|
+
displayMode === "password" && canEditDetails && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14736
|
+
"button",
|
|
14737
|
+
{
|
|
14738
|
+
type: "button",
|
|
14739
|
+
className: "grain-connection-secondary grain-connection-edit",
|
|
14740
|
+
onClick: () => setDisplayMode("full"),
|
|
14741
|
+
children: "Edit details"
|
|
14742
|
+
}
|
|
14743
|
+
),
|
|
14693
14744
|
selected && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
14694
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14745
|
+
displayMode === "full" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14695
14746
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Connection details" }),
|
|
14696
14747
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grain-connection-grid", children: entries.filter(([, field]) => !field.ui?.advanced).map(renderField) })
|
|
14748
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14749
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Connection details" }),
|
|
14750
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dl", { className: "grain-connection-readonly", children: entries.map(([key, field]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
14751
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dt", { children: field.title ?? key }),
|
|
14752
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dd", { children: String(values[key] ?? field.default ?? "") })
|
|
14753
|
+
] }, key)) })
|
|
14697
14754
|
] }),
|
|
14698
|
-
passwordField && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14755
|
+
(passwordField || actions2 && displayMode === "password") && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14699
14756
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Authentication" }),
|
|
14700
14757
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grain-connection-grid", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-field", children: [
|
|
14701
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-password", children: passwordField
|
|
14758
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-password", children: passwordField?.title ?? "Password" }),
|
|
14702
14759
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-password", children: [
|
|
14703
14760
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14704
14761
|
"input",
|
|
@@ -14723,13 +14780,16 @@ function ConnectionSetupPage({
|
|
|
14723
14780
|
/* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: "Stored on this computer after connecting." })
|
|
14724
14781
|
] }) })
|
|
14725
14782
|
] }),
|
|
14726
|
-
entries.some(([, field]) => field.ui?.advanced) && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "grain-connection-advanced", children: [
|
|
14783
|
+
displayMode === "full" && entries.some(([, field]) => field.ui?.advanced) && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "grain-connection-advanced", children: [
|
|
14727
14784
|
/* @__PURE__ */ jsxRuntimeExports.jsx("summary", { children: "Advanced settings" }),
|
|
14728
14785
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grain-connection-grid", children: entries.filter(([, field]) => field.ui?.advanced).map(renderField) })
|
|
14729
14786
|
] })
|
|
14730
14787
|
] }),
|
|
14731
14788
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-footer", children: [
|
|
14732
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
14789
|
+
tested && !error ? /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "grain-connection-success", children: [
|
|
14790
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "✓ " }),
|
|
14791
|
+
"Connection test successful."
|
|
14792
|
+
] }) : error ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "grain-connection-footer-error", children: error }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Grain will test the connection before saving it." }),
|
|
14733
14793
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-actions", children: [
|
|
14734
14794
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14735
14795
|
"button",
|
|
@@ -75059,6 +75119,10 @@ const DENSITY_HEIGHTS = {
|
|
|
75059
75119
|
normal: { row: 35, header: 42 },
|
|
75060
75120
|
comfortable: { row: 45, header: 52 }
|
|
75061
75121
|
};
|
|
75122
|
+
const NUMERIC_TYPE = /^(unsigned\s+|signed\s+)?(u?(tiny|small|medium|big|huge)?int(eger)?\d*|decimal|numeric|number|double|float\d*|real|long|short|byte|money)(\s+(precision|unsigned|signed))?\s*(\(\s*\d+\s*(,\s*\d+\s*)?\))?$/i;
|
|
75123
|
+
function isNumericColumnType(type) {
|
|
75124
|
+
return Boolean(type && NUMERIC_TYPE.test(type.trim()));
|
|
75125
|
+
}
|
|
75062
75126
|
const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
75063
75127
|
theme: theme2,
|
|
75064
75128
|
data,
|
|
@@ -75293,6 +75357,7 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75293
75357
|
return p.data[col.name];
|
|
75294
75358
|
return void 0;
|
|
75295
75359
|
},
|
|
75360
|
+
...isNumericColumnType(col.type) ? { cellClass: "sp-num-cell", headerClass: "ag-right-aligned-header" } : {},
|
|
75296
75361
|
cellClassRules: {
|
|
75297
75362
|
"sp-range-cell": (p) => isInRange(p.rowIndex ?? 0, index + 1)
|
|
75298
75363
|
},
|
|
@@ -149247,6 +149312,7 @@ function getFormInitialData(connection) {
|
|
|
149247
149312
|
delete formData["type"];
|
|
149248
149313
|
delete formData["builtIn"];
|
|
149249
149314
|
delete formData["hasPassword"];
|
|
149315
|
+
delete formData["draft"];
|
|
149250
149316
|
return formData;
|
|
149251
149317
|
}
|
|
149252
149318
|
function schemaHasPasswordField(schema) {
|
|
@@ -149285,9 +149351,10 @@ function schemaForConnectionMode(schema, connectorId, mode) {
|
|
|
149285
149351
|
}
|
|
149286
149352
|
};
|
|
149287
149353
|
}
|
|
149354
|
+
const UNREACHABLE_MESSAGE = "Can't reach Grain. Start Grain and try again.";
|
|
149288
149355
|
const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
149289
149356
|
const { callServerTool, isReady, mode, sendMessage, onMessage } = useHostContext();
|
|
149290
|
-
const
|
|
149357
|
+
const grainServiceSetup = useAppStore((state) => state.grainServiceSetup);
|
|
149291
149358
|
const supportsActiveConnection = mode === "vscode";
|
|
149292
149359
|
const trackUi = useTrackUi();
|
|
149293
149360
|
reactExports.useEffect(() => {
|
|
@@ -149519,7 +149586,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
149519
149586
|
const profileToSave = {
|
|
149520
149587
|
...formData,
|
|
149521
149588
|
type: typeToSave,
|
|
149522
|
-
id: connection?.id ?? `conn_${Date.now()}
|
|
149589
|
+
id: connection?.id ?? `conn_${Date.now()}`,
|
|
149590
|
+
...connection?.draft ? { draft: false } : {}
|
|
149523
149591
|
};
|
|
149524
149592
|
if (isEditing2 && profileToSave["password"] === "") {
|
|
149525
149593
|
delete profileToSave["password"];
|
|
@@ -149795,10 +149863,30 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
149795
149863
|
}
|
|
149796
149864
|
return null;
|
|
149797
149865
|
};
|
|
149866
|
+
const renderUnreachableActions = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginTop: 12, display: "flex", gap: 8 }, children: [
|
|
149867
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }),
|
|
149868
|
+
mode === "vscode" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149869
|
+
"button",
|
|
149870
|
+
{
|
|
149871
|
+
className: "sp-btn",
|
|
149872
|
+
onClick: () => sendMessage?.(grainServiceSetup === "not-set-up" ? "setUpGrain" : "startGrain"),
|
|
149873
|
+
children: grainServiceSetup === "not-set-up" ? "Set up Grain" : "Start Grain"
|
|
149874
|
+
}
|
|
149875
|
+
)
|
|
149876
|
+
] });
|
|
149877
|
+
const renderUnreachableState = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", children: [
|
|
149878
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: UNREACHABLE_MESSAGE }),
|
|
149879
|
+
renderUnreachableActions()
|
|
149880
|
+
] });
|
|
149798
149881
|
const renderConnectionForm = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-detail", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-detail-body", children: [
|
|
149799
149882
|
renderToast(),
|
|
149800
|
-
!selectedType &&
|
|
149801
|
-
!selectedType &&
|
|
149883
|
+
!selectedType && connectors.length === 0 && connectionsUnreachable && renderUnreachableState(),
|
|
149884
|
+
!selectedType && connectors.length === 0 && !connectionsUnreachable && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", children: [
|
|
149885
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "No database types are available." }),
|
|
149886
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }) })
|
|
149887
|
+
] }),
|
|
149888
|
+
!selectedType && connectors.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-form-section", children: "Database Type" }),
|
|
149889
|
+
!selectedType && connectors.length > 0 && ["local", "server"].map((group) => {
|
|
149802
149890
|
const groupConnectors = connectors.filter((c) => getConnectorGroup(c.id) === group);
|
|
149803
149891
|
if (groupConnectors.length === 0) {
|
|
149804
149892
|
return null;
|
|
@@ -149975,11 +150063,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
149975
150063
|
gap: "12px"
|
|
149976
150064
|
},
|
|
149977
150065
|
children: connections.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", style: { gridColumn: "1 / -1" }, children: [
|
|
149978
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: connectionsUnreachable ?
|
|
149979
|
-
connectionsUnreachable &&
|
|
149980
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }),
|
|
149981
|
-
mode === "vscode" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: () => sendMessage?.("startGrain"), children: grainServiceInstalled ? "Start Grain" : "Set up Grain" })
|
|
149982
|
-
] }),
|
|
150066
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: connectionsUnreachable ? UNREACHABLE_MESSAGE : "No connections configured." }),
|
|
150067
|
+
connectionsUnreachable && renderUnreachableActions(),
|
|
149983
150068
|
mode === "vscode" && !connectionsUnreachable && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149984
150069
|
"button",
|
|
149985
150070
|
{
|
|
@@ -150056,7 +150141,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
150056
150141
|
},
|
|
150057
150142
|
children: [
|
|
150058
150143
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `sp-dot sp-dot-${status}` }),
|
|
150059
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--sp-muted-fg)" }, children: statusLabel }),
|
|
150144
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--sp-muted-fg)" }, children: c.draft ? "Needs setup" : statusLabel }),
|
|
150145
|
+
c.draft && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-pill", children: "Draft" }),
|
|
150060
150146
|
isActive && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-pill", style: { marginLeft: "auto" }, children: "Active" })
|
|
150061
150147
|
]
|
|
150062
150148
|
}
|
|
@@ -150080,7 +150166,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
150080
150166
|
meta: selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150081
150167
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-badge", children: selectedConnection.type }),
|
|
150082
150168
|
supportsActiveConnection && activeConnectionId === selectedConnection.id && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-active-badge", children: "Active" }),
|
|
150083
|
-
selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Built-in" })
|
|
150169
|
+
selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Built-in" }),
|
|
150170
|
+
selectedConnection.draft && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Draft" })
|
|
150084
150171
|
] }),
|
|
150085
150172
|
actions: isFormOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", onClick: closeForm, "aria-label": "Cancel", children: "Cancel" }) : selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150086
150173
|
supportsActiveConnection && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -150251,6 +150338,10 @@ const TOOL_ENTRIES = {
|
|
|
150251
150338
|
list_connections: ["connections", "Show saved connection profiles."],
|
|
150252
150339
|
get_demo_dataset: ["connections", "Offer the built-in bookstore demo data and sample queries."],
|
|
150253
150340
|
save_connection: ["connections", "Create or update a connection profile."],
|
|
150341
|
+
create_connection_draft: [
|
|
150342
|
+
"connections",
|
|
150343
|
+
"Create a draft connection and give the user a setup link."
|
|
150344
|
+
],
|
|
150254
150345
|
request_connection_credentials: ["connections", "Ask the user to enter a connection password."],
|
|
150255
150346
|
test_connection: ["connections", "Verify a saved or draft profile."],
|
|
150256
150347
|
delete_connection: ["connections", "Remove a saved profile."],
|
|
@@ -150758,13 +150849,13 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
150758
150849
|
title: "This daemon can run standalone or inside VS Code; check the releases page for the latest version.",
|
|
150759
150850
|
children: "View Releases"
|
|
150760
150851
|
}
|
|
150761
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150852
|
+
) : updateAvailable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150762
150853
|
"button",
|
|
150763
150854
|
{
|
|
150764
150855
|
type: "button",
|
|
150765
150856
|
className: "sp-btn",
|
|
150766
150857
|
onClick: () => sendMessage("openExtensionPage", {}),
|
|
150767
|
-
children:
|
|
150858
|
+
children: "Open Update"
|
|
150768
150859
|
}
|
|
150769
150860
|
)
|
|
150770
150861
|
] }),
|
|
@@ -151423,7 +151514,7 @@ const LandingScreen = ({
|
|
|
151423
151514
|
activeConnectionName: storeConnName,
|
|
151424
151515
|
activeConnectorType: storeConnType,
|
|
151425
151516
|
openSettingsPanel,
|
|
151426
|
-
|
|
151517
|
+
grainServiceSetup
|
|
151427
151518
|
} = useAppStore();
|
|
151428
151519
|
const [fetchedConnName, setFetchedConnName] = reactExports.useState(null);
|
|
151429
151520
|
const [fetchedConnType, setFetchedConnType] = reactExports.useState(null);
|
|
@@ -151498,9 +151589,13 @@ const LandingScreen = ({
|
|
|
151498
151589
|
] }),
|
|
151499
151590
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-landing-subtitle", children: "Execute SQL queries directly in your IDE." })
|
|
151500
151591
|
] }),
|
|
151501
|
-
|
|
151502
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children:
|
|
151503
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("
|
|
151592
|
+
grainServiceSetup === "not-set-up" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-active-connection", children: [
|
|
151593
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Grain's background service isn't set up. Set it up once so your agents and the grain CLI can reach Grain when VS Code is closed." }),
|
|
151594
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("setUpGrain"), children: "Set up Grain" })
|
|
151595
|
+
] }),
|
|
151596
|
+
grainServiceSetup !== "not-set-up" && !hasActiveConnection && grainUnavailable && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-active-connection", children: [
|
|
151597
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: grainServiceSetup === "registered" ? "Grain is stopped. Start Grain to see your connections." : "Grain starts when needed on this machine." }),
|
|
151598
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("startGrain"), children: "Start Grain" })
|
|
151504
151599
|
] }),
|
|
151505
151600
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151506
151601
|
"div",
|
|
@@ -151630,7 +151725,7 @@ function SafeModeIndicator({
|
|
|
151630
151725
|
capability
|
|
151631
151726
|
] });
|
|
151632
151727
|
}
|
|
151633
|
-
function MultiTabLayout({ emptyState } = {}) {
|
|
151728
|
+
function MultiTabLayout({ emptyState, fillGridWidth = false } = {}) {
|
|
151634
151729
|
const {
|
|
151635
151730
|
tabs,
|
|
151636
151731
|
activeTabId,
|
|
@@ -152319,6 +152414,7 @@ ${activeTab.errorDetails}` : activeTab.error;
|
|
|
152319
152414
|
data: activeTab.result,
|
|
152320
152415
|
copyIncludesHeaders,
|
|
152321
152416
|
density: rowDensity,
|
|
152417
|
+
fillWidth: fillGridWidth,
|
|
152322
152418
|
onCellDoubleClick: handleCellDoubleClick
|
|
152323
152419
|
}
|
|
152324
152420
|
)
|
|
@@ -152332,6 +152428,7 @@ ${activeTab.errorDetails}` : activeTab.error;
|
|
|
152332
152428
|
data: activeTab.result,
|
|
152333
152429
|
copyIncludesHeaders,
|
|
152334
152430
|
density: rowDensity,
|
|
152431
|
+
fillWidth: fillGridWidth,
|
|
152335
152432
|
onCellDoubleClick: handleCellDoubleClick
|
|
152336
152433
|
}
|
|
152337
152434
|
),
|
|
@@ -152393,12 +152490,254 @@ ${activeTab.errorDetails}` : activeTab.error ?? "",
|
|
|
152393
152490
|
)
|
|
152394
152491
|
] });
|
|
152395
152492
|
}
|
|
152493
|
+
function SidebarAddButton({ label, title, onClick }) {
|
|
152494
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152495
|
+
"button",
|
|
152496
|
+
{
|
|
152497
|
+
type: "button",
|
|
152498
|
+
className: "sp-web-section-add",
|
|
152499
|
+
onClick,
|
|
152500
|
+
title,
|
|
152501
|
+
"aria-label": label,
|
|
152502
|
+
children: "+"
|
|
152503
|
+
}
|
|
152504
|
+
);
|
|
152505
|
+
}
|
|
152506
|
+
function SqlEditor({ value, onChange, onRun, readOnly = false }) {
|
|
152507
|
+
const frameRef = reactExports.useRef(null);
|
|
152508
|
+
const gutterRef = reactExports.useRef(null);
|
|
152509
|
+
const lineCount = value.split("\n").length;
|
|
152510
|
+
const digits = Math.max(2, String(lineCount).length);
|
|
152511
|
+
reactExports.useLayoutEffect(() => {
|
|
152512
|
+
frameRef.current?.style.setProperty("--sp-web-gutter-digits", String(digits));
|
|
152513
|
+
}, [digits]);
|
|
152514
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: frameRef, className: "sp-web-sql-editor-frame", children: [
|
|
152515
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152516
|
+
"div",
|
|
152517
|
+
{
|
|
152518
|
+
ref: gutterRef,
|
|
152519
|
+
className: "sp-web-sql-gutter",
|
|
152520
|
+
"aria-hidden": "true",
|
|
152521
|
+
"data-testid": "sql-gutter",
|
|
152522
|
+
children: Array.from({ length: lineCount }, (_, index) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: index + 1 }, index))
|
|
152523
|
+
}
|
|
152524
|
+
),
|
|
152525
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152526
|
+
"textarea",
|
|
152527
|
+
{
|
|
152528
|
+
className: "sp-web-sql-editor",
|
|
152529
|
+
"aria-label": "SQL editor",
|
|
152530
|
+
spellCheck: false,
|
|
152531
|
+
wrap: "off",
|
|
152532
|
+
value,
|
|
152533
|
+
readOnly,
|
|
152534
|
+
onChange: (event) => onChange(event.target.value),
|
|
152535
|
+
onScroll: (event) => {
|
|
152536
|
+
if (gutterRef.current) gutterRef.current.scrollTop = event.currentTarget.scrollTop;
|
|
152537
|
+
},
|
|
152538
|
+
onKeyDown: (event) => {
|
|
152539
|
+
if (!readOnly && (event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
152540
|
+
event.preventDefault();
|
|
152541
|
+
onRun();
|
|
152542
|
+
}
|
|
152543
|
+
}
|
|
152544
|
+
}
|
|
152545
|
+
)
|
|
152546
|
+
] });
|
|
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
|
+
}
|
|
152396
152734
|
const THEME_KEY = "grain:web-theme";
|
|
152397
152735
|
const SIDEBAR_DEFAULT_WIDTH = 220;
|
|
152398
152736
|
const SIDEBAR_MIN_WIDTH = 160;
|
|
152399
152737
|
const SIDEBAR_MAX_WIDTH = 400;
|
|
152400
152738
|
const SIDEBAR_AUTO_COLLAPSE_QUERY = "(max-width: 640px)";
|
|
152401
152739
|
const SIDEBAR_WIDTH_STORAGE_KEY = "sql-preview:web-sidebar-width";
|
|
152740
|
+
const CONNECTIONS_COLLAPSED_KEY = "grain:web-connections-collapsed";
|
|
152402
152741
|
function WebApp({ viewHint }) {
|
|
152403
152742
|
const { onMessage, isReady, sendMessage, callServerTool, track } = useHostContext();
|
|
152404
152743
|
const session = useWebSession();
|
|
@@ -152409,6 +152748,7 @@ function WebApp({ viewHint }) {
|
|
|
152409
152748
|
setActiveTab,
|
|
152410
152749
|
setTheme,
|
|
152411
152750
|
openSettingsPanel,
|
|
152751
|
+
closeSettingsPanel,
|
|
152412
152752
|
tabs,
|
|
152413
152753
|
activeTabId,
|
|
152414
152754
|
settingsPanelTab
|
|
@@ -152416,22 +152756,28 @@ function WebApp({ viewHint }) {
|
|
|
152416
152756
|
const [connections, setConnections] = reactExports.useState([]);
|
|
152417
152757
|
const [setupOpen, setSetupOpen] = reactExports.useState(false);
|
|
152418
152758
|
const [editingConnection, setEditingConnection] = reactExports.useState(null);
|
|
152419
|
-
const [
|
|
152759
|
+
const [connectionsCollapsed, setConnectionsCollapsed] = reactExports.useState(
|
|
152760
|
+
() => readStoredValue(CONNECTIONS_COLLAPSED_KEY) === "true"
|
|
152761
|
+
);
|
|
152420
152762
|
const [activeConnectionId, setActiveConnectionId] = reactExports.useState(null);
|
|
152421
|
-
const [connectionStatus, setConnectionStatus] = reactExports.useState({});
|
|
152422
152763
|
const [descriptions, setDescriptions] = reactExports.useState({});
|
|
152423
152764
|
const [queryConnections, setQueryConnections] = reactExports.useState({});
|
|
152424
152765
|
const [closedQueries, setClosedQueries] = reactExports.useState([]);
|
|
152425
152766
|
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
152426
152767
|
const localConnection = connections.find((connection) => connection.id === "built-in-duckdb");
|
|
152427
|
-
const
|
|
152768
|
+
const isAgentTab = Boolean(activeTab?.sessionId && activeTab.sessionId !== WEB_SESSION_ID);
|
|
152769
|
+
const selectedConnectionId = activeTab ? isAgentTab ? activeTab.connectionId ?? "" : queryConnections[activeTab.id] ?? localConnection?.id ?? connections[0]?.id ?? "" : "";
|
|
152770
|
+
const activeConnectionName = activeTab ? activeTab.connectionName ?? connections.find((connection) => connection.id === activeTab.connectionId)?.name ?? (activeTab.connectionId === "unknown" ? void 0 : activeTab.connectionId) : void 0;
|
|
152428
152771
|
reactExports.useEffect(() => {
|
|
152429
152772
|
if (isReady) track?.("ui_state_shown", { state: "workspace_ready" });
|
|
152430
152773
|
}, [isReady, track]);
|
|
152431
|
-
const newQuery = (connectionId = "built-in-duckdb") => {
|
|
152774
|
+
const newQuery = (connectionId = "built-in-duckdb", sql = "SELECT 42;") => {
|
|
152775
|
+
setSetupOpen(false);
|
|
152776
|
+
setEditingConnection(null);
|
|
152777
|
+
closeSettingsPanel();
|
|
152432
152778
|
const remoteId = crypto.randomUUID();
|
|
152433
152779
|
const id = addTab(
|
|
152434
|
-
|
|
152780
|
+
sql,
|
|
152435
152781
|
createProjectedTabId(WEB_SESSION_ID, remoteId),
|
|
152436
152782
|
tabs.some((tab) => tab.title === "Untitled query") ? `Untitled query ${tabs.filter((tab) => tab.title.startsWith("Untitled query")).length + 1}` : "Untitled query",
|
|
152437
152783
|
void 0,
|
|
@@ -152440,26 +152786,14 @@ function WebApp({ viewHint }) {
|
|
|
152440
152786
|
setQueryConnections((current2) => ({ ...current2, [id]: connectionId }));
|
|
152441
152787
|
setActiveConnectionId(null);
|
|
152442
152788
|
};
|
|
152443
|
-
const
|
|
152444
|
-
|
|
152445
|
-
|
|
152446
|
-
|
|
152447
|
-
|
|
152448
|
-
|
|
152449
|
-
try {
|
|
152450
|
-
const result = await callServerTool("test_connection", { connectionId: id });
|
|
152451
|
-
const message = result.content?.find((item) => item.type === "text")?.text ?? "Connection test failed";
|
|
152452
|
-
setConnectionStatus((current2) => ({
|
|
152453
|
-
...current2,
|
|
152454
|
-
[id]: result.isError || result.structuredContent?.["success"] === false ? message : "Connected"
|
|
152455
|
-
}));
|
|
152456
|
-
} catch (error) {
|
|
152457
|
-
setConnectionStatus((current2) => ({
|
|
152458
|
-
...current2,
|
|
152459
|
-
[id]: error instanceof Error ? error.message : "Connection test failed"
|
|
152460
|
-
}));
|
|
152461
|
-
}
|
|
152789
|
+
const showQuery = (tabId) => {
|
|
152790
|
+
setSetupOpen(false);
|
|
152791
|
+
setEditingConnection(null);
|
|
152792
|
+
closeSettingsPanel();
|
|
152793
|
+
setActiveConnectionId(null);
|
|
152794
|
+
setActiveTab(tabId);
|
|
152462
152795
|
};
|
|
152796
|
+
const openConnection = (id) => setActiveConnectionId(id);
|
|
152463
152797
|
const closeQuery = (id) => {
|
|
152464
152798
|
const tab = tabs.find((item) => item.id === id);
|
|
152465
152799
|
if (tab) {
|
|
@@ -152469,7 +152803,7 @@ function WebApp({ viewHint }) {
|
|
|
152469
152803
|
sql: tab.sql,
|
|
152470
152804
|
title: tab.title,
|
|
152471
152805
|
description: descriptions[id] ?? "",
|
|
152472
|
-
connectionId: queryConnections[id] ?? "built-in-duckdb"
|
|
152806
|
+
connectionId: tab.sessionId && tab.sessionId !== WEB_SESSION_ID ? tab.connectionId ?? "" : queryConnections[id] ?? "built-in-duckdb"
|
|
152473
152807
|
}
|
|
152474
152808
|
]);
|
|
152475
152809
|
if (tab.result || tab.isLoading) {
|
|
@@ -152495,14 +152829,15 @@ function WebApp({ viewHint }) {
|
|
|
152495
152829
|
};
|
|
152496
152830
|
const runQuery = async () => {
|
|
152497
152831
|
if (!activeTab || !activeTab.sql.trim() || !selectedConnectionId || activeTab.isLoading) return;
|
|
152498
|
-
const { id, sql } = activeTab;
|
|
152499
|
-
updateTab(id, { isLoading: true, error: null, cancelled: false });
|
|
152832
|
+
const { id, sql, title } = activeTab;
|
|
152833
|
+
updateTab(id, { isLoading: true, error: null, result: null, cancelled: false });
|
|
152500
152834
|
try {
|
|
152501
152835
|
const result = await callServerTool("run_query", {
|
|
152502
152836
|
sql,
|
|
152503
152837
|
session: WEB_SESSION_ID,
|
|
152504
152838
|
tabId: activeTab.remoteId,
|
|
152505
|
-
connectionId: selectedConnectionId
|
|
152839
|
+
connectionId: selectedConnectionId,
|
|
152840
|
+
title
|
|
152506
152841
|
});
|
|
152507
152842
|
const data = result.structuredContent;
|
|
152508
152843
|
if (useAppStore.getState().tabs.find((tab) => tab.id === id)?.cancelled) return;
|
|
@@ -152661,6 +152996,8 @@ function WebApp({ viewHint }) {
|
|
|
152661
152996
|
remoteId: msg.remoteId,
|
|
152662
152997
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152663
152998
|
clientType: msg.clientType,
|
|
152999
|
+
connectionId: msg.connectionId,
|
|
153000
|
+
connectionName: msg.connectionName,
|
|
152664
153001
|
isRemote: msg.isRemote
|
|
152665
153002
|
},
|
|
152666
153003
|
!msg.preserveFocus
|
|
@@ -152682,6 +153019,8 @@ function WebApp({ viewHint }) {
|
|
|
152682
153019
|
remoteId: msg.remoteId,
|
|
152683
153020
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152684
153021
|
clientType: msg.clientType,
|
|
153022
|
+
connectionId: msg.connectionId,
|
|
153023
|
+
connectionName: msg.connectionName,
|
|
152685
153024
|
isRemote: msg.isRemote
|
|
152686
153025
|
},
|
|
152687
153026
|
!msg.preserveFocus
|
|
@@ -152694,6 +153033,8 @@ function WebApp({ viewHint }) {
|
|
|
152694
153033
|
remoteId: msg.remoteId,
|
|
152695
153034
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152696
153035
|
clientType: msg.clientType,
|
|
153036
|
+
connectionId: msg.connectionId,
|
|
153037
|
+
connectionName: msg.connectionName,
|
|
152697
153038
|
isRemote: msg.isRemote
|
|
152698
153039
|
});
|
|
152699
153040
|
if (!msg.preserveFocus || !currentActiveId) {
|
|
@@ -152712,6 +153053,8 @@ function WebApp({ viewHint }) {
|
|
|
152712
153053
|
remoteId: msg.remoteId,
|
|
152713
153054
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152714
153055
|
clientType: msg.clientType,
|
|
153056
|
+
connectionId: msg.connectionId,
|
|
153057
|
+
connectionName: msg.connectionName,
|
|
152715
153058
|
isRemote: msg.isRemote
|
|
152716
153059
|
},
|
|
152717
153060
|
false
|
|
@@ -152724,6 +153067,8 @@ function WebApp({ viewHint }) {
|
|
|
152724
153067
|
remoteId: msg.remoteId,
|
|
152725
153068
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152726
153069
|
clientType: msg.clientType,
|
|
153070
|
+
connectionId: msg.connectionId,
|
|
153071
|
+
connectionName: msg.connectionName,
|
|
152727
153072
|
isRemote: msg.isRemote,
|
|
152728
153073
|
result: {
|
|
152729
153074
|
query: msg.data.query,
|
|
@@ -152731,7 +153076,7 @@ function WebApp({ viewHint }) {
|
|
|
152731
153076
|
rows: msg.data.rows,
|
|
152732
153077
|
rowCount: msg.data.totalRowsInFirstBatch ?? msg.data.rows.length,
|
|
152733
153078
|
executionTime: msg.data.executionTimeMs,
|
|
152734
|
-
connection: "
|
|
153079
|
+
connection: msg.connectionName ?? msg.connectionId ?? "Connection unknown",
|
|
152735
153080
|
wasTruncated: msg.data.wasTruncated,
|
|
152736
153081
|
executedAt: msg.data.executedAt
|
|
152737
153082
|
}
|
|
@@ -152749,6 +153094,8 @@ function WebApp({ viewHint }) {
|
|
|
152749
153094
|
remoteId: msg.remoteId,
|
|
152750
153095
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152751
153096
|
clientType: msg.clientType,
|
|
153097
|
+
connectionId: msg.connectionId,
|
|
153098
|
+
connectionName: msg.connectionName,
|
|
152752
153099
|
isRemote: msg.isRemote
|
|
152753
153100
|
},
|
|
152754
153101
|
false
|
|
@@ -152761,6 +153108,8 @@ function WebApp({ viewHint }) {
|
|
|
152761
153108
|
remoteId: msg.remoteId,
|
|
152762
153109
|
sessionDisplayName: msg.sessionDisplayName,
|
|
152763
153110
|
clientType: msg.clientType,
|
|
153111
|
+
connectionId: msg.connectionId,
|
|
153112
|
+
connectionName: msg.connectionName,
|
|
152764
153113
|
isRemote: msg.isRemote
|
|
152765
153114
|
});
|
|
152766
153115
|
break;
|
|
@@ -152868,7 +153217,33 @@ function WebApp({ viewHint }) {
|
|
|
152868
153217
|
] }),
|
|
152869
153218
|
monitorOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { ref: sidebarRef, className: "sp-web-sidebar", "aria-label": "Workspace navigation", children: [
|
|
152870
153219
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-header", children: [
|
|
152871
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153220
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153221
|
+
"button",
|
|
153222
|
+
{
|
|
153223
|
+
type: "button",
|
|
153224
|
+
className: "sp-web-sidebar-title sp-web-section-toggle",
|
|
153225
|
+
"aria-expanded": !connectionsCollapsed,
|
|
153226
|
+
"aria-controls": "sp-web-connections",
|
|
153227
|
+
onClick: () => {
|
|
153228
|
+
setConnectionsCollapsed((current2) => {
|
|
153229
|
+
writeStoredValue(CONNECTIONS_COLLAPSED_KEY, String(!current2));
|
|
153230
|
+
return !current2;
|
|
153231
|
+
});
|
|
153232
|
+
},
|
|
153233
|
+
children: [
|
|
153234
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: connectionsCollapsed ? "▸" : "▾" }),
|
|
153235
|
+
" Connections"
|
|
153236
|
+
]
|
|
153237
|
+
}
|
|
153238
|
+
),
|
|
153239
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153240
|
+
SidebarAddButton,
|
|
153241
|
+
{
|
|
153242
|
+
label: "Add connection",
|
|
153243
|
+
title: "Add connection",
|
|
153244
|
+
onClick: () => setSetupOpen(true)
|
|
153245
|
+
}
|
|
153246
|
+
),
|
|
152872
153247
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152873
153248
|
"button",
|
|
152874
153249
|
{
|
|
@@ -152877,7 +153252,7 @@ function WebApp({ viewHint }) {
|
|
|
152877
153252
|
onClick: () => setMonitorOpen(false),
|
|
152878
153253
|
title: "Hide sidebar",
|
|
152879
153254
|
"aria-label": "Hide sidebar",
|
|
152880
|
-
children:
|
|
153255
|
+
children: "«"
|
|
152881
153256
|
}
|
|
152882
153257
|
)
|
|
152883
153258
|
] }),
|
|
@@ -152894,68 +153269,55 @@ function WebApp({ viewHint }) {
|
|
|
152894
153269
|
"aria-valuemax": SIDEBAR_MAX_WIDTH
|
|
152895
153270
|
}
|
|
152896
153271
|
),
|
|
152897
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
152898
|
-
|
|
152899
|
-
|
|
152900
|
-
|
|
152901
|
-
|
|
152902
|
-
|
|
152903
|
-
|
|
152904
|
-
|
|
152905
|
-
|
|
152906
|
-
|
|
152907
|
-
|
|
152908
|
-
|
|
152909
|
-
|
|
152910
|
-
|
|
152911
|
-
|
|
152912
|
-
|
|
152913
|
-
|
|
152914
|
-
|
|
152915
|
-
|
|
152916
|
-
|
|
152917
|
-
|
|
152918
|
-
|
|
152919
|
-
|
|
152920
|
-
|
|
152921
|
-
|
|
152922
|
-
|
|
153272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153273
|
+
"div",
|
|
153274
|
+
{
|
|
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
|
+
),
|
|
153301
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-section-title", children: [
|
|
153302
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "My queries" }),
|
|
153303
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarAddButton, { label: "Add query", title: "New query", onClick: () => newQuery() })
|
|
152923
153304
|
] }),
|
|
152924
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-section-title", children: "Queries" }),
|
|
152925
153305
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-session-list", children: [
|
|
152926
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: () => newQuery(), children: "+ New query" }),
|
|
152927
153306
|
closedQueries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: reopenQuery, children: "Reopen closed query" }),
|
|
152928
|
-
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(
|
|
152929
153308
|
"button",
|
|
152930
153309
|
{
|
|
152931
153310
|
type: "button",
|
|
152932
153311
|
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
152933
153312
|
"aria-pressed": activeTabId === tab.id,
|
|
152934
|
-
onClick: () =>
|
|
152935
|
-
|
|
152936
|
-
setActiveConnectionId(null);
|
|
152937
|
-
},
|
|
152938
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: tab.title })
|
|
152939
|
-
},
|
|
152940
|
-
tab.id
|
|
152941
|
-
)),
|
|
152942
|
-
tabs.some((tab) => tab.sessionId !== WEB_SESSION_ID) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-meta sp-web-agent-heading", children: "Other sessions" }),
|
|
152943
|
-
tabs.filter((tab) => tab.sessionId !== WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152944
|
-
"button",
|
|
152945
|
-
{
|
|
152946
|
-
type: "button",
|
|
152947
|
-
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
152948
|
-
"aria-pressed": activeTabId === tab.id,
|
|
152949
|
-
onClick: () => {
|
|
152950
|
-
setActiveTab(tab.id);
|
|
152951
|
-
setActiveConnectionId(null);
|
|
152952
|
-
},
|
|
152953
|
-
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) })
|
|
152954
153315
|
},
|
|
152955
153316
|
tab.id
|
|
152956
153317
|
)),
|
|
152957
153318
|
tabs.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-empty-sessions", children: "No queries yet." })
|
|
152958
153319
|
] }),
|
|
153320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentActivity, { tabs, activeTabId, onSelect: showQuery }),
|
|
152959
153321
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-footer", children: "⌂ All work stays on this computer." })
|
|
152960
153322
|
] }),
|
|
152961
153323
|
setupOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-main", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -152992,41 +153354,6 @@ function WebApp({ viewHint }) {
|
|
|
152992
153354
|
) }),
|
|
152993
153355
|
!settingsPanelTab && (activeTab || activeConnectionId) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-workspace", children: [
|
|
152994
153356
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-tabs", role: "tablist", "aria-label": "Open tabs", children: [
|
|
152995
|
-
openConnectionIds.map((id) => {
|
|
152996
|
-
const connection = connections.find((item) => item.id === id);
|
|
152997
|
-
if (!connection) return null;
|
|
152998
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152999
|
-
"div",
|
|
153000
|
-
{
|
|
153001
|
-
className: `sp-web-query-tab${activeConnectionId === id ? " active" : ""}`,
|
|
153002
|
-
children: [
|
|
153003
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153004
|
-
"button",
|
|
153005
|
-
{
|
|
153006
|
-
type: "button",
|
|
153007
|
-
role: "tab",
|
|
153008
|
-
"aria-selected": activeConnectionId === id,
|
|
153009
|
-
onClick: () => setActiveConnectionId(id),
|
|
153010
|
-
children: connection.name ?? id
|
|
153011
|
-
}
|
|
153012
|
-
),
|
|
153013
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153014
|
-
"button",
|
|
153015
|
-
{
|
|
153016
|
-
type: "button",
|
|
153017
|
-
"aria-label": `Close ${connection.name ?? id} tab`,
|
|
153018
|
-
onClick: () => {
|
|
153019
|
-
setOpenConnectionIds((current2) => current2.filter((item) => item !== id));
|
|
153020
|
-
if (activeConnectionId === id) setActiveConnectionId(null);
|
|
153021
|
-
},
|
|
153022
|
-
children: "×"
|
|
153023
|
-
}
|
|
153024
|
-
)
|
|
153025
|
-
]
|
|
153026
|
-
},
|
|
153027
|
-
`connection-${id}`
|
|
153028
|
-
);
|
|
153029
|
-
}),
|
|
153030
153357
|
tabs.map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153031
153358
|
"div",
|
|
153032
153359
|
{
|
|
@@ -153038,18 +153365,15 @@ function WebApp({ viewHint }) {
|
|
|
153038
153365
|
type: "button",
|
|
153039
153366
|
role: "tab",
|
|
153040
153367
|
"aria-selected": tab.id === activeTabId && !activeConnectionId,
|
|
153041
|
-
onClick: () =>
|
|
153042
|
-
|
|
153043
|
-
setActiveConnectionId(null);
|
|
153044
|
-
},
|
|
153045
|
-
children: tab.title
|
|
153368
|
+
onClick: () => showQuery(tab.id),
|
|
153369
|
+
children: displayQueryTitle(tab.title, tab.sql)
|
|
153046
153370
|
}
|
|
153047
153371
|
),
|
|
153048
153372
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153049
153373
|
"button",
|
|
153050
153374
|
{
|
|
153051
153375
|
type: "button",
|
|
153052
|
-
"aria-label": `Close ${tab.title} tab`,
|
|
153376
|
+
"aria-label": `Close ${displayQueryTitle(tab.title, tab.sql)} tab`,
|
|
153053
153377
|
onClick: () => closeQuery(tab.id),
|
|
153054
153378
|
children: "×"
|
|
153055
153379
|
}
|
|
@@ -153073,51 +153397,39 @@ function WebApp({ viewHint }) {
|
|
|
153073
153397
|
activeConnectionId ? (() => {
|
|
153074
153398
|
const connection = connections.find((item) => item.id === activeConnectionId);
|
|
153075
153399
|
if (!connection) return null;
|
|
153076
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
153077
|
-
|
|
153078
|
-
|
|
153079
|
-
connection
|
|
153080
|
-
|
|
153081
|
-
|
|
153082
|
-
|
|
153083
|
-
|
|
153084
|
-
|
|
153085
|
-
|
|
153086
|
-
|
|
153087
|
-
|
|
153088
|
-
|
|
153089
|
-
|
|
153090
|
-
|
|
153091
|
-
|
|
153092
|
-
|
|
153093
|
-
|
|
153094
|
-
|
|
153095
|
-
|
|
153096
|
-
|
|
153097
|
-
|
|
153098
|
-
|
|
153099
|
-
|
|
153100
|
-
onClick: () => {
|
|
153101
|
-
setEditingConnection(connection);
|
|
153102
|
-
setSetupOpen(true);
|
|
153103
|
-
},
|
|
153104
|
-
children: "Edit"
|
|
153105
|
-
}
|
|
153106
|
-
),
|
|
153107
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153108
|
-
"button",
|
|
153109
|
-
{
|
|
153110
|
-
type: "button",
|
|
153111
|
-
className: "sp-web-secondary-button",
|
|
153112
|
-
onClick: () => void testConnection(connection.id),
|
|
153113
|
-
children: "Test"
|
|
153114
|
-
}
|
|
153115
|
-
)
|
|
153116
|
-
] })
|
|
153117
|
-
] });
|
|
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
|
+
);
|
|
153118
153424
|
})() : activeTab && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153119
153425
|
" ",
|
|
153120
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-query-heading", children: isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153427
|
+
AgentQueryHeading,
|
|
153428
|
+
{
|
|
153429
|
+
tab: activeTab,
|
|
153430
|
+
connectionName: activeConnectionName
|
|
153431
|
+
}
|
|
153432
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153121
153433
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153122
153434
|
"input",
|
|
153123
153435
|
{
|
|
@@ -153139,24 +153451,35 @@ function WebApp({ viewHint }) {
|
|
|
153139
153451
|
rows: 1
|
|
153140
153452
|
}
|
|
153141
153453
|
)
|
|
153142
|
-
] }),
|
|
153454
|
+
] }) }),
|
|
153143
153455
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-toolbar", children: [
|
|
153144
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153145
|
-
|
|
153146
|
-
|
|
153147
|
-
"
|
|
153148
|
-
|
|
153149
|
-
|
|
153150
|
-
|
|
153151
|
-
|
|
153152
|
-
|
|
153153
|
-
|
|
153154
|
-
})
|
|
153155
|
-
|
|
153156
|
-
|
|
153157
|
-
|
|
153158
|
-
|
|
153159
|
-
|
|
153456
|
+
isAgentTab ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-readonly", children: activeConnectionName ?? "Connection unknown" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153457
|
+
"select",
|
|
153458
|
+
{
|
|
153459
|
+
"aria-label": "Query connection",
|
|
153460
|
+
value: selectedConnectionId,
|
|
153461
|
+
onChange: (event) => setQueryConnections((current2) => ({
|
|
153462
|
+
...current2,
|
|
153463
|
+
[activeTab.id]: event.target.value
|
|
153464
|
+
})),
|
|
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
|
+
]
|
|
153472
|
+
}
|
|
153473
|
+
) }),
|
|
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(
|
|
153160
153483
|
"button",
|
|
153161
153484
|
{
|
|
153162
153485
|
type: "button",
|
|
@@ -153172,6 +153495,7 @@ function WebApp({ viewHint }) {
|
|
|
153172
153495
|
onClick: () => void runQuery(),
|
|
153173
153496
|
disabled: !selectedConnectionId || !activeTab.sql.trim(),
|
|
153174
153497
|
children: [
|
|
153498
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-run-glyph", "aria-hidden": "true", children: "▶" }),
|
|
153175
153499
|
"Run ",
|
|
153176
153500
|
/* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "⌘↵" })
|
|
153177
153501
|
]
|
|
@@ -153179,25 +153503,17 @@ function WebApp({ viewHint }) {
|
|
|
153179
153503
|
)
|
|
153180
153504
|
] }),
|
|
153181
153505
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153182
|
-
|
|
153506
|
+
SqlEditor,
|
|
153183
153507
|
{
|
|
153184
|
-
className: "sp-web-sql-editor",
|
|
153185
|
-
"aria-label": "SQL editor",
|
|
153186
|
-
spellCheck: false,
|
|
153187
153508
|
value: activeTab.sql,
|
|
153188
|
-
onChange: (
|
|
153189
|
-
|
|
153190
|
-
|
|
153191
|
-
event.preventDefault();
|
|
153192
|
-
void runQuery();
|
|
153193
|
-
}
|
|
153194
|
-
}
|
|
153509
|
+
onChange: (sql) => updateTab(activeTab.id, { sql }),
|
|
153510
|
+
onRun: () => void runQuery(),
|
|
153511
|
+
readOnly: isAgentTab
|
|
153195
153512
|
}
|
|
153196
153513
|
)
|
|
153197
|
-
] })
|
|
153198
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results-label", children: "Results" })
|
|
153514
|
+
] })
|
|
153199
153515
|
] }),
|
|
153200
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results", hidden: Boolean(activeConnectionId), children: /* @__PURE__ */ jsxRuntimeExports.jsx(MultiTabLayout, { emptyState: resultsEmptyState }) })
|
|
153516
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results", hidden: Boolean(activeConnectionId), children: /* @__PURE__ */ jsxRuntimeExports.jsx(MultiTabLayout, { emptyState: resultsEmptyState, fillGridWidth: true }) })
|
|
153201
153517
|
] })
|
|
153202
153518
|
] })
|
|
153203
153519
|
] });
|
|
@@ -153370,11 +153686,18 @@ bootstrap();</script>
|
|
|
153370
153686
|
margin: 5px 0 0;
|
|
153371
153687
|
}
|
|
153372
153688
|
.grain-connection-success {
|
|
153373
|
-
color: var(--
|
|
153374
|
-
|
|
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));
|
|
153375
153692
|
padding: 10px 14px;
|
|
153376
153693
|
border-radius: var(--grain-radius-sm);
|
|
153377
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
|
+
}
|
|
153378
153701
|
.grain-connection-page :is(button, input, select, summary):focus-visible {
|
|
153379
153702
|
outline: 2px solid var(--grain-accent);
|
|
153380
153703
|
outline-offset: 2px;
|
|
@@ -163150,6 +163473,12 @@ body.vscode-high-contrast .ag-theme-quartz {
|
|
|
163150
163473
|
outline: none !important;
|
|
163151
163474
|
}
|
|
163152
163475
|
|
|
163476
|
+
.sp-num-cell {
|
|
163477
|
+
justify-content: flex-end;
|
|
163478
|
+
text-align: right;
|
|
163479
|
+
font-variant-numeric: tabular-nums;
|
|
163480
|
+
}
|
|
163481
|
+
|
|
163153
163482
|
.sp-null {
|
|
163154
163483
|
color: var(--sp-muted-fg);
|
|
163155
163484
|
font-style: italic;
|
|
@@ -166216,10 +166545,79 @@ body {
|
|
|
166216
166545
|
letter-spacing: 0;
|
|
166217
166546
|
}
|
|
166218
166547
|
.sp-web-sidebar-section-title {
|
|
166219
|
-
|
|
166220
|
-
|
|
166548
|
+
display: flex;
|
|
166549
|
+
align-items: center;
|
|
166550
|
+
justify-content: space-between;
|
|
166551
|
+
margin: 18px 0 6px;
|
|
166552
|
+
padding: 17px 9px 0;
|
|
166221
166553
|
border-top: 1px solid var(--grain-border-subtle);
|
|
166222
166554
|
}
|
|
166555
|
+
.sp-web-sidebar-header .sp-web-sidebar-title {
|
|
166556
|
+
flex: 1;
|
|
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
|
+
}
|
|
166583
|
+
.sp-web-section-add,
|
|
166584
|
+
.sp-web-sidebar-close {
|
|
166585
|
+
display: inline-flex;
|
|
166586
|
+
align-items: center;
|
|
166587
|
+
justify-content: center;
|
|
166588
|
+
width: 22px;
|
|
166589
|
+
height: 22px;
|
|
166590
|
+
padding: 0;
|
|
166591
|
+
border: 0;
|
|
166592
|
+
border-radius: var(--grain-radius-sm);
|
|
166593
|
+
background: transparent;
|
|
166594
|
+
color: var(--grain-ink-muted);
|
|
166595
|
+
font: 400 16px/1 var(--grain-font-body);
|
|
166596
|
+
cursor: pointer;
|
|
166597
|
+
}
|
|
166598
|
+
.sp-web-sidebar-close {
|
|
166599
|
+
font-size: 13px;
|
|
166600
|
+
}
|
|
166601
|
+
.sp-web-section-add:hover,
|
|
166602
|
+
.sp-web-sidebar-close:hover {
|
|
166603
|
+
background: var(--grain-surface-raised);
|
|
166604
|
+
color: var(--grain-ink);
|
|
166605
|
+
}
|
|
166606
|
+
.sp-web-section-add:focus-visible,
|
|
166607
|
+
.sp-web-sidebar-close:focus-visible {
|
|
166608
|
+
outline: 1px solid var(--grain-accent);
|
|
166609
|
+
}
|
|
166610
|
+
.sp-web-connection-label {
|
|
166611
|
+
flex: 1;
|
|
166612
|
+
min-width: 0;
|
|
166613
|
+
}
|
|
166614
|
+
.sp-web-connection-dot {
|
|
166615
|
+
width: 7px;
|
|
166616
|
+
height: 7px;
|
|
166617
|
+
flex: none;
|
|
166618
|
+
border-radius: 50%;
|
|
166619
|
+
background: var(--sp-success);
|
|
166620
|
+
}
|
|
166223
166621
|
.sp-web-connection-item {
|
|
166224
166622
|
display: flex;
|
|
166225
166623
|
align-items: center;
|
|
@@ -166338,7 +166736,7 @@ body {
|
|
|
166338
166736
|
.sp-web-query-tabs {
|
|
166339
166737
|
display: flex;
|
|
166340
166738
|
align-items: stretch;
|
|
166341
|
-
min-height:
|
|
166739
|
+
min-height: 42px;
|
|
166342
166740
|
overflow-x: auto;
|
|
166343
166741
|
border-bottom: 1px solid var(--grain-border-subtle);
|
|
166344
166742
|
background: var(--grain-surface);
|
|
@@ -166352,6 +166750,9 @@ body {
|
|
|
166352
166750
|
background: var(--grain-ground);
|
|
166353
166751
|
box-shadow: inset 0 -2px var(--grain-accent);
|
|
166354
166752
|
}
|
|
166753
|
+
.sp-web-query-tab.active button:first-child {
|
|
166754
|
+
color: var(--grain-accent);
|
|
166755
|
+
}
|
|
166355
166756
|
.sp-web-query-tab button,
|
|
166356
166757
|
.sp-web-query-tab-action {
|
|
166357
166758
|
border: 0;
|
|
@@ -166359,7 +166760,7 @@ body {
|
|
|
166359
166760
|
color: var(--grain-ink);
|
|
166360
166761
|
font: inherit;
|
|
166361
166762
|
cursor: pointer;
|
|
166362
|
-
padding: 8px
|
|
166763
|
+
padding: 8px 14px;
|
|
166363
166764
|
white-space: nowrap;
|
|
166364
166765
|
}
|
|
166365
166766
|
.sp-web-query-tab button:last-child {
|
|
@@ -166370,12 +166771,20 @@ body {
|
|
|
166370
166771
|
gap: 4px;
|
|
166371
166772
|
padding: 18px 24px 14px;
|
|
166372
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
|
+
}
|
|
166373
166782
|
.sp-web-query-heading input,
|
|
166374
166783
|
.sp-web-query-heading textarea {
|
|
166375
166784
|
width: 100%;
|
|
166376
166785
|
padding: 0;
|
|
166377
166786
|
border: 0;
|
|
166378
|
-
resize:
|
|
166787
|
+
resize: none;
|
|
166379
166788
|
background: transparent;
|
|
166380
166789
|
color: var(--grain-ink);
|
|
166381
166790
|
font-family: var(--grain-font-body);
|
|
@@ -166434,26 +166843,43 @@ body {
|
|
|
166434
166843
|
opacity: 0.5;
|
|
166435
166844
|
cursor: default;
|
|
166436
166845
|
}
|
|
166846
|
+
.sp-web-sql-editor-frame {
|
|
166847
|
+
--sp-web-gutter-width: calc(var(--sp-web-gutter-digits, 2) * 1ch + 28px);
|
|
166848
|
+
position: relative;
|
|
166849
|
+
border-bottom: 1px solid var(--grain-border-subtle);
|
|
166850
|
+
background: var(--grain-ground);
|
|
166851
|
+
}
|
|
166852
|
+
.sp-web-sql-gutter {
|
|
166853
|
+
position: absolute;
|
|
166854
|
+
top: 0;
|
|
166855
|
+
bottom: 0;
|
|
166856
|
+
left: 0;
|
|
166857
|
+
box-sizing: border-box;
|
|
166858
|
+
width: var(--sp-web-gutter-width);
|
|
166859
|
+
overflow: hidden;
|
|
166860
|
+
padding: 20px 12px 40px 0;
|
|
166861
|
+
border-right: 1px solid var(--grain-border-subtle);
|
|
166862
|
+
color: var(--grain-ink-muted);
|
|
166863
|
+
font: 12px/1.7 var(--grain-font-mono);
|
|
166864
|
+
text-align: right;
|
|
166865
|
+
user-select: none;
|
|
166866
|
+
}
|
|
166437
166867
|
.sp-web-sql-editor {
|
|
166438
166868
|
display: block;
|
|
166439
166869
|
box-sizing: border-box;
|
|
166440
|
-
width: 100
|
|
166870
|
+
width: calc(100% - var(--sp-web-gutter-width));
|
|
166441
166871
|
min-height: 190px;
|
|
166442
|
-
|
|
166872
|
+
margin-left: var(--sp-web-gutter-width);
|
|
166873
|
+
padding: 20px 24px 20px 16px;
|
|
166443
166874
|
border: 0;
|
|
166444
|
-
border-bottom: 1px solid var(--grain-border-subtle);
|
|
166445
166875
|
resize: vertical;
|
|
166876
|
+
white-space: pre;
|
|
166446
166877
|
outline-color: var(--grain-accent);
|
|
166447
166878
|
background: var(--grain-ground);
|
|
166448
166879
|
color: var(--grain-ink);
|
|
166449
166880
|
font: 12px/1.7 var(--grain-font-mono);
|
|
166450
166881
|
tab-size: 2;
|
|
166451
166882
|
}
|
|
166452
|
-
.sp-web-results-label {
|
|
166453
|
-
padding: 10px 24px;
|
|
166454
|
-
font-size: 12px;
|
|
166455
|
-
font-weight: 700;
|
|
166456
|
-
}
|
|
166457
166883
|
.sp-web-results {
|
|
166458
166884
|
display: flex;
|
|
166459
166885
|
flex: 1;
|
|
@@ -166480,6 +166906,15 @@ body {
|
|
|
166480
166906
|
font-weight: 700;
|
|
166481
166907
|
}
|
|
166482
166908
|
|
|
166909
|
+
.sp-web-run-glyph {
|
|
166910
|
+
margin-right: 6px;
|
|
166911
|
+
font-size: 9px;
|
|
166912
|
+
}
|
|
166913
|
+
.sp-web-query-toolbar > .sp-web-primary-button {
|
|
166914
|
+
display: inline-flex;
|
|
166915
|
+
align-items: center;
|
|
166916
|
+
font-weight: 600;
|
|
166917
|
+
}
|
|
166483
166918
|
.sp-web-query-toolbar kbd {
|
|
166484
166919
|
margin-left: 6px;
|
|
166485
166920
|
padding: 2px 5px;
|
|
@@ -166545,6 +166980,8 @@ body {
|
|
|
166545
166980
|
.sp-web-connection-item:hover,
|
|
166546
166981
|
.sp-web-connection-item:focus-visible {
|
|
166547
166982
|
background: var(--grain-surface);
|
|
166983
|
+
}
|
|
166984
|
+
.sp-web-connection-item:focus-visible {
|
|
166548
166985
|
outline: 1px solid var(--grain-accent);
|
|
166549
166986
|
}
|
|
166550
166987
|
.sp-web-connection-detail {
|
|
@@ -166557,6 +166994,18 @@ body {
|
|
|
166557
166994
|
.sp-web-connection-detail p {
|
|
166558
166995
|
color: var(--grain-ink-muted);
|
|
166559
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
|
+
}
|
|
166560
167009
|
.sp-web-connection-actions {
|
|
166561
167010
|
display: flex;
|
|
166562
167011
|
gap: 8px;
|